From ea6dc2a56e0b6db0ad1a62a1ef5b9183eead363d Mon Sep 17 00:00:00 2001 From: aMannus Date: Mon, 6 Jul 2026 19:52:13 +0200 Subject: [PATCH 1/8] Eliminate shuffledObject (#239) --- src/port/Rando/CustomObject/CustomObject.cpp | 69 +- src/port/Rando/Logic/GeneratePools.cpp | 15 +- src/port/Rando/Logic/GenerateSaveData.cpp | 4 +- src/port/Rando/Logic/Logic.h | 26 +- src/port/Rando/MiscBehavior/OnFileLoad.cpp | 3 +- src/port/Rando/MiscBehavior/WorldState.cpp | 8 +- src/port/Rando/ObjectBehavior/Jinjo.cpp | 13 +- src/port/Rando/ObjectBehavior/Molehill.cpp | 2 - src/port/Rando/ObjectBehavior/MusicNote.cpp | 10 +- .../Rando/ObjectBehavior/ObjectBehavior.cpp | 63 +- .../Rando/ObjectBehavior/ObjectBehavior.h | 1 - src/port/Rando/StaticData/Checks.cpp | 2416 ++++++++--------- src/port/Rando/StaticData/Items.cpp | 130 +- src/port/Rando/StaticData/StaticData.h | 8 +- src/port/Rando/Types.h | 120 +- src/port/Save/SaveManager.cpp | 11 +- src/port/ShipUtils.cpp | 28 +- src/port/ShipUtils.h | 2 +- src/port/UI/DeveloperTools/SaveEditor.cpp | 27 +- 19 files changed, 1586 insertions(+), 1370 deletions(-) diff --git a/src/port/Rando/CustomObject/CustomObject.cpp b/src/port/Rando/CustomObject/CustomObject.cpp index ded35b1c3..869887707 100644 --- a/src/port/Rando/CustomObject/CustomObject.cpp +++ b/src/port/Rando/CustomObject/CustomObject.cpp @@ -127,30 +127,31 @@ void CustomObject::RemoveSpawnedIdFromList(RandoCheckId randoCheckId) { } Actor* CustomObject::SetCustomActorParametersEX(RandoCheckId randoCheckId, Actor* customActor) { - RandoSaveCheck shuffledObject = Rando::Logic::GetShuffledObject(randoCheckId); + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; customActor->marker->randoCheckId = randoCheckId; - switch (shuffledObject.randoItemId) { - case RI_EMPTY_HONEYCOMB: + RandoItemType itemType = Rando::StaticData::Items[randoSaveCheck.randoItemId].randoItemType; + switch (itemType) { + case RITYPE_EMPTY_HONEYCOMB: ActorLocal_EmptyHoneycomb* honeycombLocal; honeycombLocal = (ActorLocal_EmptyHoneycomb*)&customActor->local; honeycombLocal->uid = (honeycomb_e)Rando::Logic::GetShuffledObject(randoCheckId).randoCollectionId; break; - case RI_JIGGY: + case RITYPE_JIGGY: ActorLocal_Jiggy* jiggyLocal; jiggyLocal = (ActorLocal_Jiggy*)&customActor->local; - jiggyLocal->index = shuffledObject.randoCollectionId; + jiggyLocal->index = randoSaveCheck.randoCollectionId; break; - case RI_MUMBO_TOKEN: + case RITYPE_MUMBO_TOKEN: ActorLocal_MumboToken* tokenLocal; tokenLocal = (ActorLocal_MumboToken*)&customActor->local; tokenLocal->uid = (mumbotoken_e)Rando::Logic::GetShuffledObject(randoCheckId).randoCollectionId; break; - case RI_STOP_N_SWOP_EGG: - case RI_STOP_N_SWOP_KEY: - customActor->actorTypeSpecificField = shuffledObject.randoCollectionId; + case RITYPE_SNS_EGG: + case RITYPE_SNS_KEY: + customActor->actorTypeSpecificField = randoSaveCheck.randoCollectionId; customActor->scale = 0.5f; - if (shuffledObject.randoItemId == RI_STOP_N_SWOP_KEY) { + if (itemType == RITYPE_SNS_KEY) { customActor->position_y += 50.0f; } break; @@ -200,7 +201,7 @@ void CustomObject::FlushRandoSpawnQueue() { continue; } - actor_e randoActorId = (actor_e)Rando::StaticData::Items[randoSaveCheck.randoItemId].actorId; + actor_e randoActorId = Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId); if (randoSaveCheck.obtained) { randoActorId = GetRandomJunkActorId(randoSaveCheck); } @@ -268,8 +269,8 @@ Actor* CustomObject::ShouldCreateCustomActorEX(RandoCheckId randoCheckId, int32_ } void CustomObject::ResolveCustomActorCollisionEX(RandoCheckId randoCheckId) { - RandoSaveCheck shuffledObject = Rando::Logic::GetShuffledObject(randoCheckId); - if (shuffledObject.randoCheckId == RC_UNKNOWN) { + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; + if (randoSaveCheck.randoCheckId == RC_UNKNOWN) { return; } @@ -282,26 +283,23 @@ void CustomObject::ResolveCustomActorCollisionEX(RandoCheckId randoCheckId) { spawnPosition[1] = (int32_t)playerPosF[1]; spawnPosition[2] = (int32_t)playerPosF[2]; - switch (shuffledObject.randoItemId) { - case RI_JIGGY: + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[randoSaveCheck.randoItemId]; + RandoItemType itemType = randoItem.randoItemType; + int32_t currentLevel = map_getLevel(gsworld_getMap()); + + switch (itemType) { + case RITYPE_JIGGY: if (CVarGetInteger(CVAR_ENHANCEMENT("Cutscenes.SkipJiggyDance"), 0)) { fxSparkle_musicNote(sparklePos); } break; - case RI_JINJO_BLUE: - case RI_JINJO_GREEN: - case RI_JINJO_ORANGE: - case RI_JINJO_PINK: - case RI_JINJO_YELLOW: - if (Rando::StaticData::Checks[shuffledObject.shuffledCheckId].worldId == map_getLevel(gsworld_getMap())) { - int32_t jinjoMarkerId = - GetJinjoActorMarkerId((actor_e)Rando::StaticData::Items[shuffledObject.randoItemId].actorId); + case RITYPE_JINJO: + if (randoItem.worldId == currentLevel) { + int32_t jinjoMarkerId = GetJinjoActorMarkerId((actor_e)randoItem.actorId); item_adjustByDiffWithHud(ITEM_12_JINJOS, (1 << ((jinjoMarkerId + 6) & 0x1F))); } else { - if (Rando::Logic::ShouldSpawnJinjoJiggy( - Rando::StaticData::Checks[shuffledObject.shuffledCheckId].worldId)) { - RandoCheckId jiggyCheckId = Rando::StaticData::GetJinjoJiggyCheckByLevelId( - Rando::StaticData::Checks[shuffledObject.shuffledCheckId].worldId); + if (Rando::Logic::ShouldSpawnJinjoJiggy(randoItem.worldId)) { + RandoCheckId jiggyCheckId = Rando::StaticData::GetJinjoJiggyCheckByLevelId(randoItem.worldId); if (jiggyCheckId != RC_UNKNOWN) { Actor* customActor = ShouldCreateCustomActorEX(jiggyCheckId, spawnPosition, false); @@ -312,9 +310,9 @@ void CustomObject::ResolveCustomActorCollisionEX(RandoCheckId randoCheckId) { } } break; - case RI_MUSIC_NOTE: - D_80385FF0[Rando::StaticData::Checks[shuffledObject.shuffledCheckId].worldId]++; - if (Rando::StaticData::Checks[shuffledObject.shuffledCheckId].worldId == map_getLevel(gsworld_getMap())) { + case RITYPE_MUSIC_NOTE: + D_80385FF0[randoItem.worldId]++; + if (randoItem.worldId == currentLevel) { item_set(ITEM_C_NOTE, D_80385FF0[map_getLevel(gsworld_getMap())]); } @@ -322,8 +320,8 @@ void CustomObject::ResolveCustomActorCollisionEX(RandoCheckId randoCheckId) { fxSparkle_musicNote(sparklePos); coMusicPlayer_playMusic(COMUSIC_9_NOTE_COLLECTED, 16000); break; - case RI_STOP_N_SWOP_EGG: - case RI_STOP_N_SWOP_KEY: + case RITYPE_SNS_EGG: + case RITYPE_SNS_KEY: if (Rando::Logic::GetTotalSnsItemsCollected() >= 7) { gcparade_beginFinalParade(); } @@ -355,10 +353,11 @@ void CustomObject::ObjectCollectedEX(Prop* prop) { CustomObject::CheckObtainedEX((RandoCheckId)prop->actorProp.marker->randoCheckId); if (shouldRemoveEX) { - CustomObject::ResolveCustomActorCollisionEX((RandoCheckId)prop->actorProp.marker->randoCheckId); + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[(RandoCheckId)prop->actorProp.marker->randoCheckId]; + + CustomObject::ResolveCustomActorCollisionEX(randoSaveCheck.randoCheckId); - if (Rando::Logic::GetShuffledObject((RandoCheckId)prop->actorProp.marker->randoCheckId).randoItemId == - RI_MUSIC_NOTE) { + if (Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId) == ACTOR_51_MUSIC_NOTE) { marker_despawn(prop->actorProp.marker); } } diff --git a/src/port/Rando/Logic/GeneratePools.cpp b/src/port/Rando/Logic/GeneratePools.cpp index 090ca8354..2832273e6 100644 --- a/src/port/Rando/Logic/GeneratePools.cpp +++ b/src/port/Rando/Logic/GeneratePools.cpp @@ -64,8 +64,8 @@ void GenerateShufflePool(SaveData* saveData) { if (randoStaticCheck.randoCheckType == RCTYPE_MOLEHILL) { if (CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_MOLEHILLS].cvar, 0) == RO_GENERIC_ON) { abilityCheckPool.push_back(randoCheckId); - abilityItemPool.push_back( - { (actor_e)randoStaticCheck.actorId, randoStaticCheck.collectionId, randoCheckId }); + abilityItemPool.push_back({ Rando::StaticData::GetActorIdByRandoItemId(randoStaticCheck.randoItemId), + randoStaticCheck.collectionId, randoCheckId }); } continue; } @@ -86,7 +86,8 @@ void GenerateShufflePool(SaveData* saveData) { } checkPool.push_back(randoCheckId); - itemPool.push_back({ (actor_e)randoStaticCheck.actorId, randoStaticCheck.collectionId, randoCheckId }); + itemPool.push_back({ Rando::StaticData::GetActorIdByRandoItemId(randoStaticCheck.randoItemId), + randoStaticCheck.collectionId, randoCheckId }); } if (!itemPool.empty()) { @@ -111,8 +112,7 @@ void GenerateShufflePool(SaveData* saveData) { RandoSaveCheck randoShuffleEntry = { .name = Rando::StaticData::Checks[checkPool[i]].name, .randoCheckId = checkPool[i], - .randoItemId = Rando::StaticData::GetRandoItemByActorId(std::get<0>(itemPool[i])), - .shuffledCheckId = std::get<2>(itemPool[i]), + .randoItemId = Rando::StaticData::Checks[std::get<2>(itemPool[i])].randoItemId, .randoCollectionId = std::get<1>(itemPool[i]), .isShuffled = checkPool[i] == RC_UNKNOWN ? false : true, .obtained = false, @@ -120,7 +120,6 @@ void GenerateShufflePool(SaveData* saveData) { }; shuffledPool.push_back(randoShuffleEntry); - RANDO_SAVE_CHECKS[checkPool[i]] = randoShuffleEntry; } @@ -129,8 +128,7 @@ void GenerateShufflePool(SaveData* saveData) { RandoSaveCheck randoShuffleEntry = { .name = Rando::StaticData::Checks[abilityCheckPool[a]].name, .randoCheckId = abilityCheckPool[a], - .randoItemId = Rando::StaticData::GetRandoItemByActorId(std::get<0>(abilityItemPool[a])), - .shuffledCheckId = std::get<2>(abilityItemPool[a]), + .randoItemId = Rando::StaticData::Checks[std::get<2>(abilityItemPool[a])].randoItemId, .randoCollectionId = std::get<1>(abilityItemPool[a]), .isShuffled = true, .obtained = false, @@ -162,7 +160,6 @@ void GeneratePoolFromSaveData(SaveData* saveData) { .name = Rando::StaticData::Checks[(RandoCheckId)i].name, .randoCheckId = randoSaveCheck.randoCheckId, .randoItemId = randoSaveCheck.randoItemId, - .shuffledCheckId = randoSaveCheck.shuffledCheckId, .randoCollectionId = randoSaveCheck.randoCollectionId, .isShuffled = randoSaveCheck.isShuffled, .obtained = randoSaveCheck.obtained, diff --git a/src/port/Rando/Logic/GenerateSaveData.cpp b/src/port/Rando/Logic/GenerateSaveData.cpp index 864ecb2ca..3361ce00a 100644 --- a/src/port/Rando/Logic/GenerateSaveData.cpp +++ b/src/port/Rando/Logic/GenerateSaveData.cpp @@ -124,8 +124,8 @@ void Rando::Logic::InitializeSaveData(SaveData* saveData) { for (auto& [randoCheckId, randoStaticCheck] : Rando::StaticData::Checks) { RandoSaveCheck randoSaveCheck = { .name = randoStaticCheck.name, - .randoItemId = Rando::StaticData::GetRandoItemByActorId((actor_e)randoStaticCheck.actorId), - .shuffledCheckId = randoCheckId, + .randoItemId = randoStaticCheck.randoItemId, + // .randoItemId = Rando::StaticData::GetRandoItemByActorId((actor_e)randoStaticCheck.actorId), .randoCollectionId = randoStaticCheck.collectionId, .isShuffled = false, .obtained = false, diff --git a/src/port/Rando/Logic/Logic.h b/src/port/Rando/Logic/Logic.h index 88e9f3b04..964235b66 100644 --- a/src/port/Rando/Logic/Logic.h +++ b/src/port/Rando/Logic/Logic.h @@ -118,16 +118,18 @@ inline bool ShouldSpawnJinjoJiggy(int16_t levelId) { bool shouldSpawn = false; int16_t jinjoCount = 0; - for (auto& pool : Rando::Logic::shuffledPool) { - if (!pool.obtained) { + for (auto& location : Rando::Logic::shuffledPool) { + if (!location.obtained) { continue; } - if (Rando::StaticData::Checks[pool.shuffledCheckId].worldId != levelId) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; + + if (randoItem.worldId != levelId) { continue; } - if (pool.randoItemId >= RI_JINJO_BLUE && pool.randoItemId <= RI_JINJO_YELLOW) { + if (randoItem.randoItemType == RITYPE_JINJO) { jinjoCount++; } } @@ -142,12 +144,13 @@ inline bool ShouldSpawnJinjoJiggy(int16_t levelId) { inline int32_t GetTotalSnsItemsCollected() { int32_t snsCount = 0; - for (auto& pool : Rando::Logic::shuffledPool) { - if (!pool.obtained) { + for (auto& location : Rando::Logic::shuffledPool) { + if (!location.obtained) { continue; } - if (pool.randoItemId == RI_STOP_N_SWOP_EGG || pool.randoItemId == RI_STOP_N_SWOP_KEY) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; + if (randoItem.randoItemType == RITYPE_SNS_EGG || randoItem.randoItemType == RITYPE_SNS_KEY) { snsCount++; } } @@ -209,12 +212,13 @@ inline bool CanCollectWorldJinjos(level_e levelId) { int32_t accessibleJinjos = 0; for (auto& entry : Rando::Logic::shuffledPool) { - if (Rando::StaticData::Checks[entry.shuffledCheckId].worldId != levelId) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[entry.randoItemId]; + + if (randoItem.worldId != levelId) { continue; } - - if (entry.randoItemId >= RI_JINJO_BLUE && entry.randoItemId <= RI_JINJO_YELLOW) { - if (CanAccessCheck(entry.shuffledCheckId)) { + if (randoItem.randoItemType == RITYPE_JINJO) { + if (CanAccessCheck(entry.randoCheckId)) { accessibleJinjos++; } } diff --git a/src/port/Rando/MiscBehavior/OnFileLoad.cpp b/src/port/Rando/MiscBehavior/OnFileLoad.cpp index f4a3e49f7..7c7bd5293 100644 --- a/src/port/Rando/MiscBehavior/OnFileLoad.cpp +++ b/src/port/Rando/MiscBehavior/OnFileLoad.cpp @@ -4,6 +4,7 @@ #include "port/UI/Notification.h" #include "port/Save/Types.h" +#include "port/UI/cvar_prefixes.h" #include "port/Rando/Logic/Logic.h" // #include "port/Rando/Spoiler/Spoiler.h" @@ -33,7 +34,7 @@ void Rando::MiscBehavior::OnFileLoad() { return; } - if (CVarGetInteger("gRandoSettings.Enable", 0)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Enable"), 0)) { Rando::Logic::InitializeSaveData(saveData); Rando::Logic::GenerateShufflePool(saveData); Rando::Logic::GrantStartingLoadout(); diff --git a/src/port/Rando/MiscBehavior/WorldState.cpp b/src/port/Rando/MiscBehavior/WorldState.cpp index 81163032b..ab26bea2a 100644 --- a/src/port/Rando/MiscBehavior/WorldState.cpp +++ b/src/port/Rando/MiscBehavior/WorldState.cpp @@ -224,7 +224,9 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { } for (auto& saveCheck : RANDO_SAVE_CHECKS) { - if (Rando::StaticData::Checks[saveCheck.shuffledCheckId].randoCheckType != RCTYPE_EMPTY_HONEYCOMB) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[saveCheck.randoItemId]; + + if (randoItem.randoItemType != RITYPE_EMPTY_HONEYCOMB) { continue; } @@ -254,7 +256,9 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { } for (auto& saveCheck : RANDO_SAVE_CHECKS) { - if (Rando::StaticData::Checks[saveCheck.shuffledCheckId].randoCheckType != RCTYPE_MUMBO_TOKEN) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[saveCheck.randoItemId]; + + if (randoItem.randoItemType != RITYPE_MUMBO_TOKEN) { continue; } diff --git a/src/port/Rando/ObjectBehavior/Jinjo.cpp b/src/port/Rando/ObjectBehavior/Jinjo.cpp index 9910261e1..61764a6bd 100644 --- a/src/port/Rando/ObjectBehavior/Jinjo.cpp +++ b/src/port/Rando/ObjectBehavior/Jinjo.cpp @@ -18,18 +18,19 @@ void Rando::ObjectBehavior::InitJinjoBehavior() { COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { OnSetJiggyList* ev = (OnSetJiggyList*)event; - for (auto& pool : Rando::Logic::shuffledPool) { - if (!pool.obtained) { + for (auto& location : Rando::Logic::shuffledPool) { + if (!location.obtained) { continue; } - if (Rando::StaticData::Checks[pool.shuffledCheckId].worldId != ev->levelId) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; + + if (randoItem.worldId != ev->levelId) { continue; } - if (pool.randoItemId >= RI_JINJO_BLUE && pool.randoItemId <= RI_JINJO_YELLOW) { - int32_t jinjoMarkerId = - GetJinjoActorMarkerId((actor_e)Rando::StaticData::Items[pool.randoItemId].actorId); + if (randoItem.randoItemType == RITYPE_JINJO) { + int32_t jinjoMarkerId = GetJinjoActorMarkerId((actor_e)randoItem.actorId); item_adjustByDiffWithHud(ITEM_12_JINJOS, (1 << ((jinjoMarkerId + 6) & 0x1F))); } } diff --git a/src/port/Rando/ObjectBehavior/Molehill.cpp b/src/port/Rando/ObjectBehavior/Molehill.cpp index 2faf3459c..e7e640f73 100644 --- a/src/port/Rando/ObjectBehavior/Molehill.cpp +++ b/src/port/Rando/ObjectBehavior/Molehill.cpp @@ -91,8 +91,6 @@ void SetSpiralMountainFlags() { mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); } -// CALL_EVENT expands to a braced initializer whose commas don't survive being passed through the -// COND_HOOK macro wrapper, so fire it from a plain function the listener calls instead. static void MarkBridgeRepairedDialogComplete() { CALL_EVENT(SetRandoInfFlag, RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, true); } diff --git a/src/port/Rando/ObjectBehavior/MusicNote.cpp b/src/port/Rando/ObjectBehavior/MusicNote.cpp index 5a67a9dd5..24d32b6ee 100644 --- a/src/port/Rando/ObjectBehavior/MusicNote.cpp +++ b/src/port/Rando/ObjectBehavior/MusicNote.cpp @@ -19,13 +19,15 @@ void Rando::ObjectBehavior::InitMusicNoteBehavior() { OnSetJiggyList* ev = (OnSetJiggyList*)event; int32_t currentNotes = 0; - for (auto& pool : Rando::Logic::shuffledPool) { - if (Rando::StaticData::Checks[pool.shuffledCheckId].worldId != ev->levelId) { + for (auto& location : Rando::Logic::shuffledPool) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; + + if (randoItem.worldId != ev->levelId) { continue; } - if (pool.randoItemId == RI_MUSIC_NOTE) { - if (pool.obtained) { + if (randoItem.randoItemType == RITYPE_MUSIC_NOTE) { + if (location.obtained) { currentNotes++; } } diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index 6c84867c7..a56b829c4 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -42,20 +42,20 @@ std::vector actorSpawnWhitelist = { //ACTOR_12C_MOLEHILL, }; -std::map randoItemColors = { - { RI_UNKNOWN, UIWidgets::Colors::Brown }, - { RI_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, - { RI_JIGGY, UIWidgets::Colors::Yellow }, - { RI_JINJO_BLUE, UIWidgets::Colors::SkyBlue }, - { RI_JINJO_GREEN, UIWidgets::Colors::Green }, - { RI_JINJO_ORANGE, UIWidgets::Colors::Orange }, - { RI_JINJO_PINK, UIWidgets::Colors::Pink }, - { RI_JINJO_YELLOW, UIWidgets::Colors::Yellow }, - { RI_MOLEHILL, UIWidgets::Colors::Cyan }, - { RI_MUMBO_TOKEN, UIWidgets::Colors::Gray }, - { RI_MUSIC_NOTE, UIWidgets::Colors::Yellow }, - { RI_STOP_N_SWOP_EGG, UIWidgets::Colors::Pink }, - { RI_STOP_N_SWOP_KEY, UIWidgets::Colors::White }, +std::map randoItemColors = { + { ACTOR_1_UNKNOWN, UIWidgets::Colors::Brown }, + { ACTOR_47_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, + { ACTOR_46_JIGGY, UIWidgets::Colors::Yellow }, + { ACTOR_60_JINJO_BLUE, UIWidgets::Colors::SkyBlue }, + { ACTOR_62_JINJO_GREEN, UIWidgets::Colors::Green }, + { ACTOR_5F_JINJO_ORANGE, UIWidgets::Colors::Orange }, + { ACTOR_61_JINJO_PINK, UIWidgets::Colors::Pink }, + { ACTOR_5E_JINJO_YELLOW, UIWidgets::Colors::Yellow }, + { ACTOR_12C_MOLEHILL, UIWidgets::Colors::Cyan }, + { ACTOR_2D_MUMBO_TOKEN, UIWidgets::Colors::Gray }, + { ACTOR_51_MUSIC_NOTE, UIWidgets::Colors::Yellow }, + { ACTOR_25E_SNS_EGG, UIWidgets::Colors::Pink }, + { ACTOR_25D_ICE_KEY, UIWidgets::Colors::White }, }; std::map snsItemColors = { @@ -165,16 +165,17 @@ Actor* FindActorByRandoCheckId(RandoCheckId randoCheckId) { void Rando::StaticData::SendCollisionNotification(RandoCheckId randoCheckId) { if (CVAR_SHOW_COLLISION_NOTIFICATIONS) { RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; + actor_e actorId = Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId); std::string prefix; std::string message; std::string suffix = ""; - ImVec4 itemColor = WIDGET_TEXT_COLOR(randoItemColors.at(randoSaveCheck.randoItemId)); + ImVec4 itemColor = WIDGET_TEXT_COLOR(randoItemColors.at(actorId)); - if (randoSaveCheck.randoItemId == RI_MOLEHILL) { + if (actorId == ACTOR_12C_MOLEHILL) { prefix = "You learned"; message = abilityNameList[randoSaveCheck.randoCollectionId].c_str(); - } else if (randoSaveCheck.randoItemId == RI_STOP_N_SWOP_EGG || - randoSaveCheck.randoItemId == RI_STOP_N_SWOP_KEY) { + } else if (randoSaveCheck.randoItemId >= RI_STOP_N_SWOP_EGG_BLUE && + randoSaveCheck.randoItemId <= RI_STOP_N_SWOP_ICE_KEY) { int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); prefix = "You collected "; prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; @@ -202,14 +203,6 @@ void Rando::StaticData::SendCollisionNotification(RandoCheckId randoCheckId) { } }; -bool ShouldOverrideSpawn(RandoCheckId randoCheckId) { - if (Rando::Logic::IsCheckShuffled(randoCheckId)) { - return true; - } - - return false; -} - bool CheckEnemyOverlapPosition(int32_t pos[3]) { level_e levelId = map_getLevel(gsworld_getMap()); bool enemyOverlap = false; @@ -238,8 +231,6 @@ bool CheckEnemyOverlapPosition(int32_t pos[3]) { return enemyOverlap; } -// CALL_EVENT expands to a braced initializer whose commas don't survive being passed through the -// COND_HOOK macro wrapper, so fire it from a plain function the listener calls instead. static void FireClearBundleDespawnQueue() { CALL_EVENT(ClearBundleDespawnQueue); } @@ -359,6 +350,7 @@ void Rando::ObjectBehavior::Init() { RandoItemId randoItemId = RI_UNKNOWN; if (ev->propId->markerFlag) { + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[ev->propId->actorProp.marker->randoCheckId]; Actor* markerActor = marker_getActor(ev->propId->actorProp.marker); if (markerActor->is_bundle && func_802C9C14(markerActor)) { @@ -369,17 +361,17 @@ void Rando::ObjectBehavior::Init() { switch (ev->propId->actorProp.marker->id) { case MARKER_39_MUMBO_TOKEN: if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUMBO_TOKENS].optionValue == RO_GENERIC_ON) { - randoItemId = RI_MUMBO_TOKEN; + randoItemId = randoSaveCheck.randoItemId; } break; case MARKER_52_JIGGY: if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue == RO_GENERIC_ON) { - randoItemId = RI_JIGGY; + randoItemId = randoSaveCheck.randoItemId; } break; case MARKER_53_EMPTY_HONEYCOMB: if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_EMPTY_HONEYCOMBS].optionValue == RO_GENERIC_ON) { - randoItemId = RI_EMPTY_HONEYCOMB; + randoItemId = randoSaveCheck.randoItemId; } break; case MARKER_5A_JINJO_BLUE: @@ -388,21 +380,20 @@ void Rando::ObjectBehavior::Init() { case MARKER_5D_JINJO_PINK: case MARKER_5E_JINJO_YELLOW: if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_JINJOS].optionValue == RO_GENERIC_ON) { - randoItemId = Rando::StaticData::GetRandoItemByActorId( - jinjoMarkerMap.at(ev->propId->actorProp.marker->id)); + randoItemId = randoSaveCheck.randoItemId; } break; case MARKER_5F_MUSIC_NOTE: if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue == RO_GENERIC_ON) { - randoItemId = RI_MUSIC_NOTE; + randoItemId = randoSaveCheck.randoItemId; event->Cancelled = true; } break; case MARKER_168_ICE_KEY: - randoItemId = RI_STOP_N_SWOP_KEY; + randoItemId = randoSaveCheck.randoItemId; break; case MARKER_169_SNS_EGG: - randoItemId = RI_STOP_N_SWOP_EGG; + randoItemId = randoSaveCheck.randoItemId; break; case MARKER_265_WORLD_EXIT_PAD: for (int i = LEVEL_1_MUMBOS_MOUNTAIN; i < LEVEL_A_MAD_MONSTER_MANSION; i++) { diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.h b/src/port/Rando/ObjectBehavior/ObjectBehavior.h index 5c7fb44bb..25221fd9e 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.h +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.h @@ -4,7 +4,6 @@ #include "port/Rando/Rando.h" #include -bool ShouldOverrideSpawn(RandoCheckId randoCheckId); bool CheckEnemyOverlapPosition(int32_t pos[3]); int32_t GetJinjoActorMarkerId(actor_e actorId); extern std::vector enemyKillOverlapList; diff --git a/src/port/Rando/StaticData/Checks.cpp b/src/port/Rando/StaticData/Checks.cpp index 834064a91..870e70a11 100644 --- a/src/port/Rando/StaticData/Checks.cpp +++ b/src/port/Rando/StaticData/Checks.cpp @@ -23,1214 +23,1214 @@ std::array CheckNames = std::array(); // clang-format off std::map Checks = { - RC(RC_UNKNOWN, RCTYPE_UNKNOWN, LEVEL_D_CUTSCENE, ACTOR_1_UNKNOWN, NULL, 0, 0, 0), - RC(RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_7_BGS_MUMBOS, 0, 600, 0), - RC(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_8_BGS_TANKTUP, 0, 537, -1157), - RC(RC_BGS_JIGGY_CROCTUS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_22_CROCTUS, 0, 0, 0), - RC(RC_BGS_JIGGY_ELEVATED_WALKWAY, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_20_BGS_ELEVATED_WALKWAY, 0, 0, 0), - RC(RC_BGS_JIGGY_FLIBBITS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_24_BGS_FLIBBITS, 0, 0, 0), - RC(RC_BGS_JIGGY_HUTS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_23_BGS_HUTS, 0, 0, 0), - RC(RC_BGS_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_1F_BGS_JINGO, 0, 0, 0), - RC(RC_BGS_JIGGY_MAZE, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_25_BGS_MAZE, 0, 0, 0), - RC(RC_BGS_JIGGY_MR_VILE, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_28_BGS_MR_VILE, 0, 0, 0), - RC(RC_BGS_JIGGY_PINKEGG, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_21_BGS_PINKEGG, 0, 0, 0), - RC(RC_BGS_JIGGY_TANKTUP, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_26_BGS_TANKTUP, 0, 0, 0), - RC(RC_BGS_JIGGY_TIPTUP, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_46_JIGGY, JIGGY_27_BGS_TIPTUP, 0, 0, 0), - RC(RC_BGS_JINJO_BLUE, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_60_JINJO_BLUE, NULL, -3061, 1146, -10052), - RC(RC_BGS_JINJO_GREEN, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_62_JINJO_GREEN, NULL, 1650, 1600, 1988), - RC(RC_BGS_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_5F_JINJO_ORANGE, NULL, 5472, 0, 2853), - RC(RC_BGS_JINJO_PINK, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_61_JINJO_PINK, NULL, 5670, 0, -4158), - RC(RC_BGS_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_5E_JINJO_YELLOW, NULL, -1606, 500, 2797), - RC(RC_BGS_MOLEHILL_WADING_BOOTS, RCTYPE_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_12C_MOLEHILL, ABILITY_E_WADING_BOOTS, 4297, 100, 6286), - RC(RC_BGS_MUMBO_TOKEN_ALCOVE_ABOVE_YELLOW_FLIBBITS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_1B_BGS_ALCOVE_ABOVE_YELLOW_FLIBBITS, 4278, 1400, -1302), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_1A_BGS_BEHIND_MUMBOS_SKULL, -6940, 1000, -5838), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_1C_BGS_BEHIND_TIPTUP, 0, 0, -1829), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_YELLOW_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_18_BGS_BEHIND_YELLOW_JINJO, -1855, 0, 2835), - RC(RC_BGS_MUMBO_TOKEN_FLOATING_BETWEEN_HUT_AND_CROCTUS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_19_BGS_FLOATING_BETWEEN_HUT_AND_CROCTUS, 6546, 2992, -4697), - RC(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_1D_BGS_INSIDE_MR_VILES, 0, 300, -1754), - RC(RC_BGS_MUMBO_TOKEN_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_1E_BGS_INSIDE_MUMBOS_SKULL, 0, 0, -450), - RC(RC_BGS_MUMBO_TOKEN_TOP_OF_POLE_NEXT_TO_BIG_EGG, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_17_BGS_TOP_OF_POLE_NEXT_TO_BIG_EGG, -3993, 1055, 1295), - RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_1, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_15_BGS_UNDER_HUT_1, 5049, 0, -5142), - RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_2, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_16_BGS_UNDER_HUT_2, 5347, 0, -5055), - RC(RC_BGS_NOTE_ABOVE_MR_VILES_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -912, 347, -3385), - RC(RC_BGS_NOTE_ABOVE_MR_VILES_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1073, 318, -3495), - RC(RC_BGS_NOTE_ABOVE_MR_VILES_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1247, 405, -3608), - RC(RC_BGS_NOTE_ABOVE_MR_VILES_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1406, 517, -3718), - RC(RC_BGS_NOTE_ABOVE_MR_VILES_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1550, 652, -3828), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 29, 899, -2061), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 207, 948, -2346), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 587, 1023, -2412), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 847, 1049, -2243), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 1161, 1099, -2187), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_6, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2261, 1075, -2275), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_7, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2606, 1174, -2223), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_8, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2904, 1125, -2136), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_9, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3290, 1224, -1883), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_10, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3425, 1200, -826), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_11, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3308, 1299, -451), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_12, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2973, 1349, -237), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_13, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2619, 1299, -284), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_14, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2310, 1200, -229), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_15, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2150, 1200, 54), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_16, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2145, 1299, 442), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_17, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 1202, 1350, 656), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_18, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 918, 1200, 687), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_19, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 575, 1249, 703), - RC(RC_BGS_NOTE_ELEVATED_WALKWAY_20, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 228, 1101, 502), - RC(RC_BGS_NOTE_FIFTH_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 468, 93, -2275), - RC(RC_BGS_NOTE_FIFTH_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 287, 93, -2417), - RC(RC_BGS_NOTE_FIFTH_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 105, 93, -2559), - RC(RC_BGS_NOTE_FIRST_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -68, 93, 1120), - RC(RC_BGS_NOTE_FIRST_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -74, 93, 920), - RC(RC_BGS_NOTE_FIRST_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -82, 93, 720), - RC(RC_BGS_NOTE_FOURTH_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3178, 93, -2312), - RC(RC_BGS_NOTE_FOURTH_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3355, 93, -2460), - RC(RC_BGS_NOTE_FOURTH_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3529, 93, -2607), - RC(RC_BGS_NOTE_HUT_BUNDLE_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_BGS_NOTE_HUT_BUNDLE_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_BGS_NOTE_HUT_BUNDLE_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_BGS_NOTE_HUT_BUNDLE_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_BGS_NOTE_HUT_BUNDLE_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 280, 125, -2069), - RC(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 219, 125, -1941), - RC(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 200, 125, -1810), - RC(RC_BGS_NOTE_INSIDE_MR_VILES_RIGHT_NOSTRIL_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -280, 125, -2070), - RC(RC_BGS_NOTE_INSIDE_MR_VILES_RIGHT_NOSTRIL_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -219, 125, -1939), - RC(RC_BGS_NOTE_INSIDE_MR_VILES_RIGHT_NOSTRIL_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -199, 125, -1810), - RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1006, 444, 3631), - RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -984, 485, 3375), - RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -962, 524, 3114), - RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -912, 479, 2851), - RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -862, 437, 2592), - RC(RC_BGS_NOTE_MAZE_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -6304, 992, -3449), - RC(RC_BGS_NOTE_MAZE_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -5548, 992, -2204), - RC(RC_BGS_NOTE_MAZE_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -6054, 992, -2704), - RC(RC_BGS_NOTE_MAZE_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -6546, 992, -2193), - RC(RC_BGS_NOTE_MAZE_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -7047, 985, -3702), - RC(RC_BGS_NOTE_MAZE_6, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -8055, 991, -3200), - RC(RC_BGS_NOTE_MAZE_7, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -8553, 991, -2207), - RC(RC_BGS_NOTE_MAZE_8, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -8047, 991, -4700), - RC(RC_BGS_NOTE_MAZE_9, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -8548, 991, -4204), - RC(RC_BGS_NOTE_MAZE_10, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -8046, 991, -5201), - RC(RC_BGS_NOTE_MAZE_11, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -7553, 991, -5702), - RC(RC_BGS_NOTE_MAZE_12, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -6524, 1007, -4200), - RC(RC_BGS_NOTE_POLE_NEAR_BLUE_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -4105, 1250, -8802), - RC(RC_BGS_NOTE_POLE_NEAR_BLUE_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -4105, 1350, -8802), - RC(RC_BGS_NOTE_POLE_NEAR_BLUE_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -4105, 1450, -8802), - RC(RC_BGS_NOTE_SECOND_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1345, 92, -153), - RC(RC_BGS_NOTE_SECOND_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1591, 92, -179), - RC(RC_BGS_NOTE_SECOND_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1834, 92, -204), - RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -2216, 0, -9596), - RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -2349, 0, -10049), - RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -2489, 0, -10528), - RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -3024, 0, -10719), - RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -3558, 0, -10911), - RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 7253, 0, -3699), - RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 7433, 0, -3931), - RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 7612, 0, -4165), - RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 7599, 0, -4481), - RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 7585, 0, -4798), - RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -3501, 0, 3668), - RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -4017, 0, 3876), - RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -4544, 0, 4085), - RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -4920, 0, 3823), - RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -5293, 0, 3559), - RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 4789, 0, -4503), - RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 4793, 0, -4288), - RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 5015, 0, -4288), - RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 5009, 0, -4507), - RC(RC_BGS_NOTE_TANKTUP_FEET_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3697, 176, 1632), - RC(RC_BGS_NOTE_TANKTUP_FEET_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 4351, 174, 955), - RC(RC_BGS_NOTE_TANKTUP_FEET_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 4461, 168, 2373), - RC(RC_BGS_NOTE_TANKTUP_FEET_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 5059, 170, 1758), - RC(RC_BGS_NOTE_TANKTUP_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 1006, 0, 235), - RC(RC_BGS_NOTE_TANKTUP_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 1022, 0, 0), - RC(RC_BGS_NOTE_TANKTUP_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 1005, 0, -236), - RC(RC_BGS_NOTE_TANKTUP_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1006, 0, 236), - RC(RC_BGS_NOTE_TANKTUP_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1022, 0, 0), - RC(RC_BGS_NOTE_TANKTUP_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, -1005, 0, -234), - RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 2921, 93, -513), - RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3020, 93, -304), - RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, ACTOR_51_MUSIC_NOTE, NULL, 3114, 93, -86), - RC(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_6_CC_ABOVE_WATER, 7886, 4272, 1969), - RC(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_5_CC_UNDERWATER, 3718, 3311, 2519), - RC(RC_CC_JIGGY_BOLT, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_18_CC_BOLT, 90, 5962, -12), - RC(RC_CC_JIGGY_CLANKER_RAISED, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_17_CC_CLANKER_RAISED, 0, 0, 0), - RC(RC_CC_JIGGY_FAST_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_1E_CC_FAST_SAWBLADES, 0, -340, -1604), - RC(RC_CC_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_15_CC_JINJO, 0, 0, 0), - RC(RC_CC_JIGGY_LONG_PIPE, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_1A_CC_LONG_PIPE, 4629, 2151, 3082), - RC(RC_CC_JIGGY_RINGS, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_1C_CC_RINGS, 0, 0, 0), - RC(RC_CC_JIGGY_SLOW_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_1D_CC_SLOW_SAWBLADES, 10, -391, -2185), - RC(RC_CC_JIGGY_TAIL, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_19_CC_TAIL, 10061, 5112, 3), - RC(RC_CC_JIGGY_TOOTH, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_1B_CC_TOOTH, 0, 0, 0), - RC(RC_CC_JIGGY_SNIPPETS, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, ACTOR_46_JIGGY, JIGGY_16_CC_SNIPPETS, 0, 0, 0), - RC(RC_CC_JINJO_BLUE, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, ACTOR_60_JINJO_BLUE, NULL, 4326, 2146, -4080), - RC(RC_CC_JINJO_GREEN, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, ACTOR_62_JINJO_GREEN, NULL, 5017, -3085, -13), - RC(RC_CC_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, ACTOR_5F_JINJO_ORANGE, NULL, 6138, 5087, 2637), - RC(RC_CC_JINJO_PINK, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, ACTOR_61_JINJO_PINK, NULL, 3644, -474, 48), - RC(RC_CC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, ACTOR_5E_JINJO_YELLOW, NULL, -4726, 5337, -110), - RC(RC_CC_MOLEHILL_WONDERWING, RCTYPE_MOLEHILL, LEVEL_3_CLANKERS_CAVERN, ACTOR_12C_MOLEHILL, ABILITY_12_WONDERWING, -259, -500, 1413), - RC(RC_CC_MUMBO_TOKEN_CHOMPA_BEHIND_CLANKERS_TAIL, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_10_CC_CHOMPA_BEHIND_CLANKERS_TAIL, 9823, 4225, -19), - RC(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE, -9694, 5272, 1607), - RC(RC_CC_MUMBO_TOKEN_TUNNEL_RIGHT_OF_CLANKER, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, 870, 2146, -3148), - RC(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_13_CC_ALCOVE_WITH_OPEN_GRATE, 2028, 5456, 2344), - RC(RC_CC_MUMBO_TOKEN_CLANKERS_LEFT_TOOTH, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_14_CC_CLANKERS_LEFT_TOOTH, 532, 1424, 6632), - RC(RC_CC_NOTE_ABOVE_BOLT_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 2036, 5693, -15), - RC(RC_CC_NOTE_ABOVE_BOLT_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 1533, 5693, 381), - RC(RC_CC_NOTE_ABOVE_BOLT_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 1043, 5693, 377), - RC(RC_CC_NOTE_ABOVE_BOLT_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 939, 5693, -17), - RC(RC_CC_NOTE_CLIMBABLE_PIPE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3013, 4437, 2477), - RC(RC_CC_NOTE_CLIMBABLE_PIPE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3013, 4827, 2477), - RC(RC_CC_NOTE_CLIMBABLE_PIPE_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3013, 5117, 2477), - RC(RC_CC_NOTE_CLIMBABLE_PIPE_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3013, 5407, 2477), - RC(RC_CC_NOTE_ENTRANCE_TUNNEL_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -2580, 2841, 0), - RC(RC_CC_NOTE_ENTRANCE_TUNNEL_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -2030, 2466, 0), - RC(RC_CC_NOTE_ENTRANCE_TUNNEL_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -1480, 2461, 0), - RC(RC_CC_NOTE_ENTRANCE_TUNNEL_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -930, 2437, 0), - RC(RC_CC_NOTE_ENTRANCE_TUNNEL_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -380, 2236, 0), - RC(RC_CC_NOTE_ENTRANCE_TUNNEL_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 170, 2155, 0), - RC(RC_CC_NOTE_FAST_SAWBLADES_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -500, 1695), - RC(RC_CC_NOTE_FAST_SAWBLADES_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -500, 1130), - RC(RC_CC_NOTE_FAST_SAWBLADES_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -500, 555), - RC(RC_CC_NOTE_FAST_SAWBLADES_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -500, -20), - RC(RC_CC_NOTE_FAST_SAWBLADES_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -500, -600), - RC(RC_CC_NOTE_FAST_SAWBLADES_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -500, -1335), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, 1002, 5174), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 684, 999, 5391), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 780, 1004, 6071), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 566, 1007, 6712), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, 1008, 7036), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -566, 1015, 6712), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -792, 1005, 6071), - RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -685, 990, 5391), - RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -998, -387, 0), - RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -1399, -539, -10), - RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -1801, -493, -10), - RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -2199, -351, -10), - RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -2601, -8, -10), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -7636, 5162, -1164), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -8284, 5243, -911), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -8573, 5244, -353), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -9112, 5243, -182), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -7910, 5212, 804), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -7038, 5212, 754), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -6634, 5212, 238), - RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, -6065, 5211, 313), - RC(RC_CC_NOTE_NEAR_PINK_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 1600, 953, 20), - RC(RC_CC_NOTE_NEAR_PINK_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 1999, 1241, 45), - RC(RC_CC_NOTE_NEAR_PINK_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 2399, 1258, 45), - RC(RC_CC_NOTE_NEAR_SNIPPETS_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 13028, 3362, -761), - RC(RC_CC_NOTE_NEAR_SNIPPETS_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 13540, 3362, -973), - RC(RC_CC_NOTE_NEAR_SNIPPETS_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 14096, 3362, -969), - RC(RC_CC_NOTE_NEAR_SNIPPETS_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 14602, 3362, -732), - RC(RC_CC_NOTE_NEAR_SNIPPETS_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 14590, 3362, 702), - RC(RC_CC_NOTE_NEAR_SNIPPETS_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 14105, 3361, 929), - RC(RC_CC_NOTE_NEAR_SNIPPETS_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 13538, 3362, 931), - RC(RC_CC_NOTE_NEAR_SNIPPETS_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 13018, 3362, 713), - RC(RC_CC_NOTE_NEAR_TAIL_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 8755, 4225, -1418), - RC(RC_CC_NOTE_NEAR_TAIL_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 8756, 4225, 1278), - RC(RC_CC_NOTE_NEAR_TAIL_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9091, 4225, 1104), - RC(RC_CC_NOTE_NEAR_TAIL_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9449, 4225, 923), - RC(RC_CC_NOTE_NEAR_TAIL_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9636, 4225, 630), - RC(RC_CC_NOTE_NEAR_TAIL_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9818, 4225, 339), - RC(RC_CC_NOTE_NEAR_TAIL_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9818, 4225, -377), - RC(RC_CC_NOTE_NEAR_TAIL_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9636, 4225, -679), - RC(RC_CC_NOTE_NEAR_TAIL_9, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9438, 4225, -978), - RC(RC_CC_NOTE_NEAR_TAIL_10, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 9091, 4225, -1207), - RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6582, 5284, 2536), - RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6785, 5121, 2454), - RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6989, 4958, 2388), - RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 7194, 4787, 2321), - RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 7401, 4611, 2247), - RC(RC_CC_NOTE_SLOW_SAWBLADES_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -425, 1610), - RC(RC_CC_NOTE_SLOW_SAWBLADES_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -425, 1010), - RC(RC_CC_NOTE_SLOW_SAWBLADES_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -425, 410), - RC(RC_CC_NOTE_SLOW_SAWBLADES_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -425, -190), - RC(RC_CC_NOTE_SLOW_SAWBLADES_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -425, -790), - RC(RC_CC_NOTE_SLOW_SAWBLADES_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 0, -425, -1390), - RC(RC_CC_NOTE_TOP_OF_CLANKER_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3200, 4243, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3500, 4269, 2), - RC(RC_CC_NOTE_TOP_OF_CLANKER_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3800, 4281, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 4100, 4293, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5300, 4209, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5600, 4161, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5899, 4106, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6200, 4072, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_9, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6500, 4047, 0), - RC(RC_CC_NOTE_TOP_OF_CLANKER_10, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6800, 4063, 0), - RC(RC_CC_NOTE_UNDERWATER_LOCK_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6361, -3085, -908), - RC(RC_CC_NOTE_UNDERWATER_LOCK_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6716, -3085, -18), - RC(RC_CC_NOTE_UNDERWATER_LOCK_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6350, -3085, 866), - RC(RC_CC_NOTE_UNDERWATER_LOCK_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5468, -3085, 1225), - RC(RC_CC_NOTE_UNDERWATER_LOCK_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 4583, -3085, 865), - RC(RC_CC_NOTE_UNDERWATER_LOCK_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 4220, -3085, -19), - RC(RC_CC_NOTE_UNDERWATER_LOCK_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 4584, -3085, -906), - RC(RC_CC_NOTE_UNDERWATER_LOCK_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5469, -3085, -1273), - RC(RC_CC_NOTE_UNDERWATER_PIPE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 3866, 1198, 2618), - RC(RC_CC_NOTE_UNDERWATER_PIPE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 4427, 1188, 2637), - RC(RC_CC_NOTE_UNDERWATER_PIPE_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 4961, 1184, 2649), - RC(RC_CC_NOTE_UNDERWATER_PIPE_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5417, 1184, 2626), - RC(RC_CC_NOTE_UNDERWATER_PIPE_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5881, 1184, 2600), - RC(RC_CC_NOTE_UNDERWATER_PIPE_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6342, 1184, 2485), - RC(RC_CC_NOTE_UNDERWATER_PIPE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 6804, 1184, 2361), - RC(RC_CC_NOTE_YELLOW_GRATE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 2240, 5262, -2473), - RC(RC_CC_NOTE_YELLOW_GRATE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, ACTOR_51_MUSIC_NOTE, NULL, 5270, 5261, -2937), - RC(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_D_CCW_GNAWTYS, 694, 998, 632), - RC(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_E_CCW_NABNUTS, 640, 513, -202), - RC(RC_CCW_JIGGY_EYRIE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_49_CCW_EYRIE, 0, 0, 0), - RC(RC_CCW_JIGGY_FLOWER, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_4D_CCW_FLOWER, 0, 0, 0), - RC(RC_CCW_JIGGY_GNAWTY, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_4B_CCW_GNAWTY, 240, 600, 75), - RC(RC_CCW_JIGGY_HOUSE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_48_CCW_HOUSE, 6070, 4244, -113), - RC(RC_CCW_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_47_CCW_JINJO, 0, 0, 0), - RC(RC_CCW_JIGGY_NABNUT, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_4A_CCW_NABNUT, 0, 0, 0), - RC(RC_CCW_JIGGY_SUMMER_LEAF_JUMPS, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_4E_CCW_SUMMER_LEAF_JUMPS, 2215, 2616, 2142), - RC(RC_CCW_JIGGY_TOP_ROOM, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_50_CCW_TOP_ROOM, 0, 17, 225), - RC(RC_CCW_JIGGY_TREE_TOP, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_4F_CCW_TREE_TOP, 0, 7625, 3100), - RC(RC_CCW_JIGGY_ZUBBAS, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_46_JIGGY, JIGGY_4C_CCW_ZUBBAS, 0, 0, 125), - RC(RC_CCW_JINJO_BLUE, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_60_JINJO_BLUE, NULL, -6775, 1301, 0), - RC(RC_CCW_JINJO_GREEN, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_62_JINJO_GREEN, NULL, 0, 5760, -3330), - RC(RC_CCW_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_5F_JINJO_ORANGE, NULL, -1592, 900, -6073), - RC(RC_CCW_JINJO_PINK, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_61_JINJO_PINK, NULL, -225, 1039, -1100), - RC(RC_CCW_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_5E_JINJO_YELLOW, NULL, -3602, 0, 4266), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_6A_CCW_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, 153, 1857, 2677), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_6D_CCW_AUTUMN_LEAF_NEAR_TREEHOUSE, 3405, 4107, 1003), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_6B_CCW_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, 500, 166, 5125), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_6C_CCW_AUTUMN_SNAREBEAR_TOP_OF_TREE, 0, 5830, -3325), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_6E_CCW_AUTUMN_TOP_OF_BRANCH, -5929, 2586, 61), - RC(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_5D_CCW_SPRING_FRONT_OF_EYRIE, -2750, 4586, -513), - RC(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_62_CCW_SPRING_NABNUTS_HOUSE, -575, 300, -139), - RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_5F_CCW_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, 1904, 105, -2706), - RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_60_CCW_SPRING_SNAREBEAR_NEAR_ENTRANCE, 1000, 105, 5300), - RC(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_5E_CCW_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, -2649, 0, -395), - RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_61_CCW_SPRING_TOP_OF_BEEHIVE, 0, 3513, -5240), - RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_5C_CCW_SPRING_TOP_OF_BRANCH, -4053, 2894, 587), - RC(RC_CCW_MUMBO_TOKEN_SPRING_UNFINISHED_WOOD_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_5B_CCW_SPRING_UNFINISHED_WOOD_TREEHOUSE, 6134, 4244, 306), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_64_CCW_SUMMER_BIG_FLOWER_FIELD, -3578, 40, -4259), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_67_CCW_SUMMER_ENTRANCE_GNAWTYS_HOUSE, 2700, -600, 0), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_68_CCW_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, 2043, 3534, 1799), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_69_CCW_SUMMER_INSIDE_MUMBOS_SKULL, 0, 416, 500), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_63_CCW_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, -1861, 4469, 1583), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_65_CCW_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, -3855, 1428, 3840), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_66_CCW_SUMMER_TOP_OF_BRANCH, -4661, 2800, -1248), - RC(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_6F_CCW_WINTER_BIG_FLOWER, 0, 105, -5400), - RC(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_71_CCW_WINTER_BROKEN_BEEHIVE, 0, 3138, -3696), - RC(RC_CCW_MUMBO_TOKEN_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_70_CCW_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, 5950, -46, 0), - RC(RC_CCW_MUMBO_TOKEN_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, -3157, 300, -3149), - RC(RC_CCW_MUMBO_TOKEN_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_72_CCW_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, 40, 3969, 5000), - RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -674, -1, 925), - RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -674, 0, -900), - RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 675, -2, 925), - RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 675, 0, -674), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3929, 4900, 312), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -4375, 4900, 765), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -5024, 4900, 766), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -5471, 4900, 312), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -5471, 4900, -313), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -5024, 4900, -766), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_7, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -4376, 4900, -766), - RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_8, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3929, 4900, -313), - RC(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 768, 998, 596), - RC(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 613, 998, 664), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -359, 379, -359), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -360, 398, 375), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 362, 379, -365), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 363, 398, 364), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_NABNUTS_HOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 288, 413, -357), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_NABNUTS_HOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 382, 413, -296), - RC(RC_CCW_NOTE_AUTUMN_INSIDE_NABNUTS_HOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 471, 413, -235), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -968, 900, 2578), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 969, 900, 2569), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 2569, 900, 969), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 2570, 900, -970), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 1950, 900, -1950), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 970, 900, -2569), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_7, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -50, 1100, -2750), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_8, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -970, 900, -2570), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_9, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2584, 1100, -971), - RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_10, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2577, 900, 972), - RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 950, 10, -6531), - RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 475, 10, -6599), - RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 0, 10, -6640), - RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -475, 10, -6599), - RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -950, 10, -6531), - RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 1905, 170, -2705), - RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 1905, 250, -2705), - RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 1905, 330, -2705), - RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3801, 1452, 3790), - RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3801, 1532, 3790), - RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3801, 1612, 3790), - RC(RC_CCW_NOTE_ENTRANCE_HUB_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 816, 8, 3277), - RC(RC_CCW_NOTE_ENTRANCE_HUB_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 342, 2, 3477), - RC(RC_CCW_NOTE_ENTRANCE_HUB_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -342, 2, 3477), - RC(RC_CCW_NOTE_ENTRANCE_HUB_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -818, 8, 3275), - RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2975, 300, -2975), - RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3150, 307, -3150), - RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3325, 300, -3325), - RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_MUMBOS_SKULL_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2700, 900, 2700), - RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_MUMBOS_SKULL_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2900, 900, 2900), - RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_MUMBOS_SKULL_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -3100, 921, 3100), - RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 2875, 894, 2875), - RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 3075, 876, 3075), - RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 3275, 845, 3274), - RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 2826, 1275, -2825), - RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 3025, 1275, -3025), - RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 3225, 1275, -3225), - RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 0, 900, 2750), - RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 1950, 900, 1950), - RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 2750, 900, 0), - RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -1950, 937, -1950), - RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2750, 900, 0), - RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -1950, 1350, 1950), - RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 500, 59, -4950), - RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -500, 48, -4950), - RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -500, 52, -5850), - RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 500, 52, -5850), - RC(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 2201, -600, 0), - RC(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 1700, -589, 0), - RC(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -123, 308, 3059), - RC(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 115, 608, 3056), - RC(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 0, 3300, -2750), - RC(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 0, 3310, -2950), - RC(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 0, 3350, -3150), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 700, 4819, 4750), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 400, 4819, 4450), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 0, 4819, 4400), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -400, 4819, 4450), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -700, 4819, 4750), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 4728, 4244, -522), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 4671, 4243, -329), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 4562, 4243, 54), - RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 4507, 4244, 249), - RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -1150, 4019, 4300), - RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -1599, 4019, 4750), - RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2051, 4019, 4300), - RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -1599, 4019, 3851), - RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -4034, 2899, -939), - RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -4654, 2800, -1243), - RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -4040, 2894, 583), - RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -4652, 2800, 647), - RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 4741, 4958, -106), - RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 5156, 4957, 13), - RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 5571, 4957, 132), - RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, 5987, 4958, 252), - RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2637, 4569, -871), - RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -2308, 4869, -1528), - RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -1691, 5210, -2199), - RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_51_MUSIC_NOTE, NULL, -764, 5590, -2634), - RC(RC_CCW_SNS_YELLOW_EGG, RCTYPE_STOP_N_SWOP, LEVEL_8_CLICK_CLOCK_WOOD, ACTOR_25E_SNS_EGG, SNS_ITEM_EGG_YELLOW, 556, 150, 47), - RC(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_A_FP_SIR_SLUSH, 4295, 441, 1268), - RC(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_9_FP_WOZZAS_CAVE, -6531, 135, 422), - RC(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_31_FP_SIR_SLUSH, 0, 0 ,0), - RC(RC_FP_JIGGY_BOGGY_RACE_1, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_30_FP_BOGGY_2, 0, 0 ,0), - RC(RC_FP_JIGGY_BOGGY_RACE_2, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_2C_FP_BOGGY_3, 0, 0 ,0), - RC(RC_FP_JIGGY_IGLOO, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_2E_FP_PRESENTS, 0, 0 ,0), - RC(RC_FP_JIGGY_INSIDE_THE_TREE, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_2F_FP_XMAS_TREE, 0, 2305, 0), - RC(RC_FP_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_29_FP_JINJO, 0, 0 ,0), - RC(RC_FP_JIGGY_SLED_TO_BOGGY, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_2A_FP_BOGGY_1, 0, 0 ,0), - RC(RC_FP_JIGGY_SNOWMANS_BUTTONS, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_2D_FP_SNOWMAN_BUTTONS, 0, 0 ,0), - RC(RC_FP_JIGGY_SNOWMANS_PIPE, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_2B_FP_PIPE, -1019, 5936, 2047), - RC(RC_FP_JIGGY_WOZZA, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, ACTOR_46_JIGGY, JIGGY_32_FP_WOZZA, -4605, 822, -3938), - RC(RC_FP_JINJO_BLUE, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, ACTOR_60_JINJO_BLUE, NULL, -2588, 5684, 60), - RC(RC_FP_JINJO_GREEN, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, ACTOR_62_JINJO_GREEN, NULL, 6083, 450, 2736), - RC(RC_FP_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, ACTOR_5F_JINJO_ORANGE, NULL, 629, 366, 859), - RC(RC_FP_JINJO_PINK, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, ACTOR_61_JINJO_PINK, NULL, -6851, 1193, 930), - RC(RC_FP_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, ACTOR_5E_JINJO_YELLOW, NULL, 0, 406, -511), - RC(RC_FP_MOLEHILL_BEAK_BOMB, RCTYPE_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK, ACTOR_12C_MOLEHILL, ABILITY_1_BEAK_BOMB, -7462, 250, 1324), - RC(RC_FP_MUMBO_TOKEN_INSIDE_BOGGYS_IGLOO, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_28_FP_INSIDE_BOGGYS_IGLOO, 0, 10, -215), - RC(RC_FP_MUMBO_TOKEN_PRESENT_STACK, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_21_FP_BEHIND_PILE_PRESENT_BOXES, -5904, 260, 794), - RC(RC_FP_MUMBO_TOKEN_POTTED_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_25_FP_CHRISTMAS_TREE_POT, -4590, 350, 6344), - RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_START, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_23_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_LEFT_FOOT, 1413, 18, 2802), - RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_FINISH, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_24_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_RIGHT_FOOT, -4527, 211, -803), - RC(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_26_FP_TIP_OF_SCARF, -793, 3020, 4389), - RC(RC_FP_MUMBO_TOKEN_SNOWMAN_LEFT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_1F_FP_SNOWMAN_LEFT_FOOT, -1815, 4, -1019), - RC(RC_FP_MUMBO_TOKEN_SNOWMAN_RIGHT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_20_FP_SNOWMAN_RIGHT_FOOT, 634, 5, 769), - RC(RC_FP_MUMBO_TOKEN_VILLAGE_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_22_FP_ABOVE_CHIMNEY_FLIGHT_PAD, 5296, 2013, 2729), - RC(RC_FP_MUMBO_TOKEN_WATER_BEHIND_SNOWMAN, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_27_FP_WATER_BEHIND_SNOWMAN, -2424, -168, -4235), - RC(RC_FP_NOTE_FIRST_SLOPE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -790, 3505, 8345), - RC(RC_FP_NOTE_FIRST_SLOPE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -820, 3149, 7926), - RC(RC_FP_NOTE_FIRST_SLOPE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -843, 2725, 7475), - RC(RC_FP_NOTE_FIRST_SLOPE_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -864, 2243, 7025), - RC(RC_FP_NOTE_FIRST_SLOPE_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -888, 1727, 6573), - RC(RC_FP_NOTE_HOUSE_NEAR_MUMBO_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4268, 865, -589), - RC(RC_FP_NOTE_HOUSE_NEAR_MUMBO_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4468, 844, -705), - RC(RC_FP_NOTE_HOUSE_NEAR_MUMBO_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4659, 840, -815), - RC(RC_FP_NOTE_HOUSE_NEAR_SIR_SLUSH_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3865, 843, 3023), - RC(RC_FP_NOTE_HOUSE_NEAR_SIR_SLUSH_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3862, 844, 3237), - RC(RC_FP_NOTE_HOUSE_NEAR_SIR_SLUSH_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3860, 861, 3464), - RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -362, 379, -362), - RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -500, 398, 0), - RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -355, 398, 362), - RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 362, 378, -362), - RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 500, 387, 0), - RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 362, 398, 363), - RC(RC_FP_NOTE_NEAR_RACE_START_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 2656, 658, 5687), - RC(RC_FP_NOTE_NEAR_RACE_START_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 2700, 658, 6100), - RC(RC_FP_NOTE_NEAR_RACE_START_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 2271, 658, 6789), - RC(RC_FP_NOTE_NEAR_RACE_START_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 1892, 658, 6955), - RC(RC_FP_NOTE_NEAR_WOZZA_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -3938, 800, -3704), - RC(RC_FP_NOTE_NEAR_WOZZA_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -3705, 800, -4019), - RC(RC_FP_NOTE_NEAR_WOZZA_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -3661, 800, -4459), - RC(RC_FP_NOTE_NEAR_WOZZA_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -3920, 800, -4807), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4044, 295, 2411), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4039, 294, 106), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3763, 294, 320), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUCH_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3505, 295, 679), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3467, 295, 1433), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3654, 295, 1906), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4404, 294, 243), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4559, 295, 2482), - RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_9, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 4930, 294, 1918), - RC(RC_FP_NOTE_POTTED_TREE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -3430, 0, 6550), - RC(RC_FP_NOTE_POTTED_TREE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -3926, 0, 7284), - RC(RC_FP_NOTE_POTTED_TREE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -4844, 0, 7451), - RC(RC_FP_NOTE_POTTED_TREE_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -5579, 0, 6927), - RC(RC_FP_NOTE_POTTED_TREE_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -5754, 0, 6022), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -689, 600, -398), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -394, 600, -690), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 1, 600, -795), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 399, 600, -688), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 686, 600, -395), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 793, 600, 0), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 685, 600, 396), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 395, 600, 682), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_9, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 3, 600, 794), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_10, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -398, 600, 684), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_11, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -689, 600, 395), - RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_12, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -791, 600, 0), - RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -5971, 893, 900), - RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -6190, 893, 899), - RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -6409, 893, 900), - RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -6630, 893, 900), - RC(RC_FP_NOTE_SECOND_SLOPE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -900, 1727, 5675), - RC(RC_FP_NOTE_SECOND_SLOPE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -883, 1196, 5183), - RC(RC_FP_NOTE_SECOND_SLOPE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -867, 578, 4693), - RC(RC_FP_NOTE_SECOND_SLOPE_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -850, 0, 4201), - RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -4394, 0, -1052), - RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -4772, 0, -948), - RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -4668, 0, -570), - RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -4290, 0, -674), - RC(RC_FP_NOTE_SNOWMAN_HAT_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -672, 8736, 1047), - RC(RC_FP_NOTE_SNOWMAN_HAT_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1517, 8633, 860), - RC(RC_FP_NOTE_SNOWMAN_HAT_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -2000, 8492, 133), - RC(RC_FP_NOTE_SNOWMAN_HAT_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1804, 8434, -734), - RC(RC_FP_NOTE_SNOWMAN_HAT_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1046, 8503, -1179), - RC(RC_FP_NOTE_SNOWMAN_HAT_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -195, 8574, -1023), - RC(RC_FP_NOTE_SNOWMAN_HAT_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 257, 8711, -275), - RC(RC_FP_NOTE_SNOWMAN_HAT_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 80, 8749, 591), - RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1956, 5, -25), - RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -2176, 5, -559), - RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1254, 5, -943), - RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1026, 5, -403), - RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1378, 5, 47), - RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 283, 4, 1246), - RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -301, 4, 1176), - RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -515, 5, 629), - RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -154, 5, 162), - RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 426, 5, 244), - RC(RC_FP_NOTE_SNOWMAN_SCARF_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -2337, 1669, -5188), - RC(RC_FP_NOTE_SNOWMAN_SCARF_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -2704, 1958, -4154), - RC(RC_FP_NOTE_SNOWMAN_SCARF_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1952, 2278, -3614), - RC(RC_FP_NOTE_SNOWMAN_SCARF_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1192, 2772, -4242), - RC(RC_FP_NOTE_SNOWMAN_SCARF_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -615, 3247, -4985), - RC(RC_FP_NOTE_SNOWMAN_SCARF_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 59, 3511, -4554), - RC(RC_FP_NOTE_SNOWMAN_SCARF_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -387, 3764, -3875), - RC(RC_FP_NOTE_SNOWMAN_SCARF_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1062, 4007, -4301), - RC(RC_FP_NOTE_SNOWMAN_SCARF_9, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -631, 4267, -4977), - RC(RC_FP_NOTE_SNOWMAN_SCARF_10, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 42, 4530, -4557), - RC(RC_FP_NOTE_SNOWMAN_SCARF_11, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -20, 4790, -3699), - RC(RC_FP_NOTE_SNOWMAN_SCARF_12, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -140, 5225, -3101), - RC(RC_FP_NOTE_SNOWMAN_SCARF_13, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -248, 5452, -2390), - RC(RC_FP_NOTE_SNOWMAN_SCARF_14, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -353, 5101, -1787), - RC(RC_FP_NOTE_SNOWMAN_SCARF_15, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -491, 5430, -1199), - RC(RC_FP_NOTE_SNOWMAN_SCARF_16, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -583, 5605, -698), - RC(RC_FP_NOTE_SNOWMAN_SCARF_17, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -1514, 5605, -99), - RC(RC_FP_NOTE_SNOWMAN_SCARF_18, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, -941, 5605, 844), - RC(RC_FP_NOTE_SNOWMAN_SCARF_19, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, ACTOR_51_MUSIC_NOTE, NULL, 17, 5605, 266), - RC(RC_FP_SNS_ICE_KEY, RCTYPE_STOP_N_SWOP, LEVEL_5_FREEZEEZY_PEAK, ACTOR_25D_ICE_KEY, SNS_ITEM_ICE_KEY, 1567, 583, 2416), - RC(RC_GL_JIGGY_LOBBY, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_33_LAIR_1ST_JIGGY, -1505, 600, 123), - RC(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_37_LAIR_BGS_WITCH_SWITCH, 0, 0, -20), - RC(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_35_LAIR_CC_WITCH_SWITCH, 0, 75, 156), - RC(RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_3C_LAIR_CCW_WITCH_SWITCH, 0, 3370, 2270), - RC(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_38_LAIR_FP_WITCH_SWITCH, 4126, 2392, 6559), - RC(RC_GL_JIGGY_WITCH_SWITCH_GOBIS_VALLEY, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_3A_LAIR_GV_WITCH_SWITCH, -1290, 514, -787), - RC(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_39_LAIR_MMM_WITCH_SWITCH, 1597, 1011, -254), - RC(RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_34_LAIR_MM_WITCH_SWITCH, 4165, 1000, -2363), - RC(RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_3B_LAIR_RBB_WITCH_SWITCH, 0, 1200, 1650), - RC(RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE, RCTYPE_JIGGY, LEVEL_6_LAIR, ACTOR_46_JIGGY, JIGGY_36_LAIR_TTC_WITCH_SWITCH, 998, 783, 368), - RC(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_51_LAIR_BEHIND_PURPLE_CAULDRON, 162, -750, 4611), - RC(RC_GL_MUMBO_TOKEN_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_53_LAIR_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, -180, 351, -750), - RC(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_54_LAIR_ABOVE_CC_ENTRANCE, 0, 850, -2450), - RC(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_52_LAIR_CCW_JIGGY_PODIUM, 4936, -478, 286), - RC(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_55_LAIR_BEHIND_SARCOPHAGUS, -1486, 0, -922), - RC(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_56_LAIR_ADVENT_TOP_WINDOW, 4155, 1485, 6270), - RC(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_59_LAIR_UNDERWATER_RBB_ENTRANCE_AREA, 1764, -1400, -1136), - RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), - RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), - RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), - RC(RC_GV_EMPTY_HONEYCOMB_CACTUS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_B_GV_CACTUS, 2911, 3292, -3307), - RC(RC_GV_EMPTY_HONEYCOMB_GOBI, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_C_GV_GOBI_3, -6885, 2383, 1335), - RC(RC_GV_JIGGY_ANCIENT_ONES, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_46_GV_ANCIENT_ONES, 0, 0, 0), - RC(RC_GV_JIGGY_GOBI_1, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_44_GV_GOBI_1, 0, 0, 0), - RC(RC_GV_JIGGY_GOBI_2, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_45_GV_GOBI_2, 0, 0, 0), - RC(RC_GV_JIGGY_GRABBA, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_3E_GV_GRABBA, -4644, 1875, -4831), - RC(RC_GV_JIGGY_HISTUP, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_43_GV_HISTUP, -3, 1359, 15), - RC(RC_GV_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_3D_GV_JINJO, 0, 0, 0), - RC(RC_GV_JIGGY_MATCHING_GAME, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_40_GV_MATCHING_GAME, 0, 0, 0), - RC(RC_GV_JIGGY_MAZE, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_41_GV_MAZE, -5008, 66, 62), - RC(RC_GV_JIGGY_SHYINX, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_3F_GV_SHYINX, -2250, 1970, -49), - RC(RC_GV_JIGGY_WATER_PYRAMID, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, ACTOR_46_JIGGY, JIGGY_42_GV_WATER_PYRAMID, -1, 145, -23), - RC(RC_GV_JINJO_BLUE, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, ACTOR_60_JINJO_BLUE, NULL, 58, 535, 1570), - RC(RC_GV_JINJO_GREEN, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, ACTOR_62_JINJO_GREEN, NULL, 4952, 2538, 439), - RC(RC_GV_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, ACTOR_5F_JINJO_ORANGE, NULL, 2078, 1122, -50), - RC(RC_GV_JINJO_PINK, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, ACTOR_61_JINJO_PINK, NULL, -4964, 0, 700), - RC(RC_GV_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, ACTOR_5E_JINJO_YELLOW, NULL, 3067, 447, 10270), - RC(RC_GV_MOLEHILL_TURBO_TALON, RCTYPE_MOLEHILL, LEVEL_7_GOBIS_VALLEY, ACTOR_12C_MOLEHILL, ABILITY_11_TURBO_TALON, -6445, 2831, -822), - RC(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_2F_GV_BEHIND_SANDYBUTTS_SARCOPHAGUS, -5514, 0, 138), - RC(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_2B_GV_BOTTOM_OF_MOAT, 91, 535, -860), - RC(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_2D_GV_FRONT_OF_STAR_DOOR, -230, 2843, -3091), - RC(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_32_GV_INSIDE_JINXY, -2550, 0, -51), - RC(RC_GV_MUMBO_TOKEN_INSIDE_MEMORY_GAME_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_2E_GV_INSIDE_MEMORY_GAME_ROOM, 715, 248, 0), - RC(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_30_GV_INSIDE_WATER_PYRAMID, -300, 1439, -1194), - RC(RC_GV_MUMBO_TOKEN_NEXT_TO_RUBEE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_31_GV_NEXT_TO_RUBEE, 0, 107, -602), - RC(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_2A_GV_SAND_RIGHT_OF_JINXY, -5386, 1420, 10034), - RC(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_29_GV_TOP_OF_JINXYS_NOSE, -2149, 3340, 5867), - RC(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_2C_GV_TOP_OF_WATER_PYRAMID, 64, 3484, 400), - RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -7178, 2372, 1754), - RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -7148, 2371, 1568), - RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -7123, 2371, 1404), - RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -7105, 2371, 1247), - RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -7082, 2372, 1091), - RC(RC_GV_NOTE_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 88, 460, 8403), - RC(RC_GV_NOTE_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -251, 697, 8089), - RC(RC_GV_NOTE_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -584, 894, 7778), - RC(RC_GV_NOTE_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -935, 1082, 7449), - RC(RC_GV_NOTE_ENTRANCE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -1289, 1259, 7119), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -450, 19, -450), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -450, 19, 450), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 450, 19, -450), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 450, 19, 450), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 4215, 2452, -715), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 4815, 2452, -714), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 2395, 2130, -300), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 3090, 2730, -300), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 3090, 2730, 970), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 2395, 2130, 970), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 3792, 2656, 325), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 3930, 2849, 324), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 4070, 3040, 324), - RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 4211, 3233, 324), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -4002, 0, 43), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3504, 0, -190), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -2735, 0, 203), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -1913, 3, 210), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 4729, 0, -45), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 4178, 0, 205), - RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 5400, 0, 326), - RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -464, 2770, 1610), - RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -464, 2170, 2305), - RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 684, 2770, 1610), - RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 685, 2170, 2305), - RC(RC_GV_NOTE_MOAT_BOTTOM_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -908, 535, -472), - RC(RC_GV_NOTE_MOAT_BOTTOM_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -1182, 535, 457), - RC(RC_GV_NOTE_MOAT_BOTTOM_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -807, 535, 1318), - RC(RC_GV_NOTE_MOAT_BOTTOM_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 928, 535, 1291), - RC(RC_GV_NOTE_MOAT_BOTTOM_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 1234, 535, 411), - RC(RC_GV_NOTE_MOAT_BOTTOM_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 1055, 535, -458), - RC(RC_GV_NOTE_MOAT_EDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -2111, 1830, 1016), - RC(RC_GV_NOTE_MOAT_EDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -2100, 1830, 112), - RC(RC_GV_NOTE_MOAT_EDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -2098, 1830, -785), - RC(RC_GV_NOTE_MOAT_EDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -1455, 1830, -1432), - RC(RC_GV_NOTE_MOAT_EDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -800, 1830, -2068), - RC(RC_GV_NOTE_MOAT_EDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 110, 1830, -2068), - RC(RC_GV_NOTE_MOAT_EDGE_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 1019, 1830, -2068), - RC(RC_GV_NOTE_MOAT_EDGE_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 1671, 1830, -1416), - RC(RC_GV_NOTE_MOAT_EDGE_9, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 2307, 1837, -770), - RC(RC_GV_NOTE_NEAR_GRABBA_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3017, 1781, -5496), - RC(RC_GV_NOTE_NEAR_GRABBA_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3026, 1781, -5048), - RC(RC_GV_NOTE_NEAR_GRABBA_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3028, 1781, -4591), - RC(RC_GV_NOTE_NEAR_GRABBA_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3037, 1781, -4148), - RC(RC_GV_NOTE_NEAR_GRABBA_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3054, 1781, -3695), - RC(RC_GV_NOTE_NEAR_GRABBA_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3401, 1780, -3430), - RC(RC_GV_NOTE_NEAR_GRABBA_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3752, 1781, -3161), - RC(RC_GV_NOTE_NEAR_GRABBA_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -4116, 1780, -2895), - RC(RC_GV_NOTE_NEAR_GRABBA_9, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -4541, 1780, -2871), - RC(RC_GV_NOTE_NEAR_GRABBA_10, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -4958, 1781, -2855), - RC(RC_GV_NOTE_NEAR_GRABBA_11, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -5385, 1780, -2843), - RC(RC_GV_NOTE_NEAR_RUBEE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -685, 0, -743), - RC(RC_GV_NOTE_NEAR_RUBEE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -495, 0, -880), - RC(RC_GV_NOTE_NEAR_RUBEE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -913, 0, 428), - RC(RC_GV_NOTE_NEAR_RUBEE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -986, 0, 201), - RC(RC_GV_NOTE_NEAR_RUBEE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 496, 0, -878), - RC(RC_GV_NOTE_NEAR_RUBEE_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 679, 0, -744), - RC(RC_GV_NOTE_NEAR_RUBEE_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 915, 0, 421), - RC(RC_GV_NOTE_NEAR_RUBEE_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 988, 0, 195), - RC(RC_GV_NOTE_NEAR_TURBO_TRAINERS_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 2925, 3426, -6331), - RC(RC_GV_NOTE_NEAR_TURBO_TRAINERS_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 3522, 3403, -6008), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3165, 1378, 7933), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3720, 1390, 8460), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -4276, 1402, 8984), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -4829, 1415, 9510), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -5713, 1379, 9342), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -6046, 1329, 8619), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -6367, 1281, 7928), - RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -6724, 1233, 7210), - RC(RC_GV_NOTE_SPHYNX_FOOT_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -2776, 1606, 6486), - RC(RC_GV_NOTE_SPHYNX_FOOT_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3035, 1663, 6675), - RC(RC_GV_NOTE_SPHYNX_FOOT_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3048, 1665, 6316), - RC(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -2814, 1605, 5292), - RC(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3083, 1666, 5488), - RC(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3096, 1664, 5106), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3310, 0, -850), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -3317, 0, 748), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -1195, 1592, -50), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 95, 911, -50), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 1295, 274, -50), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 2249, 0, -829), - RC(RC_GV_NOTE_SPHYNX_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 2265, 0, 753), - RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -5, 13, -757), - RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -776, 13, -3), - RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -14, 13, 734), - RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 729, 13, -11), - RC(RC_GV_NOTE_WATER_PYRAMID_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -1168, 3324, -3242), - RC(RC_GV_NOTE_WATER_PYRAMID_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, 1214, 3821, -3576), - RC(RC_GV_NOTE_WATER_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -828, 3821, -3580), - RC(RC_GV_NOTE_WATER_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, ACTOR_51_MUSIC_NOTE, NULL, -489, 4316, -4946), - RC(RC_GV_SNS_BLUE_EGG, RCTYPE_STOP_N_SWOP, LEVEL_7_GOBIS_VALLEY, ACTOR_25E_SNS_EGG, SNS_ITEM_EGG_BLUE, 8, 470, -4141), - RC(RC_MM_EMPTY_HONEYCOMB_HILL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_1_MM_HILL, 985, 484, 1681), - RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), - RC(RC_MM_JIGGY_CHIMPY, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_9_MM_CHIMPY, 0, 0, 0), - RC(RC_MM_JIGGY_CONGA, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_A_MM_CONGA, 0, 0, 0), - RC(RC_MM_JIGGY_HILL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_07_MM_HILL, 4335, 1485, 794), - RC(RC_MM_JIGGY_HUTS, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_5_MM_HUTS, 0, 0, 0), - RC(RC_MM_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_01_MM_JINJO, 1702, -41, 2941), - RC(RC_MM_JIGGY_JUJU, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_4_MM_JUJU, 4309, 2374, -1487), - RC(RC_MM_JIGGY_MUMBOS_SKULL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_03_MM_MUMBOS_SKULL, 5580, 2756, -2708), - RC(RC_MM_JIGGY_ORANGE_PADS, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_8_MM_ORANGE_PADS, 0, 0, 0), - RC(RC_MM_JIGGY_RUINS, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_06_MM_RUINS, -3699, 2438, -2113), - RC(RC_MM_JIGGY_TICKERS_TOWER, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_46_JIGGY, JIGGY_02_MM_TICKERS_TOWER, 373, 4221, -906), - RC(RC_MM_JINJO_BLUE, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_60_JINJO_BLUE, NULL, 1702, -125, 2941), - RC(RC_MM_JINJO_GREEN, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_62_JINJO_GREEN, NULL, 0, 0, 0), - RC(RC_MM_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_5F_JINJO_ORANGE, NULL, -3297, 2755, -1421), - RC(RC_MM_JINJO_PINK, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_61_JINJO_PINK, NULL, 5876, 299, 2369), - RC(RC_MM_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_5E_JINJO_YELLOW, NULL, -4060, 1355, 1092), - RC(RC_MM_MOLEHILL_BEAK_BUSTER, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_2_BEAK_BUSTER, 3943, 2155, -3422), - RC(RC_MM_MOLEHILL_TALON_TROT, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_10_TALON_TROT, -2550, 2255, -1217), - RC(RC_MM_MOLEHILL_USE_EGGS, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_6_EGGS, -5926, 200, 6213), - RC(RC_MM_MUMBO_TOKEN_BEHIND_PINK_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_04_MM_BEHIND_PINK_JINJO, 5855, 0, 2169), - RC(RC_MM_MUMBO_TOKEN_BEHIND_RUINS, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_02_MM_BEHIND_RUINS, -4869, 2255, -2506), - RC(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_05_MM_INSIDE_TICKERS_TOWER, -343, 345, -518), - RC(RC_MM_MUMBO_TOKEN_STUMP_NEAR_CONGA, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA, -4431, 475, 6183), - RC(RC_MM_MUMBO_TOKEN_UNDER_RAMP_TO_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_03_MM_UNDER_RAMP_TO_MUMBOS_SKULL, 5150, 2168, -2447), - RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 4867, 297, 1766), - RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 4782, 298, 1892), - RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 4971, 299, 1887), - RC(RC_MM_NOTE_SOUTH_SLOPE_SECOND_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 6430, 500, 1410), - RC(RC_MM_NOTE_SOUTH_SLOPE_SECOND_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 6310, 500, 1536), - RC(RC_MM_NOTE_SOUTH_SLOPE_SECOND_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 6546, 500, 1536), - RC(RC_MM_NOTE_SOUTH_SLOPE_THIRD_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3793, 747, 1471), - RC(RC_MM_NOTE_SOUTH_SLOPE_THIRD_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3974, 747, 1411), - RC(RC_MM_NOTE_SOUTH_SLOPE_THIRD_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3928, 747, 1522), - RC(RC_MM_NOTE_SOUTH_SLOPE_FOURTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5259, 1184, 656), - RC(RC_MM_NOTE_SOUTH_SLOPE_FOURTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5469, 1184, 549), - RC(RC_MM_NOTE_SOUTH_SLOPE_FOURTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5412, 1184, 681), - RC(RC_MM_NOTE_SOUTH_SLOPE_FIFTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3202, 1247, 925), - RC(RC_MM_NOTE_SOUTH_SLOPE_FIFTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3126, 1247, 1014), - RC(RC_MM_NOTE_SOUTH_SLOPE_FIFTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3282, 1247, 1003), - RC(RC_MM_NOTE_SOUTH_SLOPE_SIXTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5860, 1547, 62), - RC(RC_MM_NOTE_SOUTH_SLOPE_SIXTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 6098, 1547, 67), - RC(RC_MM_NOTE_SOUTH_SLOPE_SIXTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5990, 1547, 169), - RC(RC_MM_NOTE_BRIDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 2585, -20, 3800), - RC(RC_MM_NOTE_BRIDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 2298, -65, 3800), - RC(RC_MM_NOTE_BRIDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 2012, -90, 3800), - RC(RC_MM_NOTE_BRIDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 1721, -90, 3800), - RC(RC_MM_NOTE_BRIDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 1441, -90, 3800), - RC(RC_MM_NOTE_BRIDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 1149, -62, 3800), - RC(RC_MM_NOTE_BRIDGE_7, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 854, -8, 3800), - RC(RC_MM_NOTE_NORTH_SLOPE_FIRST_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4497, 393, 2503), - RC(RC_MM_NOTE_NORTH_SLOPE_FIRST_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4583, 393, 2600), - RC(RC_MM_NOTE_NORTH_SLOPE_FIRST_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4417, 393, 2600), - RC(RC_MM_NOTE_NORTH_SLOPE_SECOND_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3730, 782, 1838), - RC(RC_MM_NOTE_NORTH_SLOPE_SECOND_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3776, 782, 1964), - RC(RC_MM_NOTE_NORTH_SLOPE_SECOND_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3624, 782, 1908), - RC(RC_MM_NOTE_NORTH_SLOPE_THIRD_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -5185, 837, 1737), - RC(RC_MM_NOTE_NORTH_SLOPE_THIRD_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -5277, 836, 1850), - RC(RC_MM_NOTE_NORTH_SLOPE_THIRD_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -5099, 836, 1850), - RC(RC_MM_NOTE_NORTH_SLOPE_FOURTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -2962, 1397, 813), - RC(RC_MM_NOTE_NORTH_SLOPE_FOURTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3053, 1397, 905), - RC(RC_MM_NOTE_NORTH_SLOPE_FOURTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -2868, 1397, 890), - RC(RC_MM_NOTE_NORTH_SLOPE_FIFTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -5154, 1489, 462), - RC(RC_MM_NOTE_NORTH_SLOPE_FIFTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -5238, 1489, 560), - RC(RC_MM_NOTE_NORTH_SLOPE_FIFTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -5068, 1489, 560), - RC(RC_MM_NOTE_NORTH_SLOPE_SIXTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4260, 1839, 208), - RC(RC_MM_NOTE_NORTH_SLOPE_SIXTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4342, 1839, 300), - RC(RC_MM_NOTE_NORTH_SLOPE_SIXTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4179, 1839, 300), - RC(RC_MM_NOTE_NORTH_SLOPE_SEVENTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3394, 1910, 171), - RC(RC_MM_NOTE_NORTH_SLOPE_SEVENTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3469, 1910, 263), - RC(RC_MM_NOTE_NORTH_SLOPE_SEVENTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3293, 1910, 247), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1373, 169, 1957), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1431, 346, 1784), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1497, 517, 1621), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1528, 638, 1424), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1523, 742, 1179), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1523, 857, 932), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_7, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1518, 964, 706), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_8, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1413, 1117, 500), - RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_9, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1284, 1295, 363), - RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1094, 1727, -1922), - RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1309, 1856, -1941), - RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1541, 1987, -1960), - RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -1758, 2111, -1974), - RC(RC_MM_NOTE_RUINS_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3047, 2755, -2669), - RC(RC_MM_NOTE_RUINS_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3314, 2755, -2802), - RC(RC_MM_NOTE_RUINS_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3603, 2755, -2923), - RC(RC_MM_NOTE_RUINS_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3885, 2755, -2901), - RC(RC_MM_NOTE_RUINS_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4161, 2755, -2858), - RC(RC_MM_NOTE_RUINS_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4359, 2755, -2682), - RC(RC_MM_NOTE_RUINS_7, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4542, 2755, -2495), - RC(RC_MM_NOTE_RUINS_8, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4599, 2754, -2261), - RC(RC_MM_NOTE_RUINS_9, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4649, 2755, -2009), - RC(RC_MM_NOTE_RUINS_10, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4539, 2755, -1746), - RC(RC_MM_NOTE_RUINS_11, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4416, 2755, -1509), - RC(RC_MM_NOTE_RUINS_12, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -4167, 2755, -1383), - RC(RC_MM_NOTE_RUINS_13, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3892, 2755, -1284), - RC(RC_MM_NOTE_RUINS_14, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3581, 2755, -1359), - RC(RC_MM_NOTE_UNDERWATER_RIGHT_CAVE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 2128, -824, 2181), - RC(RC_MM_NOTE_UNDERWATER_RIGHT_CAVE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 2034, -824, 2158), - RC(RC_MM_NOTE_UNDERWATER_RIGHT_CAVE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 1937, -824, 2136), - RC(RC_MM_NOTE_UNDERWATER_LEFT_CAVE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 1027, -824, 2183), - RC(RC_MM_NOTE_UNDERWATER_LEFT_CAVE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 940, -824, 2223), - RC(RC_MM_NOTE_UNDERWATER_LEFT_CAVE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 850, -824, 2267), - RC(RC_MM_NOTE_HUT_ROOF_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3378, 2439, -2353), - RC(RC_MM_NOTE_HUT_ROOF_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 4137, 2439, -2649), - RC(RC_MM_NOTE_HUT_ROOF_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5319, 2439, -1717), - RC(RC_MM_NOTE_HUT_ROOF_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 5025, 2439, -814), - RC(RC_MM_NOTE_HUT_ROOF_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3847, 2439, -715), - RC(RC_MM_NOTE_HUT_ROOF_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 3255, 2438, -1091), - RC(RC_MM_NOTE_HUT_BUNDLE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_MM_NOTE_HUT_BUNDLE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_MM_NOTE_HUT_BUNDLE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_MM_NOTE_HUT_BUNDLE_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_MM_NOTE_HUT_BUNDLE_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 0), - RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -288, 0, -154), - RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -127, 0, -308), - RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 119, 0, -298), - RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 286, 0, -155), - RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -74, 817, 19), - RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -3, 817, 52), - RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 67, 817, 0), - RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, 60, 817, -87), - RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -10, 817, -125), - RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, ACTOR_51_MUSIC_NOTE, NULL, -80, 817, -71), - RC(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_12_MMM_FLOORBOARD, -51, -135, 52), - RC(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_11_MMM_CHURCH_RAFTERS, 0, 5163, 2400), - RC(RC_MMM_JIGGY_BARREL_INTERIOR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_61_MMM_RAIN_BARREL, 2, 288, -4), - RC(RC_MMM_JIGGY_CELLAR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_5E_MMM_CELLAR, -516, 30, 477), - RC(RC_MMM_JIGGY_CEMETARY_POTS, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_63_MMM_FLOWER_POTS, 0, 0, 0), - RC(RC_MMM_JIGGY_CLOCKTOWER_TOP, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_5F_MMM_CHURCH_ROOF, -2800, 3175, -1601), - RC(RC_MMM_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_5B_MMM_JINJO, 0, 0, 0), - RC(RC_MMM_JIGGY_MANSION_TABLE, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_5D_MMM_NAPPER, 1, 511, 24), - RC(RC_MMM_JIGGY_MOTZAND, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_60_MMM_MOTZHAND, 0, 3050, -3200), - RC(RC_MMM_JIGGY_INSIDE_LOGGO, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_64_MMM_LOGGO, -518, 295, -468), - RC(RC_MMM_JIGGY_INSIDE_THE_WELLS_BUCKET, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_5C_MMM_WELL, 1, 179, 0), - RC(RC_MMM_JIGGY_TUMBLARS_PUZZLE, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_46_JIGGY, JIGGY_62_MMM_TUMBLAR, 48, 0, -58), - RC(RC_MMM_JINJO_BLUE, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_60_JINJO_BLUE, NULL, 5900, 300, 1050), - RC(RC_MMM_JINJO_GREEN, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_62_JINJO_GREEN, NULL, 1437, 2100, 248), - RC(RC_MMM_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_5F_JINJO_ORANGE, NULL, -4265, 0, 2668), - RC(RC_MMM_JINJO_PINK, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_61_JINJO_PINK, NULL, 511, 38, 203), - RC(RC_MMM_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_5E_JINJO_YELLOW, NULL, -250, 540, 300), - RC(RC_MMM_MUMBO_TOKEN_ALCOVE_CLOCK_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_35_MMM_ALCOVE_CLOCK_TOWER, -2800, 1475, -1363), - RC(RC_MMM_MUMBO_TOKEN_BEHIND_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_38_MMM_BEHIND_CHURCH, -4700, 175, -5149), - RC(RC_MMM_MUMBO_TOKEN_HIDDEN_NEAR_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_33_MMM_HIDDEN_NEAR_FOUNTAIN, 3950, -175, 325), - RC(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_3E_MMM_IN_CHIMNEY_INSIDE_DINNING_ROOM, -160, 190, -2599), - RC(RC_MMM_MUMBO_TOKEN_IN_THE_MAZE, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_37_MMM_IN_THE_MAZE, -4250, 0, 352), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_40_MMM_INSIDE_BEDROOM, 696, 0, -397), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_LOGGO, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, RP_MUMBO_TOKEN_INSIDE_LOGGO, 424, 170, 304), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_3D_MMM_INSIDE_LOGGO_AND_INSIDE_BARREL_IN_CELLAR, -507, 30, 199), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_WELL, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_3F_MMM_INSIDE_WELL, -732, 0, -109), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_WHIPCRACK_IN_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_39_MMM_INSIDE_WHIPCRACK_IN_FOUNTAIN, 5900, -275, 798), - RC(RC_MMM_MUMBO_TOKEN_NEAR_FRONT_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_34_MMM_NEAR_FRONT_TUMBLARS_SHED, 173, 350, -3610), - RC(RC_MMM_MUMBO_TOKEN_NEXT_TO_MAZE_HEDGE_RAMP, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_36_MMM_NEXT_TO_MAZE_HEDGE_RAMP, -1643, 25, -1026), - RC(RC_MMM_MUMBO_TOKEN_IN_LOGGOS_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_41_MMM_SINK_IN_LOGGOS_ROOM, 52, 104, 512), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_3A_MMM_TOP_OF_RAFTER_INSIDE_CHURCH, 0, 4806, 341), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_3B_MMM_TOP_OF_STOOL_INSIDE_CHURCH, 0, 583, -1300), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_3C_MMM_TOP_OF_TUMBLARS_SHED, 1796, 857, -4243), - RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 7150, -275, -3474), - RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 7150, -275, -3325), - RC(RC_MMM_NOTE_AROUND_THE_WELL_EAST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 4200, -275, -3325), - RC(RC_MMM_NOTE_AROUND_THE_WELL_EAST_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 4201, -275, -3475), - RC(RC_MMM_NOTE_BARREL_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -266, 0, 152), - RC(RC_MMM_NOTE_BARREL_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -267, 0, -153), - RC(RC_MMM_NOTE_BARREL_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, -310), - RC(RC_MMM_NOTE_BARREL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 270, 0, -154), - RC(RC_MMM_NOTE_BARREL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 268, 0, 152), - RC(RC_MMM_NOTE_BASEMENT_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -375, 300, 1274), - RC(RC_MMM_NOTE_BASEMENT_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -126, 300, 1275), - RC(RC_MMM_NOTE_BASEMENT_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 125, 300, 1275), - RC(RC_MMM_NOTE_BASEMENT_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 375, 300, 1275), - RC(RC_MMM_NOTE_BEDROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 760, 207, -100), - RC(RC_MMM_NOTE_BEDROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 700, 207, -200), - RC(RC_MMM_NOTE_BEDROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 640, 200, -100), - RC(RC_MMM_NOTE_BEDROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 700, 207, 0), - RC(RC_MMM_NOTE_CHAIR_EAST_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 736, 286, -500), - RC(RC_MMM_NOTE_CHAIR_EAST_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 737, 286, 0), - RC(RC_MMM_NOTE_CHAIR_EAST_SIDE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 736, 286, 499), - RC(RC_MMM_NOTE_CHAIR_NORTH_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 11, 286, -1102), - RC(RC_MMM_NOTE_CHAIR_NORTH_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -13, 286, -1751), - RC(RC_MMM_NOTE_CHAIR_WEST_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -738, 286, 499), - RC(RC_MMM_NOTE_CHAIR_WEST_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -737, 286, -1), - RC(RC_MMM_NOTE_CHAIR_WEST_SIDE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -738, 286, -499), - RC(RC_MMM_NOTE_CHURCH_ABOVE_THE_ENTRANCE, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2186, 662, -2498), - RC(RC_MMM_NOTE_CHURCH_PEW_NORTHEAST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1625, 690, 816), - RC(RC_MMM_NOTE_CHURCH_PEW_NORTHWEST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -1625, 690, 820), - RC(RC_MMM_NOTE_CHURCH_PEW_SOUTHEAST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1623, 690, 2371), - RC(RC_MMM_NOTE_CHURCH_PEW_SOUTHWEST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -1623, 690, 2373), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2800, 1063, -2135), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2800, 1063, -2500), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2800, 1063, -2900), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2800, 1063, -3301), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2800, 1063, -3699), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3199, 1060, -2900), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3600, 1057, -2900), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_8, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -4000, 1054, -2900), - RC(RC_MMM_NOTE_CHURCH_ROOFTOP_9, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -4400, 1051, -2900), - RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3148, 2075, -1948), - RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3146, 2075, -1253), - RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2452, 2075, -1948), - RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2453, 2075, -1253), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -450, 0, -75), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -438, 195, -336), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -450, 0, 0), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -450, 0, 75), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -440, 150, 337), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -75, 0, 350), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 429, 222, -233), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_8, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 0, 0, 350), - RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_9, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 75, 0, 350), - RC(RC_MMM_NOTE_GRASS_BEHIND_THE_MANSION_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -200, 225, -3525), - RC(RC_MMM_NOTE_GRASS_BEHIND_THE_MANSION_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -201, 225, -3700), - RC(RC_MMM_NOTE_GRASS_BEHIND_THE_MANSION_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -200, 225, -3876), - RC(RC_MMM_NOTE_MAIN_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 556, 75, 2111), - RC(RC_MMM_NOTE_MAIN_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 734, 75, 2236), - RC(RC_MMM_NOTE_MAIN_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1266, 75, 2236), - RC(RC_MMM_NOTE_MAIN_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1444, 75, 2110), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_NORTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 2436, 700, -1244), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_NORTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -428, 700, -1249), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_SOUTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 2436, 702, 1743), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_SOUTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -428, 700, 1743), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_NORTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1936, 1600, -797), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_NORTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 63, 1600, -796), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_SOUTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1936, 1600, 1294), - RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_SOUTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 63, 1600, 1303), - RC(RC_MMM_NOTE_MAZE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2050, 7, 1755), - RC(RC_MMM_NOTE_MAZE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -2250, 0, 2655), - RC(RC_MMM_NOTE_MAZE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3455, 0, 1780), - RC(RC_MMM_NOTE_MAZE_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3455, 0, 1445), - RC(RC_MMM_NOTE_MAZE_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3300, 0, 25), - RC(RC_MMM_NOTE_MAZE_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -3300, 0, -131), - RC(RC_MMM_NOTE_MUMBOS_SKULL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -293, 0, -157), - RC(RC_MMM_NOTE_MUMBOS_SKULL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 294, 0, -157), - RC(RC_MMM_NOTE_ORGAN_PEDALS_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 150, 131, -1698), - RC(RC_MMM_NOTE_ORGAN_PEDALS_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -150, 230, -1693), - RC(RC_MMM_NOTE_ORGAN_PIPES_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -1062, 2450, -3199), - RC(RC_MMM_NOTE_ORGAN_PIPES_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -529, 2750, -3200), - RC(RC_MMM_NOTE_ORGAN_PIPES_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 519, 2750, -3200), - RC(RC_MMM_NOTE_ORGAN_PIPES_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1054, 2450, -3199), - RC(RC_MMM_NOTE_SHED_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -700, 0, 688), - RC(RC_MMM_NOTE_SHED_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -701, 0, -725), - RC(RC_MMM_NOTE_SHED_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 700, 0, -725), - RC(RC_MMM_NOTE_SHED_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 700, 0, 688), - RC(RC_MMM_NOTE_SHED_ROOF_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1575, 988, -4460), - RC(RC_MMM_NOTE_SHED_ROOF_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 1824, 987, -4460), - RC(RC_MMM_NOTE_SHED_ROOF_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 2075, 988, -4460), - RC(RC_MMM_NOTE_SHED_ROOF_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 2325, 988, -4460), - RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 5378, -75, 521), - RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 6428, -75, 529), - RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 6423, -75, 1579), - RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 5372, -75, 1571), - RC(RC_MMM_NOTE_WELL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -475, 0, -617), - RC(RC_MMM_NOTE_WELL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -613, 0, 411), - RC(RC_MMM_NOTE_WELL_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -714, 0, 171), - RC(RC_MMM_NOTE_WELL_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, -217, 0, 131), - RC(RC_MMM_NOTE_WELL_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 694, 0, -186), - RC(RC_MMM_NOTE_WELL_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 79, 0, -201), - RC(RC_MMM_NOTE_WELL_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_51_MUSIC_NOTE, NULL, 681, 0, 182), - RC(RC_MMM_SNS_CYAN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_25E_SNS_EGG, SNS_ITEM_EGG_CYAN, 1995, 100, -476), - RC(RC_MMM_SNS_GREEN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, ACTOR_25E_SNS_EGG, SNS_ITEM_EGG_GREEN, 517, 350, -241), - RC(RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_F_RBB_BOAT_HOUSE, 0, 1000, 0), - RC(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_10_RBB_ENGINE_ROOM, 0, 360, 3541), - RC(RC_RBB_JIGGY_BOSS_BOOM_BOX, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_56_RBB_BOSS_BOOM_BOX, 0, 0, 0), - RC(RC_RBB_JIGGY_CAPTAINS_CABIN, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_58_RBB_CAPTAINS_CABIN, -997, 273, 355), - RC(RC_RBB_JIGGY_CRANE_CAGE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_59_RBB_CRANE_CAGE, -4900, 0, 0), - RC(RC_RBB_JIGGY_ENGINE_ROOM, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_5A_RBB_ENGINE_ROOM, 1, 809, -3718), - RC(RC_RBB_JIGGY_FUNNEL, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_55_RBB_FUNNEL, -2006, 2700, -2), - RC(RC_RBB_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_51_RBB_JINJO, 0, 0, 0 ), - RC(RC_RBB_JIGGY_PROPELLOR, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_57_RBB_PROPELLOR, 7750, -2007, 0), - RC(RC_RBB_JIGGY_SNORKEL, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_53_RBB_SNORKEL, 0, 0, 0), - RC(RC_RBB_JIGGY_WAREHOUSE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_52_RBB_WAREHOUSE, 850, 850, -1150), - RC(RC_RBB_JIGGY_WHISTLE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_46_JIGGY, JIGGY_54_RBB_WHISTLE, 0, 0, 0), - RC(RC_RBB_JINJO_BLUE, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_60_JINJO_BLUE, NULL, -8738, -1253, 4032), - RC(RC_RBB_JINJO_GREEN, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_62_JINJO_GREEN, NULL, 8903, -800, -2894), - RC(RC_RBB_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_5F_JINJO_ORANGE, NULL, -193, 0, -979), - RC(RC_RBB_JINJO_PINK, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_61_JINJO_PINK, NULL, 7850, -2613, 4026), - RC(RC_RBB_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_5E_JINJO_YELLOW, NULL, -8615, -1000, -3555), - RC(RC_RBB_MUMBO_TOKEN_TOXIC_WASTE_POND, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_46_RBB_TOXIC_WASTE_POND, -7401, -1000, -3425), - RC(RC_RBB_MUMBO_TOKEN_ON_LIFE_BOAT, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_44_RBB_ON_LIFE_BOAT, 7053, -985, -1672), - RC(RC_RBB_MUMBO_TOKEN_SHIPS_PROW, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_43_RBB_SHIPS_PROW, -6200, 150, 0), - RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_47_RBB_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, 6200, 400, 0), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_SHIPS_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_42_RBB_TOP_OF_SHIPS_CHIMNEY, 1000, 2750, 0), - RC(RC_RBB_MUMBO_TOKEN_FRONT_OF_CHOMPA_LEFT_OF_SHIP, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_45_RBB_FRONT_OF_CHOMPA_LEFT_OF_SHIP, -3299, -457, 3800), - RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_48_RBB_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, -650, 562, -35), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_49_RBB_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, -278, 710, -557), - RC(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_4C_RBB_INSIDE_KITCHEN, -771, 238, -293), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BUNK_IN_CABIN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_4A_RBB_TOP_OF_BUNK_IN_CABIN, 583, 323, -70), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_50_RBB_TOP_OF_BOX_INSIDE_TNT_ROOM, -435, 300, -435), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_4D_RBB_ENGINE_ROOM_LEFT_PIPE, -2450, 1100, -400), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_4E_RBB_ENGINE_ROOM_RIGHT_PIPE, 2450, 1100, -400), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_SPINNING_PLATFORM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_4F_RBB_ENGINE_ROOM_SPINNING_PLATFORM, -319, 12, 1899), - RC(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_4B_RBB_INSIDE_NAVIGATION_ROOM, -656, 0, -222), - RC(RC_RBB_NOTE_ANCHOR_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 3500, 449, -501), - RC(RC_RBB_NOTE_ANCHOR_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 3499, 449, 499), - RC(RC_RBB_NOTE_ANCHOR_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 4499, 449, -500), - RC(RC_RBB_NOTE_ANCHOR_ROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 4500, 449, 499), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -50, 43, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -384, 164, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -717, 285, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1050, 406, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -950, 1200, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -650, 1200, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -350, 1200, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -50, 1200, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -50, 2207, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -350, 2207, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -650, 2207, 0), - RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -950, 2207, 0), - RC(RC_RBB_NOTE_BUNK_CABIN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -271, 0, -496), - RC(RC_RBB_NOTE_BUNK_CABIN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -245, 0, 563), - RC(RC_RBB_NOTE_BUNK_CABIN_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 270, 0, -496), - RC(RC_RBB_NOTE_BUNK_CABIN_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 245, 0, 561), - RC(RC_RBB_NOTE_CAPTAINS_CABIN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1020, 0, -315), - RC(RC_RBB_NOTE_CAPTAINS_CABIN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1020, 0, -103), - RC(RC_RBB_NOTE_CAPTAINS_CABIN_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1020, 0, 108), - RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -3039, 1160, -2485), - RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -3370, 1160, -2484), - RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -3038, 1160, -2817), - RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -3374, 1160, -2817), - RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1499, 809, -199), - RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1700, 809, -200), - RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1700, 809, -600), - RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -1499, 809, -601), - RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -200, 809, -2200), - RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -200, 809, -2600), - RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 200, 809, -2600), - RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 200, 809, -2200), - RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 1500, 809, -199), - RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 1700, 809, -199), - RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 1700, 809, -600), - RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 1501, 809, -600), - RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -6755, -800, 2797), - RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -6755, -800, 2150), - RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -6755, -800, 1554), - RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -7128, -800, 1554), - RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -7501, -800, 1554), - RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 6950, -1175, 3050), - RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 6950, -1175, 4050), - RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 8750, -1175, 4050), - RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 8750, -1175, 3050), - RC(RC_RBB_NOTE_JIGGY_CRANE_BASE_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -5199, -200, -2900), - RC(RC_RBB_NOTE_JIGGY_CRANE_BASE_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -4900, -200, -2900), - RC(RC_RBB_NOTE_JIGGY_CRANE_BASE_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -4600, -200, -2900), - RC(RC_RBB_NOTE_KITCHEN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -313, 213, -1046), - RC(RC_RBB_NOTE_KITCHEN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -400, 163, 738), - RC(RC_RBB_NOTE_KITCHEN_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -398, 163, 149), - RC(RC_RBB_NOTE_KITCHEN_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 593, 213, -898), - RC(RC_RBB_NOTE_KITCHEN_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 389, 163, 740), - RC(RC_RBB_NOTE_NAVIGATION_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -270, 0, -719), - RC(RC_RBB_NOTE_NAVIGATION_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -87, 0, -720), - RC(RC_RBB_NOTE_NAVIGATION_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 96, 0, -720), - RC(RC_RBB_NOTE_NAVIGATION_ROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 279, 0, -719), - RC(RC_RBB_NOTE_RAMP_TO_SHIP_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 800, -760, 2751), - RC(RC_RBB_NOTE_RAMP_TO_SHIP_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 800, -667, 2424), - RC(RC_RBB_NOTE_RAMP_TO_SHIP_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 800, -575, 2102), - RC(RC_RBB_NOTE_RAMP_TO_SHIP_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 800, -482, 1775), - RC(RC_RBB_NOTE_RAMP_TO_SHIP_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 800, -389, 1450), - RC(RC_RBB_NOTE_SHIP_BOW_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 7800, -800, -1325), - RC(RC_RBB_NOTE_SHIP_BOW_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 8050, -800, -1001), - RC(RC_RBB_NOTE_SHIP_BOW_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 8149, -799, 300), - RC(RC_RBB_NOTE_SHIP_BOW_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 8149, -799, -300), - RC(RC_RBB_NOTE_SHIP_BOW_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 8050, -800, 1001), - RC(RC_RBB_NOTE_SHIP_BOW_6, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 7800, -800, 1325), - RC(RC_RBB_NOTE_SHIP_STERN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -3399, 800, -600), - RC(RC_RBB_NOTE_SHIP_STERN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -3399, 800, 600), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -650, 560, -645), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -630, 175, -419), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -170, 140, -804), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -650, 560, 560), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -236, 105, 316), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_6, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 0, 595, -860), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_7, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 492, 525, -677), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_8, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 593, 105, -105), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 531, 140, 664), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 659, 140, 665), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 530, 140, 520), - RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 660, 140, 519), - RC(RC_RBB_NOTE_TNT_CRANE_BASE_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 4500, -200, -2900), - RC(RC_RBB_NOTE_TNT_CRANE_BASE_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 4200, -200, -2900), - RC(RC_RBB_NOTE_TNT_CRANE_BASE_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 3900, -200, -2900), - RC(RC_RBB_NOTE_TNT_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -400, 750, 924), - RC(RC_RBB_NOTE_TNT_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -400, 750, 800), - RC(RC_RBB_NOTE_TNT_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -400, 750, 675), - RC(RC_RBB_NOTE_TNT_ROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -400, 750, 550), - RC(RC_RBB_NOTE_TNT_ROOM_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -400, 750, 1050), - RC(RC_RBB_NOTE_TOXIC_WASTE_POND_BARREL_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -8144, -969, -2026), - RC(RC_RBB_NOTE_TOXIC_WASTE_POND_BARREL_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -7679, -986, -2363), - RC(RC_RBB_NOTE_TOXIC_WASTE_POND_BARREL_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, -7843, -986, -3205), - RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 785, 650, 1356), - RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 785, 650, 1045), - RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 1005, 650, 1355), - RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_51_MUSIC_NOTE, NULL, 1005, 650, 1045), - RC(RC_RBB_SNS_RED_EGG, RCTYPE_STOP_N_SWOP, LEVEL_9_RUSTY_BUCKET_BAY, ACTOR_25E_SNS_EGG, SNS_ITEM_EGG_RED, -7, 113, 164), - RC(RC_SM_EMPTY_HONEYCOMB_COLLIWOBBLE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_17_SM_COLLIWOBBLE, 0, 0, 0), - RC(RC_SM_EMPTY_HONEYCOMB_QUARRIES, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_18_SM_QUARRIES, 0, 0, 0), - RC(RC_SM_EMPTY_HONEYCOMB_STUMP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_13_SM_STUMP, -1400, 99, 4824), - RC(RC_SM_EMPTY_HONEYCOMB_TREE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_16_SM_TREE, -2752, 1299, 37), - RC(RC_SM_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_15_SM_UNDERWATER, -264, -442, -651), - RC(RC_SM_EMPTY_HONEYCOMB_WATERFALL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_14_SM_WATERFALL, -6725, 1300, -1803), - RC(RC_SM_MOLEHILL_ATTACK, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_4_CLAW_SWIPE, 4675, 400, 511), - RC(RC_SM_MOLEHILL_BEAK_BARGE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_0_BARGE, 3271, -110, -2673), - RC(RC_SM_MOLEHILL_CAMERA_CONTROL, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_3_CAMERA_CONTROL, 2250, -34, 2774 ), - RC(RC_SM_MOLEHILL_CLIMB, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_5_CLIMB, -1999, 342, -2545), - RC(RC_SM_MOLEHILL_DIVE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_F_DIVE, -2336, 302, 973), - RC(RC_SM_MOLEHILL_JUMP, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, ACTOR_12C_MOLEHILL, ABILITY_8_FLAP_FLIP, -164, -190, 3313), - RC(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_4_TTC_FLOATING_BOX, 8473, 844, -2684), - RC(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_47_EMPTY_HONEYCOMB, HONEYCOMB_3_TTC_UNDERWATER, -4303, 46, 115), - RC(RC_TTC_JIGGY_ALCOVE1, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_0D_TTC_ALCOVE_1, 2832, 2152, -1797), - RC(RC_TTC_JIGGY_ALCOVE2, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_0E_TTC_ALCOVE_2, -5116, 1417, -3915), - RC(RC_TTC_JIGGY_BLUBBER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_14_TTC_BLUBBER, 0, 0, 0), - RC(RC_TTC_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_0B_TTC_JINJO, 0, 0, 0), - RC(RC_TTC_JIGGY_LIGHTHOUSE, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_0C_TTC_LIGHTHOUSE, 479, 8500, -2709), - RC(RC_TTC_JIGGY_LOCKUP, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_13_TTC_LOCKUP, -1575, 2597, -2500), - RC(RC_TTC_JIGGY_NIPPER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_12_TTC_NIPPER, 385, 227, 31), - RC(RC_TTC_JIGGY_POOL, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_0F_TTC_POOL, -2760, 2053, -4733), - RC(RC_TTC_JIGGY_RED_X, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_11_TTC_RED_X, 0, 0, 0), - RC(RC_TTC_JIGGY_SANDCASTLE, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_46_JIGGY, JIGGY_10_TTC_SANDCASTLE, 0, 350, -987), - RC(RC_TTC_JINJO_BLUE, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_60_JINJO_BLUE, NULL, -875, 242, 7206), - RC(RC_TTC_JINJO_GREEN, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_62_JINJO_GREEN, NULL, -179, 3062, 889), - RC(RC_TTC_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_5F_JINJO_ORANGE, NULL, -5626, 3112, -2856), - RC(RC_TTC_JINJO_PINK, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_61_JINJO_PINK, NULL, 4848, 1340, -240), - RC(RC_TTC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_5E_JINJO_YELLOW, NULL, -968, 5358, -776), - RC(RC_TTC_MOLEHILL_FLIGHT, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_12C_MOLEHILL, ABILITY_9_FLIGHT, -288, 2161, 1314), - RC(RC_TTC_MOLEHILL_SHOCK_JUMP, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_12C_MOLEHILL, ABILITY_D_SHOCK_JUMP, 2698, 1517, 3338), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_PILLAR_UNDERWATER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_0C_TTC_BEHIND_PILLAR_UNDERWATER, 6480, 597, -258), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_0A_TTC_BEHIND_LIGHTHOUSE_DOOR, 565, 6917, -2776), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_NIPPER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_0F_TTC_BEHIND_NIPPER, -6620, 510, 4621), - RC(RC_TTC_MUMBO_TOKEN_FLOATING_ABOVE_SHOCKJUMP_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_0E_TTC_FLOATING_ABOVE_SHOCKJUMP_PAD, 2462, 2217, 2957), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_1, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_07_TTC_INSIDE_LOCKUP_1, -2660, 2447, -6079), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_2, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_08_TTC_INSIDE_LOCKUP_2, -2646, 2447, -6223), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_SALTY_HIPPO, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_06_TTC_INSIDE_SALTY_HIPPO, 610, -412, 31), - RC(RC_TTC_MUMBO_TOKEN_ON_FLOATING_BOX, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_0B_TTC_ON_FLOATING_BOX, -783, 745, -3872), - RC(RC_TTC_MUMBO_TOKEN_POND_BOTTOM, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_0D_TTC_POND_BOTTOM, -4932, 1122, -1063), - RC(RC_TTC_MUMBO_TOKEN_SALTY_HIPPO_MAST, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_2D_MUMBO_TOKEN, MUMBOTOKEN_09_TTC_SALTY_HIPPO_MAST, -221, 2029, 929), - RC(RC_TTC_NOTE_BEACH_LOCKUP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4802, 737, -2351), - RC(RC_TTC_NOTE_BEACH_LOCKUP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4730, 737, -2420), - RC(RC_TTC_NOTE_BEACH_LOCKUP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4803, 736, -2444), - RC(RC_TTC_NOTE_BEACH_LOCKUP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4858, 736, -2273), - RC(RC_TTC_NOTE_BEACH_LOCKUP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4783, 737, -2249), - RC(RC_TTC_NOTE_INSIDE_NIPPER_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -127, -22, -1020), - RC(RC_TTC_NOTE_INSIDE_NIPPER_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 643, -22, -723), - RC(RC_TTC_NOTE_INSIDE_NIPPER_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 911, -22, -18), - RC(RC_TTC_NOTE_INSIDE_NIPPER_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 583, -21, 625), - RC(RC_TTC_NOTE_INSIDE_NIPPER_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -78, -21, 800), - RC(RC_TTC_NOTE_INSIDE_NIPPER_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -608, -21, 457), - RC(RC_TTC_NOTE_INSIDE_SHIP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -870, -750, -60), - RC(RC_TTC_NOTE_INSIDE_SHIP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -870, -750, -195), - RC(RC_TTC_NOTE_INSIDE_SHIP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -871, -750, 198), - RC(RC_TTC_NOTE_INSIDE_SHIP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -871, -750, 68), - RC(RC_TTC_NOTE_INSIDE_SHIP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 870, -750, -64), - RC(RC_TTC_NOTE_INSIDE_SHIP_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 870, -746, -197), - RC(RC_TTC_NOTE_INSIDE_SHIP_7, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 870, -698, 200), - RC(RC_TTC_NOTE_INSIDE_SHIP_8, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 870, -750, 61), - RC(RC_TTC_NOTE_JUMP_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2911, 1667, 1203), - RC(RC_TTC_NOTE_JUMP_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2911, 1792, 1203), - RC(RC_TTC_NOTE_JUMP_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2911, 1917, 1203), - RC(RC_TTC_NOTE_LIGHTHOUSE_PATH_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -363, 6087, -2487), - RC(RC_TTC_NOTE_LIGHTHOUSE_PATH_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -455, 6170, -2688), - RC(RC_TTC_NOTE_LIGHTHOUSE_PATH_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -352, 6227, -2895), - RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 563, 8055, -2949), - RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 731, 8056, -2702), - RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 552, 8056, -2465), - RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 269, 8070, -2560), - RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 275, 8055, -2864), - RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 5447, 1817, 101), - RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 5682, 1817, 444), - RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 6246, 1817, 447), - RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 6244, 1817, -452), - RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 6498, 1817, 39), - RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 5670, 1817, -372), - RC(RC_TTC_NOTE_SANDCASTLE_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2497, 431, 4437), - RC(RC_TTC_NOTE_SANDCASTLE_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2318, 431, 4609), - RC(RC_TTC_NOTE_SANDCASTLE_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2497, 431, 4609), - RC(RC_TTC_NOTE_SANDCASTLE_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2660, 431, 4609), - RC(RC_TTC_NOTE_SANDCASTLE_TOP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2497, 431, 4794), - RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -536, -90, 727), - RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -536, -90, 892), - RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 537, -90, 727), - RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 537, -90, 892), - RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1364, 1084, 622), - RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1213, 1276, 665), - RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1055, 1490, 713), - RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -896, 1703, 753), - RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -734, 1915, 773), - RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -569, 2131, 795), - RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 966, 1289, 1138), - RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 788, 1486, 1082), - RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 603, 1702, 1027), - RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 414, 1916, 1000), - RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 222, 2132, 979), - RC(RC_TTC_NOTE_SHIP_TREE_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1630, 1291, 2476), - RC(RC_TTC_NOTE_SHIP_TREE_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1539, 1291, 2621), - RC(RC_TTC_NOTE_SHIP_TREE_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1681, 1318, 2708), - RC(RC_TTC_NOTE_SHIP_TREE_LEFT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1769, 1321, 2578), - RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 417, 1291, 2891), - RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 448, 1318, 3052), - RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 297, 1321, 3090), - RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 251, 1292, 2927), - RC(RC_TTC_NOTE_SPIRAL_PATH_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4656, 817, -6660), - RC(RC_TTC_NOTE_SPIRAL_PATH_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4646, 817, -6864), - RC(RC_TTC_NOTE_SPIRAL_PATH_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4631, 817, -7067), - RC(RC_TTC_NOTE_SPIRAL_PATH_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 4499, 817, -7216), - RC(RC_TTC_NOTE_STAIRS_TO_LIGHTHOUSE, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 2070, 2517, -2499), - RC(RC_TTC_NOTE_STAIRSET_FIRST_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 266, 911, -6564), - RC(RC_TTC_NOTE_STAIRSET_FIRST_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 86, 1117, -6563), - RC(RC_TTC_NOTE_STAIRSET_FIRST_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -85, 1313, -6564), - RC(RC_TTC_NOTE_STAIRSET_FIRST_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -263, 1516, -6564), - RC(RC_TTC_NOTE_STAIRSET_SECOND_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -653, 1713, -6370), - RC(RC_TTC_NOTE_STAIRSET_SECOND_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -826, 1913, -6343), - RC(RC_TTC_NOTE_STAIRSET_SECOND_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1001, 2116, -6315), - RC(RC_TTC_NOTE_STAIRSET_SECOND_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1175, 2317, -6288), - RC(RC_TTC_NOTE_STAIRSET_THIRD_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1936, 2528, -6112), - RC(RC_TTC_NOTE_STAIRSET_THIRD_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1854, 2731, -5955), - RC(RC_TTC_NOTE_STAIRSET_THIRD_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1773, 2928, -5803), - RC(RC_TTC_NOTE_STAIRSET_THIRD_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1691, 3130, -5647), - RC(RC_TTC_NOTE_STARTING_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1144, 846, 7476), - RC(RC_TTC_NOTE_STARTING_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -1147, 846, 6935), - RC(RC_TTC_NOTE_STARTING_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -603, 846, 6938), - RC(RC_TTC_NOTE_STARTING_PLATFORM_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -603, 846, 7478), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 688, 1617, 4709), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 700, 1617, 4907), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, 713, 1617, 5104), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2607, 1617, 3019), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2548, 1617, 3217), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2488, 1617, 3417), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_7, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -719, 1617, 4183), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_8, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -520, 1617, 4172), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_9, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -319, 1617, 4160), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_10, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2515, 1617, 4735), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_11, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2638, 1617, 4933), - RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_12, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2760, 1617, 5135), - RC(RC_TTC_NOTE_UPPERLEVEL_POOL_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -3235, 1840, -1696), - RC(RC_TTC_NOTE_UPPERLEVEL_POOL_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -3001, 1840, -2007), - RC(RC_TTC_NOTE_UPPERLEVEL_POOL_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_51_MUSIC_NOTE, NULL, -2906, 1840, -2329), - RC(RC_TTC_SNS_PINK_EGG, RCTYPE_STOP_N_SWOP, LEVEL_2_TREASURE_TROVE_COVE, ACTOR_25E_SNS_EGG, SNS_ITEM_EGG_PINK, 0, 1950, 0), + RC(RC_UNKNOWN, RCTYPE_UNKNOWN, LEVEL_D_CUTSCENE, RI_UNKNOWN, NULL, 0, 0, 0), + RC(RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_7_BGS_MUMBOS, 0, 600, 0), + RC(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_8_BGS_TANKTUP, 0, 537, -1157), + RC(RC_BGS_JIGGY_CROCTUS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_22_CROCTUS, 0, 0, 0), + RC(RC_BGS_JIGGY_ELEVATED_WALKWAY, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_20_BGS_ELEVATED_WALKWAY, 0, 0, 0), + RC(RC_BGS_JIGGY_FLIBBITS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_24_BGS_FLIBBITS, 0, 0, 0), + RC(RC_BGS_JIGGY_HUTS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_23_BGS_HUTS, 0, 0, 0), + RC(RC_BGS_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_1F_BGS_JINGO, 0, 0, 0), + RC(RC_BGS_JIGGY_MAZE, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_25_BGS_MAZE, 0, 0, 0), + RC(RC_BGS_JIGGY_MR_VILE, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_28_BGS_MR_VILE, 0, 0, 0), + RC(RC_BGS_JIGGY_PINKEGG, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_21_BGS_PINKEGG, 0, 0, 0), + RC(RC_BGS_JIGGY_TANKTUP, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_26_BGS_TANKTUP, 0, 0, 0), + RC(RC_BGS_JIGGY_TIPTUP, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_27_BGS_TIPTUP, 0, 0, 0), + RC(RC_BGS_JINJO_BLUE, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_BLUE_BUBBLEGLOOP_SWAMP, NULL, -3061, 1146, -10052), + RC(RC_BGS_JINJO_GREEN, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_GREEN_BUBBLEGLOOP_SWAMP, NULL, 1650, 1600, 1988), + RC(RC_BGS_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_ORANGE_BUBBLEGLOOP_SWAMP, NULL, 5472, 0, 2853), + RC(RC_BGS_JINJO_PINK, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, NULL, 5670, 0, -4158), + RC(RC_BGS_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, NULL, -1606, 500, 2797), + RC(RC_BGS_MOLEHILL_WADING_BOOTS, RCTYPE_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MOLEHILL_WADING_BOOTS, ABILITY_E_WADING_BOOTS, 4297, 100, 6286), + RC(RC_BGS_MUMBO_TOKEN_ALCOVE_ABOVE_YELLOW_FLIBBITS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1B_BGS_ALCOVE_ABOVE_YELLOW_FLIBBITS, 4278, 1400, -1302), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1A_BGS_BEHIND_MUMBOS_SKULL, -6940, 1000, -5838), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1C_BGS_BEHIND_TIPTUP, 0, 0, -1829), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_YELLOW_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_18_BGS_BEHIND_YELLOW_JINJO, -1855, 0, 2835), + RC(RC_BGS_MUMBO_TOKEN_FLOATING_BETWEEN_HUT_AND_CROCTUS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_19_BGS_FLOATING_BETWEEN_HUT_AND_CROCTUS, 6546, 2992, -4697), + RC(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1D_BGS_INSIDE_MR_VILES, 0, 300, -1754), + RC(RC_BGS_MUMBO_TOKEN_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1E_BGS_INSIDE_MUMBOS_SKULL, 0, 0, -450), + RC(RC_BGS_MUMBO_TOKEN_TOP_OF_POLE_NEXT_TO_BIG_EGG, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_17_BGS_TOP_OF_POLE_NEXT_TO_BIG_EGG, -3993, 1055, 1295), + RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_1, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_15_BGS_UNDER_HUT_1, 5049, 0, -5142), + RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_2, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_16_BGS_UNDER_HUT_2, 5347, 0, -5055), + RC(RC_BGS_NOTE_ABOVE_MR_VILES_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -912, 347, -3385), + RC(RC_BGS_NOTE_ABOVE_MR_VILES_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1073, 318, -3495), + RC(RC_BGS_NOTE_ABOVE_MR_VILES_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1247, 405, -3608), + RC(RC_BGS_NOTE_ABOVE_MR_VILES_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1406, 517, -3718), + RC(RC_BGS_NOTE_ABOVE_MR_VILES_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1550, 652, -3828), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 29, 899, -2061), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 207, 948, -2346), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 587, 1023, -2412), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 847, 1049, -2243), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 1161, 1099, -2187), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_6, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2261, 1075, -2275), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_7, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2606, 1174, -2223), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_8, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2904, 1125, -2136), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_9, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3290, 1224, -1883), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_10, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3425, 1200, -826), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_11, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3308, 1299, -451), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_12, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2973, 1349, -237), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_13, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2619, 1299, -284), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_14, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2310, 1200, -229), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_15, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2150, 1200, 54), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_16, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2145, 1299, 442), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_17, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 1202, 1350, 656), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_18, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 918, 1200, 687), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_19, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 575, 1249, 703), + RC(RC_BGS_NOTE_ELEVATED_WALKWAY_20, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 228, 1101, 502), + RC(RC_BGS_NOTE_FIFTH_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 468, 93, -2275), + RC(RC_BGS_NOTE_FIFTH_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 287, 93, -2417), + RC(RC_BGS_NOTE_FIFTH_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 105, 93, -2559), + RC(RC_BGS_NOTE_FIRST_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -68, 93, 1120), + RC(RC_BGS_NOTE_FIRST_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -74, 93, 920), + RC(RC_BGS_NOTE_FIRST_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -82, 93, 720), + RC(RC_BGS_NOTE_FOURTH_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3178, 93, -2312), + RC(RC_BGS_NOTE_FOURTH_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3355, 93, -2460), + RC(RC_BGS_NOTE_FOURTH_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3529, 93, -2607), + RC(RC_BGS_NOTE_HUT_BUNDLE_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_NOTE_HUT_BUNDLE_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_NOTE_HUT_BUNDLE_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_NOTE_HUT_BUNDLE_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_NOTE_HUT_BUNDLE_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 280, 125, -2069), + RC(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 219, 125, -1941), + RC(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 200, 125, -1810), + RC(RC_BGS_NOTE_INSIDE_MR_VILES_RIGHT_NOSTRIL_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -280, 125, -2070), + RC(RC_BGS_NOTE_INSIDE_MR_VILES_RIGHT_NOSTRIL_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -219, 125, -1939), + RC(RC_BGS_NOTE_INSIDE_MR_VILES_RIGHT_NOSTRIL_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -199, 125, -1810), + RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1006, 444, 3631), + RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -984, 485, 3375), + RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -962, 524, 3114), + RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -912, 479, 2851), + RC(RC_BGS_NOTE_LOG_BRIDGE_NEAR_WARP_PAD_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -862, 437, 2592), + RC(RC_BGS_NOTE_MAZE_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -6304, 992, -3449), + RC(RC_BGS_NOTE_MAZE_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -5548, 992, -2204), + RC(RC_BGS_NOTE_MAZE_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -6054, 992, -2704), + RC(RC_BGS_NOTE_MAZE_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -6546, 992, -2193), + RC(RC_BGS_NOTE_MAZE_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -7047, 985, -3702), + RC(RC_BGS_NOTE_MAZE_6, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -8055, 991, -3200), + RC(RC_BGS_NOTE_MAZE_7, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -8553, 991, -2207), + RC(RC_BGS_NOTE_MAZE_8, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -8047, 991, -4700), + RC(RC_BGS_NOTE_MAZE_9, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -8548, 991, -4204), + RC(RC_BGS_NOTE_MAZE_10, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -8046, 991, -5201), + RC(RC_BGS_NOTE_MAZE_11, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -7553, 991, -5702), + RC(RC_BGS_NOTE_MAZE_12, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -6524, 1007, -4200), + RC(RC_BGS_NOTE_POLE_NEAR_BLUE_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -4105, 1250, -8802), + RC(RC_BGS_NOTE_POLE_NEAR_BLUE_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -4105, 1350, -8802), + RC(RC_BGS_NOTE_POLE_NEAR_BLUE_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -4105, 1450, -8802), + RC(RC_BGS_NOTE_SECOND_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1345, 92, -153), + RC(RC_BGS_NOTE_SECOND_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1591, 92, -179), + RC(RC_BGS_NOTE_SECOND_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1834, 92, -204), + RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -2216, 0, -9596), + RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -2349, 0, -10049), + RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -2489, 0, -10528), + RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -3024, 0, -10719), + RC(RC_BGS_NOTE_SWAMP_BEHIND_BLUE_JINJO_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -3558, 0, -10911), + RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 7253, 0, -3699), + RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 7433, 0, -3931), + RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 7612, 0, -4165), + RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 7599, 0, -4481), + RC(RC_BGS_NOTE_SWAMP_BEHIND_HUTS_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 7585, 0, -4798), + RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -3501, 0, 3668), + RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -4017, 0, 3876), + RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -4544, 0, 4085), + RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -4920, 0, 3823), + RC(RC_BGS_NOTE_SWAMP_BEHIND_LARGE_EGG_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -5293, 0, 3559), + RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 4789, 0, -4503), + RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 4793, 0, -4288), + RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 5015, 0, -4288), + RC(RC_BGS_NOTE_SWAMP_UNDER_HUTS_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 5009, 0, -4507), + RC(RC_BGS_NOTE_TANKTUP_FEET_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3697, 176, 1632), + RC(RC_BGS_NOTE_TANKTUP_FEET_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 4351, 174, 955), + RC(RC_BGS_NOTE_TANKTUP_FEET_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 4461, 168, 2373), + RC(RC_BGS_NOTE_TANKTUP_FEET_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 5059, 170, 1758), + RC(RC_BGS_NOTE_TANKTUP_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 1006, 0, 235), + RC(RC_BGS_NOTE_TANKTUP_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 1022, 0, 0), + RC(RC_BGS_NOTE_TANKTUP_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 1005, 0, -236), + RC(RC_BGS_NOTE_TANKTUP_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1006, 0, 236), + RC(RC_BGS_NOTE_TANKTUP_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1022, 0, 0), + RC(RC_BGS_NOTE_TANKTUP_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1005, 0, -234), + RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2921, 93, -513), + RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3020, 93, -304), + RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3114, 93, -86), + RC(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_6_CC_ABOVE_WATER, 7886, 4272, 1969), + RC(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_5_CC_UNDERWATER, 3718, 3311, 2519), + RC(RC_CC_JIGGY_BOLT, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_18_CC_BOLT, 90, 5962, -12), + RC(RC_CC_JIGGY_CLANKER_RAISED, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_17_CC_CLANKER_RAISED, 0, 0, 0), + RC(RC_CC_JIGGY_FAST_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1E_CC_FAST_SAWBLADES, 0, -340, -1604), + RC(RC_CC_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_15_CC_JINJO, 0, 0, 0), + RC(RC_CC_JIGGY_LONG_PIPE, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1A_CC_LONG_PIPE, 4629, 2151, 3082), + RC(RC_CC_JIGGY_RINGS, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1C_CC_RINGS, 0, 0, 0), + RC(RC_CC_JIGGY_SLOW_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1D_CC_SLOW_SAWBLADES, 10, -391, -2185), + RC(RC_CC_JIGGY_TAIL, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_19_CC_TAIL, 10061, 5112, 3), + RC(RC_CC_JIGGY_TOOTH, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1B_CC_TOOTH, 0, 0, 0), + RC(RC_CC_JIGGY_SNIPPETS, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_16_CC_SNIPPETS, 0, 0, 0), + RC(RC_CC_JINJO_BLUE, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_BLUE_CLANKERS_CAVERN, NULL, 4326, 2146, -4080), + RC(RC_CC_JINJO_GREEN, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_GREEN_CLANKERS_CAVERN, NULL, 5017, -3085, -13), + RC(RC_CC_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_ORANGE_CLANKERS_CAVERN, NULL, 6138, 5087, 2637), + RC(RC_CC_JINJO_PINK, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_PINK_CLANKERS_CAVERN, NULL, 3644, -474, 48), + RC(RC_CC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_YELLOW_CLANKERS_CAVERN, NULL, -4726, 5337, -110), + RC(RC_CC_MOLEHILL_WONDERWING, RCTYPE_MOLEHILL, LEVEL_3_CLANKERS_CAVERN, RI_MOLEHILL_WONDERWING, ABILITY_12_WONDERWING, -259, -500, 1413), + RC(RC_CC_MUMBO_TOKEN_CHOMPA_BEHIND_CLANKERS_TAIL, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_10_CC_CHOMPA_BEHIND_CLANKERS_TAIL, 9823, 4225, -19), + RC(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE, -9694, 5272, 1607), + RC(RC_CC_MUMBO_TOKEN_TUNNEL_RIGHT_OF_CLANKER, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, 870, 2146, -3148), + RC(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_13_CC_ALCOVE_WITH_OPEN_GRATE, 2028, 5456, 2344), + RC(RC_CC_MUMBO_TOKEN_CLANKERS_LEFT_TOOTH, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_14_CC_CLANKERS_LEFT_TOOTH, 532, 1424, 6632), + RC(RC_CC_NOTE_ABOVE_BOLT_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2036, 5693, -15), + RC(RC_CC_NOTE_ABOVE_BOLT_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1533, 5693, 381), + RC(RC_CC_NOTE_ABOVE_BOLT_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1043, 5693, 377), + RC(RC_CC_NOTE_ABOVE_BOLT_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 939, 5693, -17), + RC(RC_CC_NOTE_CLIMBABLE_PIPE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3013, 4437, 2477), + RC(RC_CC_NOTE_CLIMBABLE_PIPE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3013, 4827, 2477), + RC(RC_CC_NOTE_CLIMBABLE_PIPE_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3013, 5117, 2477), + RC(RC_CC_NOTE_CLIMBABLE_PIPE_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3013, 5407, 2477), + RC(RC_CC_NOTE_ENTRANCE_TUNNEL_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -2580, 2841, 0), + RC(RC_CC_NOTE_ENTRANCE_TUNNEL_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -2030, 2466, 0), + RC(RC_CC_NOTE_ENTRANCE_TUNNEL_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -1480, 2461, 0), + RC(RC_CC_NOTE_ENTRANCE_TUNNEL_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -930, 2437, 0), + RC(RC_CC_NOTE_ENTRANCE_TUNNEL_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -380, 2236, 0), + RC(RC_CC_NOTE_ENTRANCE_TUNNEL_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 170, 2155, 0), + RC(RC_CC_NOTE_FAST_SAWBLADES_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -500, 1695), + RC(RC_CC_NOTE_FAST_SAWBLADES_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -500, 1130), + RC(RC_CC_NOTE_FAST_SAWBLADES_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -500, 555), + RC(RC_CC_NOTE_FAST_SAWBLADES_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -500, -20), + RC(RC_CC_NOTE_FAST_SAWBLADES_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -500, -600), + RC(RC_CC_NOTE_FAST_SAWBLADES_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -500, -1335), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, 1002, 5174), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 684, 999, 5391), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 780, 1004, 6071), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 566, 1007, 6712), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, 1008, 7036), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -566, 1015, 6712), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -792, 1005, 6071), + RC(RC_CC_NOTE_INSIDE_CLANKERS_MOUTH_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -685, 990, 5391), + RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -998, -387, 0), + RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -1399, -539, -10), + RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -1801, -493, -10), + RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -2199, -351, -10), + RC(RC_CC_NOTE_LOWER_GILLS_TUNNEL_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -2601, -8, -10), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -7636, 5162, -1164), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -8284, 5243, -911), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -8573, 5244, -353), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -9112, 5243, -182), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -7910, 5212, 804), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -7038, 5212, 754), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -6634, 5212, 238), + RC(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, -6065, 5211, 313), + RC(RC_CC_NOTE_NEAR_PINK_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1600, 953, 20), + RC(RC_CC_NOTE_NEAR_PINK_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1999, 1241, 45), + RC(RC_CC_NOTE_NEAR_PINK_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2399, 1258, 45), + RC(RC_CC_NOTE_NEAR_SNIPPETS_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 13028, 3362, -761), + RC(RC_CC_NOTE_NEAR_SNIPPETS_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 13540, 3362, -973), + RC(RC_CC_NOTE_NEAR_SNIPPETS_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 14096, 3362, -969), + RC(RC_CC_NOTE_NEAR_SNIPPETS_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 14602, 3362, -732), + RC(RC_CC_NOTE_NEAR_SNIPPETS_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 14590, 3362, 702), + RC(RC_CC_NOTE_NEAR_SNIPPETS_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 14105, 3361, 929), + RC(RC_CC_NOTE_NEAR_SNIPPETS_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 13538, 3362, 931), + RC(RC_CC_NOTE_NEAR_SNIPPETS_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 13018, 3362, 713), + RC(RC_CC_NOTE_NEAR_TAIL_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 8755, 4225, -1418), + RC(RC_CC_NOTE_NEAR_TAIL_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 8756, 4225, 1278), + RC(RC_CC_NOTE_NEAR_TAIL_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9091, 4225, 1104), + RC(RC_CC_NOTE_NEAR_TAIL_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9449, 4225, 923), + RC(RC_CC_NOTE_NEAR_TAIL_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9636, 4225, 630), + RC(RC_CC_NOTE_NEAR_TAIL_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9818, 4225, 339), + RC(RC_CC_NOTE_NEAR_TAIL_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9818, 4225, -377), + RC(RC_CC_NOTE_NEAR_TAIL_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9636, 4225, -679), + RC(RC_CC_NOTE_NEAR_TAIL_9, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9438, 4225, -978), + RC(RC_CC_NOTE_NEAR_TAIL_10, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 9091, 4225, -1207), + RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6582, 5284, 2536), + RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6785, 5121, 2454), + RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6989, 4958, 2388), + RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 7194, 4787, 2321), + RC(RC_CC_NOTE_PIPE_NEAR_SHOCK_PAD_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 7401, 4611, 2247), + RC(RC_CC_NOTE_SLOW_SAWBLADES_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -425, 1610), + RC(RC_CC_NOTE_SLOW_SAWBLADES_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -425, 1010), + RC(RC_CC_NOTE_SLOW_SAWBLADES_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -425, 410), + RC(RC_CC_NOTE_SLOW_SAWBLADES_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -425, -190), + RC(RC_CC_NOTE_SLOW_SAWBLADES_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -425, -790), + RC(RC_CC_NOTE_SLOW_SAWBLADES_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 0, -425, -1390), + RC(RC_CC_NOTE_TOP_OF_CLANKER_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3200, 4243, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3500, 4269, 2), + RC(RC_CC_NOTE_TOP_OF_CLANKER_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3800, 4281, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 4100, 4293, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5300, 4209, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5600, 4161, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5899, 4106, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6200, 4072, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_9, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6500, 4047, 0), + RC(RC_CC_NOTE_TOP_OF_CLANKER_10, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6800, 4063, 0), + RC(RC_CC_NOTE_UNDERWATER_LOCK_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6361, -3085, -908), + RC(RC_CC_NOTE_UNDERWATER_LOCK_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6716, -3085, -18), + RC(RC_CC_NOTE_UNDERWATER_LOCK_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6350, -3085, 866), + RC(RC_CC_NOTE_UNDERWATER_LOCK_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5468, -3085, 1225), + RC(RC_CC_NOTE_UNDERWATER_LOCK_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 4583, -3085, 865), + RC(RC_CC_NOTE_UNDERWATER_LOCK_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 4220, -3085, -19), + RC(RC_CC_NOTE_UNDERWATER_LOCK_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 4584, -3085, -906), + RC(RC_CC_NOTE_UNDERWATER_LOCK_8, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5469, -3085, -1273), + RC(RC_CC_NOTE_UNDERWATER_PIPE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 3866, 1198, 2618), + RC(RC_CC_NOTE_UNDERWATER_PIPE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 4427, 1188, 2637), + RC(RC_CC_NOTE_UNDERWATER_PIPE_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 4961, 1184, 2649), + RC(RC_CC_NOTE_UNDERWATER_PIPE_4, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5417, 1184, 2626), + RC(RC_CC_NOTE_UNDERWATER_PIPE_5, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5881, 1184, 2600), + RC(RC_CC_NOTE_UNDERWATER_PIPE_6, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6342, 1184, 2485), + RC(RC_CC_NOTE_UNDERWATER_PIPE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6804, 1184, 2361), + RC(RC_CC_NOTE_YELLOW_GRATE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2240, 5262, -2473), + RC(RC_CC_NOTE_YELLOW_GRATE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5270, 5261, -2937), + RC(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_D_CCW_GNAWTYS, 694, 998, 632), + RC(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_E_CCW_NABNUTS, 640, 513, -202), + RC(RC_CCW_JIGGY_EYRIE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_49_CCW_EYRIE, 0, 0, 0), + RC(RC_CCW_JIGGY_FLOWER, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4D_CCW_FLOWER, 0, 0, 0), + RC(RC_CCW_JIGGY_GNAWTY, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4B_CCW_GNAWTY, 240, 600, 75), + RC(RC_CCW_JIGGY_HOUSE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_48_CCW_HOUSE, 6070, 4244, -113), + RC(RC_CCW_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_47_CCW_JINJO, 0, 0, 0), + RC(RC_CCW_JIGGY_NABNUT, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4A_CCW_NABNUT, 0, 0, 0), + RC(RC_CCW_JIGGY_SUMMER_LEAF_JUMPS, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4E_CCW_SUMMER_LEAF_JUMPS, 2215, 2616, 2142), + RC(RC_CCW_JIGGY_TOP_ROOM, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_50_CCW_TOP_ROOM, 0, 17, 225), + RC(RC_CCW_JIGGY_TREE_TOP, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4F_CCW_TREE_TOP, 0, 7625, 3100), + RC(RC_CCW_JIGGY_ZUBBAS, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4C_CCW_ZUBBAS, 0, 0, 125), + RC(RC_CCW_JINJO_BLUE, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_BLUE_CLICK_CLOCK_WOOD, NULL, -6775, 1301, 0), + RC(RC_CCW_JINJO_GREEN, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_GREEN_CLICK_CLOCK_WOOD, NULL, 0, 5760, -3330), + RC(RC_CCW_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, NULL, -1592, 900, -6073), + RC(RC_CCW_JINJO_PINK, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_PINK_CLICK_CLOCK_WOOD, NULL, -225, 1039, -1100), + RC(RC_CCW_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, NULL, -3602, 0, 4266), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6A_CCW_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, 153, 1857, 2677), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6D_CCW_AUTUMN_LEAF_NEAR_TREEHOUSE, 3405, 4107, 1003), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6B_CCW_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, 500, 166, 5125), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6C_CCW_AUTUMN_SNAREBEAR_TOP_OF_TREE, 0, 5830, -3325), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6E_CCW_AUTUMN_TOP_OF_BRANCH, -5929, 2586, 61), + RC(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5D_CCW_SPRING_FRONT_OF_EYRIE, -2750, 4586, -513), + RC(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_62_CCW_SPRING_NABNUTS_HOUSE, -575, 300, -139), + RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5F_CCW_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, 1904, 105, -2706), + RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_60_CCW_SPRING_SNAREBEAR_NEAR_ENTRANCE, 1000, 105, 5300), + RC(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5E_CCW_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, -2649, 0, -395), + RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_61_CCW_SPRING_TOP_OF_BEEHIVE, 0, 3513, -5240), + RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5C_CCW_SPRING_TOP_OF_BRANCH, -4053, 2894, 587), + RC(RC_CCW_MUMBO_TOKEN_SPRING_UNFINISHED_WOOD_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5B_CCW_SPRING_UNFINISHED_WOOD_TREEHOUSE, 6134, 4244, 306), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_64_CCW_SUMMER_BIG_FLOWER_FIELD, -3578, 40, -4259), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_67_CCW_SUMMER_ENTRANCE_GNAWTYS_HOUSE, 2700, -600, 0), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_68_CCW_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, 2043, 3534, 1799), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_69_CCW_SUMMER_INSIDE_MUMBOS_SKULL, 0, 416, 500), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_63_CCW_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, -1861, 4469, 1583), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_65_CCW_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, -3855, 1428, 3840), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_66_CCW_SUMMER_TOP_OF_BRANCH, -4661, 2800, -1248), + RC(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6F_CCW_WINTER_BIG_FLOWER, 0, 105, -5400), + RC(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_71_CCW_WINTER_BROKEN_BEEHIVE, 0, 3138, -3696), + RC(RC_CCW_MUMBO_TOKEN_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_70_CCW_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, 5950, -46, 0), + RC(RC_CCW_MUMBO_TOKEN_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, -3157, 300, -3149), + RC(RC_CCW_MUMBO_TOKEN_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_72_CCW_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, 40, 3969, 5000), + RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -674, -1, 925), + RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -674, 0, -900), + RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 675, -2, 925), + RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 675, 0, -674), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3929, 4900, 312), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -4375, 4900, 765), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -5024, 4900, 766), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -5471, 4900, 312), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -5471, 4900, -313), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -5024, 4900, -766), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_7, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -4376, 4900, -766), + RC(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_8, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3929, 4900, -313), + RC(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 768, 998, 596), + RC(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 613, 998, 664), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -359, 379, -359), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -360, 398, 375), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 362, 379, -365), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_MUMBOS_SKULL_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 363, 398, 364), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_NABNUTS_HOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 288, 413, -357), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_NABNUTS_HOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 382, 413, -296), + RC(RC_CCW_NOTE_AUTUMN_INSIDE_NABNUTS_HOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 471, 413, -235), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -968, 900, 2578), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 969, 900, 2569), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 2569, 900, 969), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 2570, 900, -970), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 1950, 900, -1950), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 970, 900, -2569), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_7, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -50, 1100, -2750), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_8, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -970, 900, -2570), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_9, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2584, 1100, -971), + RC(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_10, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2577, 900, 972), + RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 950, 10, -6531), + RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 475, 10, -6599), + RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 0, 10, -6640), + RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -475, 10, -6599), + RC(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -950, 10, -6531), + RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 1905, 170, -2705), + RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 1905, 250, -2705), + RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 1905, 330, -2705), + RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3801, 1452, 3790), + RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3801, 1532, 3790), + RC(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3801, 1612, 3790), + RC(RC_CCW_NOTE_ENTRANCE_HUB_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 816, 8, 3277), + RC(RC_CCW_NOTE_ENTRANCE_HUB_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 342, 2, 3477), + RC(RC_CCW_NOTE_ENTRANCE_HUB_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -342, 2, 3477), + RC(RC_CCW_NOTE_ENTRANCE_HUB_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -818, 8, 3275), + RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2975, 300, -2975), + RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3150, 307, -3150), + RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3325, 300, -3325), + RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_MUMBOS_SKULL_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2700, 900, 2700), + RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_MUMBOS_SKULL_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2900, 900, 2900), + RC(RC_CCW_NOTE_SPRING_LEDGE_NEAR_MUMBOS_SKULL_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -3100, 921, 3100), + RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 2875, 894, 2875), + RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 3075, 876, 3075), + RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 3275, 845, 3274), + RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 2826, 1275, -2825), + RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 3025, 1275, -3025), + RC(RC_CCW_NOTE_SPRING_LEDGE_OVER_LAKE_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 3225, 1275, -3225), + RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 0, 900, 2750), + RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 1950, 900, 1950), + RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 2750, 900, 0), + RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1950, 937, -1950), + RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2750, 900, 0), + RC(RC_CCW_NOTE_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1950, 1350, 1950), + RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 500, 59, -4950), + RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -500, 48, -4950), + RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -500, 52, -5850), + RC(RC_CCW_NOTE_SPRING_NEAR_BIG_FLOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 500, 52, -5850), + RC(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 2201, -600, 0), + RC(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 1700, -589, 0), + RC(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -123, 308, 3059), + RC(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 115, 608, 3056), + RC(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 0, 3300, -2750), + RC(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 0, 3310, -2950), + RC(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 0, 3350, -3150), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 700, 4819, 4750), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 400, 4819, 4450), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 0, 4819, 4400), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -400, 4819, 4450), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_5, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -700, 4819, 4750), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 4728, 4244, -522), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 4671, 4243, -329), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 4562, 4243, 54), + RC(RC_CCW_NOTE_SUMMER_OUTSIDE_TREEHOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 4507, 4244, 249), + RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1150, 4019, 4300), + RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1599, 4019, 4750), + RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2051, 4019, 4300), + RC(RC_CCW_NOTE_WINTER_NEAR_NABNUTS_HOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1599, 4019, 3851), + RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -4034, 2899, -939), + RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -4654, 2800, -1243), + RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -4040, 2894, 583), + RC(RC_CCW_NOTE_WINTER_TOP_OF_BRANCH_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -4652, 2800, 647), + RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 4741, 4958, -106), + RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 5156, 4957, 13), + RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 5571, 4957, 132), + RC(RC_CCW_NOTE_WINTER_TOP_OF_TREEHOUSE_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 5987, 4958, 252), + RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2637, 4569, -871), + RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -2308, 4869, -1528), + RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1691, 5210, -2199), + RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -764, 5590, -2634), + RC(RC_CCW_SNS_YELLOW_EGG, RCTYPE_STOP_N_SWOP, LEVEL_8_CLICK_CLOCK_WOOD, RI_STOP_N_SWOP_EGG_YELLOW, SNS_ITEM_EGG_YELLOW, 556, 150, 47), + RC(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_A_FP_SIR_SLUSH, 4295, 441, 1268), + RC(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_9_FP_WOZZAS_CAVE, -6531, 135, 422), + RC(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_31_FP_SIR_SLUSH, 0, 0 ,0), + RC(RC_FP_JIGGY_BOGGY_RACE_1, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_30_FP_BOGGY_2, 0, 0 ,0), + RC(RC_FP_JIGGY_BOGGY_RACE_2, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2C_FP_BOGGY_3, 0, 0 ,0), + RC(RC_FP_JIGGY_IGLOO, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2E_FP_PRESENTS, 0, 0 ,0), + RC(RC_FP_JIGGY_INSIDE_THE_TREE, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2F_FP_XMAS_TREE, 0, 2305, 0), + RC(RC_FP_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_29_FP_JINJO, 0, 0 ,0), + RC(RC_FP_JIGGY_SLED_TO_BOGGY, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2A_FP_BOGGY_1, 0, 0 ,0), + RC(RC_FP_JIGGY_SNOWMANS_BUTTONS, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2D_FP_SNOWMAN_BUTTONS, 0, 0 ,0), + RC(RC_FP_JIGGY_SNOWMANS_PIPE, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2B_FP_PIPE, -1019, 5936, 2047), + RC(RC_FP_JIGGY_WOZZA, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_32_FP_WOZZA, -4605, 822, -3938), + RC(RC_FP_JINJO_BLUE, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_BLUE_FREEZEEZY_PEAK, NULL, -2588, 5684, 60), + RC(RC_FP_JINJO_GREEN, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_GREEN_FREEZEEZY_PEAK, NULL, 6083, 450, 2736), + RC(RC_FP_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_ORANGE_FREEZEEZY_PEAK, NULL, 629, 366, 859), + RC(RC_FP_JINJO_PINK, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_PINK_FREEZEEZY_PEAK, NULL, -6851, 1193, 930), + RC(RC_FP_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_YELLOW_FREEZEEZY_PEAK, NULL, 0, 406, -511), + RC(RC_FP_MOLEHILL_BEAK_BOMB, RCTYPE_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK, RI_MOLEHILL_BEAK_BOMB, ABILITY_1_BEAK_BOMB, -7462, 250, 1324), + RC(RC_FP_MUMBO_TOKEN_INSIDE_BOGGYS_IGLOO, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_28_FP_INSIDE_BOGGYS_IGLOO, 0, 10, -215), + RC(RC_FP_MUMBO_TOKEN_PRESENT_STACK, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_21_FP_BEHIND_PILE_PRESENT_BOXES, -5904, 260, 794), + RC(RC_FP_MUMBO_TOKEN_POTTED_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_25_FP_CHRISTMAS_TREE_POT, -4590, 350, 6344), + RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_START, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_23_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_LEFT_FOOT, 1413, 18, 2802), + RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_FINISH, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_24_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_RIGHT_FOOT, -4527, 211, -803), + RC(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_26_FP_TIP_OF_SCARF, -793, 3020, 4389), + RC(RC_FP_MUMBO_TOKEN_SNOWMAN_LEFT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_1F_FP_SNOWMAN_LEFT_FOOT, -1815, 4, -1019), + RC(RC_FP_MUMBO_TOKEN_SNOWMAN_RIGHT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_20_FP_SNOWMAN_RIGHT_FOOT, 634, 5, 769), + RC(RC_FP_MUMBO_TOKEN_VILLAGE_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_22_FP_ABOVE_CHIMNEY_FLIGHT_PAD, 5296, 2013, 2729), + RC(RC_FP_MUMBO_TOKEN_WATER_BEHIND_SNOWMAN, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_27_FP_WATER_BEHIND_SNOWMAN, -2424, -168, -4235), + RC(RC_FP_NOTE_FIRST_SLOPE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -790, 3505, 8345), + RC(RC_FP_NOTE_FIRST_SLOPE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -820, 3149, 7926), + RC(RC_FP_NOTE_FIRST_SLOPE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -843, 2725, 7475), + RC(RC_FP_NOTE_FIRST_SLOPE_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -864, 2243, 7025), + RC(RC_FP_NOTE_FIRST_SLOPE_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -888, 1727, 6573), + RC(RC_FP_NOTE_HOUSE_NEAR_MUMBO_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4268, 865, -589), + RC(RC_FP_NOTE_HOUSE_NEAR_MUMBO_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4468, 844, -705), + RC(RC_FP_NOTE_HOUSE_NEAR_MUMBO_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4659, 840, -815), + RC(RC_FP_NOTE_HOUSE_NEAR_SIR_SLUSH_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3865, 843, 3023), + RC(RC_FP_NOTE_HOUSE_NEAR_SIR_SLUSH_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3862, 844, 3237), + RC(RC_FP_NOTE_HOUSE_NEAR_SIR_SLUSH_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3860, 861, 3464), + RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -362, 379, -362), + RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -500, 398, 0), + RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -355, 398, 362), + RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 362, 378, -362), + RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 500, 387, 0), + RC(RC_FP_NOTE_MUMBOS_SKULL_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 362, 398, 363), + RC(RC_FP_NOTE_NEAR_RACE_START_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 2656, 658, 5687), + RC(RC_FP_NOTE_NEAR_RACE_START_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 2700, 658, 6100), + RC(RC_FP_NOTE_NEAR_RACE_START_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 2271, 658, 6789), + RC(RC_FP_NOTE_NEAR_RACE_START_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 1892, 658, 6955), + RC(RC_FP_NOTE_NEAR_WOZZA_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -3938, 800, -3704), + RC(RC_FP_NOTE_NEAR_WOZZA_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -3705, 800, -4019), + RC(RC_FP_NOTE_NEAR_WOZZA_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -3661, 800, -4459), + RC(RC_FP_NOTE_NEAR_WOZZA_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -3920, 800, -4807), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4044, 295, 2411), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4039, 294, 106), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3763, 294, 320), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUCH_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3505, 295, 679), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3467, 295, 1433), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3654, 295, 1906), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4404, 294, 243), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4559, 295, 2482), + RC(RC_FP_NOTE_POND_AROUND_SIR_SLUSH_9, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 4930, 294, 1918), + RC(RC_FP_NOTE_POTTED_TREE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -3430, 0, 6550), + RC(RC_FP_NOTE_POTTED_TREE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -3926, 0, 7284), + RC(RC_FP_NOTE_POTTED_TREE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -4844, 0, 7451), + RC(RC_FP_NOTE_POTTED_TREE_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -5579, 0, 6927), + RC(RC_FP_NOTE_POTTED_TREE_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -5754, 0, 6022), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -689, 600, -398), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -394, 600, -690), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 1, 600, -795), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 399, 600, -688), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 686, 600, -395), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 793, 600, 0), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 685, 600, 396), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 395, 600, 682), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_9, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 3, 600, 794), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_10, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -398, 600, 684), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_11, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -689, 600, 395), + RC(RC_FP_NOTE_POTTED_TREE_INTERIOR_12, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -791, 600, 0), + RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -5971, 893, 900), + RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -6190, 893, 899), + RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -6409, 893, 900), + RC(RC_FP_NOTE_PRESENTS_NEAR_FLIGHT_PAD_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -6630, 893, 900), + RC(RC_FP_NOTE_SECOND_SLOPE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -900, 1727, 5675), + RC(RC_FP_NOTE_SECOND_SLOPE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -883, 1196, 5183), + RC(RC_FP_NOTE_SECOND_SLOPE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -867, 578, 4693), + RC(RC_FP_NOTE_SECOND_SLOPE_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -850, 0, 4201), + RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -4394, 0, -1052), + RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -4772, 0, -948), + RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -4668, 0, -570), + RC(RC_FP_NOTE_SIR_SLUSH_NEAR_SNOWMAN_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -4290, 0, -674), + RC(RC_FP_NOTE_SNOWMAN_HAT_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -672, 8736, 1047), + RC(RC_FP_NOTE_SNOWMAN_HAT_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1517, 8633, 860), + RC(RC_FP_NOTE_SNOWMAN_HAT_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -2000, 8492, 133), + RC(RC_FP_NOTE_SNOWMAN_HAT_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1804, 8434, -734), + RC(RC_FP_NOTE_SNOWMAN_HAT_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1046, 8503, -1179), + RC(RC_FP_NOTE_SNOWMAN_HAT_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -195, 8574, -1023), + RC(RC_FP_NOTE_SNOWMAN_HAT_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 257, 8711, -275), + RC(RC_FP_NOTE_SNOWMAN_HAT_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 80, 8749, 591), + RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1956, 5, -25), + RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -2176, 5, -559), + RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1254, 5, -943), + RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1026, 5, -403), + RC(RC_FP_NOTE_SNOWMAN_LEFT_FOOT_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1378, 5, 47), + RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 283, 4, 1246), + RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -301, 4, 1176), + RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -515, 5, 629), + RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -154, 5, 162), + RC(RC_FP_NOTE_SNOWMAN_RIGHT_FOOT_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 426, 5, 244), + RC(RC_FP_NOTE_SNOWMAN_SCARF_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -2337, 1669, -5188), + RC(RC_FP_NOTE_SNOWMAN_SCARF_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -2704, 1958, -4154), + RC(RC_FP_NOTE_SNOWMAN_SCARF_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1952, 2278, -3614), + RC(RC_FP_NOTE_SNOWMAN_SCARF_4, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1192, 2772, -4242), + RC(RC_FP_NOTE_SNOWMAN_SCARF_5, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -615, 3247, -4985), + RC(RC_FP_NOTE_SNOWMAN_SCARF_6, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 59, 3511, -4554), + RC(RC_FP_NOTE_SNOWMAN_SCARF_7, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -387, 3764, -3875), + RC(RC_FP_NOTE_SNOWMAN_SCARF_8, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1062, 4007, -4301), + RC(RC_FP_NOTE_SNOWMAN_SCARF_9, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -631, 4267, -4977), + RC(RC_FP_NOTE_SNOWMAN_SCARF_10, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 42, 4530, -4557), + RC(RC_FP_NOTE_SNOWMAN_SCARF_11, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -20, 4790, -3699), + RC(RC_FP_NOTE_SNOWMAN_SCARF_12, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -140, 5225, -3101), + RC(RC_FP_NOTE_SNOWMAN_SCARF_13, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -248, 5452, -2390), + RC(RC_FP_NOTE_SNOWMAN_SCARF_14, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -353, 5101, -1787), + RC(RC_FP_NOTE_SNOWMAN_SCARF_15, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -491, 5430, -1199), + RC(RC_FP_NOTE_SNOWMAN_SCARF_16, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -583, 5605, -698), + RC(RC_FP_NOTE_SNOWMAN_SCARF_17, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -1514, 5605, -99), + RC(RC_FP_NOTE_SNOWMAN_SCARF_18, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -941, 5605, 844), + RC(RC_FP_NOTE_SNOWMAN_SCARF_19, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 17, 5605, 266), + RC(RC_FP_SNS_ICE_KEY, RCTYPE_STOP_N_SWOP, LEVEL_5_FREEZEEZY_PEAK, RI_STOP_N_SWOP_ICE_KEY, SNS_ITEM_ICE_KEY, 1567, 583, 2416), + RC(RC_GL_JIGGY_LOBBY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_33_LAIR_1ST_JIGGY, -1505, 600, 123), + RC(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_37_LAIR_BGS_WITCH_SWITCH, 0, 0, -20), + RC(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_35_LAIR_CC_WITCH_SWITCH, 0, 75, 156), + RC(RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_3C_LAIR_CCW_WITCH_SWITCH, 0, 3370, 2270), + RC(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_38_LAIR_FP_WITCH_SWITCH, 4126, 2392, 6559), + RC(RC_GL_JIGGY_WITCH_SWITCH_GOBIS_VALLEY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_3A_LAIR_GV_WITCH_SWITCH, -1290, 514, -787), + RC(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_39_LAIR_MMM_WITCH_SWITCH, 1597, 1011, -254), + RC(RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_34_LAIR_MM_WITCH_SWITCH, 4165, 1000, -2363), + RC(RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_3B_LAIR_RBB_WITCH_SWITCH, 0, 1200, 1650), + RC(RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_36_LAIR_TTC_WITCH_SWITCH, 998, 783, 368), + RC(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_51_LAIR_BEHIND_PURPLE_CAULDRON, 162, -750, 4611), + RC(RC_GL_MUMBO_TOKEN_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_53_LAIR_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, -180, 351, -750), + RC(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_54_LAIR_ABOVE_CC_ENTRANCE, 0, 850, -2450), + RC(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_52_LAIR_CCW_JIGGY_PODIUM, 4936, -478, 286), + RC(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_55_LAIR_BEHIND_SARCOPHAGUS, -1486, 0, -922), + RC(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_56_LAIR_ADVENT_TOP_WINDOW, 4155, 1485, 6270), + RC(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_59_LAIR_UNDERWATER_RBB_ENTRANCE_AREA, 1764, -1400, -1136), + RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), + RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), + RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), + RC(RC_GV_EMPTY_HONEYCOMB_CACTUS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_B_GV_CACTUS, 2911, 3292, -3307), + RC(RC_GV_EMPTY_HONEYCOMB_GOBI, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_C_GV_GOBI_3, -6885, 2383, 1335), + RC(RC_GV_JIGGY_ANCIENT_ONES, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_46_GV_ANCIENT_ONES, 0, 0, 0), + RC(RC_GV_JIGGY_GOBI_1, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_44_GV_GOBI_1, 0, 0, 0), + RC(RC_GV_JIGGY_GOBI_2, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_45_GV_GOBI_2, 0, 0, 0), + RC(RC_GV_JIGGY_GRABBA, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_3E_GV_GRABBA, -4644, 1875, -4831), + RC(RC_GV_JIGGY_HISTUP, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_43_GV_HISTUP, -3, 1359, 15), + RC(RC_GV_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_3D_GV_JINJO, 0, 0, 0), + RC(RC_GV_JIGGY_MATCHING_GAME, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_40_GV_MATCHING_GAME, 0, 0, 0), + RC(RC_GV_JIGGY_MAZE, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_41_GV_MAZE, -5008, 66, 62), + RC(RC_GV_JIGGY_SHYINX, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_3F_GV_SHYINX, -2250, 1970, -49), + RC(RC_GV_JIGGY_WATER_PYRAMID, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_42_GV_WATER_PYRAMID, -1, 145, -23), + RC(RC_GV_JINJO_BLUE, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_BLUE_GOBIS_VALLEY, NULL, 58, 535, 1570), + RC(RC_GV_JINJO_GREEN, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_GREEN_GOBIS_VALLEY, NULL, 4952, 2538, 439), + RC(RC_GV_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_ORANGE_GOBIS_VALLEY, NULL, 2078, 1122, -50), + RC(RC_GV_JINJO_PINK, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_PINK_GOBIS_VALLEY, NULL, -4964, 0, 700), + RC(RC_GV_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_YELLOW_GOBIS_VALLEY, NULL, 3067, 447, 10270), + RC(RC_GV_MOLEHILL_TURBO_TALON, RCTYPE_MOLEHILL, LEVEL_7_GOBIS_VALLEY, RI_MOLEHILL_TURBO_TALON, ABILITY_11_TURBO_TALON, -6445, 2831, -822), + RC(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2F_GV_BEHIND_SANDYBUTTS_SARCOPHAGUS, -5514, 0, 138), + RC(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2B_GV_BOTTOM_OF_MOAT, 91, 535, -860), + RC(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2D_GV_FRONT_OF_STAR_DOOR, -230, 2843, -3091), + RC(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_32_GV_INSIDE_JINXY, -2550, 0, -51), + RC(RC_GV_MUMBO_TOKEN_INSIDE_MEMORY_GAME_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2E_GV_INSIDE_MEMORY_GAME_ROOM, 715, 248, 0), + RC(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_30_GV_INSIDE_WATER_PYRAMID, -300, 1439, -1194), + RC(RC_GV_MUMBO_TOKEN_NEXT_TO_RUBEE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_31_GV_NEXT_TO_RUBEE, 0, 107, -602), + RC(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2A_GV_SAND_RIGHT_OF_JINXY, -5386, 1420, 10034), + RC(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_29_GV_TOP_OF_JINXYS_NOSE, -2149, 3340, 5867), + RC(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2C_GV_TOP_OF_WATER_PYRAMID, 64, 3484, 400), + RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7178, 2372, 1754), + RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7148, 2371, 1568), + RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7123, 2371, 1404), + RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7105, 2371, 1247), + RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7082, 2372, 1091), + RC(RC_GV_NOTE_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 88, 460, 8403), + RC(RC_GV_NOTE_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -251, 697, 8089), + RC(RC_GV_NOTE_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -584, 894, 7778), + RC(RC_GV_NOTE_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -935, 1082, 7449), + RC(RC_GV_NOTE_ENTRANCE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -1289, 1259, 7119), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -450, 19, -450), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -450, 19, 450), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 450, 19, -450), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 450, 19, 450), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 4215, 2452, -715), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 4815, 2452, -714), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 2395, 2130, -300), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 3090, 2730, -300), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 3090, 2730, 970), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 2395, 2130, 970), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 3792, 2656, 325), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 3930, 2849, 324), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 4070, 3040, 324), + RC(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 4211, 3233, 324), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -4002, 0, 43), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3504, 0, -190), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -2735, 0, 203), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -1913, 3, 210), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 4729, 0, -45), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 4178, 0, 205), + RC(RC_GV_NOTE_MAZE_PYRAMID_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 5400, 0, 326), + RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -464, 2770, 1610), + RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -464, 2170, 2305), + RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 684, 2770, 1610), + RC(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 685, 2170, 2305), + RC(RC_GV_NOTE_MOAT_BOTTOM_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -908, 535, -472), + RC(RC_GV_NOTE_MOAT_BOTTOM_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -1182, 535, 457), + RC(RC_GV_NOTE_MOAT_BOTTOM_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -807, 535, 1318), + RC(RC_GV_NOTE_MOAT_BOTTOM_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 928, 535, 1291), + RC(RC_GV_NOTE_MOAT_BOTTOM_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 1234, 535, 411), + RC(RC_GV_NOTE_MOAT_BOTTOM_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 1055, 535, -458), + RC(RC_GV_NOTE_MOAT_EDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -2111, 1830, 1016), + RC(RC_GV_NOTE_MOAT_EDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -2100, 1830, 112), + RC(RC_GV_NOTE_MOAT_EDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -2098, 1830, -785), + RC(RC_GV_NOTE_MOAT_EDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -1455, 1830, -1432), + RC(RC_GV_NOTE_MOAT_EDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -800, 1830, -2068), + RC(RC_GV_NOTE_MOAT_EDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 110, 1830, -2068), + RC(RC_GV_NOTE_MOAT_EDGE_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 1019, 1830, -2068), + RC(RC_GV_NOTE_MOAT_EDGE_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 1671, 1830, -1416), + RC(RC_GV_NOTE_MOAT_EDGE_9, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 2307, 1837, -770), + RC(RC_GV_NOTE_NEAR_GRABBA_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3017, 1781, -5496), + RC(RC_GV_NOTE_NEAR_GRABBA_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3026, 1781, -5048), + RC(RC_GV_NOTE_NEAR_GRABBA_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3028, 1781, -4591), + RC(RC_GV_NOTE_NEAR_GRABBA_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3037, 1781, -4148), + RC(RC_GV_NOTE_NEAR_GRABBA_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3054, 1781, -3695), + RC(RC_GV_NOTE_NEAR_GRABBA_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3401, 1780, -3430), + RC(RC_GV_NOTE_NEAR_GRABBA_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3752, 1781, -3161), + RC(RC_GV_NOTE_NEAR_GRABBA_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -4116, 1780, -2895), + RC(RC_GV_NOTE_NEAR_GRABBA_9, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -4541, 1780, -2871), + RC(RC_GV_NOTE_NEAR_GRABBA_10, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -4958, 1781, -2855), + RC(RC_GV_NOTE_NEAR_GRABBA_11, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -5385, 1780, -2843), + RC(RC_GV_NOTE_NEAR_RUBEE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -685, 0, -743), + RC(RC_GV_NOTE_NEAR_RUBEE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -495, 0, -880), + RC(RC_GV_NOTE_NEAR_RUBEE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -913, 0, 428), + RC(RC_GV_NOTE_NEAR_RUBEE_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -986, 0, 201), + RC(RC_GV_NOTE_NEAR_RUBEE_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 496, 0, -878), + RC(RC_GV_NOTE_NEAR_RUBEE_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 679, 0, -744), + RC(RC_GV_NOTE_NEAR_RUBEE_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 915, 0, 421), + RC(RC_GV_NOTE_NEAR_RUBEE_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 988, 0, 195), + RC(RC_GV_NOTE_NEAR_TURBO_TRAINERS_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 2925, 3426, -6331), + RC(RC_GV_NOTE_NEAR_TURBO_TRAINERS_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 3522, 3403, -6008), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3165, 1378, 7933), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3720, 1390, 8460), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -4276, 1402, 8984), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -4829, 1415, 9510), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -5713, 1379, 9342), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -6046, 1329, 8619), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -6367, 1281, 7928), + RC(RC_GV_NOTE_SAND_NEAR_SPHYNX_8, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -6724, 1233, 7210), + RC(RC_GV_NOTE_SPHYNX_FOOT_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -2776, 1606, 6486), + RC(RC_GV_NOTE_SPHYNX_FOOT_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3035, 1663, 6675), + RC(RC_GV_NOTE_SPHYNX_FOOT_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3048, 1665, 6316), + RC(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -2814, 1605, 5292), + RC(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3083, 1666, 5488), + RC(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3096, 1664, 5106), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3310, 0, -850), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -3317, 0, 748), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -1195, 1592, -50), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 95, 911, -50), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 1295, 274, -50), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 2249, 0, -829), + RC(RC_GV_NOTE_SPHYNX_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 2265, 0, 753), + RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -5, 13, -757), + RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -776, 13, -3), + RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -14, 13, 734), + RC(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 729, 13, -11), + RC(RC_GV_NOTE_WATER_PYRAMID_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -1168, 3324, -3242), + RC(RC_GV_NOTE_WATER_PYRAMID_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, 1214, 3821, -3576), + RC(RC_GV_NOTE_WATER_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -828, 3821, -3580), + RC(RC_GV_NOTE_WATER_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -489, 4316, -4946), + RC(RC_GV_SNS_BLUE_EGG, RCTYPE_STOP_N_SWOP, LEVEL_7_GOBIS_VALLEY, RI_STOP_N_SWOP_EGG_BLUE, SNS_ITEM_EGG_BLUE, 8, 470, -4141), + RC(RC_MM_EMPTY_HONEYCOMB_HILL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_1_MM_HILL, 985, 484, 1681), + RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), + RC(RC_MM_JIGGY_CHIMPY, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_9_MM_CHIMPY, 0, 0, 0), + RC(RC_MM_JIGGY_CONGA, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_A_MM_CONGA, 0, 0, 0), + RC(RC_MM_JIGGY_HILL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_07_MM_HILL, 4335, 1485, 794), + RC(RC_MM_JIGGY_HUTS, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_5_MM_HUTS, 0, 0, 0), + RC(RC_MM_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_01_MM_JINJO, 1702, -41, 2941), + RC(RC_MM_JIGGY_JUJU, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_4_MM_JUJU, 4309, 2374, -1487), + RC(RC_MM_JIGGY_MUMBOS_SKULL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_03_MM_MUMBOS_SKULL, 5580, 2756, -2708), + RC(RC_MM_JIGGY_ORANGE_PADS, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_8_MM_ORANGE_PADS, 0, 0, 0), + RC(RC_MM_JIGGY_RUINS, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_06_MM_RUINS, -3699, 2438, -2113), + RC(RC_MM_JIGGY_TICKERS_TOWER, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_02_MM_TICKERS_TOWER, 373, 4221, -906), + RC(RC_MM_JINJO_BLUE, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, RI_JINJO_BLUE_MUMBOS_MOUNTAIN, NULL, 1702, -125, 2941), + RC(RC_MM_JINJO_GREEN, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, RI_JINJO_GREEN_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, RI_JINJO_ORANGE_MUMBOS_MOUNTAIN, NULL, -3297, 2755, -1421), + RC(RC_MM_JINJO_PINK, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, RI_JINJO_PINK_MUMBOS_MOUNTAIN, NULL, 5876, 299, 2369), + RC(RC_MM_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_1_MUMBOS_MOUNTAIN, RI_JINJO_YELLOW_MUMBOS_MOUNTAIN, NULL, -4060, 1355, 1092), + RC(RC_MM_MOLEHILL_BEAK_BUSTER, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_BEAK_BUSTER, ABILITY_2_BEAK_BUSTER, 3943, 2155, -3422), + RC(RC_MM_MOLEHILL_TALON_TROT, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_TALON_TROT, ABILITY_10_TALON_TROT, -2550, 2255, -1217), + RC(RC_MM_MOLEHILL_USE_EGGS, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_EGGS, ABILITY_6_EGGS, -5926, 200, 6213), + RC(RC_MM_MUMBO_TOKEN_BEHIND_PINK_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_04_MM_BEHIND_PINK_JINJO, 5855, 0, 2169), + RC(RC_MM_MUMBO_TOKEN_BEHIND_RUINS, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_02_MM_BEHIND_RUINS, -4869, 2255, -2506), + RC(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_05_MM_INSIDE_TICKERS_TOWER, -343, 345, -518), + RC(RC_MM_MUMBO_TOKEN_STUMP_NEAR_CONGA, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA, -4431, 475, 6183), + RC(RC_MM_MUMBO_TOKEN_UNDER_RAMP_TO_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_03_MM_UNDER_RAMP_TO_MUMBOS_SKULL, 5150, 2168, -2447), + RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4867, 297, 1766), + RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4782, 298, 1892), + RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4971, 299, 1887), + RC(RC_MM_NOTE_SOUTH_SLOPE_SECOND_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 6430, 500, 1410), + RC(RC_MM_NOTE_SOUTH_SLOPE_SECOND_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 6310, 500, 1536), + RC(RC_MM_NOTE_SOUTH_SLOPE_SECOND_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 6546, 500, 1536), + RC(RC_MM_NOTE_SOUTH_SLOPE_THIRD_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3793, 747, 1471), + RC(RC_MM_NOTE_SOUTH_SLOPE_THIRD_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3974, 747, 1411), + RC(RC_MM_NOTE_SOUTH_SLOPE_THIRD_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3928, 747, 1522), + RC(RC_MM_NOTE_SOUTH_SLOPE_FOURTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5259, 1184, 656), + RC(RC_MM_NOTE_SOUTH_SLOPE_FOURTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5469, 1184, 549), + RC(RC_MM_NOTE_SOUTH_SLOPE_FOURTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5412, 1184, 681), + RC(RC_MM_NOTE_SOUTH_SLOPE_FIFTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3202, 1247, 925), + RC(RC_MM_NOTE_SOUTH_SLOPE_FIFTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3126, 1247, 1014), + RC(RC_MM_NOTE_SOUTH_SLOPE_FIFTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3282, 1247, 1003), + RC(RC_MM_NOTE_SOUTH_SLOPE_SIXTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5860, 1547, 62), + RC(RC_MM_NOTE_SOUTH_SLOPE_SIXTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 6098, 1547, 67), + RC(RC_MM_NOTE_SOUTH_SLOPE_SIXTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5990, 1547, 169), + RC(RC_MM_NOTE_BRIDGE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 2585, -20, 3800), + RC(RC_MM_NOTE_BRIDGE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 2298, -65, 3800), + RC(RC_MM_NOTE_BRIDGE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 2012, -90, 3800), + RC(RC_MM_NOTE_BRIDGE_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 1721, -90, 3800), + RC(RC_MM_NOTE_BRIDGE_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 1441, -90, 3800), + RC(RC_MM_NOTE_BRIDGE_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 1149, -62, 3800), + RC(RC_MM_NOTE_BRIDGE_7, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 854, -8, 3800), + RC(RC_MM_NOTE_NORTH_SLOPE_FIRST_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4497, 393, 2503), + RC(RC_MM_NOTE_NORTH_SLOPE_FIRST_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4583, 393, 2600), + RC(RC_MM_NOTE_NORTH_SLOPE_FIRST_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4417, 393, 2600), + RC(RC_MM_NOTE_NORTH_SLOPE_SECOND_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3730, 782, 1838), + RC(RC_MM_NOTE_NORTH_SLOPE_SECOND_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3776, 782, 1964), + RC(RC_MM_NOTE_NORTH_SLOPE_SECOND_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3624, 782, 1908), + RC(RC_MM_NOTE_NORTH_SLOPE_THIRD_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -5185, 837, 1737), + RC(RC_MM_NOTE_NORTH_SLOPE_THIRD_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -5277, 836, 1850), + RC(RC_MM_NOTE_NORTH_SLOPE_THIRD_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -5099, 836, 1850), + RC(RC_MM_NOTE_NORTH_SLOPE_FOURTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -2962, 1397, 813), + RC(RC_MM_NOTE_NORTH_SLOPE_FOURTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3053, 1397, 905), + RC(RC_MM_NOTE_NORTH_SLOPE_FOURTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -2868, 1397, 890), + RC(RC_MM_NOTE_NORTH_SLOPE_FIFTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -5154, 1489, 462), + RC(RC_MM_NOTE_NORTH_SLOPE_FIFTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -5238, 1489, 560), + RC(RC_MM_NOTE_NORTH_SLOPE_FIFTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -5068, 1489, 560), + RC(RC_MM_NOTE_NORTH_SLOPE_SIXTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4260, 1839, 208), + RC(RC_MM_NOTE_NORTH_SLOPE_SIXTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4342, 1839, 300), + RC(RC_MM_NOTE_NORTH_SLOPE_SIXTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4179, 1839, 300), + RC(RC_MM_NOTE_NORTH_SLOPE_SEVENTH_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3394, 1910, 171), + RC(RC_MM_NOTE_NORTH_SLOPE_SEVENTH_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3469, 1910, 263), + RC(RC_MM_NOTE_NORTH_SLOPE_SEVENTH_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3293, 1910, 247), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1373, 169, 1957), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1431, 346, 1784), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1497, 517, 1621), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1528, 638, 1424), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1523, 742, 1179), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1523, 857, 932), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_7, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1518, 964, 706), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_8, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1413, 1117, 500), + RC(RC_MM_NOTE_NORTH_SLOPE_LOWER_TRAIL_9, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1284, 1295, 363), + RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1094, 1727, -1922), + RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1309, 1856, -1941), + RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1541, 1987, -1960), + RC(RC_MM_NOTE_NORTH_SLOPE_HIGHER_TRAIL_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -1758, 2111, -1974), + RC(RC_MM_NOTE_RUINS_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3047, 2755, -2669), + RC(RC_MM_NOTE_RUINS_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3314, 2755, -2802), + RC(RC_MM_NOTE_RUINS_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3603, 2755, -2923), + RC(RC_MM_NOTE_RUINS_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3885, 2755, -2901), + RC(RC_MM_NOTE_RUINS_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4161, 2755, -2858), + RC(RC_MM_NOTE_RUINS_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4359, 2755, -2682), + RC(RC_MM_NOTE_RUINS_7, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4542, 2755, -2495), + RC(RC_MM_NOTE_RUINS_8, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4599, 2754, -2261), + RC(RC_MM_NOTE_RUINS_9, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4649, 2755, -2009), + RC(RC_MM_NOTE_RUINS_10, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4539, 2755, -1746), + RC(RC_MM_NOTE_RUINS_11, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4416, 2755, -1509), + RC(RC_MM_NOTE_RUINS_12, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -4167, 2755, -1383), + RC(RC_MM_NOTE_RUINS_13, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3892, 2755, -1284), + RC(RC_MM_NOTE_RUINS_14, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3581, 2755, -1359), + RC(RC_MM_NOTE_UNDERWATER_RIGHT_CAVE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 2128, -824, 2181), + RC(RC_MM_NOTE_UNDERWATER_RIGHT_CAVE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 2034, -824, 2158), + RC(RC_MM_NOTE_UNDERWATER_RIGHT_CAVE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 1937, -824, 2136), + RC(RC_MM_NOTE_UNDERWATER_LEFT_CAVE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 1027, -824, 2183), + RC(RC_MM_NOTE_UNDERWATER_LEFT_CAVE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 940, -824, 2223), + RC(RC_MM_NOTE_UNDERWATER_LEFT_CAVE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 850, -824, 2267), + RC(RC_MM_NOTE_HUT_ROOF_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3378, 2439, -2353), + RC(RC_MM_NOTE_HUT_ROOF_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4137, 2439, -2649), + RC(RC_MM_NOTE_HUT_ROOF_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5319, 2439, -1717), + RC(RC_MM_NOTE_HUT_ROOF_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 5025, 2439, -814), + RC(RC_MM_NOTE_HUT_ROOF_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3847, 2439, -715), + RC(RC_MM_NOTE_HUT_ROOF_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 3255, 2438, -1091), + RC(RC_MM_NOTE_HUT_BUNDLE_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_NOTE_HUT_BUNDLE_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_NOTE_HUT_BUNDLE_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_NOTE_HUT_BUNDLE_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_NOTE_HUT_BUNDLE_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -288, 0, -154), + RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -127, 0, -308), + RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 119, 0, -298), + RC(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 286, 0, -155), + RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -74, 817, 19), + RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -3, 817, 52), + RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 67, 817, 0), + RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 60, 817, -87), + RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -10, 817, -125), + RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -80, 817, -71), + RC(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_12_MMM_FLOORBOARD, -51, -135, 52), + RC(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_11_MMM_CHURCH_RAFTERS, 0, 5163, 2400), + RC(RC_MMM_JIGGY_BARREL_INTERIOR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_61_MMM_RAIN_BARREL, 2, 288, -4), + RC(RC_MMM_JIGGY_CELLAR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5E_MMM_CELLAR, -516, 30, 477), + RC(RC_MMM_JIGGY_CEMETARY_POTS, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_63_MMM_FLOWER_POTS, 0, 0, 0), + RC(RC_MMM_JIGGY_CLOCKTOWER_TOP, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5F_MMM_CHURCH_ROOF, -2800, 3175, -1601), + RC(RC_MMM_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5B_MMM_JINJO, 0, 0, 0), + RC(RC_MMM_JIGGY_MANSION_TABLE, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5D_MMM_NAPPER, 1, 511, 24), + RC(RC_MMM_JIGGY_MOTZAND, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_60_MMM_MOTZHAND, 0, 3050, -3200), + RC(RC_MMM_JIGGY_INSIDE_LOGGO, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_64_MMM_LOGGO, -518, 295, -468), + RC(RC_MMM_JIGGY_INSIDE_THE_WELLS_BUCKET, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5C_MMM_WELL, 1, 179, 0), + RC(RC_MMM_JIGGY_TUMBLARS_PUZZLE, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_62_MMM_TUMBLAR, 48, 0, -58), + RC(RC_MMM_JINJO_BLUE, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_BLUE_MAD_MONSTER_MANSION, NULL, 5900, 300, 1050), + RC(RC_MMM_JINJO_GREEN, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_GREEN_MAD_MONSTER_MANSION, NULL, 1437, 2100, 248), + RC(RC_MMM_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_ORANGE_MAD_MONSTER_MANSION, NULL, -4265, 0, 2668), + RC(RC_MMM_JINJO_PINK, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_PINK_MAD_MONSTER_MANSION, NULL, 511, 38, 203), + RC(RC_MMM_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_YELLOW_MAD_MONSTER_MANSION, NULL, -250, 540, 300), + RC(RC_MMM_MUMBO_TOKEN_ALCOVE_CLOCK_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_35_MMM_ALCOVE_CLOCK_TOWER, -2800, 1475, -1363), + RC(RC_MMM_MUMBO_TOKEN_BEHIND_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_38_MMM_BEHIND_CHURCH, -4700, 175, -5149), + RC(RC_MMM_MUMBO_TOKEN_HIDDEN_NEAR_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_33_MMM_HIDDEN_NEAR_FOUNTAIN, 3950, -175, 325), + RC(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3E_MMM_IN_CHIMNEY_INSIDE_DINNING_ROOM, -160, 190, -2599), + RC(RC_MMM_MUMBO_TOKEN_IN_THE_MAZE, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_37_MMM_IN_THE_MAZE, -4250, 0, 352), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_40_MMM_INSIDE_BEDROOM, 696, 0, -397), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_LOGGO, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, RP_MUMBO_TOKEN_INSIDE_LOGGO, 424, 170, 304), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3D_MMM_INSIDE_LOGGO_AND_INSIDE_BARREL_IN_CELLAR, -507, 30, 199), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_WELL, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3F_MMM_INSIDE_WELL, -732, 0, -109), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_WHIPCRACK_IN_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_39_MMM_INSIDE_WHIPCRACK_IN_FOUNTAIN, 5900, -275, 798), + RC(RC_MMM_MUMBO_TOKEN_NEAR_FRONT_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_34_MMM_NEAR_FRONT_TUMBLARS_SHED, 173, 350, -3610), + RC(RC_MMM_MUMBO_TOKEN_NEXT_TO_MAZE_HEDGE_RAMP, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_36_MMM_NEXT_TO_MAZE_HEDGE_RAMP, -1643, 25, -1026), + RC(RC_MMM_MUMBO_TOKEN_IN_LOGGOS_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_41_MMM_SINK_IN_LOGGOS_ROOM, 52, 104, 512), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3A_MMM_TOP_OF_RAFTER_INSIDE_CHURCH, 0, 4806, 341), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3B_MMM_TOP_OF_STOOL_INSIDE_CHURCH, 0, 583, -1300), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3C_MMM_TOP_OF_TUMBLARS_SHED, 1796, 857, -4243), + RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 7150, -275, -3474), + RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 7150, -275, -3325), + RC(RC_MMM_NOTE_AROUND_THE_WELL_EAST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 4200, -275, -3325), + RC(RC_MMM_NOTE_AROUND_THE_WELL_EAST_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 4201, -275, -3475), + RC(RC_MMM_NOTE_BARREL_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -266, 0, 152), + RC(RC_MMM_NOTE_BARREL_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -267, 0, -153), + RC(RC_MMM_NOTE_BARREL_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 0, 0, -310), + RC(RC_MMM_NOTE_BARREL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 270, 0, -154), + RC(RC_MMM_NOTE_BARREL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 268, 0, 152), + RC(RC_MMM_NOTE_BASEMENT_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -375, 300, 1274), + RC(RC_MMM_NOTE_BASEMENT_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -126, 300, 1275), + RC(RC_MMM_NOTE_BASEMENT_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 125, 300, 1275), + RC(RC_MMM_NOTE_BASEMENT_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 375, 300, 1275), + RC(RC_MMM_NOTE_BEDROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 760, 207, -100), + RC(RC_MMM_NOTE_BEDROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 700, 207, -200), + RC(RC_MMM_NOTE_BEDROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 640, 200, -100), + RC(RC_MMM_NOTE_BEDROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 700, 207, 0), + RC(RC_MMM_NOTE_CHAIR_EAST_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 736, 286, -500), + RC(RC_MMM_NOTE_CHAIR_EAST_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 737, 286, 0), + RC(RC_MMM_NOTE_CHAIR_EAST_SIDE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 736, 286, 499), + RC(RC_MMM_NOTE_CHAIR_NORTH_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 11, 286, -1102), + RC(RC_MMM_NOTE_CHAIR_NORTH_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -13, 286, -1751), + RC(RC_MMM_NOTE_CHAIR_WEST_SIDE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -738, 286, 499), + RC(RC_MMM_NOTE_CHAIR_WEST_SIDE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -737, 286, -1), + RC(RC_MMM_NOTE_CHAIR_WEST_SIDE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -738, 286, -499), + RC(RC_MMM_NOTE_CHURCH_ABOVE_THE_ENTRANCE, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2186, 662, -2498), + RC(RC_MMM_NOTE_CHURCH_PEW_NORTHEAST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1625, 690, 816), + RC(RC_MMM_NOTE_CHURCH_PEW_NORTHWEST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -1625, 690, 820), + RC(RC_MMM_NOTE_CHURCH_PEW_SOUTHEAST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1623, 690, 2371), + RC(RC_MMM_NOTE_CHURCH_PEW_SOUTHWEST, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -1623, 690, 2373), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2800, 1063, -2135), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2800, 1063, -2500), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2800, 1063, -2900), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2800, 1063, -3301), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2800, 1063, -3699), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3199, 1060, -2900), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3600, 1057, -2900), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_8, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -4000, 1054, -2900), + RC(RC_MMM_NOTE_CHURCH_ROOFTOP_9, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -4400, 1051, -2900), + RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3148, 2075, -1948), + RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3146, 2075, -1253), + RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2452, 2075, -1948), + RC(RC_MMM_NOTE_CLOCKTOWER_ROOF_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2453, 2075, -1253), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -450, 0, -75), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -438, 195, -336), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -450, 0, 0), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -450, 0, 75), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -440, 150, 337), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -75, 0, 350), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 429, 222, -233), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_8, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 0, 0, 350), + RC(RC_MMM_NOTE_FRONT_WINDOW_ATTIC_9, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 75, 0, 350), + RC(RC_MMM_NOTE_GRASS_BEHIND_THE_MANSION_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -200, 225, -3525), + RC(RC_MMM_NOTE_GRASS_BEHIND_THE_MANSION_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -201, 225, -3700), + RC(RC_MMM_NOTE_GRASS_BEHIND_THE_MANSION_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -200, 225, -3876), + RC(RC_MMM_NOTE_MAIN_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 556, 75, 2111), + RC(RC_MMM_NOTE_MAIN_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 734, 75, 2236), + RC(RC_MMM_NOTE_MAIN_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1266, 75, 2236), + RC(RC_MMM_NOTE_MAIN_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1444, 75, 2110), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_NORTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 2436, 700, -1244), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_NORTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -428, 700, -1249), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_SOUTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 2436, 702, 1743), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_LOWER_SOUTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -428, 700, 1743), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_NORTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1936, 1600, -797), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_NORTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 63, 1600, -796), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_SOUTHEAST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1936, 1600, 1294), + RC(RC_MMM_NOTE_MANSION_EXTERIOR_UPPER_SOUTHWEST_CORNER, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 63, 1600, 1303), + RC(RC_MMM_NOTE_MAZE_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2050, 7, 1755), + RC(RC_MMM_NOTE_MAZE_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -2250, 0, 2655), + RC(RC_MMM_NOTE_MAZE_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3455, 0, 1780), + RC(RC_MMM_NOTE_MAZE_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3455, 0, 1445), + RC(RC_MMM_NOTE_MAZE_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3300, 0, 25), + RC(RC_MMM_NOTE_MAZE_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -3300, 0, -131), + RC(RC_MMM_NOTE_MUMBOS_SKULL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -293, 0, -157), + RC(RC_MMM_NOTE_MUMBOS_SKULL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 294, 0, -157), + RC(RC_MMM_NOTE_ORGAN_PEDALS_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 150, 131, -1698), + RC(RC_MMM_NOTE_ORGAN_PEDALS_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -150, 230, -1693), + RC(RC_MMM_NOTE_ORGAN_PIPES_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -1062, 2450, -3199), + RC(RC_MMM_NOTE_ORGAN_PIPES_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -529, 2750, -3200), + RC(RC_MMM_NOTE_ORGAN_PIPES_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 519, 2750, -3200), + RC(RC_MMM_NOTE_ORGAN_PIPES_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1054, 2450, -3199), + RC(RC_MMM_NOTE_SHED_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -700, 0, 688), + RC(RC_MMM_NOTE_SHED_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -701, 0, -725), + RC(RC_MMM_NOTE_SHED_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 700, 0, -725), + RC(RC_MMM_NOTE_SHED_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 700, 0, 688), + RC(RC_MMM_NOTE_SHED_ROOF_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1575, 988, -4460), + RC(RC_MMM_NOTE_SHED_ROOF_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 1824, 987, -4460), + RC(RC_MMM_NOTE_SHED_ROOF_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 2075, 988, -4460), + RC(RC_MMM_NOTE_SHED_ROOF_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 2325, 988, -4460), + RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 5378, -75, 521), + RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 6428, -75, 529), + RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 6423, -75, 1579), + RC(RC_MMM_NOTE_STAGNANT_FOUNTAIN_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 5372, -75, 1571), + RC(RC_MMM_NOTE_WELL_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -475, 0, -617), + RC(RC_MMM_NOTE_WELL_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -613, 0, 411), + RC(RC_MMM_NOTE_WELL_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -714, 0, 171), + RC(RC_MMM_NOTE_WELL_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, -217, 0, 131), + RC(RC_MMM_NOTE_WELL_INTERIOR_5, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 694, 0, -186), + RC(RC_MMM_NOTE_WELL_INTERIOR_6, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 79, 0, -201), + RC(RC_MMM_NOTE_WELL_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 681, 0, 182), + RC(RC_MMM_SNS_CYAN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_CYAN, SNS_ITEM_EGG_CYAN, 1995, 100, -476), + RC(RC_MMM_SNS_GREEN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_GREEN, SNS_ITEM_EGG_GREEN, 517, 350, -241), + RC(RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_F_RBB_BOAT_HOUSE, 0, 1000, 0), + RC(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_10_RBB_ENGINE_ROOM, 0, 360, 3541), + RC(RC_RBB_JIGGY_BOSS_BOOM_BOX, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_56_RBB_BOSS_BOOM_BOX, 0, 0, 0), + RC(RC_RBB_JIGGY_CAPTAINS_CABIN, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_58_RBB_CAPTAINS_CABIN, -997, 273, 355), + RC(RC_RBB_JIGGY_CRANE_CAGE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_59_RBB_CRANE_CAGE, -4900, 0, 0), + RC(RC_RBB_JIGGY_ENGINE_ROOM, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_5A_RBB_ENGINE_ROOM, 1, 809, -3718), + RC(RC_RBB_JIGGY_FUNNEL, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_55_RBB_FUNNEL, -2006, 2700, -2), + RC(RC_RBB_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_51_RBB_JINJO, 0, 0, 0 ), + RC(RC_RBB_JIGGY_PROPELLOR, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_57_RBB_PROPELLOR, 7750, -2007, 0), + RC(RC_RBB_JIGGY_SNORKEL, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_53_RBB_SNORKEL, 0, 0, 0), + RC(RC_RBB_JIGGY_WAREHOUSE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_52_RBB_WAREHOUSE, 850, 850, -1150), + RC(RC_RBB_JIGGY_WHISTLE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_54_RBB_WHISTLE, 0, 0, 0), + RC(RC_RBB_JINJO_BLUE, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_BLUE_RUSTY_BUCKET_BAY, NULL, -8738, -1253, 4032), + RC(RC_RBB_JINJO_GREEN, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_GREEN_RUSTY_BUCKET_BAY, NULL, 8903, -800, -2894), + RC(RC_RBB_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, NULL, -193, 0, -979), + RC(RC_RBB_JINJO_PINK, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_PINK_RUSTY_BUCKET_BAY, NULL, 7850, -2613, 4026), + RC(RC_RBB_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, NULL, -8615, -1000, -3555), + RC(RC_RBB_MUMBO_TOKEN_TOXIC_WASTE_POND, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_46_RBB_TOXIC_WASTE_POND, -7401, -1000, -3425), + RC(RC_RBB_MUMBO_TOKEN_ON_LIFE_BOAT, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_44_RBB_ON_LIFE_BOAT, 7053, -985, -1672), + RC(RC_RBB_MUMBO_TOKEN_SHIPS_PROW, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_43_RBB_SHIPS_PROW, -6200, 150, 0), + RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_47_RBB_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, 6200, 400, 0), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_SHIPS_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_42_RBB_TOP_OF_SHIPS_CHIMNEY, 1000, 2750, 0), + RC(RC_RBB_MUMBO_TOKEN_FRONT_OF_CHOMPA_LEFT_OF_SHIP, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_45_RBB_FRONT_OF_CHOMPA_LEFT_OF_SHIP, -3299, -457, 3800), + RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_48_RBB_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, -650, 562, -35), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_49_RBB_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, -278, 710, -557), + RC(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4C_RBB_INSIDE_KITCHEN, -771, 238, -293), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BUNK_IN_CABIN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4A_RBB_TOP_OF_BUNK_IN_CABIN, 583, 323, -70), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_50_RBB_TOP_OF_BOX_INSIDE_TNT_ROOM, -435, 300, -435), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4D_RBB_ENGINE_ROOM_LEFT_PIPE, -2450, 1100, -400), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4E_RBB_ENGINE_ROOM_RIGHT_PIPE, 2450, 1100, -400), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_SPINNING_PLATFORM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4F_RBB_ENGINE_ROOM_SPINNING_PLATFORM, -319, 12, 1899), + RC(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4B_RBB_INSIDE_NAVIGATION_ROOM, -656, 0, -222), + RC(RC_RBB_NOTE_ANCHOR_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3500, 449, -501), + RC(RC_RBB_NOTE_ANCHOR_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3499, 449, 499), + RC(RC_RBB_NOTE_ANCHOR_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 4499, 449, -500), + RC(RC_RBB_NOTE_ANCHOR_ROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 4500, 449, 499), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -50, 43, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -384, 164, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -717, 285, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_RAMP_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1050, 406, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -950, 1200, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -650, 1200, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -350, 1200, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_LOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -50, 1200, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -50, 2207, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -350, 2207, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -650, 2207, 0), + RC(RC_RBB_NOTE_BETWEEN_SMOKE_STACKS_BRIDGE_UPPER_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -950, 2207, 0), + RC(RC_RBB_NOTE_BUNK_CABIN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -271, 0, -496), + RC(RC_RBB_NOTE_BUNK_CABIN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -245, 0, 563), + RC(RC_RBB_NOTE_BUNK_CABIN_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 270, 0, -496), + RC(RC_RBB_NOTE_BUNK_CABIN_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 245, 0, 561), + RC(RC_RBB_NOTE_CAPTAINS_CABIN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1020, 0, -315), + RC(RC_RBB_NOTE_CAPTAINS_CABIN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1020, 0, -103), + RC(RC_RBB_NOTE_CAPTAINS_CABIN_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1020, 0, 108), + RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -3039, 1160, -2485), + RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -3370, 1160, -2484), + RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -3038, 1160, -2817), + RC(RC_RBB_NOTE_ENGINE_ROOM_BEHIND_GLASS_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -3374, 1160, -2817), + RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1499, 809, -199), + RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1700, 809, -200), + RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1700, 809, -600), + RC(RC_RBB_NOTE_ENGINE_ROOM_LEFT_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -1499, 809, -601), + RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -200, 809, -2200), + RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -200, 809, -2600), + RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 200, 809, -2600), + RC(RC_RBB_NOTE_ENGINE_ROOM_MIDDLE_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 200, 809, -2200), + RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 1500, 809, -199), + RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 1700, 809, -199), + RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 1700, 809, -600), + RC(RC_RBB_NOTE_ENGINE_ROOM_RIGHT_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 1501, 809, -600), + RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -6755, -800, 2797), + RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -6755, -800, 2150), + RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -6755, -800, 1554), + RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -7128, -800, 1554), + RC(RC_RBB_NOTE_FENCE_NEAR_YELLOW_JINJO_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -7501, -800, 1554), + RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 6950, -1175, 3050), + RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 6950, -1175, 4050), + RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 8750, -1175, 4050), + RC(RC_RBB_NOTE_GRATE_ABOVE_PINK_JINJO_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 8750, -1175, 3050), + RC(RC_RBB_NOTE_JIGGY_CRANE_BASE_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -5199, -200, -2900), + RC(RC_RBB_NOTE_JIGGY_CRANE_BASE_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -4900, -200, -2900), + RC(RC_RBB_NOTE_JIGGY_CRANE_BASE_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -4600, -200, -2900), + RC(RC_RBB_NOTE_KITCHEN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -313, 213, -1046), + RC(RC_RBB_NOTE_KITCHEN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -400, 163, 738), + RC(RC_RBB_NOTE_KITCHEN_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -398, 163, 149), + RC(RC_RBB_NOTE_KITCHEN_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 593, 213, -898), + RC(RC_RBB_NOTE_KITCHEN_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 389, 163, 740), + RC(RC_RBB_NOTE_NAVIGATION_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -270, 0, -719), + RC(RC_RBB_NOTE_NAVIGATION_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -87, 0, -720), + RC(RC_RBB_NOTE_NAVIGATION_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 96, 0, -720), + RC(RC_RBB_NOTE_NAVIGATION_ROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 279, 0, -719), + RC(RC_RBB_NOTE_RAMP_TO_SHIP_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 800, -760, 2751), + RC(RC_RBB_NOTE_RAMP_TO_SHIP_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 800, -667, 2424), + RC(RC_RBB_NOTE_RAMP_TO_SHIP_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 800, -575, 2102), + RC(RC_RBB_NOTE_RAMP_TO_SHIP_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 800, -482, 1775), + RC(RC_RBB_NOTE_RAMP_TO_SHIP_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 800, -389, 1450), + RC(RC_RBB_NOTE_SHIP_BOW_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 7800, -800, -1325), + RC(RC_RBB_NOTE_SHIP_BOW_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 8050, -800, -1001), + RC(RC_RBB_NOTE_SHIP_BOW_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 8149, -799, 300), + RC(RC_RBB_NOTE_SHIP_BOW_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 8149, -799, -300), + RC(RC_RBB_NOTE_SHIP_BOW_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 8050, -800, 1001), + RC(RC_RBB_NOTE_SHIP_BOW_6, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 7800, -800, 1325), + RC(RC_RBB_NOTE_SHIP_STERN_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -3399, 800, -600), + RC(RC_RBB_NOTE_SHIP_STERN_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -3399, 800, 600), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -650, 560, -645), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -630, 175, -419), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -170, 140, -804), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -650, 560, 560), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -236, 105, 316), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_6, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 0, 595, -860), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_7, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 492, 525, -677), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_8, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 593, 105, -105), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 531, 140, 664), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 659, 140, 665), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 530, 140, 520), + RC(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 660, 140, 519), + RC(RC_RBB_NOTE_TNT_CRANE_BASE_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 4500, -200, -2900), + RC(RC_RBB_NOTE_TNT_CRANE_BASE_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 4200, -200, -2900), + RC(RC_RBB_NOTE_TNT_CRANE_BASE_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3900, -200, -2900), + RC(RC_RBB_NOTE_TNT_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -400, 750, 924), + RC(RC_RBB_NOTE_TNT_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -400, 750, 800), + RC(RC_RBB_NOTE_TNT_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -400, 750, 675), + RC(RC_RBB_NOTE_TNT_ROOM_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -400, 750, 550), + RC(RC_RBB_NOTE_TNT_ROOM_5, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -400, 750, 1050), + RC(RC_RBB_NOTE_TOXIC_WASTE_POND_BARREL_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -8144, -969, -2026), + RC(RC_RBB_NOTE_TOXIC_WASTE_POND_BARREL_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -7679, -986, -2363), + RC(RC_RBB_NOTE_TOXIC_WASTE_POND_BARREL_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, -7843, -986, -3205), + RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 785, 650, 1356), + RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 785, 650, 1045), + RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 1005, 650, 1355), + RC(RC_RBB_NOTE_WAREHOUSE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 1005, 650, 1045), + RC(RC_RBB_SNS_RED_EGG, RCTYPE_STOP_N_SWOP, LEVEL_9_RUSTY_BUCKET_BAY, RI_STOP_N_SWOP_EGG_RED, SNS_ITEM_EGG_RED, -7, 113, 164), + RC(RC_SM_EMPTY_HONEYCOMB_COLLIWOBBLE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_17_SM_COLLIWOBBLE, 0, 0, 0), + RC(RC_SM_EMPTY_HONEYCOMB_QUARRIES, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_18_SM_QUARRIES, 0, 0, 0), + RC(RC_SM_EMPTY_HONEYCOMB_STUMP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_13_SM_STUMP, -1400, 99, 4824), + RC(RC_SM_EMPTY_HONEYCOMB_TREE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_16_SM_TREE, -2752, 1299, 37), + RC(RC_SM_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_15_SM_UNDERWATER, -264, -442, -651), + RC(RC_SM_EMPTY_HONEYCOMB_WATERFALL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_14_SM_WATERFALL, -6725, 1300, -1803), + RC(RC_SM_MOLEHILL_ATTACK, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLAW_SWIPE, ABILITY_4_CLAW_SWIPE, 4675, 400, 511), + RC(RC_SM_MOLEHILL_BEAK_BARGE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_BARGE, ABILITY_0_BARGE, 3271, -110, -2673), + RC(RC_SM_MOLEHILL_CAMERA_CONTROL, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CAMERA_CONTROL, ABILITY_3_CAMERA_CONTROL, 2250, -34, 2774 ), + RC(RC_SM_MOLEHILL_CLIMB, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLIMB, ABILITY_5_CLIMB, -1999, 342, -2545), + RC(RC_SM_MOLEHILL_DIVE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_DIVE, ABILITY_F_DIVE, -2336, 302, 973), + RC(RC_SM_MOLEHILL_JUMP, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_FLAP_FLIP, ABILITY_8_FLAP_FLIP, -164, -190, 3313), + RC(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_4_TTC_FLOATING_BOX, 8473, 844, -2684), + RC(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_3_TTC_UNDERWATER, -4303, 46, 115), + RC(RC_TTC_JIGGY_ALCOVE1, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0D_TTC_ALCOVE_1, 2832, 2152, -1797), + RC(RC_TTC_JIGGY_ALCOVE2, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0E_TTC_ALCOVE_2, -5116, 1417, -3915), + RC(RC_TTC_JIGGY_BLUBBER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_14_TTC_BLUBBER, 0, 0, 0), + RC(RC_TTC_JIGGY_JINJO, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0B_TTC_JINJO, 0, 0, 0), + RC(RC_TTC_JIGGY_LIGHTHOUSE, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0C_TTC_LIGHTHOUSE, 479, 8500, -2709), + RC(RC_TTC_JIGGY_LOCKUP, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_13_TTC_LOCKUP, -1575, 2597, -2500), + RC(RC_TTC_JIGGY_NIPPER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_12_TTC_NIPPER, 385, 227, 31), + RC(RC_TTC_JIGGY_POOL, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0F_TTC_POOL, -2760, 2053, -4733), + RC(RC_TTC_JIGGY_RED_X, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_11_TTC_RED_X, 0, 0, 0), + RC(RC_TTC_JIGGY_SANDCASTLE, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_10_TTC_SANDCASTLE, 0, 350, -987), + RC(RC_TTC_JINJO_BLUE, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_BLUE_TREASURE_TROVE_COVE, NULL, -875, 242, 7206), + RC(RC_TTC_JINJO_GREEN, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_GREEN_TREASURE_TROVE_COVE, NULL, -179, 3062, 889), + RC(RC_TTC_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_ORANGE_TREASURE_TROVE_COVE, NULL, -5626, 3112, -2856), + RC(RC_TTC_JINJO_PINK, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_PINK_TREASURE_TROVE_COVE, NULL, 4848, 1340, -240), + RC(RC_TTC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_YELLOW_TREASURE_TROVE_COVE, NULL, -968, 5358, -776), + RC(RC_TTC_MOLEHILL_FLIGHT, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, RI_MOLEHILL_FLIGHT, ABILITY_9_FLIGHT, -288, 2161, 1314), + RC(RC_TTC_MOLEHILL_SHOCK_JUMP, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, RI_MOLEHILL_SHOCK_JUMP, ABILITY_D_SHOCK_JUMP, 2698, 1517, 3338), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_PILLAR_UNDERWATER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0C_TTC_BEHIND_PILLAR_UNDERWATER, 6480, 597, -258), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0A_TTC_BEHIND_LIGHTHOUSE_DOOR, 565, 6917, -2776), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_NIPPER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0F_TTC_BEHIND_NIPPER, -6620, 510, 4621), + RC(RC_TTC_MUMBO_TOKEN_FLOATING_ABOVE_SHOCKJUMP_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0E_TTC_FLOATING_ABOVE_SHOCKJUMP_PAD, 2462, 2217, 2957), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_1, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_07_TTC_INSIDE_LOCKUP_1, -2660, 2447, -6079), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_2, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_08_TTC_INSIDE_LOCKUP_2, -2646, 2447, -6223), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_SALTY_HIPPO, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_06_TTC_INSIDE_SALTY_HIPPO, 610, -412, 31), + RC(RC_TTC_MUMBO_TOKEN_ON_FLOATING_BOX, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0B_TTC_ON_FLOATING_BOX, -783, 745, -3872), + RC(RC_TTC_MUMBO_TOKEN_POND_BOTTOM, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0D_TTC_POND_BOTTOM, -4932, 1122, -1063), + RC(RC_TTC_MUMBO_TOKEN_SALTY_HIPPO_MAST, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_09_TTC_SALTY_HIPPO_MAST, -221, 2029, 929), + RC(RC_TTC_NOTE_BEACH_LOCKUP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4802, 737, -2351), + RC(RC_TTC_NOTE_BEACH_LOCKUP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4730, 737, -2420), + RC(RC_TTC_NOTE_BEACH_LOCKUP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4803, 736, -2444), + RC(RC_TTC_NOTE_BEACH_LOCKUP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4858, 736, -2273), + RC(RC_TTC_NOTE_BEACH_LOCKUP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4783, 737, -2249), + RC(RC_TTC_NOTE_INSIDE_NIPPER_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -127, -22, -1020), + RC(RC_TTC_NOTE_INSIDE_NIPPER_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 643, -22, -723), + RC(RC_TTC_NOTE_INSIDE_NIPPER_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 911, -22, -18), + RC(RC_TTC_NOTE_INSIDE_NIPPER_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 583, -21, 625), + RC(RC_TTC_NOTE_INSIDE_NIPPER_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -78, -21, 800), + RC(RC_TTC_NOTE_INSIDE_NIPPER_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -608, -21, 457), + RC(RC_TTC_NOTE_INSIDE_SHIP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -870, -750, -60), + RC(RC_TTC_NOTE_INSIDE_SHIP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -870, -750, -195), + RC(RC_TTC_NOTE_INSIDE_SHIP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -871, -750, 198), + RC(RC_TTC_NOTE_INSIDE_SHIP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -871, -750, 68), + RC(RC_TTC_NOTE_INSIDE_SHIP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 870, -750, -64), + RC(RC_TTC_NOTE_INSIDE_SHIP_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 870, -746, -197), + RC(RC_TTC_NOTE_INSIDE_SHIP_7, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 870, -698, 200), + RC(RC_TTC_NOTE_INSIDE_SHIP_8, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 870, -750, 61), + RC(RC_TTC_NOTE_JUMP_PAD_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2911, 1667, 1203), + RC(RC_TTC_NOTE_JUMP_PAD_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2911, 1792, 1203), + RC(RC_TTC_NOTE_JUMP_PAD_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2911, 1917, 1203), + RC(RC_TTC_NOTE_LIGHTHOUSE_PATH_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -363, 6087, -2487), + RC(RC_TTC_NOTE_LIGHTHOUSE_PATH_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -455, 6170, -2688), + RC(RC_TTC_NOTE_LIGHTHOUSE_PATH_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -352, 6227, -2895), + RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 563, 8055, -2949), + RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 731, 8056, -2702), + RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 552, 8056, -2465), + RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 269, 8070, -2560), + RC(RC_TTC_NOTE_LIGHTHOUSE_TOP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 275, 8055, -2864), + RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 5447, 1817, 101), + RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 5682, 1817, 444), + RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 6246, 1817, 447), + RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 6244, 1817, -452), + RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 6498, 1817, 39), + RC(RC_TTC_NOTE_PLATEAU_PAST_JUMP_PADS_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 5670, 1817, -372), + RC(RC_TTC_NOTE_SANDCASTLE_TOP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2497, 431, 4437), + RC(RC_TTC_NOTE_SANDCASTLE_TOP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2318, 431, 4609), + RC(RC_TTC_NOTE_SANDCASTLE_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2497, 431, 4609), + RC(RC_TTC_NOTE_SANDCASTLE_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2660, 431, 4609), + RC(RC_TTC_NOTE_SANDCASTLE_TOP_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2497, 431, 4794), + RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -536, -90, 727), + RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -536, -90, 892), + RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 537, -90, 727), + RC(RC_TTC_NOTE_SANDCASTLE_INTERIOR_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 537, -90, 892), + RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1364, 1084, 622), + RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1213, 1276, 665), + RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1055, 1490, 713), + RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -896, 1703, 753), + RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -734, 1915, 773), + RC(RC_TTC_NOTE_SHIP_RIGGING_LEFT_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -569, 2131, 795), + RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 966, 1289, 1138), + RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 788, 1486, 1082), + RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 603, 1702, 1027), + RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 414, 1916, 1000), + RC(RC_TTC_NOTE_SHIP_RIGGING_RIGHT_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 222, 2132, 979), + RC(RC_TTC_NOTE_SHIP_TREE_LEFT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1630, 1291, 2476), + RC(RC_TTC_NOTE_SHIP_TREE_LEFT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1539, 1291, 2621), + RC(RC_TTC_NOTE_SHIP_TREE_LEFT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1681, 1318, 2708), + RC(RC_TTC_NOTE_SHIP_TREE_LEFT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1769, 1321, 2578), + RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 417, 1291, 2891), + RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 448, 1318, 3052), + RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 297, 1321, 3090), + RC(RC_TTC_NOTE_SHIP_TREE_RIGHT_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 251, 1292, 2927), + RC(RC_TTC_NOTE_SPIRAL_PATH_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4656, 817, -6660), + RC(RC_TTC_NOTE_SPIRAL_PATH_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4646, 817, -6864), + RC(RC_TTC_NOTE_SPIRAL_PATH_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4631, 817, -7067), + RC(RC_TTC_NOTE_SPIRAL_PATH_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4499, 817, -7216), + RC(RC_TTC_NOTE_STAIRS_TO_LIGHTHOUSE, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 2070, 2517, -2499), + RC(RC_TTC_NOTE_STAIRSET_FIRST_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 266, 911, -6564), + RC(RC_TTC_NOTE_STAIRSET_FIRST_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 86, 1117, -6563), + RC(RC_TTC_NOTE_STAIRSET_FIRST_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -85, 1313, -6564), + RC(RC_TTC_NOTE_STAIRSET_FIRST_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -263, 1516, -6564), + RC(RC_TTC_NOTE_STAIRSET_SECOND_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -653, 1713, -6370), + RC(RC_TTC_NOTE_STAIRSET_SECOND_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -826, 1913, -6343), + RC(RC_TTC_NOTE_STAIRSET_SECOND_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1001, 2116, -6315), + RC(RC_TTC_NOTE_STAIRSET_SECOND_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1175, 2317, -6288), + RC(RC_TTC_NOTE_STAIRSET_THIRD_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1936, 2528, -6112), + RC(RC_TTC_NOTE_STAIRSET_THIRD_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1854, 2731, -5955), + RC(RC_TTC_NOTE_STAIRSET_THIRD_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1773, 2928, -5803), + RC(RC_TTC_NOTE_STAIRSET_THIRD_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1691, 3130, -5647), + RC(RC_TTC_NOTE_STARTING_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1144, 846, 7476), + RC(RC_TTC_NOTE_STARTING_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -1147, 846, 6935), + RC(RC_TTC_NOTE_STARTING_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -603, 846, 6938), + RC(RC_TTC_NOTE_STARTING_PLATFORM_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -603, 846, 7478), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 688, 1617, 4709), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 700, 1617, 4907), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 713, 1617, 5104), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_4, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2607, 1617, 3019), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_5, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2548, 1617, 3217), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_6, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2488, 1617, 3417), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_7, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -719, 1617, 4183), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_8, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -520, 1617, 4172), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_9, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -319, 1617, 4160), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_10, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2515, 1617, 4735), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_11, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2638, 1617, 4933), + RC(RC_TTC_NOTE_UPPERLEVEL_BRIDGE_NEAR_ENTRANCE_12, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2760, 1617, 5135), + RC(RC_TTC_NOTE_UPPERLEVEL_POOL_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -3235, 1840, -1696), + RC(RC_TTC_NOTE_UPPERLEVEL_POOL_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -3001, 1840, -2007), + RC(RC_TTC_NOTE_UPPERLEVEL_POOL_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, -2906, 1840, -2329), + RC(RC_TTC_SNS_PINK_EGG, RCTYPE_STOP_N_SWOP, LEVEL_2_TREASURE_TROVE_COVE, RI_STOP_N_SWOP_EGG_PINK, SNS_ITEM_EGG_PINK, 0, 1950, 0), }; std::map> multiSpawnCheckMap = { diff --git a/src/port/Rando/StaticData/Items.cpp b/src/port/Rando/StaticData/Items.cpp index 1e33fdbc4..436eb106a 100644 --- a/src/port/Rando/StaticData/Items.cpp +++ b/src/port/Rando/StaticData/Items.cpp @@ -19,19 +19,114 @@ namespace StaticData { // clang-format off std::map Items = { - RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN), - RI(RI_EMPTY_HONEYCOMB, "an", "Empty Honeycomb", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB), - RI(RI_JIGGY, "a", "Jiggy", RITYPE_JIGGY, ACTOR_46_JIGGY), - RI(RI_JINJO_BLUE, "a", "Blue Jinjo", RITYPE_JINJO, ACTOR_60_JINJO_BLUE), - RI(RI_JINJO_GREEN, "a", "Green Jinjo", RITYPE_JINJO, ACTOR_62_JINJO_GREEN), - RI(RI_JINJO_ORANGE, "an", "Orange Jinjo", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE), - RI(RI_JINJO_PINK, "a", "Pink Jinjo", RITYPE_JINJO, ACTOR_61_JINJO_PINK), - RI(RI_JINJO_YELLOW, "a", "Yellow Jinjo", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW), - RI(RI_MOLEHILL, "a", "New Ability", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL), - RI(RI_MUMBO_TOKEN, "a", "Mumbo Token", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN), - RI(RI_MUSIC_NOTE, "a", "Note", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE), - RI(RI_STOP_N_SWOP_EGG, "a", "Mystery Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG), - RI(RI_STOP_N_SWOP_KEY, "a", "Mystery Key", RITYPE_SNS_KEY, ACTOR_25D_ICE_KEY), + RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN, LEVEL_D_CUTSCENE), + RI(RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Empty Honeycomb - BGS", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, "a", "Empty Honeycomb - CC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), + RI(RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Empty Honeycomb - CCW", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, "a", "Empty Honeycomb - FP", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, "a", "Empty Honeycomb - GV", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), + RI(RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Empty Honeycomb - GL", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_6_LAIR), + RI(RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Empty Honeycomb - MMM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Empty Honeycomb - MM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Empty Honeycomb - RBB", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Empty Honeycomb - SM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Empty Honeycomb - TTC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JIGGY_BUBBLEGLOOP_SWAMP, "a", "Jiggy - BGS", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JIGGY_CLANKERS_CAVERN, "a", "Jiggy - CC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JIGGY_CLICK_CLOCK_WOOD, "a", "Jiggy - CCW", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JIGGY_FREEZEEZY_PEAK, "a", "Jiggy - FP", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JIGGY_GOBIS_VALLEY, "a", "Jiggy - GV", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_7_GOBIS_VALLEY), + RI(RI_JIGGY_GRUNTILDAS_LAIR, "a", "Jiggy - GL", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_6_LAIR), + RI(RI_JIGGY_MAD_MONSTER_MANSION, "a", "Jiggy - MMM", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JIGGY_MUMBOS_MOUNTAIN, "a", "Jiggy - MM", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JIGGY_RUSTY_BUCKET_BAY, "a", "Jiggy - RBB", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JIGGY_TREASURE_TROVE_COVE, "a", "Jiggy - TTC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_BLUE_BUBBLEGLOOP_SWAMP, "a", "Blue Jinjo - BGS", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_BLUE_CLANKERS_CAVERN, "a", "Blue Jinjo - CC", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_BLUE_CLICK_CLOCK_WOOD, "a", "Blue Jinjo - CCW", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_BLUE_FREEZEEZY_PEAK, "a", "Blue Jinjo - FP", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_BLUE_GOBIS_VALLEY, "a", "Blue Jinjo - GV", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_BLUE_MAD_MONSTER_MANSION, "a", "Blue Jinjo - MMM", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_BLUE_MUMBOS_MOUNTAIN, "a", "Blue Jinjo - MM", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_BLUE_RUSTY_BUCKET_BAY, "a", "Blue Jinjo - RBB", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_BLUE_TREASURE_TROVE_COVE, "a", "Blue Jinjo - TTC", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_GREEN_BUBBLEGLOOP_SWAMP, "a", "Green Jinjo - BGS", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_GREEN_CLANKERS_CAVERN, "a", "Green Jinjo - CC", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_GREEN_CLICK_CLOCK_WOOD, "a", "Green Jinjo - CCW", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_GREEN_FREEZEEZY_PEAK, "a", "Green Jinjo - FP", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_GREEN_GOBIS_VALLEY, "a", "Green Jinjo - GV", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_GREEN_MAD_MONSTER_MANSION, "a", "Green Jinjo - MMM", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_GREEN_MUMBOS_MOUNTAIN, "a", "Green Jinjo - MM", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_GREEN_RUSTY_BUCKET_BAY, "a", "Green Jinjo - RBB", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_GREEN_TREASURE_TROVE_COVE, "a", "Green Jinjo - TTC", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_ORANGE_BUBBLEGLOOP_SWAMP, "a", "Orange Jinjo - BGS", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_ORANGE_CLANKERS_CAVERN, "a", "Orange Jinjo - CC", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, "a", "Orange Jinjo - CCW", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_ORANGE_FREEZEEZY_PEAK, "a", "Orange Jinjo - FP", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_ORANGE_GOBIS_VALLEY, "a", "Orange Jinjo - GV", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_ORANGE_MAD_MONSTER_MANSION, "a", "Orange Jinjo - MMM", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_ORANGE_MUMBOS_MOUNTAIN, "a", "Orange Jinjo - MM", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, "a", "Orange Jinjo - RBB", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_ORANGE_TREASURE_TROVE_COVE, "a", "Orange Jinjo - TTC", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, "a", "Pink Jinjo - BGS", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_PINK_CLANKERS_CAVERN, "a", "Pink Jinjo - CC", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_PINK_CLICK_CLOCK_WOOD, "a", "Pink Jinjo - CCW", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_PINK_FREEZEEZY_PEAK, "a", "Pink Jinjo - FP", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_PINK_GOBIS_VALLEY, "a", "Pink Jinjo - GV", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_PINK_MAD_MONSTER_MANSION, "a", "Pink Jinjo - MMM", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_PINK_MUMBOS_MOUNTAIN, "a", "Pink Jinjo - MM", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_PINK_RUSTY_BUCKET_BAY, "a", "Pink Jinjo - RBB", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_PINK_TREASURE_TROVE_COVE, "a", "Pink Jinjo - TTC", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, "a", "Yellow Jinjo - BGS", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_YELLOW_CLANKERS_CAVERN, "a", "Yellow Jinjo - CC", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, "a", "Yellow Jinjo - CCW", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_YELLOW_FREEZEEZY_PEAK, "a", "Yellow Jinjo - FP", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_YELLOW_GOBIS_VALLEY, "a", "Yellow Jinjo - GV", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_YELLOW_MAD_MONSTER_MANSION, "a", "Yellow Jinjo - MMM", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_YELLOW_MUMBOS_MOUNTAIN, "a", "Yellow Jinjo - MM", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, "a", "Yellow Jinjo - RBB", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_YELLOW_TREASURE_TROVE_COVE, "a", "Yellow Jinjo - TTC", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MOLEHILL_BARGE, "", "Beak Barge", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_BEAK_BOMB, "", "Beak Bomb", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MOLEHILL_BEAK_BUSTER, "", "Beak Buster", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MOLEHILL_CAMERA_CONTROL, "", "Camera Control", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_CLAW_SWIPE, "", "Claw Swipe", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_CLIMB, "", "Climb", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_DIVE, "", "Dive", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_EGGS, "", "Eggs", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MOLEHILL_FLAP_FLIP, "", "Flap Flip", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_FLIGHT, "", "Flight", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MOLEHILL_SHOCK_JUMP, "", "Shock Jump", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MOLEHILL_TALON_TROT, "", "Talon Trot", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MOLEHILL_TURBO_TALON, "", "Turbo Talon", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_7_GOBIS_VALLEY), + RI(RI_MOLEHILL_WADING_BOOTS, "", "Wading Boots", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MOLEHILL_WONDERWING, "", "Wonderwing", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, "a", "Mumbo Token - BGS", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MUMBO_TOKEN_CLANKERS_CAVERN, "a", "Mumbo Token - CC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, "a", "Mumbo Token - CCW", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_MUMBO_TOKEN_FREEZEEZY_PEAK, "a", "Mumbo Token - FP", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MUMBO_TOKEN_GOBIS_VALLEY, "a", "Mumbo Token - GV", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY), + RI(RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, "a", "Mumbo Token - GL", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_6_LAIR), + RI(RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, "a", "Mumbo Token - MMM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, "a", "Mumbo Token - MM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, "a", "Mumbo Token - RBB", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, "a", "Mumbo Token - TTC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, "a", "Note - BGS", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MUSIC_NOTE_CLANKERS_CAVERN, "a", "Note - CC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, "a", "Note - CCW", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_MUSIC_NOTE_FREEZEEZY_PEAK, "a", "Note - FP", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MUSIC_NOTE_GOBIS_VALLEY, "a", "Note - GV", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY), + RI(RI_MUSIC_NOTE_MAD_MONSTER_MANSION, "a", "Note - MMM", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, "a", "Note - MM", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, "a", "Note - RBB", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_MUSIC_NOTE_TREASURE_TROVE_COVE, "a", "Note - TTC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_STOP_N_SWOP_EGG_BLUE, "a", "Blue Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_7_GOBIS_VALLEY), + RI(RI_STOP_N_SWOP_EGG_CYAN, "a", "Cyan Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_STOP_N_SWOP_EGG_GREEN, "a", "Green Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_STOP_N_SWOP_EGG_PINK, "a", "Pink Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_STOP_N_SWOP_EGG_RED, "a", "Red Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_STOP_N_SWOP_EGG_YELLOW, "a", "Yellow Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_STOP_N_SWOP_ICE_KEY, "an", "Ice Key", RITYPE_SNS_KEY, ACTOR_25D_ICE_KEY, LEVEL_5_FREEZEEZY_PEAK), }; // clang-format on @@ -44,5 +139,14 @@ RandoItemId GetRandoItemByActorId(actor_e actorId) { return RI_UNKNOWN; } +actor_e GetActorIdByRandoItemId(RandoItemId randoItemId) { + for (auto& [itemId, randoStaticItem] : Items) { + if (itemId == randoItemId) { + return (actor_e)randoStaticItem.actorId; + } + } + return ACTOR_1_UNKNOWN; +} + } // namespace StaticData } // namespace Rando \ No newline at end of file diff --git a/src/port/Rando/StaticData/StaticData.h b/src/port/Rando/StaticData/StaticData.h index 9c39b7063..bfb3cb9ff 100644 --- a/src/port/Rando/StaticData/StaticData.h +++ b/src/port/Rando/StaticData/StaticData.h @@ -2,6 +2,7 @@ #define RANDO_STATIC_DATA_H #include +#include #include #include #include "port/Rando/Types.h" @@ -25,7 +26,7 @@ struct RandoStaticCheck { const char* name; RandoCheckType randoCheckType; int32_t worldId; - int32_t actorId; + RandoItemId randoItemId; int32_t collectionId; int32_t posX; int32_t posY; @@ -49,9 +50,11 @@ struct RandoStaticItem { const char* name; RandoItemType randoItemType; int16_t actorId; + int16_t worldId; }; RandoItemId GetRandoItemByActorId(actor_e actorId); +actor_e GetActorIdByRandoItemId(RandoItemId randoItemId); extern std::map Items; @@ -87,6 +90,9 @@ extern std::map Flags; void ModifyRandoInfFlagState(RandoCheckId randoCheckId); +extern std::unordered_map locationNameToEnum; +extern std::unordered_map itemNameToEnum; + } // namespace StaticData } // namespace Rando diff --git a/src/port/Rando/Types.h b/src/port/Rando/Types.h index f5b925d42..2a1deea77 100644 --- a/src/port/Rando/Types.h +++ b/src/port/Rando/Types.h @@ -1247,18 +1247,113 @@ typedef enum { typedef enum { RI_UNKNOWN, - RI_EMPTY_HONEYCOMB, - RI_JIGGY, - RI_JINJO_BLUE, - RI_JINJO_GREEN, - RI_JINJO_ORANGE, - RI_JINJO_PINK, - RI_JINJO_YELLOW, - RI_MOLEHILL, - RI_MUMBO_TOKEN, - RI_MUSIC_NOTE, - RI_STOP_N_SWOP_EGG, - RI_STOP_N_SWOP_KEY, + RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, + RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, + RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, + RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, + RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, + RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, + RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, + RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, + RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, + RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, + RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, + RI_JIGGY_BUBBLEGLOOP_SWAMP, + RI_JIGGY_CLANKERS_CAVERN, + RI_JIGGY_CLICK_CLOCK_WOOD, + RI_JIGGY_FREEZEEZY_PEAK, + RI_JIGGY_GOBIS_VALLEY, + RI_JIGGY_GRUNTILDAS_LAIR, + RI_JIGGY_MAD_MONSTER_MANSION, + RI_JIGGY_MUMBOS_MOUNTAIN, + RI_JIGGY_RUSTY_BUCKET_BAY, + RI_JIGGY_TREASURE_TROVE_COVE, + RI_JINJO_BLUE_BUBBLEGLOOP_SWAMP, + RI_JINJO_BLUE_CLANKERS_CAVERN, + RI_JINJO_BLUE_CLICK_CLOCK_WOOD, + RI_JINJO_BLUE_FREEZEEZY_PEAK, + RI_JINJO_BLUE_GOBIS_VALLEY, + RI_JINJO_BLUE_MAD_MONSTER_MANSION, + RI_JINJO_BLUE_MUMBOS_MOUNTAIN, + RI_JINJO_BLUE_RUSTY_BUCKET_BAY, + RI_JINJO_BLUE_TREASURE_TROVE_COVE, + RI_JINJO_GREEN_BUBBLEGLOOP_SWAMP, + RI_JINJO_GREEN_CLANKERS_CAVERN, + RI_JINJO_GREEN_CLICK_CLOCK_WOOD, + RI_JINJO_GREEN_FREEZEEZY_PEAK, + RI_JINJO_GREEN_GOBIS_VALLEY, + RI_JINJO_GREEN_MAD_MONSTER_MANSION, + RI_JINJO_GREEN_MUMBOS_MOUNTAIN, + RI_JINJO_GREEN_RUSTY_BUCKET_BAY, + RI_JINJO_GREEN_TREASURE_TROVE_COVE, + RI_JINJO_ORANGE_BUBBLEGLOOP_SWAMP, + RI_JINJO_ORANGE_CLANKERS_CAVERN, + RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, + RI_JINJO_ORANGE_FREEZEEZY_PEAK, + RI_JINJO_ORANGE_GOBIS_VALLEY, + RI_JINJO_ORANGE_MAD_MONSTER_MANSION, + RI_JINJO_ORANGE_MUMBOS_MOUNTAIN, + RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, + RI_JINJO_ORANGE_TREASURE_TROVE_COVE, + RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, + RI_JINJO_PINK_CLANKERS_CAVERN, + RI_JINJO_PINK_CLICK_CLOCK_WOOD, + RI_JINJO_PINK_FREEZEEZY_PEAK, + RI_JINJO_PINK_GOBIS_VALLEY, + RI_JINJO_PINK_MAD_MONSTER_MANSION, + RI_JINJO_PINK_MUMBOS_MOUNTAIN, + RI_JINJO_PINK_RUSTY_BUCKET_BAY, + RI_JINJO_PINK_TREASURE_TROVE_COVE, + RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, + RI_JINJO_YELLOW_CLANKERS_CAVERN, + RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, + RI_JINJO_YELLOW_FREEZEEZY_PEAK, + RI_JINJO_YELLOW_GOBIS_VALLEY, + RI_JINJO_YELLOW_MAD_MONSTER_MANSION, + RI_JINJO_YELLOW_MUMBOS_MOUNTAIN, + RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, + RI_JINJO_YELLOW_TREASURE_TROVE_COVE, + RI_MOLEHILL_BARGE, + RI_MOLEHILL_BEAK_BOMB, + RI_MOLEHILL_BEAK_BUSTER, + RI_MOLEHILL_CAMERA_CONTROL, + RI_MOLEHILL_CLAW_SWIPE, + RI_MOLEHILL_CLIMB, + RI_MOLEHILL_DIVE, + RI_MOLEHILL_EGGS, + RI_MOLEHILL_FLAP_FLIP, + RI_MOLEHILL_FLIGHT, + RI_MOLEHILL_SHOCK_JUMP, + RI_MOLEHILL_TALON_TROT, + RI_MOLEHILL_TURBO_TALON, + RI_MOLEHILL_WADING_BOOTS, + RI_MOLEHILL_WONDERWING, + RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, + RI_MUMBO_TOKEN_CLANKERS_CAVERN, + RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, + RI_MUMBO_TOKEN_FREEZEEZY_PEAK, + RI_MUMBO_TOKEN_GOBIS_VALLEY, + RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, + RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, + RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, + RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, + RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, + RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, + RI_MUSIC_NOTE_CLANKERS_CAVERN, + RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, + RI_MUSIC_NOTE_FREEZEEZY_PEAK, + RI_MUSIC_NOTE_GOBIS_VALLEY, + RI_MUSIC_NOTE_MAD_MONSTER_MANSION, + RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, + RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, + RI_MUSIC_NOTE_TREASURE_TROVE_COVE, + RI_STOP_N_SWOP_EGG_BLUE, + RI_STOP_N_SWOP_EGG_CYAN, + RI_STOP_N_SWOP_EGG_GREEN, + RI_STOP_N_SWOP_EGG_PINK, + RI_STOP_N_SWOP_EGG_RED, + RI_STOP_N_SWOP_EGG_YELLOW, + RI_STOP_N_SWOP_ICE_KEY, RI_MAX, } RandoItemId; @@ -1502,7 +1597,6 @@ typedef struct RandoSaveCheck { const char* name; RandoCheckId randoCheckId; RandoItemId randoItemId; - RandoCheckId shuffledCheckId; int32_t randoCollectionId; bool isShuffled; bool obtained; diff --git a/src/port/Save/SaveManager.cpp b/src/port/Save/SaveManager.cpp index 4bd6cb7d9..9adfc1394 100644 --- a/src/port/Save/SaveManager.cpp +++ b/src/port/Save/SaveManager.cpp @@ -74,7 +74,7 @@ static void BitfieldSetNBits(uint8_t* array, int startIndex, int numBits, int va } void RandoSaveCheck_to_json(nlohmann::json& j, const RandoSaveCheck& randoSaveCheck) { - j = nlohmann::json::array({ randoSaveCheck.randoCheckId, randoSaveCheck.randoItemId, randoSaveCheck.shuffledCheckId, + j = nlohmann::json::array({ randoSaveCheck.randoCheckId, randoSaveCheck.randoItemId, randoSaveCheck.randoCollectionId, randoSaveCheck.isShuffled, randoSaveCheck.obtained, randoSaveCheck.skipped }); } @@ -82,11 +82,10 @@ void RandoSaveCheck_to_json(nlohmann::json& j, const RandoSaveCheck& randoSaveCh RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& randoSaveCheck) { j.at(0).get_to(randoSaveCheck.randoCheckId); j.at(1).get_to(randoSaveCheck.randoItemId); - j.at(2).get_to(randoSaveCheck.shuffledCheckId); - j.at(3).get_to(randoSaveCheck.randoCollectionId); - j.at(4).get_to(randoSaveCheck.isShuffled); - j.at(5).get_to(randoSaveCheck.obtained); - j.at(6).get_to(randoSaveCheck.skipped); + j.at(2).get_to(randoSaveCheck.randoCollectionId); + j.at(3).get_to(randoSaveCheck.isShuffled); + j.at(4).get_to(randoSaveCheck.obtained); + j.at(5).get_to(randoSaveCheck.skipped); return randoSaveCheck; } diff --git a/src/port/ShipUtils.cpp b/src/port/ShipUtils.cpp index a0d6ebd23..bc5f6ecbc 100644 --- a/src/port/ShipUtils.cpp +++ b/src/port/ShipUtils.cpp @@ -328,8 +328,18 @@ std::vector worldOpenFlags = { FILEPROG_6E_MMM_PUZZLE_PIECES_PLACED, FILEPROG_72_RBB_PUZZLE_PIECES_PLACED, FILEPROG_76_CCW_PUZZLE_PIECES_PLACED, }; -std::vector levelAbbreviations = { - "MM", "TTC", "CC", "BGS", "FP", "GL", "GV", "CCW", "RBB", "MMM", "SM", +std::unordered_map levelAbbreviations = { + { "MM", "Mumbos Mountain" }, + { "TTC", "Treasure Trove Cove" }, + { "CC", "Clankers Cavern" }, + { "BGS", "Bubblegloop Swamp" }, + { "FP", "Freezeezy Peak" }, + { "GL", "Gruntildas Lair" }, + { "GV", "Gobis Valley" }, + { "CCW", "Click Clock Wood" }, + { "RBB", "Rusty Bucket Bay" }, + { "MMM", "Mad Monster Mansion" }, + { "SM", "Spiral Mountain" }, }; json Ship_RetrieveSaveFile(int32_t filenum) { @@ -351,9 +361,10 @@ json Ship_RetrieveSaveFile(int32_t filenum) { return jsonSave; } -std::string Ship_ConvertEnumToReadableName(const std::string& input) { +std::string Ship_ConvertEnumToReadableName(const std::string& input, bool addPrefix) { std::string result; std::string content = input; + std::string abbreviation = ""; // Step 1: Remove "RC_" prefix if present const std::string prefix = "RC_"; @@ -363,9 +374,10 @@ std::string Ship_ConvertEnumToReadableName(const std::string& input) { // Step 2: Remove level abbreviation if present for (auto& abbr : levelAbbreviations) { - std::string prefix = abbr + "_"; + std::string prefix = abbr.first + "_"; if (content.rfind(prefix, 0) == 0) { content = content.substr(prefix.size()); + abbreviation = abbr.first; break; } } @@ -398,6 +410,14 @@ std::string Ship_ConvertEnumToReadableName(const std::string& input) { } } + // Step 6: Add back full prefix if enabled + if (addPrefix && abbreviation != "") { + auto it = levelAbbreviations.find(abbreviation); + if (it != levelAbbreviations.end()) { + result = it->second + " " + result; + } + } + return result; } diff --git a/src/port/ShipUtils.h b/src/port/ShipUtils.h index cacdcb5eb..f4a2f2fe3 100644 --- a/src/port/ShipUtils.h +++ b/src/port/ShipUtils.h @@ -12,7 +12,7 @@ extern int32_t gSelectedFileNum; using nlohmann::json; json Ship_RetrieveSaveFile(int32_t filenum); -extern std::string Ship_ConvertEnumToReadableName(const std::string& input); +extern std::string Ship_ConvertEnumToReadableName(const std::string& input, bool addPrefix = false); extern std::vector worldOpenFlags; extern std::vector worldNameList; diff --git a/src/port/UI/DeveloperTools/SaveEditor.cpp b/src/port/UI/DeveloperTools/SaveEditor.cpp index 92ed90fd0..f11655557 100644 --- a/src/port/UI/DeveloperTools/SaveEditor.cpp +++ b/src/port/UI/DeveloperTools/SaveEditor.cpp @@ -108,22 +108,23 @@ void SaveEditor_UpdateCheckTracker(RandoSaveCheck randoSaveCheck) { int32_t itemIncr = randoSaveCheck.obtained ? 1 : -1; - switch (randoSaveCheck.randoItemId) { - case RI_JIGGY: + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[randoSaveCheck.randoItemId]; + switch (randoItem.randoItemType) { + case RITYPE_JIGGY: jiggyscore_setCollected(randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, itemIncr); break; - case RI_EMPTY_HONEYCOMB: + case RITYPE_EMPTY_HONEYCOMB: honeycombscore_set((honeycomb_e)randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); break; - case RI_MOLEHILL: + case RITYPE_MOLEHILL: if (randoSaveCheck.obtained) { ability_unlock((ability_e)randoSaveCheck.randoCollectionId); } else { ability_setLearned((ability_e)randoSaveCheck.randoCollectionId, 0); } break; - case RI_MUMBO_TOKEN: + case RITYPE_MUMBO_TOKEN: mumboscore_set((mumbotoken_e)randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); item_adjustByDiffWithoutHud(ITEM_1C_MUMBO_TOKEN, itemIncr); break; @@ -397,9 +398,9 @@ void DrawRandoCheckEditor() { ImGui::TableSetupColumn("shuffled", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("obtained", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("skipped", ImGuiTableColumnFlags_WidthFixed, 34.0f); - ImGui::TableSetupColumn("checkName", ImGuiTableColumnFlags_WidthStretch, 3.5f); - ImGui::TableSetupColumn("itemName", ImGuiTableColumnFlags_WidthStretch, 1.0f); - ImGui::TableSetupColumn("collectionId", ImGuiTableColumnFlags_WidthStretch, 0.5f); + ImGui::TableSetupColumn("checkName", ImGuiTableColumnFlags_WidthFixed, (ImGui::GetContentRegionAvail().x - 34.0f) * 0.60f); + ImGui::TableSetupColumn("itemName", ImGuiTableColumnFlags_WidthFixed, (ImGui::GetContentRegionAvail().x - 34.0f) * 0.25f); + ImGui::TableSetupColumn("collectionId", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableNextColumn(); for (auto& check : RANDO_SAVE_CHECKS) { @@ -444,15 +445,11 @@ void DrawRandoCheckEditor() { ImGui::TextWrapped(checkName.c_str()); ImGui::TableNextColumn(); - if (check.randoItemId == RI_MOLEHILL) { - TableCellCenteredText(abilityNameList[check.randoCollectionId].c_str()); - } else { - TableCellCenteredText(Rando::StaticData::Items[check.randoItemId].name); - } + ImGui::TextWrapped(Rando::StaticData::Items[check.randoItemId].name); ImGui::TableNextColumn(); - if (Rando::StaticData::Checks[check.shuffledCheckId].randoCheckType != RCTYPE_JINJO && - Rando::StaticData::Checks[check.shuffledCheckId].randoCheckType != RCTYPE_MUSIC_NOTE) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[check.randoItemId]; + if (randoItem.randoItemType != RITYPE_JINJO && randoItem.randoItemType != RITYPE_MUSIC_NOTE) { TableCellCenteredText(std::to_string(check.randoCollectionId).c_str()); } ImGui::TableNextColumn(); From 33adc53ec8a7bf5ef76bd6307a6d76289e57194f Mon Sep 17 00:00:00 2001 From: Douglas Simpson Date: Mon, 6 Jul 2026 21:56:07 -0500 Subject: [PATCH 2/8] Fixed Check Tracker to solve slowdown issues (#241) --- src/port/Rando/CheckTracker/CheckTracker.cpp | 17 ++++++++++++++++- src/port/Rando/CheckTracker/CheckTracker.h | 2 ++ src/port/Rando/MiscBehavior/OnFileLoad.cpp | 2 ++ src/port/ShipUtils.cpp | 6 ++++-- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/port/Rando/CheckTracker/CheckTracker.cpp b/src/port/Rando/CheckTracker/CheckTracker.cpp index 4ca2af711..1e231cc64 100644 --- a/src/port/Rando/CheckTracker/CheckTracker.cpp +++ b/src/port/Rando/CheckTracker/CheckTracker.cpp @@ -76,10 +76,13 @@ std::vector> defaultCheckColor { CVAR_NAME_ITEM_COLOR, DEFAULT_ITEM_COLOR, "Obtained Item" }, }; +std::map checkNames; + Rando::StaticData::RandoLogicData reachableRegions[RR_MAX]; Rando::StaticData::RandoLogicData reachableEvents[RA_MAX]; Rando::StaticData::RandoLogicData reachableChecks[RC_MAX]; +bool isCheckTrackerInitialized = false; bool checkTrackerPopoutState = false; ImVec4 checkTrackerBG = ImVec4{ 0, 0, 0, 0.5f }; ImVec4 collectedChecksBG = ImVec4{ 0, 0, 0, 0.5f }; @@ -113,6 +116,13 @@ std::string GetTotalCheckCount() { return totalChecks; } +void CreateCheckStringList() { + checkNames.clear(); + for (auto& entry : Rando::Logic::shuffledPool) { + checkNames.insert({ entry.randoCheckId, Ship_ConvertEnumToReadableName(entry.name) }); + } +} + void UpdateWorldCheckCount(level_e world) { worldCollected = 0; worldTotalShuffled = 0; @@ -165,6 +175,11 @@ void DrawCheckTrackerList() { return; } + if (!isCheckTrackerInitialized) { + CreateCheckStringList(); + isCheckTrackerInitialized = true; + } + if (CVAR_SHOW_COLLECTED_CHECKS && !CVAR_SHOW_SEPARATE_COLLECTED_CHECKS) { DrawCheckTrackerCount(); } @@ -228,7 +243,7 @@ void DrawCheckTrackerList() { } ImGui::BeginGroup(); - ImGui::TextColored(checkTextColor, Ship_ConvertEnumToReadableName(entry.name).c_str()); + ImGui::TextColored(checkTextColor, checkNames.at(entry.randoCheckId).c_str()); if (entry.obtained) { ImGui::SameLine(); RandoItemId randoItemId = Rando::Logic::GetShuffledObject(entry.randoCheckId).randoItemId; diff --git a/src/port/Rando/CheckTracker/CheckTracker.h b/src/port/Rando/CheckTracker/CheckTracker.h index fcc5d558f..543d5cbb6 100644 --- a/src/port/Rando/CheckTracker/CheckTracker.h +++ b/src/port/Rando/CheckTracker/CheckTracker.h @@ -4,6 +4,8 @@ #include "port/Rando/Rando.h" #include +extern bool isCheckTrackerInitialized; + namespace Rando { namespace CheckTracker { diff --git a/src/port/Rando/MiscBehavior/OnFileLoad.cpp b/src/port/Rando/MiscBehavior/OnFileLoad.cpp index 7c7bd5293..e8d8161f9 100644 --- a/src/port/Rando/MiscBehavior/OnFileLoad.cpp +++ b/src/port/Rando/MiscBehavior/OnFileLoad.cpp @@ -7,6 +7,7 @@ #include "port/UI/cvar_prefixes.h" #include "port/Rando/Logic/Logic.h" +#include "port/Rando/CheckTracker/CheckTracker.h" // #include "port/Rando/Spoiler/Spoiler.h" extern "C" { @@ -47,6 +48,7 @@ void Rando::MiscBehavior::OnFileLoad() { REGISTER_LISTENER(OnLoadFileSelect, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnLoadFileSelect* ev = (OnLoadFileSelect*)event; + isCheckTrackerInitialized = false; selectedFileNum = DEFAULT_FILE_NUM; }); } diff --git a/src/port/ShipUtils.cpp b/src/port/ShipUtils.cpp index bc5f6ecbc..1ed80e94a 100644 --- a/src/port/ShipUtils.cpp +++ b/src/port/ShipUtils.cpp @@ -394,8 +394,10 @@ std::string Ship_ConvertEnumToReadableName(const std::string& input, bool addPre for (auto& w : words) { std::transform(w.begin(), w.end(), w.begin(), [](unsigned char c) { return std::tolower(c); }); if (!w.empty()) { - if (w == "hp") { - w = "HP"; + if (w == "rbb") { + w = "RBB"; + } else if (w == "mmm") { + w = "MMM"; } else { w[0] = std::toupper(w[0]); } From 32ff274520fa0ef7c1663b0e0ece27e9c59debac Mon Sep 17 00:00:00 2001 From: Fredomato <86324131+Fredomato@users.noreply.github.com> Date: Wed, 8 Jul 2026 00:58:04 +0100 Subject: [PATCH 3/8] GL warps added to debug (#242) --- src/port/UI/DeveloperTools/GameplayTools.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/port/UI/DeveloperTools/GameplayTools.cpp b/src/port/UI/DeveloperTools/GameplayTools.cpp index d1b7d1af3..11f703de2 100644 --- a/src/port/UI/DeveloperTools/GameplayTools.cpp +++ b/src/port/UI/DeveloperTools/GameplayTools.cpp @@ -124,6 +124,26 @@ std::map> commonWarpMap = { { MAP_44_CCW_SUMMER, { "Click Clock Wood - Summer", 1 } }, { MAP_45_CCW_AUTUMN, { "Click Clock Wood - Autumn", 1 } }, { MAP_46_CCW_WINTER, { "Click Clock Wood - Winter", 1 } }, + { MAP_69_GL_MM_LOBBY, { "Gruntilda's Lair - MM Lobby", 2 } }, + { MAP_6A_GL_TTC_AND_CC_PUZZLE, { "Gruntilda's Lair - TTC and CC Puzzle", 1 } }, + { MAP_6B_GL_180_NOTE_DOOR, { "Gruntilda's Lair - 180 Note Door", 1 } }, + { MAP_6C_GL_RED_CAULDRON_ROOM, { "Gruntilda's Lair - Red Cauldron Room", 1 } }, + { MAP_6D_GL_TTC_LOBBY, { "Gruntilda's Lair - TTC Lobby", 1 } }, + { MAP_6E_GL_GV_LOBBY, { "Gruntilda's Lair - GV Lobby", 1 } }, + { MAP_6F_GL_FP_LOBBY, { "Gruntilda's Lair - FP Lobby", 1 } }, + { MAP_70_GL_CC_LOBBY, { "Gruntilda's Lair - CC Lobby", 1 } }, + { MAP_71_GL_STATUE_ROOM, { "Gruntilda's Lair - Statue Room", 1 } }, + { MAP_72_GL_BGS_LOBBY, { "Gruntilda's Lair - BGS Lobby", 1 } }, + { MAP_74_GL_GV_PUZZLE, { "Gruntilda's Lair - GV Puzzle", 1 } }, + { MAP_75_GL_MMM_LOBBY, { "Gruntilda's Lair - MMM Lobby", 1 } }, + { MAP_76_GL_640_NOTE_DOOR, { "Gruntilda's Lair - 640 Note Door", 1 } }, + { MAP_77_GL_RBB_LOBBY, { "Gruntilda's Lair - RBB Lobby", 1 } }, + { MAP_78_GL_RBB_AND_MMM_PUZZLE, { "Gruntilda's Lair - RBB and MMM Puzzle", 1 } }, + { MAP_79_GL_CCW_LOBBY, { "Gruntilda's Lair - CCW Lobby", 1 } }, + { MAP_7A_GL_CRYPT, { "Gruntilda's Lair - Crypt", 1 } }, + { MAP_80_GL_FF_ENTRANCE, { "Gruntilda's Lair - FF Entrance", 1 } }, + { MAP_8E_GL_FURNACE_FUN, { "Gruntilda's Lair - Furnace Fun", 1 } }, + { MAP_93_GL_DINGPOT, { "Gruntilda's Lair - Dingpot", 0 } }, }; // clang-format off From 2c399190823e8663581819ddd4f553002d25e086 Mon Sep 17 00:00:00 2001 From: Douglas Simpson Date: Tue, 7 Jul 2026 21:02:53 -0500 Subject: [PATCH 4/8] [RANDO] Develop rando v2 extra lives (#244) * Added types and basic functionality * Added checks to regions for logic * Added extra lives to Checks.cpp * Fixed bundle support for extra life in MM and RBB --- src/port/Rando/CustomObject/CustomObject.cpp | 2 + .../CustomObject/CustomObjectSettings.cpp | 2 +- src/port/Rando/LighthouseMenuRando.cpp | 3 + src/port/Rando/Logic/GeneratePools.cpp | 5 + .../Rando/Logic/Regions/BubblegloopSwamp.cpp | 5 + .../Rando/Logic/Regions/ClankersCavern.cpp | 3 + .../Rando/Logic/Regions/ClickClockWood.cpp | 38 ++- .../Rando/Logic/Regions/FreezeezyPeak.cpp | 3 + src/port/Rando/Logic/Regions/GobisValley.cpp | 3 + .../Rando/Logic/Regions/GruntildasLair.cpp | 18 +- .../Rando/Logic/Regions/MadMonsterMansion.cpp | 13 +- .../Rando/Logic/Regions/MumbosMountain.cpp | 4 +- .../Rando/Logic/Regions/RustyBucketBay.cpp | 5 +- .../Rando/Logic/Regions/SpiralMountain.cpp | 2 + .../Rando/Logic/Regions/TreasureTroveCove.cpp | 3 + src/port/Rando/ObjectBehavior/Bundle.cpp | 20 ++ .../Rando/ObjectBehavior/ObjectBehavior.cpp | 7 + src/port/Rando/StaticData/Checks.cpp | 45 ++++ src/port/Rando/StaticData/Items.cpp | 227 +++++++++--------- src/port/Rando/StaticData/Options.cpp | 1 + src/port/Rando/Types.h | 59 +++++ 21 files changed, 337 insertions(+), 131 deletions(-) diff --git a/src/port/Rando/CustomObject/CustomObject.cpp b/src/port/Rando/CustomObject/CustomObject.cpp index 869887707..aa30f92d3 100644 --- a/src/port/Rando/CustomObject/CustomObject.cpp +++ b/src/port/Rando/CustomObject/CustomObject.cpp @@ -46,6 +46,7 @@ extern ActorInfo chJiggy; extern ActorInfo D_80366C80; extern ActorInfo D_803685A0; extern ActorInfo sumusicNote; +extern ActorInfo chExtraLife; extern ActorInfo D_80366CA4; extern ActorInfo D_80367D00; @@ -71,6 +72,7 @@ std::map> actorInfoMap = { { ACTOR_2D_MUMBO_TOKEN, { D_803685A0, ACTOR_FLAG_UNKNOWN_6 } }, { ACTOR_46_JIGGY, { chJiggy, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_47_EMPTY_HONEYCOMB, { D_80366C80, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_49_EXTRA_LIFE, { chExtraLife, ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_51_MUSIC_NOTE, { sumusicNote, ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_5E_JINJO_YELLOW, { chJinjoYellow, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, { ACTOR_5F_JINJO_ORANGE, { chJinjoOrange, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, diff --git a/src/port/Rando/CustomObject/CustomObjectSettings.cpp b/src/port/Rando/CustomObject/CustomObjectSettings.cpp index 0bb5fdb32..a9b52b45e 100644 --- a/src/port/Rando/CustomObject/CustomObjectSettings.cpp +++ b/src/port/Rando/CustomObject/CustomObjectSettings.cpp @@ -143,7 +143,7 @@ void ApplyCustomActorPhysics(RandoCheckId randoCheckId, Actor* actor, bool isJin BundlePhysics physicsData; if ((randoCheckId >= RC_MM_NOTE_HUT_BUNDLE_1 && randoCheckId <= RC_MM_NOTE_HUT_BUNDLE_5) || - randoCheckId == RC_MM_JINJO_GREEN || randoCheckId == RC_MM_JIGGY_HUTS) { + randoCheckId == RC_MM_JINJO_GREEN || randoCheckId == RC_MM_JIGGY_HUTS || randoCheckId == RC_MM_EXTRA_LIFE_HUT) { physicsData = GetPhysicsByCheckId(RC_MM_NOTE_HUT_BUNDLE_1); } else { physicsData = isJinjoJiggy ? jinjoJiggySpawnPhysics : GetPhysicsByCheckId(randoCheckId); diff --git a/src/port/Rando/LighthouseMenuRando.cpp b/src/port/Rando/LighthouseMenuRando.cpp index ee2ab49d7..20d0c09a5 100644 --- a/src/port/Rando/LighthouseMenuRando.cpp +++ b/src/port/Rando/LighthouseMenuRando.cpp @@ -109,6 +109,9 @@ void LighthouseMenu::AddMenuRando() { AddWidget(path, "Shuffle Empty Honeycombs", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_EMPTY_HONEYCOMBS].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Empty Honeycombs into the Pool.")); + AddWidget(path, "Shuffle Extra Lives", WIDGET_CVAR_CHECKBOX) + .CVar(Rando::StaticData::Options[RO_SHUFFLE_EXTRA_LIVES].cvar) + .Options(CheckboxOptions().Tooltip("Shuffles Extra Lives into the Pool.")); AddWidget(path, "Shuffle Jiggies", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_JIGGIES].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Jiggies into the Pool.")); diff --git a/src/port/Rando/Logic/GeneratePools.cpp b/src/port/Rando/Logic/GeneratePools.cpp index 2832273e6..bb1bb4141 100644 --- a/src/port/Rando/Logic/GeneratePools.cpp +++ b/src/port/Rando/Logic/GeneratePools.cpp @@ -51,6 +51,11 @@ void GenerateShufflePool(SaveData* saveData) { continue; } + if (randoStaticCheck.randoCheckType == RCTYPE_EXTRA_LIFE && + CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_EXTRA_LIVES].cvar, 0) == RO_GENERIC_OFF) { + continue; + } + if (randoStaticCheck.randoCheckType == RCTYPE_JIGGY && CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_JIGGIES].cvar, 0) == RO_GENERIC_OFF) { continue; diff --git a/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp b/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp index 48bcf9aca..f0a44225a 100644 --- a/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp +++ b/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp @@ -7,6 +7,8 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_BUBBLEGLOOP_SWAMP] = RandoRegion{ .regionName = "Bubblegloop Swamp", .mapId = MAP_D_BGS_BUBBLEGLOOP_SWAMP, .checks = { + CHECK(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), CHECK(RC_BGS_JIGGY_CROCTUS, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP) && CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_ABILITY(ABILITY_12_WONDERWING)), CHECK(RC_BGS_JIGGY_ELEVATED_WALKWAY, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), CHECK(RC_BGS_JIGGY_FLIBBITS, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_ATTACK), @@ -129,6 +131,9 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_BUBBLEGLOOP_SWAMP_INTERIOR_MR_VILES] = RandoRegion{ .regionName = "Mr. Vile Interior", .mapId = MAP_10_BGS_MR_VILE, .checks = { + CHECK(RC_BGS_EXTRA_LIFE_MR_VILE_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_BGS_EXTRA_LIFE_MR_VILE_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_BGS_EXTRA_LIFE_MR_VILE_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), CHECK(RC_BGS_JIGGY_MR_VILE, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), CHECK(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, true), CHECK(RC_BGS_NOTE_INSIDE_MR_VILES_LEFT_NOSTRIL_1, true), diff --git a/src/port/Rando/Logic/Regions/ClankersCavern.cpp b/src/port/Rando/Logic/Regions/ClankersCavern.cpp index 2eb19c956..fe3aa56f1 100644 --- a/src/port/Rando/Logic/Regions/ClankersCavern.cpp +++ b/src/port/Rando/Logic/Regions/ClankersCavern.cpp @@ -113,6 +113,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_NEAR_CLANKER] = RandoRegion{ .regionName = "Near Clanker", .mapId = MAP_B_CC_CLANKERS_CAVERN, .checks = { CHECK(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, true), + CHECK(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, true), CHECK(RC_CC_JIGGY_BOLT, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_CC_JIGGY_CLANKER_RAISED, true), CHECK(RC_CC_JIGGY_LONG_PIPE, true), @@ -173,6 +174,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_NEAR_CLANKER_UPPER] = RandoRegion{ .regionName = "Upper Area Near Clanker", .mapId = MAP_B_CC_CLANKERS_CAVERN, .checks = { CHECK(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_CC_EXTRA_LIFE_YELLOW_GRATE, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_EXTRA_LIFE_JINJO_PIPE, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), CHECK(RC_CC_JINJO_ORANGE, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), CHECK(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, CAN_ATTACK), CHECK(RC_CC_NOTE_CLIMBABLE_PIPE_1, CAN_ATTACK), diff --git a/src/port/Rando/Logic/Regions/ClickClockWood.cpp b/src/port/Rando/Logic/Regions/ClickClockWood.cpp index a561b8f61..99e5e13ca 100644 --- a/src/port/Rando/Logic/Regions/ClickClockWood.cpp +++ b/src/port/Rando/Logic/Regions/ClickClockWood.cpp @@ -9,6 +9,7 @@ static RegisterShipInitFunc initFunc([]() { .checks = { CHECK(RC_CCW_JIGGY_FLOWER, true), CHECK(RC_CCW_JIGGY_GNAWTY, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_CCW_JINJO_ORANGE, true), CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, true), @@ -87,6 +88,9 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_CLICK_CLOCK_WOOD_AUTUMN_TOP_ROOM] = RandoRegion{ .regionName = "Autumn - Top Room of the Tree", .mapId = MAP_67_CCW_AUTUMN_WHIPCRACK_ROOM, + .checks = { + CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, true), + }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_AUTUMN_UPPER_TREE, true), }, @@ -94,16 +98,17 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_AUTUMN_UPPER_TREE] = RandoRegion{ .regionName = "Autumn - Upper Portion of the Tree", .mapId = MAP_45_CCW_AUTUMN, .checks = { - CHECK(RC_CCW_JIGGY_NABNUT, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_1, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_2, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_3, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_4, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_5, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_6, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_7, true), - CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_8, true), + CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, true), + CHECK(RC_CCW_JIGGY_NABNUT, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_1, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_2, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_3, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_4, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_5, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_6, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_7, true), + CHECK(RC_CCW_NOTE_AUTUMN_EYRIES_NEST_8, true), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_AUTUMN, true), @@ -137,6 +142,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SPRING] = RandoRegion{ .regionName = "Spring Season", .mapId = MAP_43_CCW_SPRING, .checks = { + CHECK(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), + CHECK(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, CAN_USE_ABILITY(ABILITY_12_WONDERWING) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, CAN_USE_ABILITY(ABILITY_12_WONDERWING) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), @@ -199,7 +206,9 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SPRING_TOP_ROOM] = RandoRegion{ .regionName = "Spring - Top Room of the Tree", .mapId = MAP_65_CCW_SPRING_WHIPCRACK_ROOM, .checks = { - CHECK(RC_CCW_JIGGY_TOP_ROOM, true), + CHECK(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, true), + CHECK(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, true), + CHECK(RC_CCW_JIGGY_TOP_ROOM, true), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SPRING_UPPER_TREE, true), @@ -225,6 +234,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SUMMER] = RandoRegion{ .regionName = "Summer Season", .mapId = MAP_44_CCW_SUMMER, .checks = { + CHECK(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, true), CHECK(RC_CCW_JIGGY_SUMMER_LEAF_JUMPS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_CCW_JINJO_YELLOW, true), CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, true), @@ -276,6 +286,9 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_CLICK_CLOCK_WOOD_SUMMER_TOP_ROOM] = RandoRegion{ .regionName = "Summer - Top Room of the Tree", .mapId = MAP_66_CCW_SUMMER_WHIPCRACK_ROOM, + .checks = { + CHECK(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, true) + }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SUMMER_UPPER_TREE, true), }, @@ -283,6 +296,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SUMMER_UPPER_TREE] = RandoRegion{ .regionName = "Summer - Upper Portion of the Tree", .mapId = MAP_44_CCW_SUMMER, .checks = { + CHECK(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, true), CHECK(RC_CCW_JIGGY_HOUSE, true), CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, true), CHECK(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_1, true), @@ -304,6 +318,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_WINTER] = RandoRegion{ .regionName = "Winter Season", .mapId = MAP_46_CCW_WINTER, .checks = { + CHECK(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB)), + CHECK(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_JINJO_BLUE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) || CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, true), diff --git a/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp b/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp index bda06efe3..e6f1e5085 100644 --- a/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp +++ b/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp @@ -57,6 +57,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_INTERIOR_WOZZAS_CAVE] = RandoRegion{ .regionName = "Inside Wozza's Cave", .mapId = MAP_7F_FP_WOZZAS_CAVE, .checks = { + CHECK(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, true), CHECK(RC_FP_JINJO_ORANGE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, true), CHECK(RC_FP_SNS_ICE_KEY, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -68,6 +69,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_MAIN_LOWER] = RandoRegion{ .regionName = "Lower Area near the Snowman", .mapId = MAP_27_FP_FREEZEEZY_PEAK, .checks = { + CHECK(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_FP_JIGGY_BOGGY_RACE_1, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_JIGGY_BOGGY_RACE_2, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), diff --git a/src/port/Rando/Logic/Regions/GobisValley.cpp b/src/port/Rando/Logic/Regions/GobisValley.cpp index 04045bc94..03f0d506c 100644 --- a/src/port/Rando/Logic/Regions/GobisValley.cpp +++ b/src/port/Rando/Logic/Regions/GobisValley.cpp @@ -47,6 +47,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_INTERIOR_MAZE_PYRAMID] = RandoRegion{ .regionName = "Maze Pyramid Interior", .mapId = MAP_14_GV_SANDYBUTTS_MAZE, .checks = { + CHECK(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, true), CHECK(RC_GV_JIGGY_MAZE, true), CHECK(RC_GV_JINJO_PINK, true), CHECK(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, true), @@ -131,6 +132,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_UPPER_AREA] = RandoRegion{ .regionName = "Upper Areas", .mapId = MAP_12_GV_GOBIS_VALLEY, .checks = { + CHECK(RC_GV_EXTRA_LIFE_BEHIND_JINXY, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, true), CHECK(RC_GV_EMPTY_HONEYCOMB_CACTUS, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_GV_JIGGY_ANCIENT_ONES, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_GV_JIGGY_GOBI_1, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), diff --git a/src/port/Rando/Logic/Regions/GruntildasLair.cpp b/src/port/Rando/Logic/Regions/GruntildasLair.cpp index e0b01ffe1..c06fafb0e 100644 --- a/src/port/Rando/Logic/Regions/GruntildasLair.cpp +++ b/src/port/Rando/Logic/Regions/GruntildasLair.cpp @@ -100,6 +100,9 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_BUBBLEGLOOP_SWAMP] = RandoRegion{ .regionName = "Near Bubblegloop Swamp Entrance", .mapId = MAP_72_GL_BGS_LOBBY, + .checks = { + CHECK(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, true), + }, .connections = { CONNECTION(RR_BUBBLEGLOOP_SWAMP, CAN_UNLOCK_WORLD(LEVEL_4_BUBBLEGLOOP_SWAMP)), CONNECTION(RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_260, true), @@ -127,7 +130,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_CLICK_CLOCK_WOOD] = RandoRegion{ .regionName = "Near Click Clock Wood Entrance", .mapId = MAP_79_GL_CCW_LOBBY, .checks = { - CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD, CAN_ACCESS(RA_WITCH_SWITCH_CLICK_CLOCK_WOOD) && CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), + CHECK(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD, CAN_ACCESS(RA_WITCH_SWITCH_CLICK_CLOCK_WOOD) && CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_8_CLICK_CLOCK_WOOD)), @@ -142,9 +146,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_FREEZEEZY_PEAK] = RandoRegion{ .regionName = "Near Freezeezy Peak Entrance", .mapId = MAP_6F_GL_FP_LOBBY, .checks = { - CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, CAN_ACCESS(RA_WITCH_SWITCH_MAD_MONSTER_MANSION) && CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, (CAN_EXTEND_JUMP_DISTANCE || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, CAN_ACCESS(RA_WITCH_SWITCH_MAD_MONSTER_MANSION) && CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, (CAN_EXTEND_JUMP_DISTANCE || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), }, .connections = { CONNECTION(RR_FREEZEEZY_PEAK_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_5_FREEZEEZY_PEAK)), @@ -192,6 +197,9 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_MAD_MONSTER_MANSION] = RandoRegion{ .regionName = "Near Mad Monster Mansion Entrance", .mapId = MAP_75_GL_MMM_LOBBY, + .checks = { + CHECK(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_IRON_GATE)), + }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_GOBIS_VALLEY, true), CONNECTION(RR_GRUNTILDAS_LAIR_WATER_SWITCH_1_ROOM, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_IRON_GATE) && CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), @@ -236,6 +244,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_MAD_MONSTER_MANSION] = RandoRegion{ .regionName = "Near Mad Monster Mansion Puzzle Board", .mapId = MAP_78_GL_RBB_AND_MMM_PUZZLE, .checks = { + CHECK(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, CAN_ACCESS(RA_PUZZLE_BOARD_RUSTY_BUCKET_BAY)), CHECK(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, CAN_EXTEND_JUMP_DISTANCE), }, .connections = { @@ -259,6 +268,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_PAST_NOTE_DOOR_50] = RandoRegion{ .regionName = "Past First Note Door", .mapId = MAP_6A_GL_TTC_AND_CC_PUZZLE, .checks = { + CHECK(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, CAN_ACCESS(RA_WITCH_SWITCH_CLANKERS_CAVERN)), CHECK(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, true), }, diff --git a/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp b/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp index 02b18e728..9ac6b2900 100644 --- a/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp +++ b/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp @@ -60,11 +60,12 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_CHURCH_INTERIOR_UPPER_ORGAN] = RandoRegion{ .regionName = "Church Organ", .mapId = MAP_1C_MMM_CHURCH, .checks = { - CHECK(RC_MMM_JIGGY_MOTZAND, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), - CHECK(RC_MMM_NOTE_ORGAN_PIPES_1, true), - CHECK(RC_MMM_NOTE_ORGAN_PIPES_2, true), - CHECK(RC_MMM_NOTE_ORGAN_PIPES_3, true), - CHECK(RC_MMM_NOTE_ORGAN_PIPES_4, true), + CHECK(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, true), + CHECK(RC_MMM_JIGGY_MOTZAND, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MMM_NOTE_ORGAN_PIPES_1, true), + CHECK(RC_MMM_NOTE_ORGAN_PIPES_2, true), + CHECK(RC_MMM_NOTE_ORGAN_PIPES_3, true), + CHECK(RC_MMM_NOTE_ORGAN_PIPES_4, true), }, .connections = { CONNECTION(RR_MAD_MONSTER_MANSION_CHURCH_INTERIOR, true), @@ -85,6 +86,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_CHURCH_INTERIOR_WINDOW] = RandoRegion{ .regionName = "Church Banjo Kazooie Window", .mapId = MAP_2B_MMM_SECRET_CHURCH_ROOM, .checks = { + CHECK(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, true), }, .connections = { CONNECTION(RR_MAD_MONSTER_MANSION_CHURCH_EXTERIOR, true), @@ -212,6 +214,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_INTERIOR_DINING_ROOM] = RandoRegion{ .regionName = "Dining Room", .mapId = MAP_26_MMM_NAPPERS_ROOM, .checks = { + CHECK(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_MMM_JIGGY_MANSION_TABLE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), CHECK(RC_MMM_NOTE_CHAIR_WEST_SIDE_1, true), diff --git a/src/port/Rando/Logic/Regions/MumbosMountain.cpp b/src/port/Rando/Logic/Regions/MumbosMountain.cpp index 5576b80dc..80ee1c22a 100644 --- a/src/port/Rando/Logic/Regions/MumbosMountain.cpp +++ b/src/port/Rando/Logic/Regions/MumbosMountain.cpp @@ -9,6 +9,7 @@ static RegisterShipInitFunc initFunc([]() { .checks = { CHECK(RC_MM_EMPTY_HONEYCOMB_HILL, true), CHECK(RC_MM_EMPTY_HONEYCOMB_JUJU, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_EXTRA_LIFE_HUT, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), CHECK(RC_MM_JIGGY_CHIMPY, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MM_JIGGY_CONGA, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MM_JIGGY_HILL, true), @@ -161,7 +162,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MUMBOS_MOUNTAIN_TICKERS_TOWER_TOP] = RandoRegion{ .regionName = "Top of Tickers Tower", .mapId = MAP_2_MM_MUMBOS_MOUNTAIN, .checks = { - CHECK(RC_MM_JIGGY_TICKERS_TOWER, true), + CHECK(RC_MM_EXTRA_LIFE_TICKERS_TOWER, true), + CHECK(RC_MM_JIGGY_TICKERS_TOWER, true), }, .connections = { CONNECTION(RR_MUMBOS_MOUNTAIN_ENTRANCE, true), diff --git a/src/port/Rando/Logic/Regions/RustyBucketBay.cpp b/src/port/Rando/Logic/Regions/RustyBucketBay.cpp index 4442ef91b..b015e68d8 100644 --- a/src/port/Rando/Logic/Regions/RustyBucketBay.cpp +++ b/src/port/Rando/Logic/Regions/RustyBucketBay.cpp @@ -166,6 +166,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_ENGINE_ROOM_MAIN] = RandoRegion{ .regionName = "Engine Room Main", .mapId = MAP_34_RBB_ENGINE_ROOM, .checks = { + CHECK(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_RBB_JIGGY_ENGINE_ROOM, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -248,6 +249,7 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_SHIPPING_CONTAINER_THIRD] = RandoRegion{ .regionName = "Shipping Container Third", .mapId = MAP_38_RBB_CONTAINER_3, .checks = { + CHECK(RC_RBB_EXTRA_LIFE_BOOM_BOXES, CAN_ATTACK), CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_1, true), CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_2, true), CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_3, true), @@ -286,7 +288,8 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_WAREHOUSE_UPPER] = RandoRegion{ .regionName = "Warehouse Upper", .mapId = MAP_35_RBB_WAREHOUSE, .checks = { - CHECK(RC_RBB_JIGGY_WAREHOUSE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_EXTRA_LIFE_WAREHOUSE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_JIGGY_WAREHOUSE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), }, .connections = { CONNECTION(RR_RUSTY_BUCKET_BAY_ENTRANCE, true), diff --git a/src/port/Rando/Logic/Regions/SpiralMountain.cpp b/src/port/Rando/Logic/Regions/SpiralMountain.cpp index 0d52a84d6..a7480e7c1 100644 --- a/src/port/Rando/Logic/Regions/SpiralMountain.cpp +++ b/src/port/Rando/Logic/Regions/SpiralMountain.cpp @@ -13,6 +13,8 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_SM_EMPTY_HONEYCOMB_TREE, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_SM_EMPTY_HONEYCOMB_UNDERWATER, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_SM_EMPTY_HONEYCOMB_WATERFALL, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_SM_EXTRA_LIFE_WATERFALL, CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_SM_MOLEHILL_ATTACK, true), CHECK(RC_SM_MOLEHILL_BEAK_BARGE, true), CHECK(RC_SM_MOLEHILL_CAMERA_CONTROL, true), diff --git a/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp b/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp index 40a7a557f..4c9e97753 100644 --- a/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp +++ b/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp @@ -10,6 +10,9 @@ static RegisterShipInitFunc initFunc([]() { // TODO: Logic for Flight because many checks are accessible with flight alone and don't need other methods like Shock Jump if Flight is usable CHECK(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, true), CHECK(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, true), + CHECK(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_TTC_JIGGY_ALCOVE1, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_TTC_JIGGY_ALCOVE2, true), CHECK(RC_TTC_JIGGY_BLUBBER, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), diff --git a/src/port/Rando/ObjectBehavior/Bundle.cpp b/src/port/Rando/ObjectBehavior/Bundle.cpp index 7d4c1fe2f..87f95ac89 100644 --- a/src/port/Rando/ObjectBehavior/Bundle.cpp +++ b/src/port/Rando/ObjectBehavior/Bundle.cpp @@ -18,6 +18,7 @@ void marker_despawn(ActorMarker* marker); bool applyCustomPhysics = false; std::vector bundleDespawnQueue; +int32_t vileCount = 0; void Rando::ObjectBehavior::DespawnCollectedBundles() { if (bundleDespawnQueue.empty()) { @@ -90,6 +91,10 @@ void Rando::ObjectBehavior::InitBundleBehavior() { applyCustomPhysics = true; } break; + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoCheckId = RC_MM_EXTRA_LIFE_HUT; + applyCustomPhysics = true; + break; case BUNDLE_7__JIGGY: randoCheckId = RC_MM_JIGGY_CHIMPY; break; @@ -133,6 +138,14 @@ void Rando::ObjectBehavior::InitBundleBehavior() { break; case LEVEL_4_BUBBLEGLOOP_SWAMP: switch (bundleId) { + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoCheckId = (RandoCheckId)((int32_t)RC_BGS_EXTRA_LIFE_MR_VILE_1 + vileCount); + vileCount++; + applyCustomPhysics = true; + if (vileCount >= 3) { + vileCount = 0; + } + break; case BUNDLE_7__JIGGY: randoCheckId = RC_BGS_JIGGY_CROCTUS; break; @@ -244,6 +257,13 @@ void Rando::ObjectBehavior::InitBundleBehavior() { break; } break; + case LEVEL_9_RUSTY_BUCKET_BAY: + switch (bundleId) { + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoCheckId = RC_RBB_EXTRA_LIFE_BOOM_BOXES; + applyCustomPhysics = true; + break; + } case LEVEL_B_SPIRAL_MOUNTAIN: switch (bundleId) { case BUNDLE_1F_SM_EMPTY_HONEYCOMB: diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index a56b829c4..74b8a92e9 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -31,6 +31,7 @@ std::vector actorSpawnWhitelist = { ACTOR_2D_MUMBO_TOKEN, ACTOR_46_JIGGY, ACTOR_47_EMPTY_HONEYCOMB, + ACTOR_49_EXTRA_LIFE, ACTOR_51_MUSIC_NOTE, ACTOR_5E_JINJO_YELLOW, ACTOR_5F_JINJO_ORANGE, @@ -45,6 +46,7 @@ std::vector actorSpawnWhitelist = { std::map randoItemColors = { { ACTOR_1_UNKNOWN, UIWidgets::Colors::Brown }, { ACTOR_47_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, + { ACTOR_49_EXTRA_LIFE, UIWidgets::Colors::Yellow }, { ACTOR_46_JIGGY, UIWidgets::Colors::Yellow }, { ACTOR_60_JINJO_BLUE, UIWidgets::Colors::SkyBlue }, { ACTOR_62_JINJO_GREEN, UIWidgets::Colors::Green }, @@ -389,6 +391,11 @@ void Rando::ObjectBehavior::Init() { event->Cancelled = true; } break; + case MARKER_61_EXTRA_LIFE: + if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_EXTRA_LIVES].optionValue == RO_GENERIC_ON) { + randoItemId = randoSaveCheck.randoItemId; + } + break; case MARKER_168_ICE_KEY: randoItemId = randoSaveCheck.randoItemId; break; diff --git a/src/port/Rando/StaticData/Checks.cpp b/src/port/Rando/StaticData/Checks.cpp index 870e70a11..433b02b49 100644 --- a/src/port/Rando/StaticData/Checks.cpp +++ b/src/port/Rando/StaticData/Checks.cpp @@ -26,6 +26,11 @@ std::map Checks = { RC(RC_UNKNOWN, RCTYPE_UNKNOWN, LEVEL_D_CUTSCENE, RI_UNKNOWN, NULL, 0, 0, 0), RC(RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_7_BGS_MUMBOS, 0, 600, 0), RC(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_8_BGS_TANKTUP, 0, 537, -1157), + RC(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, -4382, 985, 2799), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_1, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_2, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_3, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 7149, 0, -4353), RC(RC_BGS_JIGGY_CROCTUS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_22_CROCTUS, 0, 0, 0), RC(RC_BGS_JIGGY_ELEVATED_WALKWAY, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_20_BGS_ELEVATED_WALKWAY, 0, 0, 0), RC(RC_BGS_JIGGY_FLIBBITS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_24_BGS_FLIBBITS, 0, 0, 0), @@ -154,6 +159,9 @@ std::map Checks = { RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3114, 93, -86), RC(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_6_CC_ABOVE_WATER, 7886, 4272, 1969), RC(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_5_CC_UNDERWATER, 3718, 3311, 2519), + RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 4570, 3727, 2783), + RC(RC_CC_EXTRA_LIFE_JINJO_PIPE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 7309, 4267, 2286), + RC(RC_CC_EXTRA_LIFE_YELLOW_GRATE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 1752, 5270, -2214), RC(RC_CC_JIGGY_BOLT, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_18_CC_BOLT, 90, 5962, -12), RC(RC_CC_JIGGY_CLANKER_RAISED, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_17_CC_CLANKER_RAISED, 0, 0, 0), RC(RC_CC_JIGGY_FAST_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1E_CC_FAST_SAWBLADES, 0, -340, -1604), @@ -277,6 +285,18 @@ std::map Checks = { RC(RC_CC_NOTE_YELLOW_GRATE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5270, 5261, -2937), RC(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_D_CCW_GNAWTYS, 694, 998, 632), RC(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_E_CCW_NABNUTS, 640, 513, -202), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -225, 640, 506), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 4050, 4284, 1010), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -310, 730, -856), + RC(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -4993, 2896, -944), + RC(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 5100, 425, 0), + RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -693, 2, 528), + RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -310, 730, -855), + RC(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3604, 22, -4012), + RC(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 5848, 4244, 612), + RC(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 833, 441, 133), + RC(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -3157, 300, -3149), + RC(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3078, -338, 3076), RC(RC_CCW_JIGGY_EYRIE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_49_CCW_EYRIE, 0, 0, 0), RC(RC_CCW_JIGGY_FLOWER, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4D_CCW_FLOWER, 0, 0, 0), RC(RC_CCW_JIGGY_GNAWTY, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4B_CCW_GNAWTY, 240, 600, 75), @@ -420,6 +440,9 @@ std::map Checks = { RC(RC_CCW_SNS_YELLOW_EGG, RCTYPE_STOP_N_SWOP, LEVEL_8_CLICK_CLOCK_WOOD, RI_STOP_N_SWOP_EGG_YELLOW, SNS_ITEM_EGG_YELLOW, 556, 150, 47), RC(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_A_FP_SIR_SLUSH, 4295, 441, 1268), RC(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_9_FP_WOZZAS_CAVE, -6531, 135, 422), + RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, 6992, 1390, -3159), + RC(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -4450, 1591, -7407), + RC(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -7322, 0, 391), RC(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_31_FP_SIR_SLUSH, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_1, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_30_FP_BOGGY_2, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_2, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2C_FP_BOGGY_3, 0, 0 ,0), @@ -547,6 +570,12 @@ std::map Checks = { RC(RC_FP_NOTE_SNOWMAN_SCARF_18, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -941, 5605, 844), RC(RC_FP_NOTE_SNOWMAN_SCARF_19, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 17, 5605, 266), RC(RC_FP_SNS_ICE_KEY, RCTYPE_STOP_N_SWOP, LEVEL_5_FREEZEEZY_PEAK, RI_STOP_N_SWOP_ICE_KEY, SNS_ITEM_ICE_KEY, 1567, 583, 2416), + RC(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 0, 1600, -3700), + RC(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -1992, 878, -3052), + RC(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 2954, 1247, 100), + RC(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -8689, -1781, -3192), + RC(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 3599, -478, 2424), + RC(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -838, 1950, 835), RC(RC_GL_JIGGY_LOBBY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_33_LAIR_1ST_JIGGY, -1505, 600, 123), RC(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_37_LAIR_BGS_WITCH_SWITCH, 0, 0, -20), RC(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_35_LAIR_CC_WITCH_SWITCH, 0, 75, 156), @@ -569,6 +598,9 @@ std::map Checks = { RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), RC(RC_GV_EMPTY_HONEYCOMB_CACTUS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_B_GV_CACTUS, 2911, 3292, -3307), RC(RC_GV_EMPTY_HONEYCOMB_GOBI, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_C_GV_GOBI_3, -6885, 2383, 1335), + RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -8948, 1332, 5500), + RC(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, 1282, 18, 1971), + RC(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -230, 4820, -4421), RC(RC_GV_JIGGY_ANCIENT_ONES, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_46_GV_ANCIENT_ONES, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_1, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_44_GV_GOBI_1, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_2, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_45_GV_GOBI_2, 0, 0, 0), @@ -698,6 +730,8 @@ std::map Checks = { RC(RC_GV_SNS_BLUE_EGG, RCTYPE_STOP_N_SWOP, LEVEL_7_GOBIS_VALLEY, RI_STOP_N_SWOP_EGG_BLUE, SNS_ITEM_EGG_BLUE, 8, 470, -4141), RC(RC_MM_EMPTY_HONEYCOMB_HILL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_1_MM_HILL, 985, 484, 1681), RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), + RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_EXTRA_LIFE_TICKERS_TOWER, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 223, 3563, -382), RC(RC_MM_JIGGY_CHIMPY, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_9_MM_CHIMPY, 0, 0, 0), RC(RC_MM_JIGGY_CONGA, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_A_MM_CONGA, 0, 0, 0), RC(RC_MM_JIGGY_HILL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_07_MM_HILL, 4335, 1485, 794), @@ -823,6 +857,9 @@ std::map Checks = { RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -80, 817, -71), RC(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_12_MMM_FLOORBOARD, -51, -135, 52), RC(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_11_MMM_CHURCH_RAFTERS, 0, 5163, 2400), + RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, -1, 2263, -3465), + RC(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 13, 6), + RC(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 1326, 145), RC(RC_MMM_JIGGY_BARREL_INTERIOR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_61_MMM_RAIN_BARREL, 2, 288, -4), RC(RC_MMM_JIGGY_CELLAR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5E_MMM_CELLAR, -516, 30, 477), RC(RC_MMM_JIGGY_CEMETARY_POTS, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_63_MMM_FLOWER_POTS, 0, 0, 0), @@ -958,6 +995,9 @@ std::map Checks = { RC(RC_MMM_SNS_GREEN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_GREEN, SNS_ITEM_EGG_GREEN, 517, 350, -241), RC(RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_F_RBB_BOAT_HOUSE, 0, 1000, 0), RC(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_10_RBB_ENGINE_ROOM, 0, 360, 3541), + RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -626, 140, -351), + RC(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -2551, 1065, -2650), + RC(RC_RBB_EXTRA_LIFE_WAREHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -950, 1045, -50), RC(RC_RBB_JIGGY_BOSS_BOOM_BOX, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_56_RBB_BOSS_BOOM_BOX, 0, 0, 0), RC(RC_RBB_JIGGY_CAPTAINS_CABIN, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_58_RBB_CAPTAINS_CABIN, -997, 273, 355), RC(RC_RBB_JIGGY_CRANE_CAGE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_59_RBB_CRANE_CAGE, -4900, 0, 0), @@ -1095,6 +1135,8 @@ std::map Checks = { RC(RC_SM_EMPTY_HONEYCOMB_TREE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_16_SM_TREE, -2752, 1299, 37), RC(RC_SM_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_15_SM_UNDERWATER, -264, -442, -651), RC(RC_SM_EMPTY_HONEYCOMB_WATERFALL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_14_SM_WATERFALL, -6725, 1300, -1803), + RC(RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, NULL, 3656, 339, 6552), + RC(RC_SM_EXTRA_LIFE_WATERFALL, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, NULL, -7108, 1200, -3079), RC(RC_SM_MOLEHILL_ATTACK, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLAW_SWIPE, ABILITY_4_CLAW_SWIPE, 4675, 400, 511), RC(RC_SM_MOLEHILL_BEAK_BARGE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_BARGE, ABILITY_0_BARGE, 3271, -110, -2673), RC(RC_SM_MOLEHILL_CAMERA_CONTROL, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CAMERA_CONTROL, ABILITY_3_CAMERA_CONTROL, 2250, -34, 2774 ), @@ -1103,6 +1145,9 @@ std::map Checks = { RC(RC_SM_MOLEHILL_JUMP, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_FLAP_FLIP, ABILITY_8_FLAP_FLIP, -164, -190, 3313), RC(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_4_TTC_FLOATING_BOX, 8473, 844, -2684), RC(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_3_TTC_UNDERWATER, -4303, 46, 115), + RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, -2442, 3158, -1706), + RC(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 5864, 677, 7898), + RC(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 4710, 323, -6007), RC(RC_TTC_JIGGY_ALCOVE1, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0D_TTC_ALCOVE_1, 2832, 2152, -1797), RC(RC_TTC_JIGGY_ALCOVE2, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0E_TTC_ALCOVE_2, -5116, 1417, -3915), RC(RC_TTC_JIGGY_BLUBBER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_14_TTC_BLUBBER, 0, 0, 0), diff --git a/src/port/Rando/StaticData/Items.cpp b/src/port/Rando/StaticData/Items.cpp index 436eb106a..e6f68467a 100644 --- a/src/port/Rando/StaticData/Items.cpp +++ b/src/port/Rando/StaticData/Items.cpp @@ -19,114 +19,125 @@ namespace StaticData { // clang-format off std::map Items = { - RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN, LEVEL_D_CUTSCENE), - RI(RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Empty Honeycomb - BGS", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, "a", "Empty Honeycomb - CC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), - RI(RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Empty Honeycomb - CCW", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, "a", "Empty Honeycomb - FP", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, "a", "Empty Honeycomb - GV", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), - RI(RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Empty Honeycomb - GL", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_6_LAIR), - RI(RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Empty Honeycomb - MMM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Empty Honeycomb - MM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Empty Honeycomb - RBB", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Empty Honeycomb - SM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Empty Honeycomb - TTC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_JIGGY_BUBBLEGLOOP_SWAMP, "a", "Jiggy - BGS", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_JIGGY_CLANKERS_CAVERN, "a", "Jiggy - CC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_3_CLANKERS_CAVERN), - RI(RI_JIGGY_CLICK_CLOCK_WOOD, "a", "Jiggy - CCW", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_JIGGY_FREEZEEZY_PEAK, "a", "Jiggy - FP", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_JIGGY_GOBIS_VALLEY, "a", "Jiggy - GV", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_7_GOBIS_VALLEY), - RI(RI_JIGGY_GRUNTILDAS_LAIR, "a", "Jiggy - GL", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_6_LAIR), - RI(RI_JIGGY_MAD_MONSTER_MANSION, "a", "Jiggy - MMM", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_JIGGY_MUMBOS_MOUNTAIN, "a", "Jiggy - MM", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_JIGGY_RUSTY_BUCKET_BAY, "a", "Jiggy - RBB", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_JIGGY_TREASURE_TROVE_COVE, "a", "Jiggy - TTC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_JINJO_BLUE_BUBBLEGLOOP_SWAMP, "a", "Blue Jinjo - BGS", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_JINJO_BLUE_CLANKERS_CAVERN, "a", "Blue Jinjo - CC", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_3_CLANKERS_CAVERN), - RI(RI_JINJO_BLUE_CLICK_CLOCK_WOOD, "a", "Blue Jinjo - CCW", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_JINJO_BLUE_FREEZEEZY_PEAK, "a", "Blue Jinjo - FP", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_JINJO_BLUE_GOBIS_VALLEY, "a", "Blue Jinjo - GV", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_7_GOBIS_VALLEY), - RI(RI_JINJO_BLUE_MAD_MONSTER_MANSION, "a", "Blue Jinjo - MMM", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_JINJO_BLUE_MUMBOS_MOUNTAIN, "a", "Blue Jinjo - MM", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_JINJO_BLUE_RUSTY_BUCKET_BAY, "a", "Blue Jinjo - RBB", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_JINJO_BLUE_TREASURE_TROVE_COVE, "a", "Blue Jinjo - TTC", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_JINJO_GREEN_BUBBLEGLOOP_SWAMP, "a", "Green Jinjo - BGS", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_JINJO_GREEN_CLANKERS_CAVERN, "a", "Green Jinjo - CC", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_3_CLANKERS_CAVERN), - RI(RI_JINJO_GREEN_CLICK_CLOCK_WOOD, "a", "Green Jinjo - CCW", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_JINJO_GREEN_FREEZEEZY_PEAK, "a", "Green Jinjo - FP", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_JINJO_GREEN_GOBIS_VALLEY, "a", "Green Jinjo - GV", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_7_GOBIS_VALLEY), - RI(RI_JINJO_GREEN_MAD_MONSTER_MANSION, "a", "Green Jinjo - MMM", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_JINJO_GREEN_MUMBOS_MOUNTAIN, "a", "Green Jinjo - MM", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_JINJO_GREEN_RUSTY_BUCKET_BAY, "a", "Green Jinjo - RBB", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_JINJO_GREEN_TREASURE_TROVE_COVE, "a", "Green Jinjo - TTC", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_JINJO_ORANGE_BUBBLEGLOOP_SWAMP, "a", "Orange Jinjo - BGS", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_JINJO_ORANGE_CLANKERS_CAVERN, "a", "Orange Jinjo - CC", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_3_CLANKERS_CAVERN), - RI(RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, "a", "Orange Jinjo - CCW", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_JINJO_ORANGE_FREEZEEZY_PEAK, "a", "Orange Jinjo - FP", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_JINJO_ORANGE_GOBIS_VALLEY, "a", "Orange Jinjo - GV", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_7_GOBIS_VALLEY), - RI(RI_JINJO_ORANGE_MAD_MONSTER_MANSION, "a", "Orange Jinjo - MMM", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_JINJO_ORANGE_MUMBOS_MOUNTAIN, "a", "Orange Jinjo - MM", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, "a", "Orange Jinjo - RBB", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_JINJO_ORANGE_TREASURE_TROVE_COVE, "a", "Orange Jinjo - TTC", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, "a", "Pink Jinjo - BGS", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_JINJO_PINK_CLANKERS_CAVERN, "a", "Pink Jinjo - CC", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_3_CLANKERS_CAVERN), - RI(RI_JINJO_PINK_CLICK_CLOCK_WOOD, "a", "Pink Jinjo - CCW", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_JINJO_PINK_FREEZEEZY_PEAK, "a", "Pink Jinjo - FP", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_JINJO_PINK_GOBIS_VALLEY, "a", "Pink Jinjo - GV", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_7_GOBIS_VALLEY), - RI(RI_JINJO_PINK_MAD_MONSTER_MANSION, "a", "Pink Jinjo - MMM", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_JINJO_PINK_MUMBOS_MOUNTAIN, "a", "Pink Jinjo - MM", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_JINJO_PINK_RUSTY_BUCKET_BAY, "a", "Pink Jinjo - RBB", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_JINJO_PINK_TREASURE_TROVE_COVE, "a", "Pink Jinjo - TTC", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, "a", "Yellow Jinjo - BGS", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_JINJO_YELLOW_CLANKERS_CAVERN, "a", "Yellow Jinjo - CC", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_3_CLANKERS_CAVERN), - RI(RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, "a", "Yellow Jinjo - CCW", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_JINJO_YELLOW_FREEZEEZY_PEAK, "a", "Yellow Jinjo - FP", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_JINJO_YELLOW_GOBIS_VALLEY, "a", "Yellow Jinjo - GV", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_7_GOBIS_VALLEY), - RI(RI_JINJO_YELLOW_MAD_MONSTER_MANSION, "a", "Yellow Jinjo - MMM", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_JINJO_YELLOW_MUMBOS_MOUNTAIN, "a", "Yellow Jinjo - MM", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, "a", "Yellow Jinjo - RBB", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_JINJO_YELLOW_TREASURE_TROVE_COVE, "a", "Yellow Jinjo - TTC", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_MOLEHILL_BARGE, "", "Beak Barge", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_MOLEHILL_BEAK_BOMB, "", "Beak Bomb", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_MOLEHILL_BEAK_BUSTER, "", "Beak Buster", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_MOLEHILL_CAMERA_CONTROL, "", "Camera Control", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_MOLEHILL_CLAW_SWIPE, "", "Claw Swipe", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_MOLEHILL_CLIMB, "", "Climb", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_MOLEHILL_DIVE, "", "Dive", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_MOLEHILL_EGGS, "", "Eggs", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_MOLEHILL_FLAP_FLIP, "", "Flap Flip", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_MOLEHILL_FLIGHT, "", "Flight", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_MOLEHILL_SHOCK_JUMP, "", "Shock Jump", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_MOLEHILL_TALON_TROT, "", "Talon Trot", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_MOLEHILL_TURBO_TALON, "", "Turbo Talon", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_7_GOBIS_VALLEY), - RI(RI_MOLEHILL_WADING_BOOTS, "", "Wading Boots", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_MOLEHILL_WONDERWING, "", "Wonderwing", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_3_CLANKERS_CAVERN), - RI(RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, "a", "Mumbo Token - BGS", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_MUMBO_TOKEN_CLANKERS_CAVERN, "a", "Mumbo Token - CC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN), - RI(RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, "a", "Mumbo Token - CCW", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_MUMBO_TOKEN_FREEZEEZY_PEAK, "a", "Mumbo Token - FP", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_MUMBO_TOKEN_GOBIS_VALLEY, "a", "Mumbo Token - GV", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY), - RI(RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, "a", "Mumbo Token - GL", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_6_LAIR), - RI(RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, "a", "Mumbo Token - MMM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, "a", "Mumbo Token - MM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, "a", "Mumbo Token - RBB", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, "a", "Mumbo Token - TTC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, "a", "Note - BGS", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_MUSIC_NOTE_CLANKERS_CAVERN, "a", "Note - CC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN), - RI(RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, "a", "Note - CCW", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_MUSIC_NOTE_FREEZEEZY_PEAK, "a", "Note - FP", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_MUSIC_NOTE_GOBIS_VALLEY, "a", "Note - GV", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY), - RI(RI_MUSIC_NOTE_MAD_MONSTER_MANSION, "a", "Note - MMM", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, "a", "Note - MM", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, "a", "Note - RBB", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_MUSIC_NOTE_TREASURE_TROVE_COVE, "a", "Note - TTC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_STOP_N_SWOP_EGG_BLUE, "a", "Blue Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_7_GOBIS_VALLEY), - RI(RI_STOP_N_SWOP_EGG_CYAN, "a", "Cyan Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_STOP_N_SWOP_EGG_GREEN, "a", "Green Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_STOP_N_SWOP_EGG_PINK, "a", "Pink Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_STOP_N_SWOP_EGG_RED, "a", "Red Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_STOP_N_SWOP_EGG_YELLOW, "a", "Yellow Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_STOP_N_SWOP_ICE_KEY, "an", "Ice Key", RITYPE_SNS_KEY, ACTOR_25D_ICE_KEY, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN, LEVEL_D_CUTSCENE), + RI(RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Empty Honeycomb - BGS", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, "a", "Empty Honeycomb - CC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), + RI(RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Empty Honeycomb - CCW", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, "a", "Empty Honeycomb - FP", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, "a", "Empty Honeycomb - GV", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), + RI(RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Empty Honeycomb - GL", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_6_LAIR), + RI(RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Empty Honeycomb - MMM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Empty Honeycomb - MM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Empty Honeycomb - RBB", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Empty Honeycomb - SM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Empty Honeycomb - TTC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, "an", "Extra Life - BGS", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_EXTRA_LIFE_CLANKERS_CAVERN, "an", "Extra Life - CC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, "an", "Extra Life - CCW", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_EXTRA_LIFE_FREEZEEZY_PEAK, "an", "Extra Life - FP", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_EXTRA_LIFE_GOBIS_VALLEY, "an", "Extra Life - GV", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY), + RI(RI_EXTRA_LIFE_GRUNTILDAS_LAIR, "an", "Extra Life - GL", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_6_LAIR), + RI(RI_EXTRA_LIFE_MAD_MONSTER_MANSION, "an", "Extra Life - MMM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, "an", "Extra Life - MM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, "an", "Extra Life - RBB", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, "an", "Extra Life - SM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_EXTRA_LIFE_TREASURE_TROVE_COVE, "an", "Extra Life - TTC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JIGGY_BUBBLEGLOOP_SWAMP, "a", "Jiggy - BGS", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JIGGY_CLANKERS_CAVERN, "a", "Jiggy - CC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JIGGY_CLICK_CLOCK_WOOD, "a", "Jiggy - CCW", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JIGGY_FREEZEEZY_PEAK, "a", "Jiggy - FP", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JIGGY_GOBIS_VALLEY, "a", "Jiggy - GV", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_7_GOBIS_VALLEY), + RI(RI_JIGGY_GRUNTILDAS_LAIR, "a", "Jiggy - GL", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_6_LAIR), + RI(RI_JIGGY_MAD_MONSTER_MANSION, "a", "Jiggy - MMM", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JIGGY_MUMBOS_MOUNTAIN, "a", "Jiggy - MM", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JIGGY_RUSTY_BUCKET_BAY, "a", "Jiggy - RBB", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JIGGY_TREASURE_TROVE_COVE, "a", "Jiggy - TTC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_BLUE_BUBBLEGLOOP_SWAMP, "a", "Blue Jinjo - BGS", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_BLUE_CLANKERS_CAVERN, "a", "Blue Jinjo - CC", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_BLUE_CLICK_CLOCK_WOOD, "a", "Blue Jinjo - CCW", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_BLUE_FREEZEEZY_PEAK, "a", "Blue Jinjo - FP", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_BLUE_GOBIS_VALLEY, "a", "Blue Jinjo - GV", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_BLUE_MAD_MONSTER_MANSION, "a", "Blue Jinjo - MMM", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_BLUE_MUMBOS_MOUNTAIN, "a", "Blue Jinjo - MM", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_BLUE_RUSTY_BUCKET_BAY, "a", "Blue Jinjo - RBB", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_BLUE_TREASURE_TROVE_COVE, "a", "Blue Jinjo - TTC", RITYPE_JINJO, ACTOR_60_JINJO_BLUE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_GREEN_BUBBLEGLOOP_SWAMP, "a", "Green Jinjo - BGS", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_GREEN_CLANKERS_CAVERN, "a", "Green Jinjo - CC", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_GREEN_CLICK_CLOCK_WOOD, "a", "Green Jinjo - CCW", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_GREEN_FREEZEEZY_PEAK, "a", "Green Jinjo - FP", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_GREEN_GOBIS_VALLEY, "a", "Green Jinjo - GV", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_GREEN_MAD_MONSTER_MANSION, "a", "Green Jinjo - MMM", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_GREEN_MUMBOS_MOUNTAIN, "a", "Green Jinjo - MM", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_GREEN_RUSTY_BUCKET_BAY, "a", "Green Jinjo - RBB", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_GREEN_TREASURE_TROVE_COVE, "a", "Green Jinjo - TTC", RITYPE_JINJO, ACTOR_62_JINJO_GREEN, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_ORANGE_BUBBLEGLOOP_SWAMP, "a", "Orange Jinjo - BGS", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_ORANGE_CLANKERS_CAVERN, "a", "Orange Jinjo - CC", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, "a", "Orange Jinjo - CCW", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_ORANGE_FREEZEEZY_PEAK, "a", "Orange Jinjo - FP", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_ORANGE_GOBIS_VALLEY, "a", "Orange Jinjo - GV", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_ORANGE_MAD_MONSTER_MANSION, "a", "Orange Jinjo - MMM", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_ORANGE_MUMBOS_MOUNTAIN, "a", "Orange Jinjo - MM", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, "a", "Orange Jinjo - RBB", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_ORANGE_TREASURE_TROVE_COVE, "a", "Orange Jinjo - TTC", RITYPE_JINJO, ACTOR_5F_JINJO_ORANGE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, "a", "Pink Jinjo - BGS", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_PINK_CLANKERS_CAVERN, "a", "Pink Jinjo - CC", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_PINK_CLICK_CLOCK_WOOD, "a", "Pink Jinjo - CCW", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_PINK_FREEZEEZY_PEAK, "a", "Pink Jinjo - FP", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_PINK_GOBIS_VALLEY, "a", "Pink Jinjo - GV", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_PINK_MAD_MONSTER_MANSION, "a", "Pink Jinjo - MMM", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_PINK_MUMBOS_MOUNTAIN, "a", "Pink Jinjo - MM", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_PINK_RUSTY_BUCKET_BAY, "a", "Pink Jinjo - RBB", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_PINK_TREASURE_TROVE_COVE, "a", "Pink Jinjo - TTC", RITYPE_JINJO, ACTOR_61_JINJO_PINK, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, "a", "Yellow Jinjo - BGS", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_JINJO_YELLOW_CLANKERS_CAVERN, "a", "Yellow Jinjo - CC", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_3_CLANKERS_CAVERN), + RI(RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, "a", "Yellow Jinjo - CCW", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_JINJO_YELLOW_FREEZEEZY_PEAK, "a", "Yellow Jinjo - FP", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_JINJO_YELLOW_GOBIS_VALLEY, "a", "Yellow Jinjo - GV", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_7_GOBIS_VALLEY), + RI(RI_JINJO_YELLOW_MAD_MONSTER_MANSION, "a", "Yellow Jinjo - MMM", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_JINJO_YELLOW_MUMBOS_MOUNTAIN, "a", "Yellow Jinjo - MM", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, "a", "Yellow Jinjo - RBB", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_JINJO_YELLOW_TREASURE_TROVE_COVE, "a", "Yellow Jinjo - TTC", RITYPE_JINJO, ACTOR_5E_JINJO_YELLOW, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MOLEHILL_BARGE, "", "Beak Barge", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_BEAK_BOMB, "", "Beak Bomb", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MOLEHILL_BEAK_BUSTER, "", "Beak Buster", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MOLEHILL_CAMERA_CONTROL, "", "Camera Control", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_CLAW_SWIPE, "", "Claw Swipe", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_CLIMB, "", "Climb", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_DIVE, "", "Dive", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_EGGS, "", "Eggs", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MOLEHILL_FLAP_FLIP, "", "Flap Flip", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_MOLEHILL_FLIGHT, "", "Flight", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MOLEHILL_SHOCK_JUMP, "", "Shock Jump", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MOLEHILL_TALON_TROT, "", "Talon Trot", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MOLEHILL_TURBO_TALON, "", "Turbo Talon", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_7_GOBIS_VALLEY), + RI(RI_MOLEHILL_WADING_BOOTS, "", "Wading Boots", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MOLEHILL_WONDERWING, "", "Wonderwing", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, "a", "Mumbo Token - BGS", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MUMBO_TOKEN_CLANKERS_CAVERN, "a", "Mumbo Token - CC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, "a", "Mumbo Token - CCW", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_MUMBO_TOKEN_FREEZEEZY_PEAK, "a", "Mumbo Token - FP", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MUMBO_TOKEN_GOBIS_VALLEY, "a", "Mumbo Token - GV", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY), + RI(RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, "a", "Mumbo Token - GL", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_6_LAIR), + RI(RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, "a", "Mumbo Token - MMM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, "a", "Mumbo Token - MM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, "a", "Mumbo Token - RBB", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, "a", "Mumbo Token - TTC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, "a", "Note - BGS", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MUSIC_NOTE_CLANKERS_CAVERN, "a", "Note - CC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, "a", "Note - CCW", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_MUSIC_NOTE_FREEZEEZY_PEAK, "a", "Note - FP", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MUSIC_NOTE_GOBIS_VALLEY, "a", "Note - GV", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY), + RI(RI_MUSIC_NOTE_MAD_MONSTER_MANSION, "a", "Note - MMM", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, "a", "Note - MM", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, "a", "Note - RBB", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_MUSIC_NOTE_TREASURE_TROVE_COVE, "a", "Note - TTC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_STOP_N_SWOP_EGG_BLUE, "a", "Blue Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_7_GOBIS_VALLEY), + RI(RI_STOP_N_SWOP_EGG_CYAN, "a", "Cyan Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_STOP_N_SWOP_EGG_GREEN, "a", "Green Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_STOP_N_SWOP_EGG_PINK, "a", "Pink Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_STOP_N_SWOP_EGG_RED, "a", "Red Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_STOP_N_SWOP_EGG_YELLOW, "a", "Yellow Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_STOP_N_SWOP_ICE_KEY, "an", "Ice Key", RITYPE_SNS_KEY, ACTOR_25D_ICE_KEY, LEVEL_5_FREEZEEZY_PEAK), }; // clang-format on diff --git a/src/port/Rando/StaticData/Options.cpp b/src/port/Rando/StaticData/Options.cpp index 4afa5590e..7f3b8636a 100644 --- a/src/port/Rando/StaticData/Options.cpp +++ b/src/port/Rando/StaticData/Options.cpp @@ -18,6 +18,7 @@ std::map Options = { RO(RO_LOGIC, RO_LOGIC_GLITCHLESS), RO(RO_SPAWN_JUNK, RO_GENERIC_OFF), RO(RO_SHUFFLE_EMPTY_HONEYCOMBS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_EXTRA_LIVES, RO_GENERIC_OFF), RO(RO_SHUFFLE_JIGGIES, RO_GENERIC_OFF), RO(RO_SHUFFLE_JINJOS, RO_GENERIC_OFF), RO(RO_SHUFFLE_MOLEHILLS, RO_GENERIC_OFF), diff --git a/src/port/Rando/Types.h b/src/port/Rando/Types.h index 2a1deea77..02b60292c 100644 --- a/src/port/Rando/Types.h +++ b/src/port/Rando/Types.h @@ -11,6 +11,7 @@ typedef enum { typedef enum { RCTYPE_UNKNOWN, RCTYPE_EMPTY_HONEYCOMB, + RCTYPE_EXTRA_LIFE, RCTYPE_JIGGY, RCTYPE_JINJO, RCTYPE_MOLEHILL, @@ -24,6 +25,11 @@ typedef enum { RC_UNKNOWN, RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RC_BGS_EMPTY_HONEYCOMB_TANKTUP, + RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, + RC_BGS_EXTRA_LIFE_MR_VILE_1, + RC_BGS_EXTRA_LIFE_MR_VILE_2, + RC_BGS_EXTRA_LIFE_MR_VILE_3, + RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RC_BGS_JIGGY_CROCTUS, RC_BGS_JIGGY_ELEVATED_WALKWAY, RC_BGS_JIGGY_FLIBBITS, @@ -152,6 +158,9 @@ typedef enum { RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RC_CC_EMPTY_HONEYCOMB_UNDERWATER, + RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, + RC_CC_EXTRA_LIFE_JINJO_PIPE, + RC_CC_EXTRA_LIFE_YELLOW_GRATE, RC_CC_JIGGY_BOLT, RC_CC_JIGGY_CLANKER_RAISED, RC_CC_JIGGY_FAST_SAWBLADES, @@ -275,6 +284,18 @@ typedef enum { RC_CC_NOTE_YELLOW_GRATE_2, RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RC_CCW_EMPTY_HONEYCOMB_NABNUTS, + RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, + RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, + RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, + RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, + RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, + RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, + RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, + RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, + RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, + RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, + RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, + RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RC_CCW_JIGGY_EYRIE, RC_CCW_JIGGY_FLOWER, RC_CCW_JIGGY_GNAWTY, @@ -418,6 +439,9 @@ typedef enum { RC_CCW_SNS_YELLOW_EGG, RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, + RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, + RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, + RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RC_FP_JIGGY_BOGGY_RACE_1, RC_FP_JIGGY_BOGGY_RACE_2, @@ -545,6 +569,12 @@ typedef enum { RC_FP_NOTE_SNOWMAN_SCARF_18, RC_FP_NOTE_SNOWMAN_SCARF_19, RC_FP_SNS_ICE_KEY, + RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, + RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, + RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, + RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, + RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, + RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RC_GL_JIGGY_LOBBY, RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, @@ -567,6 +597,9 @@ typedef enum { RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RC_GV_EMPTY_HONEYCOMB_CACTUS, RC_GV_EMPTY_HONEYCOMB_GOBI, + RC_GV_EXTRA_LIFE_BEHIND_JINXY, + RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, + RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RC_GV_JIGGY_ANCIENT_ONES, RC_GV_JIGGY_GOBI_1, RC_GV_JIGGY_GOBI_2, @@ -696,6 +729,8 @@ typedef enum { RC_GV_SNS_BLUE_EGG, RC_MM_EMPTY_HONEYCOMB_HILL, RC_MM_EMPTY_HONEYCOMB_JUJU, + RC_MM_EXTRA_LIFE_HUT, + RC_MM_EXTRA_LIFE_TICKERS_TOWER, RC_MM_JIGGY_CHIMPY, RC_MM_JIGGY_CONGA, RC_MM_JIGGY_HILL, @@ -821,6 +856,9 @@ typedef enum { RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, + RC_MMM_EXTRA_LIFE_CHURCH_PIPES, + RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, + RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RC_MMM_JIGGY_BARREL_INTERIOR, RC_MMM_JIGGY_CELLAR, RC_MMM_JIGGY_CEMETARY_POTS, @@ -956,6 +994,9 @@ typedef enum { RC_MMM_SNS_GREEN_EGG, RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, + RC_RBB_EXTRA_LIFE_BOOM_BOXES, + RC_RBB_EXTRA_LIFE_ENGINE_ROOM, + RC_RBB_EXTRA_LIFE_WAREHOUSE, RC_RBB_JIGGY_BOSS_BOOM_BOX, RC_RBB_JIGGY_CAPTAINS_CABIN, RC_RBB_JIGGY_CRANE_CAGE, @@ -1093,6 +1134,8 @@ typedef enum { RC_SM_EMPTY_HONEYCOMB_TREE, RC_SM_EMPTY_HONEYCOMB_UNDERWATER, RC_SM_EMPTY_HONEYCOMB_WATERFALL, + RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, + RC_SM_EXTRA_LIFE_WATERFALL, RC_SM_MOLEHILL_ATTACK, RC_SM_MOLEHILL_BEAK_BARGE, RC_SM_MOLEHILL_CAMERA_CONTROL, @@ -1101,6 +1144,9 @@ typedef enum { RC_SM_MOLEHILL_JUMP, RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, + RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, + RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, + RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RC_TTC_JIGGY_ALCOVE1, RC_TTC_JIGGY_ALCOVE2, RC_TTC_JIGGY_BLUBBER, @@ -1235,6 +1281,7 @@ typedef enum { typedef enum { RITYPE_UNKNOWN, RITYPE_EMPTY_HONEYCOMB, + RITYPE_EXTRA_LIFE, RITYPE_JIGGY, RITYPE_JINJO, RITYPE_MOLEHILL, @@ -1258,6 +1305,17 @@ typedef enum { RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, + RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, + RI_EXTRA_LIFE_CLANKERS_CAVERN, + RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, + RI_EXTRA_LIFE_FREEZEEZY_PEAK, + RI_EXTRA_LIFE_GOBIS_VALLEY, + RI_EXTRA_LIFE_GRUNTILDAS_LAIR, + RI_EXTRA_LIFE_MAD_MONSTER_MANSION, + RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, + RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, + RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, + RI_EXTRA_LIFE_TREASURE_TROVE_COVE, RI_JIGGY_BUBBLEGLOOP_SWAMP, RI_JIGGY_CLANKERS_CAVERN, RI_JIGGY_CLICK_CLOCK_WOOD, @@ -1564,6 +1622,7 @@ typedef enum { RO_LOGIC, RO_SPAWN_JUNK, RO_SHUFFLE_EMPTY_HONEYCOMBS, + RO_SHUFFLE_EXTRA_LIVES, RO_SHUFFLE_JIGGIES, RO_SHUFFLE_JINJOS, RO_SHUFFLE_MOLEHILLS, From 56d1ded7650ab122e9b63847d9892e97811e4217 Mon Sep 17 00:00:00 2001 From: Caladius Date: Wed, 8 Jul 2026 13:14:16 -0400 Subject: [PATCH 5/8] [RANDO V2] Shuffle Blue Eggs (#245) * Shuffle Blue Eggs - MM PoC * clang * Add Blue Eggs to the shuffle pool * clang * clean up * Move options in Rando Menu * clang again --- .../CustomObject/CustomObjectSettings.cpp | 4 +- src/port/Rando/LighthouseMenuRando.cpp | 14 +- src/port/Rando/Logic/GeneratePools.cpp | 5 + .../Rando/Logic/Regions/BubblegloopSwamp.cpp | 50 ++ .../Rando/Logic/Regions/ClankersCavern.cpp | 50 +- .../Rando/Logic/Regions/ClickClockWood.cpp | 122 +++- .../Rando/Logic/Regions/FreezeezyPeak.cpp | 106 ++- src/port/Rando/Logic/Regions/GobisValley.cpp | 55 ++ .../Rando/Logic/Regions/GruntildasLair.cpp | 100 ++- .../Rando/Logic/Regions/MadMonsterMansion.cpp | 81 ++- .../Rando/Logic/Regions/MumbosMountain.cpp | 40 ++ .../Rando/Logic/Regions/RustyBucketBay.cpp | 85 ++- .../Rando/Logic/Regions/TreasureTroveCove.cpp | 45 ++ src/port/Rando/ObjectBehavior/Bundle.cpp | 6 +- .../Rando/ObjectBehavior/ObjectBehavior.cpp | 7 + src/port/Rando/ObjectBehavior/Prop.cpp | 10 +- src/port/Rando/StaticData/Checks.cpp | 594 +++++++++++++++++ src/port/Rando/StaticData/Items.cpp | 10 + src/port/Rando/StaticData/Options.cpp | 1 + src/port/Rando/Types.h | 607 ++++++++++++++++++ src/port/ShipUtils.cpp | 15 +- src/port/UI/DeveloperTools/SaveEditor.cpp | 6 +- 22 files changed, 1923 insertions(+), 90 deletions(-) diff --git a/src/port/Rando/CustomObject/CustomObjectSettings.cpp b/src/port/Rando/CustomObject/CustomObjectSettings.cpp index a9b52b45e..aefddc5d3 100644 --- a/src/port/Rando/CustomObject/CustomObjectSettings.cpp +++ b/src/port/Rando/CustomObject/CustomObjectSettings.cpp @@ -143,7 +143,9 @@ void ApplyCustomActorPhysics(RandoCheckId randoCheckId, Actor* actor, bool isJin BundlePhysics physicsData; if ((randoCheckId >= RC_MM_NOTE_HUT_BUNDLE_1 && randoCheckId <= RC_MM_NOTE_HUT_BUNDLE_5) || - randoCheckId == RC_MM_JINJO_GREEN || randoCheckId == RC_MM_JIGGY_HUTS || randoCheckId == RC_MM_EXTRA_LIFE_HUT) { + randoCheckId == RC_MM_JINJO_GREEN || randoCheckId == RC_MM_JIGGY_HUTS || + (randoCheckId >= RC_MM_BLUE_EGG_HUT_BUNDLE_1 && randoCheckId <= RC_MM_BLUE_EGG_HUT_BUNDLE_5) || + randoCheckId == RC_MM_EXTRA_LIFE_HUT) { physicsData = GetPhysicsByCheckId(RC_MM_NOTE_HUT_BUNDLE_1); } else { physicsData = isJinjoJiggy ? jinjoJiggySpawnPhysics : GetPhysicsByCheckId(randoCheckId); diff --git a/src/port/Rando/LighthouseMenuRando.cpp b/src/port/Rando/LighthouseMenuRando.cpp index 20d0c09a5..53d7ec8d5 100644 --- a/src/port/Rando/LighthouseMenuRando.cpp +++ b/src/port/Rando/LighthouseMenuRando.cpp @@ -104,7 +104,7 @@ void LighthouseMenu::AddMenuRando() { AddSidebarEntry("Rando", "Shuffle Options", 2); path = { "Rando", "Shuffle Options", SECTION_COLUMN_1 }; - AddWidget(path, "Shuffle Collectables", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Base Shuffles", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Shuffle Empty Honeycombs", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_EMPTY_HONEYCOMBS].cvar) @@ -118,9 +118,6 @@ void LighthouseMenu::AddMenuRando() { AddWidget(path, "Shuffle Jinjos", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_JINJOS].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Jinjos into the Pool.")); - AddWidget(path, "Shuffle Molehills", WIDGET_CVAR_CHECKBOX) - .CVar(Rando::StaticData::Options[RO_SHUFFLE_MOLEHILLS].cvar) - .Options(CheckboxOptions().Tooltip("Shuffles which abilities each Molehill unlocks.")); AddWidget(path, "Shuffle Mumbo Tokens", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_MUMBO_TOKENS].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Mumbo Tokens into the Pool.")); @@ -128,6 +125,15 @@ void LighthouseMenu::AddMenuRando() { .CVar(Rando::StaticData::Options[RO_SHUFFLE_MUSIC_NOTES].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Music Notes into the Pool.")); + AddWidget(path, "Advanced Shuffles", WIDGET_SEPARATOR_TEXT); + + AddWidget(path, "Shuffle Blue Eggs", WIDGET_CVAR_CHECKBOX) + .CVar(Rando::StaticData::Options[RO_SHUFFLE_BLUE_EGGS].cvar) + .Options(CheckboxOptions().Tooltip("Shuffles Blue Eggs into the Pool.")); + AddWidget(path, "Shuffle Molehills", WIDGET_CVAR_CHECKBOX) + .CVar(Rando::StaticData::Options[RO_SHUFFLE_MOLEHILLS].cvar) + .Options(CheckboxOptions().Tooltip("Shuffles which abilities each Molehill unlocks.")); + path.column = SECTION_COLUMN_2; AddWidget(path, "Win Conditions", WIDGET_SEPARATOR_TEXT); diff --git a/src/port/Rando/Logic/GeneratePools.cpp b/src/port/Rando/Logic/GeneratePools.cpp index bb1bb4141..589807047 100644 --- a/src/port/Rando/Logic/GeneratePools.cpp +++ b/src/port/Rando/Logic/GeneratePools.cpp @@ -46,6 +46,11 @@ void GenerateShufflePool(SaveData* saveData) { shuffledPool.clear(); for (auto& [randoCheckId, randoStaticCheck] : Rando::StaticData::Checks) { + if (randoStaticCheck.randoCheckType == RCTYPE_BLUE_EGG && + CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_BLUE_EGGS].cvar, 0) == RO_GENERIC_OFF) { + continue; + } + if (randoStaticCheck.randoCheckType == RCTYPE_EMPTY_HONEYCOMB && CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_EMPTY_HONEYCOMBS].cvar, 0) == RO_GENERIC_OFF) { continue; diff --git a/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp b/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp index f0a44225a..a3db78af0 100644 --- a/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp +++ b/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp @@ -7,6 +7,50 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_BUBBLEGLOOP_SWAMP] = RandoRegion{ .regionName = "Bubblegloop Swamp", .mapId = MAP_D_BGS_BUBBLEGLOOP_SWAMP, .checks = { + CHECK(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, true), + CHECK(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, true), + CHECK(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, true), + CHECK(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, true), + CHECK(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, true), + CHECK(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), CHECK(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), CHECK(RC_BGS_JIGGY_CROCTUS, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP) && CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_ABILITY(ABILITY_12_WONDERWING)), @@ -131,6 +175,8 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_BUBBLEGLOOP_SWAMP_INTERIOR_MR_VILES] = RandoRegion{ .regionName = "Mr. Vile Interior", .mapId = MAP_10_BGS_MR_VILE, .checks = { + CHECK(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, true), + CHECK(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, true), CHECK(RC_BGS_EXTRA_LIFE_MR_VILE_1, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), CHECK(RC_BGS_EXTRA_LIFE_MR_VILE_2, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), CHECK(RC_BGS_EXTRA_LIFE_MR_VILE_3, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), @@ -161,6 +207,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_BUBBLEGLOOP_SWAMP_INTERIOR_TANKTUP] = RandoRegion{ .regionName = "Tanktup Interior", .mapId = MAP_11_BGS_TIPTUP, .checks = { + CHECK(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, true), + CHECK(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, true), + CHECK(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, true), + CHECK(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, true), CHECK(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_BGS_JIGGY_TIPTUP, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), CHECK(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, true), diff --git a/src/port/Rando/Logic/Regions/ClankersCavern.cpp b/src/port/Rando/Logic/Regions/ClankersCavern.cpp index fe3aa56f1..64cec4403 100644 --- a/src/port/Rando/Logic/Regions/ClankersCavern.cpp +++ b/src/port/Rando/Logic/Regions/ClankersCavern.cpp @@ -7,7 +7,13 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_ENTRANCE] = RandoRegion{ .regionName = "Clanker's Cavern Entrance", .mapId = MAP_B_CC_CLANKERS_CAVERN, .checks = { - CHECK(RC_CC_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_3_CLANKERS_CAVERN)), + CHECK(RC_CC_BLUE_EGG_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_ENTRANCE_6, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_3_CLANKERS_CAVERN)), }, .connections = { CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE_UPPER, CAN_USE_ABILITY(ABILITY_5_CLIMB) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -30,8 +36,8 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_8, CAN_EXTEND_JUMP_DISTANCE), }, .connections = { - CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE, true), - CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE_UNDERWATER, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE_UNDERWATER, CAN_USE_ABILITY(ABILITY_F_DIVE)), }, }; @@ -52,6 +58,18 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_INTERIOR_CLANKER] = RandoRegion{ .regionName = "Inside Clanker", .mapId = MAP_22_CC_INSIDE_CLANKER, .checks = { + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_6, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_7, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_RINGS_8, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), + CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), + CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), + CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), CHECK(RC_CC_JIGGY_RINGS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_CC_JINJO_PINK, true), CHECK(RC_CC_JIGGY_TOOTH, true), @@ -112,6 +130,25 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_NEAR_CLANKER] = RandoRegion{ .regionName = "Near Clanker", .mapId = MAP_B_CC_CLANKERS_CAVERN, .checks = { + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, true), + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, true), + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, true), + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, true), + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, true), + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, true), + CHECK(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, true), + CHECK(RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CC_BLUE_EGG_YELLOW_GRATE_1, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_BLUE_EGG_YELLOW_GRATE_2, CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, true), CHECK(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, true), CHECK(RC_CC_JIGGY_BOLT, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -173,6 +210,13 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_NEAR_CLANKER_UPPER] = RandoRegion{ .regionName = "Upper Area Near Clanker", .mapId = MAP_B_CC_CLANKERS_CAVERN, .checks = { + CHECK(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, CAN_ATTACK), + CHECK(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, CAN_ATTACK), CHECK(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), CHECK(RC_CC_EXTRA_LIFE_YELLOW_GRATE, CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_CC_EXTRA_LIFE_JINJO_PIPE, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), diff --git a/src/port/Rando/Logic/Regions/ClickClockWood.cpp b/src/port/Rando/Logic/Regions/ClickClockWood.cpp index 99e5e13ca..8d95c49ce 100644 --- a/src/port/Rando/Logic/Regions/ClickClockWood.cpp +++ b/src/port/Rando/Logic/Regions/ClickClockWood.cpp @@ -7,6 +7,22 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_AUTUMN] = RandoRegion{ .regionName = "Autumn Season", .mapId = MAP_45_CCW_AUTUMN, .checks = { + CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, true), CHECK(RC_CCW_JIGGY_FLOWER, true), CHECK(RC_CCW_JIGGY_GNAWTY, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -82,6 +98,11 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_CLICK_CLOCK_WOOD_AUTUMN_INTERIOR_NABNUTS_WINDOW] = RandoRegion{ .regionName = "Autumn - Inside the Window near Nabnut's House", .mapId = MAP_63_CCW_AUTUMN_NABNUTS_WATER_SUPPLY, + .checks = { + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, true), + }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_AUTUMN_UPPER_TREE, true), }, @@ -98,6 +119,9 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_AUTUMN_UPPER_TREE] = RandoRegion{ .regionName = "Autumn - Upper Portion of the Tree", .mapId = MAP_45_CCW_AUTUMN, .checks = { + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, true), CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, true), CHECK(RC_CCW_JIGGY_NABNUT, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), @@ -122,11 +146,15 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_ENTRANCE] = RandoRegion{ .regionName = "Click Clock Wood Entrance", .mapId = MAP_40_CCW_HUB, .checks = { - CHECK(RC_CCW_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_8_CLICK_CLOCK_WOOD)), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_1, true), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_2, true), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_3, true), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_4, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, true), + CHECK(RC_CCW_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_8_CLICK_CLOCK_WOOD)), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_1, true), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_2, true), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_3, true), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_4, true), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SPRING, CAN_ACCESS(RA_TRIGGER_SWITCH_CCW_SPRING)), @@ -142,6 +170,28 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SPRING] = RandoRegion{ .regionName = "Spring Season", .mapId = MAP_43_CCW_SPRING, .checks = { + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, CAN_USE_ABILITY(ABILITY_12_WONDERWING) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), @@ -190,6 +240,11 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_CLICK_CLOCK_WOOD_SPRING_INTERIOR_MUMBOS_SKULL] = RandoRegion{ .regionName = "Spring - Inside Mumbo's Skull", .mapId = MAP_4A_CCW_SPRING_MUMBOS_SKULL, + .checks = { + CHECK(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, true), + }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SPRING, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), }, @@ -197,7 +252,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SPRING_INTERIOR_NABNUTS_HOUSE] = RandoRegion{ .regionName = "Spring - Inside Nabnut's House", .mapId = MAP_5E_CCW_SPRING_NABNUTS_HOUSE, .checks = { - CHECK(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, true), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SPRING_UPPER_TREE, true), @@ -217,6 +275,18 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SPRING_UPPER_TREE] = RandoRegion{ .regionName = "Spring - Upper Portion of the Tree", .mapId = MAP_43_CCW_SPRING, .checks = { + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, true), + CHECK(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, true), CHECK(RC_CCW_JIGGY_TREE_TOP, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE) || (CAN_ACCESS(RA_TRIGGER_SWITCH_CCW_WINTER) && CAN_USE_ABILITY(ABILITY_9_FLIGHT))), CHECK(RC_CCW_JINJO_GREEN, (CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_12_WONDERWING)) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, true), @@ -234,6 +304,20 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SUMMER] = RandoRegion{ .regionName = "Summer Season", .mapId = MAP_44_CCW_SUMMER, .checks = { + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, true), CHECK(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, true), CHECK(RC_CCW_JIGGY_SUMMER_LEAF_JUMPS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_CCW_JINJO_YELLOW, true), @@ -296,6 +380,12 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SUMMER_UPPER_TREE] = RandoRegion{ .regionName = "Summer - Upper Portion of the Tree", .mapId = MAP_44_CCW_SUMMER, .checks = { + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, true), CHECK(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, true), CHECK(RC_CCW_JIGGY_HOUSE, true), CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, true), @@ -344,6 +434,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_WINTER_INTERIOR_NABNUTS_HOUSE] = RandoRegion{ .regionName = "Winter - Inside Nabnut's House", .mapId = MAP_61_CCW_WINTER_NABNUTS_HOUSE, .checks = { + CHECK(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, true), + CHECK(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, true), + CHECK(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, true), + CHECK(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, true), + CHECK(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, true), CHECK(RC_CCW_SNS_YELLOW_EGG, true), }, .connections = { @@ -352,6 +447,16 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_CLICK_CLOCK_WOOD_WINTER_INTERIOR_NABNUTS_WINDOW] = RandoRegion{ .regionName = "Winter - Inside the Window near Nabnut's House", .mapId = MAP_64_CCW_WINTER_NABNUTS_WATER_SUPPLY, + .checks = { + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, CAN_USE_ABILITY(ABILITY_F_DIVE)), + }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_WINTER_UPPER_TREE, true), }, @@ -359,7 +464,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_WINTER_INTERIOR_WINDOW_ABOVE_NABNUT] = RandoRegion{ .regionName = "Winter - Inside the Window Above Nabnut's House", .mapId = MAP_62_CCW_WINTER_HONEYCOMB_ROOM, .checks = { - CHECK(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, true), + CHECK(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, true), + CHECK(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, true), + CHECK(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_WINTER_UPPER_TREE, true), diff --git a/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp b/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp index e6f1e5085..7c838c9c3 100644 --- a/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp +++ b/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp @@ -7,21 +7,26 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_ENTRANCE] = RandoRegion{ .regionName = "Freezeezy Peak Entrance", .mapId = MAP_27_FP_FREEZEEZY_PEAK, .checks = { - CHECK(RC_FP_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_5_FREEZEEZY_PEAK)), - CHECK(RC_FP_JIGGY_SLED_TO_BOGGY, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), - CHECK(RC_FP_NOTE_FIRST_SLOPE_1, true), - CHECK(RC_FP_NOTE_FIRST_SLOPE_2, true), - CHECK(RC_FP_NOTE_FIRST_SLOPE_3, true), - CHECK(RC_FP_NOTE_FIRST_SLOPE_4, true), - CHECK(RC_FP_NOTE_FIRST_SLOPE_5, true), - CHECK(RC_FP_NOTE_NEAR_RACE_START_1, true), - CHECK(RC_FP_NOTE_NEAR_RACE_START_2, true), - CHECK(RC_FP_NOTE_NEAR_RACE_START_3, true), - CHECK(RC_FP_NOTE_NEAR_RACE_START_4, true), - CHECK(RC_FP_NOTE_SECOND_SLOPE_1, true), - CHECK(RC_FP_NOTE_SECOND_SLOPE_2, true), - CHECK(RC_FP_NOTE_SECOND_SLOPE_3, true), - CHECK(RC_FP_NOTE_SECOND_SLOPE_4, true), + CHECK(RC_FP_BLUE_EGG_BEHIND_IGLOO_1, true), + CHECK(RC_FP_BLUE_EGG_BEHIND_IGLOO_2, true), + CHECK(RC_FP_BLUE_EGG_BEHIND_IGLOO_3, true), + CHECK(RC_FP_BLUE_EGG_BEHIND_IGLOO_4, true), + CHECK(RC_FP_BLUE_EGG_BEHIND_IGLOO_5, true), + CHECK(RC_FP_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_5_FREEZEEZY_PEAK)), + CHECK(RC_FP_JIGGY_SLED_TO_BOGGY, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_FP_NOTE_FIRST_SLOPE_1, true), + CHECK(RC_FP_NOTE_FIRST_SLOPE_2, true), + CHECK(RC_FP_NOTE_FIRST_SLOPE_3, true), + CHECK(RC_FP_NOTE_FIRST_SLOPE_4, true), + CHECK(RC_FP_NOTE_FIRST_SLOPE_5, true), + CHECK(RC_FP_NOTE_NEAR_RACE_START_1, true), + CHECK(RC_FP_NOTE_NEAR_RACE_START_2, true), + CHECK(RC_FP_NOTE_NEAR_RACE_START_3, true), + CHECK(RC_FP_NOTE_NEAR_RACE_START_4, true), + CHECK(RC_FP_NOTE_SECOND_SLOPE_1, true), + CHECK(RC_FP_NOTE_SECOND_SLOPE_2, true), + CHECK(RC_FP_NOTE_SECOND_SLOPE_3, true), + CHECK(RC_FP_NOTE_SECOND_SLOPE_4, true), }, .connections = { CONNECTION(RR_FREEZEEZY_PEAK_INTERIOR_BOGGYS_IGLOO, true), @@ -57,6 +62,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_INTERIOR_WOZZAS_CAVE] = RandoRegion{ .regionName = "Inside Wozza's Cave", .mapId = MAP_7F_FP_WOZZAS_CAVE, .checks = { + CHECK(RC_FP_BLUE_EGG_WOZZAS_CAVE_1, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WOZZAS_CAVE_2, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WOZZAS_CAVE_3, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WOZZAS_CAVE_4, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, true), CHECK(RC_FP_JINJO_ORANGE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, true), @@ -69,6 +78,28 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_MAIN_LOWER] = RandoRegion{ .regionName = "Lower Area near the Snowman", .mapId = MAP_27_FP_FREEZEEZY_PEAK, .checks = { + CHECK(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, true), + CHECK(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, true), + CHECK(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, true), + CHECK(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, true), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), + CHECK(RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), @@ -141,6 +172,13 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_MAIN_UPPER] = RandoRegion{ .regionName = "Upper Area near the Snowman", .mapId = MAP_27_FP_FREEZEEZY_PEAK, .checks = { + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_FP_JIGGY_SNOWMANS_PIPE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_FP_JINJO_BLUE, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), @@ -184,19 +222,31 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_POTTED_TREE] = RandoRegion{ .regionName = "Inside the Potted Tree", .mapId = MAP_53_FP_CHRISTMAS_TREE, .checks = { - CHECK(RC_FP_JIGGY_INSIDE_THE_TREE, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_1, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_2, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_3, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_4, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_5, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_6, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_7, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_8, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_9, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_10, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_11, true), - CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_12, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, true), + CHECK(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, true), + CHECK(RC_FP_JIGGY_INSIDE_THE_TREE, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_1, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_2, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_3, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_4, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_5, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_6, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_7, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_8, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_9, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_10, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_11, true), + CHECK(RC_FP_NOTE_POTTED_TREE_INTERIOR_12, true), }, .connections = { CONNECTION(RR_FREEZEEZY_PEAK_MAIN_LOWER, true), diff --git a/src/port/Rando/Logic/Regions/GobisValley.cpp b/src/port/Rando/Logic/Regions/GobisValley.cpp index 03f0d506c..effb49f3f 100644 --- a/src/port/Rando/Logic/Regions/GobisValley.cpp +++ b/src/port/Rando/Logic/Regions/GobisValley.cpp @@ -7,6 +7,11 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_ENTRANCE] = RandoRegion{ .regionName = "Gobi's Valley", .mapId = MAP_12_GV_GOBIS_VALLEY, .checks = { + CHECK(RC_GV_BLUE_EGG_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GV_EMPTY_HONEYCOMB_GOBI, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_GV_JIGGY_GOBI_2, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_5_CLIMB)), CHECK(RC_GV_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_7_GOBIS_VALLEY)), @@ -47,6 +52,20 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_INTERIOR_MAZE_PYRAMID] = RandoRegion{ .regionName = "Maze Pyramid Interior", .mapId = MAP_14_GV_SANDYBUTTS_MAZE, .checks = { + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, true), + CHECK(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, true), CHECK(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, true), CHECK(RC_GV_JIGGY_MAZE, true), CHECK(RC_GV_JINJO_PINK, true), @@ -87,6 +106,14 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_INTERIOR_SPHYNX] = RandoRegion{ .regionName = "Sphynx Interior", .mapId = MAP_1A_GV_INSIDE_JINXY, .checks = { + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, true), CHECK(RC_GV_JIGGY_SHYINX, CAN_USE_ABILITY(ABILITY_6_EGGS)), CHECK(RC_GV_JINJO_ORANGE, CAN_USE_ABILITY(ABILITY_6_EGGS)), CHECK(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, true), @@ -106,6 +133,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_INTERIOR_WATER_PYRAMID] = RandoRegion{ .regionName = "Water Pyramid Interior", .mapId = MAP_15_GV_WATER_PYRAMID, .checks = { + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GV_JIGGY_WATER_PYRAMID, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, true), CHECK(RC_GV_NOTE_WATER_PYRAMID_INTERIOR_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), @@ -132,6 +163,30 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_UPPER_AREA] = RandoRegion{ .regionName = "Upper Areas", .mapId = MAP_12_GV_GOBIS_VALLEY, .checks = { + CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, true), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, true), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, true), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, true), CHECK(RC_GV_EXTRA_LIFE_BEHIND_JINXY, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), CHECK(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, true), CHECK(RC_GV_EMPTY_HONEYCOMB_CACTUS, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), diff --git a/src/port/Rando/Logic/Regions/GruntildasLair.cpp b/src/port/Rando/Logic/Regions/GruntildasLair.cpp index c06fafb0e..085ac998c 100644 --- a/src/port/Rando/Logic/Regions/GruntildasLair.cpp +++ b/src/port/Rando/Logic/Regions/GruntildasLair.cpp @@ -7,7 +7,14 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_180] = RandoRegion{ .regionName = "Before Second Note Door", .mapId = MAP_6B_GL_180_NOTE_DOOR, .checks = { - CHECK(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, CAN_USE_ABILITY(ABILITY_F_DIVE)), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_260, CAN_UNLOCK_NOTE_DOOR(180)), @@ -101,7 +108,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_BUBBLEGLOOP_SWAMP] = RandoRegion{ .regionName = "Near Bubblegloop Swamp Entrance", .mapId = MAP_72_GL_BGS_LOBBY, .checks = { - CHECK(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, true), + CHECK(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, CAN_ACCESS(RA_PUZZLE_BOARD_FREEZEEZY_PEAK)), + CHECK(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, CAN_ACCESS(RA_PUZZLE_BOARD_FREEZEEZY_PEAK)), + CHECK(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, CAN_ACCESS(RA_PUZZLE_BOARD_FREEZEEZY_PEAK)), + CHECK(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, CAN_ACCESS(RA_PUZZLE_BOARD_FREEZEEZY_PEAK)), + CHECK(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, true), }, .connections = { CONNECTION(RR_BUBBLEGLOOP_SWAMP, CAN_UNLOCK_WORLD(LEVEL_4_BUBBLEGLOOP_SWAMP)), @@ -114,7 +125,15 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_CLANKERS_CAVERN] = RandoRegion{ .regionName = "Near Clanker's Cavern Entrance", .mapId = MAP_70_GL_CC_LOBBY, .checks = { - CHECK(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_UNDERWATER_PIPES) && CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_UNDERWATER_PIPES) && CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), }, .connections = { CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_3_CLANKERS_CAVERN)), @@ -130,6 +149,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_CLICK_CLOCK_WOOD] = RandoRegion{ .regionName = "Near Click Clock Wood Entrance", .mapId = MAP_79_GL_CCW_LOBBY, .checks = { + CHECK(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), + CHECK(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), + CHECK(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), + CHECK(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD, CAN_ACCESS(RA_WITCH_SWITCH_CLICK_CLOCK_WOOD) && CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), }, @@ -146,10 +169,17 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_FREEZEEZY_PEAK] = RandoRegion{ .regionName = "Near Freezeezy Peak Entrance", .mapId = MAP_6F_GL_FP_LOBBY, .checks = { - CHECK(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, CAN_ACCESS(RA_WITCH_SWITCH_MAD_MONSTER_MANSION) && CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, (CAN_EXTEND_JUMP_DISTANCE || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, true), + CHECK(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, CAN_ACCESS(RA_WITCH_SWITCH_MAD_MONSTER_MANSION) && CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, (CAN_EXTEND_JUMP_DISTANCE || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), }, .connections = { CONNECTION(RR_FREEZEEZY_PEAK_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_5_FREEZEEZY_PEAK)), @@ -168,8 +198,12 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_GOBIS_VALLEY] = RandoRegion{ .regionName = "Near Gobi's Valley Entrance", .mapId = MAP_6E_GL_GV_LOBBY, .checks = { - CHECK(RC_GL_JIGGY_WITCH_SWITCH_GOBIS_VALLEY, CAN_ACCESS(RA_WITCH_SWITCH_GOBIS_VALLEY) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_SHOCK_PAD) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), - CHECK(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, true), + CHECK(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_BRICK_WALL)), + CHECK(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_BRICK_WALL)), + CHECK(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_BRICK_WALL)), + CHECK(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_BRICK_WALL)), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_GOBIS_VALLEY, CAN_ACCESS(RA_WITCH_SWITCH_GOBIS_VALLEY) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_SHOCK_PAD) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, true), }, .connections = { CONNECTION(RR_GOBIS_VALLEY_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_7_GOBIS_VALLEY)), @@ -183,7 +217,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_RUSTY_BUCKET_BAY] = RandoRegion{ .regionName = "Near Rusty Bucket Bay Entrance", .mapId = MAP_77_GL_RBB_LOBBY, .checks = { - CHECK(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_RBB_ENTRANCE_1, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_WATER_LEVEL_1)), + CHECK(RC_GL_BLUE_EGG_RBB_ENTRANCE_2, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_WATER_LEVEL_1)), + CHECK(RC_GL_BLUE_EGG_RBB_ENTRANCE_3, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_WATER_LEVEL_1)), + CHECK(RC_GL_BLUE_EGG_RBB_ENTRANCE_4, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_WATER_LEVEL_1)), + CHECK(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, CAN_USE_ABILITY(ABILITY_F_DIVE)), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_260, CAN_USE_ABILITY(ABILITY_F_DIVE)), @@ -198,7 +236,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_MAD_MONSTER_MANSION] = RandoRegion{ .regionName = "Near Mad Monster Mansion Entrance", .mapId = MAP_75_GL_MMM_LOBBY, .checks = { - CHECK(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_IRON_GATE)), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, true), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, true), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, true), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, true), + CHECK(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_IRON_GATE)), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_GOBIS_VALLEY, true), @@ -244,8 +286,18 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_MAD_MONSTER_MANSION] = RandoRegion{ .regionName = "Near Mad Monster Mansion Puzzle Board", .mapId = MAP_78_GL_RBB_AND_MMM_PUZZLE, .checks = { + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, CAN_ACCESS(RA_PUZZLE_BOARD_RUSTY_BUCKET_BAY)), - CHECK(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, CAN_EXTEND_JUMP_DISTANCE), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_RUSTY_BUCKET_BAY, CAN_USE_ABILITY(ABILITY_F_DIVE)), @@ -257,6 +309,10 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_RUSTY_BUCKET_BAY] = RandoRegion{ .regionName = "Near Rusty Bucket Bay Puzzle Board", .mapId = MAP_78_GL_RBB_AND_MMM_PUZZLE, + .checks = { + CHECK(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_GRATE)), + CHECK(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_GRATE)), + }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_RUSTY_BUCKET_BAY, true), CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_MAD_MONSTER_MANSION, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_GRATE)), @@ -268,9 +324,17 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_PAST_NOTE_DOOR_50] = RandoRegion{ .regionName = "Past First Note Door", .mapId = MAP_6A_GL_TTC_AND_CC_PUZZLE, .checks = { + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, true), + CHECK(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, true), CHECK(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, CAN_ACCESS(RA_WITCH_SWITCH_CLANKERS_CAVERN)), - CHECK(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, true), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, CAN_ACCESS(RA_WITCH_SWITCH_CLANKERS_CAVERN)), + CHECK(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, true), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_180, true), @@ -285,7 +349,13 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_WATER_SWITCH_1_ROOM] = RandoRegion{ .regionName = "First Water Switch Room", .mapId = MAP_7A_GL_CRYPT, .checks = { - CHECK(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, true), + CHECK(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, true), + CHECK(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, true), + CHECK(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, true), + CHECK(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, true), + CHECK(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, true), + CHECK(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, true), + CHECK(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, true), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_MAD_MONSTER_MANSION, true), diff --git a/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp b/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp index 9ac6b2900..c475632a2 100644 --- a/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp +++ b/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp @@ -44,6 +44,14 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_CHURCH_INTERIOR] = RandoRegion{ .regionName = "Church Interior", .mapId = MAP_1C_MMM_CHURCH, .checks = { + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MMM_NOTE_ORGAN_PEDALS_1, true), CHECK(RC_MMM_NOTE_ORGAN_PEDALS_2, true), @@ -75,6 +83,18 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_CHURCH_INTERIOR_RAFTERS] = RandoRegion{ .regionName = "Church Rafters", .mapId = MAP_1C_MMM_CHURCH, .checks = { + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, true), CHECK(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, true), CHECK(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, true), }, @@ -86,7 +106,25 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_CHURCH_INTERIOR_WINDOW] = RandoRegion{ .regionName = "Church Banjo Kazooie Window", .mapId = MAP_2B_MMM_SECRET_CHURCH_ROOM, .checks = { - CHECK(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, true), + CHECK(RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, true), + CHECK(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, true), }, .connections = { CONNECTION(RR_MAD_MONSTER_MANSION_CHURCH_EXTERIOR, true), @@ -95,6 +133,21 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_ENTRANCE] = RandoRegion{ .regionName = "Mad Monster Mansion", .mapId = MAP_1B_MMM_MAD_MONSTER_MANSION, .checks = { + CHECK(RC_MMM_BLUE_EGG_MANSION_AWNING_1, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_MANSION_AWNING_2, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_MANSION_AWNING_3, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_MANSION_AWNING_4, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_MAZE_1, true), + CHECK(RC_MMM_BLUE_EGG_MAZE_2, true), + CHECK(RC_MMM_BLUE_EGG_MAZE_3, true), + CHECK(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, true), + CHECK(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, true), + CHECK(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, true), + CHECK(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, true), + CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_1, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), + CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_2, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), + CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_3, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), + CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_4, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), CHECK(RC_MMM_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_A_MAD_MONSTER_MANSION)), CHECK(RC_MMM_JINJO_BLUE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_MMM_JINJO_GREEN, CAN_USE_ABILITY(ABILITY_5_CLIMB) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), @@ -184,6 +237,9 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_INTERIOR_BEDROOM] = RandoRegion{ .regionName = "Bedroom", .mapId = MAP_2D_MMM_BEDROOM, .checks = { + CHECK(RC_MMM_BLUE_EGG_BEDROOM_1, true), + CHECK(RC_MMM_BLUE_EGG_BEDROOM_2, true), + CHECK(RC_MMM_BLUE_EGG_BEDROOM_3, true), CHECK(RC_MMM_JINJO_YELLOW, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, true), CHECK(RC_MMM_NOTE_BEDROOM_1, true), @@ -198,6 +254,9 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_INTERIOR_CELLAR] = RandoRegion{ .regionName = "Cellar", .mapId = MAP_1D_MMM_CELLAR, .checks = { + CHECK(RC_MMM_BLUE_EGG_CELLAR_1, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_CELLAR_CASK)), + CHECK(RC_MMM_BLUE_EGG_CELLAR_2, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_CELLAR_CASK)), + CHECK(RC_MMM_BLUE_EGG_CELLAR_3, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_CELLAR_CASK)), CHECK(RC_MMM_JIGGY_CELLAR, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_CELLAR_CASK)), CHECK(RC_MMM_JINJO_PINK, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_CELLAR_CASK)), CHECK(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_CELLAR_CASK)), @@ -214,6 +273,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_INTERIOR_DINING_ROOM] = RandoRegion{ .regionName = "Dining Room", .mapId = MAP_26_MMM_NAPPERS_ROOM, .checks = { + CHECK(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_MMM_JIGGY_MANSION_TABLE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), @@ -291,6 +355,14 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_INTERIOR_WINDOW_BOTTOM_SOUTH] = RandoRegion{ .regionName = "Bottom South Window", .mapId = MAP_28_MMM_EGG_ROOM, .checks = { + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_1, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_2, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_3, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_4, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_5, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_6, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_7, true), + CHECK(RC_MMM_BLUE_EGG_EGG_ROOM_8, true), }, .connections = { CONNECTION(RR_MAD_MONSTER_MANSION_ENTRANCE, true), @@ -299,7 +371,12 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MAD_MONSTER_MANSION_INTERIOR_WINDOW_MIDDLE_WEST] = RandoRegion{ .regionName = "Middle West Window", .mapId = MAP_2E_MMM_HONEYCOMB_ROOM, .checks = { - CHECK(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), + CHECK(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, CAN_USE_TRANSFORMATION(TRANSFORM_3_PUMPKIN)), }, .connections = { CONNECTION(RR_MAD_MONSTER_MANSION_ENTRANCE, true), diff --git a/src/port/Rando/Logic/Regions/MumbosMountain.cpp b/src/port/Rando/Logic/Regions/MumbosMountain.cpp index 80ee1c22a..595a3935f 100644 --- a/src/port/Rando/Logic/Regions/MumbosMountain.cpp +++ b/src/port/Rando/Logic/Regions/MumbosMountain.cpp @@ -7,6 +7,28 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_MUMBOS_MOUNTAIN_ENTRANCE] = RandoRegion{ .regionName = "Mumbo's Mountain", .mapId = MAP_2_MM_MUMBOS_MOUNTAIN, .checks = { + CHECK(RC_MM_BLUE_EGG_HUT_BUNDLE_1, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MM_BLUE_EGG_HUT_BUNDLE_2, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MM_BLUE_EGG_HUT_BUNDLE_3, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MM_BLUE_EGG_HUT_BUNDLE_4, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MM_BLUE_EGG_HUT_BUNDLE_5, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MM_BLUE_EGG_UNDER_RUINS_1, true), + CHECK(RC_MM_BLUE_EGG_UNDER_RUINS_2, true), + CHECK(RC_MM_BLUE_EGG_UNDER_RUINS_3, true), + CHECK(RC_MM_BLUE_EGG_UNDER_RUINS_4, true), + CHECK(RC_MM_BLUE_EGG_UNDER_RUINS_5, true), CHECK(RC_MM_EMPTY_HONEYCOMB_HILL, true), CHECK(RC_MM_EMPTY_HONEYCOMB_JUJU, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MM_EXTRA_LIFE_HUT, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), @@ -134,6 +156,12 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MUMBOS_MOUNTAIN_INTERIOR_TICKERS_TOWER] = RandoRegion{ .regionName = "Inside Tickers Tower", .mapId = MAP_C_MM_TICKERS_TOWER, .checks = { + CHECK(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), + CHECK(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), + CHECK(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), + CHECK(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), + CHECK(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), + CHECK(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), CHECK(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) || CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), CHECK(RC_MM_NOTE_INSIDE_TICKERS_TOWER_1, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), CHECK(RC_MM_NOTE_INSIDE_TICKERS_TOWER_2, CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), @@ -150,6 +178,18 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_MUMBOS_MOUNTAIN_INTERIOR_MUMBOS_SKULL] = RandoRegion{ .regionName = "Inside Mumbo's Skull", .mapId = MAP_E_MM_MUMBOS_SKULL, .checks = { + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, true), + CHECK(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, true), CHECK(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_1, true), CHECK(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_2, true), CHECK(RC_MM_NOTE_INSIDE_MUMBOS_SKULL_3, true), diff --git a/src/port/Rando/Logic/Regions/RustyBucketBay.cpp b/src/port/Rando/Logic/Regions/RustyBucketBay.cpp index b015e68d8..0101698e0 100644 --- a/src/port/Rando/Logic/Regions/RustyBucketBay.cpp +++ b/src/port/Rando/Logic/Regions/RustyBucketBay.cpp @@ -7,6 +7,28 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_ENTRANCE] = RandoRegion{ .regionName = "Rusty Bucket Bay", .mapId = MAP_31_RBB_RUSTY_BUCKET_BAY, .checks = { + CHECK(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, CAN_USE_ABILITY(ABILITY_6_EGGS) && (CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_10_TALON_TROT))), + CHECK(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, CAN_USE_ABILITY(ABILITY_6_EGGS) && (CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_10_TALON_TROT))), + CHECK(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, CAN_USE_ABILITY(ABILITY_6_EGGS) && (CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_10_TALON_TROT))), + CHECK(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, CAN_USE_ABILITY(ABILITY_6_EGGS) && (CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_10_TALON_TROT))), + CHECK(RC_RRB_BLUE_EGG_ENTRANCE_1, true), + CHECK(RC_RRB_BLUE_EGG_ENTRANCE_2, true), + CHECK(RC_RRB_BLUE_EGG_ENTRANCE_3, true), + CHECK(RC_RRB_BLUE_EGG_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RRB_BLUE_EGG_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, true), + CHECK(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, true), + CHECK(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, true), + CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, true), + CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, true), + CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, true), + CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, true), CHECK(RC_RBB_JIGGY_CRANE_CAGE, CAN_USE_ABILITY(ABILITY_0_BARGE) && CAN_USE_ABILITY(ABILITY_5_CLIMB) && CAN_USE_ABILITY(ABILITY_6_EGGS)), CHECK(RC_RBB_JIGGY_FUNNEL, CAN_USE_ABILITY(ABILITY_5_CLIMB)), CHECK(RC_RBB_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_9_RUSTY_BUCKET_BAY)), @@ -92,10 +114,14 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_ANCHOR] = RandoRegion{ .regionName = "Anchor Interior", .mapId = MAP_8B_RBB_ANCHOR_ROOM, .checks = { - CHECK(RC_RBB_NOTE_ANCHOR_ROOM_1, true), - CHECK(RC_RBB_NOTE_ANCHOR_ROOM_2, true), - CHECK(RC_RBB_NOTE_ANCHOR_ROOM_3, true), - CHECK(RC_RBB_NOTE_ANCHOR_ROOM_4, true), + CHECK(RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_RBB_NOTE_ANCHOR_ROOM_1, true), + CHECK(RC_RBB_NOTE_ANCHOR_ROOM_2, true), + CHECK(RC_RBB_NOTE_ANCHOR_ROOM_3, true), + CHECK(RC_RBB_NOTE_ANCHOR_ROOM_4, true), }, .connections = { CONNECTION(RR_RUSTY_BUCKET_BAY_ENTRANCE, CAN_USE_ABILITY(ABILITY_F_DIVE)), @@ -166,6 +192,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_ENGINE_ROOM_MAIN] = RandoRegion{ .regionName = "Engine Room Main", .mapId = MAP_34_RBB_ENGINE_ROOM, .checks = { + CHECK(RC_RBB_BLUE_EGG_ENGING_ROOM_1, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), + CHECK(RC_RBB_BLUE_EGG_ENGING_ROOM_2, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), + CHECK(RC_RBB_BLUE_EGG_ENGING_ROOM_3, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), + CHECK(RC_RBB_BLUE_EGG_ENGING_ROOM_4, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_RBB_JIGGY_ENGINE_ROOM, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), @@ -195,6 +225,15 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_KITCHEN] = RandoRegion{ .regionName = "Kitchen", .mapId = MAP_3C_RBB_KITCHEN, .checks = { + CHECK(RC_RBB_BLUE_EGG_KITCHEN_1, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_2, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_3, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_4, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_5, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_6, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_7, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_8, CAN_ATTACK), + CHECK(RC_RBB_BLUE_EGG_KITCHEN_9, CAN_ATTACK), CHECK(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, true), CHECK(RC_RBB_NOTE_KITCHEN_1, true), CHECK(RC_RBB_NOTE_KITCHEN_2, true), @@ -209,6 +248,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_NAVIGATION_ROOM] = RandoRegion{ .regionName = "Navigation Room", .mapId = MAP_3D_RBB_NAVIGATION_ROOM, .checks = { + CHECK(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, true), CHECK(RC_RBB_NOTE_NAVIGATION_ROOM_1, true), CHECK(RC_RBB_NOTE_NAVIGATION_ROOM_2, true), @@ -249,11 +292,17 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_SHIPPING_CONTAINER_THIRD] = RandoRegion{ .regionName = "Shipping Container Third", .mapId = MAP_38_RBB_CONTAINER_3, .checks = { - CHECK(RC_RBB_EXTRA_LIFE_BOOM_BOXES, CAN_ATTACK), - CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_1, true), - CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_2, true), - CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_3, true), - CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_4, true), + CHECK(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, true), + CHECK(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, true), + CHECK(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, true), + CHECK(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, true), + CHECK(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, true), + CHECK(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, true), + CHECK(RC_RBB_EXTRA_LIFE_BOOM_BOXES, CAN_ATTACK), + CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_1, true), + CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_2, true), + CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_3, true), + CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_THIRD_4, true), }, .connections = { CONNECTION(RR_RUSTY_BUCKET_BAY_ENTRANCE, true), @@ -262,6 +311,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_TNT_ROOM] = RandoRegion{ .regionName = "TNT Room", .mapId = MAP_3B_RBB_STORAGE_ROOM, .checks = { + CHECK(RC_RBB_BLUE_EGG_TNT_ROOM_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_TNT_ROOM_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_TNT_ROOM_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_TNT_ROOM_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_TNT_ROOM_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, true), CHECK(RC_RBB_NOTE_TNT_ROOM_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_RBB_NOTE_TNT_ROOM_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -276,10 +330,15 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_WAREHOUSE_LOWER] = RandoRegion{ .regionName = "Warehouse Lower", .mapId = MAP_35_RBB_WAREHOUSE, .checks = { - CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_1, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_2, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_3, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_4, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, CAN_EXTEND_JUMP_DISTANCE || (CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP))), + CHECK(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, CAN_EXTEND_JUMP_DISTANCE || (CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP))), + CHECK(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, CAN_EXTEND_JUMP_DISTANCE || (CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP))), + CHECK(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, CAN_EXTEND_JUMP_DISTANCE || (CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP))), + CHECK(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, CAN_EXTEND_JUMP_DISTANCE || (CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP))), + CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_1, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_2, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_3, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_NOTE_WAREHOUSE_INTERIOR_4, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), }, .connections = { CONNECTION(RR_RUSTY_BUCKET_BAY_ENTRANCE, true), diff --git a/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp b/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp index 4c9e97753..d05d16c7a 100644 --- a/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp +++ b/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp @@ -8,6 +8,29 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_TREASURE_TROVE_COVE_ENTRANCE] = RandoRegion{ .regionName = "Treasure Trove Cove", .mapId = MAP_7_TTC_TREASURE_TROVE_COVE, .checks = { // TODO: Logic for Flight because many checks are accessible with flight alone and don't need other methods like Shock Jump if Flight is usable + CHECK(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, true), + CHECK(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, true), + CHECK(RC_TTC_BLUE_EGG_LOCKUP_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_TTC_BLUE_EGG_LOCKUP_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_TTC_BLUE_EGG_LOCKUP_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_TTC_BLUE_EGG_LOCKUP_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_TTC_BLUE_EGG_LOCKUP_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_1, true), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_2, true), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_3, true), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_4, true), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_5, true), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_6, true), + CHECK(RC_TTC_BLUE_EGG_UPPER_POOL_7, true), CHECK(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, true), CHECK(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, CAN_EXTEND_JUMP_DISTANCE), @@ -179,6 +202,28 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_TREASURE_TROVE_COVE_LIGHTHOUSE_BASE] = RandoRegion{ .regionName = "Base of the Lighthouse", .mapId = MAP_7_TTC_TREASURE_TROVE_COVE, .checks = { + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, CAN_USE_ABILITY(ABILITY_5_CLIMB)), CHECK(RC_TTC_JINJO_YELLOW, CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WOODEN_DOOR) && CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_TTC_NOTE_LIGHTHOUSE_PATH_1, CAN_EXTEND_JUMP_DISTANCE), diff --git a/src/port/Rando/ObjectBehavior/Bundle.cpp b/src/port/Rando/ObjectBehavior/Bundle.cpp index 87f95ac89..963c787f8 100644 --- a/src/port/Rando/ObjectBehavior/Bundle.cpp +++ b/src/port/Rando/ObjectBehavior/Bundle.cpp @@ -59,8 +59,6 @@ void Rando::ObjectBehavior::InitBundleBehavior() { spawnPosition[1] = (int32_t)position[1]; spawnPosition[2] = (int32_t)position[2]; - SPDLOG_INFO("Bundle Spawn: {}", std::to_string(bundleId)); - if (bundleId == BUNDLE_16__HONEYCOMB && (currentMap == MAP_43_CCW_SPRING || currentMap == MAP_B_CC_CLANKERS_CAVERN)) { if (CheckEnemyOverlapPosition(spawnPosition)) { @@ -79,6 +77,10 @@ void Rando::ObjectBehavior::InitBundleBehavior() { randoCheckId = (RandoCheckId)((int32_t)RC_MM_NOTE_HUT_BUNDLE_1 + bundleCount); applyCustomPhysics = true; break; + case BUNDLE_1_MM_HUT_BLUE_EGG: + randoCheckId = (RandoCheckId)((int32_t)RC_MM_BLUE_EGG_HUT_BUNDLE_1 + bundleCount); + applyCustomPhysics = true; + break; case BUNDLE_3_MM_HUT_JINJO_GREEN: randoCheckId = RC_MM_JINJO_GREEN; applyCustomPhysics = true; diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index 74b8a92e9..6ce5d680f 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -33,6 +33,7 @@ std::vector actorSpawnWhitelist = { ACTOR_47_EMPTY_HONEYCOMB, ACTOR_49_EXTRA_LIFE, ACTOR_51_MUSIC_NOTE, + ACTOR_52_BLUE_EGG, ACTOR_5E_JINJO_YELLOW, ACTOR_5F_JINJO_ORANGE, ACTOR_60_JINJO_BLUE, @@ -45,6 +46,7 @@ std::vector actorSpawnWhitelist = { std::map randoItemColors = { { ACTOR_1_UNKNOWN, UIWidgets::Colors::Brown }, + { ACTOR_52_BLUE_EGG, UIWidgets::Colors::Cyan }, { ACTOR_47_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_49_EXTRA_LIFE, UIWidgets::Colors::Yellow }, { ACTOR_46_JIGGY, UIWidgets::Colors::Yellow }, @@ -391,6 +393,11 @@ void Rando::ObjectBehavior::Init() { event->Cancelled = true; } break; + case MARKER_60_BLUE_EGG_COLLECTIBLE: + if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_BLUE_EGGS].optionValue == RO_GENERIC_ON) { + randoItemId = randoSaveCheck.randoItemId; + } + break; case MARKER_61_EXTRA_LIFE: if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_EXTRA_LIVES].optionValue == RO_GENERIC_ON) { randoItemId = randoSaveCheck.randoItemId; diff --git a/src/port/Rando/ObjectBehavior/Prop.cpp b/src/port/Rando/ObjectBehavior/Prop.cpp index 12f9bb02d..db6b416b9 100644 --- a/src/port/Rando/ObjectBehavior/Prop.cpp +++ b/src/port/Rando/ObjectBehavior/Prop.cpp @@ -10,17 +10,23 @@ #include "spdlog/spdlog.h" -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue +#define BLUE_EGG_OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_BLUE_EGGS].optionValue +#define MUSIC_NOTE_OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue void Rando::ObjectBehavior::InitPropBehavior() { COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { s16* spawnPosition = va_arg(args, s16*); + int32_t propAsset = va_arg(args, int32_t); if (!IS_RANDO) { return; } - if (!OPTION_ENABLED) { + if (!BLUE_EGG_OPTION_ENABLED && propAsset == ASSET_6D7_SPRITE_BLUE_EGGS) { + return; + } + + if (!MUSIC_NOTE_OPTION_ENABLED && propAsset == ASSET_6D6_SPRITE_MUSIC_NOTE) { return; } diff --git a/src/port/Rando/StaticData/Checks.cpp b/src/port/Rando/StaticData/Checks.cpp index 433b02b49..d07a6df3d 100644 --- a/src/port/Rando/StaticData/Checks.cpp +++ b/src/port/Rando/StaticData/Checks.cpp @@ -24,6 +24,56 @@ std::array CheckNames = std::array(); // clang-format off std::map Checks = { RC(RC_UNKNOWN, RCTYPE_UNKNOWN, LEVEL_D_CUTSCENE, RI_UNKNOWN, NULL, 0, 0, 0), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4309, 100, 6025), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4368, 100, 6106), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4428, 100, 6198), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4484, 100, 6296), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4541, 100, 6389), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4133, 1400, -1304), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4208, 1400, -1422), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4343, 1400, -1422), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4412, 1400, -1304), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4342, 1400, -1184), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4207, 1400, -1184), + RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1185, 0, 0), + RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -1189, 0, 0), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 300, 0, -1830), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 150, 0, -1829), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -150, 0, -1832), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -300, 0, -1831), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7873, 1000, -6525), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7591, 1000, -6568), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7309, 1000, -6610), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7017, 1000, -6552), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -6729, 1000, -6507), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1250, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1350, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1450, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1250, 2740), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1350, 2740), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1450, 2740), + RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3209, 150, -253), + RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3403, 150, -761), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5917, 0, 2497), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5705, 0, 2672), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5283, 0, 3047), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5087, 0, 3251), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1813, 0, -2967), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1857, 0, -3096), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1889, 0, -3228), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -404, 0, -1715), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -518, 0, -1728), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -628, 0, -1744), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1497, 0, -3242), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1501, 0, -3121), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1506, 0, -3005), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -635, 0, -1361), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -528, 0, -1380), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -427, 0, -1398), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4592, 0, -3489), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4586, 0, -3710), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4809, 0, -3711), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4814, 0, -3490), RC(RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_7_BGS_MUMBOS, 0, 600, 0), RC(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_8_BGS_TANKTUP, 0, 537, -1157), RC(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, -4382, 985, 2799), @@ -157,6 +207,50 @@ std::map Checks = { RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2921, 93, -513), RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3020, 93, -304), RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3114, 93, -86), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6379, 5087, 2586), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6582, 5047, 2536), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6785, 4876, 2454), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6989, 4703, 2388), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 7194, 4526, 2321), + RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2588, 5456, 2596), + RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2494, 5456, 2556), + RC(RC_CC_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -5274, 3269, -270), + RC(RC_CC_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4937, 3221, -597), + RC(RC_CC_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4492, 3113, -449), + RC(RC_CC_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4392, 3051, -27), + RC(RC_CC_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4722, 3104, 299), + RC(RC_CC_BLUE_EGG_ENTRANCE_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -5159, 3232, 178), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2293, 3662, 2354), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2360, 3662, 2231), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2329, 3662, 2107), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2216, 3662, 2018), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2094, 3662, 1968), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 1970, 3662, 1998), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 1895, 3662, 2117), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -390, -116, 1316), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -476, -192, 480), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -433, -214, -453), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -390, -160, -1300), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 391, -160, -1300), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 434, -214, -453), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 476, -192, 480), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_8, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 389, -116, 1316), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 15075, 3648, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14862, 3649, -17), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14651, 3649, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14437, 3649, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14225, 3649, -20), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2392, 5200), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2293, 5276), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2197, 5350), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2099, 5425), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3854, 1202, -532), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3692, 1202, -356), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3529, 1202, -182), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3369, 1207, -10), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3206, 1202, 165), + RC(RC_CC_BLUE_EGG_YELLOW_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 4271, 5261, -2936), + RC(RC_CC_BLUE_EGG_YELLOW_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3247, 5262, -2842), RC(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_6_CC_ABOVE_WATER, 7886, 4272, 1969), RC(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_5_CC_UNDERWATER, 3718, 3311, 2519), RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 4570, 3727, 2783), @@ -283,6 +377,108 @@ std::map Checks = { RC(RC_CC_NOTE_UNDERWATER_PIPE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6804, 1184, 2361), RC(RC_CC_NOTE_YELLOW_GRATE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2240, 5262, -2473), RC(RC_CC_NOTE_YELLOW_GRATE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5270, 5261, -2937), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 825, 758, 531), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 682, 758, 583), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 536, 758, 628), + RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -113, 304, 3001), + RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 115, 605, 3001), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -170, 0, -700), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, -20, -630), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 170, 0, -699), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1362, 4419, 2014), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1860, 4469, 1580), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2181, 4519, 1118), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5700, 40, -1000), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5500, 40, -500), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5350, 40, 0), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3513, 4102, -541), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3595, 4104, 478), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3615, 2773, 1411), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4356, 2821, 356), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4920, 2778, 1222), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3735, 2828, -787), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4431, 2830, -882), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5370, 2882, -787), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3270, 103, -815), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3483, 109, -341), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3483, 99, 342), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3270, 121, 815), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3930, 4900, 316), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4378, 4900, 764), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5018, 4900, 773), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5468, 4900, 314), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5468, 4900, -315), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5018, 4900, -773), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4378, 4900, -764), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3930, 4900, -315), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 510, 387, 0), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, 398, 520), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, 398, -520), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 472, 413, -237), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 383, 413, -295), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 287, 413, -357), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 975, 900, 2573), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2566, 900, 968), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2568, 900, -968), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1950, 900, -1949), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 975, 900, -2574), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -50, 1050, -2750), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -975, 900, -2575), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2579, 1100, -980), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2579, 900, 980), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -977, 900, 2573), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2140, 2938, -1157), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1696, 3050, -1731), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1072, 3157, -2180), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 790, 3300, -2345), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1427, 3300, -1995), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1873, 3899, -1580), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2267, 3963, -1018), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2450, 4019, -394), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4366, -599, -311), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 5404, -593, -734), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 5831, -589, 301), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4769, -600, 726), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4302, 3719, 583), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4214, 3719, 1076), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3653, 3719, 1587), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3080, 3719, 2063), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -633, 5, -4826), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -727, 5, -5426), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -635, 5, -6006), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 9, 5, -6099), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 634, 5, -6008), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 726, 5, -5426), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 636, 5, -4834), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 9, 5, -4734), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4815, 125, 200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4930, 125, 0), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4815, 125, -201), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4585, 125, -200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4470, 125, 0), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4585, 125, 200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1153, 4019, 4293), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1284, 4019, 4611), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1599, 4019, 4747), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2047, 4019, 4303), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1920, 4019, 3996), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1603, 4019, 3851), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -285, 513, -354), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -395, 513, -280), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -504, 513, -205), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -577, 513, -110), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -646, 513, -5), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 253, -500, -621), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 617, -499, -263), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 621, -499, 254), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 258, -500, 624), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -254, -500, 621), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -622, -499, 259), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -624, -499, -254), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -262, -500, -619), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 244, 150, -509), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 88, 250, 682), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -531, 450, -430), RC(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_D_CCW_GNAWTYS, 694, 998, 632), RC(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_E_CCW_NABNUTS, 640, 513, -202), RC(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -225, 640, 506), @@ -438,6 +634,56 @@ std::map Checks = { RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1691, 5210, -2199), RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -764, 5590, -2634), RC(RC_CCW_SNS_YELLOW_EGG, RCTYPE_STOP_N_SWOP, LEVEL_8_CLICK_CLOCK_WOOD, RI_STOP_N_SWOP_EGG_YELLOW, SNS_ITEM_EGG_YELLOW, 556, 150, 47), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1536, 3505, 9857), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1606, 3505, 9635), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1674, 3505, 9422), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1610, 3505, 9197), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1545, 3505, 8981), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 404, 18, -2625), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 654, 18, -3169), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1410, 17, -2859), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1185, 18, -2295), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -344, 2110, -200), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -195, 2110, -343), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1, 2110, -399), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 199, 2110, -346), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 345, 2110, -199), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 395, 2110, 1), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 341, 2110, 196), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 199, 2110, 340), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 0, 2110, 393), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -198, 2110, 347), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -344, 2110, 198), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -396, 2110, 0), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1465, 7354, 1066), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1961, 7227, 248), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1734, 7166, -667), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -948, 7201, -1175), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -33, 7313, -984), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 496, 7442, -179), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 278, 7505, 757), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3128, -168, -4645), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2939, -168, -4791), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2759, -168, -4928), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2552, -168, -5061), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2367, -168, -5166), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2165, -168, -5146), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1979, -168, -5120), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1897, -168, -4931), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1824, -168, -4732), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1758, -168, -4514), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4112, -168, 5604), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3753, -168, 6126), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3887, -168, 6767), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4440, -168, 7130), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5069, -168, 6990), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5424, -168, 6438), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5280, -168, 5810), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4753, -168, 5455), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -6559, 0, -291), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -7119, 0, -113), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -7166, 0, 926), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -6599, 0, 1184), RC(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_A_FP_SIR_SLUSH, 4295, 441, 1268), RC(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_9_FP_WOZZAS_CAVE, -6531, 135, 422), RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, 6992, 1390, -3159), @@ -570,6 +816,73 @@ std::map Checks = { RC(RC_FP_NOTE_SNOWMAN_SCARF_18, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -941, 5605, 844), RC(RC_FP_NOTE_SNOWMAN_SCARF_19, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 17, 5605, 266), RC(RC_FP_SNS_ICE_KEY, RCTYPE_STOP_N_SWOP, LEVEL_5_FREEZEEZY_PEAK, RI_STOP_N_SWOP_ICE_KEY, SNS_ITEM_ICE_KEY, 1567, 583, 2416), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -1065), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -605), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -145), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 315), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 775), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 1235), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2799, 0, -2071), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2911, 0, -1907), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3016, 0, -1764), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3120, 0, -1616), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -9, -1395, 1178), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 382, -1395, 1090), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 820, -1395, 1183), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 820, -1395, 1692), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 445, -1395, 1832), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 27, -1395, 1781), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -185, -1395, 1477), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 3600), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4001), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4400), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4800), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6392, 122, 744), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6732, 277, 765), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7018, 426, 641), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7264, 495, 389), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7264, 496, -1392), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7018, 426, -1640), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6732, 277, -1767), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6392, 122, -1749), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2726, -176, -6393), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2986, -176, -6339), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3277, -176, -6332), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3552, -176, -6394), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1004, -800, 6827), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 888, -802, 6826), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -300, -792, 6800), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -458, -768, 6764), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1335, -1482, 1349), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1835, -1486, 485), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1832, -1486, -499), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1344, -1492, -1346), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -499, -1492, -1836), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 491, -1490, -1832), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1342, -1486, -1349), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1833, -1492, -491), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1846, -1492, 503), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1341, -1492, 1361), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -885, -749, 3037), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -98, -749, 3041), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 418, -750, 3577), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 422, -750, 4333), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -114, -750, 4871), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -864, -750, 4881), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1412, -750, 4335), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1410, -749, 3551), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1499, 0, 310), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1630, 0, 310), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1630, 0, 180), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1499, 0, 180), + RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 7900, 1750, -1445), + RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 7900, 1750, -1358), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -898, 0, -630), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -126, 0, -637), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 671, 0, -637), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 671, 0, 631), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -112, 0, 630), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -899, 0, 630), RC(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 0, 1600, -3700), RC(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -1992, 878, -3052), RC(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 2954, 1247, 100), @@ -596,6 +909,61 @@ std::map Checks = { RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 387, 2730, -6645), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 17, 2730, -6645), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -342, 2730, -6645), + RC(RC_GV_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1325, -59, 9447), + RC(RC_GV_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 845, -55, 9275), + RC(RC_GV_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 781, -51, 8805), + RC(RC_GV_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1214, -51, 8493), + RC(RC_GV_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1647, -56, 8820), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 712, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 612, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 511, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 517, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 612, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 712, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -856, 25, -1243), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -775, 25, -1243), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -775, 25, -1140), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -855, 25, -1140), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1139, 25, 880), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1139, 25, 961), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1240, 25, 964), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1240, 24, 884), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -985, 2432, 994), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1056, 2432, 466), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1137, 2432, -58), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -814, 2431, -394), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -472, 2432, -752), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 129, 2432, -740), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 740, 2432, -729), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 945, 2432, -392), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1151, 2431, -43), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1099, 2432, 473), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1039, 2432, 970), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2251, 0, -50), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2347, 0, 159), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2550, 0, 251), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2757, 0, 137), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2850, 0, -50), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2756, 0, -272), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2550, 0, -349), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2359, 0, -293), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4379, 1623, 6824), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4674, 1659, 6885), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4530, 1665, 6538), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4402, 1618, 5076), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4551, 1663, 5336), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4689, 1662, 5017), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -671, 13, -369), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -390, 13, 655), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 354, 13, -645), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 645, 13, 384), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1168, 3325, -5619), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 861, 3821, -5292), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 526, 4316, -3580), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 523, 4316, -4952), RC(RC_GV_EMPTY_HONEYCOMB_CACTUS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_B_GV_CACTUS, 2911, 3292, -3307), RC(RC_GV_EMPTY_HONEYCOMB_GOBI, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_C_GV_GOBI_3, -6885, 2383, 1335), RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -8948, 1332, 5500), @@ -728,6 +1096,46 @@ std::map Checks = { RC(RC_GV_NOTE_WATER_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -828, 3821, -3580), RC(RC_GV_NOTE_WATER_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -489, 4316, -4946), RC(RC_GV_SNS_BLUE_EGG, RCTYPE_STOP_N_SWOP, LEVEL_7_GOBIS_VALLEY, RI_STOP_N_SWOP_EGG_BLUE, SNS_ITEM_EGG_BLUE, 8, 470, -4141), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -131, 398, -496), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -362, 378, -362), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -487, 398, -146), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -493, 398, 101), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -352, 398, 371), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -131, 398, 496), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 136, 398, -499), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 361, 379, -363), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 498, 394, -129), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 495, 398, 133), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 359, 398, 362), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 134, 379, 497), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -10, 1507, -125), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -80, 1503, -71), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -74, 1521, 19), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3, 1510, 52), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 60, 1510, -87), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 67, 1510, 0), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5548, 200, 5984), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5706, 200, 5962), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5835, 201, 5896), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5911, 200, 5764), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5967, 200, 5615), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5927, 200, 5471), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5858, 200, 5343), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5732, 200, 5272), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5061, 298, 6090), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -4881, 299, 6135), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3958, 600, 6084), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3827, 600, 5997), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2840, 2355, -2408), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2811, 2355, -2445), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2776, 2355, -2494), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2743, 2355, -2538), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2713, 2355, -2576), RC(RC_MM_EMPTY_HONEYCOMB_HILL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_1_MM_HILL, 985, 484, 1681), RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), @@ -855,6 +1263,83 @@ std::map Checks = { RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 60, 817, -87), RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -10, 817, -125), RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -80, 817, -71), + RC(RC_MMM_BLUE_EGG_BEDROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 450), + RC(RC_MMM_BLUE_EGG_BEDROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 300), + RC(RC_MMM_BLUE_EGG_BEDROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 150), + RC(RC_MMM_BLUE_EGG_CELLAR_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -464, 40, -473), + RC(RC_MMM_BLUE_EGG_CELLAR_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -495, 40, -474), + RC(RC_MMM_BLUE_EGG_CELLAR_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -524, 40, -473), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 950, 588, 819), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2300, 588, 819), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2299, 588, 820), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -949, 588, 820), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2300, 588, 2369), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 950, 588, 2369), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -949, 588, 2370), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2299, 588, 2370), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4885, -2065), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2069, 4885, -1765), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2069, 4885, -1464), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4839, -2065), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4838, -1764), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4839, -1465), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2730), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2430), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2129), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2720), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2420), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2119), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, -480), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, -280), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -701, 0, -80), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 121), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 320), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 520), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -600, 0, 619), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -400, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -199, 0, 621), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 200, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 401, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 600, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 519), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 320), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 120), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -78), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -279), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -481), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -350, 550, -2499), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -176, 550, -2499), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 0, 550, -2500), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 174, 550, -2500), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 349, 550, -2500), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 446, 135, -339), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 450, 0, -35), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 450, 0, 36), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 35, 0, 351), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -36, 0, 350), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -442, 160, 331), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -437, 150, -336), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -302, 150, -336), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 225, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 61, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -103, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -268, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -442, -135, -390), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 50, 1100, -760), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 50, 1100, 1255), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 1942, 1100, 1255), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 1950, 1099, -758), + RC(RC_MMM_BLUE_EGG_MAZE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -1750, 0, 2410), + RC(RC_MMM_BLUE_EGG_MAZE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -1951, 0, 2655), + RC(RC_MMM_BLUE_EGG_MAZE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2446, 0, 760), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, -103), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, 452), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, 1008), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7174, -175, 1564), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 4200, -275, -2324), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 4200, -275, -2474), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7150, -273, -2383), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7149, -273, -2233), RC(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_12_MMM_FLOORBOARD, -51, -135, 52), RC(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_11_MMM_CHURCH_RAFTERS, 0, 5163, 2400), RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, -1, 2263, -3465), @@ -993,6 +1478,65 @@ std::map Checks = { RC(RC_MMM_NOTE_WELL_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 681, 0, 182), RC(RC_MMM_SNS_CYAN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_CYAN, SNS_ITEM_EGG_CYAN, 1995, 100, -476), RC(RC_MMM_SNS_GREEN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_GREEN, SNS_ITEM_EGG_GREEN, 517, 350, -241), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -450, 0, -750), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 450, 0, -751), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 450, 0, 750), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -450, 0, 750), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -750, -800, -3651), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -750, -800, -3726), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -50, -800, -3651), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -49, -800, -3726), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -3001), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2300), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2475), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2825), + RC(RC_RRB_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -550, -650, 3549), + RC(RC_RRB_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -1200, -450, 3899), + RC(RC_RRB_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -1750, -650, 3300), + RC(RC_RRB_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 1549, -500, 3250), + RC(RC_RRB_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 1900, -200, 3800), + RC(RC_RBB_BLUE_EGG_KITCHEN_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 702, 213, -596), + RC(RC_RBB_BLUE_EGG_KITCHEN_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 758, 213, -600), + RC(RC_RBB_BLUE_EGG_KITCHEN_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 647, 213, -601), + RC(RC_RBB_BLUE_EGG_KITCHEN_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 645, 213, -501), + RC(RC_RBB_BLUE_EGG_KITCHEN_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 705, 213, -503), + RC(RC_RBB_BLUE_EGG_KITCHEN_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 758, 213, -503), + RC(RC_RBB_BLUE_EGG_KITCHEN_7, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 760, 213, -408), + RC(RC_RBB_BLUE_EGG_KITCHEN_8, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 700, 213, -407), + RC(RC_RBB_BLUE_EGG_KITCHEN_9, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 646, 213, -404), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 590), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 409), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 230), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 50), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 3075), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 3550), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 4025), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6976, -2613, 3075), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6976, -2613, 3550), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6975, -2613, 4025), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -3721, -185, -1677), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -3953, -185, -1677), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -4185, -185, -1678), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -651, 140, -959), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -651, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -520, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -390, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -389, 140, -959), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -520, 140, -959), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 450), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 324), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 199), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -399, 400, 74), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, -49), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4500, -250, -1150), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 5050, 50, -1050), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4100, -250, 1150), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4650, 150, 1050), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -726, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -537, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -350, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -163, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 25, 575, 124), RC(RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_F_RBB_BOAT_HOUSE, 0, 1000, 0), RC(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_10_RBB_ENGINE_ROOM, 0, 360, 3541), RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -626, 140, -351), @@ -1143,6 +1687,56 @@ std::map Checks = { RC(RC_SM_MOLEHILL_CLIMB, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLIMB, ABILITY_5_CLIMB, -1999, 342, -2545), RC(RC_SM_MOLEHILL_DIVE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_DIVE, ABILITY_F_DIVE, -2336, 302, 973), RC(RC_SM_MOLEHILL_JUMP, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_FLAP_FLIP, ABILITY_8_FLAP_FLIP, -164, -190, 3313), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1667, 1639), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1792, 1639), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1917, 1639), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -2906, 1012, -6249), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -2941, 1011, -6045), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3580, 1062, -5526), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3808, 1062, -5389), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3978, 1312, -5163), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3995, 1312, -4990), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4215, 1411, -4547), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4413, 1412, -4482), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -106, -23, 186), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -142, -23, 315), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -267, -23, 318), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -306, -23, 212), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -215, -23, 117), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 1012, 5782, -2017), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 864, 5826, -1874), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 648, 5857, -1874), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 743, 6580, -3494), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 944, 6625, -3436), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 1077, 6667, -3226), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2475, 5793, -2303), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2357, 5791, -2182), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2351, 5822, -2417), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2241, 5819, -2305), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 720, 5819, -4297), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 869, 5820, -4332), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 750, 5791, -4131), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 918, 5793, -4172), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1269, 5795, -2811), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1147, 5822, -2700), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1145, 5792, -2928), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1037, 5818, -2802), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 687, 5822, -1177), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 843, 5819, -1172), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 857, 5793, -1336), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 689, 5794, -1347), + RC(RC_TTC_BLUE_EGG_LOCKUP_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3966, 1190, 1747), + RC(RC_TTC_BLUE_EGG_LOCKUP_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4051, 1190, 1793), + RC(RC_TTC_BLUE_EGG_LOCKUP_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4051, 1190, 1706), + RC(RC_TTC_BLUE_EGG_LOCKUP_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3882, 1190, 1795), + RC(RC_TTC_BLUE_EGG_LOCKUP_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3882, 1190, 1707), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -5319, 2470, -2929), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -5154, 2470, -3256), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4975, 2470, -3543), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4749, 2470, -3780), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4410, 2470, -3814), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4092, 2470, -3826), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3957, 2470, -3586), RC(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_4_TTC_FLOATING_BOX, 8473, 844, -2684), RC(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_3_TTC_UNDERWATER, -4303, 46, 115), RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, -2442, 3158, -1706), diff --git a/src/port/Rando/StaticData/Items.cpp b/src/port/Rando/StaticData/Items.cpp index e6f68467a..b1cf735c7 100644 --- a/src/port/Rando/StaticData/Items.cpp +++ b/src/port/Rando/StaticData/Items.cpp @@ -20,6 +20,16 @@ namespace StaticData { // clang-format off std::map Items = { RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN, LEVEL_D_CUTSCENE), + RI(RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, "a", "Blue Egg - BGS", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_BLUE_EGG_CLANKERS_CAVERN, "a", "Blue Egg - CC", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN), + RI(RI_BLUE_EGG_CLICK_CLOCK_WOOD, "a", "Blue Egg - CCW", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_BLUE_EGG_FREEZEEZY_PEAK, "a", "Blue Egg - FP", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_BLUE_EGG_GOBIS_VALLEY, "a", "Blue Egg - GV", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_7_GOBIS_VALLEY), + RI(RI_BLUE_EGG_GRUNTILDAS_LAIR, "a", "Blue Egg - Gl", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_6_LAIR), + RI(RI_BLUE_EGG_MAD_MONSTER_MANSION, "a", "Blue Egg - MMM", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_BLUE_EGG_MUMBOS_MOUNTAIN, "a", "Blue Egg - MM", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_BLUE_EGG_RUSTY_BUCKET_BAY, "a", "Blue Egg - RBB", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_BLUE_EGG_TREASURE_TROVE_COVE, "a", "Blue Egg - TTC", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE), RI(RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Empty Honeycomb - BGS", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, "a", "Empty Honeycomb - CC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), RI(RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Empty Honeycomb - CCW", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), diff --git a/src/port/Rando/StaticData/Options.cpp b/src/port/Rando/StaticData/Options.cpp index 7f3b8636a..88f303601 100644 --- a/src/port/Rando/StaticData/Options.cpp +++ b/src/port/Rando/StaticData/Options.cpp @@ -17,6 +17,7 @@ namespace StaticData { std::map Options = { RO(RO_LOGIC, RO_LOGIC_GLITCHLESS), RO(RO_SPAWN_JUNK, RO_GENERIC_OFF), + RO(RO_SHUFFLE_BLUE_EGGS, RO_GENERIC_OFF), RO(RO_SHUFFLE_EMPTY_HONEYCOMBS, RO_GENERIC_OFF), RO(RO_SHUFFLE_EXTRA_LIVES, RO_GENERIC_OFF), RO(RO_SHUFFLE_JIGGIES, RO_GENERIC_OFF), diff --git a/src/port/Rando/Types.h b/src/port/Rando/Types.h index 02b60292c..9b1f44c1d 100644 --- a/src/port/Rando/Types.h +++ b/src/port/Rando/Types.h @@ -10,6 +10,7 @@ typedef enum { typedef enum { RCTYPE_UNKNOWN, + RCTYPE_BLUE_EGG, RCTYPE_EMPTY_HONEYCOMB, RCTYPE_EXTRA_LIFE, RCTYPE_JIGGY, @@ -23,6 +24,56 @@ typedef enum { typedef enum { RC_UNKNOWN, + RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, + RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, + RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, + RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, + RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, + RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, + RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, + RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, + RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, + RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, + RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, + RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, + RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, + RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, + RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, + RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, + RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, + RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, + RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, + RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, + RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, + RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, + RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, + RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, + RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, + RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, + RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, + RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, + RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, + RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, + RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, + RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, + RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, + RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, + RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, + RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, + RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, + RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, + RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, + RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, + RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, + RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, + RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, + RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, + RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, + RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, + RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, + RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, + RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, + RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, @@ -156,6 +207,50 @@ typedef enum { RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_1, RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_2, RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, + RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, + RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, + RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, + RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, + RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, + RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, + RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, + RC_CC_BLUE_EGG_ENTRANCE_1, + RC_CC_BLUE_EGG_ENTRANCE_2, + RC_CC_BLUE_EGG_ENTRANCE_3, + RC_CC_BLUE_EGG_ENTRANCE_4, + RC_CC_BLUE_EGG_ENTRANCE_5, + RC_CC_BLUE_EGG_ENTRANCE_6, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, + RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, + RC_CC_BLUE_EGG_NEAR_RINGS_1, + RC_CC_BLUE_EGG_NEAR_RINGS_2, + RC_CC_BLUE_EGG_NEAR_RINGS_3, + RC_CC_BLUE_EGG_NEAR_RINGS_4, + RC_CC_BLUE_EGG_NEAR_RINGS_5, + RC_CC_BLUE_EGG_NEAR_RINGS_6, + RC_CC_BLUE_EGG_NEAR_RINGS_7, + RC_CC_BLUE_EGG_NEAR_RINGS_8, + RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, + RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, + RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, + RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, + RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, + RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, + RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, + RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, + RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, + RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, + RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, + RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, + RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, + RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, + RC_CC_BLUE_EGG_YELLOW_GRATE_1, + RC_CC_BLUE_EGG_YELLOW_GRATE_2, RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, @@ -282,6 +377,108 @@ typedef enum { RC_CC_NOTE_UNDERWATER_PIPE_7, RC_CC_NOTE_YELLOW_GRATE_1, RC_CC_NOTE_YELLOW_GRATE_2, + RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, + RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, + RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, + RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, + RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, + RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, + RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, + RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, + RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, + RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, + RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, + RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, + RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, + RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, + RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, + RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, + RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, + RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, + RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, + RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, + RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, + RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, + RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, + RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, + RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, + RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, + RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, + RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, + RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, + RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, + RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, + RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, + RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, + RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, + RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, + RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, + RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, + RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, + RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, + RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, + RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, + RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, + RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, + RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, + RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, + RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, + RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, + RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, + RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, + RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, + RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, + RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, + RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, + RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, + RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, + RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, + RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, + RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, @@ -437,6 +634,56 @@ typedef enum { RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_3, RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_4, RC_CCW_SNS_YELLOW_EGG, + RC_FP_BLUE_EGG_BEHIND_IGLOO_1, + RC_FP_BLUE_EGG_BEHIND_IGLOO_2, + RC_FP_BLUE_EGG_BEHIND_IGLOO_3, + RC_FP_BLUE_EGG_BEHIND_IGLOO_4, + RC_FP_BLUE_EGG_BEHIND_IGLOO_5, + RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, + RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, + RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, + RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, + RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, + RC_FP_BLUE_EGG_SNOWMANS_HAT_1, + RC_FP_BLUE_EGG_SNOWMANS_HAT_2, + RC_FP_BLUE_EGG_SNOWMANS_HAT_3, + RC_FP_BLUE_EGG_SNOWMANS_HAT_4, + RC_FP_BLUE_EGG_SNOWMANS_HAT_5, + RC_FP_BLUE_EGG_SNOWMANS_HAT_6, + RC_FP_BLUE_EGG_SNOWMANS_HAT_7, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, + RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, + RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, + RC_FP_BLUE_EGG_WOZZAS_CAVE_1, + RC_FP_BLUE_EGG_WOZZAS_CAVE_2, + RC_FP_BLUE_EGG_WOZZAS_CAVE_3, + RC_FP_BLUE_EGG_WOZZAS_CAVE_4, RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, @@ -569,6 +816,73 @@ typedef enum { RC_FP_NOTE_SNOWMAN_SCARF_18, RC_FP_NOTE_SNOWMAN_SCARF_19, RC_FP_SNS_ICE_KEY, + RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, + RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, + RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, + RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, + RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, + RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, + RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, + RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, + RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, + RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, + RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, + RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, + RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, + RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, + RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, + RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, + RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, + RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, + RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, + RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, + RC_GL_BLUE_EGG_MMM_ENTRANCE_1, + RC_GL_BLUE_EGG_MMM_ENTRANCE_2, + RC_GL_BLUE_EGG_MMM_ENTRANCE_3, + RC_GL_BLUE_EGG_MMM_ENTRANCE_4, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, + RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, + RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, + RC_GL_BLUE_EGG_RBB_ENTRANCE_1, + RC_GL_BLUE_EGG_RBB_ENTRANCE_2, + RC_GL_BLUE_EGG_RBB_ENTRANCE_3, + RC_GL_BLUE_EGG_RBB_ENTRANCE_4, + RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, + RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, + RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, + RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, + RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, + RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, + RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, + RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, @@ -595,6 +909,61 @@ typedef enum { RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, + RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, + RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, + RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, + RC_GV_BLUE_EGG_ENTRANCE_1, + RC_GV_BLUE_EGG_ENTRANCE_2, + RC_GV_BLUE_EGG_ENTRANCE_3, + RC_GV_BLUE_EGG_ENTRANCE_4, + RC_GV_BLUE_EGG_ENTRANCE_5, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, + RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, + RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, + RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, + RC_GV_BLUE_EGG_SPHYNX_LEFT_1, + RC_GV_BLUE_EGG_SPHYNX_LEFT_2, + RC_GV_BLUE_EGG_SPHYNX_LEFT_3, + RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, + RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, + RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, + RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, + RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, + RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, + RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, + RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, + RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, + RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, + RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, RC_GV_EMPTY_HONEYCOMB_CACTUS, RC_GV_EMPTY_HONEYCOMB_GOBI, RC_GV_EXTRA_LIFE_BEHIND_JINXY, @@ -727,6 +1096,46 @@ typedef enum { RC_GV_NOTE_WATER_PYRAMID_TOP_3, RC_GV_NOTE_WATER_PYRAMID_TOP_4, RC_GV_SNS_BLUE_EGG, + RC_MM_BLUE_EGG_HUT_BUNDLE_1, + RC_MM_BLUE_EGG_HUT_BUNDLE_2, + RC_MM_BLUE_EGG_HUT_BUNDLE_3, + RC_MM_BLUE_EGG_HUT_BUNDLE_4, + RC_MM_BLUE_EGG_HUT_BUNDLE_5, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, + RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, + RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, + RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, + RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, + RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, + RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, + RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, + RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, + RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, + RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, + RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, + RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, + RC_MM_BLUE_EGG_UNDER_RUINS_1, + RC_MM_BLUE_EGG_UNDER_RUINS_2, + RC_MM_BLUE_EGG_UNDER_RUINS_3, + RC_MM_BLUE_EGG_UNDER_RUINS_4, + RC_MM_BLUE_EGG_UNDER_RUINS_5, RC_MM_EMPTY_HONEYCOMB_HILL, RC_MM_EMPTY_HONEYCOMB_JUJU, RC_MM_EXTRA_LIFE_HUT, @@ -854,6 +1263,83 @@ typedef enum { RC_MM_NOTE_INSIDE_TICKERS_TOWER_4, RC_MM_NOTE_INSIDE_TICKERS_TOWER_5, RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, + RC_MMM_BLUE_EGG_BEDROOM_1, + RC_MMM_BLUE_EGG_BEDROOM_2, + RC_MMM_BLUE_EGG_BEDROOM_3, + RC_MMM_BLUE_EGG_CELLAR_1, + RC_MMM_BLUE_EGG_CELLAR_2, + RC_MMM_BLUE_EGG_CELLAR_3, + RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, + RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, + RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, + RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, + RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, + RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, + RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, + RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, + RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, + RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, + RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, + RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, + RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, + RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, + RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, + RC_MMM_BLUE_EGG_EGG_ROOM_1, + RC_MMM_BLUE_EGG_EGG_ROOM_2, + RC_MMM_BLUE_EGG_EGG_ROOM_3, + RC_MMM_BLUE_EGG_EGG_ROOM_4, + RC_MMM_BLUE_EGG_EGG_ROOM_5, + RC_MMM_BLUE_EGG_EGG_ROOM_6, + RC_MMM_BLUE_EGG_EGG_ROOM_7, + RC_MMM_BLUE_EGG_EGG_ROOM_8, + RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, + RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, + RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, + RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, + RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, + RC_MMM_BLUE_EGG_MANSION_AWNING_1, + RC_MMM_BLUE_EGG_MANSION_AWNING_2, + RC_MMM_BLUE_EGG_MANSION_AWNING_3, + RC_MMM_BLUE_EGG_MANSION_AWNING_4, + RC_MMM_BLUE_EGG_MAZE_1, + RC_MMM_BLUE_EGG_MAZE_2, + RC_MMM_BLUE_EGG_MAZE_3, + RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, + RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, + RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, + RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, + RC_MMM_BLUE_EGG_NEAR_WELL_1, + RC_MMM_BLUE_EGG_NEAR_WELL_2, + RC_MMM_BLUE_EGG_NEAR_WELL_3, + RC_MMM_BLUE_EGG_NEAR_WELL_4, RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RC_MMM_EXTRA_LIFE_CHURCH_PIPES, @@ -992,6 +1478,65 @@ typedef enum { RC_MMM_NOTE_WELL_INTERIOR_7, RC_MMM_SNS_CYAN_EGG, RC_MMM_SNS_GREEN_EGG, + RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, + RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, + RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, + RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, + RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, + RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, + RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, + RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, + RC_RBB_BLUE_EGG_ENGING_ROOM_1, + RC_RBB_BLUE_EGG_ENGING_ROOM_2, + RC_RBB_BLUE_EGG_ENGING_ROOM_3, + RC_RBB_BLUE_EGG_ENGING_ROOM_4, + RC_RRB_BLUE_EGG_ENTRANCE_1, + RC_RRB_BLUE_EGG_ENTRANCE_2, + RC_RRB_BLUE_EGG_ENTRANCE_3, + RC_RRB_BLUE_EGG_ENTRANCE_4, + RC_RRB_BLUE_EGG_ENTRANCE_5, + RC_RBB_BLUE_EGG_KITCHEN_1, + RC_RBB_BLUE_EGG_KITCHEN_2, + RC_RBB_BLUE_EGG_KITCHEN_3, + RC_RBB_BLUE_EGG_KITCHEN_4, + RC_RBB_BLUE_EGG_KITCHEN_5, + RC_RBB_BLUE_EGG_KITCHEN_6, + RC_RBB_BLUE_EGG_KITCHEN_7, + RC_RBB_BLUE_EGG_KITCHEN_8, + RC_RBB_BLUE_EGG_KITCHEN_9, + RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, + RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, + RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, + RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, + RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, + RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, + RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, + RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, + RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, + RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, + RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, + RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, + RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, + RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, + RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, + RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, + RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, + RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, + RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, + RC_RBB_BLUE_EGG_TNT_ROOM_1, + RC_RBB_BLUE_EGG_TNT_ROOM_2, + RC_RBB_BLUE_EGG_TNT_ROOM_3, + RC_RBB_BLUE_EGG_TNT_ROOM_4, + RC_RBB_BLUE_EGG_TNT_ROOM_5, + RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, + RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, + RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, + RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, + RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, + RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, + RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, + RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, + RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RC_RBB_EXTRA_LIFE_BOOM_BOXES, @@ -1142,6 +1687,56 @@ typedef enum { RC_SM_MOLEHILL_CLIMB, RC_SM_MOLEHILL_DIVE, RC_SM_MOLEHILL_JUMP, + RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, + RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, + RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, + RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, + RC_TTC_BLUE_EGG_INSIDE_NIPPER_1, + RC_TTC_BLUE_EGG_INSIDE_NIPPER_2, + RC_TTC_BLUE_EGG_INSIDE_NIPPER_3, + RC_TTC_BLUE_EGG_INSIDE_NIPPER_4, + RC_TTC_BLUE_EGG_INSIDE_NIPPER_5, + RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, + RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, + RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, + RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, + RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, + RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, + RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, + RC_TTC_BLUE_EGG_LOCKUP_1, + RC_TTC_BLUE_EGG_LOCKUP_2, + RC_TTC_BLUE_EGG_LOCKUP_3, + RC_TTC_BLUE_EGG_LOCKUP_4, + RC_TTC_BLUE_EGG_LOCKUP_5, + RC_TTC_BLUE_EGG_UPPER_POOL_1, + RC_TTC_BLUE_EGG_UPPER_POOL_2, + RC_TTC_BLUE_EGG_UPPER_POOL_3, + RC_TTC_BLUE_EGG_UPPER_POOL_4, + RC_TTC_BLUE_EGG_UPPER_POOL_5, + RC_TTC_BLUE_EGG_UPPER_POOL_6, + RC_TTC_BLUE_EGG_UPPER_POOL_7, RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, @@ -1280,6 +1875,7 @@ typedef enum { typedef enum { RITYPE_UNKNOWN, + RITYPE_BLUE_EGG, RITYPE_EMPTY_HONEYCOMB, RITYPE_EXTRA_LIFE, RITYPE_JIGGY, @@ -1294,6 +1890,16 @@ typedef enum { typedef enum { RI_UNKNOWN, + RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, + RI_BLUE_EGG_CLANKERS_CAVERN, + RI_BLUE_EGG_CLICK_CLOCK_WOOD, + RI_BLUE_EGG_FREEZEEZY_PEAK, + RI_BLUE_EGG_GOBIS_VALLEY, + RI_BLUE_EGG_GRUNTILDAS_LAIR, + RI_BLUE_EGG_MAD_MONSTER_MANSION, + RI_BLUE_EGG_MUMBOS_MOUNTAIN, + RI_BLUE_EGG_RUSTY_BUCKET_BAY, + RI_BLUE_EGG_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, @@ -1621,6 +2227,7 @@ typedef enum { typedef enum { RO_LOGIC, RO_SPAWN_JUNK, + RO_SHUFFLE_BLUE_EGGS, RO_SHUFFLE_EMPTY_HONEYCOMBS, RO_SHUFFLE_EXTRA_LIVES, RO_SHUFFLE_JIGGIES, diff --git a/src/port/ShipUtils.cpp b/src/port/ShipUtils.cpp index 1ed80e94a..087f900dd 100644 --- a/src/port/ShipUtils.cpp +++ b/src/port/ShipUtils.cpp @@ -329,17 +329,10 @@ std::vector worldOpenFlags = { }; std::unordered_map levelAbbreviations = { - { "MM", "Mumbos Mountain" }, - { "TTC", "Treasure Trove Cove" }, - { "CC", "Clankers Cavern" }, - { "BGS", "Bubblegloop Swamp" }, - { "FP", "Freezeezy Peak" }, - { "GL", "Gruntildas Lair" }, - { "GV", "Gobis Valley" }, - { "CCW", "Click Clock Wood" }, - { "RBB", "Rusty Bucket Bay" }, - { "MMM", "Mad Monster Mansion" }, - { "SM", "Spiral Mountain" }, + { "MM", "Mumbos Mountain" }, { "TTC", "Treasure Trove Cove" }, { "CC", "Clankers Cavern" }, + { "BGS", "Bubblegloop Swamp" }, { "FP", "Freezeezy Peak" }, { "GL", "Gruntildas Lair" }, + { "GV", "Gobis Valley" }, { "CCW", "Click Clock Wood" }, { "RBB", "Rusty Bucket Bay" }, + { "MMM", "Mad Monster Mansion" }, { "SM", "Spiral Mountain" }, }; json Ship_RetrieveSaveFile(int32_t filenum) { diff --git a/src/port/UI/DeveloperTools/SaveEditor.cpp b/src/port/UI/DeveloperTools/SaveEditor.cpp index f11655557..d93c46eba 100644 --- a/src/port/UI/DeveloperTools/SaveEditor.cpp +++ b/src/port/UI/DeveloperTools/SaveEditor.cpp @@ -398,8 +398,10 @@ void DrawRandoCheckEditor() { ImGui::TableSetupColumn("shuffled", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("obtained", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("skipped", ImGuiTableColumnFlags_WidthFixed, 34.0f); - ImGui::TableSetupColumn("checkName", ImGuiTableColumnFlags_WidthFixed, (ImGui::GetContentRegionAvail().x - 34.0f) * 0.60f); - ImGui::TableSetupColumn("itemName", ImGuiTableColumnFlags_WidthFixed, (ImGui::GetContentRegionAvail().x - 34.0f) * 0.25f); + ImGui::TableSetupColumn("checkName", ImGuiTableColumnFlags_WidthFixed, + (ImGui::GetContentRegionAvail().x - 34.0f) * 0.60f); + ImGui::TableSetupColumn("itemName", ImGuiTableColumnFlags_WidthFixed, + (ImGui::GetContentRegionAvail().x - 34.0f) * 0.25f); ImGui::TableSetupColumn("collectionId", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableNextColumn(); From c3b05bc76f4e1995fc3f2cc4f3b22eafaa5ab324 Mon Sep 17 00:00:00 2001 From: Douglas Simpson Date: Fri, 10 Jul 2026 10:18:50 -0500 Subject: [PATCH 6/8] [RANDO] Develop rando v2 beehive shuffle (#249) * Added functionality to shuffle honeycombs from beehives * Added logic to each region for Beehive Shuffle Deleted an extra check for FP Witch Switch in GruntildasLair.cpp Moved Extra Life Shuffle to advanced shuffle menu * Adjusted name for option in LighthouseMenuRando.cpp --- src/port/Rando/LighthouseMenuRando.cpp | 9 +- src/port/Rando/Logic/GeneratePools.cpp | 5 + .../Rando/Logic/Regions/BubblegloopSwamp.cpp | 12 + .../Rando/Logic/Regions/ClankersCavern.cpp | 29 +- .../Rando/Logic/Regions/ClickClockWood.cpp | 214 +++++++++------ .../Rando/Logic/Regions/FreezeezyPeak.cpp | 96 ++++--- src/port/Rando/Logic/Regions/GobisValley.cpp | 243 +++++++++-------- .../Rando/Logic/Regions/GruntildasLair.cpp | 87 ++++-- .../Rando/Logic/Regions/MadMonsterMansion.cpp | 12 + .../Rando/Logic/Regions/MumbosMountain.cpp | 6 + .../Rando/Logic/Regions/RustyBucketBay.cpp | 9 + .../Rando/Logic/Regions/TreasureTroveCove.cpp | 12 + src/port/Rando/ObjectBehavior/Bundle.cpp | 253 ++++++++++++++++++ .../Rando/ObjectBehavior/ObjectBehavior.cpp | 11 + src/port/Rando/StaticData/Checks.cpp | 153 +++++++++++ src/port/Rando/StaticData/Items.cpp | 11 + src/port/Rando/StaticData/Options.cpp | 23 +- src/port/Rando/Types.h | 167 ++++++++++++ 18 files changed, 1055 insertions(+), 297 deletions(-) diff --git a/src/port/Rando/LighthouseMenuRando.cpp b/src/port/Rando/LighthouseMenuRando.cpp index 53d7ec8d5..0a5a8117a 100644 --- a/src/port/Rando/LighthouseMenuRando.cpp +++ b/src/port/Rando/LighthouseMenuRando.cpp @@ -109,9 +109,6 @@ void LighthouseMenu::AddMenuRando() { AddWidget(path, "Shuffle Empty Honeycombs", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_EMPTY_HONEYCOMBS].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Empty Honeycombs into the Pool.")); - AddWidget(path, "Shuffle Extra Lives", WIDGET_CVAR_CHECKBOX) - .CVar(Rando::StaticData::Options[RO_SHUFFLE_EXTRA_LIVES].cvar) - .Options(CheckboxOptions().Tooltip("Shuffles Extra Lives into the Pool.")); AddWidget(path, "Shuffle Jiggies", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_JIGGIES].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Jiggies into the Pool.")); @@ -127,9 +124,15 @@ void LighthouseMenu::AddMenuRando() { AddWidget(path, "Advanced Shuffles", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Shuffle Beehive Contents", WIDGET_CVAR_CHECKBOX) + .CVar(Rando::StaticData::Options[RO_SHUFFLE_BEEHIVE_HONEYCOMBS].cvar) + .Options(CheckboxOptions().Tooltip("Shuffles Contents of Beehives into the Pool.")); AddWidget(path, "Shuffle Blue Eggs", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_BLUE_EGGS].cvar) .Options(CheckboxOptions().Tooltip("Shuffles Blue Eggs into the Pool.")); + AddWidget(path, "Shuffle Extra Lives", WIDGET_CVAR_CHECKBOX) + .CVar(Rando::StaticData::Options[RO_SHUFFLE_EXTRA_LIVES].cvar) + .Options(CheckboxOptions().Tooltip("Shuffles Extra Lives into the Pool.")); AddWidget(path, "Shuffle Molehills", WIDGET_CVAR_CHECKBOX) .CVar(Rando::StaticData::Options[RO_SHUFFLE_MOLEHILLS].cvar) .Options(CheckboxOptions().Tooltip("Shuffles which abilities each Molehill unlocks.")); diff --git a/src/port/Rando/Logic/GeneratePools.cpp b/src/port/Rando/Logic/GeneratePools.cpp index 589807047..64aca987e 100644 --- a/src/port/Rando/Logic/GeneratePools.cpp +++ b/src/port/Rando/Logic/GeneratePools.cpp @@ -61,6 +61,11 @@ void GenerateShufflePool(SaveData* saveData) { continue; } + if (randoStaticCheck.randoCheckType == RCTYPE_HONEYCOMB && + CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_BEEHIVE_HONEYCOMBS].cvar, 0) == RO_GENERIC_OFF) { + continue; + } + if (randoStaticCheck.randoCheckType == RCTYPE_JIGGY && CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_JIGGIES].cvar, 0) == RO_GENERIC_OFF) { continue; diff --git a/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp b/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp index a3db78af0..f2090606a 100644 --- a/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp +++ b/src/port/Rando/Logic/Regions/BubblegloopSwamp.cpp @@ -53,6 +53,18 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), CHECK(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC)), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, CAN_EXTEND_JUMP_DISTANCE && CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, CAN_EXTEND_JUMP_DISTANCE && CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, CAN_EXTEND_JUMP_DISTANCE && CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, CAN_ATTACK), + CHECK(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, CAN_ATTACK), CHECK(RC_BGS_JIGGY_CROCTUS, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP) && CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS) || CAN_USE_ABILITY(ABILITY_12_WONDERWING)), CHECK(RC_BGS_JIGGY_ELEVATED_WALKWAY, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), CHECK(RC_BGS_JIGGY_FLIBBITS, CAN_USE_TRANSFORMATION(TRANSFORM_5_CROC) || CAN_ATTACK), diff --git a/src/port/Rando/Logic/Regions/ClankersCavern.cpp b/src/port/Rando/Logic/Regions/ClankersCavern.cpp index 64cec4403..df842726b 100644 --- a/src/port/Rando/Logic/Regions/ClankersCavern.cpp +++ b/src/port/Rando/Logic/Regions/ClankersCavern.cpp @@ -24,16 +24,19 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLANKERS_CAVERN_ENTRANCE_UPPER] = RandoRegion{ .regionName = "Upper Entrance", .mapId = MAP_B_CC_CLANKERS_CAVERN, .checks = { - CHECK(RC_CC_JINJO_YELLOW, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_1, true), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_2, true), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_3, true), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_4, true), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_5, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_6, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_7, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_8, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_CC_JINJO_YELLOW, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_1, true), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_2, true), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_3, true), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_4, true), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_5, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_6, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_7, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_CC_NOTE_NEAR_LEVEL_ENTRANCE_8, CAN_EXTEND_JUMP_DISTANCE), }, .connections = { CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE, CAN_USE_ABILITY(ABILITY_F_DIVE)), @@ -70,6 +73,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), CHECK(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, CAN_ACCESS_REGION(RR_CLANKERS_CAVERN_UNDERWATER_LOCK)), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, CAN_ATTACK), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, CAN_ATTACK), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, CAN_ATTACK), CHECK(RC_CC_JIGGY_RINGS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_CC_JINJO_PINK, true), CHECK(RC_CC_JIGGY_TOOTH, true), @@ -151,6 +157,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_CC_BLUE_EGG_YELLOW_GRATE_2, CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, true), CHECK(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, true), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, CAN_ATTACK), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, CAN_ATTACK), + CHECK(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, CAN_ATTACK), CHECK(RC_CC_JIGGY_BOLT, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_CC_JIGGY_CLANKER_RAISED, true), CHECK(RC_CC_JIGGY_LONG_PIPE, true), diff --git a/src/port/Rando/Logic/Regions/ClickClockWood.cpp b/src/port/Rando/Logic/Regions/ClickClockWood.cpp index 8d95c49ce..99146fae7 100644 --- a/src/port/Rando/Logic/Regions/ClickClockWood.cpp +++ b/src/port/Rando/Logic/Regions/ClickClockWood.cpp @@ -7,53 +7,62 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_AUTUMN] = RandoRegion{ .regionName = "Autumn Season", .mapId = MAP_45_CCW_AUTUMN, .checks = { - CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, true), - CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, true), - CHECK(RC_CCW_JIGGY_FLOWER, true), - CHECK(RC_CCW_JIGGY_GNAWTY, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_CCW_JINJO_ORANGE, true), - CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, true), - CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, true), - CHECK(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_1, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_2, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_1, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_2, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_3, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_4, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_5, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_6, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_7, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_8, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_9, true), - CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_10, true), - CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_1, true), - CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_2, true), - CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_3, true), - CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_4, true), - CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_5, true), - CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_1, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_2, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_3, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, true), + CHECK(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, true), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, CAN_ATTACK), + CHECK(RC_CCW_JIGGY_FLOWER, true), + CHECK(RC_CCW_JIGGY_GNAWTY, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_JINJO_ORANGE, true), + CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, true), + CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, true), + CHECK(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_1, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_NOTE_AUTUMN_GNAWTYS_INTERIOR_2, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_1, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_2, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_3, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_4, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_5, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_6, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_7, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_8, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_9, true), + CHECK(RC_CCW_NOTE_AUTUMN_LOWER_TREE_LEDGE_10, true), + CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_1, true), + CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_2, true), + CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_3, true), + CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_4, true), + CHECK(RC_CCW_NOTE_AUTUMN_NEAR_BIG_FLOWER_5, true), + CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_1, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_2, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_BIG_FLOWER_3, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_NOTE_AUTUMN_SNAREBEAR_NEAR_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_AUTUMN_INTERIOR_BEEHIVE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), @@ -146,15 +155,21 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_ENTRANCE] = RandoRegion{ .regionName = "Click Clock Wood Entrance", .mapId = MAP_40_CCW_HUB, .checks = { - CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, true), - CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, true), - CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, true), - CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, true), - CHECK(RC_CCW_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_8_CLICK_CLOCK_WOOD)), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_1, true), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_2, true), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_3, true), - CHECK(RC_CCW_NOTE_ENTRANCE_HUB_4, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, true), + CHECK(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, true), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, CAN_ATTACK), + CHECK(RC_CCW_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_8_CLICK_CLOCK_WOOD)), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_1, true), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_2, true), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_3, true), + CHECK(RC_CCW_NOTE_ENTRANCE_HUB_4, true), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SPRING, CAN_ACCESS(RA_TRIGGER_SWITCH_CCW_SPRING)), @@ -194,6 +209,15 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, CAN_ATTACK), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, CAN_USE_ABILITY(ABILITY_12_WONDERWING) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, CAN_USE_ABILITY(ABILITY_12_WONDERWING) || CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), @@ -304,35 +328,41 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_CLICK_CLOCK_WOOD_SUMMER] = RandoRegion{ .regionName = "Summer Season", .mapId = MAP_44_CCW_SUMMER, .checks = { - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, true), - CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, true), - CHECK(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, true), - CHECK(RC_CCW_JIGGY_SUMMER_LEAF_JUMPS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), - CHECK(RC_CCW_JINJO_YELLOW, true), - CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, true), - CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, CAN_ACCESS(RA_GNAWTYS_BOULDER)), - CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, CAN_ATTACK && CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), - CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), - CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), - CHECK(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_1, CAN_ACCESS(RA_GNAWTYS_BOULDER)), - CHECK(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_2, CAN_ACCESS(RA_GNAWTYS_BOULDER)), - CHECK(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_1, true), - CHECK(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_2, true), - CHECK(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_1, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), - CHECK(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_2, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), - CHECK(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_3, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, true), + CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, true), + CHECK(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, true), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_CCW_JIGGY_SUMMER_LEAF_JUMPS, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_CCW_JINJO_YELLOW, true), + CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, true), + CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, CAN_ACCESS(RA_GNAWTYS_BOULDER)), + CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, CAN_ATTACK && CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, CAN_USE_ABILITY(ABILITY_12_WONDERWING)), + CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_1, CAN_ACCESS(RA_GNAWTYS_BOULDER)), + CHECK(RC_CCW_NOTE_SUMMER_GNAWTYS_ENTRANCE_2, CAN_ACCESS(RA_GNAWTYS_BOULDER)), + CHECK(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_1, true), + CHECK(RC_CCW_NOTE_SUMMER_LEAF_NEAR_ENTRANCE_2, true), + CHECK(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_1, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_2, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_CCW_NOTE_SUMMER_NEAR_BEEHIVE_3, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_SUMMER_INTERIOR_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), @@ -387,6 +417,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, true), CHECK(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, true), CHECK(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, true), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, CAN_ATTACK), CHECK(RC_CCW_JIGGY_HOUSE, true), CHECK(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, true), CHECK(RC_CCW_NOTE_SUMMER_OUTSIDE_NABNUTS_HOUSE_1, true), @@ -411,6 +444,12 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_9_FLIGHT) && CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB)), CHECK(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, CAN_ACCESS(RA_GNAWTYS_BOULDER) && CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, CAN_ATTACK), CHECK(RC_CCW_JINJO_BLUE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) || CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, true), CHECK(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, true), @@ -427,6 +466,11 @@ static RegisterShipInitFunc initFunc([]() { }; Regions[RR_CLICK_CLOCK_WOOD_WINTER_INTERIOR_MUMBOS_SKULL] = RandoRegion{ .regionName = "Winter - Inside Mumbo's Skull", .mapId = MAP_4D_CCW_WINTER_MUMBOS_SKULL, + .checks = { + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, CAN_ATTACK), + CHECK(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, CAN_ATTACK), + }, .connections = { CONNECTION(RR_CLICK_CLOCK_WOOD_WINTER, true), }, diff --git a/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp b/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp index 7c838c9c3..9c8d79cf0 100644 --- a/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp +++ b/src/port/Rando/Logic/Regions/FreezeezyPeak.cpp @@ -103,6 +103,15 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), CHECK(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, CAN_ATTACK), CHECK(RC_FP_JIGGY_BOGGY_RACE_1, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS)), CHECK(RC_FP_JIGGY_BOGGY_RACE_2, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_TRANSFORMATION(TRANSFORM_4_WALRUS) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), CHECK(RC_FP_JIGGY_SNOWMANS_BUTTONS, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), @@ -172,48 +181,51 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_FREEZEEZY_PEAK_MAIN_UPPER] = RandoRegion{ .regionName = "Upper Area near the Snowman", .mapId = MAP_27_FP_FREEZEEZY_PEAK, .checks = { - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_JIGGY_SNOWMANS_PIPE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), - CHECK(RC_FP_JINJO_BLUE, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), - CHECK(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), - CHECK(RC_FP_NOTE_NEAR_WOZZA_1, true), - CHECK(RC_FP_NOTE_NEAR_WOZZA_2, true), - CHECK(RC_FP_NOTE_NEAR_WOZZA_3, true), - CHECK(RC_FP_NOTE_NEAR_WOZZA_4, true), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_1, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_2, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_3, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_4, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_5, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_6, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_7, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_HAT_8, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_1, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_2, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_3, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_4, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_5, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_6, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_7, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_8, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_9, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_10, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_11, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_12, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_13, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_14, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_15, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_16, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_17, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_18, true), - CHECK(RC_FP_NOTE_SNOWMAN_SCARF_19, true), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, CAN_ATTACK), + CHECK(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, CAN_ATTACK), + CHECK(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, CAN_USE_ABILITY(ABILITY_1_BEAK_BOMB) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_JIGGY_SNOWMANS_PIPE, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_FP_JINJO_BLUE, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, CAN_USE_ABILITY(ABILITY_10_TALON_TROT)), + CHECK(RC_FP_NOTE_NEAR_WOZZA_1, true), + CHECK(RC_FP_NOTE_NEAR_WOZZA_2, true), + CHECK(RC_FP_NOTE_NEAR_WOZZA_3, true), + CHECK(RC_FP_NOTE_NEAR_WOZZA_4, true), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_1, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_2, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_3, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_4, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_5, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_6, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_7, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_HAT_8, CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_1, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_2, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_3, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_4, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_5, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_6, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_7, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_8, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_9, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_10, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_11, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_12, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_13, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_14, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_15, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_16, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_17, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_18, true), + CHECK(RC_FP_NOTE_SNOWMAN_SCARF_19, true), }, .connections = { CONNECTION(RR_FREEZEEZY_PEAK_MAIN_LOWER, true), diff --git a/src/port/Rando/Logic/Regions/GobisValley.cpp b/src/port/Rando/Logic/Regions/GobisValley.cpp index effb49f3f..41223fd72 100644 --- a/src/port/Rando/Logic/Regions/GobisValley.cpp +++ b/src/port/Rando/Logic/Regions/GobisValley.cpp @@ -7,28 +7,31 @@ using namespace Rando::Logic; static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_ENTRANCE] = RandoRegion{ .regionName = "Gobi's Valley", .mapId = MAP_12_GV_GOBIS_VALLEY, .checks = { - CHECK(RC_GV_BLUE_EGG_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_GV_BLUE_EGG_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_GV_BLUE_EGG_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_GV_BLUE_EGG_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_GV_BLUE_EGG_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), - CHECK(RC_GV_EMPTY_HONEYCOMB_GOBI, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_JIGGY_GOBI_2, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_5_CLIMB)), - CHECK(RC_GV_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_7_GOBIS_VALLEY)), - CHECK(RC_GV_JINJO_BLUE, true), - CHECK(RC_GV_JINJO_YELLOW, true), - CHECK(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, true), - CHECK(RC_GV_NOTE_ENTRANCE_1, true), - CHECK(RC_GV_NOTE_ENTRANCE_2, true), - CHECK(RC_GV_NOTE_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GV_NOTE_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GV_NOTE_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GV_NOTE_MOAT_BOTTOM_1, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), - CHECK(RC_GV_NOTE_MOAT_BOTTOM_2, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), - CHECK(RC_GV_NOTE_MOAT_BOTTOM_3, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), - CHECK(RC_GV_NOTE_MOAT_BOTTOM_4, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), - CHECK(RC_GV_NOTE_MOAT_BOTTOM_5, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), - CHECK(RC_GV_NOTE_MOAT_BOTTOM_6, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_1, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_2, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_BLUE_EGG_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_GV_EMPTY_HONEYCOMB_GOBI, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, CAN_ATTACK), + CHECK(RC_GV_JIGGY_GOBI_2, CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_5_CLIMB)), + CHECK(RC_GV_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_7_GOBIS_VALLEY)), + CHECK(RC_GV_JINJO_BLUE, true), + CHECK(RC_GV_JINJO_YELLOW, true), + CHECK(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, true), + CHECK(RC_GV_NOTE_ENTRANCE_1, true), + CHECK(RC_GV_NOTE_ENTRANCE_2, true), + CHECK(RC_GV_NOTE_ENTRANCE_3, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GV_NOTE_ENTRANCE_4, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GV_NOTE_ENTRANCE_5, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GV_NOTE_MOAT_BOTTOM_1, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), + CHECK(RC_GV_NOTE_MOAT_BOTTOM_2, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), + CHECK(RC_GV_NOTE_MOAT_BOTTOM_3, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), + CHECK(RC_GV_NOTE_MOAT_BOTTOM_4, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), + CHECK(RC_GV_NOTE_MOAT_BOTTOM_5, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), + CHECK(RC_GV_NOTE_MOAT_BOTTOM_6, CAN_ACCESS(RA_DRAIN_WATER_PYRAMID)), }, .connections = { CONNECTION(RR_GOBIS_VALLEY_UPPER_AREA, CAN_USE_ABILITY(ABILITY_10_TALON_TROT) || CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), @@ -163,101 +166,107 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GOBIS_VALLEY_UPPER_AREA] = RandoRegion{ .regionName = "Upper Areas", .mapId = MAP_12_GV_GOBIS_VALLEY, .checks = { - CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, true), - CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, true), - CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, true), - CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, true), - CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, true), - CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, true), - CHECK(RC_GV_EXTRA_LIFE_BEHIND_JINXY, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, true), - CHECK(RC_GV_EMPTY_HONEYCOMB_CACTUS, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_JIGGY_ANCIENT_ONES, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_JIGGY_GOBI_1, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), - CHECK(RC_GV_JIGGY_GRABBA, CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GV_JINJO_GREEN, true), - CHECK(RC_GV_MOLEHILL_TURBO_TALON, true), - CHECK(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, true), - CHECK(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), - CHECK(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, CAN_USE_ABILITY(ABILITY_6_EGGS)), - CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_1, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_2, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_1, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_2, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_3, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_4, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_1, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_2, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_3, true), - CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_4, true), - CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_1, true), - CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_2, true), - CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_3, true), - CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_4, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_1, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_2, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_3, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_4, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_5, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_6, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_7, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_8, true), - CHECK(RC_GV_NOTE_MOAT_EDGE_9, true), - CHECK(RC_GV_NOTE_NEAR_GRABBA_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_4, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_5, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_6, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_7, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_8, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_9, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_10, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_GRABBA_11, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_NEAR_TURBO_TRAINERS_1, true), - CHECK(RC_GV_NOTE_NEAR_TURBO_TRAINERS_2, true), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_4, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_5, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_6, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_7, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_8, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), - CHECK(RC_GV_NOTE_SPHYNX_FOOT_LEFT_1, true), - CHECK(RC_GV_NOTE_SPHYNX_FOOT_LEFT_2, true), - CHECK(RC_GV_NOTE_SPHYNX_FOOT_LEFT_3, true), - CHECK(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_1, true), - CHECK(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_2, true), - CHECK(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_3, true), - CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_1, true), - CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_2, true), - CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_3, true), - CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_4, true), + CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, true), + CHECK(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, true), + CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, true), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, true), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, true), + CHECK(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, true), + CHECK(RC_GV_EXTRA_LIFE_BEHIND_JINXY, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, true), + CHECK(RC_GV_EMPTY_HONEYCOMB_CACTUS, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, CAN_ATTACK), + CHECK(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, CAN_ATTACK), + CHECK(RC_GV_JIGGY_ANCIENT_ONES, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_JIGGY_GOBI_1, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_GV_JIGGY_GRABBA, CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GV_JINJO_GREEN, true), + CHECK(RC_GV_MOLEHILL_TURBO_TALON, true), + CHECK(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, true), + CHECK(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, CAN_USE_ABILITY(ABILITY_6_EGGS)), + CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_4, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_NOTE_DESERT_DOOR_ALCOVE_5, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_9_FLIGHT)), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_1, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_SIDE_2, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_1, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_2, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_3, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_STAIRS_4, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_1, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_2, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_3, true), + CHECK(RC_GV_NOTE_MATCH_GAME_PYRAMID_TOP_4, true), + CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_1, true), + CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_2, true), + CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_3, true), + CHECK(RC_GV_NOTE_MAZE_PYRAMID_STAIRS_4, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_1, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_2, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_3, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_4, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_5, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_6, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_7, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_8, true), + CHECK(RC_GV_NOTE_MOAT_EDGE_9, true), + CHECK(RC_GV_NOTE_NEAR_GRABBA_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_4, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_5, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_6, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_7, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_8, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_9, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_10, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_GRABBA_11, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_NEAR_TURBO_TRAINERS_1, true), + CHECK(RC_GV_NOTE_NEAR_TURBO_TRAINERS_2, true), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_1, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_2, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_3, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_4, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_5, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_6, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_7, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SAND_NEAR_SPHYNX_8, CAN_USE_ABILITY(ABILITY_E_WADING_BOOTS)), + CHECK(RC_GV_NOTE_SPHYNX_FOOT_LEFT_1, true), + CHECK(RC_GV_NOTE_SPHYNX_FOOT_LEFT_2, true), + CHECK(RC_GV_NOTE_SPHYNX_FOOT_LEFT_3, true), + CHECK(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_1, true), + CHECK(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_2, true), + CHECK(RC_GV_NOTE_SPHYNX_FOOT_RIGHT_3, true), + CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_1, true), + CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_2, true), + CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_3, true), + CHECK(RC_GV_NOTE_WATER_PYRAMID_TOP_4, true), }, .connections = { CONNECTION(RR_GOBIS_VALLEY_ENTRANCE, true), diff --git a/src/port/Rando/Logic/Regions/GruntildasLair.cpp b/src/port/Rando/Logic/Regions/GruntildasLair.cpp index 085ac998c..a9a878ee4 100644 --- a/src/port/Rando/Logic/Regions/GruntildasLair.cpp +++ b/src/port/Rando/Logic/Regions/GruntildasLair.cpp @@ -31,7 +31,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_260] = RandoRegion{ .regionName = "Before Third Note Door", .mapId = MAP_71_GL_STATUE_ROOM, .checks = { - CHECK(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_SHOCK_PAD) && CAN_ACCESS(RA_WITCH_SWITCH_BUBBLEGLOOP_SWAMP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, CAN_ATTACK), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_SHOCK_PAD) && CAN_ACCESS(RA_WITCH_SWITCH_BUBBLEGLOOP_SWAMP) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_BEFORE_NOTE_DOOR_180, true), @@ -93,8 +96,11 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_LOBBY] = RandoRegion{ .regionName = "Lobby", .mapId = MAP_69_GL_MM_LOBBY, .checks = { - CHECK(RC_GL_JIGGY_LOBBY, true), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN, CAN_ACCESS(RA_WITCH_SWITCH_MUMBOS_MOUNTAIN) && CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, CAN_ATTACK), + CHECK(RC_GL_JIGGY_LOBBY, true), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN, CAN_ACCESS(RA_WITCH_SWITCH_MUMBOS_MOUNTAIN) && CAN_USE_TRANSFORMATION(TRANSFORM_2_TERMITE)), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_PAST_NOTE_DOOR_50, CAN_UNLOCK_NOTE_DOOR(50)), @@ -113,6 +119,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, CAN_ACCESS(RA_PUZZLE_BOARD_FREEZEEZY_PEAK)), CHECK(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, CAN_ACCESS(RA_PUZZLE_BOARD_FREEZEEZY_PEAK)), CHECK(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, true), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, CAN_ATTACK), }, .connections = { CONNECTION(RR_BUBBLEGLOOP_SWAMP, CAN_UNLOCK_WORLD(LEVEL_4_BUBBLEGLOOP_SWAMP)), @@ -125,15 +134,18 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_CLANKERS_CAVERN] = RandoRegion{ .regionName = "Near Clanker's Cavern Entrance", .mapId = MAP_70_GL_CC_LOBBY, .checks = { - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), - CHECK(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_UNDERWATER_PIPES) && CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, CAN_ACCESS(RA_PUZZLE_BOARD_BUBBLEGLOOP_SWAMP)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, CAN_ACCESS(RA_TRIGGER_SWITCH_GL_UNDERWATER_PIPES) && CAN_EXTEND_JUMP_DISTANCE && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), }, .connections = { CONNECTION(RR_CLANKERS_CAVERN_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_3_CLANKERS_CAVERN)), @@ -154,6 +166,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), CHECK(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_ATTACK), CHECK(RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD, CAN_ACCESS(RA_WITCH_SWITCH_CLICK_CLOCK_WOOD) && CAN_USE_TRANSFORMATION(TRANSFORM_6_BEE)), }, .connections = { @@ -169,17 +184,22 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_FREEZEEZY_PEAK] = RandoRegion{ .regionName = "Near Freezeezy Peak Entrance", .mapId = MAP_6F_GL_FP_LOBBY, .checks = { - CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, true), - CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, true), - CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, true), - CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, true), - CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, true), - CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, true), - CHECK(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), - CHECK(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, CAN_ACCESS(RA_WITCH_SWITCH_MAD_MONSTER_MANSION) && CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_EXTEND_JUMP_DISTANCE), - CHECK(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, (CAN_EXTEND_JUMP_DISTANCE || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, true), + CHECK(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, true), + CHECK(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, CAN_ATTACK), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_FREEZEEZY_PEAK, CAN_ACCESS(RA_WITCH_SWITCH_FREEZEEZY_PEAK) && CAN_ACCESS(RA_TRIGGER_SWITCH_GL_FLIGHT_PAD) && CAN_USE_ABILITY(ABILITY_11_TURBO_TALON)), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_MAD_MONSTER_MANSION, CAN_ACCESS(RA_WITCH_SWITCH_MAD_MONSTER_MANSION) && CAN_BREAK_OBJECT(RA_BREAK_OBJECT_WINDOWS) && CAN_EXTEND_JUMP_DISTANCE), + CHECK(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, (CAN_EXTEND_JUMP_DISTANCE || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), }, .connections = { CONNECTION(RR_FREEZEEZY_PEAK_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_5_FREEZEEZY_PEAK)), @@ -236,11 +256,14 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_MAD_MONSTER_MANSION] = RandoRegion{ .regionName = "Near Mad Monster Mansion Entrance", .mapId = MAP_75_GL_MMM_LOBBY, .checks = { - CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, true), - CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, true), - CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, true), - CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, true), - CHECK(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_IRON_GATE)), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, true), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, true), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, true), + CHECK(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, true), + CHECK(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, CAN_BREAK_OBJECT(RA_BREAK_OBJECT_IRON_GATE)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, CAN_ATTACK), }, .connections = { CONNECTION(RR_GRUNTILDAS_LAIR_NEAR_PUZZLE_BOARD_GOBIS_VALLEY, true), @@ -254,7 +277,10 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_GRUNTILDAS_LAIR_NEAR_ENTRANCE_TREASURE_TROVE_COVE] = RandoRegion{ .regionName = "Near Treasure Trove Cove Entrance", .mapId = MAP_6D_GL_TTC_LOBBY, .checks = { - CHECK(RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE, CAN_ACCESS(RA_WITCH_SWITCH_TREASURE_TROVE_COVE) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, CAN_ATTACK), + CHECK(RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE, CAN_ACCESS(RA_WITCH_SWITCH_TREASURE_TROVE_COVE) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), }, .connections = { CONNECTION(RR_TREASURE_TROVE_COVE_ENTRANCE, CAN_UNLOCK_WORLD(LEVEL_2_TREASURE_TROVE_COVE)), @@ -297,6 +323,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, CAN_USE_ABILITY(ABILITY_F_DIVE)), CHECK(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, CAN_ACCESS(RA_PUZZLE_BOARD_RUSTY_BUCKET_BAY)), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, CAN_ATTACK), + CHECK(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, CAN_ATTACK), CHECK(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, CAN_EXTEND_JUMP_DISTANCE), }, .connections = { diff --git a/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp b/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp index c475632a2..a246d124d 100644 --- a/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp +++ b/src/port/Rando/Logic/Regions/MadMonsterMansion.cpp @@ -52,6 +52,12 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, CAN_ATTACK), CHECK(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MMM_NOTE_ORGAN_PEDALS_1, true), CHECK(RC_MMM_NOTE_ORGAN_PEDALS_2, true), @@ -148,6 +154,12 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_2, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_3, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), CHECK(RC_MMM_BLUE_EGG_NEAR_WELL_4, CAN_USE_ABILITY(ABILITY_7_FEATHERY_FLAP)), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, CAN_ATTACK), + CHECK(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, CAN_ATTACK), CHECK(RC_MMM_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_A_MAD_MONSTER_MANSION)), CHECK(RC_MMM_JINJO_BLUE, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_MMM_JINJO_GREEN, CAN_USE_ABILITY(ABILITY_5_CLIMB) && CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), diff --git a/src/port/Rando/Logic/Regions/MumbosMountain.cpp b/src/port/Rando/Logic/Regions/MumbosMountain.cpp index 595a3935f..30920e610 100644 --- a/src/port/Rando/Logic/Regions/MumbosMountain.cpp +++ b/src/port/Rando/Logic/Regions/MumbosMountain.cpp @@ -32,6 +32,12 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_MM_EMPTY_HONEYCOMB_HILL, true), CHECK(RC_MM_EMPTY_HONEYCOMB_JUJU, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MM_EXTRA_LIFE_HUT, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER)), + CHECK(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, CAN_ATTACK), + CHECK(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, CAN_ATTACK), + CHECK(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, CAN_ATTACK), + CHECK(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, CAN_ATTACK), + CHECK(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, CAN_ATTACK), + CHECK(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, CAN_ATTACK), CHECK(RC_MM_JIGGY_CHIMPY, CAN_USE_ABILITY(ABILITY_5_CLIMB) || CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MM_JIGGY_CONGA, CAN_USE_ABILITY(ABILITY_6_EGGS) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_MM_JIGGY_HILL, true), diff --git a/src/port/Rando/Logic/Regions/RustyBucketBay.cpp b/src/port/Rando/Logic/Regions/RustyBucketBay.cpp index 0101698e0..cdd7bd015 100644 --- a/src/port/Rando/Logic/Regions/RustyBucketBay.cpp +++ b/src/port/Rando/Logic/Regions/RustyBucketBay.cpp @@ -29,6 +29,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, true), CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, true), CHECK(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, true), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, CAN_ATTACK), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, CAN_ATTACK), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, CAN_ATTACK), CHECK(RC_RBB_JIGGY_CRANE_CAGE, CAN_USE_ABILITY(ABILITY_0_BARGE) && CAN_USE_ABILITY(ABILITY_5_CLIMB) && CAN_USE_ABILITY(ABILITY_6_EGGS)), CHECK(RC_RBB_JIGGY_FUNNEL, CAN_USE_ABILITY(ABILITY_5_CLIMB)), CHECK(RC_RBB_JIGGY_JINJO, CAN_COLLECT_JINJOS(LEVEL_9_RUSTY_BUCKET_BAY)), @@ -198,6 +201,9 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_RBB_BLUE_EGG_ENGING_ROOM_4, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, CAN_ATTACK), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, CAN_ATTACK), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, CAN_ATTACK), CHECK(RC_RBB_JIGGY_ENGINE_ROOM, CAN_ACCESS(RA_TRIGGER_SWITCH_RBB_PROPELLOR_FIRST)), CHECK(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), CHECK(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP)), @@ -265,6 +271,9 @@ static RegisterShipInitFunc initFunc([]() { Regions[RR_RUSTY_BUCKET_BAY_INTERIOR_SHIPPING_CONTAINER_FIRST] = RandoRegion{ .regionName = "Shipping Container First", .mapId = MAP_37_RBB_CONTAINER_1, .checks = { + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, CAN_ATTACK), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, CAN_ATTACK), + CHECK(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, CAN_ATTACK), CHECK(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, true), CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_1, true), CHECK(RC_RBB_NOTE_SHIPPING_CONTAINER_INTERIOR_FIRST_2, true), diff --git a/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp b/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp index d05d16c7a..1b5ef07e9 100644 --- a/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp +++ b/src/port/Rando/Logic/Regions/TreasureTroveCove.cpp @@ -36,6 +36,18 @@ static RegisterShipInitFunc initFunc([]() { CHECK(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, CAN_EXTEND_JUMP_DISTANCE), CHECK(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, true), CHECK(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, CAN_USE_ABILITY(ABILITY_F_DIVE)), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, CAN_ATTACK), + CHECK(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, CAN_ATTACK), CHECK(RC_TTC_JIGGY_ALCOVE1, CAN_USE_ABILITY(ABILITY_D_SHOCK_JUMP)), CHECK(RC_TTC_JIGGY_ALCOVE2, true), CHECK(RC_TTC_JIGGY_BLUBBER, CAN_USE_ABILITY(ABILITY_2_BEAK_BUSTER) && CAN_USE_ABILITY(ABILITY_8_FLAP_FLIP) && CAN_USE_ABILITY(ABILITY_F_DIVE)), diff --git a/src/port/Rando/ObjectBehavior/Bundle.cpp b/src/port/Rando/ObjectBehavior/Bundle.cpp index 963c787f8..6f7806343 100644 --- a/src/port/Rando/ObjectBehavior/Bundle.cpp +++ b/src/port/Rando/ObjectBehavior/Bundle.cpp @@ -59,6 +59,8 @@ void Rando::ObjectBehavior::InitBundleBehavior() { spawnPosition[1] = (int32_t)position[1]; spawnPosition[2] = (int32_t)position[2]; + SPDLOG_INFO("Bundle ID: {} :: {}, {}, {}", (int32_t)bundleId, spawnPosition[0], spawnPosition[1], spawnPosition[2]); + if (bundleId == BUNDLE_16__HONEYCOMB && (currentMap == MAP_43_CCW_SPRING || currentMap == MAP_B_CC_CLANKERS_CAVERN)) { if (CheckEnemyOverlapPosition(spawnPosition)) { @@ -106,6 +108,15 @@ void Rando::ObjectBehavior::InitBundleBehavior() { case BUNDLE_15__JIGGY: randoCheckId = RC_MM_JIGGY_CONGA; break; + case BUNDLE_18__HONEYCOMB: + if (spawnPosition[1] < 400) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1 + bundleCount); + } else { + randoCheckId = + (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1 + bundleCount); + } + break; default: break; } @@ -120,6 +131,21 @@ void Rando::ObjectBehavior::InitBundleBehavior() { break; default: break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 900 && position[1] > 890) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1 + bundleCount); + } else if (position[1] < 1770 && position[1] > 1765) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1 + bundleCount); + } else if (position[1] < 1910 && position[1] > 1905) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1 + bundleCount); + } else if (position[1] < 875 && position[1] > 870) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1 + bundleCount); + } + break; } break; case LEVEL_3_CLANKERS_CAVERN: @@ -134,6 +160,18 @@ void Rando::ObjectBehavior::InitBundleBehavior() { break; } break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 1405 && position[1] > 1395) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1 + bundleCount); + } else if (position[1] < 5495 && position[1] > 5490) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1 + bundleCount); + } else if (position[1] < 3820 && position[1] > 3810) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1 + bundleCount); + } + break; default: break; } @@ -184,6 +222,21 @@ void Rando::ObjectBehavior::InitBundleBehavior() { break; } break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 1260 && position[1] > 1250) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1 + bundleCount); + } else if (position[1] < 1160 && position[1] > 1150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1 + bundleCount); + } else if (position[0] < 4390 && position[0] > 4385) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1 + bundleCount); + } else if (position[0] < 2565 && position[0] > 2560) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); + } + break; default: break; } @@ -203,6 +256,21 @@ void Rando::ObjectBehavior::InitBundleBehavior() { case BUNDLE_7__JIGGY: randoCheckId = RC_FP_JIGGY_BOGGY_RACE_2; break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 820 && position[1] > 810) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1 + bundleCount); + } else if (position[1] < 590 && position[1] > 580) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1 + bundleCount); + } else if (position[1] < 1755 && position[1] > 1745) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1 + bundleCount); + } else if (position[1] < 5760 && position[1] > 5750) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1 + bundleCount); + } + break; } break; case LEVEL_6_LAIR: @@ -243,6 +311,51 @@ void Rando::ObjectBehavior::InitBundleBehavior() { spawnPosition[2]); } break; + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_69_GL_MM_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1 + bundleCount); + break; + case MAP_6D_GL_TTC_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1 + bundleCount); + break; + case MAP_6F_GL_FP_LOBBY: + if (position[1] < 295 && position[1] > 285) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1 + bundleCount); + } else if (position[1] < 255 && position[1] > 245) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1 + bundleCount); + } + break; + case MAP_70_GL_CC_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1 + bundleCount); + break; + case MAP_71_GL_STATUE_ROOM: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1 + bundleCount); + break; + case MAP_72_GL_BGS_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1 + bundleCount); + break; + case MAP_75_GL_MMM_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1 + bundleCount); + break; + case MAP_78_GL_RBB_AND_MMM_PUZZLE: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1 + bundleCount); + break; + case MAP_79_GL_CCW_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1 + bundleCount); + break; + } + break; default: break; } @@ -255,6 +368,99 @@ void Rando::ObjectBehavior::InitBundleBehavior() { break; case BUNDLE_D__EMPTY_HONEYCOMB: randoCheckId = RC_GV_EMPTY_HONEYCOMB_GOBI; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 2990 && position[1] > 2980) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1 + bundleCount); + } else if (position[1] < 1990 && position[1] > 1980) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1 + bundleCount); + } else if (position[1] < 610 && position[1] > 600) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_8_CLICK_CLOCK_WOOD: + switch (bundleId) { + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_40_CCW_HUB: + if (position[1] < 150 && position[1] > 140) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1 + + bundleCount); + } + break; + case MAP_43_CCW_SPRING: + if (position[0] < 5 && position[0] > -5) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1 + + bundleCount); + } else if (position[0] < -1545 && position[0] > -1555) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[0] < 4345 && position[0] > 4340) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_44_CCW_SUMMER: + if (position[1] < -440 && position[1] > -450) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[1] < 4580 && position[1] > 4570) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1 + + bundleCount); + } + break; + case MAP_45_CCW_AUTUMN: + if (position[1] < 1435 && position[1] > 1425) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[1] < 4405 && position[1] > 4395) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_46_CCW_WINTER: + if (position[1] < 1060 && position[1] > 1050) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1 + + bundleCount); + } else if (position[1] < 4405 && position[1] > 4395) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_4D_CCW_WINTER_MUMBOS_SKULL: + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1 + + bundleCount); + break; + } default: break; } @@ -265,7 +471,52 @@ void Rando::ObjectBehavior::InitBundleBehavior() { randoCheckId = RC_RBB_EXTRA_LIFE_BOOM_BOXES; applyCustomPhysics = true; break; + case BUNDLE_18__HONEYCOMB: + if (position[0] == 0 && position[1] == 156 && position[2] == 4800) { + randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1 + bundleCount); + } else if (position[0] == 0 && position[1] == 156 && position[2] == -178) { + randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1 + bundleCount); + } else if (position[0] == 7850 && position[1] == -1019 && position[2] == 3550) { + randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1 + bundleCount); + } + break; + default: + break; + } + case LEVEL_A_MAD_MONSTER_MANSION: + switch (bundleId) { + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_1C_MMM_CHURCH: + if (position[0] < 1880 && position[0] > 1870) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1 + bundleCount); + } else if (position[0] < -1870 && position[0] > -1880) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1 + bundleCount); + } + break; + case MAP_1B_MMM_MAD_MONSTER_MANSION: + if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1 + bundleCount); + } else if (position[1] < 335 && position[1] > 325) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1 + + bundleCount); + } + break; + default: + break; + } + break; + default: + break; } + break; case LEVEL_B_SPIRAL_MOUNTAIN: switch (bundleId) { case BUNDLE_1F_SM_EMPTY_HONEYCOMB: @@ -275,6 +526,8 @@ void Rando::ObjectBehavior::InitBundleBehavior() { randoCheckId = RC_SM_EMPTY_HONEYCOMB_QUARRIES; } break; + case BUNDLE_18__HONEYCOMB: + break; default: break; } diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index 6ce5d680f..68f158eaf 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -32,6 +32,7 @@ std::vector actorSpawnWhitelist = { ACTOR_46_JIGGY, ACTOR_47_EMPTY_HONEYCOMB, ACTOR_49_EXTRA_LIFE, + ACTOR_50_HONEYCOMB, ACTOR_51_MUSIC_NOTE, ACTOR_52_BLUE_EGG, ACTOR_5E_JINJO_YELLOW, @@ -49,6 +50,7 @@ std::map randoItemColors = { { ACTOR_52_BLUE_EGG, UIWidgets::Colors::Cyan }, { ACTOR_47_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_49_EXTRA_LIFE, UIWidgets::Colors::Yellow }, + { ACTOR_50_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_46_JIGGY, UIWidgets::Colors::Yellow }, { ACTOR_60_JINJO_BLUE, UIWidgets::Colors::SkyBlue }, { ACTOR_62_JINJO_GREEN, UIWidgets::Colors::Green }, @@ -258,6 +260,10 @@ void Rando::ObjectBehavior::Init() { CustomObject::FlushRandoSpawnQueue(); DespawnCollectedBundles(); + if (ev->actorId == ACTOR_12_BEEHIVE) { + SPDLOG_INFO("Actor ID: {} {}, {}, {}", ev->actorId, ev->posX, ev->posY, ev->posZ); + } + if (currentMap == MAP_12_GV_GOBIS_VALLEY) { if (ev->actorId == ACTOR_118_GRABBA) { event->Cancelled = RANDO_SAVE_CHECKS[RC_GV_JIGGY_GRABBA].obtained; @@ -378,6 +384,11 @@ void Rando::ObjectBehavior::Init() { randoItemId = randoSaveCheck.randoItemId; } break; + case MARKER_55_HONEYCOMB: + if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_BEEHIVE_HONEYCOMBS].optionValue == RO_GENERIC_ON) { + randoItemId = randoSaveCheck.randoItemId; + } + break; case MARKER_5A_JINJO_BLUE: case MARKER_5B_JINJO_GREEN: case MARKER_5C_JINJO_ORANGE: diff --git a/src/port/Rando/StaticData/Checks.cpp b/src/port/Rando/StaticData/Checks.cpp index d07a6df3d..8a23c19b4 100644 --- a/src/port/Rando/StaticData/Checks.cpp +++ b/src/port/Rando/StaticData/Checks.cpp @@ -81,6 +81,18 @@ std::map Checks = { RC(RC_BGS_EXTRA_LIFE_MR_VILE_2, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), RC(RC_BGS_EXTRA_LIFE_MR_VILE_3, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), RC(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 7149, 0, -4353), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), RC(RC_BGS_JIGGY_CROCTUS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_22_CROCTUS, 0, 0, 0), RC(RC_BGS_JIGGY_ELEVATED_WALKWAY, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_20_BGS_ELEVATED_WALKWAY, 0, 0, 0), RC(RC_BGS_JIGGY_FLIBBITS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_24_BGS_FLIBBITS, 0, 0, 0), @@ -256,6 +268,15 @@ std::map Checks = { RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 4570, 3727, 2783), RC(RC_CC_EXTRA_LIFE_JINJO_PIPE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 7309, 4267, 2286), RC(RC_CC_EXTRA_LIFE_YELLOW_GRATE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 1752, 5270, -2214), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), RC(RC_CC_JIGGY_BOLT, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_18_CC_BOLT, 90, 5962, -12), RC(RC_CC_JIGGY_CLANKER_RAISED, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_17_CC_CLANKER_RAISED, 0, 0, 0), RC(RC_CC_JIGGY_FAST_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1E_CC_FAST_SAWBLADES, 0, -340, -1604), @@ -493,6 +514,48 @@ std::map Checks = { RC(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 833, 441, 133), RC(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -3157, 300, -3149), RC(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3078, -338, 3076), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), RC(RC_CCW_JIGGY_EYRIE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_49_CCW_EYRIE, 0, 0, 0), RC(RC_CCW_JIGGY_FLOWER, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4D_CCW_FLOWER, 0, 0, 0), RC(RC_CCW_JIGGY_GNAWTY, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4B_CCW_GNAWTY, 240, 600, 75), @@ -689,6 +752,18 @@ std::map Checks = { RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, 6992, 1390, -3159), RC(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -4450, 1591, -7407), RC(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -7322, 0, 391), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), RC(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_31_FP_SIR_SLUSH, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_1, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_30_FP_BOGGY_2, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_2, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2C_FP_BOGGY_3, 0, 0 ,0), @@ -889,6 +964,36 @@ std::map Checks = { RC(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -8689, -1781, -3192), RC(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 3599, -478, 2424), RC(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -838, 1950, 835), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), RC(RC_GL_JIGGY_LOBBY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_33_LAIR_1ST_JIGGY, -1505, 600, 123), RC(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_37_LAIR_BGS_WITCH_SWITCH, 0, 0, -20), RC(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_35_LAIR_CC_WITCH_SWITCH, 0, 75, 156), @@ -969,6 +1074,15 @@ std::map Checks = { RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -8948, 1332, 5500), RC(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, 1282, 18, 1971), RC(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -230, 4820, -4421), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), RC(RC_GV_JIGGY_ANCIENT_ONES, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_46_GV_ANCIENT_ONES, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_1, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_44_GV_GOBI_1, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_2, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_45_GV_GOBI_2, 0, 0, 0), @@ -1140,6 +1254,12 @@ std::map Checks = { RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), RC(RC_MM_EXTRA_LIFE_TICKERS_TOWER, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 223, 3563, -382), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), RC(RC_MM_JIGGY_CHIMPY, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_9_MM_CHIMPY, 0, 0, 0), RC(RC_MM_JIGGY_CONGA, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_A_MM_CONGA, 0, 0, 0), RC(RC_MM_JIGGY_HILL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_07_MM_HILL, 4335, 1485, 794), @@ -1345,6 +1465,18 @@ std::map Checks = { RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, -1, 2263, -3465), RC(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 13, 6), RC(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 1326, 145), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), RC(RC_MMM_JIGGY_BARREL_INTERIOR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_61_MMM_RAIN_BARREL, 2, 288, -4), RC(RC_MMM_JIGGY_CELLAR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5E_MMM_CELLAR, -516, 30, 477), RC(RC_MMM_JIGGY_CEMETARY_POTS, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_63_MMM_FLOWER_POTS, 0, 0, 0), @@ -1542,6 +1674,15 @@ std::map Checks = { RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -626, 140, -351), RC(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -2551, 1065, -2650), RC(RC_RBB_EXTRA_LIFE_WAREHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -950, 1045, -50), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), RC(RC_RBB_JIGGY_BOSS_BOOM_BOX, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_56_RBB_BOSS_BOOM_BOX, 0, 0, 0), RC(RC_RBB_JIGGY_CAPTAINS_CABIN, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_58_RBB_CAPTAINS_CABIN, -997, 273, 355), RC(RC_RBB_JIGGY_CRANE_CAGE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_59_RBB_CRANE_CAGE, -4900, 0, 0), @@ -1742,6 +1883,18 @@ std::map Checks = { RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, -2442, 3158, -1706), RC(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 5864, 677, 7898), RC(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 4710, 323, -6007), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), RC(RC_TTC_JIGGY_ALCOVE1, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0D_TTC_ALCOVE_1, 2832, 2152, -1797), RC(RC_TTC_JIGGY_ALCOVE2, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0E_TTC_ALCOVE_2, -5116, 1417, -3915), RC(RC_TTC_JIGGY_BLUBBER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_14_TTC_BLUBBER, 0, 0, 0), diff --git a/src/port/Rando/StaticData/Items.cpp b/src/port/Rando/StaticData/Items.cpp index b1cf735c7..415740927 100644 --- a/src/port/Rando/StaticData/Items.cpp +++ b/src/port/Rando/StaticData/Items.cpp @@ -52,6 +52,17 @@ std::map Items = { RI(RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, "an", "Extra Life - RBB", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY), RI(RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, "an", "Extra Life - SM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN), RI(RI_EXTRA_LIFE_TREASURE_TROVE_COVE, "an", "Extra Life - TTC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Honeycomb - BGS", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_HONEYCOMB_CLANKERS_CAVERN, "a", "Honeycomb - CC", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), + RI(RI_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Honeycomb - CCW", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_HONEYCOMB_FREEZEEZY_PEAK, "a", "Honeycomb - FP", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_HONEYCOMB_GOBIS_VALLEY, "a", "Honeycomb - GV", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), + RI(RI_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Honeycomb - GL", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_6_LAIR), + RI(RI_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Honeycomb - MMM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Honeycomb - MM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Honeycomb - RBB", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Honeycomb - SM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Honeycomb - TTC", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), RI(RI_JIGGY_BUBBLEGLOOP_SWAMP, "a", "Jiggy - BGS", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_JIGGY_CLANKERS_CAVERN, "a", "Jiggy - CC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_3_CLANKERS_CAVERN), RI(RI_JIGGY_CLICK_CLOCK_WOOD, "a", "Jiggy - CCW", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD), diff --git a/src/port/Rando/StaticData/Options.cpp b/src/port/Rando/StaticData/Options.cpp index 88f303601..066e19c50 100644 --- a/src/port/Rando/StaticData/Options.cpp +++ b/src/port/Rando/StaticData/Options.cpp @@ -15,17 +15,18 @@ namespace StaticData { // clang-format off std::map Options = { - RO(RO_LOGIC, RO_LOGIC_GLITCHLESS), - RO(RO_SPAWN_JUNK, RO_GENERIC_OFF), - RO(RO_SHUFFLE_BLUE_EGGS, RO_GENERIC_OFF), - RO(RO_SHUFFLE_EMPTY_HONEYCOMBS, RO_GENERIC_OFF), - RO(RO_SHUFFLE_EXTRA_LIVES, RO_GENERIC_OFF), - RO(RO_SHUFFLE_JIGGIES, RO_GENERIC_OFF), - RO(RO_SHUFFLE_JINJOS, RO_GENERIC_OFF), - RO(RO_SHUFFLE_MOLEHILLS, RO_GENERIC_OFF), - RO(RO_SHUFFLE_MUMBO_TOKENS, RO_GENERIC_OFF), - RO(RO_SHUFFLE_MUSIC_NOTES, RO_GENERIC_OFF), - RO(RO_SHUFFLE_STOP_N_SWOP, RO_GENERIC_OFF), + RO(RO_LOGIC, RO_LOGIC_GLITCHLESS), + RO(RO_SPAWN_JUNK, RO_GENERIC_OFF), + RO(RO_SHUFFLE_BEEHIVE_HONEYCOMBS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_BLUE_EGGS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_EMPTY_HONEYCOMBS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_EXTRA_LIVES, RO_GENERIC_OFF), + RO(RO_SHUFFLE_JIGGIES, RO_GENERIC_OFF), + RO(RO_SHUFFLE_JINJOS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_MOLEHILLS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_MUMBO_TOKENS, RO_GENERIC_OFF), + RO(RO_SHUFFLE_MUSIC_NOTES, RO_GENERIC_OFF), + RO(RO_SHUFFLE_STOP_N_SWOP, RO_GENERIC_OFF), }; // clang-format on diff --git a/src/port/Rando/Types.h b/src/port/Rando/Types.h index 9b1f44c1d..ba6b63e3f 100644 --- a/src/port/Rando/Types.h +++ b/src/port/Rando/Types.h @@ -13,6 +13,7 @@ typedef enum { RCTYPE_BLUE_EGG, RCTYPE_EMPTY_HONEYCOMB, RCTYPE_EXTRA_LIFE, + RCTYPE_HONEYCOMB, RCTYPE_JIGGY, RCTYPE_JINJO, RCTYPE_MOLEHILL, @@ -81,6 +82,18 @@ typedef enum { RC_BGS_EXTRA_LIFE_MR_VILE_2, RC_BGS_EXTRA_LIFE_MR_VILE_3, RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, + RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, + RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, + RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, + RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RC_BGS_JIGGY_CROCTUS, RC_BGS_JIGGY_ELEVATED_WALKWAY, RC_BGS_JIGGY_FLIBBITS, @@ -256,6 +269,15 @@ typedef enum { RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RC_CC_EXTRA_LIFE_JINJO_PIPE, RC_CC_EXTRA_LIFE_YELLOW_GRATE, + RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, + RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, + RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, + RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, + RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, + RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, + RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, + RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, + RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, RC_CC_JIGGY_BOLT, RC_CC_JIGGY_CLANKER_RAISED, RC_CC_JIGGY_FAST_SAWBLADES, @@ -493,6 +515,48 @@ typedef enum { RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, + RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, + RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, + RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, + RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, + RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, + RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, + RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, + RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, + RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, + RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, RC_CCW_JIGGY_EYRIE, RC_CCW_JIGGY_FLOWER, RC_CCW_JIGGY_GNAWTY, @@ -689,6 +753,18 @@ typedef enum { RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RC_FP_EXTRA_LIFE_WOZZAS_CAVE, + RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, + RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, + RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, + RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, + RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, + RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, + RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, + RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, + RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, + RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, + RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, + RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RC_FP_JIGGY_BOGGY_RACE_1, RC_FP_JIGGY_BOGGY_RACE_2, @@ -889,6 +965,36 @@ typedef enum { RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, + RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, + RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, + RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, + RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, + RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, + RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, + RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, + RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, + RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, + RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, + RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, + RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, + RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, RC_GL_JIGGY_LOBBY, RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, @@ -969,6 +1075,15 @@ typedef enum { RC_GV_EXTRA_LIFE_BEHIND_JINXY, RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, + RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, + RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, + RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, + RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, + RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, + RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, + RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, + RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, + RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RC_GV_JIGGY_ANCIENT_ONES, RC_GV_JIGGY_GOBI_1, RC_GV_JIGGY_GOBI_2, @@ -1140,6 +1255,12 @@ typedef enum { RC_MM_EMPTY_HONEYCOMB_JUJU, RC_MM_EXTRA_LIFE_HUT, RC_MM_EXTRA_LIFE_TICKERS_TOWER, + RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, + RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, + RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, + RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, + RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, + RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, RC_MM_JIGGY_CHIMPY, RC_MM_JIGGY_CONGA, RC_MM_JIGGY_HILL, @@ -1345,6 +1466,18 @@ typedef enum { RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, + RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, + RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, + RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, + RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, + RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, + RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, + RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, + RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, + RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, + RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, + RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, + RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, RC_MMM_JIGGY_BARREL_INTERIOR, RC_MMM_JIGGY_CELLAR, RC_MMM_JIGGY_CEMETARY_POTS, @@ -1542,6 +1675,15 @@ typedef enum { RC_RBB_EXTRA_LIFE_BOOM_BOXES, RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RC_RBB_EXTRA_LIFE_WAREHOUSE, + RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, + RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, + RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, + RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, + RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, + RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, + RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, + RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, + RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, RC_RBB_JIGGY_BOSS_BOOM_BOX, RC_RBB_JIGGY_CAPTAINS_CABIN, RC_RBB_JIGGY_CRANE_CAGE, @@ -1742,6 +1884,18 @@ typedef enum { RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RC_TTC_EXTRA_LIFE_SPIRAL_PATH, + RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, + RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, + RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, + RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, + RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, + RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, + RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, + RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, + RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, + RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, + RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, + RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, RC_TTC_JIGGY_ALCOVE1, RC_TTC_JIGGY_ALCOVE2, RC_TTC_JIGGY_BLUBBER, @@ -1878,6 +2032,7 @@ typedef enum { RITYPE_BLUE_EGG, RITYPE_EMPTY_HONEYCOMB, RITYPE_EXTRA_LIFE, + RITYPE_HONEYCOMB, RITYPE_JIGGY, RITYPE_JINJO, RITYPE_MOLEHILL, @@ -1922,6 +2077,17 @@ typedef enum { RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, + RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, + RI_HONEYCOMB_CLANKERS_CAVERN, + RI_HONEYCOMB_CLICK_CLOCK_WOOD, + RI_HONEYCOMB_FREEZEEZY_PEAK, + RI_HONEYCOMB_GOBIS_VALLEY, + RI_HONEYCOMB_GRUNTILDAS_LAIR, + RI_HONEYCOMB_MAD_MONSTER_MANSION, + RI_HONEYCOMB_MUMBOS_MOUNTAIN, + RI_HONEYCOMB_RUSTY_BUCKET_BAY, + RI_HONEYCOMB_SPIRAL_MOUNTAIN, + RI_HONEYCOMB_TREASURE_TROVE_COVE, RI_JIGGY_BUBBLEGLOOP_SWAMP, RI_JIGGY_CLANKERS_CAVERN, RI_JIGGY_CLICK_CLOCK_WOOD, @@ -2227,6 +2393,7 @@ typedef enum { typedef enum { RO_LOGIC, RO_SPAWN_JUNK, + RO_SHUFFLE_BEEHIVE_HONEYCOMBS, RO_SHUFFLE_BLUE_EGGS, RO_SHUFFLE_EMPTY_HONEYCOMBS, RO_SHUFFLE_EXTRA_LIVES, From 127a2824f16d279009af353c87045e118994b833 Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 7 Aug 2026 22:12:08 +0200 Subject: [PATCH 7/8] Custom collectible (#439) * Custom collectible * it builds now * Fix spawn code under Gameplay Tools * Not working pulling functions from map * Added semi working draw stuff * Vanilla sprites and models work now * Custom models working but update function doesn't always * Fix broken actor info referencing and cleanup * Update README.md (#248) * Fix HD dialog-font crash on v1.1/PAL/JP bases (#251) * Fix SkipSM to account for Rando. (#253) * Add note door dance skip. (#255) * Anchor game sync (#199) * Sync progress flags. * Sync jiggies, tokens, and honeycombs. * Fix item collection triggers (were triggering before actually collecting just from proximity). Add saved item (note totals, tokens, jiggies, honeycombs) collection/use updates. Add note and jinjo collection to realtime sync.] Add jiggy spawn syncing. Make note collection packets update totals outside levels. * Add level and map flag syncing, and re-enable volatile flags for witch switch reasons. * Apply jiggy pedestal authority. * Potentially fix retention off. * Fix include casing. * Move retention files to common folder, add Retention files for common inclusion. Add listener to jinjo retention for VB_OVERRIDE_BUNDLE_SPAWN to prevent jinjo bundle from crashing when already collected. * Exclude Sandcastle and Christmas Tree cutscenes from syncing to avoid infinite scene reload cutscene glitches. * Properly live-sync ability unlocks. * Make honeycomb packets trigger HUD animations. * Make note door clear sync play animation, sound, and sparkles. * Live sync destructibles, fix cobwebs state on state restore. * Sync already-spawned jiggies when player entering a map another player is in. * Live, persistent acorn and worm sync in CCW. * Sync RBB transients. * Live-sync Blubber's Gold, the FP presents, and Conga's orange like acorns/worms. * Clear jinjo retention if jiggy orphaned, and force 31 (all collected) for retention value if jinjo jiggy collected. * Sync CC. * Sync BGS. * PUZZLE_STEP on Clanker's teeth. * Sync GV and honeycomb switches. * FP transient syncs. * Sync MMM. * CCW sync. * Fix dynamic spawned jiggy sync. Add hut sync. * Sync orange pads, juju totem, fix chimpy jiggy spawn. * Fix multiple bundle jiggy spawns. * Initial rando hookup. * Sync Bottles Bonuses. Add checkboxes for bottles bonuses when unlocked or connected to Anchor. * Fix jiggy dual spawn, remote hut ordering. Rando improvement. * Fix spawn-in croctus look-at binding player movement. * Fix timed jiggy switch timer sync. * Purge pending jiggy spawns on close/restart. * Fix actor misplacement issue. * Fix more transient syncs and puzzle steps. * Fix honeycomb switch spawns, ancient one next-step spawns, and level-open cutscene camera resets. * Sync final Grunty fight. Fix jiggy HUD to display level counts when same-level jiggy is collected. * Fix file on disk deletion. More fix for actor misplacement. * Re-implement collision and shadows. * Implement the room window and teleport to player functionality. * Make teleport go directly to other player. * Change forced disconnect on romhack status mismatch to warning. Make "Reset All Team States" reset the romhack status of the room. * Add notifications for jiggies and level opens in vanilla and rando checks. * Live sync/update blubber's gold and bear cub presents steps, and temporarily persist gold steps. * Add carried item and throw sync. * More actor misplacement fixing. * Defer actor despawn during game frame update. * Clear vanilla retention on file delete. * Add remote collect simulation to test actor misplacement fixes. * Clear temporary persistence when no players are in a level. * Fix sub-area destructible persistence. * Prevent camera actions during level door openings. * Fix Blubber's gold and the bear cub's presents not showing in-world after being thrown. * Fix collectibles showing in world after being thrown. Fix count desync of worms/acorns. * Fix flower watering stages. * Semi-persist ignored controllers (only by list index for now). * Fix grunty fight: non-authority eggs not damaging, jinjos not despawning, remote freeze during first jinjo statue cutscene. * Make fireballs (spell 0) target local players. * Fix timed switch jiggy despawns. * Swap to HM Torch main, latest commit. * Re-enable global room. * Add team-state check syncing and despawn. Add isRando and seed to room state (cleared on Clear All Team States) and warning on seed mismatch. * Make levitate cheat a fixed upward value, cancel fall damage/animation if used during damage fall. * Fix same-map warp-to-player getting stuck on level geometry. * Some comment cleanup. * Sync Slushes and snowman buttons in FP, and prevent multiple players from playing the twinkly minigame at the same time. * Prevent remote-triggered door-open camera locks. * More comment cleanup. * Disable vanilla retention checkboxes when Anchor connected. * Bump LUS. Force wait for team state when loading save. Force reload when joining/requesting team state after loading file. Increase levitate speed to 500. More comment cleanup. * Remove extra first-load team state request. * Fix live sync of entered levels for Level Totals. * Fix Tanktup cutscene unfreeze. * Add new water level packet and fix water level snapping for offline and remote clients. * Engine room fan switch temp persistence. * Fix engine fan persistence and Grunty door live sync. * Fix final fight syncing. * More comments. * Final comment sweep. * Comment streamlining. * Restore moved enum with #if 0. * Clang-format for anchor-game-sync PR. * Add a differ in Default and Authentic boot logos (#256) * Code cleanup (#252) * Code cleanup: ResourceMgr region dialog checks * Code cleanup: consolidate port functions for dialog fonts * Code cleanup: duplicate declarations for romhacks and lus/port type changes * Code cleanup: Remove declarations with no callers * Code cleanup: Remove duplicate declarations * Stop functions.h pulling C++ headers into extern "C" * Guard decomp headers with extern "C", drop redundant wrappers * Restore ShipUtils.h includes lost when functions.h dropped it * Fix spawn queue not scaling with draw distance setting * Remove more dead code, fixups and comment clarity * Fix orbit camers getting stuck on rare occasions * Resolve more extern "C" cleanups after anchor rebase * Polish Cheats (Levitate, Transforms) * Adjust camera orbit core smoothing when player is on uneven terrain * Clang format * Decomp pass 5 (#247) * CCW documentation from decomp upstream * audioManager documentation from decomp upstream * RBB documentation from decomp upstream * Model Appendages and BS method table documentation from decomp upstream * Compile fixes and clang-format after decomp pass 5 * Fix clang -Wint-conversion errors in RBB whistle tables * Fix clang -Wint-conversion and pointer-type errors from decomp pass 5 * Align filenames and decomp header comments with upstream * Missed one * Documentation and file renames from decomp upstream * Checksums, 08776d1f * PAL matching from decomp upstream * Rubee & Function Documentation, ac3ddb91 * PAL match func_80240204, 1b2edf8b * PAL matching 2, 485bef33 * Draw code documentation from decomp and pointer truncation fixups * Add decomp's headers split * Missed function renames from past decomp commits * Cleanup functions.h a bit * Post-rebase fixups * Hotfix for camera orbit core (#259) * Hotfix for camera orbit core * Fix a bug where rotating modern cam while climbing caused it to get stuck * Add permadeath enhancement (#254) * Romhack code integration (#258) * Switch soundfontctl extraction to own factory * Reorder GEO section * Bump Torch and LUS * Add ported romhack code for Jiggies of Time, Nostalgia 64, and Cutthroat Coast * Fix missing jiggy puzzle sizes and flags * CTC: Blank note door digits * Add Cheato's Challenges port * Sort disabled romhacks alphabetically * Add Bubbling Bog Brewery code port * Disable select enhancements in romhacks * Add partial support for Gruntch and Santa's Village * Post-rebase fixups * Mute Chimpy Stump on MM load enhancement. (#261) A bit of decomp catchup renaming. * Fix romhack extern. * Fix Windows and Macports workflows. * Linux compile errors and a couple decomp pass bugs (#262) * Exclude `unused` folder from build list. * Restore ActorID to eliminate warning about unnamed typedef. Undo exclusion of unused folder because of references of functions housed there causing linking errors. Handle switches without default branches. Suppress MSVC warning for zero-sized c99 flexible arrays (C4200). * Bump Torch. Add shader copy to port O2R generation workflow. * Clean calls to src/unused, filter out the unused files, make ReadStampedCrc endianness-agnostic (#263) * Clean calls to src/unused, filter out the unused files, make ReadStampedCrc endianness-agnostic * Update mod subfolder paths * Adjust orbit camera snapback * Fix Linux packaging. * Rc cleanup 1 (#268) * Remove remote collect sim. * Another attempt at fixing packaging for Linux. * Fix Mumbo's Hut fast transformations. * Remove frame drop warning. * Add to Easier Boggy Races enhancement to mention the need for a map reload to take effect. * Switch focus to molehills + AP items only * Rc fixes 2 (#274) * Filter OoT factories from Torch * Correct jiggy hud element centering * Carry segment-address provenance instead of inferring it from pointer value * Patch Banjo's belt buckle depth (VB, on by default) * Bump libulttraship and add imgui file picker for gamepad-only users * Correct snow particle interpolation with unique id and rename weather related files for accuracy * Anchor" adjust bottles tutorial handling and add honeycomb bundle spawn sync * Fix lookup paths for appimage * Clang format * Interpolation: clean dead code, optimize adaptivefps and draw distance * RC Fixes #3 (#275) * Revert: Patch Banjo's belt buckle depth (VB, on by default) * Resolve a crash * Rework modern camera * Menu and logging cleanup. * Apply modern camera changes back to free look. (#277) * Apply modern camera changes back to free look. * Free look takes precedence over modern camera. * Adds a built-in mapper to create or edit mapping strings for controllers the game doesn't recognize or are improperly mapped. (#278) * Mute Chimpy and add a fix enhancement for Freezeezy Peak Lobby's door trim (#279) * Mute Chimpy on MM load enhancement. * Clang format * Add a fix enhancement for the FP Lobby door trim * Revive decomp os functions (#280) * os: real thread table * os: blocking message queues * os: DP status word * os: RSP task submission * interpolation: ring of trees with ownership claims * os: VI retrace source and framebuffer registers * thread5: run the decomp's graphics thread * vimgr: pace the tick from the retrace clock * os: osViBlack blank register * os: deadline timers, taking libultra/os.cpp port-side * os: SI controller reads as request and completion * fix: count the demo audio hold in ticks, not renders * pacing: drop sub-frames against the deadline instead of predicting * audio: revive the decomp's audio pipeline against the RCP * fix: keep mid-tick SI completions out of the demo's pad buffer * perf: replace four decomp hot spots through the event system * fix: memmove for overlapping ranges in bk_vector_remove * fix: drop the game-thread fallback poll in osContGetReadData * Bump LUS and make use of memoization * Add a watchdog for thread5 to log stalls * Add a thread safety for rumble * Comment out GfxDebuggerWindow * os: swap rumble thread bypass for real rumble thread (#281) * os: swap rumble thread bypass for real rumble thread * Linux compile fix * Fix a rare crash with the tooie jiggy animation (#282) * Fix rando softlock in SM jump tutorial (#284) * Fix a few issues with note retention (#283) * Restore molehill rando functionality. Update readme and building docs. Add 50-note-door ability to FFM start. * Fix interpolation bug introduced by rings (#285) * Resolve a crash when searching in imgui (#286) * Fix CC rando mapstates (#287) * Restore event call in `chmole_learnedAllSpiralMountainAbilities` (#288) * Rando: don't require pumpkin for shuffled MMM honeycomb (#289) * Fix rando events (#290) * Make InitRandoEvents call only once per real save load (instead of only on rando OnSaveLoad). Fix actor save state restorations in rando. * full-project clang * RC Patches 4 (#291) * Thread safety in teardown + imgui safety * Interpolation adjustments * Optimize initial rom scans * Mute Chimpy stump's rumble on reentry to MM * Anchor: BGS catchup bug with tanktup and yellow flibbit initializer * Clang format * RBB: fix lfieboat culling by disabling the DIAG check, fix whistle switch interpolation * GV: gate ancient ones catch-up behind anchor being connected * Interpolation: particles adjustments * Add another fix for tooie jiggy dance * Fix Lair water level taking the wrong path when player exits RBB * Convert imgui text to ascii so it renders properly * Extend prop count (#292) * Restore event call in `chmole_learnedAllSpiralMountainAbilities` * Extend propCnt1/propCnt2 to avoid overflow while creating particles. Add guards surrounding these structures to inform if a prop clear is attempted that isn't part of a given cube. * Widen unk0_4 as well (not really a vanilla issue, but could present problems with hacks and such). * More and better guards. * Fix flowered pots in MMM not surviving transitions. * Add comment to find better place for warn functions in PerfPatches later. Fix memory footprint of Cube. Fix guard placements and return values in `func_8032D9C0`. * Final adjustments to RC (#293) * Defer the note retention seed out of demo playback * Adjust modern controls * Bottles bonus demo sync and picture rendering * Fix missing topper enemy in SM ending demo * Sort the VBehaviorID enum * Clang format * Serialize jiggy puzzle counters through the active layout * Don't pop the thread watchdog during expected stalls like the native file dialog * Bump Split Rock Alfa (#294) * Restore event call in `chmole_learnedAllSpiralMountainAbilities` * Bump version to 1.0.0 and name Split Rock. * Final pre-release clang. * Missing include. (#296) * Use cast on StopNSwop va_arg (#295) * Add project description * Fix packet bleed in global Anchor room. (#301) * Fix packet bleed in global Anchor room. * Remove certain exceptions from global exclusion. Put windows .pdb back in debug folder in the release builds. * Capture framebuffer at a slightly later time (#304) * Fix token and jiggy total sync with Share Consumables off. (#310) * Interpolation and shadows (#311) * Adjust interpolation for shadows when camera moves, disable shadows for music notes * Give verrtex-animated models unique animations * Interpolate vertex-animated models * Fix rando savestate restore crashing and duplicating junk items (#312) * Split Rock Bravo (#316) * Anchor: fix ccw jiggy podium to be hidden for players in anchor and only perform logic when connected (#327) * Fix starting abilities duplicating onto remaining molehills (#325) * Allow builders to define CPU_OPTION (#323) * Slide all control schemes through LUS mappings proper (#322) * Fix default volume in new system. * Fix alt assets default values. * Fix occlusion for stonehenge (#324) * Uncap render fps for cutscenes and demos (#331) * Align actor array and marker pool (#335) * Apply more hud adjustments (#336) * Fix dialog asset remap gaps and void conditional-dialog callbacks (#345) * Fix language pack redirects not working (#349) * Bump Torch (#350) * Fix snow particle alpha transparency and xmas tree light interpolation (#330) * Repair Banjo Dreamie (#346) * Add anchor color customization and nametags (#334) * Custom actor mostly done, item queue half done * Update special thanks section in README * More item gives done * Modify workflows to upload artifacts from pull requests (#352) Mirror soh a bit * Restore rumble to proper state and restore screenshake (#353) * Restore rumble to proper state and restore screenshake * Make screen shake an accessibility option * Fix imgui audio backends showing up when they shouldn't (#356) * Add missing images and update readme for keyboard keys (#357) * Add a modern controls exception for jigsaw podiums so player can take their placed pieces back (#360) * Anchor fixes (#361) * Gate local Anchor codepaths behind world syncing to prevent operation in global room. * Fix witch switch cutscenes and sub area transitions clearing transient persistence values. * Fix two asan triggers (#362) * Kill note shadows for custom objects (#363) * Add special thanks to Banjo decomp team * Fix Gruntys Lair Gate not rising after collection (#364) * Init audio before menu (#369) * Fix stack overflow in furnace fun (#365) * Maintain aspect for auxfbo (bottles bonus) (#372) * Maintain aspect for auxfbo (bottles bonus) * Adjust frame pacing for bottles bonus and sns pictures mode * Prevent EggAim enhancement from allowing transformations to fire in first person. (#368) * Fix Presents not using the correct Level Flag. (#367) * Update README.md (#383) * Fix OSTimer teardown race condition (#382) * GV: fix Gobi and Trunker reverting after a death reload (#381) * Prevent gag transformation from incurring a token charge while fast transformation is enabled. (#379) Also add a warp entry for Furnace Fun at the pad. * Start work on jinjos * More draw work * Disable Note Retention during parades * Stop language packs shadowing HD assets they don't localize (#351) * Fix GamePlayTimer display and some warnings. (#387) * Moves No Mumbo Detransform to a VB Hook. (#388) * AP item improvements, more item queue work * Fix input viewer (#395) * Fix input viewer * Clang and fix menu column * Minor menu tweaks * update cvar to use macro * [RANDO] Spoiler Generation Option (#370) * Save and Load of Spoiler Logs * Color change for success notification * clangified * Fix if statement to check for string.empty(). * case change * Fix log refresh and seedID * Add Refresh Button * Add Tooltip for refresh button, gross * Randomized props fully replaced * Make remote clients live react to puzzle completion and prevent pedestal authority from releasing if a puzzle was completed. (#400) * Fix retention behavior while cvar is off (store but don't despawn). (#398) Fix transient persistence clearing bleeding out of Anchor. * Language pack modding doc update and Torch bump (#401) * Update lang pack documentation * Bump Torch * Batch of romhack bugfixes (#380) * CTC: fix the rock raising itself on map reload * Debugging: add a flag tracer to dev tools * Fix bottles tutorials gated on map instead of level * Anchor: gate sync on singleplayer and romhacks for some cases * Anchor: consolidate remoteOpens into helper remoteCue and add missing * Patch romhack: used ability flags and anchor empty honeycomb sync rework * Fix applying bkcf to wrong warp function and clean up Dreamie no-op * BBB and Gruntch flip UsedAbilities bits * Finish reimplementing Gruntch features * Mark Gruntch as fully supported * Add launch arg handling for romhacks * Fix saving * Shuffle molehills with custom collectible * General bug fixes (#402) * Fix SNS demos not working on v1.1, PAL, JP * Fix audio bgm running when game window is frozen (drag/resize) * Fix audio static on certain platforms * Fix decomp animation function names being backwards * 1.0.2. (#403) * Clean up rando molehills * Implemented jiggies * Fix build post merge * Fix jiggies, implement jinjos * Finish jinjos * implement bundles + mumbo tokens * Handle honeycombs and extra lives * Remove rando junk options * Fix jiggie totals and bundle crash * Clang * Fix includes * Fix animations * Fix build hopefully --------- Co-authored-by: Jeod <47716344+JeodC@users.noreply.github.com> Co-authored-by: Caladius Co-authored-by: Malkierian Co-authored-by: Eblo <7004497+Eblo@users.noreply.github.com> Co-authored-by: JordanLongstaff --- .github/macports.yml | 2 + .github/workflows/linux.yml | 48 - .github/workflows/mac.yml | 23 - .github/workflows/main.yml | 47 +- .github/workflows/switch.yml | 38 - .github/workflows/windows.yml | 20 - .gitmodules | 2 +- CMakeLists.txt | 24 +- README.md | 81 +- Torch | 2 +- assets/yaml/jp/rev0/soundfont.yaml | 4 +- assets/yaml/pal/rev0/soundfont.yaml | 4 +- assets/yaml/us/rev0/soundfont.yaml | 4 +- assets/yaml/us/rev1/soundfont.yaml | 4 +- cmake/GenerateFlagNames.cmake | 123 ++ config.yml | 6 +- docs/BUILDING.md | 12 +- docs/modding/LANGUAGE PACKS.md | 71 +- docs/poweredbylus.darkmode.png | Bin 0 -> 213165 bytes docs/poweredbylus.lightmode.png | Bin 0 -> 210989 bytes include/actor.h | 4 + include/bk_math.h | 2 + include/bool.h | 11 + include/bs_funcs.h | 278 +-- include/checksums.h | 115 ++ include/core1/core1.h | 59 +- include/core1/main.h | 12 +- include/core1/ml.h | 10 +- include/core1/sns.h | 8 + include/core1/sprite.h | 8 + include/core1/viewport.h | 10 +- include/core2/ba/carry.h | 2 +- include/core2/ba/model.h | 8 + include/core2/ba/physics.h | 10 + include/core2/ba/timer.h | 2 +- include/core2/bonetransform.h | 8 + include/core2/commonParticle.h | 8 + include/core2/modelRender.h | 2 +- include/core2/particle.h | 8 + include/core2/statetimer.h | 8 + include/core2/timedfunc.h | 2 + include/enums.h | 743 ++++--- include/file_and_line.h | 19 +- include/functions.h | 956 ++++----- include/gc/gctransition.h | 10 +- include/model.h | 8 + include/prop.h | 17 +- include/structs.h | 9 + include/variables.h | 8 + include/version.h | 3 + lib/ultralib/include/PR/gbi.h | 2 +- .../include/{assert.h => ultra_assert.h} | 0 libultraship | 2 +- port/anim/lighthouse_shrug | Bin 0 -> 408 bytes port/anim/lighthouse_walk | Bin 0 -> 288 bytes port/models/lighthouse | Bin 0 -> 5688 bytes port/models/lighthouse_GEO | Bin 0 -> 212 bytes port/models/lighthouse_VTX | Bin 0 -> 7684 bytes port/models/lighthouse_tex_0 | Bin 0 -> 1104 bytes port/models/lighthouse_tex_1 | Bin 0 -> 1104 bytes port/models/lighthouse_tex_2 | Bin 0 -> 1104 bytes .../gArchipelagoItemDL | 16 + .../gArchipelagoItemDL_tri_0 | 56 + .../gArchipelagoItemDL_tri_1 | 57 + .../gArchipelagoItemDL_tri_2 | 57 + .../gArchipelagoItemDL_tri_3 | 57 + .../gArchipelagoItemDL_tri_4 | 57 + .../gArchipelagoItemDL_tri_5 | 56 + .../gArchipelagoItemDL_tri_6 | 56 + .../gArchipelagoItemDL_vtx_0 | 64 + .../gArchipelagoItemDL_vtx_1 | 77 + .../gArchipelagoItemDL_vtx_2 | 70 + .../gArchipelagoItemDL_vtx_3 | 68 + .../gArchipelagoItemDL_vtx_4 | 69 + .../gArchipelagoItemDL_vtx_5 | 64 + .../gArchipelagoItemDL_vtx_6 | 64 + .../gArchipelagoJunkDL | 16 + .../gArchipelagoJunkDL_tri_0 | 56 + .../gArchipelagoJunkDL_tri_1 | 57 + .../gArchipelagoJunkDL_tri_2 | 57 + .../gArchipelagoJunkDL_tri_3 | 57 + .../gArchipelagoJunkDL_tri_4 | 57 + .../gArchipelagoJunkDL_tri_5 | 56 + .../gArchipelagoJunkDL_tri_6 | 56 + .../gArchipelagoJunkDL_vtx_0 | 64 + .../gArchipelagoJunkDL_vtx_1 | 77 + .../gArchipelagoJunkDL_vtx_2 | 70 + .../gArchipelagoJunkDL_vtx_3 | 68 + .../gArchipelagoJunkDL_vtx_4 | 69 + .../gArchipelagoJunkDL_vtx_5 | 64 + .../gArchipelagoJunkDL_vtx_6 | 64 + .../gArchipelagoProgressiveDL | 18 + .../gArchipelagoProgressiveDL_tri_0 | 56 + .../gArchipelagoProgressiveDL_tri_1 | 57 + .../gArchipelagoProgressiveDL_tri_2 | 57 + .../gArchipelagoProgressiveDL_tri_3 | 57 + .../gArchipelagoProgressiveDL_tri_4 | 57 + .../gArchipelagoProgressiveDL_tri_5 | 56 + .../gArchipelagoProgressiveDL_tri_6 | 41 + .../gArchipelagoProgressiveDL_tri_7 | 41 + .../gArchipelagoProgressiveDL_vtx_0 | 64 + .../gArchipelagoProgressiveDL_vtx_1 | 77 + .../gArchipelagoProgressiveDL_vtx_2 | 70 + .../gArchipelagoProgressiveDL_vtx_3 | 68 + .../gArchipelagoProgressiveDL_vtx_4 | 69 + .../gArchipelagoProgressiveDL_vtx_5 | 64 + .../gArchipelagoProgressiveDL_vtx_6 | 39 + .../gArchipelagoProgressiveDL_vtx_7 | 39 + .../mat_gArchipelagoItemDL_black | 12 + .../mat_gArchipelagoItemDL_blue | 12 + .../mat_gArchipelagoItemDL_green | 12 + .../mat_gArchipelagoItemDL_orange | 12 + .../mat_gArchipelagoItemDL_outline | 12 + .../mat_gArchipelagoItemDL_pink | 12 + .../mat_gArchipelagoItemDL_purple | 12 + .../mat_gArchipelagoItemDL_red | 12 + .../mat_gArchipelagoItemDL_yellow | 12 + .../mat_gArchipelagoJunkDL_black_junk | 12 + .../mat_gArchipelagoJunkDL_blue_junk | 12 + .../mat_gArchipelagoJunkDL_green_junk | 12 + .../mat_gArchipelagoJunkDL_grey_blue | 12 + .../mat_gArchipelagoJunkDL_grey_green | 12 + .../mat_gArchipelagoJunkDL_grey_orange | 12 + .../mat_gArchipelagoJunkDL_grey_outline | 12 + .../mat_gArchipelagoJunkDL_grey_pink | 12 + .../mat_gArchipelagoJunkDL_grey_red | 12 + .../mat_gArchipelagoJunkDL_grey_yellow | 12 + .../mat_gArchipelagoJunkDL_orange_junk | 12 + .../mat_gArchipelagoJunkDL_purple_junk | 12 + .../mat_gArchipelagoJunkDL_red_junk | 12 + .../mat_gArchipelagoJunkDL_yellow_junk | 12 + ...pelagoProgressiveDL_arrow_gold_progressive | 12 + ...ArchipelagoProgressiveDL_black_progressive | 12 + ...gArchipelagoProgressiveDL_blue_progressive | 12 + ...ArchipelagoProgressiveDL_green_progressive | 12 + ...rchipelagoProgressiveDL_orange_progressive | 12 + ...ArchipelagoProgressiveDL_progressive_arrow | 12 + ...gArchipelagoProgressiveDL_progressive_blue | 12 + ...ArchipelagoProgressiveDL_progressive_green | 12 + ...rchipelagoProgressiveDL_progressive_orange | 12 + ...chipelagoProgressiveDL_progressive_outline | 12 + ...gArchipelagoProgressiveDL_progressive_pink | 12 + ..._gArchipelagoProgressiveDL_progressive_red | 12 + ...rchipelagoProgressiveDL_progressive_yellow | 12 + ...rchipelagoProgressiveDL_purple_progressive | 12 + ..._gArchipelagoProgressiveDL_red_progressive | 12 + ...rchipelagoProgressiveDL_yellow_progressive | 12 + .../objects/object_archipelago_item/model.xml | 0 port/textures/icons/g2ShipIcon.png | Bin 13286 -> 0 bytes port/textures/intro/xylophone | Bin 0 -> 131164 bytes port/textures/mapping-xbox.png | Bin 0 -> 79348 bytes .../{actor_spawninit.c => bgsspawnqueue.c} | 12 +- src/BGS/bss_pad.c | 2 - src/BGS/ch/{choir_turtle.c => choirturtle.c} | 6 +- src/BGS/ch/croctus.c | 211 +- src/BGS/ch/frogminigame.c | 31 +- src/BGS/ch/leafboat.c | 4 +- src/BGS/ch/mrvile.c | 106 +- src/BGS/ch/mudhut.c | 53 +- src/BGS/ch/pinkegg.c | 27 +- src/BGS/ch/swampswitch.c | 8 +- src/BGS/ch/tanktup.c | 291 +-- src/BGS/ch/{tanktup_legs.c => tanktuplegs.c} | 19 +- src/BGS/ch/tiptup.c | 328 ++- src/BGS/ch/yellowflibbit.c | 1 + src/BGS/ch/yumblie.c | 6 +- src/BGS/checksums.c | 7 + src/BGS/crc.c | 9 +- src/BGS/{minigame_vile.c => mrvileminigame.c} | 476 +++-- src/CC/bss_pad.c | 2 - src/CC/{actor_spawninit.c => ccspawnqueue.c} | 2 +- src/CC/ch/{clanker.c => ccgrates.c} | 16 +- src/CC/ch/{key.c => clankerkey.c} | 18 +- src/CC/ch/{screw.c => clankerscrew.c} | 18 +- src/CC/ch/clankertoothext.c | 48 +- src/CC/ch/tooth.c | 3 + src/CC/checksums.c | 7 + src/CC/crc.c | 10 +- src/CC/ma/clanker.c | 451 ++++ src/CC/ma/clankerrings.c | 130 ++ src/CC/minigame_rings.c | 115 -- src/CC/model_renderstate.c | 24 +- src/CC/platform_physics.c | 441 ---- src/CCW/actor_spawninit.c | 157 -- src/CCW/bss_pad.c | 2 - src/CCW/ccwspawnqueue.c | 229 +++ src/CCW/ch/acorn.c | 140 +- src/CCW/ch/adulteyrie.c | 129 ++ src/CCW/ch/beanstalk.c | 239 +++ .../ch/{nabnut_summer.c => bellyfullnabnut.c} | 52 +- src/CCW/ch/caterpillar.c | 152 +- src/CCW/ch/{gobi_ccw.c => ccwgobi.c} | 143 +- src/CCW/ch/cutsceneadulteyrie.c | 114 ++ src/CCW/ch/deadbeanstalk.c | 14 +- src/CCW/ch/deadsnarebear.c | 25 + src/CCW/ch/eyrie_baby.c | 301 --- src/CCW/ch/eyrie_egg.c | 70 - src/CCW/ch/eyrie_summer.c | 120 -- src/CCW/ch/eyrie_winter.c | 105 - src/CCW/ch/eyrieegg.c | 94 + src/CCW/ch/fairy.c | 129 -- src/CCW/ch/gnawty.c | 143 -- src/CCW/ch/gnawtyboulder.c | 55 +- src/CCW/ch/grublinhood.c | 45 +- src/CCW/ch/indoorsgnawty.c | 98 + src/CCW/ch/nabnut_autumn.c | 172 -- src/CCW/ch/nabnut_dialog.c | 85 - src/CCW/ch/nabnut_spring.c | 97 - src/CCW/ch/nabnut_winter.c | 124 -- src/CCW/ch/outsideautumnnabnut.c | 226 ++ src/CCW/ch/seasonswitchdoors.c | 245 +++ src/CCW/ch/snarebear.c | 138 +- src/CCW/ch/snore.c | 28 +- src/CCW/ch/springnabnut.c | 110 + src/CCW/ch/summeroutsidegnawty.c | 160 ++ src/CCW/ch/swimminggnawty.c | 140 ++ src/CCW/ch/vacationtexttrigger.c | 2 +- src/CCW/ch/zubba.c | 216 -- src/CCW/ch/zubba_hive_npc.c | 133 -- src/CCW/ch/zubbadoor.c | 37 +- src/CCW/ch/zubbahoneylump.c | 244 +++ src/CCW/checksums.c | 7 + src/CCW/eyrie_baby.c | 382 ++++ src/CCW/flower.c | 170 -- src/CCW/minigame_zubba.c | 221 -- src/CCW/nabnut_winter.c | 174 ++ src/CCW/seasonal_switch.c | 171 -- src/CCW/snarebear_proximity.c | 122 -- src/CCW/zubba.c | 240 +++ src/CCW/zubba_hive_npc.c | 157 ++ src/FP/bss_pad.c | 2 - src/FP/ch/bearcub.c | 68 +- src/FP/ch/boggy1.c | 12 +- src/FP/ch/boggy2.c | 52 +- src/FP/ch/boggy3.c | 18 +- .../slalomctrl.c => ch/boggyraceflag1.c} | 8 +- .../slalom2ctrl.c => ch/boggyraceflag2.c} | 8 +- src/FP/ch/cavewozza.c | 10 +- src/FP/ch/racesled.c | 2 +- src/FP/ch/snowmanbutton.c | 18 +- src/FP/ch/twinkly.c | 10 +- src/FP/ch/twinklybox.c | 16 +- src/FP/ch/twinklymuncher.c | 6 +- src/FP/ch/wozza.c | 14 +- src/FP/ch/xmastree.c | 82 +- src/FP/ch/xmastreeice.c | 28 + src/FP/ch/xmastreestar.c | 4 +- src/FP/ch/xmastreeswitch.c | 4 +- src/FP/checksums.c | 7 + src/FP/{actor_spawninit.c => fpspawnqueue.c} | 4 +- src/FP/{mapstate => ma}/slalom.c | 26 +- src/FP/{mapstate => ma}/snowbutton.c | 0 src/FP/{mapstate => ma}/snowy.c | 0 src/FP/{ch => }/wozza_fire.c | 0 src/GV/bss_pad.c | 2 - src/GV/{ch => }/cactus.c | 0 src/GV/{ch => }/carpet1.c | 0 src/GV/{ch => }/carpet2.c | 12 +- src/GV/ch/ancientone.c | 65 +- src/GV/ch/buriedpyramid.c | 9 +- src/GV/ch/{egg_pot.c => eggpot.c} | 2 +- src/GV/ch/gobi1.c | 6 +- src/GV/ch/gobi2.c | 8 +- src/GV/ch/gobi3.c | 5 +- src/GV/ch/gobirock.c | 2 +- src/GV/ch/gobirope.c | 2 +- src/GV/ch/grabba.c | 12 +- src/GV/ch/histup.c | 20 +- src/GV/ch/jinxy.c | 158 -- src/GV/{ => ch}/mazectrl.c | 16 +- src/GV/ch/mummum.c | 2 +- src/GV/ch/sarcophagus.c | 2 +- src/GV/ch/slappa.c | 2 +- src/GV/ch/toots.c | 2 +- src/GV/ch/trunker.c | 6 +- src/GV/checksums.c | 7 + src/GV/crc.c | 10 +- src/GV/gv_helpers.c | 14 +- src/GV/{actor_spawninit.c => gvspawnqueue.c} | 80 +- src/GV/{ch => }/handshadow.c | 0 src/GV/{ch => }/jinxy_head.c | 0 src/GV/magiccarpet2.c | 171 ++ .../carpet_shadow.c => magiccarpetshadow.c} | 19 +- src/GV/matchinggame.c | 6 +- src/GV/pyramid_raise.c | 164 +- src/GV/{ch => }/rubee.c | 64 +- .../{pyramid_trigger.c => sandybutteggtoll.c} | 13 +- src/GV/smoke_particle.c | 4 +- src/GV/water_pyramidrot.c | 20 +- src/LAIR/bss_pad.c | 2 - src/MM/ch/chimpystump.c | 14 +- src/MM/ch/conga.c | 198 +- src/MM/ch/conga.h | 11 + src/MM/ch/hut.c | 69 +- src/MM/ch/juju.c | 3 +- src/MM/ch/jujuhitbox.c | 21 +- src/MM/ch/lmonkey.c | 14 +- src/MM/ch/orange.c | 2 +- src/MM/ch/orangepad.c | 159 +- src/MM/ch/orangepad.h | 14 + src/MM/checksums.c | 7 + src/MM/crc.c | 8 +- src/MM/{actor_spawninit.c => mmspawnqueue.c} | 2 +- src/MMM/bathroom_particles.c | 6 +- src/MMM/bss_pad.c | 2 - src/MMM/ch/{flowerpot.c => cemetarypot.c} | 18 +- src/MMM/ch/loggo.c | 10 +- src/MMM/ch/napper.c | 16 +- src/MMM/ch/portrait.c | 4 +- .../{portrait_chompa.c => portraitchompa.c} | 6 +- src/MMM/ch/{limbo.c => skeleton.c} | 6 +- src/MMM/ch/tumblar.c | 8 +- src/MMM/checksums.c | 7 + src/MMM/crc.c | 9 +- src/MMM/minigame_organ.c | 10 +- src/MMM/minigame_shed.c | 2 +- .../{actor_spawninit.c => mmmspawnqueue.c} | 229 ++- src/MMM/napper_room.c | 8 +- src/RBB/actor_spawninit.c | 231 --- src/RBB/bss_pad.c | 2 - src/RBB/ch/anchor.c | 33 +- src/RBB/ch/anchorctrl.c | 45 +- src/RBB/ch/anchorswitch.c | 27 +- src/RBB/ch/axle.c | 138 +- src/RBB/ch/bellbuoy.c | 153 +- src/RBB/ch/boombox.c | 253 +-- src/RBB/ch/bossboombox.c | 450 ++-- src/RBB/ch/bossboomboxctrl.c | 18 +- src/RBB/ch/cog.c | 67 +- src/RBB/ch/dolphin.c | 76 +- src/RBB/ch/eggtoll1.c | 173 +- src/RBB/ch/enginefan.c | 142 +- src/RBB/ch/enginefanswitch.c | 40 +- src/RBB/ch/engineparts.c | 104 +- src/RBB/ch/grimlet.c | 113 +- src/RBB/ch/propellor.c | 43 +- src/RBB/ch/propellorswitch.c | 35 +- src/RBB/ch/rarewareflag.c | 13 +- src/RBB/ch/rowboat.c | 137 +- .../ch/{seaman_grublin.c => seamangrublin.c} | 2 +- src/RBB/ch/siren.c | 61 - src/RBB/ch/whistle.c | 109 +- src/RBB/ch/whistlectrl.c | 39 +- src/RBB/ch/whistleswitch.c | 172 +- src/RBB/checksums.c | 7 + src/RBB/crane_boombox.c | 84 +- src/RBB/crane_jiggycage.c | 140 +- src/RBB/miniboombox_container.c | 54 +- src/RBB/propellorctrl.c | 4 +- src/RBB/rbbspawnqueue.c | 241 +++ src/RBB/siren.c | 81 + src/SM/{ch => }/bottles_movecheck.c | 0 src/SM/ch/ambient_fish.c | 2 +- src/SM/ch/attacktutorial.c | 24 +- src/SM/ch/jumptutorial.c | 14 +- src/SM/ch/smbottles.c | 42 +- src/SM/ch/vegetables.c | 12 +- src/SM/checksums.c | 7 + src/SM/{ch => }/furniture.c | 0 src/SM/{ch => }/quarrie.c | 5 +- src/SM/{crc.c => smspawnqueue.c} | 45 +- src/SM/version_compat.c | 168 +- src/TTC/actor_spawninit.c | 8 +- src/TTC/ch/blubber.c | 53 +- src/TTC/ch/clam.c | 8 +- src/TTC/ch/leaky.c | 24 +- src/TTC/ch/lockup.c | 10 +- src/TTC/ch/lockup.h | 23 + src/TTC/ch/nipper.c | 56 +- src/TTC/ch/treasure.c | 2 +- src/TTC/ch/treasurehunt.c | 72 +- src/TTC/checksums.c | 7 + src/TTC/crc.c | 23 +- src/TTC/{ => ma}/castle.c | 16 +- src/boot/bk_boot_1050.c | 10 +- src/core1/audio_instruments.c | 14 +- src/core1/audio_manager.c | 721 ++++--- src/core1/{io => }/bamotor.c | 59 +- src/core1/debugtext.c | 2 +- src/core1/defragmanager.c | 4 +- src/core1/depthbuffer.c | 54 +- src/core1/display_list.c | 111 +- src/core1/graphics_thread.c | 144 +- src/core1/{math/ml.c => gu_matrix.c} | 2 +- src/core1/{math/mlmtx.c => gu_perspective.c} | 13 +- src/core1/init.c | 23 +- src/core1/math/longlong_arith.c | 63 - src/core1/math/longlong_convert.c | 40 - src/core1/{math/vector.c => ml.c} | 136 +- src/core1/{math/matrix_stack.c => mlmtx.c} | 21 +- src/core1/musicplayer.c | 47 +- src/core1/musicplayer.h | 7 + src/core1/n_audio/n_csplayer.c | 2 +- src/core1/n_audio/n_env.c | 2 +- src/core1/n_audio/n_seqplayer.c | 2 +- src/core1/overlay.c | 15 +- src/core1/{io => }/pfsmanager.c | 46 +- src/core1/{stopnswop_payload.c => sns.c} | 2 +- src/core1/stopnswop.c | 4 +- src/core1/syncprintf.c | 17 - src/core1/viewport.c | 20 +- src/core1/vimgr.c | 52 +- src/core2/abilityprogress.c | 28 +- src/core2/actor_array.c | 137 +- src/core2/actor_cleanup.c | 5 +- src/core2/actor_cubepropsystem.c | 147 +- src/core2/actor_motioncurve.c | 34 +- src/core2/actor_updatestub.c | 15 +- src/core2/anim/{controller.c => anctrl.c} | 1 + src/core2/anim/anim_bonetransform.c | 6 + src/core2/anim/anim_buffer.c | 2 + src/core2/anim/anim_defrag.c | 4 +- src/core2/anim/anim_driver.c | 82 +- src/core2/anim/anim_sequencehandler.c | 1 + src/core2/anim/{anim_cache.c => animcache.c} | 1 + ...anim_texturecache.c => animtexturecache.c} | 1 + src/core2/anim/{sequence.c => anseq.c} | 1 + .../{anim_sequencestruct.c => betavent.c} | 17 +- src/core2/anim/bonetransformlist.c | 1 + .../anim/{anim_spriteframe.c => chumpfish.c} | 3 +- src/core2/anim/{skeletal.c => skeletalanim.c} | 1 + src/core2/anim/sprite.c | 2 +- src/core2/ba/{ba_anim.c => anim.c} | 81 +- src/core2/ba/ba_animcache.c | 1 + src/core2/ba/ba_animstate.c | 197 -- src/core2/ba/ba_camera.c | 3 +- src/core2/ba/ba_eyeblink_data.c | 1 + src/core2/ba/ba_eyemouth_data.c | 9 +- src/core2/ba/ba_falling.c | 4 +- src/core2/ba/ba_health.c | 5 +- src/core2/ba/ba_hitbox.c | 17 +- src/core2/ba/ba_intensity.c | 1 + src/core2/ba/ba_lookdir.c | 75 +- src/core2/ba/ba_momentum.c | 1 + src/core2/ba/ba_musicstate.c | 1 + src/core2/ba/ba_recoil.c | 9 +- src/core2/ba/ba_state.c | 331 --- src/core2/ba/ba_statusflags.c | 3 +- src/core2/ba/ba_stickinterp.c | 1 + src/core2/ba/ba_underwater.c | 1 + src/core2/ba/ba_yaw.c | 1 + src/core2/ba/{ba_bounds.c => babounds.c} | 3 +- src/core2/ba/{ba_buzz.c => babuzz.c} | 1 + src/core2/ba/{ba_eyes.c => baeyes.c} | 11 +- src/core2/ba/{ba_flag.c => baflag.c} | 1 + src/core2/ba/{ba_input.c => bainput.c} | 1 + src/core2/ba/{ba_key.c => bakey.c} | 1 + src/core2/ba/{ba_lookat.c => balookat.c} | 1 + src/core2/ba/{ba_sfx.c => basfx.c} | 1 + src/core2/ba/{ba_stick.c => bastick.c} | 3 +- src/core2/ba/{ba_timer.c => batimer.c} | 5 +- src/core2/ba/bsmethods.c | 335 +++ .../ba/{ba_carriedobj.c => carriedobj.c} | 7 +- src/core2/ba/{ba_carry.c => carry.c} | 3 +- src/core2/ba/{ba_scripted.c => drone.c} | 1 + .../ba/{ba_falldamage.c => falldamage.c} | 5 +- src/core2/ba/{ba_flap.c => flap.c} | 1 + .../ba/{ba_groundsurface.c => hazards.c} | 9 +- src/core2/ba/{ba_eyeblink.c => iFrame.c} | 2 + src/core2/ba/iFrame.h | 10 + src/core2/ba/{ba_marker.c => marker.c} | 50 +- src/core2/ba/{ba_model.c => model.c} | 19 +- src/core2/ba/modelappendages.c | 209 ++ src/core2/ba/{ba_physics.c => physics.c} | 17 +- .../ba/{ba_modelselect.c => playermodel.c} | 24 +- .../ba/{ba_position.c => playerposition.c} | 9 +- src/core2/bs/ant.c | 60 +- src/core2/bs/{beak_barge.c => bBarge.c} | 10 +- src/core2/bs/{beak_egg_fire.c => bEggAss.c} | 17 +- src/core2/bs/{beak_egg_aim.c => bEggHead.c} | 28 +- src/core2/bs/{flap_flip.c => bFlap.c} | 10 +- src/core2/bs/{backflip.c => bFlip.c} | 10 +- src/core2/bs/{beak_bomb.c => bFly.c} | 132 +- src/core2/bs/{stilt_stride.c => bLongLeg.c} | 68 +- src/core2/bs/{beak_peck.c => bPeck.c} | 9 +- src/core2/bs/{shock_spring.c => bShock.c} | 28 +- src/core2/bs/{beak_swim.c => bSwim.c} | 72 +- src/core2/bs/{talon_trot.c => bTrot.c} | 52 +- src/core2/bs/{wonderwing.c => bWhirl.c} | 28 +- src/core2/bs/{beak_buster.c => bbuster.c} | 12 +- src/core2/bs/bee.c | 4 +- src/core2/bs/{bee_fly.c => beeFly.c} | 24 +- src/core2/bs/{bee_main.c => beeMain.c} | 98 +- src/core2/bs/{bs_list.c => bsList.c} | 1 + .../bs/{bs_storedstate.c => bsStoredState.c} | 1 + src/core2/bs/bs_statemachine.c | 1 + src/core2/bs/carry.c | 11 +- src/core2/bs/claw.c | 5 +- src/core2/bs/climb.c | 16 +- src/core2/bs/croc.c | 67 +- src/core2/bs/crouch.c | 10 +- src/core2/bs/die.c | 10 +- src/core2/bs/{scripted.c => drone.c} | 1 + .../bs/{scripted_enter.c => droneenter.c} | 4 +- src/core2/bs/{scripted_goto.c => dronegoto.c} | 4 +- src/core2/bs/{scripted_look.c => dronelook.c} | 16 +- .../bs/{scripted_vanish.c => dronevanish.c} | 4 +- .../bs/{scripted_transform.c => dronexform.c} | 44 +- src/core2/bs/{jiggy_dance.c => jig.c} | 14 +- src/core2/bs/jump.c | 33 +- src/core2/bs/{hurt.c => ow.c} | 1 + src/core2/bs/player_spawn.c | 257 +-- src/core2/bs/pumpkin.c | 39 +- src/core2/bs/rebound.c | 21 +- src/core2/bs/rest.c | 29 +- src/core2/bs/sled.c | 3 +- src/core2/bs/slide.c | 5 +- src/core2/bs/splat.c | 7 +- src/core2/bs/stand.c | 49 +- src/core2/bs/surf.c | 11 +- src/core2/bs/swim.c | 25 +- src/core2/bs/talk.c | 2 +- src/core2/bs/throw.c | 6 +- src/core2/bs/timeout.c | 39 +- src/core2/bs/turn.c | 4 +- src/core2/bs/walk.c | 55 +- src/core2/bs/walrus.c | 77 +- src/core2/bs/{washing_machine.c => washy.c} | 12 +- src/core2/bundle.c | 1 + src/core2/camera/dynamicCam1.c | 46 - src/core2/ch/beehive.c | 6 +- src/core2/ch/beeswarm.c | 8 +- src/core2/ch/bottlesbonus.c | 25 +- src/core2/ch/bottlesbonuscursor.c | 30 +- src/core2/ch/{climb_base.c => climbBase.c} | 5 +- src/core2/ch/clucker.c | 6 +- src/core2/ch/collectible.c | 12 +- src/core2/ch/crab.c | 169 +- src/core2/ch/extralife.c | 1 + src/core2/ch/feather.c | 1 + src/core2/ch/gameSelect.h | 14 + src/core2/ch/ghost.c | 188 +- src/core2/ch/gloop.c | 2 +- src/core2/ch/goldfeather.c | 5 +- src/core2/ch/gravestone.c | 4 +- .../ch/{grill_chompa.c => grillechompa.c} | 3 +- src/core2/ch/honeycomb.c | 23 +- src/core2/ch/icecube.c | 2 +- src/core2/ch/jiggy.c | 224 +- src/core2/ch/jiggy.h | 20 + src/core2/ch/jinjo.c | 187 +- src/core2/ch/level_collectible.c | 378 ---- src/core2/ch/levelcollectible.c | 692 +++++++ src/core2/ch/mole.c | 204 +- src/core2/ch/molehill.c | 12 +- src/core2/ch/mumbo_sign.c | 26 - src/core2/ch/mumbosign.c | 27 + src/core2/ch/mumbotoken.c | 11 +- src/core2/ch/shock_jumppad.c | 1 + src/core2/ch/snacker.c | 6 +- src/core2/ch/snowball.c | 2 +- src/core2/ch/snowman.c | 23 +- src/core2/ch/trainers.c | 4 +- src/core2/ch/wadingboots.c | 10 +- src/core2/checksums.c | 7 + src/core2/climb.c | 41 +- src/core2/collision/climbsurface.c | 23 +- src/core2/collision/dispatch.c | 1 + src/core2/collision/enemy.c | 5 +- src/core2/collision/filter.c | 1 + src/core2/collision/geometrybounds.c | 1 + src/core2/collision/hitboxdata.c | 452 ++-- src/core2/collision/polydetect.c | 1 + src/core2/collision/raycast.c | 1 + .../{raycastmap.c => scarabbeetle.c} | 15 +- src/core2/collision/spherecast.c | 1 + src/core2/collision/tricheck.c | 1 + src/core2/crc_bootvalidation.c | 138 +- src/core2/{demo_input.c => demo.c} | 8 +- src/core2/dialog/binload.c | 5 +- src/core2/dialog/progressDialog.c | 135 ++ src/core2/dialog/progress_dialogs.c | 134 -- src/core2/displaylist_init.c | 7 +- src/core2/fileselect.c | 2 + src/core2/{freelist.c => fla.c} | 1 + src/core2/flags_bitfield.c | 64 +- src/core2/font/print.c | 439 ++-- src/core2/font/render.c | 39 +- src/core2/frame/auxbuffer.c | 77 +- src/core2/frame/rendermem.c | 18 +- src/core2/frame/texture_capture.c | 15 +- src/core2/fx/{enemy_shadow.c => badShad.c} | 11 +- ...effect_spriteanim.c => banjokazooiesign.c} | 38 +- ...{projectile_manager.c => commonParticle.c} | 13 +- .../{background_decor.c => cutscene_actors.c} | 47 +- src/core2/fx/drips.c | 1 + src/core2/fx/effect_colordata.c | 1 + src/core2/fx/effect_debris.c | 138 +- src/core2/fx/effect_ice.c | 4 +- src/core2/fx/effect_jiggy.c | 1 + src/core2/fx/effect_jiggy_list.c | 19 +- src/core2/fx/effect_jiggy_spawn.c | 1 + src/core2/fx/effect_modelparticle.c | 1 + src/core2/fx/effect_playerspray.c | 9 +- src/core2/fx/effect_ripple.c | 3 +- src/core2/fx/effect_simplesprite.c | 1 + src/core2/fx/effect_soundemit.c | 132 -- src/core2/fx/effect_sparkleemit.c | 5 +- .../fx/{effect_eggshatter.c => eggshatter.c} | 1 + .../{effect_generic.c => explosionripple.c} | 1 + src/core2/fx/firefx.c | 1 + .../fx/{droplet.c => piranhaWaterParticles.c} | 3 +- src/core2/fx/projectile_anim.c | 1 + src/core2/fx/projectile_blueegg.c | 11 +- src/core2/fx/projectile_render.c | 1 + src/core2/fx/projectile_smoke.c | 1 + src/core2/fx/projectile_sparkle.c | 1 + src/core2/fx/projectile_spawnfx.c | 1 + src/core2/fx/projectile_system.c | 1 + .../fx/{effect_ripple_spawn.c => ripple.c} | 1 + .../fx/{effect_sparkle.c => shoesparkle.c} | 34 +- src/core2/fx/shrapnel.c | 3 +- .../fx/{effect_sparkle_spawn.c => sparkle.c} | 1 + src/core2/{sfx/init.c => fx/weather.c} | 1 + src/core2/fx/weather_emitter.c | 188 ++ .../{sfx/playstate.c => fx/weather_leaves.c} | 5 +- .../{sfx/streamctrl.c => fx/weather_rain.c} | 5 +- .../{sfx/filedata.c => fx/weather_snow.c} | 58 +- src/core2/fx/whipcrack.c | 1 + src/core2/gameSelect.c | 125 +- src/core2/gameloop.c | 144 +- src/core2/gamestate.c | 64 +- src/core2/{context => gc}/bound.c | 1 + src/core2/{context => gc}/dialog.c | 48 +- src/core2/gc/dialog.h | 22 + .../{context => gc}/enter_text_trigger.c | 21 +- .../{context/gameover.c => gc/gameoversign.c} | 20 +- .../overlaycopyright.c} | 1 + .../overlaynocontroller.c} | 5 +- .../overlaypressstart.c} | 7 +- src/core2/{context => gc}/parade.c | 1 + .../{context/pause_menu.c => gc/pauseMenu.c} | 56 +- src/core2/{context => gc}/pictureframe.c | 14 +- .../{context/map_info.c => gc/section.c} | 1 + src/core2/{context => gc}/sky.c | 27 +- src/core2/{context => gc}/transition.c | 47 +- src/core2/{context => gc}/zoombox.c | 26 +- src/core2/{actor_cubebounds.c => gccube.c} | 32 +- .../{score_honeycomb.c => honeycombscore.c} | 1 + src/core2/inventory_slots.c | 3 +- src/core2/{score_jiggy.c => jiggyscore.c} | 7 + .../{specificflags.c => levelspecificflags.c} | 25 +- src/core2/level/lightconfig.c | 2 +- src/core2/level/metadata.c | 1 + src/core2/map/audioconfig.c | 1 + src/core2/map/cutscene_skip.c | 29 +- src/core2/map/cutscene_triggers.c | 1 + src/core2/map/envcolor.c | 1 + src/core2/map/exit.c | 11 +- src/core2/map/gsworld.c | 125 +- src/core2/map/list.c | 3 +- src/core2/map/loadzone.c | 1 + src/core2/map/{model.c => mapModel.c} | 85 +- src/core2/map/{savestate.c => mapsavestate.c} | 1 + .../{specificflags.c => mapspecificflags.c} | 13 +- src/core2/map/overlay.c | 19 +- src/core2/map/warp_dispatch.c | 20 +- src/core2/map/world_reset.c | 1 + src/core2/matrix_interp.c | 1 + src/core2/model/lighting.c | 1 + src/core2/model/mesh_dataaccess.c | 1 + src/core2/model/meshbounds.c | 1 + src/core2/model/{render.c => modelRender.c} | 32 +- src/core2/model/rendernormal.c | 1 + src/core2/model/skinning.c | 1 + src/core2/model/vertex_brightness.c | 1 + src/core2/{mumbo_transforms.c => mumbo.c} | 141 +- src/core2/{score_mumbo.c => mumboscore.c} | 1 + .../{demo_ctrl.c => mumboshandwithpicture.c} | 71 +- .../{camera/firstpersoncamera.c => nc/1p.c} | 39 +- .../{camera => nc}/camera_debug_freecam.c | 1 + src/core2/{camera => nc}/camera_ease.c | 3 +- src/core2/{camera => nc}/camera_focus.c | 1 + src/core2/{camera => nc}/camera_focustarget.c | 1 + src/core2/{camera => nc}/camera_fog.c | 1 + src/core2/{camera => nc}/camera_motor1.c | 13 + src/core2/{camera => nc}/camera_motor2.c | 1 + src/core2/{camera => nc}/camera_nodemanager.c | 18 +- src/core2/{camera => nc}/camera_position.c | 1 + src/core2/{camera => nc}/camera_set.c | 1 + src/core2/{camera => nc}/cameranode_type1.c | 1 + src/core2/{camera => nc}/cameranode_type2.c | 1 + src/core2/{camera => nc}/cameranode_type3.c | 1 + src/core2/{camera => nc}/cameranode_type4.c | 1 + src/core2/{camera => nc}/cameranodelist.c | 1 + src/core2/{camera/dynamicCamD.c => nc/die.c} | 11 +- src/core2/nc/dynamicCam1.c | 50 + src/core2/{camera => nc}/dynamicCam10.c | 1 + src/core2/{camera => nc}/dynamicCam11.c | 1 + src/core2/{camera => nc}/dynamicCam12.c | 1 + src/core2/{camera => nc}/dynamicCam13.c | 1 + src/core2/{camera => nc}/dynamicCam3.c | 9 +- src/core2/{camera => nc}/dynamicCam5.c | 3 +- src/core2/{camera => nc}/dynamicCam8.c | 1 + src/core2/{camera => nc}/dynamicCam9.c | 11 +- src/core2/{camera => nc}/dynamicCamA.c | 1 + src/core2/{camera => nc}/dynamicCamB.c | 1 + src/core2/{camera => nc}/dynamicCamC.c | 3 +- src/core2/{camera => nc}/dynamicCamF.c | 1 + src/core2/{camera => nc}/dynamicCamera.c | 161 +- src/core2/{camera/dynamicCam4.c => nc/fly.c} | 31 +- src/core2/{camera => nc}/randomCamera.c | 1 + src/core2/{camera => nc}/staticCamera.c | 3 +- .../{factory.c => commonParticleTypeMap.c} | 1 + .../{colordefault.c => dustemitter.c} | 1 + src/core2/particle/emitter1.c | 1 + src/core2/particle/emitter2.c | 1 + src/core2/particle/emitterstruct.c | 3 +- src/core2/particle/initcallback.c | 1 + src/core2/particle/lifescale.c | 1 + src/core2/particle/particle.c | 27 +- .../{accel.c => particleemittermanager.c} | 1 + src/core2/particle/positionset.c | 1 + src/core2/particle/samplerate.c | 1 + src/core2/particle/scale1.c | 1 + src/core2/particle/scale2.c | 1 + src/core2/particle/spawn.c | 1 + src/core2/particle/typeindex.c | 1 + src/core2/particle/velocityrange.c | 1 + src/core2/particle/velocityset.c | 1 + src/core2/playerutils.c | 82 +- .../{prop_assetcache.c => propModelList.c} | 1 + src/core2/quiz/game.c | 626 ++++-- .../quiz/{minigamemanager.c => minigame.c} | 3 +- src/core2/quiz/questionmanager.c | 1 + ...bitfield.c => quizquestionaskedbitfield.c} | 5 +- src/core2/quiz/storage.c | 3 +- .../core2/quiz/storage.h | 14 +- src/core2/savedata.c | 5 +- .../scorequeue/{drawui_air.c => airscore.c} | 1 + .../{drawui_stub.c => common1score.c} | 1 + .../{drawui_sprites.c => common2score.c} | 11 +- .../{drawui_models.c => common3score.c} | 13 +- src/core2/scorequeue/dispatch.c | 1 + .../{drawui_health.c => healthscore.c} | 1 + ...wui_honeycarrier.c => honeycarrierscore.c} | 1 + .../{drawui_jinjo.c => jinjoscore.c} | 1 + .../{drawui_lives.c => lifescore.c} | 1 + src/core2/scorequeue/manager.c | 5 +- src/core2/scorequeue/queue_collectibles.c | 1 + src/core2/scorequeue/queue_honeycombs.c | 1 + src/core2/scorequeue/queue_lives.c | 1 + src/core2/scorequeue/queue_major_items.c | 1 + src/core2/scorequeue/queue_notes.c | 1 + src/core2/scorequeue/queue_timers.c | 1 + src/core2/scorequeue/queue_totals.c | 1 + src/core2/sfx/instruments.c | 6 +- src/core2/sfx/pitched.c | 1 + src/core2/sfx/randompitch.c | 1 + src/core2/sfx/sequenceindex.c | 1 + src/core2/sfx/soundsource.c | 1 + src/core2/sfx/source.c | 12 +- src/core2/sfx/trackmanager.c | 1 + src/core2/sfx/volume.c | 1 + src/core2/{snacker_ctl.c => snackerctl.c} | 9 +- src/core2/{spawn_queue.c => spawnqueue.c} | 356 ++-- src/core2/spline_bezier.c | 1 + src/core2/spline_pathfollow.c | 10 +- src/core2/sprite/render.c | 7 +- src/core2/sprite/rendertex.c | 1 + src/core2/sprite/screenoverlay.c | 13 +- src/core2/sprite/texblock.c | 1 + src/core2/{state_timer.c => statetimer.c} | 1 + src/core2/texture_dataaccess.c | 7 +- src/core2/time.c | 9 +- src/core2/time_framedelta.c | 20 +- .../{timed_funcqueue.c => timedfuncqueue.c} | 1 + src/core2/{vector.c => vla.c} | 5 +- src/core2/vtx/alphablend.c | 1 + src/core2/vtx/colorapply.c | 1 + src/core2/vtx/colorintensity.c | 1 + src/core2/vtx/colorset.c | 1 + src/core2/vtx/convert.c | 1 + src/core2/vtx/{lighting.c => gclights.c} | 11 +- src/core2/vtx/list.c | 7 +- src/core2/vtx/listutils.c | 6 +- src/core2/vtx/meshcount.c | 1 + src/core2/vtx/normalset.c | 1 + src/core2/vtx/positionset.c | 11 +- src/core2/vtx/renderstart.c | 3 +- src/core2/vtx/scale.c | 1 + src/core2/vtx/transform.c | 2 + src/core2/vtx/uvset.c | 1 + src/cutscenes/bss_pad.c | 2 - src/cutscenes/checksums.c | 7 + src/cutscenes/cutscene_trigger.c | 2 +- ...ctor_spawninit.c => cutscenesspawnqueue.c} | 2 +- src/cutscenes/{fx => }/glow_sparkle.c | 0 src/cutscenes/{fx => }/smoke.c | 0 src/cutscenes/{fx => }/sparkle.c | 0 .../{character_parade.c => theendsign.c} | 15 +- src/emptyLvl/checksums.c | 7 + src/{overlay_stub => emptyLvl}/empty_level.c | 2 +- src/{FINALE/ch => fight}/chbossjinjo.c | 2 +- src/{FINALE/ch => fight}/chbossjinjobase.c | 10 +- src/{FINALE/ch => fight}/chbossshadow.c | 2 +- src/fight/checksums.c | 7 + src/{FINALE/ch => fight}/chfinalboss.c | 111 +- src/{FINALE => fight}/chgreenblast.c | 0 src/{FINALE/ch => fight}/chjinjonator.c | 2 +- src/{FINALE/ch => fight}/chjinjonatorbase.c | 52 +- src/{FINALE => fight}/chspellbarrier.c | 0 src/{FINALE => fight}/chspellfireball.c | 0 src/{FINALE => fight}/chstonejinjo.c | 0 src/{FINALE => fight}/fight.c | 2 - src/{FINALE => fight}/fight.h | 36 +- src/{LAIR => lair}/ch/brentilda.c | 9 +- src/{LAIR => lair}/ch/cauldron.c | 8 +- src/{LAIR => lair}/ch/cheato.c | 8 +- .../ch/furnacefunprizes.c} | 6 +- src/{LAIR => lair}/ch/gruntling.c | 2 +- .../ch/lairgruntilda.c} | 8 +- .../item_pillows.c => lair/ch/refillpillow.c} | 6 +- src/lair/checksums.c | 7 + src/{LAIR/ch => lair}/fall_damagedetect.c | 0 src/{LAIR/ch => lair}/ff_lava_fireball.c | 0 .../ch => lair}/ff_lava_fireball_actor.c | 0 src/{LAIR => lair}/ff_manager.c | 42 +- src/{LAIR => lair}/jigsawpicture.c | 121 +- src/lair/jigsawpicture.h | 11 + .../lairspawnqueue.c} | 649 +++++- src/{LAIR/ch => lair}/tooty_parade.c | 0 src/port/Audio/AudioSync.cpp | 23 + src/port/Audio/mixer.h | 30 +- src/port/Controller/ControlSchemes.cpp | 255 ++- src/port/Controller/Mapper.cpp | 1709 ++++++++++++++++ src/port/Controller/Mapper.h | 182 ++ src/port/Controller/ModernCamera.cpp | 179 +- src/port/DevTools/DevSequences.cpp | 4 + src/port/DevTools/DevSequences.h | 1 + src/port/DevTools/FlagTracer.cpp | 243 +++ src/port/DevTools/OcclusionDebug.cpp | 7 +- src/port/DevTools/ThreadWatchdog.cpp | 580 ++++++ src/port/DevTools/ThreadWatchdog.h | 94 + src/port/Engine.cpp | 329 +-- src/port/Engine.h | 5 - src/port/Enhancements/Backports/EggAim.cpp | 14 +- src/port/Enhancements/Backports/FastSwim.cpp | 2 - src/port/Enhancements/Backports/Honeyback.cpp | 2 - .../Backports/TooieJiggyDance.cpp | 23 +- .../Enhancements/Camera/FreeLookCamera.cpp | 201 +- .../Enhancements/Camera/OrbitCameraCore.cpp | 157 -- .../Enhancements/Camera/OrbitCameraCore.h | 59 - src/port/Enhancements/Cheats/Cheats.cpp | 129 +- .../Enhancements/Cosmetics/PlayerColors.cpp | 480 +++++ .../Enhancements/Cosmetics/PlayerColors.h | 43 + .../Enhancements/Cutscenes/CutsceneSkips.cpp | 14 + .../Enhancements/Cutscenes/IntroLogos.cpp | 59 + src/port/Enhancements/Events/Hooks/Events.h | 99 +- .../Events/Hooks/List/BehaviorEvent.h | 1 + .../Events/Hooks/List/EngineEvent.h | 11 + .../Events/Hooks/List/GameEvent.h | 20 + .../Events/Hooks/List/RandoEvent.h | 2 + .../Enhancements/Events/PortEnhancements.cpp | 16 + src/port/Enhancements/Fixes/GameFixes.cpp | 44 +- .../Fixes/TransientLevelState.cpp | 62 + .../Enhancements/Gameplay/DamageScale.cpp | 13 - src/port/Enhancements/Gameplay/Difficulty.cpp | 53 + .../Gameplay/EasierBoggyRaces.cpp | 2 - .../Enhancements/Gameplay/FurnaceFunMoves.cpp | 7 +- .../Enhancements/Gameplay/SkipSMTutorial.cpp | 30 +- .../Gameplay/WaterPyramidTimer.cpp | 2 - .../JinjoRetention/JinjoRetention.cpp | 195 -- .../JinjoRetention/JinjoRetention.h | 8 - .../NoteRetention/NoteRetention.cpp | 425 ---- .../NoteRetention/NoteRetention.h | 17 - .../Restorations/ReturnToLair.cpp | 6 +- .../Enhancements/Retention/JinjoRetention.cpp | 271 +++ .../Enhancements/Retention/NoteRetention.cpp | 495 +++++ src/port/Enhancements/Retention/Retention.cpp | 31 + src/port/Enhancements/Retention/Retention.h | 80 + src/port/Enhancements/Retention/WormSync.cpp | 199 ++ .../Enhancements/Trackers/DisplayOverlay.cpp | 12 +- src/port/Extractor/GameExtractor.cpp | 126 +- src/port/Extractor/GameExtractor.h | 8 +- src/port/FilePicker.cpp | 66 + src/port/FilePicker.h | 34 + src/port/Game.cpp | 297 ++- src/port/GameStatus.cpp | 78 +- src/port/GameVersion/AssetVersionRemap.h | 1111 +++++----- src/port/GameVersion/BaseGameVersion.cpp | 70 +- src/port/GameVersion/BaseGameVersion.h | 6 + src/port/Interpolation/AdaptiveFps.cpp | 185 -- src/port/Interpolation/AdaptiveFps.h | 46 - src/port/Interpolation/FrameInterpolation.cpp | 836 +++++--- src/port/Interpolation/FrameInterpolation.h | 26 +- src/port/LaunchArgs.cpp | 148 ++ src/port/LaunchArgs.h | 13 + src/port/Localization/Language.cpp | 84 +- src/port/Localization/Localization.cpp | 44 +- src/port/Nametag/Nametag.cpp | 172 +- src/port/Nametag/Nametag.h | 11 +- src/port/Nametag/NametagBindings.cpp | 48 +- src/port/Network/Anchor/Anchor.cpp | 285 ++- src/port/Network/Anchor/Anchor.h | 137 +- src/port/Network/Anchor/AnchorRoomWindow.cpp | 15 +- src/port/Network/Anchor/Authority.cpp | 35 +- src/port/Network/Anchor/Authority.h | 6 +- src/port/Network/Anchor/DummyPlayer.cpp | 222 +- src/port/Network/Anchor/DummyPlayer.h | 39 +- src/port/Network/Anchor/FightSync.c | 554 +++++ src/port/Network/Anchor/FightSync.h | 98 + src/port/Network/Anchor/HookHandlers.cpp | 429 +++- src/port/Network/Anchor/JigsawPedestal.cpp | 93 + src/port/Network/Anchor/JigsawPedestal.h | 23 + src/port/Network/Anchor/JsonConversions.hpp | 34 + src/port/Network/Anchor/Menu.cpp | 194 +- .../Network/Anchor/Packets/AllClientState.cpp | 11 +- .../Network/Anchor/Packets/BreakObject.cpp | 114 ++ .../Network/Anchor/Packets/CarryThrow.cpp | 64 + .../Network/Anchor/Packets/CollectItem.cpp | 152 ++ .../Network/Anchor/Packets/DamagePlayer.cpp | 36 +- .../Network/Anchor/Packets/DisableAnchor.cpp | 1 - src/port/Network/Anchor/Packets/EggToll.cpp | 108 + .../Anchor/Packets/EntranceDiscovered.cpp | 6 +- .../Network/Anchor/Packets/FightEvent.cpp | 72 + .../Network/Anchor/Packets/FightState.cpp | 70 + .../Network/Anchor/Packets/FightUpdate.cpp | 75 + .../Network/Anchor/Packets/GameComplete.cpp | 7 +- src/port/Network/Anchor/Packets/GiveItem.cpp | 9 +- src/port/Network/Anchor/Packets/Handshake.cpp | 2 - src/port/Network/Anchor/Packets/HutSmash.cpp | 108 + .../Network/Anchor/Packets/JiggyCrane.cpp | 35 + src/port/Network/Anchor/Packets/MapLoad.cpp | 6 +- .../Network/Anchor/Packets/PedestalOwner.cpp | 27 + src/port/Network/Anchor/Packets/PlayerSfx.cpp | 18 - .../Network/Anchor/Packets/PlayerUpdate.cpp | 70 +- .../Network/Anchor/Packets/PuzzleStep.cpp | 340 +++ .../Anchor/Packets/RequestTeamState.cpp | 7 +- .../Anchor/Packets/RequestTeleport.cpp | 32 +- .../Network/Anchor/Packets/ScopedFlag.cpp | 79 + .../Network/Anchor/Packets/ScopedState.cpp | 88 + .../Network/Anchor/Packets/ServerMessage.cpp | 1 - .../Network/Anchor/Packets/SetAbility.cpp | 51 + .../Network/Anchor/Packets/SetCheckStatus.cpp | 109 +- src/port/Network/Anchor/Packets/SetFlag.cpp | 95 +- .../Network/Anchor/Packets/SetItemCount.cpp | 47 + .../Network/Anchor/Packets/SpawnHoneycomb.cpp | 47 + .../Network/Anchor/Packets/SpawnJiggy.cpp | 171 ++ .../Network/Anchor/Packets/TeleportTo.cpp | 57 +- src/port/Network/Anchor/Packets/UnsetFlag.cpp | 86 +- .../Anchor/Packets/UpdateClientState.cpp | 16 +- .../Anchor/Packets/UpdateRoomState.cpp | 109 +- .../Anchor/Packets/UpdateTeamState.cpp | 494 +++-- .../Network/Anchor/Packets/VileEatRequest.cpp | 9 - .../Network/Anchor/Packets/VileEatResult.cpp | 12 +- .../Network/Anchor/Packets/VileGameState.cpp | 9 +- .../Network/Anchor/Packets/VileHoleState.cpp | 2 - .../Network/Anchor/Packets/VileUpdate.cpp | 4 +- src/port/Network/Anchor/Packets/WaterRise.cpp | 121 ++ src/port/Network/Anchor/VileSync.c | 8 +- src/port/Network/Anchor/VileSync.h | 2 +- src/port/OS/OS.h | 95 + src/port/OS/OS_AI.cpp | 61 + src/port/OS/OS_Cont.cpp | 103 + src/port/OS/OS_Mesg.cpp | 239 +++ src/port/OS/OS_RCP.cpp | 102 + src/port/OS/OS_Threads.cpp | 155 ++ src/port/OS/OS_Time.cpp | 39 + src/port/OS/OS_Timer.cpp | 121 ++ src/port/OS/OS_VI.cpp | 111 + src/port/{stub.c => OS/libultra.c} | 46 +- src/port/Patches/AnimVertexPatches.cpp | 54 + src/port/Patches/CameraPatches.cpp | 11 +- src/port/Patches/FramePacingPatches.cpp | 48 +- src/port/Patches/FramebufferPatches.cpp | 133 +- src/port/Patches/GeoCull.cpp | 12 +- src/port/Patches/GeoCull.h | 4 - src/port/Patches/GraphicsPatches.cpp | 193 +- src/port/Patches/MirrorPatches.cpp | 24 +- src/port/Patches/Patches.h | 128 +- src/port/Patches/PerfPatches.cpp | 252 +++ src/port/Patches/SpritePatches.cpp | 27 +- src/port/Patches/TransitionPatches.cpp | 17 - src/port/Rando/CheckTracker/CheckTracker.cpp | 14 +- .../CustomCollectible/CustomCollectible.cpp | 243 +++ .../CustomCollectible/CustomCollectible.h | 46 + .../CustomCollectibleDrawCustom.cpp | 108 + .../CustomCollectibleDrawCustom.h | 36 + src/port/Rando/CustomObject/CustomObject.cpp | 60 +- src/port/Rando/ItemQueue.cpp | 344 ++++ src/port/Rando/ItemQueue.h | 10 + src/port/Rando/LighthouseMenuRando.cpp | 65 +- src/port/Rando/Logic/GeneratePools.cpp | 7 +- src/port/Rando/Logic/GenerateSaveData.cpp | 31 +- src/port/Rando/Logic/GlitchlessLogic.cpp | 54 +- src/port/Rando/Logic/Logic.h | 59 +- src/port/Rando/MiscBehavior/OnFileLoad.cpp | 27 +- src/port/Rando/MiscBehavior/WorldState.cpp | 65 +- src/port/Rando/ObjectBehavior/BlueEgg.cpp | 40 + src/port/Rando/ObjectBehavior/Boggy.cpp | 6 +- src/port/Rando/ObjectBehavior/Bundle.cpp | 1059 +++++----- .../Rando/ObjectBehavior/EmptyHoneyComb.cpp | 38 + src/port/Rando/ObjectBehavior/ExtraLife.cpp | 38 + src/port/Rando/ObjectBehavior/Gobi.cpp | 6 +- src/port/Rando/ObjectBehavior/Jiggy.cpp | 99 +- src/port/Rando/ObjectBehavior/Jinjo.cpp | 65 +- src/port/Rando/ObjectBehavior/Molehill.cpp | 186 +- src/port/Rando/ObjectBehavior/MumboToken.cpp | 38 + src/port/Rando/ObjectBehavior/MusicNote.cpp | 59 +- .../Rando/ObjectBehavior/ObjectBehavior.cpp | 141 +- .../Rando/ObjectBehavior/ObjectBehavior.h | 7 - src/port/Rando/ObjectBehavior/Present.cpp | 18 +- src/port/Rando/ObjectBehavior/Prop.cpp | 52 - src/port/Rando/ObjectBehavior/StopNSwop.cpp | 2 +- src/port/Rando/ObjectBehavior/Switch.cpp | 6 - src/port/Rando/Rando.cpp | 4 +- src/port/Rando/Rando.h | 4 + src/port/Rando/Spoiler/File.cpp | 72 + src/port/Rando/Spoiler/Generate.cpp | 111 + src/port/Rando/Spoiler/RefreshOptions.cpp | 40 + src/port/Rando/Spoiler/Spoiler.h | 26 + src/port/Rando/StaticData/Checks.cpp | 1821 ++++++++--------- src/port/Rando/StaticData/Flags.cpp | 1 - src/port/Rando/StaticData/Items.cpp | 58 +- src/port/Rando/StaticData/StaticData.h | 1 + src/port/Rando/Types.h | 53 +- src/port/Resource/Alt/AltBoldFont.cpp | 15 +- src/port/Resource/Alt/AltDialogFont.cpp | 160 ++ src/port/Resource/GfxBridge.c | 30 +- src/port/Resource/Importers/MapFactory.cpp | 15 +- src/port/Resource/Importers/ModelFactory.cpp | 56 +- src/port/Resource/Type/Sprite.cpp | 21 - src/port/ResourceHelpers.cpp | 79 +- src/port/ResourceHelpers.h | 5 + src/port/Romhack/RomhackCompat.cpp | 8 +- src/port/Romhack/RomhackConfig.cpp | 117 +- src/port/Romhack/RomhackConfig.h | 14 +- src/port/Romhack/RomhackQuirks.cpp | 56 - src/port/Romhack/RomhackRegistration.cpp | 61 + src/port/Romhack/RomhackTable.h | 65 +- src/port/Romhack/Shared/HackShared.cpp | 147 ++ src/port/Romhack/Shared/HackShared.h | 23 + src/port/Romhack/Shared/ProximityDialogs.cpp | 83 + src/port/Romhack/Shared/ProximityDialogs.h | 39 + src/port/Romhack/Shared/StealthNoise.cpp | 362 ++++ src/port/Romhack/Shared/StealthNoise.h | 20 + src/port/Romhack/Shared/Storybook.cpp | 134 ++ src/port/Romhack/Shared/Storybook.h | 12 + src/port/Romhack/Specific/BubblingBog.cpp | 24 + src/port/Romhack/Specific/CutThroatCoast.cpp | 284 +++ src/port/Romhack/Specific/Dreamie.cpp | 37 + src/port/Romhack/Specific/JiggiesOfTime.cpp | 31 + src/port/Romhack/Specific/NewHorizons.cpp | 25 + src/port/Romhack/Specific/Nostalgia64.cpp | 90 + src/port/Romhack/Specific/TheGruntch.cpp | 540 +++++ src/port/Save/SaveConverter.cpp | 53 +- src/port/Save/SaveConverter.h | 8 +- src/port/Save/SaveManager.cpp | 209 +- src/port/Save/Types.h | 3 + src/port/ShipUtils.cpp | 17 +- src/port/ShipUtils.h | 5 +- src/port/UI/DeveloperTools/GameplayTools.cpp | 90 +- src/port/UI/DeveloperTools/SaveEditor.cpp | 73 +- src/port/UI/InputViewer.cpp | 624 +++--- src/port/UI/LighthouseGui.cpp | 25 +- src/port/UI/LighthouseInputEditorWindow.cpp | 23 + src/port/UI/LighthouseMenu.cpp | 7 + src/port/UI/LighthouseMenuDevTools.cpp | 27 +- src/port/UI/LighthouseMenuEnhancements.cpp | 172 +- src/port/UI/LighthouseMenuNetwork.cpp | 2 - src/port/UI/LighthouseMenuSettings.cpp | 115 +- src/port/UI/LighthouseModMenuWindow.cpp | 133 +- src/port/UI/LighthouseModals.cpp | 7 +- src/port/UI/Menu.cpp | 19 +- src/port/UI/Menu.h | 3 + src/port/UI/MenuTypes.h | 2 + src/port/UI/Notification.cpp | 26 +- src/port/UI/ResolutionEditor.cpp | 28 +- src/port/UI/ResolutionEditor.h | 2 +- src/port/UI/UIWidgets.cpp | 29 +- .../Gameplay/DisableSnackerSpawn.cpp | 2 - .../enhancements/Gameplay/EasierMrVile.cpp | 2 - src/unused/datalookup.c | 2 +- src/unused/debug_assert.c | 2 +- src/unused/debug_boxdraw.c | 2 +- src/unused/unused_block.c | 2 +- 1077 files changed, 42075 insertions(+), 20243 deletions(-) delete mode 100644 .github/workflows/linux.yml delete mode 100644 .github/workflows/mac.yml delete mode 100644 .github/workflows/switch.yml delete mode 100644 .github/workflows/windows.yml create mode 100644 cmake/GenerateFlagNames.cmake create mode 100644 docs/poweredbylus.darkmode.png create mode 100644 docs/poweredbylus.lightmode.png create mode 100644 include/checksums.h rename lib/ultralib/include/{assert.h => ultra_assert.h} (100%) create mode 100644 port/anim/lighthouse_shrug create mode 100644 port/anim/lighthouse_walk create mode 100644 port/models/lighthouse create mode 100644 port/models/lighthouse_GEO create mode 100644 port/models/lighthouse_VTX create mode 100644 port/models/lighthouse_tex_0 create mode 100644 port/models/lighthouse_tex_1 create mode 100644 port/models/lighthouse_tex_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 create mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 create mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 create mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive create mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive create mode 100644 port/objects/object_archipelago_item/model.xml delete mode 100644 port/textures/icons/g2ShipIcon.png create mode 100644 port/textures/intro/xylophone create mode 100644 port/textures/mapping-xbox.png rename src/BGS/{actor_spawninit.c => bgsspawnqueue.c} (91%) delete mode 100644 src/BGS/bss_pad.c rename src/BGS/ch/{choir_turtle.c => choirturtle.c} (95%) rename src/BGS/ch/{tanktup_legs.c => tanktuplegs.c} (75%) create mode 100644 src/BGS/checksums.c rename src/BGS/{minigame_vile.c => mrvileminigame.c} (58%) delete mode 100644 src/CC/bss_pad.c rename src/CC/{actor_spawninit.c => ccspawnqueue.c} (98%) rename src/CC/ch/{clanker.c => ccgrates.c} (73%) rename src/CC/ch/{key.c => clankerkey.c} (91%) rename src/CC/ch/{screw.c => clankerscrew.c} (88%) create mode 100644 src/CC/checksums.c create mode 100644 src/CC/ma/clanker.c create mode 100644 src/CC/ma/clankerrings.c delete mode 100644 src/CC/minigame_rings.c delete mode 100644 src/CC/platform_physics.c delete mode 100644 src/CCW/actor_spawninit.c delete mode 100644 src/CCW/bss_pad.c create mode 100644 src/CCW/ccwspawnqueue.c create mode 100644 src/CCW/ch/adulteyrie.c create mode 100644 src/CCW/ch/beanstalk.c rename src/CCW/ch/{nabnut_summer.c => bellyfullnabnut.c} (61%) rename src/CCW/ch/{gobi_ccw.c => ccwgobi.c} (55%) create mode 100644 src/CCW/ch/cutsceneadulteyrie.c create mode 100644 src/CCW/ch/deadsnarebear.c delete mode 100644 src/CCW/ch/eyrie_baby.c delete mode 100644 src/CCW/ch/eyrie_egg.c delete mode 100644 src/CCW/ch/eyrie_summer.c delete mode 100644 src/CCW/ch/eyrie_winter.c create mode 100644 src/CCW/ch/eyrieegg.c delete mode 100644 src/CCW/ch/fairy.c delete mode 100644 src/CCW/ch/gnawty.c create mode 100644 src/CCW/ch/indoorsgnawty.c delete mode 100644 src/CCW/ch/nabnut_autumn.c delete mode 100644 src/CCW/ch/nabnut_dialog.c delete mode 100644 src/CCW/ch/nabnut_spring.c delete mode 100644 src/CCW/ch/nabnut_winter.c create mode 100644 src/CCW/ch/outsideautumnnabnut.c create mode 100644 src/CCW/ch/seasonswitchdoors.c create mode 100644 src/CCW/ch/springnabnut.c create mode 100644 src/CCW/ch/summeroutsidegnawty.c create mode 100644 src/CCW/ch/swimminggnawty.c delete mode 100644 src/CCW/ch/zubba.c delete mode 100644 src/CCW/ch/zubba_hive_npc.c create mode 100644 src/CCW/ch/zubbahoneylump.c create mode 100644 src/CCW/checksums.c create mode 100644 src/CCW/eyrie_baby.c delete mode 100644 src/CCW/flower.c delete mode 100644 src/CCW/minigame_zubba.c create mode 100644 src/CCW/nabnut_winter.c delete mode 100644 src/CCW/seasonal_switch.c delete mode 100644 src/CCW/snarebear_proximity.c create mode 100644 src/CCW/zubba.c create mode 100644 src/CCW/zubba_hive_npc.c delete mode 100644 src/FP/bss_pad.c rename src/FP/{mapstate/slalomctrl.c => ch/boggyraceflag1.c} (94%) rename src/FP/{mapstate/slalom2ctrl.c => ch/boggyraceflag2.c} (89%) create mode 100644 src/FP/checksums.c rename src/FP/{actor_spawninit.c => fpspawnqueue.c} (99%) rename src/FP/{mapstate => ma}/slalom.c (91%) rename src/FP/{mapstate => ma}/snowbutton.c (100%) rename src/FP/{mapstate => ma}/snowy.c (100%) rename src/FP/{ch => }/wozza_fire.c (100%) delete mode 100644 src/GV/bss_pad.c rename src/GV/{ch => }/cactus.c (100%) rename src/GV/{ch => }/carpet1.c (100%) rename src/GV/{ch => }/carpet2.c (90%) rename src/GV/ch/{egg_pot.c => eggpot.c} (95%) delete mode 100644 src/GV/ch/jinxy.c rename src/GV/{ => ch}/mazectrl.c (90%) create mode 100644 src/GV/checksums.c rename src/GV/{actor_spawninit.c => gvspawnqueue.c} (84%) rename src/GV/{ch => }/handshadow.c (100%) rename src/GV/{ch => }/jinxy_head.c (100%) create mode 100644 src/GV/magiccarpet2.c rename src/GV/{ch/carpet_shadow.c => magiccarpetshadow.c} (61%) rename src/GV/{ch => }/rubee.c (56%) rename src/GV/{pyramid_trigger.c => sandybutteggtoll.c} (69%) delete mode 100644 src/LAIR/bss_pad.c create mode 100644 src/MM/ch/conga.h create mode 100644 src/MM/ch/orangepad.h create mode 100644 src/MM/checksums.c rename src/MM/{actor_spawninit.c => mmspawnqueue.c} (97%) delete mode 100644 src/MMM/bss_pad.c rename src/MMM/ch/{flowerpot.c => cemetarypot.c} (73%) rename src/MMM/ch/{portrait_chompa.c => portraitchompa.c} (98%) rename src/MMM/ch/{limbo.c => skeleton.c} (95%) create mode 100644 src/MMM/checksums.c rename src/MMM/{actor_spawninit.c => mmmspawnqueue.c} (55%) delete mode 100644 src/RBB/actor_spawninit.c delete mode 100644 src/RBB/bss_pad.c rename src/RBB/ch/{seaman_grublin.c => seamangrublin.c} (97%) delete mode 100644 src/RBB/ch/siren.c create mode 100644 src/RBB/checksums.c create mode 100644 src/RBB/rbbspawnqueue.c create mode 100644 src/RBB/siren.c rename src/SM/{ch => }/bottles_movecheck.c (100%) create mode 100644 src/SM/checksums.c rename src/SM/{ch => }/furniture.c (100%) rename src/SM/{ch => }/quarrie.c (94%) rename src/SM/{crc.c => smspawnqueue.c} (80%) create mode 100644 src/TTC/ch/lockup.h create mode 100644 src/TTC/checksums.c rename src/TTC/{ => ma}/castle.c (98%) rename src/core1/{io => }/bamotor.c (78%) rename src/core1/{math/ml.c => gu_matrix.c} (99%) rename src/core1/{math/mlmtx.c => gu_perspective.c} (93%) delete mode 100644 src/core1/math/longlong_arith.c delete mode 100644 src/core1/math/longlong_convert.c rename src/core1/{math/vector.c => ml.c} (88%) rename src/core1/{math/matrix_stack.c => mlmtx.c} (95%) create mode 100644 src/core1/musicplayer.h rename src/core1/{io => }/pfsmanager.c (93%) rename src/core1/{stopnswop_payload.c => sns.c} (99%) delete mode 100644 src/core1/syncprintf.c rename src/core2/anim/{controller.c => anctrl.c} (99%) rename src/core2/anim/{anim_cache.c => animcache.c} (98%) rename src/core2/anim/{anim_texturecache.c => animtexturecache.c} (98%) rename src/core2/anim/{sequence.c => anseq.c} (99%) rename src/core2/anim/{anim_sequencestruct.c => betavent.c} (88%) rename src/core2/anim/{anim_spriteframe.c => chumpfish.c} (99%) rename src/core2/anim/{skeletal.c => skeletalanim.c} (99%) rename src/core2/ba/{ba_anim.c => anim.c} (88%) delete mode 100644 src/core2/ba/ba_animstate.c delete mode 100644 src/core2/ba/ba_state.c rename src/core2/ba/{ba_bounds.c => babounds.c} (93%) rename src/core2/ba/{ba_buzz.c => babuzz.c} (98%) rename src/core2/ba/{ba_eyes.c => baeyes.c} (88%) rename src/core2/ba/{ba_flag.c => baflag.c} (95%) rename src/core2/ba/{ba_input.c => bainput.c} (98%) rename src/core2/ba/{ba_key.c => bakey.c} (98%) rename src/core2/ba/{ba_lookat.c => balookat.c} (98%) rename src/core2/ba/{ba_sfx.c => basfx.c} (99%) rename src/core2/ba/{ba_stick.c => bastick.c} (98%) rename src/core2/ba/{ba_timer.c => batimer.c} (93%) create mode 100644 src/core2/ba/bsmethods.c rename src/core2/ba/{ba_carriedobj.c => carriedobj.c} (93%) rename src/core2/ba/{ba_carry.c => carry.c} (95%) rename src/core2/ba/{ba_scripted.c => drone.c} (98%) rename src/core2/ba/{ba_falldamage.c => falldamage.c} (96%) rename src/core2/ba/{ba_flap.c => flap.c} (98%) rename src/core2/ba/{ba_groundsurface.c => hazards.c} (96%) rename src/core2/ba/{ba_eyeblink.c => iFrame.c} (92%) create mode 100644 src/core2/ba/iFrame.h rename src/core2/ba/{ba_marker.c => marker.c} (95%) rename src/core2/ba/{ba_model.c => model.c} (94%) create mode 100644 src/core2/ba/modelappendages.c rename src/core2/ba/{ba_physics.c => physics.c} (96%) rename src/core2/ba/{ba_modelselect.c => playermodel.c} (87%) rename src/core2/ba/{ba_position.c => playerposition.c} (87%) rename src/core2/bs/{beak_barge.c => bBarge.c} (94%) rename src/core2/bs/{beak_egg_fire.c => bEggAss.c} (72%) rename src/core2/bs/{beak_egg_aim.c => bEggHead.c} (63%) rename src/core2/bs/{flap_flip.c => bFlap.c} (94%) rename src/core2/bs/{backflip.c => bFlip.c} (94%) rename src/core2/bs/{beak_bomb.c => bFly.c} (85%) rename src/core2/bs/{stilt_stride.c => bLongLeg.c} (88%) rename src/core2/bs/{beak_peck.c => bPeck.c} (92%) rename src/core2/bs/{shock_spring.c => bShock.c} (86%) rename src/core2/bs/{beak_swim.c => bSwim.c} (89%) rename src/core2/bs/{talon_trot.c => bTrot.c} (92%) rename src/core2/bs/{wonderwing.c => bWhirl.c} (90%) rename src/core2/bs/{beak_buster.c => bbuster.c} (94%) rename src/core2/bs/{bee_fly.c => beeFly.c} (91%) rename src/core2/bs/{bee_main.c => beeMain.c} (85%) rename src/core2/bs/{bs_list.c => bsList.c} (97%) rename src/core2/bs/{bs_storedstate.c => bsStoredState.c} (97%) rename src/core2/bs/{scripted.c => drone.c} (97%) rename src/core2/bs/{scripted_enter.c => droneenter.c} (97%) rename src/core2/bs/{scripted_goto.c => dronegoto.c} (94%) rename src/core2/bs/{scripted_look.c => dronelook.c} (84%) rename src/core2/bs/{scripted_vanish.c => dronevanish.c} (96%) rename src/core2/bs/{scripted_transform.c => dronexform.c} (91%) rename src/core2/bs/{jiggy_dance.c => jig.c} (92%) rename src/core2/bs/{hurt.c => ow.c} (98%) rename src/core2/bs/{washing_machine.c => washy.c} (90%) delete mode 100644 src/core2/camera/dynamicCam1.c rename src/core2/ch/{climb_base.c => climbBase.c} (95%) create mode 100644 src/core2/ch/gameSelect.h rename src/core2/ch/{grill_chompa.c => grillechompa.c} (97%) create mode 100644 src/core2/ch/jiggy.h delete mode 100644 src/core2/ch/level_collectible.c create mode 100644 src/core2/ch/levelcollectible.c delete mode 100644 src/core2/ch/mumbo_sign.c create mode 100644 src/core2/ch/mumbosign.c create mode 100644 src/core2/checksums.c rename src/core2/collision/{raycastmap.c => scarabbeetle.c} (97%) rename src/core2/{demo_input.c => demo.c} (91%) create mode 100644 src/core2/dialog/progressDialog.c delete mode 100644 src/core2/dialog/progress_dialogs.c rename src/core2/{freelist.c => fla.c} (99%) rename src/core2/fx/{enemy_shadow.c => badShad.c} (93%) rename src/core2/fx/{effect_spriteanim.c => banjokazooiesign.c} (61%) rename src/core2/fx/{projectile_manager.c => commonParticle.c} (96%) rename src/core2/fx/{background_decor.c => cutscene_actors.c} (69%) delete mode 100644 src/core2/fx/effect_soundemit.c rename src/core2/fx/{effect_eggshatter.c => eggshatter.c} (98%) rename src/core2/fx/{effect_generic.c => explosionripple.c} (94%) rename src/core2/fx/{droplet.c => piranhaWaterParticles.c} (94%) rename src/core2/fx/{effect_ripple_spawn.c => ripple.c} (99%) rename src/core2/fx/{effect_sparkle.c => shoesparkle.c} (50%) rename src/core2/fx/{effect_sparkle_spawn.c => sparkle.c} (99%) rename src/core2/{sfx/init.c => fx/weather.c} (98%) create mode 100644 src/core2/fx/weather_emitter.c rename src/core2/{sfx/playstate.c => fx/weather_leaves.c} (97%) rename src/core2/{sfx/streamctrl.c => fx/weather_rain.c} (97%) rename src/core2/{sfx/filedata.c => fx/weather_snow.c} (78%) rename src/core2/{context => gc}/bound.c (98%) rename src/core2/{context => gc}/dialog.c (97%) create mode 100644 src/core2/gc/dialog.h rename src/core2/{context => gc}/enter_text_trigger.c (78%) rename src/core2/{context/gameover.c => gc/gameoversign.c} (85%) rename src/core2/{context/overlay_copyright.c => gc/overlaycopyright.c} (97%) rename src/core2/{context/overlay_nocontroller.c => gc/overlaynocontroller.c} (97%) rename src/core2/{context/overlay_pressstart.c => gc/overlaypressstart.c} (94%) rename src/core2/{context => gc}/parade.c (99%) rename src/core2/{context/pause_menu.c => gc/pauseMenu.c} (95%) rename src/core2/{context => gc}/pictureframe.c (89%) rename src/core2/{context/map_info.c => gc/section.c} (99%) rename src/core2/{context => gc}/sky.c (88%) rename src/core2/{context => gc}/transition.c (94%) rename src/core2/{context => gc}/zoombox.c (98%) rename src/core2/{actor_cubebounds.c => gccube.c} (99%) rename src/core2/{score_honeycomb.c => honeycombscore.c} (97%) rename src/core2/{score_jiggy.c => jiggyscore.c} (90%) rename src/core2/level/{specificflags.c => levelspecificflags.c} (82%) rename src/core2/map/{model.c => mapModel.c} (93%) rename src/core2/map/{savestate.c => mapsavestate.c} (99%) rename src/core2/map/{specificflags.c => mapspecificflags.c} (85%) rename src/core2/model/{render.c => modelRender.c} (97%) rename src/core2/{mumbo_transforms.c => mumbo.c} (74%) rename src/core2/{score_mumbo.c => mumboscore.c} (97%) rename src/core2/{demo_ctrl.c => mumboshandwithpicture.c} (68%) rename src/core2/{camera/firstpersoncamera.c => nc/1p.c} (74%) rename src/core2/{camera => nc}/camera_debug_freecam.c (98%) rename src/core2/{camera => nc}/camera_ease.c (96%) rename src/core2/{camera => nc}/camera_focus.c (96%) rename src/core2/{camera => nc}/camera_focustarget.c (97%) rename src/core2/{camera => nc}/camera_fog.c (98%) rename src/core2/{camera => nc}/camera_motor1.c (94%) rename src/core2/{camera => nc}/camera_motor2.c (99%) rename src/core2/{camera => nc}/camera_nodemanager.c (94%) rename src/core2/{camera => nc}/camera_position.c (98%) rename src/core2/{camera => nc}/camera_set.c (98%) rename src/core2/{camera => nc}/cameranode_type1.c (99%) rename src/core2/{camera => nc}/cameranode_type2.c (98%) rename src/core2/{camera => nc}/cameranode_type3.c (99%) rename src/core2/{camera => nc}/cameranode_type4.c (96%) rename src/core2/{camera => nc}/cameranodelist.c (99%) rename src/core2/{camera/dynamicCamD.c => nc/die.c} (73%) create mode 100644 src/core2/nc/dynamicCam1.c rename src/core2/{camera => nc}/dynamicCam10.c (96%) rename src/core2/{camera => nc}/dynamicCam11.c (98%) rename src/core2/{camera => nc}/dynamicCam12.c (99%) rename src/core2/{camera => nc}/dynamicCam13.c (98%) rename src/core2/{camera => nc}/dynamicCam3.c (81%) rename src/core2/{camera => nc}/dynamicCam5.c (87%) rename src/core2/{camera => nc}/dynamicCam8.c (97%) rename src/core2/{camera => nc}/dynamicCam9.c (86%) rename src/core2/{camera => nc}/dynamicCamA.c (98%) rename src/core2/{camera => nc}/dynamicCamB.c (98%) rename src/core2/{camera => nc}/dynamicCamC.c (91%) rename src/core2/{camera => nc}/dynamicCamF.c (95%) rename src/core2/{camera => nc}/dynamicCamera.c (85%) rename src/core2/{camera/dynamicCam4.c => nc/fly.c} (70%) rename src/core2/{camera => nc}/randomCamera.c (97%) rename src/core2/{camera => nc}/staticCamera.c (96%) rename src/core2/particle/{factory.c => commonParticleTypeMap.c} (98%) rename src/core2/particle/{colordefault.c => dustemitter.c} (98%) rename src/core2/particle/{accel.c => particleemittermanager.c} (98%) rename src/core2/{prop_assetcache.c => propModelList.c} (99%) rename src/core2/quiz/{minigamemanager.c => minigame.c} (98%) rename src/core2/quiz/{bitfield.c => quizquestionaskedbitfield.c} (81%) rename include/core2/quiz_storage.h => src/core2/quiz/storage.h (85%) rename src/core2/scorequeue/{drawui_air.c => airscore.c} (99%) rename src/core2/scorequeue/{drawui_stub.c => common1score.c} (91%) rename src/core2/scorequeue/{drawui_sprites.c => common2score.c} (97%) rename src/core2/scorequeue/{drawui_models.c => common3score.c} (89%) rename src/core2/scorequeue/{drawui_health.c => healthscore.c} (99%) rename src/core2/scorequeue/{drawui_honeycarrier.c => honeycarrierscore.c} (99%) rename src/core2/scorequeue/{drawui_jinjo.c => jinjoscore.c} (99%) rename src/core2/scorequeue/{drawui_lives.c => lifescore.c} (99%) rename src/core2/{snacker_ctl.c => snackerctl.c} (95%) rename src/core2/{spawn_queue.c => spawnqueue.c} (61%) rename src/core2/{state_timer.c => statetimer.c} (97%) rename src/core2/{timed_funcqueue.c => timedfuncqueue.c} (99%) rename src/core2/{vector.c => vla.c} (92%) rename src/core2/vtx/{lighting.c => gclights.c} (94%) delete mode 100644 src/cutscenes/bss_pad.c create mode 100644 src/cutscenes/checksums.c rename src/cutscenes/{actor_spawninit.c => cutscenesspawnqueue.c} (99%) rename src/cutscenes/{fx => }/glow_sparkle.c (100%) rename src/cutscenes/{fx => }/smoke.c (100%) rename src/cutscenes/{fx => }/sparkle.c (100%) rename src/cutscenes/{character_parade.c => theendsign.c} (79%) create mode 100644 src/emptyLvl/checksums.c rename src/{overlay_stub => emptyLvl}/empty_level.c (75%) rename src/{FINALE/ch => fight}/chbossjinjo.c (99%) rename src/{FINALE/ch => fight}/chbossjinjobase.c (95%) rename src/{FINALE/ch => fight}/chbossshadow.c (97%) create mode 100644 src/fight/checksums.c rename src/{FINALE/ch => fight}/chfinalboss.c (95%) rename src/{FINALE => fight}/chgreenblast.c (100%) rename src/{FINALE/ch => fight}/chjinjonator.c (99%) rename src/{FINALE/ch => fight}/chjinjonatorbase.c (85%) rename src/{FINALE => fight}/chspellbarrier.c (100%) rename src/{FINALE => fight}/chspellfireball.c (100%) rename src/{FINALE => fight}/chstonejinjo.c (100%) rename src/{FINALE => fight}/fight.c (99%) rename src/{FINALE => fight}/fight.h (94%) rename src/{LAIR => lair}/ch/brentilda.c (95%) rename src/{LAIR => lair}/ch/cauldron.c (98%) rename src/{LAIR => lair}/ch/cheato.c (96%) rename src/{LAIR/ch/minigame_ffprize.c => lair/ch/furnacefunprizes.c} (97%) rename src/{LAIR => lair}/ch/gruntling.c (99%) rename src/{LAIR/ch/grunty_final.c => lair/ch/lairgruntilda.c} (95%) rename src/{LAIR/ch/item_pillows.c => lair/ch/refillpillow.c} (94%) create mode 100644 src/lair/checksums.c rename src/{LAIR/ch => lair}/fall_damagedetect.c (100%) rename src/{LAIR/ch => lair}/ff_lava_fireball.c (100%) rename src/{LAIR/ch => lair}/ff_lava_fireball_actor.c (100%) rename src/{LAIR => lair}/ff_manager.c (97%) rename src/{LAIR => lair}/jigsawpicture.c (79%) create mode 100644 src/lair/jigsawpicture.h rename src/{LAIR/actor_spawninit.c => lair/lairspawnqueue.c} (73%) rename src/{LAIR/ch => lair}/tooty_parade.c (100%) create mode 100644 src/port/Controller/Mapper.cpp create mode 100644 src/port/Controller/Mapper.h create mode 100644 src/port/DevTools/FlagTracer.cpp create mode 100644 src/port/DevTools/ThreadWatchdog.cpp create mode 100644 src/port/DevTools/ThreadWatchdog.h delete mode 100644 src/port/Enhancements/Camera/OrbitCameraCore.cpp delete mode 100644 src/port/Enhancements/Camera/OrbitCameraCore.h create mode 100644 src/port/Enhancements/Cosmetics/PlayerColors.cpp create mode 100644 src/port/Enhancements/Cosmetics/PlayerColors.h create mode 100644 src/port/Enhancements/Cutscenes/IntroLogos.cpp create mode 100644 src/port/Enhancements/Fixes/TransientLevelState.cpp delete mode 100644 src/port/Enhancements/Gameplay/DamageScale.cpp create mode 100644 src/port/Enhancements/Gameplay/Difficulty.cpp delete mode 100644 src/port/Enhancements/JinjoRetention/JinjoRetention.cpp delete mode 100644 src/port/Enhancements/JinjoRetention/JinjoRetention.h delete mode 100644 src/port/Enhancements/NoteRetention/NoteRetention.cpp delete mode 100644 src/port/Enhancements/NoteRetention/NoteRetention.h create mode 100644 src/port/Enhancements/Retention/JinjoRetention.cpp create mode 100644 src/port/Enhancements/Retention/NoteRetention.cpp create mode 100644 src/port/Enhancements/Retention/Retention.cpp create mode 100644 src/port/Enhancements/Retention/Retention.h create mode 100644 src/port/Enhancements/Retention/WormSync.cpp create mode 100644 src/port/FilePicker.cpp create mode 100644 src/port/FilePicker.h delete mode 100644 src/port/Interpolation/AdaptiveFps.cpp delete mode 100644 src/port/Interpolation/AdaptiveFps.h create mode 100644 src/port/LaunchArgs.cpp create mode 100644 src/port/LaunchArgs.h create mode 100644 src/port/Network/Anchor/FightSync.c create mode 100644 src/port/Network/Anchor/FightSync.h create mode 100644 src/port/Network/Anchor/JigsawPedestal.cpp create mode 100644 src/port/Network/Anchor/JigsawPedestal.h create mode 100644 src/port/Network/Anchor/Packets/BreakObject.cpp create mode 100644 src/port/Network/Anchor/Packets/CarryThrow.cpp create mode 100644 src/port/Network/Anchor/Packets/CollectItem.cpp create mode 100644 src/port/Network/Anchor/Packets/EggToll.cpp create mode 100644 src/port/Network/Anchor/Packets/FightEvent.cpp create mode 100644 src/port/Network/Anchor/Packets/FightState.cpp create mode 100644 src/port/Network/Anchor/Packets/FightUpdate.cpp create mode 100644 src/port/Network/Anchor/Packets/HutSmash.cpp create mode 100644 src/port/Network/Anchor/Packets/JiggyCrane.cpp create mode 100644 src/port/Network/Anchor/Packets/PedestalOwner.cpp create mode 100644 src/port/Network/Anchor/Packets/PuzzleStep.cpp create mode 100644 src/port/Network/Anchor/Packets/ScopedFlag.cpp create mode 100644 src/port/Network/Anchor/Packets/ScopedState.cpp create mode 100644 src/port/Network/Anchor/Packets/SetAbility.cpp create mode 100644 src/port/Network/Anchor/Packets/SetItemCount.cpp create mode 100644 src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp create mode 100644 src/port/Network/Anchor/Packets/SpawnJiggy.cpp create mode 100644 src/port/Network/Anchor/Packets/WaterRise.cpp create mode 100644 src/port/OS/OS.h create mode 100644 src/port/OS/OS_AI.cpp create mode 100644 src/port/OS/OS_Cont.cpp create mode 100644 src/port/OS/OS_Mesg.cpp create mode 100644 src/port/OS/OS_RCP.cpp create mode 100644 src/port/OS/OS_Threads.cpp create mode 100644 src/port/OS/OS_Time.cpp create mode 100644 src/port/OS/OS_Timer.cpp create mode 100644 src/port/OS/OS_VI.cpp rename src/port/{stub.c => OS/libultra.c} (62%) create mode 100644 src/port/Patches/AnimVertexPatches.cpp create mode 100644 src/port/Patches/PerfPatches.cpp create mode 100644 src/port/Rando/CustomCollectible/CustomCollectible.cpp create mode 100644 src/port/Rando/CustomCollectible/CustomCollectible.h create mode 100644 src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp create mode 100644 src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h create mode 100644 src/port/Rando/ItemQueue.cpp create mode 100644 src/port/Rando/ItemQueue.h create mode 100644 src/port/Rando/ObjectBehavior/BlueEgg.cpp create mode 100644 src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp create mode 100644 src/port/Rando/ObjectBehavior/ExtraLife.cpp create mode 100644 src/port/Rando/ObjectBehavior/MumboToken.cpp delete mode 100644 src/port/Rando/ObjectBehavior/Prop.cpp create mode 100644 src/port/Rando/Spoiler/File.cpp create mode 100644 src/port/Rando/Spoiler/Generate.cpp create mode 100644 src/port/Rando/Spoiler/RefreshOptions.cpp create mode 100644 src/port/Rando/Spoiler/Spoiler.h create mode 100644 src/port/Resource/Alt/AltDialogFont.cpp delete mode 100644 src/port/Romhack/RomhackQuirks.cpp create mode 100644 src/port/Romhack/RomhackRegistration.cpp create mode 100644 src/port/Romhack/Shared/HackShared.cpp create mode 100644 src/port/Romhack/Shared/HackShared.h create mode 100644 src/port/Romhack/Shared/ProximityDialogs.cpp create mode 100644 src/port/Romhack/Shared/ProximityDialogs.h create mode 100644 src/port/Romhack/Shared/StealthNoise.cpp create mode 100644 src/port/Romhack/Shared/StealthNoise.h create mode 100644 src/port/Romhack/Shared/Storybook.cpp create mode 100644 src/port/Romhack/Shared/Storybook.h create mode 100644 src/port/Romhack/Specific/BubblingBog.cpp create mode 100644 src/port/Romhack/Specific/CutThroatCoast.cpp create mode 100644 src/port/Romhack/Specific/Dreamie.cpp create mode 100644 src/port/Romhack/Specific/JiggiesOfTime.cpp create mode 100644 src/port/Romhack/Specific/NewHorizons.cpp create mode 100644 src/port/Romhack/Specific/Nostalgia64.cpp create mode 100644 src/port/Romhack/Specific/TheGruntch.cpp diff --git a/.github/macports.yml b/.github/macports.yml index 976224723..de075020d 100644 --- a/.github/macports.yml +++ b/.github/macports.yml @@ -1,6 +1,8 @@ ports: - name: libsdl2 select: [ universal ] + - name: libsdl2_net + select: [ universal ] - name: libpng select: [ universal ] - name: glew diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index dfac3075b..000000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Linux Validation -on: [pull_request] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Update machine - run: sudo apt update - - name: Install dependencies - run: sudo apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev libogg-dev libvorbis-dev - - name: Install latest SDL - run: | - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://www.libsdl.org/release/SDL2-2.24.1.tar.gz - tar -xzf SDL2-2.24.1.tar.gz - cd SDL2-2.24.1 - ./configure - make -j 10 - sudo make install - - name: Install latest tinyxml2 - run: | - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz - tar -xzf 10.0.0.tar.gz - cd tinyxml2-10.0.0 - mkdir -p build - cd build - cmake .. - make - sudo make install - - name: Build - run: | - cmake -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE=Release - cmake --build build-cmake -j - - name: Create Package - run: | - mkdir Lighthouse-release - mv build-cmake/Lighthouse Lighthouse-release/ - - name: Publish packaged artifacts - uses: actions/upload-artifact@v4 - with: - name: Lighthouse-linux-x64 - path: Lighthouse-release - retention-days: 1 diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml deleted file mode 100644 index 569dcca20..000000000 --- a/.github/workflows/mac.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: MacOS Validation - -on: - pull_request: - branches: [ "*" ] - -jobs: - build: - runs-on: macos-14 - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - uses: melusina-org/setup-macports@v1 - with: - parameters: '.github/macports.yml' - - uses: hendrikmuhs/ccache-action@v1.2 - with: - key: macos # ccache-macos - - name: Build - run: | - cmake -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE=Release -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" - cmake --build build-cmake -j \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8fb69d3a2..f9d670ee5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,7 @@ name: GenerateBuilds on: push: + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -8,9 +9,11 @@ concurrency: jobs: generate-port-o2r: + # Same-repo branches fire both push and pull_request; only build once. + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: true - name: Extract Project Version @@ -22,7 +25,7 @@ jobs: - name: Install dependencies run: sudo apt-get install gcc g++ git cmake ninja-build lsb-release - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.13 + uses: hendrikmuhs/ccache-action@v1.2.23 with: key: ${{ runner.os }}-o2r-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | @@ -41,8 +44,9 @@ jobs: run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" make -C Torch type=release -j3 + cp -r ./libultraship/src/fast/shaders ./port Torch/cmake-build-release/torch pack port lighthouse.o2r o2r -u ${{ steps.extract_version.outputs.version }} - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: lighthouse.o2r path: lighthouse.o2r @@ -52,31 +56,31 @@ jobs: needs: generate-port-o2r runs-on: windows-2022 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: recursive - name: Build run: | - cmake -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64 -DCMAKE_BUILD_TYPE=Release + cmake -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64 cmake --build ./build/x64 --config Release --parallel 10 - name: Download lighthouse.o2r - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: lighthouse.o2r - path: ./build/x64/Release + path: ./build/x64 - name: Create Package run: | mkdir lighthouse-release mkdir lighthouse-release/debug - mv build/x64/Release/Lighthouse.exe lighthouse-release/ - mv build/x64/Release/lighthouse.o2r lighthouse-release/ - mv build/x64/Release/*.pdb lighthouse-release/debug/ + mv build/x64/Lighthouse.exe lighthouse-release/ + mv build/x64/lighthouse.o2r lighthouse-release/ + mv build/x64/*.pdb lighthouse-release/debug/ mv README.md lighthouse-release/readme.txt mv config.yml lighthouse-release/ mv assets lighthouse-release/ Invoke-WebRequest -Uri "https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt" -OutFile "lighthouse-release/gamecontrollerdb.txt" - name: Upload build - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: Lighthouse-windows path: lighthouse-release @@ -85,13 +89,13 @@ jobs: needs: generate-port-o2r runs-on: macos-14 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: submodules: recursive - uses: melusina-org/setup-macports@v1 with: parameters: '.github/macports.yml' - - uses: hendrikmuhs/ccache-action@v1.2 + - uses: hendrikmuhs/ccache-action@v1.2.23 with: key: macos # ccache-macos - name: Build @@ -99,7 +103,7 @@ jobs: cmake -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE=Release -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" cmake --build build-cmake -j - name: Download lighthouse.o2r - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: lighthouse.o2r path: ./build-cmake @@ -109,7 +113,7 @@ jobs: mv _packages/*.dmg Lighthouse.dmg mv README.md readme.txt - name: Publish packaged artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: Lighthouse-mac path: | @@ -120,7 +124,7 @@ jobs: needs: generate-port-o2r runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: recursive - name: Update machine @@ -128,7 +132,7 @@ jobs: - name: Install dependencies run: sudo apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev libogg-dev libvorbis-dev - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.14 + uses: hendrikmuhs/ccache-action@v1.2.23 with: key: linux-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | @@ -183,7 +187,7 @@ jobs: sudo make install sudo cp -av /usr/local/lib/libzip* /lib/x86_64-linux-gnu/ - name: Download lighthouse.o2r - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: lighthouse.o2r path: ./build-cmake @@ -196,11 +200,12 @@ jobs: mv README.md readme.txt mv build-cmake/*.appimage lighthouse.appimage - name: Upload build - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: Lighthouse-linux path: | lighthouse.appimage + readme.txt gamecontrollerdb.txt build-switch: @@ -210,7 +215,7 @@ jobs: container: image: devkitpro/devkita64:20241023 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: recursive - name: Install dependencies @@ -229,7 +234,7 @@ jobs: mv README.md readme.txt mv build-switch/*.nro Lighthouse.nro - name: Upload build - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: Lighthouse-switch path: | diff --git a/.github/workflows/switch.yml b/.github/workflows/switch.yml deleted file mode 100644 index db9773c5c..000000000 --- a/.github/workflows/switch.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Switch Validation -on: [pull_request] - -jobs: - build-switch: - if: false - runs-on: ubuntu-latest - container: - image: devkitpro/devkita64:20241023 - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y ninja-build - sudo apt-get remove -y cmake - git -C libultraship remote add nx https://github.com/YoshiCrystal9/libultraship.git - git -C libultraship fetch nx - git -C libultraship checkout nx/main-nx - wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh - sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir - cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake - cmake --build build-switch --config Release -j3 - wget -O gamecontrollerdb.txt https://github.com/mdqinc/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt - mv README.md readme.txt - mv build-switch/*.nro Lighthouse.nro - - name: Upload build - uses: actions/upload-artifact@v4 - with: - name: Lighthouse-switch - retention-days: 1 - path: | - Lighthouse.nro - config.yml - assets - gamecontrollerdb.txt \ No newline at end of file diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index a0f8ae5e1..000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Windows Validation -on: [pull_request] - -jobs: - build: - runs-on: windows-2022 - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build - run: | - cmake -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64 -DCMAKE_BUILD_TYPE=Release - cmake --build ./build/x64 - - name: Upload build - uses: actions/upload-artifact@v4 - with: - name: lighthouse-windows - path: ./build/x64/Debug - retention-days: 1 \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 8f556ee49..5481e188f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,4 @@ branch = main [submodule "Torch"] path = Torch - url = https://github.com/Malkierian/Torch.git + url = https://github.com/HarbourMasters/Torch.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 360b6670b..b4e2ec1ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # Set the project version and language -project(Lighthouse VERSION 0.0.1 LANGUAGES C CXX ASM) +project(Lighthouse VERSION 1.0.2 LANGUAGES C CXX ASM) include(FetchContent) include(cmake/lighthouse-cvars.cmake) @@ -28,7 +28,7 @@ math(EXPR PATCH_INDEX "${PROJECT_VERSION_PATCH}") # Use the patch number to select the correct word list(GET NATO_PHONETIC_ALPHABET ${PATCH_INDEX} PROJECT_PATCH_WORD) -set(PROJECT_BUILD_NAME "Barnard ${PROJECT_PATCH_WORD}" CACHE STRING "" FORCE) +set(PROJECT_BUILD_NAME "Split Rock ${PROJECT_PATCH_WORD}" CACHE STRING "" FORCE) #set(PROJECT_TEAM "SonicDcer & Lywx" CACHE STRING "" FORCE) # Get Git Information @@ -188,12 +188,16 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/properties.h.in ${CMAKE_CURRENT_SOUR set(Header_Files "resource.h") source_group("include" FILES ${Header_Files}) +# Flag enum name tables for the Flag Tracer, derived from include/enums.h. +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateFlagNames.cmake) + # Include directories include_directories( "${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/include" "${PROJECT_SOURCE_DIR}/lib/ultralib/include" "${PROJECT_SOURCE_DIR}/src" + "${CMAKE_BINARY_DIR}/generated" ) # Collect source files to build the executable @@ -218,6 +222,8 @@ file(GLOB_RECURSE ALL_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/include/*" ) +list(FILTER ALL_FILES EXCLUDE REGEX "src/unused/") + list(APPEND ALL_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc) @@ -497,6 +503,7 @@ option(BUILD_SM64 "Build with Super Mario 64 support" OFF) option(BUILD_MK64 "Build with Mario Kart 64 support" OFF) option(BUILD_SF64 "Build with Star Fox 64 support" OFF) option(BUILD_FZERO "Build with F-Zero X support" OFF) +option(BUILD_OOT "Build with Ocarina of Time support" OFF) option(BUILD_MARIO_ARTIST "Build with Mario Artist support" OFF) option(BUILD_NAUDIO "Build with NAudio support" OFF) add_subdirectory(Torch) @@ -541,6 +548,7 @@ if(MSVC) /we4311; # pointer truncation (e.g. void* to int) /we4312; # conversion to pointer of greater size (e.g. int to void*) /we4133; # incompatible pointer types + /wd4200; # we don't care about zero-sized flexible arrays ${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT}; ${DEFAULT_CXX_EXCEPTION_HANDLING} ) @@ -690,10 +698,12 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") > ) else() - if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(CPU_OPTION -msse2 -mfpmath=sse) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") - set(CPU_OPTION -mcpu=native) + if(NOT DEFINED CPU_OPTION) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + set(CPU_OPTION -msse2 -mfpmath=sse) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(CPU_OPTION -mcpu=native) + endif() endif() target_compile_options(${PROJECT_NAME} PRIVATE @@ -763,6 +773,8 @@ add_custom_target( if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") install(FILES "${CMAKE_BINARY_DIR}/lighthouse.o2r" DESTINATION . COMPONENT ${PROJECT_NAME}) + install(DIRECTORY "${CMAKE_SOURCE_DIR}/assets/" DESTINATION ./assets COMPONENT ${PROJECT_NAME}) + install(FILES "${CMAKE_BINARY_DIR}/config.yml" DESTINATION . COMPONENT ${PROJECT_NAME}) endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") diff --git a/README.md b/README.md index 0597f77ba..2ef18d4ce 100644 --- a/README.md +++ b/README.md @@ -2,39 +2,44 @@ [comment]: <> (Todo: Make Dark Mode Image) # Lighthouse +Harbour Masters port of Banjo Kazooie -Lead Developers: -TODO: fill in +Lead Developer: +* Malkierian -## Discord +Developers: +* JeodC +* Caladius +## Discord Official Discord: https://discord.com/invite/shipofharkinian -If you're having any trouble after reading through this `README`, feel free ask for help in the Lighthouse Support text channels. Please keep in mind that we do not condone piracy. +If you're having any trouble after reading through this `README`, feel free ask for help in the Lighthouse text channels. Please keep in mind that we do not condone piracy. # Quick Start Lighthouse does not include any copyrighted assets. You are required to provide a supported copy of the game. ### 1. Verify your ROM dump -The supported ROMs are US 1.0 and US 1.1 Rev A versions. You can verify you have dumped a supported copy of the game by using the SHA-1 File Checksum Online at https://www.romhacking.net/hash/. +Any retail version listed below is supported. You can verify you have dumped a supported copy of the game by using the SHA-1 File Checksum Online at https://www.romhacking.net/hash/. -- `baserom.us.v10.z64`: `1fe1632098865f639e22c11b9a81ee8f29c75d7a` -- `baserom.us.v11.z64`: `ded6ee166e740ad1bc810fd678a84b48e245ab80` -- `baserom.jp.z64`: `90726d7e7cd5bf6cdfd38f45c9acbf4d45bd9fd8` -- `baserom.pal.z64`: `bb359a75941df74bf7290212c89fbc6e2c5601fe` +* `baserom.us.v10.z64`: `1fe1632098865f639e22c11b9a81ee8f29c75d7a` +* `baserom.us.v11.z64`: `ded6ee166e740ad1bc810fd678a84b48e245ab80` +* `baserom.jp.z64`: `90726d7e7cd5bf6cdfd38f45c9acbf4d45bd9fd8` +* `baserom.pal.z64`: `bb359a75941df74bf7290212c89fbc6e2c5601fe` -TODO: add info about languages +If you have multiple regions of the game and want to use them as language packs, see `# Language Packs` below. ### 2. Verify your ROM is in .z64 format Your ROM needs to be in .z64 format. If it's in .n64 format, use the following to convert it to a .z64: https://hack64.net/tools/swapper.php -### 2. Download Lighthouse from [Releases](https://github.com/HarbourMasters/Lighthouse/releases) +### 3. Download Lighthouse from [Releases](https://github.com/HarbourMasters/Lighthouse/releases) + +### 4. Generating the OTR from the ROM and Play! -### 3. Generating the OTR from the ROM and Play! #### Windows * Extract every file from the zip into a folder of your choosing. -* Run lighthouse.exe and select your US 1.0 or US 1.1 ROM. +* Run lighthouse.exe and select your compatible ROM. #### Linux * Extract every file from the zip into a folder of your choosing. @@ -42,56 +47,57 @@ Your ROM needs to be in .z64 format. If it's in .n64 format, use the following t #### MacOS * Extract every file from the zip into a folder of your choosing. -* Run lighthouse and select your US 1.0 or US 1.1 ROM. - -#### Nintendo Switch -* Run one of the PC releases to generate an `sf64.o2r` file. After launching the game on PC, you will be able to find these files in the same directory as `lighthouse.exe` or `lighthouse.appimage`. -* Copy the files to your sd card +* Run lighthouse and select your compatible ROM. # Configuration +Lighthouse ships with a file with many standard controller mappings that can be used as-is with most controllers. If your controller isn't recognized by Lighthouse, or isn't working properly, you can create your own custom mapping using the built-in mapper in the Settings menu. + ### Default keyboard configuration -| N64 | A | B | Z | Start | Analog stick | C buttons | D-Pad | -| - | - | - | - | - | - | - | - | -| Keyboard | X | C | Z | Space | WASD | Arrow keys | TFGH | +| N64 | A | B | L | R | Z | Start | Analog stick | C buttons | D-Pad | +| - | - | - | - | - | - | - | - | - | - | +| Keyboard | X | C | E | R | Z | Space | WASD | Arrow keys | TFGH | ### Other shortcuts | Keys | Action | | - | - | -| F1 | Toggle menubar | -| F4 | Reset | +| ESC | Toggle menubar | +| Ctrl+R / ⌘R | Reset | | F11 | Fullscreen | | Tab | Toggle Alternate assets | ### Graphics Backends +Currently, there are three rendering APIs supported: DirectX11 (Windows), OpenGL (all platforms), and Metal (macOS). You can change which API to use in the `Settings` menu of the menubar, which requires a restart. If you're having an issue with crashing, you can change the API in the `lighthouse.cfg.json` file by finding the line `"Backend":{`... and changing the `id` value to `2` and set the `Name` to `OpenGL`. `DirectX 11` with id `1` is the default on Windows. `Metal` with id `3` is the default on macOS. + +# Language Packs + +Lighthouse supports using multiple regions of Banjo-Kazooie as language packs. Generate your base `bk.o2r` file and once Lighthouse has started, open the imgui menu. Under General -> Languages, you will be able to select another ROM to extract as a language pack. PAL supports UK, French, and German, and Japanese adds Japanese support. After the language pack is generated, the language it brings will be added to the dropdown menu. -TODO: verify this info +# Romhacks -Currently, there are three rendering APIs supported: DirectX11 (Windows), OpenGL (all platforms), and Metal (macOS). You can change which API to use in the `Settings` menu of the menubar, which requires a restart. If you're having an issue with crashing, you can change the API in the `lighthouse.cfg.json` file by finding the line `"Backend":{`... and changing the `id` value to `3` and set the `Name` to `OpenGL`. `DirectX 11` with id `2` is the default on Windows. `Metal` with id `4` is the default on macOS. +Many romhacks can be extracted from patched ROMs and used as mods with Lighthouse. This can be done in-game using the Romhacks menu in the Settings section. If any hack isn't fully supported, the menu should inform you when extracting the mod. Most supported romhacks currently haven't been fully tested, so there may still be some issues. + +_NOTE: When using romhacks, only US v1.0 is supported, inherited from Banjo's Backpack. Therefore, it is recommended to use **US v1.0** as your base `bk.o2r` file. # Custom Assets + Custom assets are packed in `.o2r` or `.otr` files. To use custom assets, place them in the `mods` folder. If you're interested in creating and/or packing your own custom asset `.o2r`/`.otr` files, check out the following tools: * [**retro - OTR and O2R generator**](https://github.com/HarbourMasters64/retro) -* [**fast64 - Blender plugin (Note that SF64 is not supported at this time)**](https://github.com/HarbourMasters/fast64) +* [**fast64 - Blender plugin (Note that BK64 is not supported at this time)**](https://github.com/HarbourMasters/fast64) # Development -### Building - -TODO: add a main branch +### Building If you want to manually compile Lighthouse, please consult the [building instructions](https://github.com/HarbourMasters/Lighthouse/blob/main/docs/BUILDING.md). ### Playtesting -If you want to playtest a continuous integration build, you can find them at the links below. Keep in mind that these are for playtesting only, and you will likely encounter bugs and possibly crashes. - -TODO: replace these with lighthouse builds +If you want to playtest a continuous integration build, you can find them at the links below. Keep in mind that these are for playtesting only, and you will likely encounter bugs and possibly crashes. -* [Windows](https://nightly.link/HarbourMasters/Starship/workflows/main/main/starship-windows.zip) -* [macOS](https://nightly.link/HarbourMasters/Starship/workflows/main/main/starship-mac-x64.zip) -* [Linux](https://nightly.link/HarbourMasters/Starship/workflows/main/main/Starship-linux.zip) -* [Switch](https://nightly.link/HarbourMasters/Starship/workflows/main/main/Starship-switch.zip) +* [Windows](https://nightly.link/HarbourMasters/Lighthouse/workflows/main/main/Lighthouse-windows.zip) +* [macOS](https://nightly.link/HarbourMasters/Lighthouse/workflows/main/main/Lighthouse-mac.zip) +* [Linux](https://nightly.link/HarbourMasters/Lighthouse/workflows/main/main/Lighthouse-linux.zip) @@ -102,4 +108,5 @@ TODO: replace these with lighthouse builds # Special Thanks: -TODO: fill in +* The Banjo decomp team +* Fredomato, scorched11 for work on rando diff --git a/Torch b/Torch index 75956acb7..f89e94467 160000 --- a/Torch +++ b/Torch @@ -1 +1 @@ -Subproject commit 75956acb7c2210427d3ac4cc7213421f6e1c490c +Subproject commit f89e944671b406615246685a5a60b65e48ab01f8 diff --git a/assets/yaml/jp/rev0/soundfont.yaml b/assets/yaml/jp/rev0/soundfont.yaml index e0d1e89b1..ee925d2ef 100644 --- a/assets/yaml/jp/rev0/soundfont.yaml +++ b/assets/yaml/jp/rev0/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xDA80A0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xEC7890 size: 0x9FB0 symbol: soundfont2ctl diff --git a/assets/yaml/pal/rev0/soundfont.yaml b/assets/yaml/pal/rev0/soundfont.yaml index a1176d24a..b549551f0 100644 --- a/assets/yaml/pal/rev0/soundfont.yaml +++ b/assets/yaml/pal/rev0/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xDA8DF0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xEC85E0 size: 0x9FB0 symbol: soundfont2ctl diff --git a/assets/yaml/us/rev0/soundfont.yaml b/assets/yaml/us/rev0/soundfont.yaml index d6220ade8..7378d4f5d 100644 --- a/assets/yaml/us/rev0/soundfont.yaml +++ b/assets/yaml/us/rev0/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xD846C0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xEA3EB0 size: 0x9FB0 symbol: soundfont2ctl diff --git a/assets/yaml/us/rev1/soundfont.yaml b/assets/yaml/us/rev1/soundfont.yaml index 138c28ffd..bb9ae6b69 100644 --- a/assets/yaml/us/rev1/soundfont.yaml +++ b/assets/yaml/us/rev1/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xD87CA0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BLOB + type: BK64:SOUNDFONT_CTL offset: 0xEA7490 size: 0x9FB0 symbol: soundfont2ctl diff --git a/cmake/GenerateFlagNames.cmake b/cmake/GenerateFlagNames.cmake new file mode 100644 index 000000000..a2b9388ef --- /dev/null +++ b/cmake/GenerateFlagNames.cmake @@ -0,0 +1,123 @@ +# Lifts the flag enums out of include/enums.h into a lookup table for the Flag +# Tracer. Generated into the build tree so it can't drift from enums.h. + +function(_flagnames_parse_enum ENUM_NAME OUT_VAR) + set(_entries "") + set(_in_enum FALSE) + set(_next 0) + + foreach(_line IN LISTS FLAGNAMES_LINES) + if(NOT _in_enum) + if(_line MATCHES "^[ \t]*enum[ \t]+${ENUM_NAME}[ \t]*(\\{)?[ \t]*$") + set(_in_enum TRUE) + endif() + continue() + endif() + + if(_line MATCHES "^[ \t]*\\}") + break() + endif() + + string(REGEX REPLACE "//.*$" "" _clean "${_line}") + string(REGEX REPLACE "/\\*.*\\*/" "" _clean "${_clean}") + + if(_clean MATCHES "^[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*(=[ \t]*(0[xX][0-9a-fA-F]+|[0-9]+))?[ \t]*,?[ \t]*$") + set(_ident "${CMAKE_MATCH_1}") + set(_explicit "${CMAKE_MATCH_3}") + if(NOT _explicit STREQUAL "") + math(EXPR _next "${_explicit}") + endif() + list(APPEND _entries " { ${_next}, \"${_ident}\" },") + math(EXPR _next "${_next} + 1") + endif() + endforeach() + + if(_entries STREQUAL "") + message(FATAL_ERROR "GenerateFlagNames: no entries parsed for 'enum ${ENUM_NAME}'! Has enums.h changed shape?") + endif() + + string(REPLACE ";" "\n" _joined "${_entries}") + set(${OUT_VAR} "${_joined}" PARENT_SCOPE) +endfunction() + +function(_flagnames_emit_table ENUM_NAME TABLE_NAME OUT_VAR) + _flagnames_parse_enum("${ENUM_NAME}" _rows) + set(${OUT_VAR} + "// ${ENUM_NAME}\nstatic const FlagName ${TABLE_NAME}[] = {\n${_rows}\n};\n" + PARENT_SCOPE) +endfunction() + +set(FLAGNAMES_HEADER "${CMAKE_BINARY_DIR}/generated/FlagNames.generated.h") +set(FLAGNAMES_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/include/enums.h") + +file(STRINGS "${FLAGNAMES_SOURCE}" FLAGNAMES_LINES) + +set(FLAGNAMES_BODY +"// GENERATED at configure time by cmake/GenerateFlagNames.cmake from include/enums.h. +#pragma once + +struct FlagName { + int index; + const char* name; +}; +") + +foreach(_pair "file_progress_e:kFileProgressNames" "volatile_flags_e:kVolatileNames" "level_flags_e:kLevelNames") + string(REPLACE ":" ";" _pair "${_pair}") + list(GET _pair 0 _enum) + list(GET _pair 1 _table) + _flagnames_emit_table("${_enum}" "${_table}" _table_text) + string(APPEND FLAGNAMES_BODY "\n${_table_text}") +endforeach() + +set(FLAGNAMES_MAP_GROUPS + "sm_specific_flags:kSmNames:0xB" + "mm_specific_flags:kMmNames:0x1" + "ttc_specific_flags:kTtcNames:0x2" + "bgs_specific_flags:kBgsNames:0x4" + "fp_specific_flags:kFpNames:0x5" + "mmm_specific_flags:kMmmNames:0xA" + "rbb_main_specific_flags:kRbbMainNames:0x9" + "rbb_boat_room_specific_flags:kRbbBoatNames:0x9" + "ccw_zubba_specific_flags:kCcwZubbaNames:0x8" + "ccw_winter_specific_flags:kCcwWinterNames:0x8" + "lair_specific_flags:kLairNames:0x6" +) + +set(FLAGNAMES_GROUP_ROWS "") +foreach(_entry IN LISTS FLAGNAMES_MAP_GROUPS) + string(REPLACE ":" ";" _parts "${_entry}") + list(GET _parts 0 _enum) + list(GET _parts 1 _table) + list(GET _parts 2 _level) + _flagnames_emit_table("${_enum}" "${_table}" _table_text) + string(APPEND FLAGNAMES_BODY "\n${_table_text}") + list(APPEND FLAGNAMES_GROUP_ROWS + " { ${_level}, ${_table}, (int)(sizeof(${_table}) / sizeof(${_table}[0])) },") +endforeach() + +string(REPLACE ";" "\n" FLAGNAMES_GROUP_ROWS "${FLAGNAMES_GROUP_ROWS}") +string(APPEND FLAGNAMES_BODY +" +// Map-specific lookup needs the loaded level to disambiguate. +struct MapFlagGroup { + int level; + const FlagName* names; + int count; +}; + +static const MapFlagGroup kMapFlagGroups[] = { +${FLAGNAMES_GROUP_ROWS} +}; +") + +set(_existing "") +if(EXISTS "${FLAGNAMES_HEADER}") + file(READ "${FLAGNAMES_HEADER}" _existing) +endif() +if(NOT _existing STREQUAL "${FLAGNAMES_BODY}") + file(WRITE "${FLAGNAMES_HEADER}" "${FLAGNAMES_BODY}") + message(STATUS "Generated ${FLAGNAMES_HEADER}") +endif() + +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${FLAGNAMES_SOURCE}") diff --git a/config.yml b/config.yml index 92309861a..270dfe886 100644 --- a/config.yml +++ b/config.yml @@ -19,7 +19,7 @@ ded6ee166e740ad1bc810fd678a84b48e245ab80: config: gbi: F3DEX_BK64 sort: OFFSET - logging: ERROR + logging: WARN textures: ADDITIONAL_DEFINES include_autogen: true output: @@ -34,7 +34,7 @@ bb359a75941df74bf7290212c89fbc6e2c5601fe: config: gbi: F3DEX_BK64 sort: OFFSET - logging: ERROR + logging: WARN textures: ADDITIONAL_DEFINES include_autogen: true output: @@ -49,7 +49,7 @@ bb359a75941df74bf7290212c89fbc6e2c5601fe: config: gbi: F3DEX_BK64 sort: OFFSET - logging: ERROR + logging: WARN textures: ADDITIONAL_DEFINES include_autogen: true output: diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 96037377e..65d0ee921 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -9,7 +9,7 @@ Requires: * The `MSVC v143 - VS 2022 C++ build tools` component of Visual Studio * Python 3 (can be installed manually or as part of Visual Studio) * Git (can be installed manually or as part of Visual Studio) - * Cmake (can be installed via chocolatey or manually) + * Cmake version <= 3.3 (can be installed via chocolatey or manually) During installation, check the "Desktop development with C++" feature set: @@ -22,10 +22,10 @@ It is recommended that you install Python and Git standalone, the install proces _Note: Be sure to either clone with the ``--recursive`` flag or do ``git submodule update --init`` after cloning to pull in the libultraship submodule!_ -2. Place a Banjo-Kazooie `.z64` ROM in the `baseroms/` directory. -3. Build and generate the `bk.o2r` asset archive. +2. Build and generate the `lighthouse.o2r` port assets archive. +3. Generate the `bk.o2r` ROM asset archive. -_Note: Instructions assume using powershell_ +_Note: Instructions assume using powershell, however, it's recommended to use the GeneratePortO2R project in VS and the built-in extraction flow to create the asset archives ```powershell # Navigate to the lighthouse repo within powershell. ie: cd "C:\yourpath\lighthouse" cd lighthouse @@ -216,13 +216,13 @@ cmake --build build-cmake --target clean ``` # Compatible Roms -See [`supportedHashes.json`](supportedHashes.json) +Any retail version. See [the readme](https://github.com/HarbourMasters/Lighthouse/blob/develop/README.md#1-verify-your-rom-dump) ## Getting CI to work on your fork The CI works via [Github Actions](https://github.com/features/actions) where we mostly make use of machines hosted by Github; except for the very first step of the CI process called "Extract assets". This step extracts assets from the ROM and generates the `bk.o2r` archive. -To get this step working on your fork, you'll need to add a machine to your own repository as a self-hosted runner via "Settings > Actions > Runners" in your repository settings. Make sure to add the 'asset-builder' tag to your newly added runner to assign it to run this step. To setup your runner as a service read the docs [here](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service?platform=linux). +To get this step working on your fork, you'll need to enable actions for all sources in the Actions tab on GitHub. You can also add your own local runner on GitHub. ### Runner on Windows You'll have to enable the ability to run unsigned scripts through PowerShell. To do this, open Powershell as administrator and run `set-executionpolicy remotesigned`. Most dependencies get installed as part of the CI process. You will also need to separately install 7z and add it to the PATH so `7z` can be run as a command. [Chocolatey](https://chocolatey.org/) or other package managers can be used to install it easily. diff --git a/docs/modding/LANGUAGE PACKS.md b/docs/modding/LANGUAGE PACKS.md index 8164704e8..ef42bfc33 100644 --- a/docs/modding/LANGUAGE PACKS.md +++ b/docs/modding/LANGUAGE PACKS.md @@ -1,6 +1,6 @@ # Making a Language Pack -A language pack is a small companion archive that adds a new in-game language alongside the retail `bkpal.o2r` / `bkjp.o2r`. Players drop it into their `mods/lang/` folder and pick the new language from the options menu. +A language pack is a small companion archive that adds a new in-game language alongside the retail `bkpal.o2r` / `bkjp.o2r`. Players drop it into their `mods/~lang/` folder and pick the new language from the options menu. This guide walks through building one pack end to end: a **Spanish** translation, from the first export to a finished `bkes.o2r`. @@ -8,6 +8,19 @@ This guide walks through building one pack end to end: a **Spanish** translation ## 1. Export the text to editable YAML +Pack mode has to be on **before** you export. In the repo's `config.yml`, find your base ROM's entry (keyed by ROM hash) and add the `dialog_pack` flag to its `config:` block, pointing `output.binary` at your pack's filename: + +```yaml +config: + dialog_pack: true # add + output: + binary: bkes.o2r # was bk.o2r; the pack's filename +``` + +This is the one edit the pack flow makes to the base game's config, and it also redirects the normal game build - so **revert it once your pack is built**. + +Now run the export: + ``` torch modding export -s -d ``` @@ -20,7 +33,13 @@ This decodes every asset into an editable form under `/src/assets/asset | `lang/us/quizq/` | Grunty furnace quiz questions | 170 | | `lang/us/gruntyq/` | Final-boss Grunty questions | 30 | -You only edit the files you want to translate. Anything you leave alone stays in English. Rename the `us` folder to your country code (`es` for this example) and delete whatever asset yamls you won't be modifying. +You only edit the files you want to translate. Anything you leave alone stays in English. Next, edit the country code in **three places**: + +1. the folder name - `lang/us/` -> `lang/es/` (`es` for this example); +2. the top-level key inside each yaml you keep - `lang/us/dialog/ASSET_…` -> `lang/es/dialog/ASSET_…`; +3. both sides of every `modding.yml` entry - `assets/lang/us/…: assets/lang/us/….yaml` -> `assets/lang/es/…`. + +Then delete the asset yamls you won't be modifying and prune their `modding.yml` entries to match. --- @@ -58,7 +77,9 @@ lang/es/quizq/ASSET_1213_FF_QUIZ_QUESTION: - [0x83, 0xfd, 0x6c, "75"] ``` -Translate the question lines and the answer text. On each option, **keep the two bytes before the string** (`0xfd, 0x6c`) as they bind the answer to its slot. (Here `$` and `%` are font slots this pack draws as `¿` and `Á` once its font is in place; see below.) +Translate the question lines and the answer text. On each option, **keep the two bytes before the string** (`0xfd, 0x6c`) as they bind the answer to its slot; the importer rejects an option row without them. Grunty questions (`gruntyq/`) use the same shape. (Here `$` and `%` are font slots this pack draws as `¿` and `Á` once its font is in place; see below.) + +One yaml hygiene rule: always put double quotes around your translations - an unquoted `,`, `:` or `#` breaks the yaml when the pack is imported. ### How the text is encoded @@ -70,7 +91,7 @@ The dialog/quiz/grunty font (`0x6EB`) is a flat, contiguous sheet beginning at b ! " # $ % & ' ( ) * + , - . / 0-9 : ; < = > ? @ A-Z [ \ ] ^ ``` -The stock font holds only the ASCII set - `A–Z`, `0–9`, and punctuation. **None of Spanish's accents are in it**: `¡ ¿ Á É Í Ó Ú Ñ` all live in byte positions the stock font draws as ASCII symbols (`#`, `%`, `&`, …). So each accent has to be **added** to the font, and you type it as whatever slot you put it in. Our Spanish pack repaints eight symbol slots - `#` `$` `%` `&` `(` `)` `*` `+` → `¡` `¿` `Á` `É` `Í` `Ó` `Ú` `Ñ` (full table in [#5](#5-fonts-and-glyphs)). That's why `COMPA+ERO` renders *COMPAÑERO* (`+` = Ñ) and `$EST%S` renders *¿ESTÁS*. A `\xNN` escape works for any byte inside a double-quoted string, if you'd rather not type the symbol. +The stock font holds only the ASCII set - `A–Z`, `0–9`, and punctuation. **None of Spanish's accents are in it**: `¡ ¿ Á É Í Ó Ú Ñ` all live in byte positions the stock font draws as ASCII symbols (`#`, `%`, `&`, …). So each accent has to be **added** to the font, and you type it as whatever slot you put it in. Our Spanish pack repaints eight symbol slots - `#` `$` `%` `&` `(` `)` `*` `+` → `¡` `¿` `Á` `É` `Í` `Ó` `Ú` `Ñ` (full table in [#5](#5-fonts-and-glyphs)). That's why `COMPA+ERO` renders *COMPAÑERO* (`+` = Ñ) and `$EST%S` renders *¿ESTÁS*. A `\xNN` escape works for any byte inside a **single-quoted** string (`'\xFD'` style - the importer decodes them, and it's the form the exporter itself emits for text carrying inline control codes). Use it for slots past `0x7E`, an extended sheet's high glyphs included; a literal backslash in such a string is `\\`. Don't put high escapes in *double*-quoted strings - there the yaml parser processes them itself, which is fine up to `\x7F` but re-encodes `\x80`–`\xFF` as two UTF-8 bytes, desyncing the text. The same goes for lowercase `a–z` and any non-Latin script - no stock glyph, so you add one. There are two ways to add glyphs, both covered in [#5 Fonts and glyphs](#5-fonts-and-glyphs): @@ -83,7 +104,7 @@ Either way, you type the **slot**, and the replacement font makes it render. Pic ## 3. Declare the language -Two small things turn an ordinary import into a language pack: a header that names the language, and a config flag that puts the build into pack mode. +Two small things turn an ordinary import into a language pack: the `dialog_pack` config flag you already set in [step 1](#1-export-the-text-to-editable-yaml), and a header that names the language. ### Name the language @@ -98,7 +119,7 @@ strings: # optional - see "Hardcoded UI strings" below "": "" ``` -Torch turns this into the `langinfo` manifest that Lighthouse reads to build its language menu. Because it lives in your pack's source, you never touch the base game's canonical asset config. The fields: +Torch turns this into the `langinfo` manifest that Lighthouse reads to build its language menu. Because it lives in your pack's source, the language list never touches the base game's asset yamls. The fields: - **`name`** - what shows in the options menu. This label is drawn by the PC menu (not the in-game font), so the native spelling with real accents is fine here. - **`index`** - the language's slot; `0` for a single-language pack. @@ -178,18 +199,9 @@ strings: One limit comes with this approach: **word order is fixed by the engine.** The number always precedes its noun and the prefix always precedes the game number, so a language that needs the count *after* the noun can't reorder it here. The numbers and the clock are rendered by the engine and aren't translatable - only the words around them are. And the rebuild only happens for a pack that actually supplies these `strings:`; a base US/PAL game keeps its own built-in line. -### Turn on pack mode - -The second piece is a `dialog_pack` flag in the config entry, plus an output name: +### Pack mode -```yaml -config: - dialog_pack: true - output: - binary: bkes.o2r -``` - -`dialog_pack: true` trims the build down to just the translated assets, prefixes them under `lang//`, and builds the `langinfo` manifest. +The `dialog_pack: true` flag was already set back in [step 1](#1-export-the-text-to-editable-yaml) - the export needs it too. At import time it's what trims the build down to just the translated assets, prefixes them under `lang//`, and builds the `langinfo` manifest. --- @@ -199,7 +211,7 @@ config: torch modding import o2r -s -d ``` -The importer walks the asset list: your edited yamls are re-encoded from ``, everything else parses straight from the ROM, and `dialog_pack` strips the result down to the language assets plus `langinfo`. The finished pack lands in **`mods/lang/`** automatically, named from your `output.binary` - `bkes.o2r` in our case. Copy that into the game's `mods/lang/` folder and it shows up in the options menu. +The importer walks the asset list: your edited yamls are re-encoded from ``, everything else parses straight from the ROM, and `dialog_pack` strips the result down to the language assets plus `langinfo`. The finished pack lands in **`/mods/~lang/`** automatically, named from your `output.binary` - `bkes.o2r` in our case. Copy that into Lighthouse's `mods/~lang/` folder and it shows up in the options menu. --- @@ -256,15 +268,32 @@ You can still ship that content by declaring it as an **additive** asset - a slo On import, `dialog_pack` scans your `modding.yml` for any `lang//{dialog,quizq,gruntyq,sprite}/ASSET_` the base table didn't provide and folds it into the pack. Use the **canonical (v1.0) id** for the slot (`0x11CA` for the Motzand credit) no matter which region your base ROM is. -The `sprite` folder also covers **world-name banners** (one per world, at `0x1600`+). Provide them as RGBA32 intensity-mask sprites - the same format the JP cart uses - and the runtime tints each with its world's bold-font sphere colour, rendering titles as graphics instead of bold-font text. - This matters for the parade because Lighthouse keys the alternate (PAL/JP-style) parade on the *presence* of `0x11CA` in the active pack, not on the base version. A player on a plain US v1.0 `bk.o2r` who loads a pack that supplies `0x11CA` gets the Motzand parade order **and** the translated credit, while the rest of the game keeps using US assets. Cover `0x11CA` and the parade switches; omit it and the US parade is left untouched. +### World-name banners + +The `sprite` folder covers the pause-menu **world-name banners** - the pre-rendered titles the JP release draws on its totals pages instead of bold-font text. There are twelve, one per menu page, and a pack ships them as additive sprites at `0x1600 + page`: + +| Id | Page | Id | Page | +|---|---|---|---| +| `0x1600` | Totals overview | `0x1606` | Bubblegloop Swamp | +| `0x1601` | Spiral Mountain | `0x1607` | Freezeezy Peak | +| `0x1602` | Gruntilda's Lair | `0x1608` | Gobi's Valley | +| `0x1603` | Mumbo's Mountain | `0x1609` | Mad Monster Mansion | +| `0x1604` | Treasure Trove Cove | `0x160A` | Rusty Bucket Bay | +| `0x1605` | Clanker's Cavern | `0x160B` | Click Clock Wood | + +Each page is checked on its own: ship any subset, and a page without a banner keeps drawing its name as bold-font text. A `script: 0` pack can banner just the handful of names its repainted font can't spell and leave the rest to text. Declare each one like any other additive asset (the yaml under `sprite/`, plus its `modding.yml` line). + +The sprite itself is a single-frame **RGBA32 intensity mask** - the same format as the JP originals. Draw the title as white-on-transparent artwork, not pre-coloured text: at draw time the runtime refills the mask live with the world's swirling bold-font sphere texture (the highlighted current-world page gets its own sphere; other pages the default fill). The banner renders centered on the page header at its native size and is only scaled down if it's wider than ~92% of the screen, so any sensible resolution works. + +(A `script: 1` pack that reuses the JP cart's own banners keeps their native ids - `0xE2C`–`0xE37` re-point to the `0x1600` slots automatically. `0xE38` is not a banner; it's the default fill texture the masks are filled with.) + --- ## 7. HD fonts & textures (optional) -Everything above produces an **SD** pack - the only kind Torch builds. Players running an HD texture pack need high-resolution versions of whatever you replaced, and those are made with a different tool: [Retro](https://github.com/HarbourMasters/retro), HarbourMasters' OTR/O2R generation tool. The two pipelines are separate - Torch doesn't build HD assets, and Retro doesn't build the SD pack. +Everything above produces an **SD** pack. Players running an HD texture pack need high-resolution versions of whatever you replaced, and those are made with a different tool: [Retro](https://github.com/HarbourMasters/retro), HarbourMasters' OTR/O2R generation tool. The two tiers live at different paths inside the o2r, scoped by language: diff --git a/docs/poweredbylus.darkmode.png b/docs/poweredbylus.darkmode.png new file mode 100644 index 0000000000000000000000000000000000000000..2e2660814fdc04be71c078bd4e12800849de5394 GIT binary patch literal 213165 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 z

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 XE#MDywVZnl{iC6(rIPiB`OW_WIlKFS literal 0 HcmV?d00001 diff --git a/docs/poweredbylus.lightmode.png b/docs/poweredbylus.lightmode.png new file mode 100644 index 0000000000000000000000000000000000000000..740675417b594e406d85069d54574f1dceadd7b8 GIT binary patch literal 210989 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 PU&=nkg9`C~=wA9Cm#!~S literal 0 HcmV?d00001 diff --git a/include/actor.h b/include/actor.h index e786a2899..88e37cde7 100644 --- a/include/actor.h +++ b/include/actor.h @@ -5,6 +5,10 @@ struct actorMarker_s; +// [port] actor_new is the only allocator of ActorMarkers, one per actor, so the +// marker pool and the actor array have to be sized off the same number. +#define ACTOR_POOL_SIZE 0x200 + #define ACTOR_FLAG_NONE (0) #define ACTOR_FLAG_UNKNOWN_0 (1 << 0) // 0x1 #define ACTOR_FLAG_UNKNOWN_1 (1 << 1) // 0x2 diff --git a/include/bk_math.h b/include/bk_math.h index 53d2e4c3f..54928bb9a 100644 --- a/include/bk_math.h +++ b/include/bk_math.h @@ -18,6 +18,8 @@ out[2] = c;\ } +#define TUPLE_SET(dst, value) { dst[0] = dst[1] = dst[2] = value; } + #define TUPLE_COPY(dst, src) {\ dst[0] = src[0];\ dst[1] = src[1];\ diff --git a/include/bool.h b/include/bool.h index 51ec6ef6e..fbbfd6d75 100644 --- a/include/bool.h +++ b/include/bool.h @@ -3,8 +3,19 @@ #include +#ifndef __cplusplus #define NOT(boolean) ((boolean) ^ 1) #define BOOL(boolean) ((boolean) ? true : false) +#endif + +// Lighthouse [port] Decomp code uses TRUE/FALSE (typedef int bool upstream). +// Windows headers may also define these; values are identical. +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif #if 0 #include diff --git a/include/bs_funcs.h b/include/bs_funcs.h index 717d3099d..16c904417 100644 --- a/include/bs_funcs.h +++ b/include/bs_funcs.h @@ -1,6 +1,10 @@ #ifndef __BS_FUNCS__ #define __BS_FUNCS__ +#ifdef __cplusplus +extern "C" { +#endif + //interrupt void func_802B5350(void); void func_80296608(void); @@ -42,9 +46,9 @@ void bsturn_init(void); void bsturn_update(void); void bsturn_end(void); //0xd -void func_802B63F8(void); -void func_802B64D0(void); -void func_802B6500(void); +void timeout_transformation_init(void); +void timeout_transformation_update(void); +void timeout_transformation_end(void); //bsow void bsow_init(void); void bsow_update(void); @@ -86,9 +90,9 @@ void bsbtrot_exit_init(void); void bsbtrot_exit_update(void); void bsbtrot_exit_end(void); //bsfly_knockback -void func_802A4D90(void); -void func_802A4EC8(void); -void func_802A4F44(void); +void bsbfly_knockback_init(void); +void bsbfly_knockback_update(void); +void bsbfly_knockback_end(void); //BS_1A_WONDERWING_ENTER void bsbwhirl_enter_init(void); void bsbwhirl_enter_update(void); @@ -117,17 +121,17 @@ void bsegghead_end(void); void bseggass_init(void); void bseggass_update(void); void bseggass_end(void); -//BS_WALK_CREEP(void); +//BS_1F_WALK_CREEP(void); void bswalk_creep_init(void); void bswalk_creep_update(void); //BS_20_LANDING(void); void bsstand_landing_init(void); void bsstand_landing_update(void); -//BS_BSHOCK_CHARGE(void); +//BS_21_BSHOCK_CHARGE(void); void bsbshock_charge_init(void); void bsbshock_charge_update(void); void bsbshock_charge_end(void); -//BS_BSHOCK_JUMP(void); +//BS_22_BSHOCK_JUMP(void); void bsbshock_init(void); void bsbshock_update(void); void bsbshock_end(void); @@ -139,7 +143,7 @@ void func_802A505C(void); //BS_FLY(void); void bsbfly_init(void); void bsbfly_update(void); -void func_802A3F70(void); +void bsbfly_end(void); //BS_25_LONGLEG_ENTER(void); void bsblongleg_enter_init(void); void bsblongleg_enter_update(void); @@ -148,30 +152,30 @@ void bsblongleg_enter_end(void); void bsblongleg_stand_enter(void); void bsblongleg_stand_update(void); void bsblongleg_stand_end(void); -//BS_LONGLEG_WALK(void); +//BS_27_LONGLEG_WALK(void); void bsblongleg_walk_init(void); void bsblongleg_walk_update(void); void bsblongleg_walk_end(void); -//BS_LONGLEG_JUMP(void); +//BS_28_LONGLEG_JUMP(void); void bsblongleg_jump_init(void); void bsblongleg_jump_update(void); void bsblongleg_jump_end(void); -//BS_LONGLEG_EXIT(void); +//BS_29_LONGLEG_EXIT(void); void bsblongleg_exit_init(void); void bsblongleg_exit_update(void); void bsblongleg_exit_end(void); -//BS_BOMB(void); -void func_802A3F9C(void); -void func_802A411C(void); -void func_802A4404(void); +//BS_2A_BOMB(void); +void bsbfly_bomb_init(void); +void bsbfly_bomb_update(void); +void bsbfly_bomb_end(void); //BS_2B_DIVE_IDLE(void); -void func_802A762C(void); -void func_802A7674(void); -void func_802A7718(void); +void bsbdive_idle_init(void); +void bsbdive_idle_update(void); +void bsbdive_idle_end(void); //BS_2C_DIVE_B(void); -void func_802A7738(void); -void func_802A7838(void); -void func_802A7A2C(void); +void bsbdiveb_init(void); +void bsbdiveb_update(void); +void bsbdiveb_end(void); //BS_2D_SWIM_IDLE, void bsswim_idle_init(void); void bsswim_idle_update(void); @@ -186,21 +190,21 @@ void bsjump_fall_update(void); void bsjump_fall_end(void); //BS_30_DIVE_ENTER void bsSwim_dive_init(void); -void func_802A7E2C(void); -void func_802A7F4C(void); -//BS_ROLL(void); +void bsSwim_dive_update(void); +void bsSwim_dive_end(void); +//BS_31_ROLL(void); int bstwirl_hitboxActive(void); void bstwirl_init(void); void bstwirl_update(void); void bstwirl_end(void); -//BS_SLIDE +//BS_32_SLIDE void bsslide_init(void); void bsslide_update(void); void bsslide_end(void); //0x33(void); -void func_802B9ACC(void); -void func_802B9B14(void); -void func_802B9AAC(void); +void bswashy_init(void); +void bswashy_update(void); +void bswashy_end(void); void func_802B9D00(void); //BS_34_JIG_NOTEDOOR(void); void bsjig_notedoor_init(void); @@ -210,18 +214,18 @@ void bsjig_notedoor_end(void); void bsant_idle_init(void); void bsant_idle_update(void); void bsant_idle_end(void); -//BS_ANT_WALK +//BS_36_ANT_WALK void bsant_walk_init(void); void bsant_walk_update(void); void bsant_walk_end(void); -//BS_ANT_JUMP +//BS_37_ANT_WALK void bsant_jump_init(void); void bsant_jump_update(void); void bsant_jump_end(void); //BS_39_DIVE_A -void func_802A7A54(void); -void func_802A7AB0(void); -void func_802A7BA8(void); +void bsswim_divea_init(void); +void bsswim_divea_update(void); +void bsswim_divea_end(void); //BS_3A_CARRY_IDLE(void); void bscarry_idle_init(void); void bscarry_idle_update(void); @@ -253,17 +257,17 @@ void func_802B1BF4(void); void func_802B1CF8(void); void func_802B1DA4(void); //0x40 -void func_802B2BF0(void); -void func_802B2C58(void); -void func_802B2D50(void); +void bspumpkin_flush_init(void); +void bspumpkin_flush_update(void); +void bspumpkin_flush_end(void); //BS_41_DIE void bsdie_init(void); void bsdie_update(void); void bsdie_end(void); //BS_42_DINGPOT -void func_802A5120(void); -void func_802A5190(void); -void func_802A51C0(void); +void bsfly_dingpotLaunch_init(void); +void bsfly_dingpotLaunch_update(void); +void bsfly_dingpotLaunch_end(void); //BS_43_ANT_DIE void bsant_die_init(void); void bsant_die_update(void); @@ -298,9 +302,9 @@ void bspumpkin_fall_init(void); void bspumpkin_fall_update(void); void bspumpkin_fall_end(void); //BS_4C_LANDING_IN_WATER -void func_802A846C(void); -void func_802A85EC(void); -void func_802A872C(void); +void bsbswim_landingInWater_init(void); +void bsbswim_landingInWater_update(void); +void bsbswim_landingInWater_end(void); //BS_4D_PUMPKIN_OW void __bspumpkin_ow_init(void); void __bspumpkin_ow_update(void); @@ -319,18 +323,18 @@ void bsclimb_move_init(void); void bsclimb_move_update(void); void bsclimb_move_end(void); //BS_51_CLIMB_EXIT -void func_802B1928(void); -void func_802B1A54(void); -void func_802B1BCC(void); +void bsjump_climbExit_init(void); +void bsjump_climbExit_update(void); +void bsjump_climbExit_end(void); //0x52 -void func_802B5FD0(void); -void func_802B6064(void); -void func_802B60D0(void); +void bssurf_init(void); +void bssurf_update(void); +void bssurf_end(void); void func_802B60D8(void); //0x53 -void func_802B6270(void); -void func_802B6314(void); -void func_802B63C8(void); +void timeout_banjo_init(void); +void timeout_banjo_update(void); +void timeout_banjo_end(void); //0x55 void bsblongleg_slide_init(void); @@ -338,14 +342,14 @@ void bsblongleg_slide_update(void); void bsblongleg_slide_end(void); //0x56 -void func_802B3868(void); -void func_802B3954(void); -void func_802B3A20(void); +void rebound_init(void); +void rebound_update(void); +void rebound_end(void); //0x57 -void func_802A4430(void); -void func_802A4548(void); -void func_802A4664(void); +void bsbfly_beakbombend_init(void); +void bsbfly_beakbombend_update(void); +void bsbfly_beakbombend_end(void); void func_802A505C(void); //0x58 void bsbfly_beakbomb_crash_init(void); @@ -358,9 +362,9 @@ void func_802A4CF0(void); void func_802A4D10(void); void func_802A505C(void); //0x54 -void func_802A7F6C(void); -void func_802A8098(void); -void func_802A82D4(void); +void bsbswim_die_init(void); +void bsbswim_die_update(void); +void bsbswim_die_end(void); //0x5B void bsthrow_init(void); @@ -388,9 +392,9 @@ void bscroc_fall_update(void); void bscroc_fall_end(void); //0x62 -void func_802A6394(void); -void func_802A63F0(void); -void func_802A6450(void); +void bsblongleg_locked_init(void); +void bsblongleg_locked_update(void); +void bsblongleg_locked_end(void); //0x63 void bscroc_ow_init(void); void bscroc_ow_update(void); @@ -422,9 +426,9 @@ void bswalrus_fall_update(void); void bswalrus_fall_end(void); //0x6B -void func_802A1F6C(void); -void func_802A1FC8(void); -void func_802A2014(void); +void bsbee_locked_init(void); +void bsbee_locked_update(void); +void bsbee_locked_end(void); //0x0000006C void bswalrus_ow_init(void); void bswalrus_ow_update(void); @@ -460,23 +464,23 @@ void bssplat_update(void); void bssplat_end(void); //0x00000073 -void func_802B3CEC(void); -void func_802B3D1C(void); -void func_802B3D6C(void); +void bsrest_bs73unknown_init(void); +void bsrest_bs73unknown_update(void); +void bsrest_bs73unknown_end(void); //0x00000074 -void func_802B3E2C(void); -void func_802B3E64(void); -void func_802B3EF4(void); +void bsrest_bs74unknown_init(void); +void bsrest_bs74unknown_update(void); +void bsrest_bs74unknown_end(void); //0x00000075 -void func_802B3D8C(void); -void func_802B3DBC(void); -void func_802B3E0C(void); +void bsrest_bs75unknown_init(void); +void bsrest_bs75unknown_update(void); +void bsrest_bs75unknown_end(void); //0x00000076 -void func_802A4F74(void); -void func_802A4FC8(void); -void func_802A503C(void); +void bsbfly_locked_init(void); +void bsbfly_locked_update(void); +void bsbfly_locked_end(void); //0x00000077 void bsswim_lookat_init(void); @@ -489,9 +493,9 @@ void bsbswim_lookat_update(void); void bsbswim_lookat_end(void); //0x00000079 -void bsbtrot_unk79_init(void); -void bsbtrot_unk79_update(void); -void bsbtrot_unk79_end(void); +void bsbtrot_locked_init(void); +void bsbtrot_locked_update(void); +void bsbtrot_locked_end(void); //0x0000007A void bswalk_mud_init(void); @@ -517,59 +521,59 @@ void bswalrus_sled_jump_update(void); void bswalrus_sled_jump_end(void); void func_802B98C0(void); //0x0000007F -void func_802A7BD0(void); -void func_802A7CA8(void); -void func_802A7D74(void); +void bsbswim_ow_init(void); +void bsbswim_ow_update(void); +void bsbswim_ow_end(void); //0x00000080 void bswalrus_timeout_init(void); -void func_802B9830(void); -void func_802B9880(void); +void bswalrus_timeout_update(void); +void bswalrus_timeout_end(void); //0x00000081 -void func_802B90D0(void); -void func_802B9130(void); -void func_802B917C(void); +void bswalrus_sledlocked_init(void); +void bswalrus_sledlocked_update(void); +void bswalrus_sledlocked_end(void); void func_802B98C0(void); //0x00000082 -void func_802B95A0(void); -void func_802B963C(void); -void func_802B976C(void); +void bswalrus_sledloseinair_init(void); +void bswalrus_sledloseinair_update(void); +void bswalrus_sledloseinair_end(void); void func_802B98C0(void); //0x00000085 -void func_802A1080(void); -void func_802A10D4(void); -void func_802A117C(void); +void bsbeemain_idle_init(void); +void bsbeemain_idle_update(void); +void bsbeemain_idle_end(void); //0x00000086 -void func_802A11A4(void); -void func_802A1214(void); -void func_802A12D4(void); +void bsbeemain_walk_init(void); +void bsbeemain_walk_update(void); +void bsbeemain_walk_end(void); //0x00000087 -void func_802A12FC(void); -void func_802A1438(void); -void func_802A163C(void); +void bsbeemain_jump_init(void); +void bsbeemain_jump_update(void); +void bsbeemain_jump_end(void); //0x00000088 -void func_802A1664(void); -void func_802A170C(void); -void func_802A18C8(void); +void bsbeemain_fall_init(void); +void bsbeemain_fall_update(void); +void bsbeemain_fall_end(void); //0x00000089 -void func_802A1B68(void); -void func_802A1B88(void); -void func_802A1BA8(void); +void bsbeemain_ow_init(void); +void bsbeemain_ow_update(void); +void bsbeemain_ow_end(void); //0x0000008A void bsbeemain_die_init(void); -void func_802A1DD8(void); -void func_802A1F2C(void); +void bsbeemain_die_update(void); +void bsbeemain_die_end(void); //0x0000008B -void func_802A0590(void); -void func_802A0630(void); -void func_802A0704(void); +void bsbeefly_bs8Bunknown_init(void); +void bsbeefly_bs8Bunknown_update(void); +void bsbeefly_bs8Bunknown_end(void); //0x0000008C void bsbeefly_enter(void); @@ -582,19 +586,19 @@ void bscroc_locked_update(void); void bscroc_locked_end(void); //0x0000008E -void func_8029F398(void); -void func_8029F3F4(void); -void func_8029F440(void); +void bsant_locked_init(void); +void bsant_locked_update(void); +void bsant_locked_end(void); //0x0000008F -void func_802B34A0(void); -void func_802B34F8(void); -void func_802B353C(void); +void bspumpkin_locked_init(void); +void bspumpkin_locked_update(void); +void bspumpkin_locked_end(void); //0x00000091 -void func_802A4D30(void); -void func_802A4D50(void); -void func_802A4D70(void); +void bsbfly_ow_init(void); +void bsbfly_ow_update(void); +void bsbfly_ow_end(void); void func_802A505C(void); //0x00000092 void bsant_drone_init(void); @@ -632,9 +636,9 @@ void bswalk_drone_update(void); void bswalk_drone_end(void); void bsdrone_interrupt(void); //0x00000099 -void func_802A50B0(void); -void func_802A50D8(void); -void func_802A50F8(void); +void bsbfly_drone_init(void); +void bsbfly_drone_update(void); +void bsbfly_drone_end(void); void bsdrone_interrupt(void); //0x0000009A void bsbtrot_drone_init(void); @@ -657,9 +661,9 @@ void bsbee_drone_update(void); void bsbee_drone_end(void); void bsdrone_interrupt(void); //0x0000009E -void func_802ABCCC(void); -void func_802ABD0C(void); -void func_802ABD40(void); +void bsclimb_locked_init(void); +void bsclimb_locked_update(void); +void bsclimb_locked_end(void); void func_802ABD60(void); //0x0000009F void bsant_bounce_init(void); @@ -682,9 +686,9 @@ void bswalrus_bounce_update(void); void bswalrus_bounce_end(void); //0x000000A3 -void func_802A1BC8(void); -void func_802A1BE8(void); -void func_802A1C08(void); +void bsbeemain_bounce_init(void); +void bsbeemain_bounce_update(void); +void bsbeemain_bounce_end(void); //0x000000A4 void bsbwhirl_drone_init(void); @@ -692,9 +696,9 @@ void bsbwhirl_drone_update(void); void bsbwhirl_drone_end(void); //0x000000A5 -void func_802AADBC(void); -void func_802AAE08(void); -void func_802AAE4C(void); +void bsbwhirl_bsA5unknown_init(void); +void bsbwhirl_bsA5unknown_update(void); +void bsbwhirl_bsA5unknown_end(void); void bsDroneGoTo_init(void); void bsDroneGoTo_update(void); @@ -712,4 +716,8 @@ void bsDroneEnter_end(void); void bsDroneVanish_init(void); void bsDroneVanish_update(void); void bsDroneVanish_end(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/checksums.h b/include/checksums.h new file mode 100644 index 000000000..403428120 --- /dev/null +++ b/include/checksums.h @@ -0,0 +1,115 @@ +#ifndef BANJO_KAZOOIE_CHECKSUMS_H +#define BANJO_KAZOOIE_CHECKSUMS_H + +#include + +/* The checksums for the boot and core1 segments are stored right after the boot segment in ROM + */ + +#define CRC_BOOT_TEXT_CHECKSUM1 0 +#define CRC_BOOT_TEXT_CHECKSUM2 4 +#define CRC_CORE1_TEXT_CHECKSUM1 8 +#define CRC_CORE1_TEXT_CHECKSUM2 12 +#define CRC_CORE1_DATA_CHECKSUM1 16 +#define CRC_CORE1_DATA_CHECKSUM2 20 + +extern u8 crc_ROM_START[]; + +/* Each overlay bss section contains four checksum values, calculated from the rarezip decompressor. + * These values are written by the overlay loader. They are checked with pre-calculated values for + * different anti-tampering measurements. + * The exception is the core1 overlay, which checksums are written to a special place. + */ +struct overlay_checksums_s { + s32 text_checksum1; + s32 text_checksum2; + s32 data_checksum1; + s32 data_checksum2; +}; + +extern struct overlay_checksums_s gChecksumsCore1; +extern struct overlay_checksums_s gChecksumsCore2; +extern struct overlay_checksums_s gChecksumsCC; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsGV; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsMMM; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsTTC; +extern struct overlay_checksums_s gChecksumsMM; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsBGS; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsRBB; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsFP; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsSM; +extern struct overlay_checksums_s gChecksumsCutscenes; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsLair; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsFight; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsCCW; // (unused) no anti tampering measurements +extern struct overlay_checksums_s gChecksumsEmptyLvl; // (unused) no anti tampering measurements + +/* The pre-calculated checksums are located in random places. + * + * The calculation process should be as following (needs to be confirmed!!): + * 1. At compile time all checksum variables (listed below) are set to zero + * 2. The text checksums for all overlays (except core1) are calculated and written. + * 3. The data checksums are calculated in two passes: + * 3-1. Data checksum 1 is calculated and written for each overlay (except core1). + * 3-2. Data checksum 2 is calculated and written for each overlay (except core1). + * 4. The boot and core1 checksums are calculated and written to the CRC section. + * + * Notes: + * - Checksums 1 sums up every byte + * - Checksum 2 XORes every byte after it is shifted right by "current checksum 1 AND 0x17" + * (This means checksum 2 must be calculated together with checksum 1) + * (Step 3-1 discards checksum 2 and step 3-2 discards checksum 1) + * - Checksums without a correspondending variable are just discarded. + */ + +extern s32 D_803727F4; // core2 text checksum 2 (location: core2) +extern s32 D_80276574; // core2 data checksum 2 (location: core1) + +extern s32 D_80389BE0; // CC text checksum 1 (location: CC) +extern s32 D_80389BE4; // CC text checksum 2 (location: CC) +extern s32 D_80389BE8; // CC data checksum 1 (location: CC) +extern s32 D_80276570; // CC data checksum 2 (location: core1) + +extern s32 D_80390F30; // GV text checksum 1 (location: GV) +extern s32 D_80390F34; // GV text checksum 2 (location: GV) +extern s32 D_80390F38; // GV data checksum 1 (location: GV) +extern s32 D_80275904; // GV data checksum 2 (location: core1) + +extern s32 D_8038C300; // MMM text checksum 1 (location: MMM) +extern s32 D_8038C304; // MMM text checksum 2 (location: MMM) +extern s32 D_8038C308; // MMM data checksum 1 (location: MMM) +extern s32 D_80275854; // MMM data checksum 2 (location: core1) + +extern s32 D_8038C750; // TTC text checksum 1 (location: TTC) +extern s32 D_8038C754; // TTC text checksum 2 (location: TTC) +extern s32 D_8038C758; // TTC data checksum 1 (location: TTC) +extern s32 D_80276CB0; // TTC data checksum 2 (location: core1) + +extern s32 D_803899C0; // MM text checksum 1 (location: MM) +extern s32 D_803899C4; // MM text checksum 2 (location: MM) +extern s32 D_803899C8; // MM data checksum 1 (location: MM) +extern s32 D_80275654; // MM data checksum 2 (location: core1) + +extern s32 D_80390B20; // BGS text checksum 1 (location: BGS) +extern s32 D_80390B24; // BGS text checksum 2 (location: BGS) +extern s32 D_80390B28; // BGS data checksum 1 (location: BGS) +extern s32 D_802758F0; // BGS data checksum 2 (location: core1) + +extern s32 D_80276CB4; // RBB data checksum 2 (location: core1) + +extern s32 D_802758F4; // FP data checksum 2 (location: core1) + +extern s32 D_8038AAE0; // SM text checksum 1 (location: SM) +extern s32 D_8038AAE4; // SM text checksum 2 (location: SM) +extern s32 D_8038AAE8; // SM data checksum 1 (location: SM) +extern s32 D_80275650; // SM data checksum 2 (location: core1) + +extern s32 D_80275850; // Cutscenes data checksum 2 (location: core1) + +extern s32 D_80275900; // Lair data checksum 2 (location: core1) + +extern s32 D_80275D34; // Fight data checksum 2 (location: core1) + +extern s32 D_80275D30; // CCW data checksum 2 (location: core1) + +#endif diff --git a/include/core1/core1.h b/include/core1/core1.h index f63707888..bf301700d 100644 --- a/include/core1/core1.h +++ b/include/core1/core1.h @@ -2,6 +2,7 @@ #define BANJO_KAZOOIE_CORE1_CORE1_H #include +#include // [port] for ALSeqpConfig/ALHeap in audioManager decls (decomp gets this via SDK ultra64.h) #include "bool.h" #include "enums.h" #include "structs.h" @@ -23,6 +24,10 @@ #include "core1/viewport.h" #include "core1/vimgr.h" +#ifdef __cplusplus +extern "C" { +#endif + /* need to sort out in individual header files */ void* malloc(size_t size); @@ -38,10 +43,20 @@ void func_8025ABB8(enum comusic_e comusic_id, s32 arg1, s32 arg2, s32 arg3); int func_8025AD7C(enum comusic_e arg0); int func_8025ADBC(enum comusic_e arg0); -OSMesgQueue * audioManager_getFrameMesgQueue(void); void piMgr_read(void *vaddr, s32 devaddr, s32 size); +/* src/core1/code_1D00.c */ + +void audioManager_setupSeqp(ALSeqpConfig *config); +void audioManager_init(void); +ALHeap *audioManager_getALHeapInfo(void); +OSMesgQueue *audioManager_getDMANotifyMesgQueue(void); +OSIoMesg *audioManager_getExtraDMAMesg(void); +OSMesgQueue *audioManager_getFrameMesgQueue(void); +OSMesgQueue *audioManager_getReplyMesgQueue(void); + + /* src/core1/overlay.c */ void overlay_load( @@ -123,17 +138,17 @@ void core1_ce60_func_8024BD40(s32 arg0, s32 arg1); /* src/core1/depthbuffer.c */ -extern u8 D_8000E800; +extern u8 D_8000E800[]; -void func_80253190(Gfx **gfx); -void func_80253208(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer); -int func_80253400(void); -bool depthBuffer_isPointerSet(void); -void depthBuffer_stub(void); -void func_80253428(int arg0); -void func_802534A8(int arg0); -void zBuffer_set(Gfx **gfx); -void *zBuffer_get(void); +void depthbuffer_clear(Gfx **gfx); +void depthbuffer_clearRegion(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer); +bool depthbuffer_getUnk4(void); +bool depthbuffer_isDataPtrSet(void); +void depthbuffer_stub(void); +void depthbuffer_enable(bool enable); +void depthbuffer_setUnk4(bool value); +void depthbuffer_set(Gfx **gfx); +void *depthbuffer_getDataPtr(void); @@ -149,8 +164,8 @@ struct ucode_task_data_s { s32 unk4; // is only set for gfx tasks (0 or 0x40000000) void *data_ptr; // begin of dlist data (was u64* upstream; void* here for port-side casts) void *data_ptr_end; // end of dlist data - OSMesgQueue *unk10; // only relevant for audio tasks - s32 unk14; // only relevant for audio tasks + OSMesgQueue *audio_mesg_queue; // only relevant for audio tasks + OSMesg audio_mesg; // only relevant for audio tasks }; #define DEFAULT_FRAMEBUFFER_WIDTH 292 @@ -162,10 +177,10 @@ extern u16 gFramebuffers[2][DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIG void core1_15B30_requestLockForTaskDataID(void); void core1_15B30_requestReleaseForTaskDataID(void); -void core1_15B30_addAudioTaskData(Gfx **start, Gfx **end, void *mesg_queue, void *msg); -void func_80253640(Gfx ** gdl, void *arg1); -void scissorBox_SetForGameMode(Gfx **gdl, s32 framebuffer_idx); -void setupScissorBoxAndFramebuffer(Gfx **gfx, uintptr_t framebuffer_address); +void core1_15B30_addAudioTaskData(Acmd *start, Acmd *end, OSMesgQueue *mesg_queue, OSMesg msg); +void setupFramebuffer(Gfx **gfx, void *color_buffer); +void setupFramebufferForGamemode(Gfx **gfx, s32 framebuffer_idx); +void setupScissorBoxAndFramebuffer(Gfx **gfx, void *color_buffer); void setupDefaultScissorBoxAndFramebuffer(Gfx **gfx, s32 framebuffer_idx); void core1_15B30_finishDList_renderThread(Gfx **gfx); void core1_15B30_finishDList(Gfx **gfx); @@ -186,8 +201,8 @@ void graphicsCache_checkFrame(Gfx *gfxStart, Gfx *gfxEnd, Mtx *mtxStart, Mtx *mt void scissorBox_set(s32 left, s32 top, s32 right, s32 bottom); void scissorBox_setDefault(void); void core1_15B30_addTask7TaskData(s32 framebuffer_id); -void toggleTextureFilterPoint(void); -void getGraphicsStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx); +void core1_15B30_toggleTexturePointFilter(void); +void graphicscache_swapAndGetStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx); void dummy_func_80254464(void); /* src/core1/defragmanager.c */ @@ -200,5 +215,11 @@ void dummy_func_80254464(void); void defragManager_init(void); void defragManager_free(void); void defragManager_setPriority(OSPri pri); +void defragManager_resume(void); +void defragManager_pause(void); + +#ifdef __cplusplus +} +#endif #endif diff --git a/include/core1/main.h b/include/core1/main.h index 4774cb689..534adeaa0 100644 --- a/include/core1/main.h +++ b/include/core1/main.h @@ -3,11 +3,15 @@ #include #include "enums.h" +#ifdef __cplusplus +extern "C" { +#endif + void core1_main(s32 arg0); void func_8023DA74(void); void func_8023DA9C(s32 arg0); -u32 globalTimer_getTimeMasked(u32 mask); -//s32 globalTimer_getTime(void); +s32 globalTimer_getTimeMasked(s32 mask); +s32 globalTimer_getTime(void); void globalTimer_reset(void); enum map_e getSpecialBootMap(void); enum map_e getDefaultBootMap(void); @@ -25,4 +29,8 @@ void mainThread_create(void); OSThread *mainThread_get(void); void disableInput_set(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core1/ml.h b/include/core1/ml.h index 8968621c8..04ef38101 100644 --- a/include/core1/ml.h +++ b/include/core1/ml.h @@ -14,7 +14,7 @@ void ml_vec3f_cross_product(f32 dst[3], f32 vec1[3], f32 vec2[3]); void ml_vec3f_interpolate_fast(f32 dst[3], f32 start[3], f32 end[3], f32 t); f32 ml_vec3f_dot_product(f32 vec1[3], f32 vec2[3]); f32 ml_vec3f_distance(f32 vec1[3], f32 vec2[3]); -f32 ml_func_802560D0(f32 arg0[3], f32 arg1[3], f32 arg2[3]); +f32 ml_vec3f_distance_to_point(f32 arg0[3], f32 arg1[3], f32 arg2[3]); f32 ml_distanceSquared_vec3f(f32 vec1[3], f32 vec2[3]); void func_802562DC(f32 vec1[3], f32 vec2[3], f32 vec3[3]); f32 ml_vec3f_length_unused(f32 vec[3]); @@ -23,7 +23,7 @@ void ml_vec3f_normalize(f32 vec[3]); void ml_vec2f_normalize(f32 vec[2]); void ml_3f_normalize(f32 *x, f32 *y, f32 *z); void ml_vec3f_set_length_copy(f32 dst[3], f32 src[3], f32 len); -void func_80256664(f32 ptr[3]); +void ml_vec3f_clamp_deg360(f32 ptr[3]); void func_80256740(f32 vec[3]); void ml_vec3f_pitch_rotate_copy(f32 dst[3], f32 src[3], f32 pitch); void ml_vec3f_yaw_rotate_copy(f32 dst[3], f32 src[3], f32 yaw); @@ -39,7 +39,7 @@ f32 ml_acosf(f32 x); f32 func_8025715C(f32 val1, f32 val2); f32 func_80257204(f32 val1, f32 val2, f32 val3, f32 val4); f32 func_80257248(f32 vec1[3], f32 vec2[3]); -void func_8025727C(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2); +void ml_horizontal_and_vertical_angles(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2); void ml_init(void); void ml_free(void); f32 func_802575BC(f32 val); @@ -110,7 +110,7 @@ void ml_translate_y_local(f32 position[3], f32 rotation[3], f32 dy); void ml_translate_z_local(f32 dst[3], f32 src[3], f32 dz); void ml_translate_x_local(f32 dst[3], f32 src[3], f32 dx); void func_8025901C(f32 arg0, f32 arg1[3], f32 arg2[3], f32 arg3); -f32 func_80259198(f32 arg0, f32 arg1); +f32 ml_clamp_abs_f(f32 arg0, f32 arg1); f32 mlDiffDegF(f32 arg0, f32 arg1); bool ml_vec3f_point_within_horizontal_distance(f32 vec[3], f32 x, f32 z, f32 distance); bool ml_vec3f_within_horizontal_distance(f32 vec1[3], f32 vec2[3], f32 distance); @@ -118,7 +118,7 @@ bool ml_vec3w_within_horizontal_distance(s32 vec1[3], s32 vec2[3], s32 distance) bool ml_vec3f_within_distance(f32 vec1[3], f32 vec2[3], f32 distance); bool ml_stub_80259400(f32 x); void ml_sub_delta_time(f32 *x); -void func_8025947C(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); +void ml_project_point_onto_vecf3(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); f32 func_80259554(f32 dst[3], f32 vec1[3], f32 vec2[3], f32 vec3[3]); void func_802596AC(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); s32 ml_getViewportYawWithOffset(f32 x); diff --git a/include/core1/sns.h b/include/core1/sns.h index 11301e48f..321bb9d95 100644 --- a/include/core1/sns.h +++ b/include/core1/sns.h @@ -1,6 +1,10 @@ #ifndef BANJO_KAZOOIE_CORE1_SNS_H #define BANJO_KAZOOIE_CORE1_SNS_H +#ifdef __cplusplus +extern "C" { +#endif + /** * sns sets */ @@ -133,4 +137,8 @@ void sns_stub (void); void snspayload_append_key_to_outgoing_payload (struct SnsPayload *payload, s32 key); void snspayload_calc_checksum (struct SnsPayload *payload); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core1/sprite.h b/include/core1/sprite.h index d78f57896..1ae8be8a6 100644 --- a/include/core1/sprite.h +++ b/include/core1/sprite.h @@ -1,6 +1,10 @@ #ifndef BANJO_KAZOOIE_CORE1_SPRITE_H #define BANJO_KAZOOIE_CORE1_SPRITE_H +#ifdef __cplusplus +extern "C" { +#endif + u32 sprite_getUnk8(BKSprite *self); u32 sprite_getUnkA(BKSprite *self); u32 sprite_getUnk6(BKSprite *self); @@ -8,4 +12,8 @@ u32 sprite_getUnk4(BKSprite *self); s32 sprite_getFrameCount(BKSprite *self); BKSpriteFrame *sprite_getFramePtr(BKSprite *self, u32 frame_id); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core1/viewport.h b/include/core1/viewport.h index 64e6daf61..1a5bafaa8 100644 --- a/include/core1/viewport.h +++ b/include/core1/viewport.h @@ -1,9 +1,13 @@ #ifndef BANJO_KAZOOIE_CORE1_VIEWPORT_H #define BANJO_KAZOOIE_CORE1_VIEWPORT_H +#ifdef __cplusplus +extern "C" { +#endif + void viewport_moveAlongZAxis(f32 offset); f32 viewport_getDistance(f32 arg0[3]); -void viewport_getLookbk_vector(f32 arg0[3]); +void viewport_getLookVector(f32 arg0[3]); void viewport_getPosition_vec3f(f32 arg0[3]); void viewport_getPosition_vec3w(s32 dst[3]); void viewport_getPosition_vec3s(s16 dst[3]); @@ -50,4 +54,8 @@ void viewport_backupState(void); void viewport_restoreState(void); void viewport_adjustPointDistance(f32 pos[3], f32 distance); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/ba/carry.h b/include/core2/ba/carry.h index 5c74db27c..af50dfa28 100644 --- a/include/core2/ba/carry.h +++ b/include/core2/ba/carry.h @@ -9,7 +9,7 @@ void bacarry_end(void); void bacarry_update(void); void bacarry_reset_marker(void); -ActorMarker *bacarry_get_marker(void); +ActorMarker *bacarry_getMarker(void); void bacarry_set_marker(ActorMarker *arg0); void bacarry_set_offsets(f32 height, f32 rotation); diff --git a/include/core2/ba/model.h b/include/core2/ba/model.h index 47324d8c4..2a22a4c20 100644 --- a/include/core2/ba/model.h +++ b/include/core2/ba/model.h @@ -1,6 +1,10 @@ #ifndef _PLAYER_MODEL_H_ #define _PLAYER_MODEL_H_ +#ifdef __cplusplus +extern "C" { +#endif + typedef enum player_model_direction_e { PLAYER_MODEL_DIR_NONE = 0, PLAYER_MODEL_DIR_BANJO = 1, @@ -15,4 +19,8 @@ void baModel_setYDisplacement(f32); void baModel_8029217C(f32); void baModel_setVisible(s32 arg0); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/ba/physics.h b/include/core2/ba/physics.h index e2d49e0c7..c29a820a9 100644 --- a/include/core2/ba/physics.h +++ b/include/core2/ba/physics.h @@ -3,6 +3,11 @@ #include #include "libultraship/libultra/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + typedef enum ba_physics_type_e{ BA_PHYSICS_NONE, BA_PHYSICS_UNK1, @@ -50,4 +55,9 @@ void baphysics_set_gravity(f32); void baphysics_set_terminal_velocity(f32); int baphysics_is_slower_than(f32); int baphysics_goto_done(void); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/ba/timer.h b/include/core2/ba/timer.h index 186cf9ab0..95d191aca 100644 --- a/include/core2/ba/timer.h +++ b/include/core2/ba/timer.h @@ -4,7 +4,7 @@ #include void batimer_incrementBy(s32 id, f32 inc_value_sec); -int batimer_decrement(s32 id); +bool batimer_decrement(s32 id); void batimer_increment(s32 id); f32 batimer_get(s32 id); int batimer_isAt(s32 id, f32 value_sec); diff --git a/include/core2/bonetransform.h b/include/core2/bonetransform.h index dfd76f140..80be38b91 100644 --- a/include/core2/bonetransform.h +++ b/include/core2/bonetransform.h @@ -2,6 +2,10 @@ #define _BONE_TRANSFORMATION_H_ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { f32 unk0[4]; f32 scale[3]; @@ -16,4 +20,8 @@ typedef struct bone_transform_list_s{ BoneTransformList *boneTransformList_new(void); BoneTransformList *boneTransformList_defrag(BoneTransformList *self); void boneTransformList_free(BoneTransformList *self); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/commonParticle.h b/include/core2/commonParticle.h index bf6ded7a8..2283965b3 100644 --- a/include/core2/commonParticle.h +++ b/include/core2/commonParticle.h @@ -7,6 +7,10 @@ #include "prop.h" #include "core2/anim/sprite.h" +#ifdef __cplusplus +extern "C" { +#endif + #define PARTICLE_LIMIT 40 #ifndef FUNCUNK40_DEFINED @@ -76,4 +80,8 @@ void func_80344E3C(u8, f32[3]); void func_80344D94(u8, f32[3]); void func_80344EE4(u8, f32, f32); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/modelRender.h b/include/core2/modelRender.h index 2da2e1174..2b955bd7f 100644 --- a/include/core2/modelRender.h +++ b/include/core2/modelRender.h @@ -41,7 +41,7 @@ void modelRender_setEnvColor(s32 r, s32 g, s32 b, s32 a); void modelRender_setAlpha(s32 a); void modelRender_func_8033A444(AnimMtxList *arg0); void modelRender_setRefPoints(Vec3fArray *ref_points); -void func_8033A45C(s32 arg0, s32 arg1); +void modelRender_setAppendageVisibility(s32 arg0, s32 arg1); void modelRender_func_8033A470(s32 arg0, s32 arg1); void modelRender_setTextureList(BKTextureList *texture_list); void modelRender_setAnimatedTexturesCacheId(s32 arg0); diff --git a/include/core2/particle.h b/include/core2/particle.h index 8ad811a4a..28487e577 100644 --- a/include/core2/particle.h +++ b/include/core2/particle.h @@ -3,6 +3,10 @@ #include "structs.h" +#ifdef __cplusplus +extern "C" { +#endif + #define PART_EMIT_NO_OPA 0x20 #define PART_EMIT_NO_DEPTH 0x10 #define PART_EMIT_NO_LOOP 0x8 @@ -24,4 +28,8 @@ void func_802EFF9C(ParticleEmitter *self, f32); void partEmitMgr_freeEmitter(ParticleEmitter *self); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/statetimer.h b/include/core2/statetimer.h index 0d15969f0..3863783e8 100644 --- a/include/core2/statetimer.h +++ b/include/core2/statetimer.h @@ -4,6 +4,10 @@ #include #include "structs.h" +#ifdef __cplusplus +extern "C" { +#endif + enum state_timer_e{ STATE_TIMER_0_UNKNOWN, STATE_TIMER_1_THROW = 1, @@ -24,4 +28,8 @@ void stateTimer_init(void); void stateTimer_clear(enum state_timer_e timer_id); void stateTimer_set(enum state_timer_e timer_id, f32 value); void stateTimer_update(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/core2/timedfunc.h b/include/core2/timedfunc.h index 2892d462e..1c3007b4f 100644 --- a/include/core2/timedfunc.h +++ b/include/core2/timedfunc.h @@ -4,7 +4,9 @@ #include "generic.h" +#ifndef __cplusplus #define reinterpret_cast(type, var) (*((type *)&var)) +#endif void timedFunc_set_0(f32 time, GenFunction_0 funcPtr); diff --git a/include/enums.h b/include/enums.h index 90de73ab1..4e573581e 100644 --- a/include/enums.h +++ b/include/enums.h @@ -449,7 +449,7 @@ enum level_flags_e LEVEL_FLAG_23_RBB_OPEN, LEVEL_FLAG_24_CCW_OPEN, - LEVEL_FLAG_25_CCW_UNKNOWN, + LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, LEVEL_FLAG_26_FP_WALRUS_JIGGY_DROPPED, LEVEL_FLAG_27_RBB_UNKNOWN, LEVEL_FLAG_28_RBB_UNKNOWN, @@ -632,7 +632,7 @@ typedef enum map_e MAP_5A_CCW_SUMMER_ZUBBA_HIVE = 0x5A, // Summer & Spring are swapped here MAP_5B_CCW_SPRING_ZUBBA_HIVE, MAP_5C_CCW_AUTUMN_ZUBBA_HIVE, - // Unused + MAP_5D_UNUSED, MAP_5E_CCW_SPRING_NABNUTS_HOUSE = 0x5E, MAP_5F_CCW_SUMMER_NABNUTS_HOUSE = 0x5F, MAP_60_CCW_AUTUMN_NABNUTS_HOUSE = 0x60, @@ -654,7 +654,7 @@ typedef enum map_e MAP_70_GL_CC_LOBBY = 0x70, MAP_71_GL_STATUE_ROOM, MAP_72_GL_BGS_LOBBY, - // Unused + MAP_73_UNUSED, MAP_74_GL_GV_PUZZLE = 0x74, MAP_75_GL_MMM_LOBBY, MAP_76_GL_640_NOTE_DOOR, @@ -1468,6 +1468,7 @@ enum sfx_e SFX_3F9_UNKNOWN, //chmole SFX_3FA_HONEYCOMB_TALKING, SFX_3FB_UNKNOWN, //conga + SFX_3FC_ZUBBA_UNK, SFX_405_UNKNOWN = 0x405, SFX_406_GOLD_BULLION_TALKING, @@ -1762,10 +1763,10 @@ enum mumbotoken_e typedef enum actor_e { - ACTOR_1_UNKNOWN = 0x1, + ACTOR_1_UNKNOWN = 0x1, ACTOR_2_UNKNOWN, - ACTOR_4_BIGBUTT = 0x4, + ACTOR_4_BIGBUTT = 0x4, ACTOR_5_TERMITE, ACTOR_6_GRUBLIN, ACTOR_7_MUMBO, @@ -1776,14 +1777,11 @@ typedef enum actor_e ACTOR_C_MUD_HUT, ACTOR_D_WOOD_DEMOLISHED, ACTOR_E_SMALL_BULL, - ACTOR_F_CHIMPY = 0xF, - - ACTOR_10E_BLUBBER_SHIP_TOP_HATCH = 0x10e, + ACTOR_F_CHIMPY, - ACTOR_11_JUJU_CTRL = 0x11, + ACTOR_11_JUJU_CTRL = 0x11, ACTOR_12_BEEHIVE, //ACTOR_13_SINKING_BOBBER - ACTOR_14_ORANGE_PROJECTILE = 0x14, ACTOR_15_UNKNOWN, @@ -1794,10 +1792,15 @@ typedef enum actor_e ACTOR_1B_FRAMERATE_20, ACTOR_1C_FRAMERATE_15, ACTOR_1D_FRAMERATE_12, - - ACTOR_1E_LEAKY = 0x1E, + ACTOR_1E_LEAKY, + ACTOR_1F_UNUSED, // Maybe was supposed to be Termite Transformation? + ACTOR_20_TRANSFORM_PUMPKIN, + ACTOR_21_TRANSFORM_CROC, + ACTOR_22_TRANSFORM_WALRUS, + ACTOR_23_TRANSFORM_BEE, ACTOR_25_CEMETARY_POT = 0x25, + ACTOR_26_CLIMB_BASE, ACTOR_29_ORANGE_COLLECTIBLE = 0x29, ACTOR_2A_GOLD_BULLION, @@ -1813,6 +1816,7 @@ typedef enum actor_e ACTOR_39_NAPPER = 0x39, ACTOR_3A_MOTZHAND, + ACTOR_3B_CLANKER_DIALOG_TRIGGER, ACTOR_3C_CC_KEY = 0x3C, ACTOR_3D_CLANKER_SAWBLADE_PROPELLOR_1, @@ -1901,31 +1905,31 @@ typedef enum actor_e ACTOR_BC_BANJOS_CURTAINS = 0xBC, ACTOR_BD_BANJOS_HOUSE_DOOR, - ACTOR_C5_CHIMPY_STUMP = 0xC5, + ACTOR_C5_CHIMPY_STUMP = 0xC5, ACTOR_C7_GRAVESTONE = 0xC7, - ACTOR_C8_BOGGY_2 = 0xC8, + ACTOR_C8_BOGGY_2, ACTOR_CA_TEEHEE = 0xCA, ACTOR_CB_1881_BARREL_TOP, - ACTOR_E4_FLIGHT_PAD = 0xE4, + ACTOR_E4_FLIGHT_PAD = 0xE4, - ACTOR_E6_GLOOP = 0xE6, + ACTOR_E6_GLOOP = 0xE6, ACTOR_E7_GLOOP_BUBBLE, ACTOR_E8_TANKTUP, ACTOR_E9_TANKTUP_LEG_FL, ACTOR_EA_TANKTUP_LEG_BL, ACTOR_EB_TANKTUP_LEG_FR, ACTOR_EC_TANKTUP_LEG_BR, - ACTOR_ED_PINK_EGG_LARGE = 0xED, + ACTOR_ED_PINK_EGG_LARGE, ACTOR_EE_PINK_EGG_MEDIUM, ACTOR_EF_PINK_EGG_SMALL, ACTOR_F0_PINK_EGG_SMALLEST, ACTOR_F1_LEAF_BOAT, ACTOR_F2_BLACK_SNIPPET, ACTOR_F3_EXPLOSION_RIPPLE, - ACTOR_F4_BURIED_TREASURE = 0xF4, + ACTOR_F4_BURIED_TREASURE, ACTOR_F5_MUTIE_SNIPPET, ACTOR_F6_BIG_ALLIGATOR, @@ -1936,12 +1940,13 @@ typedef enum actor_e ACTOR_105_UNKNOWN, ACTOR_106_UNKNOWN, ACTOR_107_UNKNOWN, - - ACTOR_109_SHACK_DOOR = 0x109, + ACTOR_108_MODEL_PLAYER_SHADOW, + ACTOR_109_SHACK_DOOR, ACTOR_10A_MANSION_DOOR, ACTOR_10B_CELLAR_HATCH, ACTOR_10C_CHURCH_GATE_LEFT_LOCK, ACTOR_10D_HEDGE_GATE_RIGHT_LOCK_1, + ACTOR_10E_BLUBBER_SHIP_TOP_HATCH, ACTOR_114_CHURCH_DOOR = 0x114, ACTOR_115_BLUBBER, @@ -1962,12 +1967,13 @@ typedef enum actor_e ACTOR_124_SIR_SLUSH, ACTOR_125_SNOWBALL, ACTOR_126_SIR_SLUSH_HAT, + ACTOR_129_RED_FEATHER = 0x129, ACTOR_12B_TUTORIAL_BOTTLES = 0x12B, ACTOR_12C_MOLEHILL, - ACTOR_12E_GOBI_1 = 0x12E, + ACTOR_12E_GOBI_1 = 0x12E, ACTOR_12F_GOBI_ROPE, ACTOR_130_GOBI_ROCK, ACTOR_131_GOBI_2, @@ -1994,8 +2000,8 @@ typedef enum actor_e ACTOR_147_ANCIENT_ONE, ACTOR_149_TTC_BLUBBER_UNKNOWN = 0x149, - ACTOR_14A_TTC_BLUBBER_UNKNOWN = 0x14a, - ACTOR_14B_TTC_BLUBBER_UNKNOWN = 0x14b, + ACTOR_14A_TTC_BLUBBER_UNKNOWN, + ACTOR_14B_TTC_BLUBBER_UNKNOWN, ACTOR_14E_BGS_ELEVATED_WALKWAY_SWITCH = 0x14E, ACTOR_14F_DESTROYED_JIGGY, @@ -2028,14 +2034,15 @@ typedef enum actor_e ACTOR_16B_CCW_AUTUMN_SEASON_DOOR, ACTOR_16C_CCW_SUMMER_SWITCH, ACTOR_16D_CCW_SUMMER_SEASON_DOOR, - ACTOR_16E_UNKNOWN = 0x16E, + ACTOR_16E_UNKNOWN, ACTOR_16F_QUARRIE, ACTOR_172_RBB_EGG_TOLL = 0x172, - - ACTOR_175_MODEL_RUSTY_BUCKET_REAR_PROPELLER = 0x175, - - ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1 = 0x177, + ACTOR_173_RBB_CAGE_UP_SWITCH, + ACTOR_174_RBB_TNT_DOWN_SWITCH, + ACTOR_175_RUSTY_BUCKET_REAR_PROPELLER, + ACTOR_176_RBB_GREEN_PROPELLOR_SWITCH, + ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1, ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, @@ -2047,7 +2054,7 @@ typedef enum actor_e ACTOR_180_RBB_SPINNING_DOUBLE_PIPE_2, ACTOR_181_SCARF_SLED = 0x181, - ACTOR_182_RACE_SLED = 0x182, + ACTOR_182_RACE_SLED, ACTOR_188_PIRANHA_WATER_PARTICLES = 0x188, @@ -2058,22 +2065,25 @@ typedef enum actor_e ACTOR_198_BANJOS_BED = 0x198, ACTOR_199_BANJOS_CHAIR, ACTOR_19A_BANJOS_STOVE, - + ACTOR_19B_MUMBOS_HAND_WITH_PICTURE, ACTOR_19C_MODEL_THE_END_SIGN = 0x19C, ACTOR_1BB_ENGINE_ROOM_PROPELLOR_1 = 0x1BB, ACTOR_1BC_ENGINE_ROOM_PROPELLOR_2, ACTOR_1BD_ENGINE_ROOM_PROPELLOR_3, - - ACTOR_1C2_WHISTLE_1 = 0x1C2, + ACTOR_1BE_RBB_GREY_PROPELLOR_SWITCH, + ACTOR_1BF_WHISTLE_SWITCH_1, + ACTOR_1C0_WHISTLE_SWITCH_2, + ACTOR_1C1_WHISTLE_SWITCH_3, + ACTOR_1C2_WHISTLE_1, ACTOR_1C3_WHISTLE_2, ACTOR_1C4_WHISTLE_3, - - ACTOR_1C5_WHISTLE_CTRL = 0x1C5, + ACTOR_1C5_WHISTLE_CTRL, ACTOR_1C6_GRIMLET, ACTOR_1C7_ANCHOR_SWITCH, ACTOR_1C8_SNORKEL, ACTOR_1C9_ANCHOR, + ACTOR_1CA_RAREWARE_FLAG, ACTOR_1CC_GRILLE_CHOMPA = 0x1CC, ACTOR_1CD_UNKNOWN, @@ -2095,6 +2105,7 @@ typedef enum actor_e ACTOR_1E2_CCW_SPRING_SWITCH, ACTOR_1E3_CCW_SPRING_SEASON_DOOR, ACTOR_1E4_TOOTS, + ACTOR_1E5_UNKNOWN, ACTOR_1E9_SNARE_BEAR = 0x1E9, ACTOR_1EA_POLAR_BEAR_CUB_BLUE, @@ -2163,11 +2174,11 @@ typedef enum actor_e ACTOR_230_BREAKABLE_FLOOR_COBWEB = 0x230, ACTOR_231_BREAKABLE_WALL_COBWEB, + ACTOR_233_CCW_MUMBOS_HUT = 0x233, ACTOR_234_CCW_ENTRANCE_DOOR = 0x234, ACTOR_235_FP_ENTRANCE_DOOR_LEFT, ACTOR_236_FP_ENTRANCE_DOOR_RIGHT, - - ACTOR_237_CCW_WITCH_SWITCH = 0x237, + ACTOR_237_CCW_WITCH_SWITCH, ACTOR_239_FP_WITCH_SWITCH = 0x239, ACTOR_23A_GL_ADVENT_CALENDAR_HATCH_DOOR, @@ -2180,8 +2191,7 @@ typedef enum actor_e ACTOR_242_FF_TELEPORT_PAD = 0x242, ACTOR_243_GV_SNS_CHAMBER_DOOR, ACTOR_244_GV_SNS_SARCOPHAGUS, - - ACTOR_245_GV_SNS_SWITCH = 0x245, + ACTOR_245_GV_SNS_SWITCH, ACTOR_246_FLIGHT_PAD_SWITCH, ACTOR_247_LAIR_SWITCH_FLIGHT_PAD, ACTOR_248_SHOCK_JUMP_PAD_SWITCH, @@ -2197,7 +2207,10 @@ typedef enum actor_e ACTOR_25C_SHARKFOOD_ISLAND, ACTOR_25D_ICE_KEY, ACTOR_25E_SNS_EGG, - + ACTOR_25F_CCW_UNKNOWN_NABNUT_WINDOW, + ACTOR_260_CCW_UNKNOWN_NABNUT_WINDOW, + ACTOR_261_CCW_AUTUMN_NABNUT_WINDOW, + ACTOR_262_CCW_WINTER_NABNUT_WINDOW, ACTOR_263_SUNNY_LIFEBOAT = 0x263, ACTOR_264_SHADOW_LIFEBOAT, ACTOR_265_DINING_DOOR, @@ -2215,6 +2228,9 @@ typedef enum actor_e ACTOR_282_BOSS_BOOM_BOX_LARGE, ACTOR_283_BOSS_BOOM_BOX_MEDIUM, ACTOR_284_BOSS_BOOM_BOX_SMALL, + ACTOR_285_JINXY_HEAD_SANDYBUTT_1, + ACTOR_286_JINXY_HEAD_SANDYBUTT_2, + ACTOR_287_JINXY_HEAD_SANDYBUTT_3, ACTOR_289_BETA_VENT = 0x289, ACTOR_28A_CLANKER_WHIPCRACK, @@ -2227,32 +2243,46 @@ typedef enum actor_e ACTOR_293_CLANKER_SAWBLADE_PROPELLOR_10, ACTOR_294_CLANKER_SAWBLADE_PROPELLOR_11, ACTOR_295_CLANKER_SAWBLADE_PROPELLOR_12, - - ACTOR_298_ZUBBA_DOOR = 0x298, - - ACTOR_29A_ZUBBA_DOOR = 0x29A, + ACTOR_296_BELL_BUOY, + ACTOR_297_ROWBOAT, + ACTOR_298_ZUBBA_DOOR_SUMMER, + ACTOR_299_ZUBBA_HONEY_LUMP, + ACTOR_29A_ZUBBA_DOOR_AUTUMN = 0x29A, ACTOR_29B_ZUBBA, - + ACTOR_29C_ZUBBA_DOCILE, ACTOR_29D_CCW_BEANSTALK = 0x29D, ACTOR_29E_CCW_GOBI, ACTOR_29F_CLUCKER, ACTOR_2A0_EAGLE_EGG, ACTOR_2A1_EEYRIE_BABY, ACTOR_2A2_CATERPILLAR, - + ACTOR_2A3_EEYRIE_ADULT, ACTOR_2A4_BOOM_BOX_SLOW = 0x2A4, - + ACTOR_2A5_BOOM_BOX_MINIGAME_CTRL = 0x2A5, + ACTOR_2A6_NABNUT_SPRING = 0x2A6, + ACTOR_2A7_NABNUT_FULL_BELLY, ACTOR_2A8_NABNUT = 0x2A8, ACTOR_2A9_ACORN, - - ACTOR_2AC_GNAWTY_BOULDER = 0x2AC, - - ACTOR_2B4_BOTTLES_BONUS_BANJO_HAND = 0x2B4, + ACTOR_2AA_GNAWTY_SWIMMING, + ACTOR_2AB_GNAWTY_SUMMER, + ACTOR_2AC_GNAWTY_BOULDER, + ACTOR_2AD_BOSS_BOOMBOX_CTRL, + ACTOR_2AE_LEAF_EMITTER_CCW_AUTUMN, + ACTOR_2AF_LEAF_EMITTER_CCW_HUB, + ACTOR_2B0_RAIN_EMITTER_CCW_SPRING, + ACTOR_2B1_RAIN_EMITTER_CCW_HUB, + ACTOR_2B2_SNOW_EMITTER_CCW_WINTER, + ACTOR_2B3_SNOW_EMITTER_CCW_HUB, + ACTOR_2B4_BOTTLES_BONUS_BANJO_HAND, + ACTOR_2B5_UNKNOWN, ACTOR_2D8_TWO_ICE_POLES_NEAR_CHEATO_3 = 0x2D8, - - ACTOR_2DB_DINGPOT = 0x2DB, - + ACTOR_2D9_UNKNOWN, + ACTOR_2DA_UNKNOWN, + ACTOR_2DB_DINGPOT, + ACTOR_2DC_GNAWTYS_SHELVES, + ACTOR_2DD_GNAWTYS_BED, + ACTOR_2DE_GNAWTYS_DEN, ACTOR_2DF_LIGHTHOUSE_B = 0x2DF, ACTOR_2E0_TTC_STAIRS_1, ACTOR_2E1_TTC_STAIRS_2, @@ -2260,12 +2290,11 @@ typedef enum actor_e ACTOR_2E3_LEVEL_ENTRY_SIGNS, ACTOR_2E4_WORLD_EXIT_PAD, ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE, - + ACTOR_2E6_NABNUT_DOOR, + ACTOR_2E7_WHIPCRACK_ROOM_DOOR, ACTOR_2E8_WINDOW = 0x2E8, ACTOR_2E9_WIDE_WINDOW, ACTOR_2EA_TALL_WINDOW, - - ACTOR_2E5_DOOR_OF_GRUNTY = 0x2e5, ACTOR_2F4_FISHBOWL = 0x2F4, ACTOR_2F5_CUCKOO_CLOCK, @@ -2273,17 +2302,25 @@ typedef enum actor_e ACTOR_2FF_GREEN_FOG_OUTSIDE_TOWER = 0x2FF, ACTOR_300_BIKINI_GIRL, + ACTOR_30B_DEAD_BEANSTALK = 0x30B, + ACTOR_30C_SNORE_Z, ACTOR_30D_BOOM_BOX_FAST = 0x30D, - + ACTOR_30E_CUTSCENE_ADULT_EYRIE, ACTOR_30F_WHIPCRACK = 0x30f, ACTOR_310_NABNUT_HOUSE_PILE_OF_ACORNS, - + ACTOR_311_PINK_SQUIRREL, + ACTOR_312_NABNUT_BEDSHEETS, ACTOR_313_NABNUT_BED = 0x313, ACTOR_314_NABNUT_IN_AUTUMN_HOUSE, - + ACTOR_315_NABNUT_EATING_ACORNS, + ACTOR_316_UNKNOWN, + ACTOR_317_UNKNOWN, + ACTOR_318_CCW_UNKNOWN = 0x318, ACTOR_319_GV_MAZE_CTRL = 0x319, - - ACTOR_31D_SANDYBUTT_PYRAMID = 0x31D, + ACTOR_31A_INDOORS_GNAWTY, + ACTOR_31B_SPINNING_SINGLE_PIPE_SFX_CTRL, + ACTOR_31C_DOUBLE_SINGLE_PIPE_SFX_CTRL, + ACTOR_31D_SANDYBUTT_PYRAMID, ACTOR_31E_PALM_TREE, ACTOR_32B_UNKNOWN = 0x32B, //something with Tanktup @@ -2309,12 +2346,12 @@ typedef enum actor_e ACTOR_348_BRENTILDA = 0x348, ACTOR_349_UNKNOWN, - ACTOR_34D_BEE_SWARM = 0x34D, + ACTOR_34D_BEE_SWARM = 0x34D, ACTOR_34E_LIMBO, ACTOR_34F_MUMMUM, ACTOR_350_SEAMAN_GRUBLIN, - - ACTOR_352_UNKNOWN = 0x352, + ACTOR_351_UNKNOWN, + ACTOR_352_UNKNOWN, ACTOR_353_XMAS_TREE_EGG_TOLL, ACTOR_354_DRIPS, @@ -2324,22 +2361,22 @@ typedef enum actor_e ACTOR_36A_15_MUMBO_TOKEN_SIGN, ACTOR_36B_10_MUMBO_TOKEN_SIGN, ACTOR_36C_25_MUMBO_TOKEN_SIGN, + ACTOR_36D_COLLYWOBBLE_B, + ACTOR_36E_BAWL_THE_ONION_B, + ACTOR_36F_TOPPER_THE_CARROT_B, + ACTOR_370_GOLD_FEATHER, - ACTOR_COLLYWOBBLE_B = 0x36D, - ACTOR_BAWL_THE_ONION_B = 0x36E, - ACTOR_TOPPER_THE_CARROT_B = 0x36F, - ACTOR_370_GOLD_FEATHER = 0x370, - - ACTOR_374_VACATION_TEXT_TRIGGER = 0x374, + ACTOR_374_VACATION_TEXT_TRIGGER = 0x374, ACTOR_375_GRUBLIN_HOOD, ACTOR_376_FF_MINIGAME, ACTOR_379_UNKNOWN = 0x379, ACTOR_37A_BOTTLES, - ACTOR_37D_ICECUBE_A = 0x37d, + ACTOR_37D_ICECUBE_A = 0x37D, + ACTOR_37E_DEAD_SNAREBEAR, - ACTOR_37F_LOGGO = 0x37F, + ACTOR_37F_LOGGO = 0x37F, ACTOR_380_SCARAB_BEETLE, ACTOR_381_PORTRAIT_CHOMPA, ACTOR_382_PORTRAIT_OF_GRUNTY, @@ -2363,7 +2400,7 @@ typedef enum actor_e ACTOR_3A6_BOSS_JINJO_GREEN, ACTOR_3A7_BOSS_JINJO_PINK, ACTOR_3A8_BOSS_JINJO_YELLOW, - ACTOR_3A9_JINJONATOR_STATUE_BASE = 0x3A9, + ACTOR_3A9_JINJONATOR_STATUE_BASE, ACTOR_3AA_GRUNTY_SPELL_GREEN_ATTACK = 0x3AA, ACTOR_3AB_GRUNTY_SPELL_BARRIER, @@ -2377,8 +2414,7 @@ typedef enum actor_e ACTOR_3BD_SM_BRIDGE_CHECKSUM_TRIGGER = 0x3BD, ACTOR_3BE_LAIR_UNKNOWN, - - ACTOR_3BF_GRUNTLING_BLUE = 0x3BF, + ACTOR_3BF_GRUNTLING_BLUE, ACTOR_3C0_GRUNTLING_BLACK, ACTOR_3C1_PURPLE_TEEHEE, ACTOR_3C2_GIANT_GRAVESTONE, @@ -2388,10 +2424,11 @@ typedef enum actor_e ACTOR_3C7_FF_PRIZE_GRUNTY_DOLL = 0x3C7, ACTOR_3C8_FF_PRIZE_TOOTY, ACTOR_3C9_FURNACE_FUN_PICK_PRICE, - ACTOR_3CA_ROCK_TRAPPING_GRUNTY = 0x3CA, + ACTOR_3CA_ROCK_TRAPPING_GRUNTY, ACTOR_3CB_UNKNOWN, + ACTOR_3CC_DUMMY_PLAYER_ANCHOR = 0x3CC, // Lighthouse [port] network anchor dummy player + ACTOR_3CD_CUSTOM_COLLECTIBLE = 0x3CD, // Lighthouse [port] rando custom collectible - ACTOR_3CC_DUMMY_PLAYER_ANCHOR = 0x3CC, } ActorID; enum bundle_e { @@ -2440,23 +2477,23 @@ enum bs_e { BS_0_NONE = 0x0, BS_1_IDLE = 0x1, BS_2_WALK_SLOW = 0x2, - BS_WALK = 0x3, + BS_3_WALK = 0x3, BS_4_WALK_FAST = 0x4, BS_5_JUMP = 0x5, - BS_CLAW = 0x6, - BS_CROUCH = 0x7, + BS_6_CLAW = 0x6, + BS_7_CROUCH = 0x7, BS_8_BTROT_JUMP = 0x8, BS_9_EGG_HEAD = 0x9, BS_A_EGG_ASS = 0xA, BS_B_UNKOWN = 0xB, - BS_SKID = 0xC, - BS_D_TIMEOUT = 0xD, + BS_C_SKID = 0xC, + BS_D_TIMEOUT_TRANSFORMATION = 0xD, BS_E_OW = 0xE, BS_F_BBUSTER = 0xF, - BS_BFLAP = 0x10, + BS_10_BFLAP = 0x10, BS_11_BPECK = 0x11, BS_12_BFLIP = 0x12, - BS_BBARGE = 0x13, + BS_13_BBARGE = 0x13, BS_14_BTROT_ENTER = 0x14, BS_15_BTROT_IDLE = 0x15, BS_16_BTROT_WALK = 0x16, @@ -2468,31 +2505,31 @@ enum bs_e { BS_1C_WONDERWING_WALK = 0x1C, BS_1D_WONDERWING_JUMP = 0x1D, BS_1E_WONDERWING_EXIT = 0x1E, - BS_WALK_CREEP = 0x1F, + BS_1F_WALK_CREEP = 0x1F, BS_20_LANDING = 0x20, - BS_BSHOCK_CHARGE = 0x21, - BS_BSHOCK_JUMP = 0x22, + BS_21_BSHOCK_CHARGE = 0x21, + BS_22_BSHOCK_JUMP = 0x22, BS_23_FLY_ENTER = 0x23, BS_24_FLY = 0x24, BS_25_LONGLEG_ENTER = 0x25, BS_26_LONGLEG_IDLE = 0x26, - BS_LONGLEG_WALK = 0x27, - BS_LONGLEG_JUMP = 0x28, - BS_LONGLEG_EXIT = 0x29, - BS_BOMB = 0x2A, + BS_27_LONGLEG_WALK = 0x27, + BS_28_LONGLEG_JUMP = 0x28, + BS_29_LONGLEG_EXIT = 0x29, + BS_2A_BOMB = 0x2A, BS_2B_DIVE_IDLE = 0x2B, BS_2C_DIVE_B = 0x2C, BS_2D_SWIM_IDLE = 0x2D, BS_2E_SWIM = 0x2E, BS_2F_FALL = 0x2F, BS_30_DIVE_ENTER = 0x30, - BS_ROLL = 0x31, - BS_SLIDE = 0x32, - + BS_31_ROLL = 0x31, + BS_32_SLIDE = 0x32, + BS_33_WASHY_UNKNOWN = 0x33, BS_34_JIG_NOTEDOOR = 0x34, BS_35_ANT_IDLE = 0x35, - BS_ANT_WALK = 0x36, - BS_ANT_JUMP = 0x37, + BS_36_ANT_WALK = 0x36, + BS_37_ANT_WALK = 0x37, BS_38_ANT_FALL = 0x38, BS_39_DIVE_A = 0x39, BS_3A_CARRY_IDLE = 0x3A, @@ -2500,14 +2537,14 @@ enum bs_e { BS_3C_TALK = 0x3C, BS_3D_FALL_TUMBLING = 0x3D, BS_3E_ANT_OW = 0x3E, - BS_3F = 0x3F, + BS_3F_UNKNOWN = 0x3F, BS_40_PUMPKIN_FLUSH = 0x40, BS_41_DIE = 0x41, BS_42_DINGPOT = 0x42, BS_43_ANT_DIE = 0x43, BS_44_JIG_JIGGY = 0x44, BS_45_BTROT_SLIDE = 0x45, - + BS_46_UNKNOWN = 0x46, BS_48_PUMPKIN_IDLE = 0x48, BS_49_PUMPKIN_WALK = 0x49, @@ -2519,39 +2556,39 @@ enum bs_e { BS_4F_CLIMB_IDLE = 0x4F, BS_50_CLIMB_MOVE = 0x50, BS_51_CLIMB_EXIT = 0x51, - BS_52_UNKNOWN = 0x52, //tumblar??? a.k.a bssurf - BS_53_TIMEOUT = 0x53, + BS_52_SURF = 0x52, //tumblar??? a.k.a bssurf + BS_53_TIMEOUT_BANJO = 0x53, BS_54_SWIM_DIE = 0x54, - BS_LONGLEG_SLIDE = 0x55, + BS_55_LONGLEG_SLIDE = 0x55, BS_56_RECOIL = 0x56, BS_57_BOMB_END = 0x57, BS_58_BEAKBOMB_CRASH = 0x58, BS_59_BFLY_UNK59 = 0x59, BS_5A_LOADZONE = 0x5A, - BS_CARRY_THROW = 0x5B, + BS_5B_CARRY_THROW = 0x5B, BS_5E_CROC_IDLE = 0x5E, - BS_CROC_WALK = 0x5F, - BS_CROC_JUMP = 0x60, + BS_5F_CROC_WALK = 0x5F, + BS_60_CROC_JUMP = 0x60, BS_61_CROC_FALL = 0x61, BS_62_LONGLEG_LOCKED = 0x62, - BS_CROC_OW = 0x63, - BS_CROC_DIE = 0x64, + BS_63_CROC_OW = 0x63, + BS_64_CROC_DIE = 0x64, BS_67_WALRUS_IDLE = 0x67, - BS_WALRUS_WALK = 0x68, - BS_WALRUS_JUMP = 0x69, + BS_68_WALRUS_WALK = 0x68, + BS_69_WALRUS_JUMP = 0x69, BS_6A_WALRUS_FALL = 0x6A, BS_6B_BEE_LOCKED = 0x6B, //[107] = "Locked", -- Bee, Mumbo Transform Cutscene - BS_WALRUS_OW = 0x6C, - BS_WALRUS_DIE = 0x6D, + BS_6C_WALRUS_OW = 0x6C, + BS_6D_WALRUS_DIE = 0x6D, BS_6E_CROC_BITE = 0x6E, - BS_CROC_EAT_BAD = 0x6F, + BS_6F_CROC_EAT_BAD = 0x6F, BS_70_CROC_EAT_GOOD = 0x70, BS_71_BTROT_FALL = 0x71, - BS_SPLAT = 0x72, // Getting up after fall damage + BS_72_SPLAT = 0x72, // Getting up after fall damage BS_73_UNKNOWN = 0x73, // locked_cutscene BS_74_UNKNOWN = 0x74, // locked jiggypad, xform, bottles BS_75_UNKNOWN = 0x75, // locked bottles @@ -2559,8 +2596,8 @@ enum bs_e { BS_77_SWIM_LOOKAT_DRONE = 0x77, BS_78_DIVE_LOOKAT_DRONE = 0x78, BS_79_BTROT_LOCKED = 0x79, - BS_WALK_MUD = 0x7A, - BS_BTROT_OW = 0x7B, + BS_7A_WALK_MUD = 0x7A, + BS_7B_BTROT_OW = 0x7B, BS_7C_SLED = 0x7C, BS_7D_WALRUS_SLED = 0x7D, BS_7E_WALRUS_SLED = 0x7E, @@ -2571,18 +2608,18 @@ enum bs_e { BS_85_BEE_IDLE = 0x85, - BS_BEE_WALK = 0x86, - BS_BEE_JUMP = 0x87, + BS_86_BEE_WALK = 0x86, + BS_87_BEE_JUMP = 0x87, BS_88_BEE_FALL = 0x88, - BS_BEE_OW = 0x89, - BS_BEE_DIE = 0x8A, - - BS_BEE_FLY = 0x8C, + BS_89_BEE_OW = 0x89, + BS_8A_BEE_DIE = 0x8A, + BS_8B_UNKNOWN = 0x8B, + BS_8C_BEE_FLY = 0x8C, BS_8D_CROC_LOCKED = 0x8D, BS_8E_ANT_LOCKED = 0x8E, // "Locked", -- Jiggy podium, Bottles' text outside Mumbo's BS_8F_PUMPKIN_LOCKED = 0x8F, - BS_FLY_OW = 0x91, + BS_91_FLY_OW = 0x91, BS_92_ANT_DRONE = 0x92, BS_93_PUMPKIN_DRONE = 0x93, BS_94_CROC_DRONE = 0x94, @@ -2596,11 +2633,11 @@ enum bs_e { BS_9C_WALRUS_SLED_DRONE = 0x9C, BS_9D_BEE_DRONE = 0x9D, BS_9E_CLIMB_LOCKED = 0x9E, - BS_ANT_BOUNCE = 0x9F, - BS_PUMPKIN_BOUNCE = 0xA0, - BS_CROC_BOUNCE = 0xA1, - BS_WALRUS_BOUNCE = 0xA2, - BS_BEE_BOUNCE = 0xA3, + BS_9F_ANT_BOUNCE = 0x9F, + BS_A0_ANT_BOUNCE = 0xA0, + BS_A1_CROC_BOUNCE = 0xA1, + BS_A2_WALRUS_BOUNCE = 0xA2, + BS_A3_BEE_BOUNCE = 0xA3, BS_A4_WONDERWING_DRONE = 0xA4, BS_A5_WONDERWING_UNKA5 = 0xA5 }; @@ -2650,18 +2687,24 @@ enum ttc_specific_flags { }; enum bgs_specific_flags { - BGS_SPECIFIC_FLAG_1 = 1, - BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_RESET = 2, - BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_TIMER_RUNNING = 3, - BGS_SPECIFIC_FLAG_WALKWAY_JIGGY = 4, - BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_SWITCH_PRESSED = 5, - BGS_SPECIFIC_FLAG_7 = 7, - BGS_SPECIFIC_FLAG_8 = 8, - BGS_SPECIFIC_FLAG_MAZE_JIGGY_SWITCH_PRESSED = 9, - BGS_SPECIFIC_FLAG_A = 0xA, - BGS_SPECIFIC_FLAG_MAZE_JIGGY_RESET = 0xB, - BGS_SPECIFIC_FLAG_MAZE_JIGGY_TIMER_RUNNING = 0xC, - BGS_SPECIFIC_FLAG_MAZE_JIGGY = 0xD + BGS_SPECIFIC_FLAG_1 = 1, // WALKWAY_JIGGY + BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET, + BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING, + BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY, + BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED, + BGS_SPECIFIC_FLAG_6_MR_VILE, + BGS_SPECIFIC_FLAG_7, // WALKWAY_JIGGY + BGS_SPECIFIC_FLAG_8, // WALKWAY_JIGGY + BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED, + BGS_SPECIFIC_FLAG_A, // MAZE_JIGGY + BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET, + BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING, + BGS_SPECIFIC_FLAG_D_MAZE_JIGGY, + BGS_SPECIFIC_FLAG_E_UNUSED, + BGS_SPECIFIC_FLAG_F_UNUSED, + BGS_SPECIFIC_FLAG_10_FROG_MINIGAME_FIRST_MET, + BGS_SPECIFIC_FLAG_11_UNUSED, + BGS_SPECIFIC_FLAG_12_FROG_MINIGAME_BATTLE_ACTIVE }; enum fp_specific_flags { @@ -2694,6 +2737,38 @@ enum mmm_specific_flags { MMM_SPECIFIC_FLAG_7_UNKNOWN }; +enum rbb_main_specific_flags { + RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER, + RBB_MAIN_SPECIFIC_FLAG_1_WHISTLE_SWITCH_1, + RBB_MAIN_SPECIFIC_FLAG_2_WHISTLE_SWITCH_2, + RBB_MAIN_SPECIFIC_FLAG_3_WHISTLE_SWITCH_3, + RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING, + + RBB_MAIN_SPECIFIC_FLAG_8_UNK = 8 +}; + +enum rbb_boat_room_specific_flags { + RBB_BOAT_ROOM_SPECIFIC_FLAG_0_HONEYCOMB_SPAWNED +}; + +enum ccw_season_e +{ + CCW_SEASON_0_SPRING, + CCW_SEASON_1_SUMMER, + CCW_SEASON_2_AUTUMN, + CCW_SEASON_3_WINTER +}; + +enum ccw_zubba_specific_flags { + CCW_ZUBBA_SPECIFIC_FLAG_7_SPRING_DIALOG = 0x7, + CCW_ZUBBA_SPECIFIC_FLAG_8_AUTUMN_DIALOG +}; + +enum ccw_winter_specific_flags { + CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT = 0x5, + CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT +}; + enum lair_specific_flags { LAIR_SPECIFIC_FLAG_7_UKNOWN = 0x7, LAIR_SPECIFIC_FLAG_9_UKNOWN = 0x9 @@ -3042,17 +3117,19 @@ typedef enum asset_e ASSET_132_ANIM_FLOTSAM_MOVE = 0x132, ASSET_133_ANIM_NIPPER_DIE = 0x133, - ASSET_138_ANIM_ZOOMBOX = 0x138, - ASSET_139_ANIM_BOTTLES_EXIT = 0x139, - ASSET_13A_ANIM_BOTTLES_ENTER = 0x13A, - ASSET_13B_ANIM_BOTTLES_IDLE = 0x13B, - - ASSET_13E_ANIM_SNORKEL_SWIM = 0x13E, - ASSET_13F_ANIM_SNORKEL_STUCK = 0x13F, - - ASSET_141_ANIM_ANCHOR_LOWERED = 0x141, - ASSET_142_ANIM_ANCHOR_RISING = 0x142, - ASSET_143_ANIM_SNOWMAN_BUTTON = 0x143, + ASSET_137_ANIM_GRIMLET_ATTACK = 0x137, + ASSET_138_ANIM_ZOOMBOX, + ASSET_139_ANIM_BOTTLES_EXIT, + ASSET_13A_ANIM_BOTTLES_ENTER, + ASSET_13B_ANIM_BOTTLES_IDLE, + ASSET_13C_ANIM_MOLEHILL_UNKNOWN, + ASSET_13D_ANIM_MOLEHILL_UNKNOWN, + ASSET_13E_ANIM_SNORKEL_SWIM, + ASSET_13F_ANIM_SNORKEL_STUCK, + ASSET_140_ANIM_RAREWARE_FLAG, + ASSET_141_ANIM_ANCHOR_LOWERED, + ASSET_142_ANIM_ANCHOR_RISING, + ASSET_143_ANIM_SNOWMAN_BUTTON, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR = 0x146, ASSET_147_ANIM_BOOMBOX_MOVE = 0x147, @@ -3079,12 +3156,18 @@ typedef enum asset_e ASSET_166_ANIM_BURIED_TREASURE_BOUNCE = 0x166, ASSET_167_ANIM_BSREST_MOVE = 0x167, + ASSET_16A_ANIM_BELL_BUOY = 0x16A, + ASSET_16B_ANIM_SNAREBEAR_ATTACK = 0x16B, + ASSET_16C_ANIM_SNAREBEAR_IDLE = 0x16C, + ASSET_16E_ANIM_MUMBO_RECLINE = 0x16E, ASSET_16F_ANIM_ZUBBA_FLY_MOVE = 0x16F, ASSET_170_ANIM_ZUBBA_FLY_IDLE = 0x170, ASSET_171_ANIM_ZUBBA_DIE = 0x171, ASSET_172_ANIM_ZUBBA_LAND = 0x172, - + ASSET_173_ANIM_BEANSTALK_UNK = 0x173, + ASSET_174_ANIM_BEANSTALK_UNK = 0x174, + ASSET_175_ANIM_BEANSTALK_UNK = 0x175, ASSET_176_ANIM_GOBI_YAWN = 0x176, ASSET_177_ANIM_GOBI_SLEEP = 0x177, @@ -3093,7 +3176,9 @@ typedef enum asset_e ASSET_17E_ANIM_POLAR_BEAR_CUB_SAD = 0x17E, ASSET_17F_ANIM_MUMBO_SWEEP = 0x17F, ASSET_180_ANIM_MUMBO_ROTATE = 0x180, - + ASSET_181_ANIM_BEANSTALK_UNK = 0x181, + ASSET_182_ANIM_BEANSTALK_UNK = 0x182, + ASSET_183_ANIM_BEANSTALK_UNK = 0x183, ASSET_184_ANIM_CLUCKER_ATTACK_SHORT = 0x184, ASSET_185_ANIM_CLUCKER_ATTACK_LONG = 0x185, ASSET_186_ANIM_CLUCKER_DIE = 0x186, @@ -3102,17 +3187,25 @@ typedef enum asset_e ASSET_189_ANIM_FLOTSAM_DIE = 0x189, ASSET_18A_ANIM_XMAS_GIFT = 0x18A, + ASSET_18D_ANIM_CATERPILLAR_UNK = 0x18D, ASSET_18E_ANIM_CATERPILLAR_IDLE = 0x18E, + ASSET_199_ANIM_EEYRIE_ADULT_UNK = 0x199, + ASSET_19A_ANIM_EEYRIE_ADULT_UNK = 0x19A, ASSET_19B_ANIM_UNKNOWN = 0x19B, - + ASSET_19C_ANIM_BSWALRUS_BOUNCE = 0x19C, ASSET_19D_ANIM_BSWALRUS_DIE = 0x19D, ASSET_19E_ANIM_BSWALRUS_SLED = 0x19E, ASSET_19F_ANIM_BSWALRUS_SLED_JUMP = 0x19F, ASSET_1A1_ANIM_SLED = 0x1A1, ASSET_1A2_ANIM_NABNUT_SLEEP = 0x1A2, + ASSET_1A3_ANIM_NABNUT_SPRING_LOOKING_AROUND = 0x1A3, + ASSET_1A4_ANIM_NABNUT_SPRING_EATING = 0x1A4, + ASSET_1A6_ANIM_GNAWTY_IDLE = 0x1A6, + ASSET_1A7_ANIM_GNAWTY_CHEERING = 0x1A7, + ASSET_1A8_ANIM_GNAWTY_RUNNING = 0x1A8, ASSET_1A9_ANIM_BSWALRUS_LOSS = 0x1A9, ASSET_1AF_ANIM_TWINKLY_MUNCHER_APPEAR = 0x1AF, @@ -3156,6 +3249,10 @@ typedef enum asset_e ASSET_217_ANIM_UNKNOWN = 0x217, + ASSET_21C_ANIM_SNORE_Z = 0x21C, + ASSET_21D_ANIM_ADULT_EYRIE_UNK = 0x21D, + ASSET_21E_ANIM_ADULT_EYRIE_UNK = 0x21E, + ASSET_220_ANIM_SIR_SLUSH_DIE = 0x220, ASSET_221_ANIM_WOZZA_IN_CAVE = 0x221, @@ -3172,8 +3269,11 @@ typedef enum asset_e ASSET_22D_ANIM_NABNUT_BACKFLIP = 0x22D, ASSET_22E_ANIM_NABNUT_STAND = 0x22E, ASSET_22F_ANIM_NABNUT_RUN = 0x22F, + ASSET_230_ANIM_PINK_SQUIRREL_UNK = 0x230, + ASSET_231_ANIM_NABNUT_BEDSHEETS_UNK = 0x231, ASSET_233_ANIM_ICECUBE = 0x233, + ASSET_234_ANIM_DEAD_SNAREBEAR = 0x234, ASSET_236_ANIM_BSPUMPKIN_REBOUND = 0x236, @@ -3209,12 +3309,24 @@ typedef enum asset_e ASSET_288_ANIM_FLIBBIT_OW = 0x288, - ASSET_2A9_ANIM_BAT_FALL = 0x2A9, - ASSET_2AA_ANIM_BAT_DIE = 0x2AA, - ASSET_2AB_ANIM_TEEHEE_DIE = 0x2AB, + ASSET_2A1_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN = 0x2A1, + ASSET_2A2_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A3_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A4_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A5_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A6_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A7_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A8_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, + ASSET_2A9_ANIM_BAT_FALL, + ASSET_2AA_ANIM_BAT_DIE, + ASSET_2AB_ANIM_TEEHEE_DIE, ASSET_2C0_ANIM_CHUMP_DIE = 0x2C0, + ASSET_2C6_ANIM_MUMBOS_HAND_WITH_PICTURE = 0x2C6, + ASSET_2C7_ANIM_MUMBOS_HAND_WITH_PICTURE, + ASSET_2C8_ANIM_MUMBOS_HAND_WITH_PICTURE, + // 2d1 Grey House Brick (Upon Smashing MM Huts) ASSET_2D2_MODEL_ORANGE = 0x2d2, //projectile // 2d3 MM Conga Tree @@ -3442,11 +3554,11 @@ typedef enum asset_e ASSET_3B0_SNACKER = 0x3B0, // 3b1 Concert Mumbo ASSET_3B2_MODEL_TWO_ICE_POLES_NEAR_CHEATO_3 = 0x3B2, - // 3b3 Mumbo's Hut - // Unused - // Unused - ASSET_3B6_MODEL_TTC_STAIRS_1 = 0x3B6, - ASSET_3B7_MODEL_TTC_STAIRS_1 = 0x3B7, + ASSET_3B3_MODEL_CCW_MUMBOS_HUT, + ASSET_3B4_MODEL_UNUSED, + ASSET_3B5_MODEL_UNUSED, + ASSET_3B6_MODEL_TTC_STAIRS_1, + ASSET_3B7_MODEL_TTC_STAIRS_2, // Unused // Unused // Unused @@ -3483,30 +3595,30 @@ typedef enum asset_e ASSET_3D9_MODEL_GV_KAZOOIE_DOOR = 0x3D9, // 3da GV Sun Door ASSET_3DB_MODEL_GV_STAR_HATCH = 0x3db, - ASSET_3DC_MODEL_MAGIC_CARPET = 0x3DC, - ASSET_3DD_MODEL_RUBEE = 0x3DD, - ASSET_3DE_MODEL_HISTUP = 0x3DE, - ASSET_3DF_MODEL_TRUNKER = 0x3DF, - ASSET_3E0_MODEL_GOBI = 0x3E0, - ASSET_3E1_MODEL_RUBEES_EGG_POT = 0x3E1, - ASSET_3E2_MODEL_GV_KAZOOIE_TARGET = 0x3E2, - ASSET_3E3_MODEL_GOBI_ROPE = 0x3E3, - ASSET_3E4_MODEL_GOBI_ROCK = 0x3E4, - ASSET_3E5_MODEL_GRABBA_SHADOW = 0x3E5, - // 3e6 GV Jinxy Head 2 - ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW = 0x3e7, - ASSET_3E8_MODEL_ANCIENT_ONE = 0x3E8, - ASSET_3E9_MODEL_RED_ARROW = 0x3E9, - ASSET_3EA_MODEL_RED_X = 0x3EA, - ASSET_3EB_MODEL_RED_QUESTION_MARK = 0x3EB, - ASSET_3EC_MODEL_SHRAPNEL = 0x3EC, - ASSET_3ED_MODEL_BUZZBOMB = 0x3ED, - ASSET_3EE_TANKTUP = 0x3EE, - ASSET_3EF_MODEL_TANKTUP_LEG_FL = 0x3EF, - ASSET_3F0_MODEL_TANKTUP_LEG_BL = 0x3F0, - ASSET_3F1_MODEL_TANKTUP_LEG_FR = 0x3F1, - ASSET_3F2_MODEL_TANKTUP_LEG_BR = 0x3F2, - ASSET_3F3_MODEL_GOBI_SPIT = 0x3F3, + ASSET_3DC_MODEL_MAGIC_CARPET, + ASSET_3DD_MODEL_RUBEE, + ASSET_3DE_MODEL_HISTUP, + ASSET_3DF_MODEL_TRUNKER, + ASSET_3E0_MODEL_GOBI, + ASSET_3E1_MODEL_RUBEES_EGG_POT, + ASSET_3E2_MODEL_GV_KAZOOIE_TARGET, + ASSET_3E3_MODEL_GOBI_ROPE, + ASSET_3E4_MODEL_GOBI_ROCK, + ASSET_3E5_MODEL_GRABBA_SHADOW, + ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, + ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW, + ASSET_3E8_MODEL_ANCIENT_ONE, + ASSET_3E9_MODEL_RED_ARROW, + ASSET_3EA_MODEL_RED_X, + ASSET_3EB_MODEL_RED_QUESTION_MARK, + ASSET_3EC_MODEL_SHRAPNEL, + ASSET_3ED_MODEL_BUZZBOMB, + ASSET_3EE_TANKTUP, + ASSET_3EF_MODEL_TANKTUP_LEG_FL, + ASSET_3F0_MODEL_TANKTUP_LEG_BL, + ASSET_3F1_MODEL_TANKTUP_LEG_FR, + ASSET_3F2_MODEL_TANKTUP_LEG_BR, + ASSET_3F3_MODEL_GOBI_SPIT, // Unused // 3f5 BGS Green Jiggy Switch ASSET_3F5_BGS_JIGGY_SWITCH = 0x3F5, @@ -3522,7 +3634,7 @@ typedef enum asset_e ASSET_3FF_MODEL_GV_SUN_DOOR = 0x3FF, ASSET_400_MODEL_SUN_SWITCH = 0x400, ASSET_401_MODEL_FLOTSAM = 0x401, - ASSET_402_MODEL_EGG_TOLL = 0x402, + ASSET_402_MODEL_EGG_TOLL = 0x402, // Floating Green Orb ASSET_403_MODEL_RUSTY_BUCKET_REAR_PROPELLER = 0x403, ASSET_404_MODEL_RBB_GREEN_PROPELLER_SWITCH = 0x404, ASSET_405_MODEL_RBB_GREY_PROPELLER_SWITCH = 0x405, @@ -3550,7 +3662,7 @@ typedef enum asset_e ASSET_41B_MODEL_ANCHOR_SWITCH = 0x41B, ASSET_41C_MODEL_SNORKEL = 0x41C, ASSET_41D_MODEL_ANCHOR = 0x41D, - // 41e RBB Rareware Flag + ASSET_41E_MODEL_RAREWARE_FLAG = 0x41E, // 41f (Gruntilda's Final Battle Forcefield?) // 420 (Explosion 2D?) ASSET_421_MODEL_FP_SNOWMAN_BUTTON = 0x421, @@ -3559,7 +3671,7 @@ typedef enum asset_e // 424 GV Cactus ASSET_425_MODEL_CROCTUS = 0x425, ASSET_426_MODEL_XMAS_TREE_STAR = 0x426, - // 427 (Wooden Plank) + ASSET_427_MODEL_WOODEN_PLANK = 0x427, ASSET_428_MODEL_BOSS_BOOM_BOX = 0x428, ASSET_429_MODEL_CC_KEY = 0x429, ASSET_42A_UNKNOWN = 0x42A, // 42a (Smoke 2D?) @@ -3580,15 +3692,15 @@ typedef enum asset_e ASSET_438_MODEL_HONEYCOMB_SWITCH = 0x438, // 439 (Unknown?) ASSET_43A_MODEL_CLANKER_SAWBLADE_PROPELLOR = 0x43A, - // 43b RBB Bell Buoy - // 43c RBB Row Boat + ASSET_43B_MODEL_BELL_BUOY, + ASSET_43C_MODEL_ROWBOAT, ASSET_43D_MODEL_MMM_CLOCK_SWITCH = 0x43D, ASSET_43E_MODEL_HEDGE_GATE_RIGHT_LOCK_2 = 0x43E, // 43f (White Star?) ASSET_440_MODEL_SNAREBEAR = 0x440, // 441 (Sir Slush Snowball?) ASSET_442_MODEL_TWINKLY_BOX = 0x442, - // 443 CCW Zubba Honey Lump + ASSET_443_MODEL_ZUBBA_HONEY_LUMP = 0x443, ASSET_444_MODEL_CCW_ZUBBA_DOOR = 0x444, ASSET_445_MODEL_CCW_ZUBBA_DOOR = 0x445, ASSET_446_MODEL_ZUBBA = 0x446, @@ -3619,9 +3731,9 @@ typedef enum asset_e // 45f (Firey Rock?) ASSET_460_MODEL_KAZOOIE_RACK_FEATHERS = 0x460, ASSET_461_MODEL_GREEN_FOG_OUTSIDE_TOWER, - // 462 Nabnut's Girlfriend - // 463 Nabnut's Bed Sheet - // 464 Nabnut's Bed + ASSET_462_MODEL_PINK_SQUIRREL = 0x462, + ASSET_463_MODEL_NABNUT_BEDSHEETS = 0x463, + ASSET_464_MODEL_NABNUT_BED = 0x464, // 465 Dead Snarebear // 466 (Sparkle 2D?) ASSET_467_MODEL_TRANSITION_FALLING_JIGGIES = 0x467, @@ -3636,12 +3748,12 @@ typedef enum asset_e ASSET_46F_MODEL_CUCKOO_CLOCK = 0x46F, // 470 Banjo's Bookshelves // 471 Empty Blow Picture Frame - // 472 Blank Picture - ASSET_473_MODEL_BBQ_MUMBO = 0x473, - ASSET_474_MODEL_BBQ_GRILL_AND_FISH = 0x474, - ASSET_475_SPRITE_GAME_OVER_HEART = 0x475, - ASSET_476_SPRITE_BLUE_GLOW = 0x476, - ASSET_477_SPRITE_YELLOW_GLOW = 0x477, + ASSET_472_UNKNOWN = 0x472, // Blank Picture? + ASSET_473_MODEL_BBQ_MUMBO, + ASSET_474_MODEL_BBQ_GRILL_AND_FISH, + ASSET_475_SPRITE_GAME_OVER_HEART, + ASSET_476_SPRITE_BLUE_GLOW, + ASSET_477_SPRITE_YELLOW_GLOW, // 478 (Yellow Glow?) ASSET_479_MODEL_BIKINI_GIRL = 0x479, // 47a (Brown Ball?) @@ -3663,7 +3775,7 @@ typedef enum asset_e ASSET_48A_MODEL_FLIGHT_PAD = 0x48A, ASSET_48B_MODEL_JIGGY_PODIUM = 0x48B, ASSET_48C_MODEL_BOOM_BOX = 0x48C, - // 48d Nabnut Eating Acorns + ASSET_48D_MODEL_NABNUT_EATING_ACORNS = 0x48D, ASSET_48E_MODEL_ACORN = 0x48E, ASSET_48F_MODEL_GNAWTY = 0x48F, ASSET_490_MODEL_GNAWTY_BOULDER = 0x490, @@ -3781,12 +3893,12 @@ typedef enum asset_e ASSET_4FE_MODEL_WHIPCRACK_PART_1 = 0x4FE, ASSET_4FF_MODEL_WHIPCRACK_PART_2 = 0x4FF, ASSET_500_MODEL_WHIPCRACK_PART_3 = 0x500, - // 501 CCW Mound Of Acorns + ASSET_501_MODEL_MOUND_OF_ACORNS = 0x501, ASSET_502_MODEL_NABNUT = 0x502, - // 503 Nabnut (Belly Full) + ASSET_503_MODEL_NABNUT_BELLY_FULL = 0x503, ASSET_504_MODEL_ICECUBE = 0x504, ASSET_505_MODEL_ICECUBE_CHUNK = 0x505, - // 506 CCW Dead Snarebear (Venus Flytrap) + ASSET_506_CCW_DEAD_SNAREBEAR = 0x506, ASSET_507_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_1 = 0x507, ASSET_508_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_2 = 0x508, ASSET_509_MODEL_GL_SARCOPHAGUS = 0x509, @@ -3809,28 +3921,28 @@ typedef enum asset_e ASSET_51C_MODEL_SCARAB_BEETLE_PART_1 = 0x51C, // 51d SCARAB BEETLE PART (Wing) ASSET_51E_MODEL_SCARAB_BEETLE_PART_2 = 0x51e, - ASSET_51F_MODEL_SCARAB_BEETLE_PART_3 = 0x51F, - ASSET_520_MODEL_SCARAB_BEETLE_PART_4 = 0x520, - ASSET_521_MODEL_PORTRAIT_CHOMPA = 0x521, - ASSET_522_MODEL_PORTRAIT_OF_GRUNTY = 0x522, - ASSET_523_MODEL_PORTRAIT_CHOMPA_TEETH = 0x523, - ASSET_524_MODEL_PORTRAIT_CHOMPA_HEAD = 0x524, - ASSET_525_MODEL_PORTRAIT_CHOMPA_PART = 0x525, - ASSET_526_SPRITE_FIRE = 0x526, - ASSET_527_MODEL_PORTRAIT_OF_BLACKEYE = 0x527, - ASSET_528_MODEL_PORTRAIT_OF_TOWER = 0x528, - ASSET_529_MODEL_PORTRAIT_OF_TREE_AND_MOON = 0x529, - ASSET_52A_MODEL_PORTRAIT_OF_TEEHEE = 0x52A, - ASSET_52B_MODEL_PORTRAIT_OF_MINION = 0x52B, - ASSET_52C_MODEL_GRUBLIN_HOOD = 0x52C, - ASSET_52D_MODEL_GRUBLIN_HOOD_HAT = 0x52D, - ASSET_52E_MODEL_CCW_SEASON_DOOR = 0x52E, - ASSET_52F_MODEL_BANJOS_CHAIR = 0x52F, - ASSET_530_MODEL_BANJOS_BED = 0x530, - // 531 Gnawty's Den - ASSET_532_MODEL_BANJO_KAZOOIE_CUTSCENES = 0x532, // (Gameboy/Beer/Sunglasses/Chair) - // 533 CCW Nabnut's Door - ASSET_534_MODEL_FLIGHT_PAD_SWITCH = 0x534, + ASSET_51F_MODEL_SCARAB_BEETLE_PART_3, + ASSET_520_MODEL_SCARAB_BEETLE_PART_4, + ASSET_521_MODEL_PORTRAIT_CHOMPA, + ASSET_522_MODEL_PORTRAIT_OF_GRUNTY, + ASSET_523_MODEL_PORTRAIT_CHOMPA_TEETH, + ASSET_524_MODEL_PORTRAIT_CHOMPA_HEAD, + ASSET_525_MODEL_PORTRAIT_CHOMPA_PART, + ASSET_526_SPRITE_FIRE, + ASSET_527_MODEL_PORTRAIT_OF_BLACKEYE, + ASSET_528_MODEL_PORTRAIT_OF_TOWER, + ASSET_529_MODEL_PORTRAIT_OF_TREE_AND_MOON, + ASSET_52A_MODEL_PORTRAIT_OF_TEEHEE, + ASSET_52B_MODEL_PORTRAIT_OF_MINION, + ASSET_52C_MODEL_GRUBLIN_HOOD, + ASSET_52D_MODEL_GRUBLIN_HOOD_HAT, + ASSET_52E_MODEL_CCW_SEASON_DOOR, + ASSET_52F_MODEL_BANJOS_CHAIR, + ASSET_530_MODEL_BANJOS_BED, + ASSET_531_MODEL_GNAWTYS_DEN, + ASSET_532_MODEL_BANJO_KAZOOIE_CUTSCENES, // (Gameboy/Beer/Sunglasses/Chair) + ASSET_533_MODEL_NABNUT_DOOR, + ASSET_534_MODEL_FLIGHT_PAD_SWITCH, // 535 Flight Pad Blue Fragment // 536 Flight Pad Red Fragment // 537 Flight Pad Yellow Fragment @@ -3855,40 +3967,40 @@ typedef enum asset_e ASSET_54A_MODEL_GRUNTLING_RED = 0x54A, // 54b (Big Fireball?) ASSET_54C_MODEL_GAME_OVER = 0x54C, - ASSET_54D_MODEL_BANJO_KAZOOIE_SIGN = 0x54D, - ASSET_54E_MODEL_COPYRIGHT_OVERLAY = 0x54E, - ASSET_54F_MODEL_CHEATO = 0x54F, - ASSET_550_MODEL_LARGE_DOOR_TO_FINAL_BATTLE = 0x550, - ASSET_551_MODEL_JINJONATOR = 0x551, - ASSET_552_MODEL_BROOMSTICK_PIECE_HEAD = 0x552, - ASSET_553_MODEL_BROOMSTICK_PIECE_SHORT = 0x553, - ASSET_554_MODEL_BROOMSTICK_PIECE_LONG = 0x554, - ASSET_555_MODEL_BROOMSTICK_PIECE_EYE = 0x555, - ASSET_556_MODEL_YELLOW_JINJO_BLAST = 0x556, - ASSET_557_MODEL_ORANGE_JINJO_BLAST = 0x557, - ASSET_558_MODEL_GREEN_JINJO_BLAST = 0x558, - ASSET_559_MODEL_PINK_JINJO_BLAST = 0x559, - ASSET_55A_MODEL_WORLD_EXIT_PAD = 0x55A, - ASSET_55B_MODEL_BOGGY_IGLOO = 0x55B, - ASSET_55C_MODEL_PRESS_START_OVERLAY = 0x55C, - ASSET_55D_MODEL_NO_CONTROLLER_OVERLAY = 0x55D, - ASSET_55E_MODEL_NAPPER = 0x55E, - ASSET_55F_MODEL_FF_PRIZE_WASHING_CAULDRON = 0x55F, - ASSET_560_MODEL_FF_PRIZE_GRUNTY_DOLL = 0x560, - ASSET_561_MODEL_GRUNTLING_BLUE = 0x561, - ASSET_562_MODEL_GRUNTLING_BLACK = 0x562, - ASSET_563_MODEL_LEVEL_ENTRY_SIGNS = 0x563, - ASSET_564_MODEL_PURPLE_TEEHEE = 0x564, - ASSET_565_MODEL_BOTTLES_BONUS_BANJO_HAND = 0x565, - ASSET_566_MODEL_BLACK_SNIPPET = 0x566, - ASSET_567_MODEL_BLACK_CRAB_HEAD = 0x567, - ASSET_568_MODEL_BLACK_CRAB_LEG = 0x568, - ASSET_569_MODEL_BLACK_CRAB_CLAW = 0x569, - ASSET_56A_MODEL_FP_HOUSE_CHIMNEY = 0x56A, - ASSET_56B_MODEL_SANDYBUTT_PYRAMID = 0x56B, - ASSET_56C_MODEL_THE_END_SIGN = 0x56C, - ASSET_56D_MUMBOS_HAND_WITH_PICTURE = 0x56D, // Mumbo's Hand with SNS pictures - // 56E Hammerhead Beach Scenery + ASSET_54D_MODEL_BANJO_KAZOOIE_SIGN, + ASSET_54E_MODEL_COPYRIGHT_OVERLAY, + ASSET_54F_MODEL_CHEATO, + ASSET_550_MODEL_LARGE_DOOR_TO_FINAL_BATTLE, + ASSET_551_MODEL_JINJONATOR, + ASSET_552_MODEL_BROOMSTICK_PIECE_HEAD, + ASSET_553_MODEL_BROOMSTICK_PIECE_SHORT, + ASSET_554_MODEL_BROOMSTICK_PIECE_LONG, + ASSET_555_MODEL_BROOMSTICK_PIECE_EYE, + ASSET_556_MODEL_YELLOW_JINJO_BLAST, + ASSET_557_MODEL_ORANGE_JINJO_BLAST, + ASSET_558_MODEL_GREEN_JINJO_BLAST, + ASSET_559_MODEL_PINK_JINJO_BLAST, + ASSET_55A_MODEL_WORLD_EXIT_PAD, + ASSET_55B_MODEL_BOGGY_IGLOO, + ASSET_55C_MODEL_PRESS_START_OVERLAY, + ASSET_55D_MODEL_NO_CONTROLLER_OVERLAY, + ASSET_55E_MODEL_NAPPER, + ASSET_55F_MODEL_FF_PRIZE_WASHING_CAULDRON, + ASSET_560_MODEL_FF_PRIZE_GRUNTY_DOLL, + ASSET_561_MODEL_GRUNTLING_BLUE, + ASSET_562_MODEL_GRUNTLING_BLACK, + ASSET_563_MODEL_LEVEL_ENTRY_SIGNS, + ASSET_564_MODEL_PURPLE_TEEHEE, + ASSET_565_MODEL_BOTTLES_BONUS_BANJO_HAND, + ASSET_566_MODEL_BLACK_SNIPPET, + ASSET_567_MODEL_BLACK_CRAB_HEAD, + ASSET_568_MODEL_BLACK_CRAB_LEG, + ASSET_569_MODEL_BLACK_CRAB_CLAW, + ASSET_56A_MODEL_FP_HOUSE_CHIMNEY, + ASSET_56B_MODEL_SANDYBUTT_PYRAMID, + ASSET_56C_MODEL_THE_END_SIGN, + ASSET_56D_MUMBOS_HAND_WITH_PICTURE, // Mumbo's Hand with SNS pictures + ASSET_56E_HAMMERHEAD_BEACH_SCENERY, // Credits map // 56F Unused // 570 Unused // Unused @@ -4730,7 +4842,7 @@ typedef enum asset_e ASSET_DA6_DIALOG_BEEHIVE_WITH_BEES = 0xDA6, ASSET_DA7_DIALOG_MUMBO_CCW_SUMMER = 0xDA7, ASSET_DA8_DIALOG_MUMBO_CCW_AUTUMN = 0xDA8, - + ASSET_DA9_DIALOG_MUMBO_CCW_VACATION = 0xDA9, ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS = 0xDAA, ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS = 0xDAB, ASSET_DAC_DIALOG_MUMBO_FAIL_TO_BUY = 0xDAC, @@ -4809,14 +4921,20 @@ typedef enum asset_e ASSET_F5D_DIALOG_MUMBO_MAGIC_RUN_OUT_FULL = 0xF5D, ASSET_F5E_DIALOG_MUMBO_MAGIC_RUN_OUT_ABREV = 0xF5E, - ASSET_F64_DIALOG_NOTEDOORS_LEARN = 0xf64, - ASSET_F65_DIALOG_NOTEDOORS_REFRESHER = 0xF65, - ASSET_F66_DIALOG_UNKNOWN = 0xF66, - ASSET_F67_DIALOG_UNKNOWN = 0xF67, + ASSET_F64_DIALOG_NOTEDOORS_LEARN = 0xF64, + ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, + ASSET_F66_DIALOG_UNKNOWN, + ASSET_F67_DIALOG_UNKNOWN, + ASSET_F68_DIALOG_MM_THREE_NEW_MOVES_TO_LEARN, + + ASSET_F6E_DIALOG_DIDNT_LEARN_ALL_MOVES_FROM_MM = 0xF6E, - ASSET_F79_DIALOG_UNKNOWN = 0xf79, - ASSET_F7A_DIALOG_UNKNOWN = 0xF7A, - ASSET_F7B_DIALOG_BOTTLES_JIGSAW_PICTURE_MEET = 0xF7B, + ASSET_F79_DIALOG_UNKNOWN = 0xF79, + ASSET_F7A_DIALOG_UNKNOWN, + ASSET_F7B_DIALOG_BOTTLES_JIGSAW_PICTURE_MEET, + + ASSET_F7F_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_BEFORE_PODIUM = 0xF7F, + ASSET_F80_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_AFTER_PODIUM, ASSET_FA8_EGG_CHEAT_ACTIVATION = 0xFA8, ASSET_FA9_RED_FEATHER_CHEAT_ACTIVATION = 0xFA9, @@ -5285,6 +5403,7 @@ typedef enum asset_e ASSET_1514_MODEL_GL_FF_ENTRANCE_XLU = 0x1514, ASSET_1515_MODEL_GL_BATTLEMENTS_XLU, + // [port] JP-exclusive sprites for world name banners SPRITE_WORLD_NAME_TOTAL = 0x1600, SPRITE_WORLD_NAME_SPIRAL_MOUNTAIN, SPRITE_WORLD_NAME_GRUNTILDAS_LAIR, @@ -5335,8 +5454,8 @@ enum marker_e{ MARKER_13_SNIPPET = 0x13, MARKER_14_SNACKER, MARKER_15_CLAM, - - MARKER_17_CONCERT_BANJO = 0x17, + MARKER_16_UNKNOWN, // src/core2/code_4BE10.c + MARKER_17_CONCERT_BANJO, MARKER_1B_CONCERT_TOOTY = 0x1B, MARKER_1C_INTRO_N64_CUBE, @@ -5359,8 +5478,8 @@ enum marker_e{ MARKER_32_PLAYER_SHADOW, MARKER_33_LEAKY, MARKER_34_CEMETARY_POT, - - MARKER_36_ORANGE_COLLECTIBLE = 0x36, + MARKER_35_CLIMB_BASE, + MARKER_36_ORANGE_COLLECTIBLE, MARKER_37_GOLD_BULLION, MARKER_38_TURBO_TALON_TRAINERS, MARKER_39_MUMBO_TOKEN, @@ -5384,8 +5503,8 @@ enum marker_e{ MARKER_53_EMPTY_HONEYCOMB, MARKER_55_HONEYCOMB = 0x55, - - MARKER_57_STEAM = 0x57, + MARKER_56_UNKNOWN, + MARKER_57_STEAM, MARKER_58_WADING_BOOTS_TOUCH_SPARKLE, MARKER_59_TURBO_TRAINERS_TOUCH_SPARKLE, MARKER_5A_JINJO_BLUE, @@ -5430,8 +5549,8 @@ enum marker_e{ MARKER_99_TEEHEE = 0x99, MARKER_9A_1881_BARREL_TOP, - - MARKER_9C_SHACK_DOOR = 0x9C, + MARKER_9B_MODEL_PLAYER_SHADOW, + MARKER_9C_SHACK_DOOR, MARKER_9D_MANSION_DOOR, MARKER_9E_CELLAR_HATCH, MARKER_9F_CHURCH_GATE_LEFT_LOCK, @@ -5462,7 +5581,7 @@ enum marker_e{ MARKER_B8_MOLEHILL, MARKER_B9_FP_SNOWMAN_BUTTON, MARKER_BA_XMAS_TREE, - MARKER_BB_UNKNOWN, + MARKER_BB_JINXY_HEAD_SANDYBUTT, MARKER_BC_GOBI_1, MARKER_BD_GOBI_ROPE, MARKER_BE_GOBI_ROCK, @@ -5593,7 +5712,7 @@ enum marker_e{ MARKER_167_SHARKFOOD_ISLAND, MARKER_168_ICE_KEY, MARKER_169_SNS_EGG, - // 0x16A src/core2/code_4C020.c + MARKER_16A_FF_TELEPORT_PAD, // src/core2/code_4C020.c MARKER_16B_SNIPPET_UPSIDEDOWN = 0x16B, MARKER_16C_NIPPER, MARKER_16D_CHEATO_1, @@ -5610,13 +5729,13 @@ enum marker_e{ MARKER_178_NO_CONTROLLER_OVERLAY, MARKER_179_JIGSAW_PUZZLE, MARKER_17A_BOTTLES_BONUS_BANJO_HAND, - - MARKER_17C_MODEL_THE_END_SIGN = 0x17C, + MARKER_17B_UNKNOWN, + MARKER_17C_MODEL_THE_END_SIGN, MARKER_17D_IRON_GATE_NO_LOCK, MARKER_182_RBB_EGG_TOLL = 0x182, - MARKER_183_RBB_EGG_TOLL, - MARKER_184_RBB_EGG_TOLL, + MARKER_183_RBB_CAGE_UP_SWITCH, + MARKER_184_RBB_TNT_DOWN_SWITCH, MARKER_185_RBB_REAR_PROPELLER, MARKER_186_RBB_GREEN_PROPELLER_SWITCH, MARKER_187_RBB_SPINNING_SINGLE_PIPE_1, @@ -5636,6 +5755,7 @@ enum marker_e{ MARKER_195_WHISTLE_SWITCH_1, MARKER_196_WHISTLE_SWITCH_2, MARKER_197_WHISTLE_SWITCH_3, + MARKER_198_RAREWARE_FLAG, MARKER_19A_TIPTUP = 0x19A, MARKER_19B_CHOIR_TURTLE_YELLOW, @@ -5653,33 +5773,49 @@ enum marker_e{ MARKER_1A7_CLANKER_WHIPCRACK, MARKER_1A9_CC_BREAKABLE_GRATES = 0x1A9, - - MARKER_1AC_ZUBBA_DOOR = 0x1AC, - + MARKER_1AA_BELL_BUOY, + MARKER_1AB_ROWBOAT, + MARKER_1AC_ZUBBA_DOOR, + MARKER_1AD_ZUBBA_HONEY_LUMP, MARKER_1AE_ZUBBA = 0x1AE, - + MARKER_1AF_ZUBBA_DOCILE, MARKER_1B0_CCW_BEANSTALK = 0x1B0, MARKER_1B1_CCW_GOBI, MARKER_1B2_CLUCKER_A, MARKER_1B3_EAGLE_EGG, MARKER_1B4_EEYRIE_BABY, MARKER_1B5_CATERPILLAR, - + MARKER_1B6_EEYRIE_ADULT, MARKER_1B7_BOOM_BOX = 0x1B7, - + MARKER_1B8_BOOM_BOX_MINIGAME_CTRL = 0x1B8, + MARKER_1B9_NABNUT_SPRING = 0x1B9, + MARKER_1BA_NABNUT_FULL_BELLY, MARKER_1BB_NABNUT = 0x1BB, - + MARKER_1BC_CARRIED_ACORN, + MARKER_1BD_GNAWTY_SWIMMING, + MARKER_1BE_GNAWTY_SUMMER, MARKER_1BF_GNAWTY_BOULDER = 0x1BF, + MARKER_1C0_BOSS_BOOMBOX_CTRL = 0x1C0, + MARKER_1C2_DEAD_BEANSTALK = 0x1C2, + MARKER_1C3_SNORE_Z, + MARKER_1C4_CUTSCENE_ADULT_EYRIE, MARKER_1C5_WHIPCRACK = 0x1C5, - + MARKER_1C6_MOUND_OF_ACORNS, + MARKER_1C7_PINK_SQUIRREL, + MARKER_1C8_NABNUT_BEDSHEETS, + MARKER_1C9_NABNUT_BED, + MARKER_1CA_NABNUT, + MARKER_1CB_NABNUT_EATING_ACORNS, + MARKER_1CC_CCW_UNKNOWN, MARKER_1CD_GV_MAZE_CTRL = 0x1CD, - + MARKER_1CE_INDOOR_GNAWTY, MARKER_1CF_GRILLE_CHOMPA_ATTACKING = 0x1CF, MARKER_1D0_CLUCKER_B, MARKER_1D1_PORTRAIT_CHOMPA_B, - - MARKER_1D4_SANDYBUTT_PYRAMID = 0x1D4, + MARKER_1D2_SPINNING_SINGLE_PIPE_SFX_CTRL, + MARKER_1D3_DOUBLE_SINGLE_PIPE_SFX_CTRL, + MARKER_1D4_SANDYBUTT_PYRAMID, MARKER_1D5_PALM_TREE, MARKER_1E0_BRENTILDA = 0x1E0, @@ -5702,6 +5838,7 @@ enum marker_e{ MARKER_1F2_WIDE_WINDOW, MARKER_1F3_TALL_WINDOW, MARKER_1F4_TOOTS, + MARKER_1F5_UNKNOWN, MARKER_1F9_SNARE_BEAR = 0x1F9, MARKER_1FA_POLAR_BEAR_CUB_BLUE, @@ -5731,6 +5868,9 @@ enum marker_e{ MARKER_218_LIMBO, MARKER_219_MUMMUM, MARKER_21A_SEAMAN_GRUBLIN, + MARKER_21B_UNKNOWN, + + MARKER_21E_CCW_MUMBOS_HUT = 0x21E, MARKER_224_BREAKABLE_FLOOR_COBWEB = 0x224, MARKER_225_BREAKABLE_WALL_COBWEB, @@ -5762,12 +5902,12 @@ enum marker_e{ MARKER_240_LAIR_SWITCH_FLIGHT_PAD, MARKER_241_SHOCK_JUMP_PAD_SWITCH, MARKER_242_LAIR_SWITCH_SHOCK_JUMP_PAD, - + MARKER_243_NABNUT_DOOR, MARKER_244_DINGPOT = 0x244, MARKER_245_XMAS_TREE_EGG_TOLL = 0x245, MARKER_250_ICECUBE_A = 0x250, - + MARKER_251_DEAD_SNAREBEAR, MARKER_252_LOGGO = 0x252, MARKER_253_SCARAB_BEETLE, MARKER_254_PORTRAIT_CHOMPA_A, @@ -5793,11 +5933,12 @@ enum marker_e{ MARKER_268_STAIRS_1, MARKER_269_STAIRS_2, MARKER_26A_LIGHTHOUSE_B, - - // 0x26E src/core2/code_4C020.c - // 0x26F src/core2/code_4C020.c - - MARKER_270_TWO_ICE_POLES_NEAR_CHEATO_3 = 0x270, + MARKER_26B_GNAWTYS_DEN, + MARKER_26C_GNAWTYS_BED, + MARKER_26D_GNAWTYS_SHELVES, + MARKER_26E_UNKNOWN, // src/core2/code_4C020.c + MARKER_26F_UNKNOWN, // src/core2/code_4C020.c + MARKER_270_TWO_ICE_POLES_NEAR_CHEATO_3, MARKER_276_STONE_JINJO = 0x276, @@ -5817,7 +5958,8 @@ enum marker_e{ MARKER_288_GRUNTY_SHADOW = 0x288, - MARKER_295_GRUNTLING_BLUE = 0x295, + MARKER_294_MUMBOS_HAND_WITH_PICTURE = 0x294, + MARKER_295_GRUNTLING_BLUE, MARKER_296_TEEHEE_PURPLE, MARKER_297_GIANT_GRAVESTONE, MARKER_298_MUMMUM_BALL, @@ -5829,6 +5971,7 @@ enum marker_e{ MARKER_29E_BIGBUTT_KNOCKED_DOWN, MARKER_29F_DUMMY_PLAYER_ANCHOR, + MARKER_300_CUSTOM_COLLECTIBLE, }; enum hitbox_e{ diff --git a/include/file_and_line.h b/include/file_and_line.h index a931d6b5e..93f44d73f 100644 --- a/include/file_and_line.h +++ b/include/file_and_line.h @@ -1,8 +1,11 @@ #ifndef _FILE_AND_LINE_H_ #define _FILE_AND_LINE_H_ + #include -extern void __assert(const char *, const char *, int); +#if 0 +extern void __assert(const char *, const char *, int); +#endif #ifdef NONMATCHING #define LINE(line_num) __LINE__ @@ -10,18 +13,24 @@ extern void __assert(const char *, const char *, int); #define matching_assert(EX, F, L) assert(EX) #else #define LINE(line_num) line_num + #ifdef __ANSI_CPP__ - #define FILE(file_name) # file_name + #define FILE(file_name) #file_name #else #define FILE(file_name) "file_name" #endif +#if 0 #ifdef __ANSI_CPP__ - #define matching_assert(EX, F, L) ((EX)?((void)0):__assert( # EX , # F, L)) + #define matching_assert(EX, F, L) \ + ((EX) ? ((void)0) : __assert(#EX, #F, L)) #else - #define matching_assert(EX, F , L) ((EX)?((void)0):__assert("EX", "F", L)) + #define matching_assert(EX, F, L) \ + ((EX) ? ((void)0) : __assert("EX", "F", L)) #endif #endif - + #define matching_assert(EX, F, L) ((void)0) #endif + +#endif \ No newline at end of file diff --git a/include/functions.h b/include/functions.h index b6b8d686b..8222da5b3 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2,10 +2,18 @@ #define FUNCTIONS_H #include +#include "string.h" +#include "math.h" + +#include "port/UI/cvar_prefixes.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#ifdef __cplusplus +extern "C" { +#endif #include "enums.h" #include "structs.h" -#include "string.h" #include "rand.h" #include "prop.h" @@ -21,22 +29,21 @@ #include "core2/staticcamera.h" #include "core2/anim/sprite.h" #include "core2/ba/anim.h" +#include "core2/ba/carry.h" +#include "core2/ba/drone.h" +#include "core2/lighting.h" +#include "core2/particle.h" #include "core2/ba/model.h" +#include "core2/ba/physics.h" #include "core2/ba/timer.h" #include "core2/nc/camera.h" +#include "core2/yaw.h" -#include "port/ShipUtils.h" -#include "port/UI/cvar_prefixes.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include "math.h" #include "bk_time.h" #include "bs_funcs.h" #include "bsint.h" #include "generic.h" -#include - // FuncUnk40 defined in core2/commonParticle.h — forward-typedef here to avoid circular include #ifndef FUNCUNK40_DEFINED #define FUNCUNK40_DEFINED @@ -60,13 +67,14 @@ extern f32 fabsf(f32); f32 cosf(f32); -// --- core2/prop_assetcache.c --- +// --- core2/propModelList.c --- BKModelBin *propModelList_getModelIfActive(s32 arg0); BKSpriteDisplayData *propModelList_getSpriteDisplayList(s32 arg0); BKSprite *propModelList_getSprite(s32 arg0); BKModelBin *propModelList_getModel(s32); // --- core2/actor_cubepropsystem.c --- +BKModelBin *marker_loadModelBin(ActorMarker *marker); ActorMarker *func_8032DCAC(void); BKVertexList *func_80330CFC(Actor *self, s32 arg1); BKModelBin *func_80330E28(Actor *self); @@ -87,7 +95,7 @@ void marker_setActorUpdateFunc(ActorMarker *marker, ActorUpdateFunc method); void marker_setCollisionScripts(ActorMarker *marker, MarkerCollisionFunc ow_func, MarkerCollisionFunc arg2, MarkerCollisionFunc die_func); void marker_setFreeMethod(ActorMarker *, void (*)(Actor *)); -// --- core2/actor_cubebounds.c --- +// --- core2/gccube.c --- NodeProp *cubeList_findNodePropByActorIdAndPosition_s32(enum actor_e actor_id, s32 position[3]); NodeProp *func_80305510(s32 arg0); BKCollisionTriangle *func_80303800(f32 volume_p1[3], f32 volume_p2[3], f32 arg2[3], u32 arg3); @@ -107,10 +115,7 @@ u8 GetCurrentMap(); s32 getGameMode(void); void transitionToMap(enum map_e map, s32 exit, s32 transition); -// --- core2/time.c --- -f32 time_getDelta(void); - -// --- core2/map_list.c --- +// --- core2/map/list.c --- BKCollisionTriangle *func_8029463C(void); BKModelBin *func_802946A8(void); BKCollisionTriangle *func_802946CC(void); @@ -123,7 +128,7 @@ BKCollisionTriangle *func_8031C5F4(struct0 *self); BKModelBin *func_8031C5DC(struct0 *self); struct0 *func_8031B9D8(void); -// --- core2/collision/funcs.c --- +// --- core2/collision/dispatch.c --- BKCollisionTriangle *func_80320B98(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3); // func_80320C94, func_80320DB0 return BKCollisionTriangle* but // have conflicting local externs (bool/s32/int) in decomp source files. @@ -154,6 +159,8 @@ Actor *marker_getActor(ActorMarker *); Actor *marker_getActorAndRotation(ActorMarker *marker, f32 rotation[3]); Actor *subaddie_getLinkedActor(Actor *); ActorMarker *func_8032B16C(enum jiggy_e jiggy_id); +ActorMarker *actorArray_findHoneycombMarkerById(enum honeycomb_e id); +ActorMarker *actorArray_findMumboTokenMarkerById(enum mumbotoken_e id); bool func_80329078(Actor *, s32, s32); bool func_80329480(Actor *); bool subaddie_maybe_set_state_position_direction(Actor *, s32, f32, s32, f32 ); @@ -192,12 +199,6 @@ struct56s *func_80343F00(s32 indx, f32 arg1[3]); Struct83s *func_803406B0(void); Struct83s *func_803406D4(Struct83s *self); -// --- core2/vtx/list.c --- - -// --- core2/spline_bezier.c --- - -// --- core2/model/render.c --- - // --- core2/vtx/colorapply.c --- Struct70s *func_8034C344(s32 arg0); Struct70s *func_8034C448(s32 arg0); @@ -241,8 +242,8 @@ BoneTransformList *anim_getStartTransform(Animation *self); BoneTransformList *anim_getTargetTransform(Animation *self); // --- core1/audio_manager.c --- -void *func_802403B8(void *state); -void *audioManager_getThread_PAL(void); +ALDMAproc audioManager_DMAInitProc(void *state); +OSThread *audioManager_getThread_PAL(void); // --- core2/anim/anim_sequencehandler.c --- u8 *func_8032479C(void); @@ -261,20 +262,12 @@ f32 babuzz_80290890(f32 arg0); f32 babuzz_80290920(f32 arg0, f32 arg1, f32 arg2); f32 baeyes_getEyePosition(s32 id); f32 baanim_getTimer(void); -f32 batimer_get(s32 id); f32 bafalldamage_get_distance_fallen(void); f32 bastick_calculateZonePosition(f32 arg0, f32 arg1, f32 arg2); f32 bastick_getX(void); f32 bastick_getAngle(void); f32 baModel_getYaw(void); -f32 baphysics_get_gravity(void); -f32 baphysics_get_target_horizontal_velocity(void); -f32 baphysics_get_target_vertical_velocity(void); -f32 baphysics_get_target_yaw(void); -f32 baphysics_get_vertical_velocity(void); -f32 baphysics_get_horizontal_velocity(void); -f32 baphysics_get_horizontal_velocity_percentage(void); -f32 climbGetRadius(void); +f32 climb_getRadius(void); f32 func_8029B3B0(f32 arg0); f32 func_8029B56C(f32 arg0, f32 arg1, f32 arg2, f32 arg3); f32 func_8029B9C0(void); @@ -301,7 +294,7 @@ f32 player_getYaw(void); // Only functions that return pointers or have no conflicting local externs. NodeProp *cube_findNodePropByActorId(Cube *cube, enum actor_e actor_id); -// --- core2/camera/cameranodelist.c --- +// --- core2/nc/cameranodelist.c --- PivotCameraNode *ncCameraNodeList_getPivotCameraNode(int camera_node_index); StaticCameraNode *ncCameraNodeList_getStaticCameraNode(int camera_node_index); ZoomCameraNode *ncCameraNodeList_getZoomCameraNode(int camera_node_index); @@ -309,34 +302,61 @@ RandomCameraNode *ncCameraNodeList_getRandomCameraNode(int camera_node_index); // MISC POINTER-RETURNING + OS + GBI PROTOTYPES -s16 *func_8030C704(void); +s16 *picturebox_getColorBuffer(void); // COMMONLY MISSING PROTOTYPES -// --- core2/fx/score_jiggy.c --- +// --- core2/jiggyscore.c --- u32 jiggyscore_isCollected(enum jiggy_e jiggy_id); int jiggyscore_isSpawned(enum jiggy_e jiggy_id); -// --- core2/fx/score_honeycomb.c --- +// --- core2/honeycombscore.c --- bool honeycombscore_get(enum honeycomb_e indx); -// --- core2/map/specificflags.c --- +// --- core2/map/mapspecificflags.c --- s32 mapSpecificFlags_get(s32 i); void mapSpecificFlags_set(s32, s32); +void mapSpecificFlags_setEx(s32 i, s32 val, s32 triggerEvent); -// --- core2/level/specificflags.c --- +// --- core2/level/levelspecificflags.c --- s32 levelSpecificFlags_get(s32 i); void levelSpecificFlags_set(s32, s32); +void levelSpecificFlags_setEx(s32 index, s32 val, s32 triggerEvent); +void levelSpecificFlags_getSizeAndPtr(s32 *size, u8 **addr); // --- core2/gameloop.c --- s32 getGameMode(void); void transitionToMap(enum map_e map, s32 exit, s32 transition); -// --- core2/gamestate.c (item system) --- +// --- core2/gamestate.c --- s32 item_empty(enum item_e item); void item_set(s32 item, s32 val); +void item_setEx(s32 item, s32 val, s32 triggerEvent); // --- core2/game_complete.c --- +enum AnchorFlagSpace { + ANCHOR_FLAGSPACE_FILE_PROGRESS = 0, + ANCHOR_FLAGSPACE_VOLATILE = 1, + ANCHOR_FLAGSPACE_LEVEL_SPECIFIC = 2, + ANCHOR_FLAGSPACE_MAP_SPECIFIC = 3, + ANCHOR_FLAGSPACE_RANDO_INF = 4, +}; +enum AnchorCollectibleSpace { + ANCHOR_COLLECTIBLE_JIGGY = 0, + ANCHOR_COLLECTIBLE_HONEYCOMB = 1, + ANCHOR_COLLECTIBLE_MUMBO = 2, + ANCHOR_COLLECTIBLE_NOTE = 3, + ANCHOR_COLLECTIBLE_JINJO = 4, + ANCHOR_COLLECTIBLE_WORM = 5, + ANCHOR_COLLECTIBLE_ACORN = 6, + ANCHOR_COLLECTIBLE_PRESENT_BLUE = 7, + ANCHOR_COLLECTIBLE_PRESENT_GREEN = 8, + ANCHOR_COLLECTIBLE_PRESENT_RED = 9, + ANCHOR_COLLECTIBLE_GOLD = 10, + ANCHOR_COLLECTIBLE_ORANGE = 11, +}; + +// --- core2/flags_bitfield.c --- bool fileProgressFlag_get(enum file_progress_e index); s32 fileProgressFlag_getN(enum file_progress_e offset, s32 numBits); s32 volatileFlag_get(enum volatile_flags_e index); @@ -345,9 +365,11 @@ s32 volatileFlag_getN(enum volatile_flags_e index, s32 numBits); void fileProgressFlag_setN(enum file_progress_e, s32, s32); void volatileFlag_set(enum volatile_flags_e index, s32 set); void volatileFlag_setN(enum volatile_flags_e startIndex, s32 set, s32 length); +void fileProgressFlag_setEx(enum file_progress_e index, s32 set, s32 triggerEvent); +void volatileFlag_setEx(enum volatile_flags_e index, s32 set, s32 triggerEvent); -// --- core2/dialog/progress_dialogs.c --- -void volatileFlag_setAndTriggerDialog_0(enum volatile_flags_e arg0); +// --- core2/dialog/progressDialog.c --- +void progressDialog_setAndTriggerDialog_0(enum volatile_flags_e arg0); // --- core1/init.c --- s32 globalTimer_getTime(void); @@ -360,14 +382,14 @@ void subaddie_set_ideal_yaw(Actor *self, int arg1); bool subaddie_playerIsWithinSphere(Actor *self, s32 dist); Actor *actor_spawnWithYaw_s32(enum actor_e id, s32 (*pos)[3], s32 rot); -// --- core2/actor_cubebounds.c --- +// --- core2/gccube.c --- bool nodeProp_findPositionFromActorId(enum actor_e actor_id, f32 *arg1); // --- core2/ba/ba_lookdir.c --- enum bsgroup_e player_movementGroup(void); enum hitbox_e player_getActiveHitbox(ActorMarker *marker); bool player_isDead(void); -bool func_8028F20C(void); +bool player_isStableWithExtraSteps(void); s32 func_8028F66C(enum bs_interrupt_e arg0); void func_8028F8F8(s32 arg0, bool arg1); void func_8028F918(s32 arg0); @@ -395,7 +417,8 @@ void func_8030E0FC(u8, f32, f32, f32); void sfxSource_func_8030E2C4(u8); void sfxSource_func_8030E2C4(u8 indx); void func_8030E4E4(enum sfx_e uid); -void gcsfx_playAtSampleRate(enum sfx_e uid); +void gcsfx_playAtSampleRate(enum sfx_e uid, s32 sample_rate); +void gcsfx_play(enum sfx_e uid); void func_8030E560(enum sfx_e uid, s32 arg1); void func_8030E58C(enum sfx_e uid, f32 arg1); void func_8030E5F4(enum sfx_e uid, f32 arg1); @@ -421,7 +444,7 @@ void sfxsource_setSfxId(u8 indx, enum sfx_e uid); void sfxsource_set_fade_distances(u8, f32, f32); void sfxsource_set_position(u8, f32[3]); -// --- core2/camera/camera_motor1.c --- +// --- core2/nc/camera_motor1.c --- void gcStaticCamera_activate(s32 arg0); bool func_802BB270(void); @@ -430,13 +453,13 @@ void func_803114D0(void); int gcdialog_hasCurrentTextId(void); bool gcdialog_showDialog(s32 text_id, s32 arg1, f32 *pos, ActorMarker *marker, void(*callback)(ActorMarker *, enum asset_e, s32), void(*arg5)(ActorMarker *, enum asset_e, s32)); -// --- core2/cutscene/lair.c --- +// --- core2/map/cutscene_skip.c --- void func_8031CD20(NodeProp *arg0, s32 arg1, s32 arg2); // --- core2/collision/polydetect.c --- void func_80340690(Struct83s *self); -// --- core2/actor_cubebounds.c --- +// --- core2/gccube.c --- bool func_803077FC(f32 arg0[3], s32 *arg1, s32 *arg2, s32 arg3, u32 arg4); bool func_80305C30(s32 arg0); bool func_80308F54(s32 cube_index); @@ -454,54 +477,54 @@ bool func_80331158(ActorMarker *arg0, f32 *arg1, f32 *arg2); // --- core2/ba/ba_lookdir.c --- bool func_8028F280(void); -// --- core2/ba/ba_anim.c --- +// --- core2/ba/anim.c --- bool baanim_isStopped(void); bool baanim_isAnimID(enum asset_e anim_id); AnimCtrl *baanim_getAnimCtrlPtr(void); bool baanim_isAt(f32); void baanim_playForDuration_loopSmooth(enum asset_e anim_id, f32 duration); -void baanim_playForDuration_loopStartingAt(enum asset_e anim_id, f32, f32); -void baanim_playForDuration_once(enum asset_e anim_id, f32 duration); -void baanim_playForDuration_onceSmooth(enum asset_e, f32); -void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f32 arg2); +void baanim_playForDuration_loopSmoothStartingAt(enum asset_e anim_id, f32, f32); +void baanim_playForDuration_onceSmooth(enum asset_e anim_id, f32 duration); +void baanim_playForDuration_once(enum asset_e, f32); +void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 arg2); void baanim_scaleDuration(f32); void baanim_setDurationRange(f32, f32); void baanim_setEnd(f32); void baanim_setEndAndDuration(f32, f32); void baanim_setVelocityMapRanges(f32, f32, f32, f32); -// --- core2/ba/ba_groundsurface.c --- +// --- core2/ba/hazards.c --- bool isOnFloor(void); bool isPlayerInHazard(void); bool canTakeGroundDamage(void); -// --- core2/ba/ba_animstate.c --- -bool func_8029DFE0(void); -f32 func_8029DFC8(void); -f32 func_8029DFD4(void); -void func_8029E090(bool, f32); -void func_8029E0C4(f32); -void func_8029E0D0(f32); -bool func_8029DFBC(void); -bool func_8029DFA4(void); -bool func_8029DFB0(void); -bool func_8029DFEC(void); - -// --- core2/ba/ba_carriedobj.c --- +// --- core2/ba/modelappendages.c --- +bool modelAppendages_hideTurboTrainers(void); +f32 modelAppendages_showBanjosLeftEye(void); +f32 modelAppendages_showBanjosRightEye(void); +void modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(bool, f32); +void modelAppendages_setBanjosLeftEyeVisibility(f32); +void modelAppendages_setBanjosRightEyeVisibility(f32); +bool modelAppendages_showKazooiesUpperHalf(void); +bool modelAppendages_showKazooiesAss(void); +bool modelAppendages_showKazooiesFeetAndShoes(void); +bool modelAppendages_hideWadingBoots(void); + +// --- core2/ba/carriedobj.c --- bool player_setCarryObjectPose(enum actor_e actor_id, Actor **arg1); -// --- core2/camera/camera_nodemanager.c --- +// --- core2/nc/camera_nodemanager.c --- bool func_802BB720(s32 arg0, f32 arg1[3], f32 arg2[3], s32 *arg3); bool func_802BB884(f32 arg0[3], f32 *arg1); bool func_802BC428(void); -// --- core2/camera/camera_fog.c --- +// --- core2/nc/camera_fog.c --- bool func_802BEF64(void); -// --- core2/camera/camera_focus.c --- +// --- core2/nc/camera_focus.c --- bool func_802BAC1C(void); -// --- core2/camera/dynamicCamera.c --- +// --- core2/nc/dynamicCamera.c --- bool func_802BC640(f32 arg0[3], f32 arg1[3], f32 arg2, s32 arg3); bool func_802BCE0C(f32 arg0[3], f32 arg1[3]); f32 func_802BD8D4(void); @@ -509,21 +532,21 @@ void func_802BD8A4(f32, f32, f32); void func_802BE230(f32, f32); void func_802BE244(f32, f32); -// --- core2/camera/dynamicCam12.c --- +// --- core2/nc/dynamicCam12.c --- bool __is_flying_in_FP(void); bool func_802C189C(void); -// --- core2/camera/dynamicCam13.c --- +// --- core2/nc/dynamicCam13.c --- bool func_802C0640(void); -// --- core2/camera/dynamicCamA.c --- +// --- core2/nc/dynamicCamA.c --- bool ncDynamicCamA_func_802C1EE0(void); bool ncDynamicCamA_func_802C1DB0(f32); -// --- core2/camera/firstpersoncamera.c --- -bool __ncFirstPersonCamera_fullyZoomedIn(void); +// --- core2/nc/1p.c --- +bool __ncba1p_fullyZoomedIn(void); -// --- core2/collision/funcs.c --- +// --- core2/collision/dispatch.c --- void func_80320B24(void *arg0, void *arg1, void *arg2); void func_80320B44(void *arg0, void *arg1, void *arg2, void *arg3); @@ -534,37 +557,32 @@ f32 func_80294438(void); f32 floor_getCurrentFloorYPosition(void); void func_80293D48(f32, f32); -// --- core2/spline_bezier.c --- - -// --- core2/vtx/list.c --- - // --- core2/spline_pathfollow.c --- void func_80343DEC(Actor *self); -// --- core2/model/render.c --- - -// --- core2/spawn_queue.c --- -void __spawnQueue_add_0(void (*arg0)(void)); -void __spawnQueue_add_2(void (*arg0)(void), uintptr_t arg1, uintptr_t arg2); +// --- core2/spawnqueue.c --- Actor *spawnQueue_actor_f32(enum actor_e actor_id, uintptr_t x, uintptr_t y, uintptr_t z); +Actor *spawnQueue_actor_s32(uintptr_t actor_id, uintptr_t x, uintptr_t y, uintptr_t z); +Actor *spawnQueue_actor_s16(uintptr_t actor_id, uintptr_t x, uintptr_t y, uintptr_t z); +void __spawnQueue_add_0(GenFunction_0); void __spawnQueue_add_1(GenFunction_1, uintptr_t); -#define SPAWNQUEUE_ADD_1(method, arg0) __spawnQueue_add_1((GenFunction_1) (method), reinterpret_cast(uintptr_t, (arg0))) +void __spawnQueue_add_2(GenFunction_2, uintptr_t, uintptr_t); +void __spawnQueue_add_3(GenFunction_3, uintptr_t, uintptr_t, uintptr_t); void __spawnQueue_add_4(GenFunction_4, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +void __spawnQueue_add_5(GenFunction_5, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +#define SPAWNQUEUE_ADD_1(method, arg0) __spawnQueue_add_1((GenFunction_1) (method), reinterpret_cast(uintptr_t, (arg0))) -// --- core2/sprite/displaydata.c --- +// --- core2/fx/commonParticle.c --- void commonParticle_add(ActorMarker *arg0, s32 arg1, FuncUnk40 arg2); int commonParticle_new(enum common_particle_e particle_id, int arg1); // --- core2/particle/particle.c --- void particleEmitter_setModel(ParticleEmitter *self, enum asset_e model_id); -void particleEmitter_setSfx(ParticleEmitter *self, enum sfx_e sfx_id, s32 arg2); -void particleEmitter_setAlpha(ParticleEmitter *self, s32 arg1); void particleEmitter_setVelocityAccelerationAndPositionRanges(ParticleEmitter *self, ParticleSettingsVelocityAccelerationPosition *settings); void func_802EFC28(ParticleEmitter *self, ParticleSettingsScaleAndLifetimeDrawModeEmitCount *settings); ParticleEmitter *partEmitMgr_defragEmitter(ParticleEmitter *); ParticleEmitter *partEmitMgr_newEmitter(u32); ParticleEmitter *particleEmitter_new(u32 capacity); -void particleEmitter_func_802EFA20(ParticleEmitter *, f32, f32); void func_802EFF50(ParticleEmitter *, f32); void particleEmitter_emitInVolume(ParticleEmitter *, f32[3], f32[3], s32); void particleEmitter_emitN(ParticleEmitter *, int); @@ -592,7 +610,7 @@ void particleEmitter_update(ParticleEmitter *self); void particleEmitter_setVelocityAndAccelerationRanges(ParticleEmitter *, ParticleSettingsVelocityAcceleration *); // --- core2/quiz/game.c --- -void func_802D68F0(s32 seconds); +void code_4C020_setHourglassTimer(s32 seconds); void func_802D4A9C(Actor *self, s32 arg1); void func_802D4AC0(Actor *self, s32 arg1, enum file_progress_e arg2); void func_802D6264(f32, enum map_e, s32, s32, s32, enum file_progress_e); @@ -611,32 +629,32 @@ void coMusicPlayer_playMusic(enum comusic_e, s32); // --- core1/stopnswop.c --- bool sns_get_item_state(enum StopNSwop_Item item, s32 set); -// --- FP/mapstate/slalom.c --- +// --- FP/ma/slalom.c --- bool maSlalom_isActive(void); // --- FP/ch/boggy2.c --- bool func_8038A1A0(ActorMarker *marker); -// code3B10_checkGVChecksums omitted: decomp defines as (void) but callers pass Actor* - // --- CC/model_renderstate.c --- +void code13C0_checkCCChecksums(void); void CC_func_80387D4C(void); // OS function prototypes extern uintptr_t osVirtualToPhysical(void *addr); extern void *osPhysicalToVirtual(uintptr_t addr); -// GBI function prototypes (implementations in src/port/stub.c) +// GBI function prototypes void gSPSegment(void* value, int segNum, uintptr_t target); void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target); void gSPDisplayList(Gfx* pkt, Gfx* dl); void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset); void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0); +void gSPVertexSeg(Gfx* pkt, u32 seg, uintptr_t off, int n, int v0); void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr); int ResourceMgr_OTRSigCheck(char* imgData); -// --- BGS/actor_spawninit.c --- -void BGS_func_8038F1E0(void); +// --- BGS/bgsspawnqueue.c --- +void bgs_updateSpawnableActors(void); // --- BGS/ch/croctus.c --- void BGS_func_803885DC(void); @@ -648,14 +666,14 @@ void func_8038CEA0(void); void func_8038CEB8(void); // --- BGS/ch/mrvile.c --- -bool BGS_func_8038C338(ActorMarker *marker); -bool func_8038C2A8(ActorMarker *marker); -void BGS_func_8038C434(ActorMarker *marker); -void BGS_func_8038C460(ActorMarker *arg0); -void func_8038C384(ActorMarker *marker); -void func_8038C3B0(ActorMarker *marker); -void func_8038C3DC(ActorMarker *marker); -void func_8038C408(ActorMarker *marker); +bool chMrVile_isInitialIdle(ActorMarker *marker); +bool chMrVile_playerWithinRange(ActorMarker *marker); +void chMrVile_setStateRunFromPlayer(ActorMarker *marker); +void chMrVile_setInitialIdleStill(ActorMarker *arg0); +void chMrVile_setStateAttackPlayer(ActorMarker *marker); +void chMrVile_setStateTalkToPlayer(ActorMarker *marker); +void chMrVile_setStatePlayMinigame(ActorMarker *marker); +void chMrVile_setStateIdleWalking(ActorMarker *marker); // --- BGS/ch/mudhut.c --- void chMudHut_checkBGSChecksums(void); @@ -664,66 +682,71 @@ void chMudHut_checkBGSChecksums(void); void func_8038F51C(Actor *self); // --- BGS/ch/tiptup.c --- -s32 func_80388E70(ActorMarker *self); void chTiptup_choirHitReaction(ActorMarker *self, s32 arg1); +s32 chTiptup_getUnkB(ActorMarker *self); void func_80388FFC(ActorMarker *self, s32 *arg1, f32* arg2); // --- BGS/ch/yumblie.c --- bool chyumblie_is_edible(ActorMarker * arg0); bool func_8038B684(ActorMarker * arg0); -// --- BGS/minigame_vile.c --- -bool chvilegame_cpu_consume_piece(ActorMarker *marker, f32 position[3]); -s32 chvilegame_get_piece_count(ActorMarker *marker); -s32 chvilegame_get_score_difference(ActorMarker *marker); -s32 func_8038A9E0(ActorMarker *marker); -void chvilegame_new_piece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type); +// --- BGS/mrvileminigame.c --- +bool chMrVileMinigame_mrVileConsumePiece(ActorMarker *marker, f32 position[3]); +s32 chMrVileMinigame_getPieceCount(ActorMarker *marker); +s32 chMrVileMinigame_getScoreDifference(ActorMarker *marker); +s32 chMrVileMinigame_getDialogIndex(ActorMarker *marker); +void chMrVileMinigame_newPiece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type); void chvilegame_remove_piece(ActorMarker *game_marker, ActorMarker *piece_marker); -// --- CC/actor_spawninit.c --- +// --- CC/ccspawnqueue.c --- void CC_func_80387DA0(void); // --- CC/ch/clankertoothext.c --- void CC_func_803870E0(void); void func_803870EC(s32 arg0); -// --- CC/minigame_rings.c --- -void func_803880D4(void); -void func_80388104(void); -void func_8038817C(void); +// --- CC/ma/clankerrings.c --- +void maClankerRings_release(void); +void maClankerRings_init(void); +void maClankerRings_update(void); -// --- CC/platform_physics.c --- +// --- CC/ma/clanker.c --- int CC_func_80388CA0(void); -void CC_func_8038868C(void); -void CC_func_80388760(Gfx **gfx, Mtx **mtx, Vtx **vtx); +void maClanker_raiseClankerCutscene(void); +void maClanker_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void CC_func_80388F4C(void); void func_80388B4C(f32 arg0[3]); void func_80388B78(f32 arg0[3], f32 arg1[3]); void func_80388BBC(f32 arg0[3], f32 arg1[3]); void func_80388CB4(void); void func_80388D54(void); -void func_80388ED4(s32 arg0); -void func_803894A0(void); - -// --- CCW/actor_spawninit.c --- +void maClanker_playScrewNoise(s32 arg0); +void maClanker_defrag(void); +void maClanker_release(void); +void maClanker_init(void); +void maClanker_update(void); +s32 maClankerRings_isMinigameActive(void); +void maClankerRings_passRing(s32); + +// --- CCW/ccwspawnqueue.c --- void CCW_func_8038DB6C(void); -// --- CCW/ch/nabnut_winter.c --- -void func_8038BC50(f32 dst[3]); +// --- CCW/nabnut_winter.c --- +void chAutumnOutsideNabnut_getPosition(f32 dst[3]); -// --- CCW/ch/eyrie_baby.c --- +// --- CCW/eyrie_baby.c --- void func_80389BD8(f32 dst[3]); -// --- CCW/flower.c --- -bool func_80388438(); -void func_803883F4(); +// --- CCW/ch/beanstalk.c --- +bool chCCWBeanstalk_hasSpawned(); +void chCCWBeanstalk_growBeanstalk(); -// --- CCW/minigame_zubba.c --- -void func_803867C8(ActorMarker *marker); -void func_80386814(ActorMarker *marker); -void func_80386840(ActorMarker *marker, s32 *score, s32 *total); +// --- CCW/ch/zubbahoneylump.c --- +void chZubbaFight_zubbaKilled(ActorMarker *marker); +void chZubbaFight_zubbaDisappear(ActorMarker *marker); +void chZubbaFight_zubbaScore(ActorMarker *marker, s32 *score, s32 *total); -// --- FP/actor_spawninit.c --- +// --- FP/fpspawnqueue.c --- void FP_func_80391324(void); // --- FP/ch/boggy2.c --- @@ -735,7 +758,7 @@ void chTwinkly_decideShatterColor(f32 position[3], enum marker_e marker_id); // --- FP/ch/twinklybox.c --- bool preventSnowmanAttack(ActorMarker *marker); -// --- FP/mapstate/slalom.c --- +// --- FP/ma/slalom.c --- bool maSlolam_WithinRadiusOfBoggy(f32 position[3], s32 radius); void maSlalom_end(); void maSlalom_init(void); @@ -748,25 +771,25 @@ void maSlalom_start(void); void maSlalom_unlinkBoggy(void); void maSlalom_update(void); -// --- FP/mapstate/snowbutton.c --- +// --- FP/ma/snowbutton.c --- void maSnowButton_decRemaining(void); void maSnowButton_end(void); void maSnowButton_init(void); void maSnowButton_update(void); -// --- FP/mapstate/snowy.c --- +// --- FP/ma/snowy.c --- void maSnowy_decRemaining(void); void maSnowy_end(void); void maSnowy_incTotal(void); void maSnowy_init(void); void maSnowy_update(void); -// --- FP/ch/wozza_fire.c --- +// --- FP/wozza_fire.c --- void func_803918C0(void); void func_8039195C(void); void func_80391994(void); -// --- GV/actor_spawninit.c --- +// --- GV/gvspawnqueue.c --- s32 code7FF0_getMagicCarpetState(Actor *arg0, s32 arg1); void GV_func_8038F154(void); @@ -786,10 +809,10 @@ bool chGobiRock_isDestroyed(void); // --- GV/ch/grabba.c --- s32 GV_func_8038C5BC(void); -// --- GV/ch/handshadow.c --- +// --- GV/handshadow.c --- void func_8038C748(void); -// --- GV/ch/jinxy_head.c --- +// --- GV/jinxy_head.c --- int func_8038E344(ActorMarker *this_marker); void func_8038E2FC(ActorMarker *this_marker); @@ -809,8 +832,8 @@ void gv_matchingGame_init(void); void gv_matchingGame_reset(void); void gv_matchingGame_update(void); -// --- GV/pyramid_trigger.c --- -int func_8038D388(void); +// --- GV/sandybutteggtoll.c --- +bool func_8038D388(void); // --- GV/water_pyramidactivate.c --- void func_803900F8(void); @@ -827,7 +850,7 @@ void gv_waterCtrl_end(void); void gv_waterCtrl_init(void); void gv_waterCtrl_update(void); -// --- MM/actor_spawninit.c --- +// --- MM/mmspawnqueue.c --- void MM_func_803888B0(void); // --- MM/ch/hut.c --- @@ -843,13 +866,13 @@ void func_803892A8(ActorMarker **ptr); // --- MM/ch/jujuhitbox.c --- void chjujuhitbox_setJuju(Actor *self, s32 slave_id, Actor *slavePtr); -// --- MMM/actor_spawninit.c --- +// --- MMM/mmmspawnqueue.c --- void MMM_func_803890E0(void); // --- MMM/organ_tiles.c --- void func_8038B5D8(Struct5Fs *arg0, Struct68s *arg1, s32 arg2, s32 arg3); -// --- MMM/ch/flowerpot.c --- +// --- MMM/ch/cemetarypot.c --- bool chFlowerpot_eggCollision(ActorMarker *marker); void chFlowerpot_reset(); @@ -891,7 +914,7 @@ void func_80389544(void); void func_803895B0(s32 arg0); void func_8038966C(void); -// --- RBB/actor_spawninit.c --- +// --- RBB/rbbspawnqueue.c --- void RBB_func_80386C48(void); // --- RBB/ch/eggtoll1.c --- @@ -901,8 +924,8 @@ void func_8038685C(ActorMarker *marker); s32 chWhistleCtrl_newEvent(Actor *self, s32 whistle_id, Actor *other); // --- RBB/miniboombox_container.c --- -void func_8038FB54(void); -void func_8038FB6C(void); +void chBoomBoxMinigameCtrl_countInc(void); +void chBoomBoxMinigameCtrl_countDec(void); // --- RBB/propellorctrl.c --- void rbb_propellorCtrl_reset(void); @@ -912,7 +935,7 @@ void rbb_propellorCtrl_update(void); // --- SM/quarrie_honeycomb.c --- bool codeBF0_shouldSpawnQuarrieHoneyComb(ActorMarker *marker); -// --- SM/crc.c --- +// --- SM/smspawnqueue.c --- void SM_resetSpawnableActors(); void codeF0_breakAbilitiesIfChecksumsFail(); @@ -931,7 +954,7 @@ void chTreasurehunt_resetProgress(void); // --- TTC/crc.c --- void code3040_checkTTCChecksums(void); -// --- TTC/castle.c --- +// --- TTC/ma/castle.c --- bool maCastle_hasBanjoKazooieCodeBeenEntered(void); bool maCastle_isSecretCheatCodeRelatedValueEqualToScrambledAddressValue(); void maCastle_init(void); @@ -953,10 +976,10 @@ void musicInstruments_init(void); // --- core1/musicplayer.c --- int func_8025AEEC(void); -s32 comusic_active_track_count(void); +s32 coMusicPlayer_getTrackCount(void); s32 func_8025ADD4(enum comusic_e id); -void comusicPlayer_free(void); -void comusicPlayer_init(void); +void coMusicPlayer_free(void); +void coMusicPlayer_init(void); void comusic_defrag(void); void func_8025A23C(s32 arg0); void func_8025A2B0(void); @@ -980,7 +1003,7 @@ void func_80244814(void *arg0); void func_80244978(intptr_t arg0, s16 type, s32 arg2); void func_80244A98(s32 arg0); -// --- core1/io/ba_motor.c --- +// --- core1/bamotor.c --- void baMotor_80250C08(void); void baMotor_80250FC0(void); void baMotor_init(void); @@ -995,18 +1018,14 @@ void func_802451A4(f32 arg0[3], f32 arg1[3], f32 arg2[3], f32 arg3[3], f32 arg4[ // --- core1/debugtext.c --- s32 gcdebugText_isThreadLocked(void); -void func_80247F24(s32 arg0, s32 arg1); +void gcdebugText_showLargeValue(s32 arg0, s32 arg1); void func_80247F9C(s32 arg0); void gcdebugText_pauseThread(void); -// --- core1/defragmanager.c --- -void defragManager_free(void); -void defragManager_init(void); - -// --- core1/math/mlmtx.c --- +// --- core1/gu_perspective.c --- void _guMtxF2L(float mf[4][4], Mtx *m); -// --- core1/inflate.c --- +// --- boot/inflate.c --- int bk_inflate(void); // --- core1/initthread.c --- @@ -1028,9 +1047,6 @@ void func_80255A04(void); void func_80255A14(void); void func_80255ACC(void); -// --- core1/ml.c --- -void func_802596AC(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); - // --- core1/mlmtx.c --- void func_802515D4(f32 arg0[3][3]); @@ -1067,6 +1083,7 @@ void ability_setAllLearned(s32 val); void ability_setAllUsed(s32 val); void ability_setHasUsed(enum ability_e move); void ability_setLearned(s32 move, s32 val); +void ability_setLearnedEx(s32 move, s32 val, s32 triggerEvent); void ability_use(s32 arg0); // --- core2/actor_array.c --- @@ -1100,6 +1117,8 @@ void func_803268B4(void); void func_80326C24(s32 arg0); void func_803283BC(void); void func_803283D4(void); +void port_actorDespawn_beginDefer(void); +void port_actorDespawn_endDefer(void); void func_80328CA8(Actor *self, s32 angle); void func_803297FC(Actor *arg0, f32 *o1, f32 *o2); s32 func_80329904(ActorMarker *arg0, s32 arg1, f32 *arg2); @@ -1119,7 +1138,7 @@ void func_8032BC18(Actor *self); void func_8032BC60(Actor *self, s32 arg1, f32 arg2[3]); void subaddie_set_state_looped(Actor * self, u32 arg1); -// --- core2/actor_cubebounds.c --- +// --- core2/gccube.c --- bool func_80305248(f32 arg0[3], s32 arg1, f32 *arg2); bool func_8030526C(f32 arg0[3], s32 arg1, f32 *arg2); bool func_80305290(bool (* arg0)(NodeProp *), bool (* arg1)(Prop *)); @@ -1136,7 +1155,7 @@ s32 func_80307164(s32 arg0[3]); s32 func_80307258(f32 arg0[3], s32 arg1, s32 arg2); s32 nodeprop_getRadius(NodeProp *arg0); s32 nodeprop_getScale(NodeProp *nodeProp); -u32 nodeprop_getYaw(NodeProp *nodeProp); +u32 nodeProp_getYaw(NodeProp *nodeProp); void code7AF80_freeTotalCounts(void); void cubeList_defrag(); void cubeList_free(); @@ -1161,9 +1180,9 @@ void spawnableActorList_new(void); // --- core2/actor_cubepropsystem.c --- s32 actor_getAnimatedTexturesCacheId(Actor *actor); -s32 codeA5BC0_getNodePropBit6(NodeProp *arg0); -s32 codeA5BC0_getNodePropUnk8(NodeProp *arg0); -s32 codeA5BC0_getNodePropUnkA(NodeProp *arg0); +s32 codeA5BC0_getNodePropCategory(NodeProp *arg0); +s32 codeA5BC0_getNodePropActorId(NodeProp *arg0); +s32 codeA5BC0_getNodePropMarkerId(NodeProp *arg0); s32 codeA5BC0_getNodePropUnkC(NodeProp *arg0); s32 func_8032E49C(Cube *cube, enum actor_e *actor_id_list, NodeProp **node_list, s32 node_list_capacity); s32 func_8032E5A8(Cube *cube, s32 arg1, f32 (*arg2)[3], s32 capacity); @@ -1177,7 +1196,7 @@ void cube_sortAbsolute(Cube *cube); void cube_sortRelative(Cube *cube); void func_8032D3A8(void); void func_8032D3D8(Gfx **gdl, Mtx **mptr, Vtx **vptr); -void func_8032D474(Gfx **gdl, Mtx **mptr, Vtx **vptr); +void core2_A5BC0_drawScreenOverlayMarkers(Gfx **gdl, Mtx **mptr, Vtx **vptr); void func_8032E070(void); void func_8032EE2C(s32 arg0[3], s32 arg1, s32 arg2); void func_8032EE80(Cube *cube); @@ -1215,7 +1234,7 @@ void func_80296CC0(f32 arg0[3]); // --- core2/scorequeue/queue_timers.c --- bool func_802FCD98(struct8s *arg0); -// --- core2/ambient_fish.c --- +// --- SM/ch/ambient_fish.c --- void func_803500D8(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_803500E8(void); void func_80350174(void); @@ -1244,7 +1263,7 @@ void anim_resetSmooth(Animation *self); void anim_setIndex(Animation *self, enum asset_e arg1); void anim_update(Animation *self); -// --- core2/anim/anim_cache.c --- +// --- core2/anim/animcache.c --- bool animCache_inUse(s16 index); s16 animCache_getNew(void); void animCache_defrag(void); @@ -1260,14 +1279,7 @@ void func_80361E10(Actor *self); void func_80361E9C(Actor *self); void func_80361EE0(Actor *self); -// --- core2/anim/anim_texturecache.c --- -bool AnimTextureListCache_tryGetTextureOffset(s32 list_index, s32 texture_index, s32 *current_frame); -s32 AnimTextureListCache_newList(void); -void AnimTextureListCache_setAnimTextureList(s32 arg0, BKAnimTextureList *bk_anim_texture_list); -void AnimTextureListCache_free(void); -void AnimTextureListCache_freeList(s32 arg0); -void AnimTextureListCache_init(void); -void AnimTextureListCache_update(void); +// --- core2/anim/animtexturecache.c --- // --- core2/anim/bonetransformlist.c --- void boneTransformList_getBoneScale(BoneTransformList *self, s32 bone_id, f32 scale[3]); @@ -1277,7 +1289,7 @@ void func_8033A6B0(BoneTransformList *self, s32 bone_id, f32 arg2[3]); void func_8033A8F0(BoneTransformList *self, s32 bone_id, f32 arg2[4]); void func_8033A968(BoneTransformList *self, s32 bone_id, f32 arg2[3]); -// --- core2/anim_sequence.c --- +// --- core2/anim/anseq.c --- void anSeq_free(void **ppAnSeq); void anSeq_setActivationFrameDelay(void **ppAnSeq, s32 arg1); void anSeq_update(void **ppAnSeq, AnimCtrl *pAnCtl); @@ -1292,13 +1304,15 @@ void func_803353F4(intptr_t arg0, s32 arg1); void func_80335418(intptr_t arg0, s32 arg1); void sfxInstruments_init(void); -// --- core2/ba/ba_anim.c --- +// --- core2/ba/anim.c --- void baAnim_defrag(void); void baAnim_free(void); void baAnim_init(void); void baAnim_update(void); void baanim_80289F30(void); enum baanim_update_type_e baanim_getUpdateType(void); +void baanim_applyBottlesBonusMask(uintptr_t arg0, s32 mask); +s32 baanim_getActiveBottlesBonusMask(void); void baanim_setModifyMethod(void (*arg0)(uintptr_t, uintptr_t)); void baanim_setUpdateType(enum baanim_update_type_e arg0); @@ -1307,50 +1321,44 @@ void animBinCache_free(void); void animBinCache_init(void); void animBinCache_update(void); -// --- core2/ba/ba_animstate.c --- -void func_8029DD6C(void); -void func_8029DFF8(void); -void func_8029E058(bool); -void func_8029E064(bool); -void func_8029E070(bool); -void func_8029E0DC(bool); -void func_8029E0E8(bool); -void func_8029E0F4(bool); -void func_8029E100(void); - -// --- core2/ba/ba_bounds.c --- +// --- core2/ba/modelappendages.c --- +void modelAppendages_loadAppendage(void); +void modelAppendages_reset(void); +void modelAppendages_setKazooiesAssVisibility(bool); +void modelAppendages_setKazooiesFeetAndShoesVisibility(bool); +void modelAppendages_setKazooiesUpperHalfVisibility(bool); +void modelAppendages_setTurboTrainersVisibility(bool); +void modelAppendages_setSledVisibility(bool); +void modelAppendages_setWadingBootsVisibility(bool); +void modelAppendages_kazooiesUpperHalfVisibilityTimer(void); + +// --- core2/ba/babounds.c --- void babounds_init(void); void babounds_update(void); -// --- core2/ba/ba_buzz.c --- +// --- core2/ba/babuzz.c --- void babuzz_release(void); void babuzz_reset(void); -// --- core2/ba/ba_carriedobj.c --- +// --- core2/ba/carriedobj.c --- void bacarriedobj_dec(enum actor_e actor_id); void bacarriedobj_displayOnHud(enum actor_e actor_id); void bacarriedobj_inc(enum actor_e actor_id); void bacarriedobj_spawn(enum actor_e actor_id); +void bacarriedobj_incWithExtraSteps(enum actor_e actor_id); +void bacarriedobj_decWithExtraSteps(enum actor_e actor_id); +void bacarriedobj_displayOnHudWithExtraSteps(enum actor_e actor_id); void func_8028DEEC(enum actor_e actor_id, Actor *actor); -// --- core2/ba/ba_carry.c --- -void bacarry_end(void); -void bacarry_init(void); -void bacarry_reset_marker(void); -void bacarry_set_marker(ActorMarker *arg0); -void bacarry_update(void); - -// --- core2/ba/ba_scripted.c --- +// --- core2/ba/drone.c --- enum bs_e badrone_802926E8(void); -enum bs_e badrone_enter(void); enum bs_e badrone_look(void); enum bs_e badrone_transform(void); enum bs_e badrone_vanish(void); -void badrone_get_position_and_duration(f32 position[3], f32 *duration); void badrone_goto_end(void); void badrone_init(void); -// --- core2/ba/ba_eyeblink.c --- +// --- core2/ba/iFrame.c --- s32 baiFrame_getState(void); void baiFrame_reset(void); void baiFrame_start(void); @@ -1369,13 +1377,13 @@ void func_802C7478(Actor *actor); void func_802C75A0(Actor *actor, s32 arg1); void func_802C79C4(void); -// --- core2/ba/ba_eyes.c --- +// --- core2/ba/baeyes.c --- void baeyes_close(void); void baeyes_open(void); void baeyes_reset(void); void baeyes_update(void); -// --- core2/ba/ba_falldamage.c --- +// --- core2/ba/falldamage.c --- s32 bafalldamage_get_damage(s32 *damage); s32 bafalldamage_get_state(void); void bafalldamage_init(void); @@ -1388,7 +1396,7 @@ void func_80350BC8(void); void func_80350BFC(void); void func_80350CA4(void); -// --- core2/ba/ba_groundsurface.c --- +// --- core2/ba/hazards.c --- void freeHazardSfxId(void); void hazards_reset(void); void hazards_update(void); @@ -1403,7 +1411,7 @@ void func_80290298(void); // --- core2/ba/ba_hitbox.c --- enum hitbox_e hitbox_getHitboxForActor(ActorMarker *arg0); -// --- core2/ba/ba_input.c --- +// --- core2/ba/bainput.c --- int bainput_isEnabled(s32 arg0); int bainput_should_beak_barge(void); int bainput_should_beak_bust(void); @@ -1428,7 +1436,7 @@ s32 func_80291660(void); void func_80291590(void); void func_802915B8(void); -// --- core2/ba/ba_key.c --- +// --- core2/ba/bakey.c --- int bakey_getAndSetState(s32 button_indx, s32 val); int bakey_releaseCount(s32 button_indx); int bakey_released(s32 button_indx); @@ -1436,7 +1444,7 @@ void bakey_disableAll(s32 arg0); void bakey_reset(void); void bakey_update(void); -// --- core2/ba/ba_lookat.c --- +// --- core2/ba/balookat.c --- int balookat_try_get_position(f32 arg0[3]); s32 balookat_getState(void); void balookat_init(void); @@ -1451,9 +1459,9 @@ bool func_8028EFC8(void); bool func_8028EFEC(void); bool func_8028F070(void); bool func_8028F098(void); -bool func_8028F0D4(void); +bool player_isBanjoOrWishywashy(void); bool func_8028F150(void); -bool func_8028F170(void); +bool player_isInFirstPersonView(void); bool func_8028F1E0(void); bool func_8028F25C(void); bool func_8028F2A0(void); @@ -1467,16 +1475,16 @@ bool func_8028F530(s32 arg0); bool func_8028F55C(s32 arg0, ActorMarker *marker); bool func_8028F590(s32 arg0, ActorMarker *marker); bool func_8028F5F8(f32 arg0[3]); -bool func_8028FB88(enum transformation_e xform_id); +bool player_transform(enum transformation_e xform_id); bool func_8028FBD4(f32 arg0[3]); bool player_is_in_jiggy_jig(void); bool player_is_present(void); bool player_throwCarriedObject(void); enum actor_e carriedObj_getActorId(void); enum bswatergroup_e player_getWaterState(void); -enum marker_e bacarry_get_markerId(void); +enum marker_e bacarry_getMarkerId(void); f32 func_8028EC64(f32 arg0[3]); -int ability_isUnlocked(enum ability_e uid); +bool ability_isUnlocked(enum ability_e uid); int func_8028EC04(void); s32 func_8028E4A4(void); s32 func_8028F68C(enum bs_interrupt_e arg0, ActorMarker *marker); @@ -1513,7 +1521,7 @@ void player_getVelocity(f32 dst[3]); void player_setIdealRotation(f32 rotation[3]); void player_setRotation(f32 rotation[3]); -// --- core2/ba/ba_marker.c --- +// --- core2/ba/marker.c --- bool baMarker_isCollidable(void); enum actor_e baMarker_getCarriedObjectActorId(void); s32 baMarker_8028D688(void); @@ -1527,7 +1535,7 @@ void baMarker_init(void); void baMarker_setCarriedObject(enum actor_e actor_id); void baMarker_update(void); -// --- core2/ba/ba_model.c --- +// --- core2/ba/model.c --- void assetcache_release(void *); enum asset_e baModel_getModelId(void); s32 baModel_isVisible(void); @@ -1546,14 +1554,16 @@ void baModel_getPosition(f32* dst); void baModel_reset(void); void baModel_setEnvAlpha(s32 alpha); void baModel_setPostDraw(void (*draw_func)(Gfx **gfx, Mtx **mtx, Vtx **vtx)); -void baModel_setVisible(s32 arg0); void baModel_update(void); void baModel_updateModel(void); -// --- core2/ba/ba_modelselect.c --- +// --- core2/ba/playermodel.c --- s32 func_802985F0(void); void func_802986D0(void); void func_80298700(void); +void playerModel_set(void); +void playerModel_free(void); +enum asset_e playerModel_get(void); // --- core2/ba/ba_momentum.c --- void func_8029065C(void); @@ -1567,7 +1577,7 @@ void func_8032196C(void); void func_803219A8(void); void func_803219F4(s32 arg0); -// --- core2/ba/ba_position.c --- +// --- core2/ba/playerposition.c --- void playerPosition_init(void); void playerPosition_func_8029842C(void); void playerPosition_func_80298464(f32 arg0[3]); @@ -1575,7 +1585,8 @@ void playerPosition_func_80298504(f32 arg0[3]); void playerPosition_getOffset(f32 arg0[3]); void playerPosition_setOffset(f32 arg0[3]); void playerPosition_applyOffset(void); -void player_setPosition(f32 arg0[3]); +void playerPosition_set(f32 arg0[3]); +void player_setWarpDestination(f32 position[3], f32 yaw, s32 exit_id); // --- core2/ba/ba_recoil.c --- enum asset_e func_80294974(void); @@ -1593,7 +1604,7 @@ void get_throw_target_position(f32 dst[3]); void set_talk_target_position(f32 src[3]); void set_throw_target_position(f32 src[3]); -// --- core2/ba/ba_sfx.c --- +// --- core2/ba/basfx.c --- void basfx_80299AAC(void); void basfx_80299BD4(void); void basfx_80299DB8(void); @@ -1606,7 +1617,7 @@ void basfx_free(void); void basfx_reset(void); void basfx_update(void); -// --- core2/ba/ba_sfxintensity.c --- +// --- core2/ba/ba_camera.c --- void cameraMode_update(void); void func_80290B6C(void); void func_80291488(s32 arg0); @@ -1614,8 +1625,8 @@ void func_802914CC(s32 arg0); void func_8029151C(s32 arg0); void func_80291548(void); -// --- core2/ba/ba_state.c --- -void func_80295914(void); +// --- core2/ba/bsmethods.c --- +void bsmethods_reset(void); void func_80295B04(void); void func_80295C08(void (* arg0)(void)); void func_80295C14(void); @@ -1632,7 +1643,7 @@ void func_8032320C(void); void func_80323230(void); void func_80323238(void); -// --- core2/ba/ba_stick.c --- +// --- core2/ba/bastick.c --- void bastick_lockAtzero(bool arg0); void bastick_reset(void); void bastick_resetZones(void); @@ -1648,34 +1659,29 @@ void func_802992F0(void); void func_802993C8(void); void func_8029957C(s32 arg0); -// --- core2/ba/ba_timer.c --- -s32 batimer_decrement(s32 timer_id); -void batimer_incrementBy(s32 id, f32 inc_value_sec); -void batimer_set(s32 timer_id, f32 duration); - // --- core2/bs/ant.c --- int bsant_inSet(s32 move_indx); -// --- core2/bs/beak_barge.c --- +// --- core2/bs/bBarge.c --- s32 bsbbarge_hitboxActive(void); -// --- core2/bs/beak_bomb.c --- +// --- core2/bs/bFly.c --- int bsbfly_bombHitboxActive(void); int bsbfly_inSet(enum bs_e arg0); -// --- core2/bs/stilt_stride.c --- +// --- core2/bs/bLongLeg.c --- int bslongleg_inSet(s32 move_indx); -// --- core2/bs/beak_peck.c --- +// --- core2/bs/bPeck.c --- s32 bsbpeck_hitboxActive(void); -// --- core2/bs/beak_swim.c --- +// --- core2/bs/bSwim.c --- bool bsbswim_inSet(enum bs_e move_id); -// --- core2/bs/talon_trot.c --- +// --- core2/bs/bTrot.c --- int bsbtrot_inSet(s32 move_indx); -// --- core2/bs/beak_buster.c --- +// --- core2/bs/bbuster.c --- s32 bsbbuster_hitboxActive(void); s32 func_8029FC4C(void); void func_802A02B4(s32 arg0); @@ -1684,10 +1690,10 @@ void func_802A02B4(s32 arg0); void func_802A02C0(void); void func_802A0340(void); -// --- core2/bs/bee_fly.c --- +// --- core2/bs/beeFly.c --- int bsBeeFly_inSet(s32); -// --- core2/bs/bs_storedstate.c --- +// --- core2/bs/bsStoredState.c --- enum transformation_e bsStoredState_getTransformation(void); s32 bsStoredState_getTrotFlag(void); void bsStoredState_8029A924(void); @@ -1710,12 +1716,12 @@ void bscroc_set_ate_wrong_thing(void); // --- core2/bs/crouch.c --- enum bs_e func_802ADCD4(enum bs_e arg0); -// --- core2/bs/scripted.c --- +// --- core2/bs/drone.c --- void bsdrone_end(void); void bsdrone_init(void); void bsdrone_update(void); -// --- core2/bs/jiggy_dance.c --- +// --- core2/bs/jig.c --- int bsjig_inJiggyJig(enum bs_e state); void func_802B0CD8(void); @@ -1741,44 +1747,44 @@ void func_802B6FA8(void); // --- core2/bs/walrus.c --- int bswalrus_inSledSet(enum bs_e state); -// --- core2/camera/camera_ease.c --- +// --- core2/nc/camera_ease.c --- void func_802C2250(void); void func_802C2258(void); void func_802C22C0(f32 target_position[3], f32 target_rotation[3]); -// --- core2/camera/camera_focus.c --- +// --- core2/nc/camera_focus.c --- void func_802BABD8(void); void func_802BAC10(void); void func_802BAC58(void); -// --- core2/camera/camera_fog.c --- +// --- core2/nc/camera_fog.c --- void func_802BEE2C(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802BEF70(void); void func_802BEF78(void); void func_802BEFB0(void); -// --- core2/prop_assetcache.c --- +// --- core2/propModelList.c --- void propModelList_free(void); void propModelList_init(void); void propModelList_flush(s32 arg0); -// --- core2/camera/camera_motor1.c --- +// --- core2/nc/camera_motor1.c --- s32 func_802BB294(void); void func_802BAF20(void); void func_802BAF40(void); -// --- core2/camera/camera_motor2.c --- +// --- core2/nc/camera_motor2.c --- void func_802BB2A0(void); void func_802BB2A8(void); void func_802BB3C4(s32 arg0); void func_802BB41C(s32 arg0); void func_802BB4D8(f32 position[3], f32 rotation[3]); -// --- core2/camera/camera_nodemanager.c --- +// --- core2/nc/camera_nodemanager.c --- s32 ncCamera_getType(void); void camera_setType(enum camera_type_e camera_type); void func_802BBD0C(Gfx **gdl, Mtx **mptr, Vtx **vptr); -void func_802BBD2C(f32 *arg0, f32 *arg1); +void core2_34790_getClipDistances(f32 *arg0, f32 *arg1); void nccamera_init(void); void func_802BC10C(void); void func_802BC21C(s32 arg0, s32 arg1); @@ -1795,26 +1801,26 @@ s32 func_80322758(void); void func_80322764(void); void func_8032278C(s32 arg0, s32 arg1); -// --- core2/camera/camera_position.c --- +// --- core2/nc/camera_position.c --- void func_802BE940(void); -// --- core2/camera/camera_set.c --- +// --- core2/nc/camera_set.c --- void func_803525A0(f32 arg0[3]); -// --- core2/camera/cameranode_type1.c --- +// --- core2/nc/cameranode_type1.c --- bool code336F0_func_802BA87C(PivotCameraNode *self); bool code336F0_func_802BA89C(PivotCameraNode *self); bool code336F0_func_802BA8BC(PivotCameraNode *self); void code336F0_func_802BA7D8(PivotCameraNode *self, f32 arg1[3]); -// --- core2/camera/cameranode_type3.c --- +// --- core2/nc/cameranode_type3.c --- bool code33310_func_802BA4D0(ZoomCameraNode *self); bool code33310_func_802BA4F0(ZoomCameraNode *self); -// --- core2/camera/cameranode_type4.c --- +// --- core2/nc/cameranode_type4.c --- s32 code33250_func_802BA234(RandomCameraNode *self); -// --- core2/camera/cameranodelist.c --- +// --- core2/nc/cameranodelist.c --- s32 ncCameraNodeList_getNodeType(int camera_node_index); s32 ncCameraNodeList_nodeIsValid(int camera_node_index); void ncCameraNodeList_defrag(); @@ -1822,88 +1828,88 @@ void ncCameraNodeList_free(); void ncCameraNodeList_fromFile(File *file_ptr); void ncCameraNodeList_init(); -// --- core2/camera/dynamicCam1.c --- +// --- core2/nc/dynamicCam1.c --- void ncDynamicCam1_end(void); void ncDynamicCam1_init(void); void ncDynamicCam1_update(void); -// --- core2/camera/dynamicCam10.c --- +// --- core2/nc/dynamicCam10.c --- void ncDynamicCam10_end(void); void ncDynamicCam10_init(void); void ncDynamicCam10_update(void); -// --- core2/camera/dynamicCam11.c --- +// --- core2/nc/dynamicCam11.c --- void func_802BF798(s32 camera_node_index); void ncDynamicCam11_end(void); void ncDynamicCam11_init(void); void ncDynamicCam11_update(void); -// --- core2/camera/dynamicCam12.c --- +// --- core2/nc/dynamicCam12.c --- void dynamicCam12_init(void); void func_802C0F4C(void); void ncDynamicCam12_end(void); void ncDynamicCam12_update(void); -// --- core2/camera/dynamicCam13.c --- +// --- core2/nc/dynamicCam13.c --- void func_802C095C(void); void ncDynamicCam13_end(void); void ncDynamicCam13_init(void); void ncDynamicCam13_update(void); -// --- core2/camera/dynamicCam3.c --- +// --- core2/nc/dynamicCam3.c --- void ncDynamicCam3_end(void); void ncDynamicCam3_init(void); void ncDynamicCam3_update(void); -// --- core2/camera/dynamicCam4.c --- -void ncDynamicCam4_end(void); -void ncDynamicCam4_func_802BFE74(bool); -void ncDynamicCam4_init(void); -void ncDynamicCam4_update(void); +// --- core2/nc/fly.c --- +void ncbafly_end(void); +void ncbafly_func_802BFE74(bool); +void ncbafly_init(void); +void ncbafly_update(void); -// --- core2/camera/dynamicCam5.c --- +// --- core2/nc/dynamicCam5.c --- void ncDynamicCam5_end(void); void ncDynamicCam5_func_802BF590(f32 arg0[3]); void ncDynamicCam5_init(void); void ncDynamicCam5_update(void); -// --- core2/camera/dynamicCam8.c --- +// --- core2/nc/dynamicCam8.c --- void ncDynamicCam8_end(void); void ncDynamicCam8_func_802BF9B8(s32 arg0); void ncDynamicCam8_init(void); void ncDynamicCam8_update(void); -// --- core2/camera/dynamicCam9.c --- +// --- core2/nc/dynamicCam9.c --- void ncDynamicCam9_end(void); void ncDynamicCam9_init(void); void ncDynamicCam9_update(void); -// --- core2/camera/dynamicCamA.c --- +// --- core2/nc/dynamicCamA.c --- void ncDynamicCamA_end(void); void ncDynamicCamA_init(void); void ncDynamicCamA_update(void); -// --- core2/camera/dynamicCamB.c --- +// --- core2/nc/dynamicCamB.c --- void ncDynamicCamB_end(void); void ncDynamicCamB_init(void); void ncDynamicCamB_update(void); -// --- core2/camera/dynamicCamC.c --- +// --- core2/nc/dynamicCamC.c --- void ncDynamicCamC_end(void); void ncDynamicCamC_init(void); void ncDynamicCamC_update(void); -// --- core2/camera/dynamicCamD.c --- -void ncDynamicCamD_end(void); -void ncDynamicCamD_init(void); -void ncDynamicCamD_update(void); +// --- core2/nc/die.c --- +void ncbadie_end(void); +void ncbadie_init(void); +void ncbadie_update(void); -// --- core2/camera/dynamicCamF.c --- +// --- core2/nc/dynamicCamF.c --- void ncDynamicCamF_end(void); void ncDynamicCamF_init(void); void ncDynamicCamF_update(void); -// --- core2/camera/dynamicCamera.c --- +// --- core2/nc/dynamicCamera.c --- int func_802BE60C(void); int func_802BE834(f32 arg0[3]); int ncDynamicCamera_getState(void); @@ -1930,21 +1936,21 @@ void ncDynamicCamera_setState(s32 state); void ncDynamicCamera_setUpdateEnabled(bool arg0); void ncDynamicCamera_update(void); -// --- core2/camera/firstpersoncamera.c --- -s32 ncFirstPersonCamera_getState(void); -void ncFirstPersonCamera_getPositionAndRotation(f32 position[3], f32 rotation[3]); -void ncFirstPersonCamera_getZoomedInRotation(f32 dst[3]); -void ncFirstPersonCamera_reset(void); -void ncFirstPersonCamera_setState(enum nc_first_person_state state); -void ncFirstPersonCamera_setZoomedOutPosition(f32 src[3]); -void ncFirstPersonCamera_setZoomedOutRotation(f32 src[3]); +// --- core2/nc/1p.c --- +s32 ncba1p_getState(void); +void ncba1p_getPositionAndRotation(f32 position[3], f32 rotation[3]); +void ncba1p_getZoomedInRotation(f32 dst[3]); +void ncba1p_reset(void); +void ncba1p_setState(enum nc_first_person_state state); +void ncba1p_setZoomedOutPosition(f32 src[3]); +void ncba1p_setZoomedOutRotation(f32 src[3]); -// --- core2/camera/randomCamera.c --- +// --- core2/nc/randomCamera.c --- void ncRandomCamera_end(void); void ncRandomCamera_init(void); void ncRandomCamera_update(void); -// --- core2/camera/staticCamera.c --- +// --- core2/nc/staticCamera.c --- void ncStaticCamera_end(void); void ncStaticCamera_exit(void); void ncStaticCamera_getPosition(f32 dst[3]); @@ -1980,7 +1986,7 @@ s32 chBottlesBonusCursor_getState(void); void chBottlesBonusCursor_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void chBottlesBonusCursor_lose(void); -// --- core2/ch/drips.c --- +// --- core2/fx/drips.c --- void func_80359A40(f32 position[3], void *arg1, s32 cnt); // --- core2/ch/goldfeather.c --- @@ -1988,6 +1994,7 @@ void func_802D8BE4(bool gold_feather); // --- core2/ch/honeycomb.c --- enum honeycomb_e func_802CA1C4(Actor *self); +enum mumbotoken_e func_802E0CB0(Actor *self); void func_802CA1CC(enum honeycomb_e id); // --- core2/ch/jiggy.c --- @@ -1998,27 +2005,27 @@ void chjiggy_setJiggyId(Actor *self, u32 id); // --- core2/ch/jigsawdance.c --- void chJigsawDance_setState(Actor * self, u32 arg1); -// --- core2/ch/mmm_veggies.c --- +// --- cutscenes/cutscene_trigger.c --- void func_802CDAC4(Actor *); // --- core2/ch/mole.c --- int chmole_learnedAllLevelAbilities(enum level_e level); int chmole_learnedAllSpiralMountainAbilities(void); -// --- core2/ch/overlaycopyright.c --- +// --- core2/gc/overlaycopyright.c --- void chOverlayCopyright_func_802DCB0C(s32 arg0, s32 arg1); void chOverlayCopyright_spawn(s32 arg0, s32 arg1); -// --- core2/ch/overlaynocontroller.c --- +// --- core2/gc/overlaynocontroller.c --- void chOverlayNoController_func_802DD040(s32 arg0, s32 arg1); void chOverlayNoController_spawn(s32 arg0, s32 arg1); -// --- core2/ch/overlaypressstart.c --- +// --- core2/gc/overlaypressstart.c --- void chOverlayPressStart_func_802DCDB0(void); void chOverlayPressStart_func_802DCDC0(NodeProp *arg0, ActorMarker *arg1); void chOverlayPressStart_spawn(NodeProp *arg0, ActorMarker *arg1); -// --- core2/ch/soundsource.c --- +// --- core2/sfx/soundsource.c --- void func_802D09B8(Actor *self, s32 arg1); // --- core2/ch/trainers.c --- @@ -2031,9 +2038,9 @@ void chwadingboots_802D6E54(Actor *self); // --- core2/climb.c --- u8 func_8029825C(void); -void climbClear(void); -void climbRelease(void); -void func_80298344(void); +void climb_clear(void); +void climb_release(void); +void climb_regrab_update(void); // --- core2/bundle.c --- bool func_802C9C14(Actor *actor); @@ -2065,7 +2072,7 @@ void itemPrint_init(void); void itemPrint_reset(void); void itemPrint_update(void); -// --- core2/collision/cachesize.c --- +// --- core2/time_framedelta.c --- void func_8033DC04(void); void func_8033DC10(void); void func_8033DC18(void); @@ -2108,7 +2115,7 @@ void func_80351B28(Struct68s *arg0, f32 arg1[3]); void func_80351C2C(Struct68s *arg0, f32 arg1[3]); void func_80351C48(void); -// --- core2/collision/funcs.c --- +// --- core2/collision/dispatch.c --- bool func_803209F8(f32 arg0[3], f32 arg1[3], f32 *arg2, f32 arg3[3]); void func_80320B7C(void); void func_80320B84(void); @@ -2122,7 +2129,7 @@ s32 collision_getHitsToTrigger(CollisionParams *arg0); s32 collision_getDropBundleNum(CollisionParams *arg0); void func_8033D2F4(void); -// --- core2/collision/init.c --- +// --- core2/map/envcolor.c --- void func_8031B710(void); void func_8031B718(void); void func_8031B790(void); @@ -2153,18 +2160,18 @@ void func_803451B0(u8 index, f32 arg1[3]); void func_80356714(void); void codeCF5F0_forgetAllAbilitiesExceptClawSwipeIfChecksumsFail(void); -// --- core2/cutscene/animated.c --- +// --- GV/ch/mummum.c --- void func_8035D490(ActorMarker *marker); void func_8035D4F0(ActorMarker *marker, s32 arg1); -// --- core2/cutscene/ctrl.c --- +// --- core2/nc/camera_focustarget.c --- s32 func_802C0190(void); void func_802C0120(void); void func_802C0148(void); void func_802C0150(s32 arg0); void func_802C02D4(f32 arg0[3]); -// --- core2/cutscene/lair.c --- +// --- core2/map/cutscene_skip.c --- s32 cutscenetrigger_update(void); void func_8031CC8C(NodeProp *arg0, s32 arg1); void func_8031CC40(enum map_e map_id, s32 arg1); @@ -2178,7 +2185,7 @@ void clearScoreStates(void); void debugScoreStates(void); void warp_mmmEnterLoggo(NodeProp *arg0, ActorMarker *arg1); -// --- core2/cutscene/nodeupdate.c --- +// --- core2/map/warp_dispatch.c --- s32 func_8033451C(s32 arg0); s32 func_80334524(s32 arg0); s32 func_8033452C(s32 arg0); @@ -2188,7 +2195,7 @@ void func_803343F8(s32 indx); void func_80334428(void); void func_80334448(NodeProp *arg0, ActorMarker *arg1); -// --- core2/demo_input.c --- +// --- core2/demo.c --- int demo_readInput(OSContPad* arg0, s32* arg1); void demo_free(void); void demo_load(enum map_e map, s32 demo_id); @@ -2204,10 +2211,10 @@ void dialogBin_terminate(void); void dialogBin_update(void); void func_8031B62C(void); -// --- core2/dialog/progress_dialogs.c --- +// --- core2/dialog/progressDialog.c --- void progressDialog_showDialogMaskZero(enum file_progress_e progress_flag); -void volatileFlag_setAndTriggerDialog_4(enum volatile_flags_e arg0); -void volatileFlag_setAndTriggerDialog_E(enum volatile_flags_e arg0); +void progressDialog_setAndTriggerDialog_4(enum volatile_flags_e arg0); +void progressDialog_setAndTriggerDialog_E(enum volatile_flags_e arg0); // --- core2/inventory_slots.c --- void func_803246F0(u8* self, s32 indx); @@ -2241,7 +2248,7 @@ void func_802E67AC(void); void func_802E67C4(void); void func_802E6820(s32 arg0); -// --- core2/frame/bufferreadback.c --- +// --- core2/frame/rendermem.c --- bool func_802E4424(void); bool func_802E4A08(void); s32 func_802E4A98(s32 arg0); @@ -2263,18 +2270,18 @@ void func_802E4214(enum map_e map_id); void func_802E4384(void); void func_802E4A70(void); void func_802E4A80(void); -void game_draw(s32 arg0); +void game_draw(bool arg0); // --- core2/frame/rendermem.c --- void dummy_func_802E35D0(void); void func_802E3580(void); void func_802E35D8(void); -// --- core2/fx/airscore.c --- +// --- core2/scorequeue/airscore.c --- s32 fxairscore_count_to_time(s32 count); s32 fxairscore_time_to_count(s32 time); -// --- core2/fx/common2score.c --- +// --- core2/scorequeue/common2score.c --- enum item_e func_802FDD0C(struct8s *arg0); // --- core2/fx/effect_colordata.c --- @@ -2285,7 +2292,7 @@ void func_80345C78(f32 arg0[4], f32 arg1[3]); void func_80345CD4(f32 arg0[4], f32 arg1[4]); void func_80345D30(f32 arg0[4], f32 arg1[4], f32 arg2[4]); -// --- core2/fx/effect_eggshatter.c --- +// --- core2/fx/eggshatter.c --- void eggShatter_defrag(void); void eggShatter_draw(Gfx **gPtr, Mtx **mPtr, Vtx **vPtr); void eggShatter_free(void); @@ -2293,7 +2300,7 @@ void eggShatter_init(void); void eggShatter_new(f32 position[3]); void eggShatter_update(void); -// --- core2/fx/effect_enemyrender.c --- +// --- core2/gc/pictureframe.c --- Actor * func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802DF270(void); @@ -2304,7 +2311,7 @@ void func_802DAD8C(ParticleEmitter *pCtrl, Actor *self, enum asset_e model_id); void humanoidBaddie_enterInvulnerableState(ActorMarker *marker, s32 arg1); void humanoidBaddie_update(Actor *self); -// --- core2/fx/effect_particle.c --- +// --- core2/mumboshandwithpicture.c --- void func_802DF090(s32 arg0, s32 arg1); void func_802DF0C8(void); void func_802DF11C(s32 arg0, s32 arg1); @@ -2315,11 +2322,11 @@ void func_802929F8(void); // --- core2/fx/effect_simplesprite.c --- void func_802DC110(f32 *position, enum asset_e sprite_id); -// --- core2/fx/effect_spriteanim.c --- +// --- core2/fx/banjokazooiesign.c --- void func_802DC9A4(s32 arg0, s32 arg1); void func_802DC9DC(s32 arg0, s32 arg1); -// --- core2/fx/honeycarrierscore.c --- +// --- core2/scorequeue/honeycarrierscore.c --- void gcpausemenu_80314AC8(int arg0); // --- core2/fx/ripple.c --- @@ -2328,7 +2335,7 @@ void fxRipple_802F3584(s32 arg0, f32 position[3], uintptr_t arg2); void fxRipple_free(void); void fxRipple_init(void); -// --- core2/fx/score_honeycomb.c --- +// --- core2/honeycombscore.c --- s32 honeycombscore_get_level_total(enum level_e level_id); s32 honeycombscore_get_total(void); void honeycombscore_clear(void); @@ -2336,7 +2343,7 @@ void honeycombscore_debug(void); void honeycombscore_getSizeAndPtr(s32 *size, u8 **addr); void honeycombscore_set(enum honeycomb_e indx, bool val); -// --- core2/fx/score_jiggy.c --- +// --- core2/jiggyscore.c --- s32 jiggyscore_leveltotal(s32 lvl); s32 jiggyscore_total(void); void * jiggyscore_clearAllSpawned(void); @@ -2346,8 +2353,10 @@ void jiggyscore_getSizeAndPtr(s32 *size, u8 **addr); void jiggyscore_setCollected(s32 indx, s32 val); void jiggyscore_setSpawned(s32, s32); -// --- core2/fx/score_jiggylist.c --- +// --- core2/fx/effect_jiggy_list.c --- void codeABC00_spawnJiggyAtLocation(enum jiggy_e, f32[3]); +void codeABC00_spawnJiggyAtLocationEx(enum jiggy_e, f32[3], s32 triggerEvent); +s32 jiggylist_hasSpawnedObject(enum jiggy_e jiggy_id); void func_80332E08(void); void func_8033301C(void); void func_80333270(enum jiggy_e jiggy_id, f32 position[3], void (*method)(Actor *, ActorMarker *), ActorMarker *other_marker); @@ -2357,7 +2366,7 @@ void jiggylist_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void jiggylist_map_actors(void); void jiggylist_set_level(enum map_e map_id); -// --- core2/fx/score_mumbo.c --- +// --- core2/mumboscore.c --- bool mumboscore_get(enum mumbotoken_e indx); void mumboscore_clear(void); void mumboscore_debug(void); @@ -2386,24 +2395,25 @@ void gameSelect_saveAndExit(void); void gameSelect_setGameNumber(s32 arg0); void gameSelect_resetGameNumber(void); -// --- core2/game_complete.c --- -s32 bitfield_get_bit(u8 *array, s32 index); -s32 bitfield_get_n_bits(u8 *array, s32 offset, s32 numBits); +// --- core2/flags_bitfield.c --- +s32 bitfieldarray_getBit(u8 *array, s32 index); +s32 bitfieldarray_getNBits(u8 *array, s32 offset, s32 numBits); s32 dummy_func_80320240(void); s32 dummy_func_80320248(void); s32 fileProgressFlag_getAndSet(enum file_progress_e index, s32 set); s32 func_8032056C(void); s32 func_80320708(void); -void bitfield_set_bit(u8 *array, s32 index, s32 set); -void bitfield_set_n_bits(u8 *array, s32 startIndex, s32 set, s32 length); +void bitfieldarray_setBit(u8 *array, s32 index, s32 set); +void bitfieldarray_setNBits(u8 *array, s32 startIndex, s32 set, s32 length); void fileProgressFlag_getSizeAndPtr(s32 *size, u8 **addr); +void volatileFlag_getSizeAndPtr(s32 *size, u8 **addr); void fileProgressFlag_set(enum file_progress_e index, s32 set); void volatileFlag_backupAll(void); void volatileFlag_clear(void); void volatileFlag_restoreAll(void); // --- core2/gc/dialog.c --- -int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, void (*arg4)(ActorMarker *, enum asset_e, s32)); +int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, s32 (*arg4)(ActorMarker *, enum asset_e, s32)); int gcdialog_showDialogConditional(s32 text_id, s32 arg1, f32 *pos, ActorMarker *marker, void(*callback)(ActorMarker *, enum asset_e, s32), void(*arg5)(ActorMarker *, enum asset_e, s32), s32(*arg6)(ActorMarker *, s32, s32)); int gcdialog_getCurrentTextId(void); int func_803115C4(s32 next_state); @@ -2450,14 +2460,14 @@ void sky_free(void); void sky_reset(void); void sky_update(void); -// --- core2/gfx/displaylistdata.c --- +// --- (data declarations - origin unknown) --- void func_8030C180(void); void func_8030C1A0(void); void func_8030C204(void); void func_8030C2D4(Gfx **gdl, Mtx **mptr, Vtx **vptr); -void scissorBox_setSmall(void); +void picturebox_setScissorBox(void); -// --- core2/gfx/displaylistinit.c --- +// --- core2/displaylist_init.c --- void func_80315084(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_80315110(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_803151D0(Gfx **gfx, Mtx **mtx, Vtx **vtx); @@ -2473,14 +2483,11 @@ void func_803411B0(void); void func_80341A54(void); void glspline_defrag(void); -// --- core2/level/lightconfig.c --- -// code35520_getDistanceVectors and code35520_selectTable are declared in core2/core2.h - // --- core2/level/metadata.c --- int barebound_set_active(s32 arg0); s32 barebound_802987B4(void); -// --- core2/level/specificflags.c --- +// --- core2/level/levelspecificflags.c --- s32 levelSpecificFlags_getN(s32 i, s32 n); s32 levelSpecificFlags_getSet(s32 arg0, s32 arg1); s32 levelSpecificFlags_validateCRC1(void); @@ -2488,7 +2495,7 @@ s32 levelSpecificFlags_validateCRC2(void); void levelSpecificFlags_clear(void); void levelSpecificFlags_setN(s32 index, s32 val, s32 n); -// --- core2/load_zone.c --- +// --- core2/map/loadzone.c --- void codeA960_forceLoadzone(s32); void func_80291910(void); void func_802919A0(void); @@ -2507,11 +2514,7 @@ void func_8034B9BC(s32 arg0); void func_8034B9E4(void); void func_8034BA7C(enum map_e map_id, s32 exit_id); -// --- core2/map/model.c --- -// NOTE: func_802E76B0, collisionList_func_802E805C, func_802E8E88, func_802E9118, -// func_802E92AC, func_802E9DD8 return BKCollisionTriangle* but have conflicting -// local externs (bool/s32/void) in decomp source files. Files that need -// the pointer type already have correct local externs. +// --- core2/map/mapModel.c --- BKCollisionTriangle *func_802E76B0(BKCollisionList *collisionList, BKVertexList *vertexList, f32 startPoint[3], f32 endPoint[3], f32 arg4[3], u32 flagFilter); Vec3fArray *func_803097A0(void); BKCollisionTriangle *func_80309B48(f32 startPoint[3], f32 endPoint[3], f32 arg2[3], u32 flagFilter); @@ -2528,26 +2531,25 @@ void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void mapModel_setEnvColor(s32 r, s32 g, s32 b); void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/map/savestate.c --- +// --- core2/map/mapsavestate.c --- int game_is_frozen(void); // --- core2/map/gsworld.c --- -enum map_e gsworld_getMap(void); -// --- core2/map/specificflags.c --- +// --- core2/map/mapspecificflags.c --- s32 mapSpecificFlags_validateCRC1(void); u32 mapSpecificFlags_getClear(s32 i); u32 mapSpecificFlags_getN(s32 idx, s32 n); void mapSpecificFlags_clearAll(void); void mapSpecificFlags_setN(s32 idx, s32 val, s32 n); -// --- core2/map_list.c --- +// --- core2/map/list.c --- void func_8029A47C(s32 arg0[3]); void func_8029A4D0(void); void func_8029A54C(void); void func_8029A554(void); -// --- core2/model/matrixrotate.c --- +// --- core2/fx/projectile_system.c --- void func_8033F9C0(void); void func_8033FA24(void); @@ -2556,21 +2558,21 @@ void func_8033F738(ActorMarker *arg0); void func_8033F784(ActorMarker *arg0); void func_8033F7A4(ActorMarker *arg0, BKVertexList *arg1); -// --- core2/model/render.c --- +// --- core2/model/modelRender.c --- void modelRender_setBoneTransformList(BoneTransformList *arg0); // --- core2/model/rendernormal.c --- void animVerticesList_transform(BKAnimVerticesList *arg0, BKVertexList *arg1, AnimMtxList *mtx_list); -// --- core2/mumbo_transforms.c --- +// --- core2/mumbo.c --- void chmumbo_func_802D1724(void); void func_802D2CB8(void); void func_802D2CDC(void); -// --- core2/overlay.c --- +// --- core2/map/overlay.c --- // leveloverlay_* functions are declared in core2/core2.h -// --- core2/particle/bathroom.c --- +// --- MMM/bathroom_particles.c --- void func_8029ADA8(void); void func_8029ADCC(void); void func_8029AE1C(void); @@ -2578,7 +2580,7 @@ void func_8029AE48(void); void func_8029AE74(s32 arg0); void func_8029AF1C(void); -// --- core2/particle/colordefault.c --- +// --- core2/particle/dustemitter.c --- bool dustEmitter_isActive(s32 arg0); s32 dustEmitter_returnGiven(s32 arg0); void dustEmitter_init(void); @@ -2613,14 +2615,11 @@ void partEmitMgr_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr); void partEmitMgr_drawPass0(Gfx **gdl, Mtx **mptr, Vtx **vptr); void partEmitMgr_drawPass1(Gfx **gdl, Mtx **mptr, Vtx **vptr); void partEmitMgr_free(void); -void partEmitMgr_freeEmitter(ParticleEmitter *self); void partEmitMgr_init(void); void partEmitMgr_update(void); void particleEmitter_draw(ParticleEmitter *self, Gfx **gdl, Mtx **mPtr, Vtx **vPtr); void particleEmitter_emitUniformLine(ParticleEmitter *self, f32 start[3], f32 end[3], s32 count); void particleEmitter_free(ParticleEmitter *self); -void particleEmitter_func_802EFA78(ParticleEmitter *self, s32 arg1); -void particleEmitter_setParticleCallback(ParticleEmitter *self, void (*arg1)(ParticleEmitter *self, f32 pos[3])); // --- core2/bs/player_spawn.c --- bool func_8029BDE8(void); @@ -2653,7 +2652,7 @@ void func_8029C5E8(void); void func_8029C674(void); void func_8029C6D0(void); void func_8029C748(void); -void func_8029C7F4(s32 arg0, s32 yaw_state, s32 arg2, s32 arg3); +void code_14420_setUpdateTypes(enum baanim_update_type_e arg0, enum yaw_state_e yaw_state, s32 arg2, BaPhysicsType arg3); void code_14420_setVoidOutLocation(enum map_e map_id, s32 exit_id); void func_8029C848(AnimCtrl *arg0); void func_8029C984(void); @@ -2698,7 +2697,7 @@ void func_802F4200(f32 arg0[3]); void func_802F422C(void); void func_802F4250(void); -// --- core2/cutscene_triggers.c --- +// --- core2/map/cutscene_triggers.c --- void func_803223AC(void); void func_80322490(void); void func_803224FC(void); @@ -2715,21 +2714,21 @@ bool player_isActive(void); bool player_isFallTumbling(void); bool player_isInRBB(void); bool player_isSwimming(void); -int can_dive(void); -int can_feathery_flap(void); -int can_peck(void); -int can_view_first_person(void); -int func_8028ABB8(void); -int func_8028ADB4(void); -int func_8028B394(void); -int func_8028B4C4(void); -int func_8028B528(void); -int player_isOnDangerousGround(void); -int player_isSliding(void); -int player_isStable(void); -int player_shouldFall(void); -int player_shouldSlideTrot(void); -int wishyWashyFlag_get(void); +bool can_dive(void); +bool can_feathery_flap(void); +bool can_peck(void); +bool can_view_first_person(void); +bool func_8028ABB8(void); +bool func_8028ADB4(void); +bool func_8028B394(void); +bool func_8028B4C4(void); +bool func_8028B528(void); +bool player_isOnDangerousGround(void); +bool player_isSliding(void); +bool player_isStable(void); +bool player_shouldFall(void); +bool player_shouldSlideTrot(void); +bool wishyWashyFlag_get(void); s32 can_beak_barge(void); s32 can_beak_bomb(void); s32 can_beak_bust(void); @@ -2744,12 +2743,12 @@ s32 func_8028B120(void); void func_8028B6FC(void); void func_8028B71C(void); -// --- core2/actor_gameover.c --- +// --- core2/gc/gameoversign.c --- void func_802DC528(NodeProp *arg0, ActorMarker *arg1); void func_802DC560(NodeProp*, ActorMarker*); void func_802DC604(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/level_transition.c --- +// --- core2/gc/transition.c --- int func_8032190C(void); enum level_e level_get(void); void func_803216D0(enum map_e map); @@ -2757,7 +2756,7 @@ void func_80321854(void); void func_80321918(int arg0); void func_80321924(void); -// --- core2/quiz/bitfield.c --- +// --- core2/quiz/quizquestionaskedbitfield.c --- void quizQuestionAskedBitfield_defrag(void); void quizQuestionAskedBitfield_free(void); void quizQuestionAskedBitfield_init(void); @@ -2823,7 +2822,7 @@ void saveData_load(void *savedata); void savedata_init(void); void savedata_update_crc(void *buffer, s32 size); -// --- core2/sfx/filedata.c --- +// --- core2/fx/weather_snow.c --- void func_802F8FF0(void); void func_802F8FFC(void); void func_802F9054(void); @@ -2832,7 +2831,7 @@ void func_802F9114(void); void func_802F919C(void); void func_802F962C(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/sfx/init.c --- +// --- core2/fx/weather.c --- struct3s * func_802F7C7C(void); struct6s * func_802F7C38(void); void func_802F7CC0(void); @@ -2842,7 +2841,7 @@ void func_802F7D44(void); void func_802F7DE4(void); void func_802F7E54(void); -// --- core2/sfx/playstate.c --- +// --- core2/fx/weather_leaves.c --- void func_802F8A70(struct6s *self); void func_802F8A90(struct6s *self, Gfx **gdl, Mtx **mptr, Vtx **vptr); void func_802F8B8C(struct6s *self); @@ -2877,7 +2876,7 @@ void sfxSource_setCallbackByIndex(u8 indx, void (*arg1)(u8)); void sfxSource_triggerCallbackByIndex(u8 indx); void func_8030DFB4(u8 indx, s32 arg1); -// --- core2/sfx/streamctrl.c --- +// --- core2/fx/weather_rain.c --- void func_802F80F0(struct3s *self); void func_802F8110(struct3s *self, Gfx **gdl, Mtx **mptr, u32 arg3); void func_802F8214(struct3s * self); @@ -2891,15 +2890,15 @@ void func_8034F734(void); void func_8034F774(void); void func_8034F918(void); -// --- core2/snacker_pool1.c --- +// --- core2/scorequeue/queue_collectibles.c --- bool func_802FBE04(void); void func_802FBB18(void); void func_802FBDFC(void); -// --- core2/snacker_pool2.c --- +// --- core2/scorequeue/queue_major_items.c --- bool func_802FC390(void); -// --- core2/spawn_queue.c --- +// --- core2/spawnqueue.c --- void spawnQueue_flush(void); void spawnQueue_free(void); void spawnQueue_func_802C3A18(void); @@ -2910,7 +2909,7 @@ void spawnQueue_unlock(void); // --- core2/spline_bezier.c --- -// --- core2/sprite/displaydata.c --- +// --- core2/fx/commonParticle.c --- s32 func_8033E8AC(void); u8 func_8033E93C(void); void commonParticle_init(void); @@ -2975,12 +2974,12 @@ void item_setMaxCount(s32 item); void itemscore_highNoteScores_fromSaveData(u8 *savedata); void itemscore_levelReset(enum level_e level); void notescore_getSizeAndPtr(s32 *size, void **ptr); +void itemscore_noteScores_getSizeAndPtr(s32 *size, u8 **addr); +void itemscore_noteScores_setLevel(enum level_e level, s32 score); void saveditem_getSizeAndPtr(s32 *size, u8 **buffer); void timeScores_getSizeAndPtr(s32 *size, void **ptr); -// --- core2/texture/copy.c --- - -// --- core2/timed_funcqueue.c --- +// --- core2/timedfuncqueue.c --- void func_80324C58(void); void func_80324DBC(f32 time, enum asset_e text_id, s32 arg2, f32 position[3], ActorMarker *caller, void (*callback_method_1)(ActorMarker *, enum asset_e, s32), void (*callback_method_2)(ActorMarker *, enum asset_e, s32)); void timedFuncQueue_defrag(void); @@ -2997,9 +2996,7 @@ void func_8034BF54(ActorMarker *marker); void func_8034BFF8(ActorMarker *marker); void func_8034C21C(ActorMarker *marker); -// --- core2/vtx/lighting.c --- -void lighting_free(); -void lighting_init(); +// --- core2/vtx/gclights.c --- void lightingVectorList_fromFile(File *file_ptr); // --- core2/vtx/listutils.c --- @@ -3023,20 +3020,13 @@ void func_8034C8D8(void); void func_8034C97C(void); void func_8034C9B0(int arg0); -// --- core2/vtx/list.c --- - -// --- core2/yaw.c --- -void yaw_init(void); -void yaw_setUpdateState(s32 arg0); -void yaw_update(void); - -// --- cutscenes/actor_spawninit.c --- +// --- cutscenes/cutscenesspawnqueue.c --- void cutscene_func_8038C4E0(void); -// --- FINALE/fight.c --- +// --- fight/fight.c --- void fight_addSpawnableActors(void); -// --- lair/actor_spawninit.c --- +// --- lair/lairspawnqueue.c --- void lair_func_8038A0C4(void); // --- lair/ch/brentilda.c --- @@ -3051,24 +3041,38 @@ void ff_init(void); void lair_func_8038E0B0(void); void lair_func_8038E768(Gfx **dl, Mtx **m, Vtx **v); -// --- LAIR/jigsawpicture.c --- +// --- lair/jigsawpicture.c --- bool jigsawPicture_isJigsawPictureComplete(s32 arg0); -// --- port/stub.c --- +// --- port/OS/libultra.c --- s32 osContSetCh(u8 ch); u32 __osGetSR(void); void osCreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p); void osDestroyThread(OSThread* thread); -void osDpSetStatus(u32 data); void osSetThreadPri(OSThread* thread, OSPri p); void osSpTaskYield(void); void osStartThread(OSThread* thread); void osStopThread(OSThread* t); +u32 bkGetSR(void); +float gu_sqrtf(float val); +void osViExtendVStart(u32 arg0); +OSYieldResult osSpTaskYielded(OSTask* task); +void __osError(s16 error_code, s16 num_args, ...); +s32 eeprom_readBlocks(s32 file, s32 offset, void* buffer, s32 count); +s32 eeprom_writeBlocks(s32 file, s32 offset, void* buffer, s32 count); + +// --- port/OS/OS_RCP.cpp --- +u32 osDpGetStatus(void); +void osDpSetStatus(u32 data); + +// --- port/OS/OS_VI.cpp --- +void* osViGetCurrentFramebuffer(void); +void* osViGetNextFramebuffer(void); -// --- unmapped (definition not found in src/) --- +// --- provided by libultraship --- s32 osPiReadIo(u32, u32 *); -// --- core2/ba/ba_stick.c --- +// --- core2/ba/bastick.c --- s32 bastick_getZone(void); // --- core2/ba/ba_lookdir.c --- @@ -3083,7 +3087,7 @@ void particleEmitter_manualFree(ParticleEmitter *self); // --- core2/anim/anim_bonetransform.c --- void func_8033BD20(void **arg0); -// --- core2/timed_funcqueue.c --- +// --- core2/timedfuncqueue.c --- bool timedFuncQueue_is_empty(void); // --- core2/fx/effect_colordata.c --- @@ -3110,13 +3114,13 @@ bool func_80245524(f32 arg0[3], void *arg1, intptr_t *arg2, f32 *arg3); // --- core2/bs/player_spawn.c --- void func_8029BC60(enum asset_e *anim_id, f32 *anim_duration); -// --- core2/frame/bufferreadback.c --- +// --- core2/frame/rendermem.c --- s32 func_802E4AD4(s32 arg0); // --- core2/sfx/instruments.c --- void func_8033543C(Struct81s *arg0); -// --- core2/model/matrixrotate.c --- +// --- core2/fx/projectile_system.c --- void func_8033F7F0(u8 indx, Gfx **gfx, Mtx **mtx, Vtx **vtx); // --- core2/spline_pathfollow.c --- @@ -3130,7 +3134,7 @@ void func_8034CF90(void *arg0, BKModel *arg1, s32 arg2); // --- core2/vtx/renderstart.c --- void setStruct6DsOpacity(Struct6Ds *arg0, s32 arg1); -// --- core2/anim/anim_cache.c --- +// --- core2/anim/animcache.c --- int animCache_getBoneTransformList(s16 index, BoneTransformList **arg1); // --- core2/anim/bonetransformlist.c --- @@ -3149,7 +3153,7 @@ bool chCollectible_collectRedFeather(ActorProp *arg0); bool chNipper_isInState7(s16 arg0[3]); // --- core2/actor_cubepropsystem.c --- -s32 codeA5BC0_getPositionAndReturnRadius(void *arg0, s32 arg1[3]); +s32 codeA5BC0_getPositionAndSelectorOrRadius(void *arg0, s32 arg1[3]); // --- core2/gamestate.c --- void itemscore_timeScores_fromSaveData(u16 *savedata); @@ -3159,25 +3163,20 @@ int savedata_8033CE40(void *buffer); int savedata_8033CC98(s32 filenum, void *buffer); void savedata_clear(void *savedata); -// --- core2/spawn_queue.c --- +// --- core2/spawnqueue.c --- void spawnQueue_defrag(void); -void bkmemcpy64(void *dest, void *src, s32 size); // handwritten assembly code that performs an optimized 8 byte memcpy -void bkmemset64(void *dest, s32 value, s32 size); // handwritten assembly code that performs an optimized 8 byte memset -u32 bkGetSR(void); // handwritten assembly code that replicates the __osGetSR function +// --- port/MemShims.c --- +void bkmemcpy64(void *dest, void *src, s32 size); +void bkmemset64(void *dest, s32 value, s32 size); // --- RBB/ch/engineparts.c --- f32 func_8038A6B8(ActorMarker *); -// --- core1/io/ba_motor.c --- +// --- core1/bamotor.c --- void baMotor_80250D94(f32, f32, f32); void baMotor_80250E94(f32, f32, f32, f32, f32, f32); -// --- core1/io/pfsmanager.c --- -OSContPad *func_8024F3F4(void); -OSMesgQueue *pfsManager_getFrameReplyQ(void); -void controller_copyFaceButtons(s32, s32 [6]); - // --- core1/memory.c --- void * bk_malloc(size_t size); void *bk_realloc(void* ptr, size_t size); @@ -3192,16 +3191,16 @@ void *assetcache_reload(enum asset_e assetId); // --- core2/sfx/trackmanager.c --- void musicKeepsPlaying(void); -// --- core2/ba/ba_eyeblink.c --- +// --- core2/ba/iFrame.c --- void baiFrame_startWithValue(f32); -// --- core2/ba/ba_eyes.c --- +// --- core2/ba/baeyes.c --- void baeyes_openSingleEye(s32, f32); -// --- core2/ba/ba_falldamage.c --- +// --- core2/ba/falldamage.c --- void bafalldamage_start(void); -// --- core2/ba/ba_flag.c --- +// --- core2/ba/baflag.c --- bool baflag_isFalse(enum misc_flag_e arg0); bool baflag_isTrue(enum misc_flag_e arg0); void baflag_clear(enum misc_flag_e arg0); @@ -3213,43 +3212,40 @@ void baflag_toggle(enum misc_flag_e arg0); f32 func_802915D8(void); f32 func_80291604(void); -// --- core2/ba/ba_key.c --- +// --- core2/ba/bakey.c --- int bakey_pressed(s32); u32 bakey_held(s32); -// --- core2/ba/ba_marker.c --- +// --- core2/ba/marker.c --- ActorMarker *baMarker_get(void); -// --- core2/ba/ba_model.c --- +// --- core2/ba/model.c --- f32 baModel_80292230(void); void baModel_80291A50(s32 arg0, f32* arg1); void baModel_80292078(s32, f32); void baModel_80292158(f32); -// --- core2/ba/ba_physics.c --- +// --- core2/ba/physics.c --- f32 get_slope_timer(void); -void baphysics_get_velocity(f32 dst[3]); -void baphysics_reset_gravity(void); -void baphysics_set_gravity(f32 gravity); -// --- core2/ba/ba_position.c --- -f32 player_getYPosition(void); -void _player_getPosition(f32 dst[3]); +// --- core2/ba/playerposition.c --- +f32 playerPosition_getY(void); +void playerPosition_get(f32 dst[3]); void playerPosition_addY(f32); -void player_setYPosition(f32); +void playerPosition_setY(f32); // --- core2/ba/ba_recoil.c --- f32 get_turbo_duration(void); void func_80294980(f32 arg0[3]); -// --- core2/ba/ba_sfx.c --- +// --- core2/ba/basfx.c --- void basfx_80299CF4(enum sfx_e, f32, s32); void basfx_80299D2C(enum sfx_e, f32, s32); void basfx_playJumpSfx(f32, f32); void basfx_playOwSfx(f32); void basfx_updateClockSfxSource(f32, f32); -// --- core2/ba/ba_stick.c --- +// --- core2/ba/bastick.c --- f32 bastick_distance(void); f32 bastick_getAngleRelativeToBanjo(void); f32 bastick_getY(void); @@ -3275,7 +3271,7 @@ void bs_setState(s32 state_id); void bs_updateState(void); void bs_setInterruptResponse(s32 arg0); -// --- core2/bs/bs_storedstate.c --- +// --- core2/bs/bsStoredState.c --- f32 bsStoredState_getLongLegTimer(void); f32 bsStoredState_getTurboTimer(void); void bsStoredState_setLongLegTimer(f32); @@ -3285,19 +3281,19 @@ void bsStoredState_setTurboTimer(f32); // --- core2/bs/walk.c --- f32 func_802B6F9C(void); -// --- core2/camera/camera_motor2.c --- +// --- core2/nc/camera_motor2.c --- void func_802BB3DC(s32, f32, f32); -// --- core2/camera/dynamicCam3.c --- +// --- core2/nc/dynamicCam3.c --- void func_802C1B20(f32); -// --- core2/camera/dynamicCamD.c --- -void ncDynamicCamD_func_802BF2C0(f32); +// --- core2/nc/die.c --- +void ncbadie_func_802BF2C0(f32); // --- core2/climb.c --- -f32 climbGetBottomY(void); -f32 climbGetTopY(void); -void climbGetBottom(f32 dst[3]); +f32 climb_getBottomY(void); +f32 climb_getTopY(void); +void climb_getBottom(f32 dst[3]); // --- core2/scorequeue/manager.c --- void func_802FAD64(enum item_e); @@ -3305,25 +3301,25 @@ void func_802FAD64(enum item_e); // --- core2/collision/hitboxdata.c --- enum marker_collision_func_type_e collision_getNextState(CollisionParams *arg0); -// --- core2/fx/airscore.c --- +// --- core2/scorequeue/airscore.c --- struct7s *fxairscore_new(s32); void fxairscore_draw(enum item_e, struct8s *, Gfx**, Mtx**, Vtx **); void fxairscore_free(s32, struct7s *); void fxairscore_update(enum item_e, struct7s *); -// --- core2/fx/common1score.c --- +// --- core2/scorequeue/common1score.c --- struct7s *fxcommon1score_new(enum asset_e item_id); void fxcommon1score_draw(enum item_e arg0, struct8s *arg1, Gfx **arg2, Mtx **arg3, Vtx **arg4); void fxcommon1score_free(enum item_e item_id, struct8s *); void fxcommon1score_update(enum item_e, struct8s *); -// --- core2/fx/common2score.c --- +// --- core2/scorequeue/common2score.c --- struct8s *fxcommon2score_new(enum item_e); void fxcommon2score_draw(enum item_e, struct8s *, Gfx**, Mtx**, Vtx **); void fxcommon2score_free(enum item_e, struct8s *); void fxcommon2score_update(s32, struct8s *); -// --- core2/fx/common3score.c --- +// --- core2/scorequeue/common3score.c --- void *fxcommon3score_new(enum item_e); void fxcommon3score_draw(enum item_e, void *, Gfx**, Mtx**, Vtx **); void fxcommon3score_free(enum item_e item_id, void *); @@ -3342,34 +3338,34 @@ void func_802927E0(f32, f32); void func_80292900(f32, f32); void func_80292974(f32, f32, f32); -// --- core2/fx/effect_spriteanim.c --- +// --- core2/fx/banjokazooiesign.c --- Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/fx/healthscore.c --- +// --- core2/scorequeue/healthscore.c --- struct7s *fxhealthscore_new(enum item_e); void fxhealthscore_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx); void fxhealthscore_free(enum item_e, struct8s *); void fxhealthscore_update(enum item_e, struct8s *); -// --- core2/fx/honeycarrierscore.c --- +// --- core2/scorequeue/honeycarrierscore.c --- struct7s *fxhoneycarrierscore_new(s32); void fxhoneycarrierscore_draw(s32, struct8s *, Gfx**, Mtx**, Vtx **); void fxhoneycarrierscore_free(s32, struct8s *); void fxhoneycarrierscore_update(s32, struct8s *); -// --- core2/fx/jinjoscore.c --- +// --- core2/scorequeue/jinjoscore.c --- struct8s *fxjinjoscore_new(enum item_e); void fxjinjoscore_draw(s32, struct8s *, Gfx**, Mtx**, Vtx **); void fxjinjoscore_free(enum item_e, struct8s *); void fxjinjoscore_update(enum item_e, struct8s *); -// --- core2/fx/lifescore.c --- +// --- core2/scorequeue/lifescore.c --- struct8s *fxlifescore_new(s32); void fxlifescore_draw(enum item_e, struct8s *, Gfx**, Mtx**, Vtx **); void fxlifescore_free(s32, struct8s *); void fxlifescore_update(enum item_e, struct8s *); -// --- core2/fx/score_jiggylist.c --- +// --- core2/fx/effect_jiggy_list.c --- void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]); // --- core2/fx/sparkle.c --- @@ -3387,7 +3383,7 @@ f32 barebound_get_vertical_velocity(void); f32 barebound_get_horizontal_velocity(void); f32 barebound_get_gravity(void); -// --- core2/particle/bathroom.c --- +// --- MMM/bathroom_particles.c --- void func_8029AD28(f32, s32); // --- core2/bs/player_spawn.c --- @@ -3409,14 +3405,14 @@ void pitch_setIdeal(f32); // --- core2/playerutils.c --- bool func_8028AED4(f32*, f32); -int player_inWater(void); +bool player_inWater(void); // --- core2/roll.c --- f32 roll_get(void); void roll_setAngularVelocity(f32, f32); void roll_setIdeal(f32); -// --- core2/sfx/playstate.c --- +// --- core2/fx/weather_leaves.c --- struct6s *func_802F8BE0(s32 arg0); // --- core2/sfx/randompitch.c --- @@ -3426,13 +3422,13 @@ void func_802F9F80(s32, f32, f32, f32); void func_802F9FD0(s32, f32, f32, f32); void func_802FA060(s32, s32, s32, f32); -// --- core2/sfx/streamctrl.c --- +// --- core2/fx/weather_rain.c --- struct3s *func_802F8264(s32 arg0); // --- core2/fx/projectile_anim.c --- void func_80352CF4(f32 *, f32 *, f32, f32); -// --- core2/timed_funcqueue.c --- +// --- core2/timedfuncqueue.c --- void func_80324D2C(f32, enum comusic_e); void func_80324D54(f32, enum sfx_e, f32, s32, f32 [3], f32, f32); void func_80324E38(f32, s32); @@ -3440,7 +3436,7 @@ void timed_exitStaticCamera(f32 time); void timed_playSfx(f32, enum sfx_e, f32, s32); void timed_setStaticCameraToNode(f32, s32); -// --- core2/vector.c --- +// --- core2/vla.c --- VLA * bk_vector_defrag(VLA *vla); VLA * bk_vector_new(u32 elemSize, u32 cnt); s32 bk_vector_getIndex(VLA *vla, void *element); @@ -3475,21 +3471,25 @@ Struct70s *func_8034C528(s32); Struct70s *func_8034C5AC(s32); s16 func_8034C50C(Struct70s *arg0); -// --- core2/yaw.c --- -f32 yaw_get(void); -f32 yaw_getIdeal(void); -void yaw_applyIdeal(void); -void yaw_rotateTimed(f32); -void yaw_set(f32); -void yaw_setIdeal(f32); -void yaw_setVelocityBounded(f32, f32); +// --- GV/gv_helpers.c --- +void rubeeEggPot_addedEggToPot(void); +s32 rubeeEggPot_getEggGoal(void); + +// --- core2/frame/auxbuffer.c --- +void picturebox_init(void); +void picturebox_free(void); +void picturebox_func_8030C180(void); +void picturebox_resetScissorBoxAndFramebuffer(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- port/stub.c --- -float gu_sqrtf(float val); +// --- core2/actor_cubepropsystem.c --- +void core2_A5BC0_drawUnknownMarkers(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- unknown source (no .c definition found) --- -void _guMtxIdentF_80245D44(float mf[4][4]); //static should NOT be here -void func_80241304(Mtx *m, float x, float y, float z); -BKModelBin * marker_loadModelBin(ActorMarker *marker); +// --- core2/crc_bootvalidation.c --- +void codeCF5F0_init(void); +void codeCF5F0_triggerAntiTamperMeasurement(void); + +#ifdef __cplusplus +} +#endif #endif // FUNCTIONS_H diff --git a/include/gc/gctransition.h b/include/gc/gctransition.h index a891672a7..d196963df 100644 --- a/include/gc/gctransition.h +++ b/include/gc/gctransition.h @@ -1,8 +1,12 @@ #ifndef __GC_TRANSITION__ #define __GC_TRANSITION__ +#ifdef __cplusplus +extern "C" { +#endif + void gctransition_defrag(void); -void gctransition_draw(Gfx **arg0, Mtx **arg1, Vtx **arg2); +void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void gctransition_8030BD4C(void); f32 gctransition_8030BD88(void); int gctransition_done(void); @@ -14,4 +18,8 @@ void gctransition_8030BEA4(s32 arg0); void gctransition_update(void); void gctransition_reset(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/model.h b/include/model.h index 282b9d5e8..3125d8c3e 100644 --- a/include/model.h +++ b/include/model.h @@ -4,6 +4,10 @@ #include #include "bool.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Model header * Contains offsets relative to the start of the file to the various sections * If a section is not present in the file, the offset will be zero @@ -512,4 +516,8 @@ void model_free(BKModel *self); void gclights_recolor_vertices(BKVertexList *arg0, f32 position[3], f32 rotation[3], f32 scale, f32 arg4[3], BKVertexList *arg5); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/prop.h b/include/prop.h index c51c5c7d9..564b2f560 100644 --- a/include/prop.h +++ b/include/prop.h @@ -58,6 +58,8 @@ typedef struct model_prop_s{ u8 padB_3 :4; } ModelProp; +#define MODEL_ASSET_OFFSET 0x2D1 + // [port] On N64 the marker pointer is 4 bytes, so words[3] (12 bytes) covers // the entire struct. On 64-bit, the pointer is 8 bytes (16 bytes total). @@ -124,7 +126,7 @@ typedef struct actorMarker_s{ u32 unk40_22:1; u32 unk40_21:1; u32 unk40_20:1; - u32 unk40_19:1; + u32 unk40_19:1; // set for screen overlay sprites u32 pad40_18:19; Vec3fArray * unk44; BKModel * unk48; @@ -396,13 +398,20 @@ typedef struct { u32 pad10_0:1; } OtherNode; //can be inplace of NodeProp (see code7AF80_initCubeFromFile) size: 12 (0xC) bytes +// Distance scratch __cube_sort fills, one entry per prop. Cubes past this are +// left unsorted rather than overrunning it. +#define CUBE_SORT_SCRATCH_SIZE 0x400 + typedef struct cude_s{ s32 x:5; s32 y:5; s32 z:5; - u32 prop1Cnt:6; - u32 prop2Cnt:6; - u32 unk0_4:5; //node_prop_count + // [port] were bitfields (:5/:6/:6). The 64th prop wrapped a count to 0, which + // realloc'd the prop array to nothing while live markers still pointed into it; + // unk0_4 is the front index of the node-prop partition and wrapped at 32. + u32 unk0_4:16; //node_prop_count + u16 prop1Cnt; + u16 prop2Cnt; NodeProp *prop1Ptr; Prop *prop2Ptr; }Cube; diff --git a/include/structs.h b/include/structs.h index 9652e2d14..ce50d76ab 100644 --- a/include/structs.h +++ b/include/structs.h @@ -8,6 +8,10 @@ #include "enums.h" #include "bool.h" +#ifdef __cplusplus +extern "C" { +#endif + // [port] Forward-declare struct tags used in function pointers inside structs below. // Without these, clang treats the struct tag as file-local to each struct definition. struct actor_s; @@ -433,6 +437,7 @@ typedef struct{ typedef struct struct_4D_s{ f32 unk0[3]; f32 unkC[3]; + u32 id; // [port] stable identity for frame interpolation }struct4Ds; typedef struct{ @@ -794,4 +799,8 @@ typedef struct { struct ALHeap *unkC; //heap u16 unk10; }Struct87s; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/variables.h b/include/variables.h index cb494bd33..fef76269d 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1,6 +1,10 @@ #ifndef VARIABLES_H #define VARIABLES_H +#ifdef __cplusplus +extern "C" { +#endif + #define BAD_PI 3.141592654 #define BAD_DTOR (BAD_PI/ 180.0) #define M_TAU (2*M_PI) @@ -9,4 +13,8 @@ extern f32 climbPoleBottom[3]; extern f32 climbPoleTop[3]; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/version.h b/include/version.h index 0f24f9c16..3efff4330 100644 --- a/include/version.h +++ b/include/version.h @@ -31,6 +31,9 @@ #define JP_EXCLUSIVE(body) #endif +// [port] AssetVersionRemap.h keys on usa0 +#define VER_SELECT(usa0, pal, usa1, jp) usa0 + #if VERSION == VERSION_USA_1_0 #define VER_SELECT(usa0, pal, usa1, jp) usa0 #elif VERSION == VERSION_PAL diff --git a/lib/ultralib/include/PR/gbi.h b/lib/ultralib/include/PR/gbi.h index 4b21795f9..052fb33a8 100644 --- a/lib/ultralib/include/PR/gbi.h +++ b/lib/ultralib/include/PR/gbi.h @@ -4579,7 +4579,7 @@ typedef union { #endif -// [port] Function declarations for GBI overrides in stub.c +// [port] Function declarations for GBI overrides in libultra.c // The decomp macros above are inside #if 0, so callers need prototypes // to avoid implicit-declaration truncation of 64-bit pointer arguments. #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) diff --git a/lib/ultralib/include/assert.h b/lib/ultralib/include/ultra_assert.h similarity index 100% rename from lib/ultralib/include/assert.h rename to lib/ultralib/include/ultra_assert.h diff --git a/libultraship b/libultraship index 2c63e7ede..2917d0f4f 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 2c63e7edef577cd2a3726ce24dfedd7f088f12ae +Subproject commit 2917d0f4fe62c579174561dcd34f327c9410bb72 diff --git a/port/anim/lighthouse_shrug b/port/anim/lighthouse_shrug new file mode 100644 index 0000000000000000000000000000000000000000..e751332baea9b383a8971b84151888ef31da6f35 GIT binary patch literal 408 zcmZQzU|{fb^mYPL4Da`?y$8Y|Ht}Eq11C_i76T<1vX1nFdCTLvau7;J#-NenJPasg08i-8%dDv2Wcx}vz>zI$%BF(ih>~Cw6s);?sk0NdoStCxZOWxZ4JBp=H*Mi zeD8hl&+mNz00$53?;*e+mp=JP{j1+=y)^i;aJ7IJ0RE}#{Q7kyW4;7sQr_vQM(p- z{1?^7@xuG}Ki(+*B)&TBmRd*J?FhDJNuKM@=Kib3H#!b| zFQD&~e8GU@uTm1s;xCKG72=Te`5(oXT95L7Ww*fRyi*DUy?fVF%~xL`->C6s!u!~6 z3br_}cH4rTJNr8vpR4Te1NC2}*ZBGjjq{W#dCSx#udJ~SY^49)%f7S{-j77;Uef5| zG>|rC1!LZ)cuuf7$MJ}DbJ!l5PWdC%4MEeOc}z<%%ezjNf2A&Zg5saP_@`fzcq|J_ zU95!cw>8PTk<`H`uJgJh#+j(Wa$V}6)WcST^KLU~(|D)J*ln^MI&JYw^iPUs;RV^g zOCC*4W-6%#T$fB;>XFIlnyi;&bG-Rd{{zRT?^dL)gi==`$uD6^>bvBbIIPk0wW{b> z6a8wd>zCzMLahHdQJT!~d(A|!vGzEnc`(1Jc`|!!6dzh|9KVCG*d37;7 zD|{r7zQFgGf0m?fd%54ReihL_j5z;BRmLKP2c%UCwL|?Z$(xSFe&z^|^&GPIczylP z`G4mBm5BGXGRCK?G3URyF4&MfI3u_|ew}utuFcMM$l==C+^dUq1Wf}XaHWa9z z+I@R!ac*&xzb{N;Lz?%m@b>_oc~{GCX?ZVNwa5Bcw&r%>;mqk3ol3zDC8;bDgG zQB!!BCFc@Zo_6G1!WAAC6e;nhrGT+4=M*__DRX{~q#rJ6lxWf#^Ox~BxQM!|3-422 z%J%m>gmj;^a@agipV?JcuivVPwc-sxJx z$5`KNofn4Jf%81D^^WJEv3*?YdNaFbc9#6JZL#y`5}hCX_~apFp#1#ojdRxq%5Jc0 z%%3!0*)>1+(sY)&-NE|?%j{-==Qb>J_+Z_(SZ24w`eU=q$2gGM!iPEhAaz_GXW9U% z>#nT&DaT?-ttxd+NHPY{W88kEbqdTLbG|L|FOL9!{!lr z2X+wI_lsw)^v$8~D|ri8G`|1Do9g?03$~8PTfxr1r=AanzOUqIJla#=KY;I}e*F?m zjmSHJPR`IEmwL)7FXpD%Gp~NW1RnfQJKF0W{(k=Q!@ur(0k*?i$EN#_fA;OXef?PP WWt8=Ek1jmFcz*uWH|@(uQ2qz=^ZoV! literal 0 HcmV?d00001 diff --git a/port/models/lighthouse_GEO b/port/models/lighthouse_GEO new file mode 100644 index 0000000000000000000000000000000000000000..166eeaa4ffea73290c9b3fece13e129f5d9f9b32 GIT binary patch literal 212 zcmZQzU|?|aaqVIq`=i+w43X#-0wRnsksnf!S*EyUOIU~l1f}iD`e}Uhr>m`rZAIIww?B|GmiS}{4>#@IP3HRi2z9xWwS$Kc) zIN!6u2MVtukN3+A@Gepyp}xPzw!Q`=+^tM=zPB9Wk1h>=JTnY+l03U zxA;eTnuLll6X{>c~E!{Q=l7 z6n>fZ$6!A}b!2~)_M2dTtMDT255b=Kr+utHb-YU)Zv)2Dc=vF;c>DtxpZhJEPcQvn zga7N2k8b+E3w!R@$UaZ|NA_K`AB_073a_Jm>faFgH_(3o^0Qa% zqw$7vytx?fRpGVtza94PsE+K1(7p-w?+dS?{Y=<*s*daj(f(1`50U&-(f(8STQ%+D z{q{N6=w8D3y>(r>|4t;0PS58C>QhOR+ak|zxGLKj=XaBn^Srl?dOG}fK^JRjACDK? zPl3P0t5{3_rSLx~x`zG>!9Re$SVO)7T+Zua75M|;gH@B~z~y}C?N2@re41+VJHQ`= z9$i5`5_~aq!IO^ye@Hd?5a{nfzu~AaVEs#=yGyk1MSLDsP5w6Yz0h5kso#P9T-CJS z0zOi7k$eaEaOln=`5(aLJn!lu-wK{rO}-mkzNg*Y6aIq`k3z_A4!lM+`3&&MqCUmcpzlilp zz6v3qe*@R=eaPQG!S51&nd83>-XJ>UZ$J1@)#N+Ddt^N!e|x~st0q4PenfQ0Upx4F zs>#!Qg#4xXNb|SKZx#Exv-*CXPFDHXL^n{!=Tm%sO?0dLn_^!}`}jOs0DeYz4S9V2 zECgqM$m8>77P!W%KlzR9ZwfPhkH0@@K03(Le1z{!4eCYKyH<}~U+^GP1pyR*QVPx83l9RbdKk;nD!jqHn9FY`(N zxE?+V&U})`_3$om=94_Ghj)N8pX6~p+y>5klE?LMnvV|h?qs9?neNZG^!@8hHu$xw z3#u#J1~1>2U5@%7?3kH@Vx3W|HI(&eJps+=Mea3Rnvbf_&DgX738mgkAb%NZULA4 zzFfu^iGNs+jQ_*PznsVGKb*Ar$6!CKg6oaru@muG0KT$<@i~?pXa12z`HSP#2Yabk zpK-L0;}^%P6VJaH_7?9rUhNof7Ryf|Ll;D0-~%|DLUO5}&%AI5hw@+bAT<7!wPcfeC2g~0t!25}P$j_7D{h=*? ztHDp6M?7oYVgnc3qH^KJL?y+et_KiJL?y+{(;>3JL?Cs{(#*2JL?Cs z{(wB|@3`KqKOnb$t`PcxtUn;P{;d%Dfvi6uxBkugfvi6uxBkugfvi6uxBkugfg9Op z{R92ee1!Ka%}3}L()TfN>mM7t>7Ty8!TwKpclY3Tcj!;7AAPPs`;B1#!EZx>@w9$+ z%mwmSz((PWxaR`7^~2*oCO-r&XV{{T$*q5G?<1F9N$$H&_mNxw-Q>vSuIc;u{WA39 zc77HT)(4}}4NAXX2=$75D^w@^-r9LusCYx`>w4Jh_chq3{eR$9;PU;p@oYZkUj?Q- zjBoR^`B?ql>O1|fanoV-WFET3IcWB8d4HuOdLa5A>F-*h#op@s9PHn8FF><@%Ylow z`abVEy>l(l?BDY4N=dZU_pRWwVQ>9dE4XN@?{nZk#`COy%Ylow`aYj@`gNF}^=J9y zN=dZU@2%i#-F#^FXRY9(t$xpe&vebu?9X!GqOE?(5%jMO*!z17DBlS$~!T7oEnt6vey5cw7FO67DzKFD;d(xu04px&PAr67Cahe>5fJ zmy)OaBZ+ullc;&lfqLellLx zUo@*e3xDayFn`t7pTJ*r8lP~VZT*eiZTip0 z>~Hlq)_2|WkUx!AR)15c^9%8``rG20u0O=r>T8Q{y8aMPtFJA-)=xm|{`nEsH7^TW!XHwk)NneGSsv1R&RjMrD@|6fz91O5O2 literal 0 HcmV?d00001 diff --git a/port/models/lighthouse_tex_0 b/port/models/lighthouse_tex_0 new file mode 100644 index 0000000000000000000000000000000000000000..dd7712dbb22e30163152cb041c5c395f17712929 GIT binary patch literal 1104 zcma(~$&%t$5ai(Sclc-K?28ZnqnUwjV44P+O$b_I*9J%kNg$zp7h-D|(ZEdj?q6^* zwj+FWzE|}svr?&4DwX>E!*9RBllpT>T<&$B|1W+9<1hbI>Zerdw2xiy?Rq{RPhY>^ z4!h&=a{c4m>2SIxr#LvC-!|JY*e91OoZGj{*VE~oyk9O!@_xJQT`xSu+s%4^x_!SU zZ-?Y|0sn5dPZDq?JI6GWT^z6D-W^OwQw_s5RL!ysBk*0{cWuLP z+;tRfcl)hstyU}5Q01j+IhG%U(b~5xUDaKG9YK;}X}YFbmbTI?$Fw~^3?t7rG|h5D z&+!~lQB+ki?%}GcYHkoj>%g-N-S*?aGE{LPtyD#^99>i3PnPGou4NjwY5I|C$ihNd zYPu>Lrn*{6lDLEnIJ#@;wxcfjxuz-FY9X#vc_E78d@e0zQ4kbU2bV0)L}?)@i@6}L zmi&z4d43@;W-KSk@^T?bf*|vvAo9GVECqJT@`5NU!gMl&h}o2#bAmEvS&o}Q20t0I z+>DzGEHmXLk>@CK%r{C-LJ9xL>g&l@)OT|*D1R`jFLZR>kb;onz2~Ys-hx(My=kj0jfX8e$ zpUc6J%V+NmG_WGl2BNLnfU`r$2uD1oso%zX9}L_Cx;* D4uaQS literal 0 HcmV?d00001 diff --git a/port/models/lighthouse_tex_1 b/port/models/lighthouse_tex_1 new file mode 100644 index 0000000000000000000000000000000000000000..4313a78346eb58bdee5df841b6c09ebfbc6faf21 GIT binary patch literal 1104 zcma)*-%nCu7{{NB*5A=>i#1$PcWqsCXG1Nj)r}LT7kbf#OGVi9#%yUqZc4~fTdcS+ z-AteqHf&Ct4iW`Z87Bn=M*I-TBXHiA-uE0mqIS`;`HrbVIrLllslX>E0$=LLT|R83_trhF!Ork-OnKl>!I;VAki$GOn#ccV;VU=U6@&-X|1 z$){F}9NPUwoObJUZsK&gKD0IZ*gR2B9m4yb{(jH?8P1p$Z@y}Hf%*9Iay-vlB7Pqt z-1N;Lx&D?2%;$1>QhusGRI2bx{uqtW%DK(CmbLA=v7)HzbEcO z$GWgDl#BDnxy9~=PrKP^1+=W3@c5|gN?(ZR!5O!<*^yx9mC)!Z3hL?G&sCsZqlP5x zYOOm{@HB#Ip01`4?3@ysyd)n*tg0UGLDBaN9ytGq28j8E;LwwyV1e_u!M!hZbV6_| zEufgrVSM22QCTC1^J}2Skv-w-9Z)%u!c?Bxp1@o{OAOu1qmrqQm^kq3Brs3-Ze#MlX?##KZyM%v2R!ITZO&XIMQfq3r=_g=y!Q{{^aG8omGk literal 0 HcmV?d00001 diff --git a/port/models/lighthouse_tex_2 b/port/models/lighthouse_tex_2 new file mode 100644 index 0000000000000000000000000000000000000000..5a1a396cd86cdba73b1dfd59c83a625eb3da2fc1 GIT binary patch literal 1104 zcmb_b$!)|i4Aeng)UhpWGkNEeN199vDJ3nWg$%W}Y}pR52tq)r1NGSp_ z1GIHMrkqQyrDRUQPXMGt;!@iU(Q3({*aHmtluOSF;#M<9Z$}@ReB@nP04ca}1OxUd zEdW$l2(4B?AwLH-(e-p RFi!tGU9=vqo4)_~ + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 new file mode 100644 index 000000000..42e911411 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 new file mode 100644 index 000000000..259b27c4e --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 new file mode 100644 index 000000000..dc680a34a --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 new file mode 100644 index 000000000..a134560fb --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 new file mode 100644 index 000000000..65134138f --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 new file mode 100644 index 000000000..3b458b736 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 new file mode 100644 index 000000000..b21f2c4b7 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 new file mode 100644 index 000000000..9f4483ec6 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 new file mode 100644 index 000000000..9339e42f0 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 new file mode 100644 index 000000000..e1122533a --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 new file mode 100644 index 000000000..29c025d0f --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 new file mode 100644 index 000000000..c3c88918b --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 new file mode 100644 index 000000000..70117ba12 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 new file mode 100644 index 000000000..70117ba12 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL b/port/objects/object_archipelago_item/gArchipelagoJunkDL new file mode 100644 index 000000000..4beef5eb3 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 new file mode 100644 index 000000000..f2137f135 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 new file mode 100644 index 000000000..ae92327e4 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 new file mode 100644 index 000000000..bbbc96439 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 new file mode 100644 index 000000000..6d11e6b1c --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 new file mode 100644 index 000000000..827df8c0d --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 new file mode 100644 index 000000000..6714bf7a4 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 new file mode 100644 index 000000000..3980be483 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 new file mode 100644 index 000000000..9f4483ec6 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 new file mode 100644 index 000000000..9339e42f0 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 new file mode 100644 index 000000000..e1122533a --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 new file mode 100644 index 000000000..29c025d0f --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 new file mode 100644 index 000000000..c3c88918b --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 new file mode 100644 index 000000000..70117ba12 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 new file mode 100644 index 000000000..70117ba12 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL new file mode 100644 index 000000000..ed07b28c9 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 new file mode 100644 index 000000000..1a679a463 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 new file mode 100644 index 000000000..f49d299ef --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 new file mode 100644 index 000000000..ea82a9347 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 new file mode 100644 index 000000000..8cfca6524 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 new file mode 100644 index 000000000..639c5aea4 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 new file mode 100644 index 000000000..99a4852cb --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 new file mode 100644 index 000000000..e7ab8546c --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 new file mode 100644 index 000000000..0f50ed430 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 new file mode 100644 index 000000000..9f4483ec6 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 new file mode 100644 index 000000000..9339e42f0 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 new file mode 100644 index 000000000..e1122533a --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 new file mode 100644 index 000000000..29c025d0f --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 new file mode 100644 index 000000000..c3c88918b --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 new file mode 100644 index 000000000..70117ba12 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 new file mode 100644 index 000000000..b76b5b312 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 new file mode 100644 index 000000000..b76b5b312 --- /dev/null +++ b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black new file mode 100644 index 000000000..7ef279db5 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue new file mode 100644 index 000000000..770d70e48 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green new file mode 100644 index 000000000..9a57f3f8c --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange new file mode 100644 index 000000000..c3da3eff1 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline new file mode 100644 index 000000000..d39d1af92 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink new file mode 100644 index 000000000..e3b896b02 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple new file mode 100644 index 000000000..64f362026 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red new file mode 100644 index 000000000..8cc9fec5e --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow new file mode 100644 index 000000000..1b0d4be92 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk new file mode 100644 index 000000000..7ef279db5 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk new file mode 100644 index 000000000..b8f17f3bf --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk new file mode 100644 index 000000000..05312bc76 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue new file mode 100644 index 000000000..a55a1459a --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green new file mode 100644 index 000000000..20d667aa3 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange new file mode 100644 index 000000000..ad2a5ac38 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline new file mode 100644 index 000000000..d39d1af92 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink new file mode 100644 index 000000000..a3d546483 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red new file mode 100644 index 000000000..78236fa28 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow new file mode 100644 index 000000000..8def121b7 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk new file mode 100644 index 000000000..17867ed9c --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk new file mode 100644 index 000000000..7a880f3e9 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk new file mode 100644 index 000000000..20b763643 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk new file mode 100644 index 000000000..7e88e53d7 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive new file mode 100644 index 000000000..fa76abb08 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive new file mode 100644 index 000000000..7ef279db5 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive new file mode 100644 index 000000000..770d70e48 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive new file mode 100644 index 000000000..9a57f3f8c --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive new file mode 100644 index 000000000..c3da3eff1 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow new file mode 100644 index 000000000..c41b05db9 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue new file mode 100644 index 000000000..c9073d0cf --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green new file mode 100644 index 000000000..84e26fe7a --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange new file mode 100644 index 000000000..076acfe28 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline new file mode 100644 index 000000000..d39d1af92 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink new file mode 100644 index 000000000..e3b896b02 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red new file mode 100644 index 000000000..930fb41e6 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow new file mode 100644 index 000000000..383d9441c --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive new file mode 100644 index 000000000..64f362026 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive new file mode 100644 index 000000000..8cc9fec5e --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive new file mode 100644 index 000000000..1b0d4be92 --- /dev/null +++ b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/port/objects/object_archipelago_item/model.xml b/port/objects/object_archipelago_item/model.xml new file mode 100644 index 000000000..e69de29bb diff --git a/port/textures/icons/g2ShipIcon.png b/port/textures/icons/g2ShipIcon.png deleted file mode 100644 index 49785b681a18951b5611a04a8f594bea3bcab154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13286 zcmeHsbyQp1ws&wVv`BFY?oROF4#A3h2myi@fO*~j9-i*@2p2dI>F)st!u=5T0D#}eq73sUW^S*DRjSCR zx=T=Ti@Bpa(m{{WSWizMJGNhCE`QXIMi&xd65?#Q*?QCbga3xboPpGqudMjwfPGrm zazojFFURN6NA}E|Ege7E^>gbLvDLe@?*2EY=W~fG-(>d}_W|cQ0~Hrja_|m@6KmPh zeL9ODuDRzbR>GbgY5Q`gbc5|zp}{zgzNR|mthXHzU3+hi8xlQl#V*&5sjj33_uo7n z-5VQxwbJ^z>hZ$P1g^wS$AjZ#j2=8@a^@ttAT+xs-Io1CoVYmxzE2{eXILAzTLb$cN;iSKapXo zOb}hAy`L|mDN)l>?M1NMMp>MaJ$jqKc=W^khq>G-(CL^;XKTN9MzW{TwRTFheOL09 zNGi?NW29x2VC%{8*4TPOg_~bL|8~tX-_=eDKc;_XEzW+ISKU_ADb<&yDvvEh>$E9$ zL(u1(+l{mHPI4A8agqnpj=E<*3faRoSiAFRZV- zCYmg`?#8^q{OASUTz$nSI^hdwiZWMagMo>GPP3}7zQ4>GnXONV1b~XQ(Ob1KU1HpX z)G5^XZ69R1jTzU2Q`@%v77t|XR9KR%)8`FVagA_^e{Sl&)qO7Wgc9~lBEeBGtl+yDNf3ldCmJU$de*Kuvhoz>BwWcDBUTO|{(1ehbV1B%Pf3H~i~F>n*w(~7BP7XvVe~IrwMx?5n1GL*_BwTp;>y~B zf#uBH`LIMi!B63up4p#(U~x98M-4OY zh+$C@;*|1UQyb*Dqgq8(0A~XHQs?}Y`fQt2!#>;MLNFb7W2Q;R|CJ6Fxn(=mx3QVedz3yr{Cw{oqbUfj;2Xr zUEDTf$fdf>?o7HePt#{ybnf%TnXSGIA?LJ&d5HbW5#Eistk^y&sLDB3{zH|}f`s`% zW-?^4lf_lgQPoF2;hXki1E$RrnEdm(=s;KJ`KjR+)`9mgOKhh? z+^xx1V~?aUmX7^*msOA0CmL-tto&s~qlGV6*jH16OAM83U}9-Z?Jpd_ME2 z;-6zO9e2ZYkCxz6sRk3=!K#v=>XN=Ty@te$4Stu*TSdr;@Dv25d8EEnx9aV2+obPe zeeuzW%2m~2sow73gyv;|2slALY6MOTH0c+4t81b7k;_5d4ejCfXEaw&mAT8n=rabH ze)Jjp5v7@BbY?BPClL)9in?f3=_BuBFg~ws^r{$6amXr!78t{Y1dWz55}{mTz3guBUpF|iS=N!fYbw^ZcT{#1@2vo)DT zsrP05CONG?_DA;BQ~6O7P7-3X6G)}u{9`S3f+cED#`{tR!vnMn(zUO>S#sc+6X{pA z_yTF}?>m=(hC{D+Q{NAm+ejC8(3j$#ENvV4l8{@f&yPC}I!Jjku7)XAswLn#sK^UH zJU@z|tUtD6`>G>TTe~KZ<52KUJlu$7uGY%qI)?3=EP z0c?T1bUs%)NZaCNyoedDO{`;J0{0<{ii@*kjP5+0fyY>fwpyV#QH&0@Ai+qT2dGqM zds$K;=jhI>nbyxc(?T@n4^PRbY>Y$BfMB(AOj*217tsVBozeQZA3V7!4`ibuLn*u3 zr?To!`Nsq6>Ff&M#Y1ad8VOZ+M$HCqAH1?QlTE+0m`f!4!W=Xqi0cmQ$b1P-NM_T& zSZJ})ELI@0c{#xNl+%Rnq-Rx})Wny5GzHM#rBzPb^y-B}mWG)@25?XPQ>|$!bx39z z|Ca?$T;O`9y`3{~r=&aCVr*SCm^r$iMX0!Xf?Y{I=TN*x>cqu%m$l!L^+j6iz8Zly$&Ug_ z_yNd`kw}vVJ8+$y;+`NLnMee;r?GhtD5&f>GBWetst4te4e>a^5|^h|GL4*Qn0)Cu zJX0!B|2xSis&7*IUCdcyDQ8_9CQU;Uj_W})nj4qP6x;lK!bO2g=6pXKV})=p_stV;x%ePkL&H_zFd?dxvrv#XsiLX(=R?IS+L4W_CPwwV}aM=3|VRkZdU)?fBtzoyHtO;ZL z>C#F#vLycBt_t)M5(3Yd1Pl z@9UNM`ZnVjCi`}MYCn$=?}8y*H!(7%K%>l|-fXmNCiS^4=)%IFHW!`h^FS%7Vz5nj zU%novLK>42PeZ4e&u_WndoU`f!V?U2ez( zP#Kp)JK3-v5V&hS!S2sA{S<4RWD_eVX{42xh_C=`B|=46g$!xHhhIu|zlJA7x+}9=^TDohwd>H_Sd*1RW7j#VX7R zpIbNH6(_vdmtS$26D4Cf6|`tOM?vKwfsNcUbfgIlO+BBTs?XnBP5Te}(ixq7+^)gU zFQPaE^-<;g41d%cP9fEVInKv#IYZMNq~iQWp!HTj0{BD<${j`U_JzvNDk&$}BT-H3 z8iQ)1mYl}0_pLa)k+mJqlCj0;^y14?p-T9Q@HwjJ$PO5tXxIML`E~3NsU4Boj?b=y zRm4vg{}}vPZ#JCCEc|_YYM)m-SrX{XNL)|J{dWf=KSN92*ocONS(Nzfy_|7A6W>OT zVlZ@*sR>>(a6bDq{o<_S<26>|_4;uI%v=+q_jj0V@E`OD{)zXIBHm6+nt7rM5Zrnqe`^^>jd67XJbB3<$>RxUAkh_JV&RJM5iK=2kA6Rf1 zrjskY-Y9YQ$~4!L(tb+z<-=$Z(N)=&PTs|Ok!GMDYv5zeK?d^pK1HQ+H;4Kr`;~~u zm?6zD=g(y(j%KNYI!#cWd^7AghjtxZxNyeObk!W$oOJcA#KSD(&r!}}Blnkeii69) z(BIGS+k5|Y)(JsdpnMYD*@reA|ANZ+s4{$;Di?lo#2aA_2Xb!EJma_N8^_V`8D)~wA5l11R#Me{7EMRDs#DOfJ!S#VBGEzSl(`m<|vh+IWH2Hdd=fDtD!Id&; zM8=}X$(-%us>_>1(g%BF@S+)j=5k!JLJgEI(wy#Tmn$A8h~0Jh833l4<`$-w&E_3y zsQS_F5N>eKfdZ;-$Z|@j+4{x+*M5fii#cAgIbOEjBO~Y6mHyw$VzM9Xwv;jRH#}hI zAdZ}mtyLH#F#<8JcUf~8h@!s=`^?$q5d0=Ttd6;Vy768zSCj%{+(fl?w)>mZp zeXcgI2B>78TDI*Zj;fQto2*s*gztr-Xr^?s)YkC%>iPuNPT)8{1~6ZDvql!{i| z9S4yn6kp`~=$C}HG3@v8do;nGn~|>gpyMra=6qA2AkP*phsMEQCxD#fmfQ=n!-L>$ z#d$x0#No1U+NYidYfe?vH{Z9fiF_$?K1mMe6)xXqFJxy zY8U2j`4}pb2*@x*FGGVd)SP-?-^X_9JNgghJ7AIk5$ZW**J?R>EN+qTRy)c`E z^E%xtDJaez&+ym^yo8vklX+(sRmgtL5i53z{xgnGln&c&+JG0aH{ksO$lIpkGR2=XByYpH^N)!5 zg73!4`F3bY%HUPy5ECJ>7){z;@=xPVZcOGQHi z!8rM;I#{v3mpt>`>chQbj^?T24aU+4r^xRP_kyU%Q)+X~q$KH@_2FyY9tC;K+;*+m z6lS*Ra$v!UW{#LruL^pm9qhJlWW&rTHO>hp8E2$^UU#>H5uLCMd!8HV;@p64B+@)| zm{Ar-wk4s^hw8o}7UPCi-0FQ_rcU}1fn>VLGE(I<_82RDF=q3ZdY(^9opReXV=LZvFEziffv-g z`CrBn9P>wK+(n!j`sQqg0w49*?9Hei^(`_fl*1CiTlH5ZUJJ;RQwXmG;duOk^KGto zmc9xjmI-9`T(&CXy^VJ5{U4b!_n?Yg_FNQaxQ zi!;vk9PpK%twK2T8P8mhlhb6cQUs6fE>ol4^SP+UAI9u8fH9=fb+IXBae2&bL>p%} zlp+Be8I`~mWIc-O(B%b)`dbOn6 zoa>W!<=q)RVU}}}C==C&3uMXP=Oh{UZ4$0L*5XOW3nLi#Uj|-^1Z5 zACbUS8l}~Ia(T(jU(}#C%%b0xsgKZDtkw2t_0p&pqI*M_*d(cCELRmI<$B$)wI>>s zpwTxjO7}REJ)t<;qr8PSw8dq*@N0T1mDb#0CVh~!2o(|Z*C#kqJwQLFy_nD43M%G0EbJFG1CXK>@qK*^=yPI!UKNE>!!_X360 zJ9+^B9T)!Ung$9+0_mFsz!$WSWjN0a=rFDVV{Pcz$Ix`(c$Vsy-R|)!p#HYW49hP-D@Z=0__#-4lp7WZ+DOKY6??dz{zSc*ESg zIKRYr(Q0SV)}%J7S(URYDj>sTOaCt0elOt`F&CJeZ9+H7cj}nMP5S6_QvXcFi#@ea z4gn)IH@IM8_xpspuy>>wXd(+H=Txdi&gPM z5mW^upsxuzLe2Dv1@SWA?^>ZOC8p!+ujd3hO42GxomA(ho9u9&Mup~=fRAN{p7>=^ zVW*b`#EowfTzg95Qe7JZkqr;SoqB;6E|F55vRPTF60zliWs7by@K?vU=mF%oS#I z@8O_s*7tm-*hYNi(tA#kMs!+y*Wql0>d&4Rd@}PmaH!k)v|d>eUIE0t2@#hP=WJ7p zUS*9W7o=ZW?hRbM@;s;eYY)bW=pJj zk5NvA5N=?@sM4;!jv6`QYmF{1;=Vh_-((`Kg@OP2eU zpDg5D__CN*z>nahx;5B2YvTlMP`5^3>}@xrfK}ml?>OIci__eDFSuEV*=5Vgt@!&LG9da;e39s9;g!_06<#S&jSi`h9iNta0i4Nm}$TL4HFPy z2WBz`K?EQkif~7ST7W0~L4dXaEWjBiVaFsZgD>qTi2`tiBcVV)R~I)gNk1^tZ(K=K z`Xh`ug(u3iG*pI`9ihNJ#Jt2=NOE@uDnvz5LyfP(NNbFXmqme_$xVy|lS{d3bxe z{I;=!@xxuZI0nYE?=I~qbD=(6$Xi&^T ze-$bU`L`SujHIF`9Ex=JG;nu!0WW)D#MkDRL^yinu&{}%l*r5?Z^{?YrR>w@?_mw>?E zvqBOI`y&J|s1Mxkx1T7iKU6SBsG9>EwS4?pum6xE{)bwC!^Fe|C7>d_wr~+~UJ)@d zAyf;Fy4l&x#8HX;S9C9Td!#Sa6E5$7;t|Casy=^n1>`VBxY@b;dU5`%y{{wu zSAtNKp*Z3d02v4hN(z7^L1Ik&|NG&A;1YHcg7(6^;vfN0UJ+YyAzpENm@qFKBrazA ztLQ;uf0X)PiYji z7ydu@i*Ps8Tb?g!H`u_En1|X)V%ut}DgkbPeRDfYUZNy;9%`mu0005$uL}*3kx7XX z;vm%_$~fDY*!RUTzl%+Ap>#azO7aGNA3wh`ue30vdiQwMEO0+vV(vqBQ_^gbjY3Q} z0ba4R9HBZShPuy$$smD(bR|l)L!?x&<1K-pG!*t82R(pZL^N~O~=frX*bRgiA_%*h>QK&n#xoZ*Ok*n~c}6Wj6y%Ht&utXGHbq zS=PuJ{#+}cbFZe*Ii;2@-MB=PTYf<(C&+?rLGjLYY|YfYr8{oZ?E2uPkE(TzjO9;t zH(WsV=7opmi9#L^my6aUt%*;q?j6418U!A#sX^U3MLOl077kV6p>qZr{8M1fJ^T{j z@TGwW$iveV2fGJUf$5Hj$~NhaPfw@H%E(}v@cJOqZ}z;A9Cl}1Vz2Yus&$XbqiopC z$!VCM?{H+~I8%Cpn5yGVwfdbjjY&9;n1dtRb;7-b;ZGNb-Z@xJBD&%66-?+7=wQkd zYHp^|o17DLcYbC>S=1Hu$dV_sw4X{( z@aOyD^=S;yOZ(~0Iph}@jhFQN(Aw-PRh}!^F8+QE(ykZ)z_e1?N4DzL%xUtUF}*Fw zSv5SOH&7hP=lFDwQB4VQ-ut})q&BPV;AGLWj*1;FHVRo2!0+`mfSNBQ8s z;sB*m;WxpzmcGlZ&Z5|T1Mhx-AML`Vd<{ROWoO$51$ETqvHCsyd68QOHKg)rwQ2G{ z{xbYY1X6Ks>fGK{!0{{;9+h{7zG$AWoebZixHt-(E00VWI1M|Tnb@`M()~!3sbG&; zB9L&geK4|m-NpZWuYF&})a#CkkJXeB8M91nKR{{kIQ?x!cCnl=8gm%H6=%y6Ds5^i z<6KYVXTLh3K9!_WAfL#>qOR}l!#cCEb@=Tw)u)5CUYCV>c>jtG1YJN_xWF{U@JVVY zkCg|)(cOdl89H$u2YxKAL{F3JBHu9e^=3mcfRcu$;^Tt&OfpE$f+9)2N~9yl;fhKs zitnK#Ac=lS7QB3VnVKCqK7pZdd3m}K=WBU8d_3VBI<-i4+B5`^^4&`UVZ9B-z(KO^ z_r2ct?bPxIyo+OS_%>S=TrnhnimAAZr4;e>e77Q7w!?i@SsAi_np{e!=@@?;nx~Pw z6P0*oV(wLsn%aPhS?-mm_z~x95z~L|A)|{O00eSa>G{_S|}JzTenh zzr)fqyLplXiG9+tQS-PpI^|(0>%oUG^udgFVFUEq;47b4dhl>DzNps=(pt7<_dL)Y-gfMg&Gdi z-KtJQ12nG$aGx)E#nFm;$T>JT)Xn;wl0S@t#;h$!#2r7;@_)^0NkSuLMd_a=&0F!F zo(%(Vw!d1FN)5Mk@-Ybr+#1iSZ;u|YICvtLH=L!0>!lCD7h~&bGT?kok954qHW#{h z7pCIc{PsCLPN>-);`*;_NmM_twuys;C?dLG;F87=j5YW6Yl zlkbg4GC>u0SrZUNWGX(wXD#j2p=X`SwQExTwGiUy&iYGY963 zu?ut=O!guwuB<)pPaUd{;TgFY*y9&U<;JGei7-ea>Ip(C{UD&w>&L&!dvmCoF>J!b zLoSfYjiq3ox0}R@Bb%jK%?Y^M^xoGK+Re#Mf)c(ibSr!)FUVvP8mVB);3u^o;nn&< zzyqg8vS4YFMASjXDD&&|*Xn}!3WljhMYfBDpP*8Vu33fKIUW2+{@I%pkw0fH4&Zp?)$tv+o<>ZpeRXo%h_dN^&el3wV z@P(}}vdzhuYrJ|S%qB^gIU8by@eyEo>{H2i4GJL=IQyRu(v>9gYGFz(aFPs_R^7K2 zdxowf_#EXzFQVe^?kr3`R3r+sW*`Qqb2ni9tRf_M%W23HPsNa|3B#IqO!lP}Q5sZI zBb>i?x<#8gmON41V}jwPolJ)(5+jt;+scGF8c$NeqZd1gPR~Stk6qFBEi-ez1ODe- z+7%O{kNCG}l0+mJ%;XufQ_H!OhaoKJuJ_%v??11vTzTcCeIb4@q_i*{_DY{p6X<($ zy=zfn#5|8z-JDZe&{^t$&PadfPRLWUe22`V^QJ`R*Lo`?gNEDUMbO9;J+oQoh4ou~ z=0bGD;LI`pR+fj$P|e=WlcQ*2=m&+~%YCy!=Uy(wf`N(=pR(tScvAXG!5-f0KN6*< zNwE6SUL1s`l2=QE_o(D`?hg+sn0OAi&(1Bi9%s0-3P6*KL&;bPrkk1aY$-nC9usNv zacyB`Td*%BaWK!mf#uyJKiZ=yJE3|$S5#wk{ViG7UKgPV4 zai^_znk%?eN0{hhCiAflSI^_a034{-4%jVp(XvdUYIaMZ`Adk-3l3fa2u5U2{>$fX z>BNutKQg`dKC_ErQxp_f`#yb+>w2FY|MNm?#@dmMCbBc~Apt2l8>yO7ue%zSoIjt! zb5r!SX_{~@=DfElwUji^Ql}ju{#Bv8WFNJ|vg+W6V8wl9V=C$xWaupPg(D;|e_mH+ zVrCTs3kjVF$qJQS)U&nzqXenI}3pI`s!45+~3b9 zkj+*wpDp3Id^hz8qElhfSu$G$I%e6KYov~M1XV@DmF^xg=U_MaAJ`7`2h?nvgqe(C zMeb*|{Vd+8aC>s5oxi~t-&h$>y_z_nlKkA)YEXV^88Cf|Il)~TA#R|d%WPI7Zb{x1 zyff_k@@^r`l2ml831y=Klgt)7iSm|{3`iW z@MH6@II~1LaRsp1)ONx{lHr)UrAm#hPsDYzzY@z=p1WOZvb=L6HArUH4i+%Smb{ym zeUDC1z$sV&(vK0JL4r{>WiyE1x#6~6=7#yC0$J@10R%ap?YK}5%WVd}l&OfJWEIXP z6b)fab|`9dCM`-d<1$Q1z_0atA_bO8y9Eioj($%{x?LJ+6t6&S2ko1qUTJ@bU*Yfr zSb8yvrj(p}Fy`x>>rB6+_Wkf7QiRMj{i4;<_U)7CI5pG7ISF%Sf8=!B&{;P9ilnhC z+eLwQSC?9!4sxWpWY z?OFBvtgEhytGjF8zik!WRo7j+u(o~w^UlqgnS18koS9n_nEO1FGiT1*&U?=9^qF{h zd3klzx3!vt@bky+dKWL@R`U<}yo5g&S^|vK2(ceNuL9|Psho;1Dwut$d@ zJbLXj=nec2RNsbr{TL{3_N3|chdnwR;n8cKK|i$cZ-gH1-ty8* z@98qqYw!6+@9gr?>py4fH{|JS6ZDpsUV2ZLhhBTnH+pB6k6!;dTfZUCz`wE%=&g_E z8@KWFGPWaz`Z(qDSZOE0}rmnZJ^+H24cyk5ZbkF(2|r;kq8tDokl<9g){ zb$UAgyf`nvG(SyGr}N@8KQGRcXQVrZciMlv^3a=3%jdbVyXnH!G7pM7oah^OQ-N64qb%0mD&b9P` ze8EcN<)7xE>FIP{oaX1ne=VHHS6)2%ymX#EN7H%w^`<*&kF)vp+V3d6Uin|nt@m?=KP4DXb)A}5ZyV_p8@*T~OUVc~GN6Xi1-(aVw^XKWfUVj<* zw|{TQ6=kir{2Zm%n+Lu6X!&~i2Rl8TKTpT?`pdw-fqy-9R&V{HW$Wc1?DTa0JRKkG z{&KZ_p7y_?-?8@8)%C;E^4(oOJe^;6>vy+*4SkN`o%Wx*>x;Yf(fM_C+}-)}v_4n+ z(~$36ywm>lbp3I)emcLdj=MTPgH67x{b|TI@b5^ScX$19#8%{Wx4q8RcfRM}+5Xfk z&r$z7o1bUDv-R=h@$7MR`e3)u(fsrB$4hrq|M||(^RK(pdF3(K?BUt#XgV*yj>`8m zKQDj0bWhtq)b;cH>+W=(KL?vVJbN8Y=jGQ?`JU$I<&T%{Y5Rw|ex85bozC;;V6%s3 zucPU7ejSx}uJIfG8TxBL=USa~W`2zNJ#hUt{4=nBoLLtQS?>3>QNQi;x#2ha{AOT$ zaQW?gsmF9a^~Q~Q>sYu*=n^UBlJ`f2$*dt8-H+o3n^D!ZI5S8u*(dS}~nzR9Eg z>FGGn|L(SrXOF$cw)mAgjC;rC@SgCWt#UnA zp1azoJU_WwzgGD?JMB%^s^6d+oNa@>4Izw^ys=URRpEq^!idwF>Q?^1m?_gpJ4Pv*zjW$nqluyi{+e>{0C8wPsDlSil1 zvgq_76zAbyneMT7<P>g0t@g;)YrmuPdTrFJkCv~Oe-P0V zd~dH0hLej&z{#FSIJrc)mI_yI1We2Hk;VpgW03Zj-ni0VJYFTOmV2JO!H}*cA9`p8 zL!Oj2=&{`yv`XDt?)B=VW$NX3BR#?YO$$cAcUO&r@2*LP?@tKVwPWG?>yqHe><}6M z#4b92?ucvEP3W|S?y%ia9a{6EmCjLnoXxM*ZfDWywO_AZTE1R>H_{XQ?-2Tb7XE*; zD$>9|U7oDC8_P_!7UK!sEFU=XOm80a>f*`QD{rXN_xpq3KPAG%#Q&*XBW3&#lxNz% zG%cOZi`(L-pVM)kTsocRw>M79JzwMY`p*`hUO(EBW9vCjzAe6Ul>pXDo_A6Pt&Jmcx3(|NjRdVAwMJ?Cq>z5cYtr`M0R?)i{TeBrE6ug~=A<;mA8Z>ZDv`-9;B z!8IdQ`2YU;F|e}IPih0W_*eRv_Kz}6%RS9+Pn@U69+}9)lRH$??e&K(KD~ahCC7Mf z{~kEUcLe_@I>MRwKQTYlKK!%Fo@0yC_ZV3=D4*GDk5WeeJ@MmU2$}5@l~*lxVtHtx z8;C}-MWKHndSx1`J}A>|-Lv?}Gh00Lb1iu%GL<1MhZon&tE4CQJRMrnSCt1a@&CZa z5xVLCvB{+&!Jnc|G4&BTTOp6%Ryrk5i+?>qBVo_O_7Xen^#LhcJ^X}68S3HJN{jNf z(mIRIRe3sdmG%BVj{pC%Ki01NiDhmJKaM^p^_eG!(Af%k{I=35c~ZHi3S*@zVa>E^ zG*`Ph`31m>a?Fc(g+Tm`9M%1V~g zf?wif;VK2c(ZZEb2E$?tB^uwTeDIH}0RPxZ2*7J(m3S$2 z(f5HN>5w$O3$k+7LtgGiD9YOeMLBCAFJlpmPq5Zc^NtCd09hjoVB*Mp$QhXjxx$qn zn+qfSA|#uX7@;wm8#W47XH>(1!WKAIG6Rm6w8F8XX|OZ95?W%%NitAxM|?7L#*c+A z;hG@)Xi(+c3U&ToT-tpAAox6~Z5?ir|I1VtBH;0G_DHhm(`i;lhm3 z5M(kjc^gLt!n(95SeGtb86#j_CSH-y7#|?fEAvM5PaWe28;inVV{sVt6^BA!iEvE{ zg}OvviEl$`Fo;)~5S9mtS9hK~zkmNwqSg5y#Q#TE$a?^&Ye$PeJiIdkUOY4cUOqMg zP92VbdoLIcYno&|#3oYbq|g?g^gbu}Ua_CUbKE-~F(s7t|pOCe;-3JBS}5{CD!g3yhtA#}qU2wlGxLRYVWz*+5JinlH^ z;(y6bp&SDzH$znSHi((O8)CZlz{q)fVPxlp5Ic7t#Ln3dF|9iwD7#tI8(z8;M$I@3 zqgszZ!t|q%(EKwP)pSs@Il6cwjH$mI#?)N_Nwrr(Qq5H`w(4r|k1m&Jh;E-@@i0Dn zBNUcj29qi-gR;s?p{nu{sIB}NG*ljisg*}ydetFlF53fz6XvM+QO>liPFPd36E@WB zfK4^qU~A0RE(Z1(X%juyqj{T!3}lG;O6>XxV3&M+|jTEe%r7Z?rm5EziU_k z4>in(+bd_mn(?`!tY;cK;8fEbc(JJ+{?gP2uQbhqYjaB^JtSWletvLEZVvpTu@1hN z)&O5jZ-6gb>fy^7b@1h^TKICdaJARKS97c3tBxx8bZ!MaT0arG60F;j-8r%Fb?;>O zX1Q>!m;~RfDuHiS7sLH6<0YM>JTWBtf6*KdXLjYlnLQKX?A~lRyDtmQ?$3f-=gNJ{ z*9TMKKS$HxKgWdd(h2b0@f3J}f088Q)V4Sk{=dIr42%jf!K5TJym}-Cez+w8emFS_ ze!MLne!M*ne!Mdle!NS#emfH0yFL>3&K)MnL)(<);Iw;!XD#?t(hxopD$^XeCuQJO z5Y5EDxvx_4iTB>=D*O-IBiD1^1$8R?2klq_-etKEymbkLY+Y^>|6yy_LHL^W5Vm{` z_?DDOIwkvr^1yrlk|u~=xD%om?6Qgfxb}-6uI&IsRtowi&Q{@n^t5B(6Ok^;3(s7{ z#D7?FrX4OGxtGXDPi#I_;pfHZ=w;jW>H&R8Sm8}*M$TM5|}SLwok zN7Y3zYw{Kd^^?z{rAFs4@!yl*E$JiWL-HNt8v@tVEZ2qqCmTDN_xJd;*pw{E_J1raQuY5IF3XeBF;AooAo&aS_G04yoh>O6-!p4QtMLEb zHcVV{`hc7uV}9`utsFqi(kS=LL$!zAt?vb zfm#**y)T_1`NG^&%EZ69)>8iFqVY`p2X9}h6aRe>v0@YW7M4o7(MJE`dWc%QT^Ii2 zXC7kWKRjoVDBC+YnTh}S{M}Z%(N+qX4gNl5noaz_)l?2o zRu#bSh57&MQzyZ{+bhNKKk5Go{=Z&S4wn~O&fB~+Cr5?K%rs zH)g2D|6lFPka$kc8_C4~HFGTMCNr~rnfU+V#zfut|LJ#8aNph_NjKU@%EV(K!959` zfP1c}@_`%`a3i!R? zE7tfQ@xL^|g4O#=N}2fops5CyC&*(KVn<%kFu1!s6Il3vZ(gxz>qFDhnfTw97bWG7 z)H@7`>_7IVsPKRGKqf4l7%0+QSQo~`{{t&!JHNalNqYYe*Z*+-Pw;>C#!>Ll1re~n zEdX}3`oYypg5VDqhr`+1M~d@*GXBT@AMyX){lePibPv8mOmI#@XW-q23{nPOJvmJL zo7%F)GBD+jV&dOtMWa-Xew*g7@qa-tco)gzL`kPmzkP~}#q~d&|10qyxqLGOx6G4d z4{u(;#D7SoWsOlO6Yu?!%OS31KePXjtJy2bjhnnnh5xaY*MP~}a(*N)=RYQ`8_K9@2=epStC*<8ti9?Ok4f`;i49ahR~9*FD2I| z{*Pu%6#1U2sAl5-$_!yGxWDaTg@2k>AkP1l{r}fJWw2~~BwSaK#Kixv8Z2!N%46aG zp1Fxk{9iiNvWH)l=)=VSU$)EZ#cy9c+9v*wbp$i>G{4*jPG27dH2!~jU~RAFC_TL1SJ`hW8>d2QPFV4KzYKhFP$ZJj0gcG$9JCjR|< z+a(%FpQ4WWmRE@De>DChmu>>Huy=(#Ax)i3{0A0Jvne|;Z3+|rqnnONJkj}UnfMP9 zaF2Rz;eSH<5=n+KPkAY`Rrv3z-V0;;*Bqy$&tl@gFD|8FU@l;>>)#qgKvT6m?V241VFhW{sAZ`M}A%25OFn?E-tpNaoVi$_CW zW;7H3PqZuAHd3dBkl1>>K8A_^d*;VWH2=IP#cKT@=l>ralGg~I+%l4h|MxG8lVlKm z%CNP-3}4+Q^!vj4AL;)Q|Nng`5>_`W<}EJ7pbEzdABpXyy}D^RjJV{Beo*%R zi2w2wOMhLQSjohHXO_IyqLhbuxVW^7IsadqCeOW;dB*$35phiXKT=*N`HSWmD30U* zJ4(~x%T8e(Kv@5$`~S;J5+T@ZV&ebxMV2un$|q%{%;Un$U?%>bUnArDwXI`S`2X&T z@i0EzBKe=N8^8b z?qZRC)bJ!G{#O*vx00un*`8dRx;Us2Kmz2ov=q%ij<_K@(=+L>1S|JeWkx!(48 ziSUtdb>c|4qa+JnXe@?*wF#IP_WxP)e;ogB%7_v5zqcUYYX2YC|2|z+U}YOAC!z<# zFLnxh|BC&8od2KRA@2b^vLb!rWEN#J_j5rF>2433lTj{TsGywXpwZ zS^vZNKlcA4mTm=8;BfFVo0<5JXkH`LEmE(P*zp@v&cy$S{N*B_$sEYUe?s9!lH3U; zM^)>8g(VkC=|nH)0k5i@UKRd3O4dpAt1CBKo&Ul4|CX|qQaY(?L>`7a3T6zr|Nme^ zx3C{S3;w6L5q1h~WqDXM+*#J7!vC97TA?(=dTy)K(-Rj14@}B~51Xr)=YLrE|9Ji+ z$@WuiSt|U0yS@n8k}NnSd82*y_J%YS{?8oDkmTMlCz^@>n-^Nv2vQ7DB$ROA2u{%<5yWm?7;wB5vhr-U@#>A2qZgV57*Y{W_Vo7PWa;@?!2ES7_*E{%zQ zpZV2NIR)&PFP;A*>;JyftE61UsCC1Qu^4uT`K&SRveSkiC&_!a6-EZ|2>u4CHloB zD^>X4SGx(k`}gLEJgi$pCWafb8{o#eB{t9hk@G*e|MzsmTzITb-Tx#0HzvtvXNdgT z;UVx;X)*WwAC3Pn7M8)Ge0d%2o~9Hg{*RQ(>k3ND5dBZ~B&+a$R=|H>snGTddG9L^ zVdDSyeX`t-E)~uJ3*Y}!j{l$BX=xu&#z1xN)Fq)z{O_9QhJ64VxRmTAc-9;8tu0>Z$+wHWmJdbz08b@X8=)b|(}6{^gc)E1@k*RQSj9 zzvc+J{t=%^c@oM!wsE&~{+Hl?RLud&=GfwGD*Pu`oB*GobdhGXa2|+t{%1s#rCk#9 zrNHX=_zD&Nd#m?AqHz8nY1?zVnfRX^C!dvJVFY>eg?9jU+xFU5? z;#26gdd8Dyi;wr5C$~SH_`s`n3>*Ke<+W+weY2$V|G56|FUj;sp44X!d zhb@^Ea9Pn*_;tl>c%Z(Md;SOUe>Zi;`h|)LP3M2VoLdF22 z-@mY)iT~h9ZA{rjZg}BhCjJ9PTlO|W$F(u>ACKDDjW+S!Fw= z^FO%$kNtmRhNYd%k1t{3e`m!?2==y|X(hJPa>;XBVP;?$EKSOQOLNQN;hGuD`TsLj z^^(8l#l#GF{`bSyN_e;`7k-wV1O>rzUua7|KL28w@a|9l`#%K#|6FZ7<{)hwkyDc} zjEVnO`z&)$qohub7_`U12Kx z9nptAA@>-D%v;3n|NHUpJvNJp|8U`*I3h>sXYwpKy@iSYu*`0e&o6os6aR4&<+X+E z@+(#6{|gG_H3YgokBu&Z)VMN8iz|f;VXrYuxRN6?MScDP#+C2?;rbuW{}0q|gk`yM zTSn|BVQ*R`Y?{~rTPN1THsRViu@;t$>z|tm{v&iGO!p6lr|M=%@BiWYKlcBxHOPAa zmuI9i@&DnpD!4RroJuBCu-&MoXAhNZQt&Z-~Yq)f1Lk+vezaGJJZi+5W`0_} zy>XUZHe`|VG;OO?ixeFt$mVQf3VJSVm z_+l0QCr_65218gYjg!HgPNjH(TBfnYo{@)$7-H_~W-M=5DNPPdFtpDNsKdyYY#FtQZK!yM0va6-^aXDL6_{aDEeSK}$E2Vz=eqqrP zoB01(-Fi4)w+{A~ErJUQ+F*OZEZ9{z6J{pns_>8R|6f)-O*nhwE!j$RjrR)_`u~{& z;{RYu3KRc#6=$pD5xFl2`@Qt}AH@IWOv_r`$@*j_{=e-jfVY-sL3e71O7`mf;mq+r z;(twvW$$o)u0Iq1&s`v&6a3&>XqH0Ej-fC>A0iqfChe2wx+fWCjQOy``5aMnVI+>wm}}>`>mX16aVDk6pV2uIow9sLzGCZks_;L$?x@5wGJmrQ z|KrO42mB)@i8P~Adztvpo46V#rZ0lL^o3B6z5t5T=fkA*ZYWFdf{KiJP?gaMwHX~y zpD`Djg!zABsAcbMc6K`#|5wzlfotkkOXq(xLSo^HvQFmy-|bcHaM8pHSdlytdWHG_ zfy@&4oiJ}we*c4v|6i_`_hU+eg5d8>4XX9O&suBYf6H@Wf7%$>G%g-CjgN!vsqyf? zwb{(`e~AC$a7*95uOQYY{=eOv4_|J|gXb4bfLmG<;O180-JGr@_}6x!@2AfH;P@Z$ zU!P=|-(y*RbyQgQ6TbgJ*8gz+fBKNTwsdM&tWEsm_dm|w5(lqdG6J3#zW?+5(FpkL z*TT7<{`dds{{Js0tlKGNz0!0~)8GGLz5hqn|5jG-f|?1IwanUa z^}6vtb4(sI#-+ip>w1{q|IxbtcmJdc$yex~lX*ER{M-8e55517@BiZYzc)JyB$=3^F!}$IW8UKH@N1p$qt?%p}tHM8i|BsaOZ&nKDfT{QY zw0{4C#(&>TCy)IVcvIF<)%^fCRncmd$)O|u!_a(O_y(Bp{V!?#PniFE?~>PyeAYIq z@bABGf$%L5%U-Kbb14)5er;1Bc>Pk<_rGl6KXmR=sa%PDe%TdF{D+py?;$9CMEJsT zyO{V79&5p4aN=|({$tZti#7y?<~RlaGjl9!j+s$eO#H7aoCjq5Pxt?;GHXR!I+OB* zF~DNG_W$2#YJtV^@}3&;&tsE>vp*WX|78pRhYRF07%20T-a_&FUu69s*Z)qhoCtsI z%>+I8zokPy--B|WUN8K=532vi|NptF+_IK@cvc7#|1Vw~W%K)Atp5M8!WpHE0C z6aS-gcS>?|$}Z9T{V)3bKkolw|KD9K&u2DQZxO%$r(FN*OrHWBsr7KIb`8+@-(4v0 z!%T}y72daFjt>+6cdiSAs}=>rw>Jyl z{-eJCN8|sgW7N2x#v?CoC;p^*OUrjuo<@G+W7DPzHU5R~f13K+cvDp>_^hf2pA`+@ zySxc}m*F)9%vJqsM!w!m{QEDE&&&7<@0tcJnh&9C*I3Q}Ll-WGfI4BU;cdN6Lu|t^ zv~eMXHT77&|J$$>aQ~0j|9gifLsY4-b~stMg!l2IOEv(0|1&I2KAV&%tmonPKb7PE zFcNJ6$S9R`6sLNdrjd{ypif~QOTMDgtOJG)B4>V_4 z<`bBYwyZW-ls_MO^1EPJ{ybQb-wCrP)QS3vq9(v5VeRjD^)hMxf2m@OL;TS-CL4|w zHo#TCV#3C&B;Q zZNmCOeFn@;V82W7$c!{5{x|1YY*>{O3XgY>gO4|5S&jd{-J1okZ5R(n8%IcfSK7C{ zI1rxQI0~NKgjYN~yCn{uy&w*b%#`;){;(qkp4}Y-&+U!2T>GNnhGmxY);w=`Y)?3R z_Ny4_`=5w^eE;W-6X9@CxAp!6vp=TssW(pJk;hNdyC_clY+78v#J{=K(!UeBfx>_d zoj|Yu2dxs$2?=$KzPwY@z&mRqn1bapRMN2OsWP3uC-fN7X#>UMg?D;r{HK-+-vTjN z#+E4)`SEKl`6&&Hfq4ljFh5~D)I?aHeO2mJ`iSSJ z=BVMYaa5mE(Wx|F3UU&pnD_d|-1)ILyxslK6=n z40-k`Y4zM!OfbU*Gls#61|POw9xiRA>&2%nIpn!sd3Mqh-lH^Wrk5 zp9r5a^jq4h!asih8{gwo(hYP^*HJC?z#blALrl&_CjLWWEPe9ml!Z+Ej~ONJeG*x& z4z>8gmJKW)k!QAec+biFn9yy_5xxb&!2kcvvFv{kI$lWZawNYz9jtVvUgkZ)rXwN2 zDNhEWb8#s7AuW=LfA0@OceGsfS{#Q!Tj_Lo1A{rmOtaQdPoIDKFYoIWUAhZ5m~!-){(FOMxHyL9Bs z${%!nvmuA4$7Z@xJ}q0B=Ei&CUkuGho2}OWvH$nk-6CPvXH^3z_y2JHAOHV{Da*2E z<6U3G#J_KYy!SMqzdexe!1x9x{u44ci23&QOJw4|P?-A@-wl>L*|dYMYkK3Hav^@e z@bnVl9B}{pKe+yn=19Im8k=@9^bpxktc$nW|Ht+J?@uJd*7`t6wuC!|oB?&} z^#_k$uYOO`3wa?vHt%Xs;UEA1kC(UQET(s-@c*>>-~Yq?e}aGShI~S z$MZkcaq=1)(@qUrszyF8le+d3>TofUdlZbyCa%}44JY$$xdemzDAJ_j< zCtV`hJSwRT#-=QQ@e{gXf^elxmT=^f@yk^e!nZ&e_`hYk{BDz#zc~3Ja>s=U-|J)a|F7?t-z#y7 zZ+SlB*y|J<+^mE6*efp<%MHPFRRgBxYzYTGy}}uQUf~SDQsG+C z2);c{;3NE>NFu{$iZDl*KOOwKTfncY1^nl=f`8`>Dc!2&qt{-&^jiJqL^|S^dC9}!@wQZWqJ089 zF-N#MgsU?JPSh)KO6%q1kH~&#RV+N!7cX3K@YLp5czSCr+_zdWuHeYgj7{1;I_@kz zgG3JTuRB7!@Iw1vOI(9*_2k#(c5AR#bNyAwvXw_?=f{>F)^km|HROSoZI6F6^YH4N z!d}fXUBSb%(?&Y&OIO4-mAei5T*a#;pSpCrqD+-Cb@+#uH(mMCpqHl)({*E`UoTI# zZn;XIo=f){%E{T~KGfxry7lv){~WHp_F8Ro6<6082g{M<3B%srUby3qJK(09Zi4C4 z<+U12b6VLs>JMIi9hHB+@bmm=q^s&Y!OGijzYSk}@r8tc@_aCdh~I(iTeof<{P4pM zKz`qS_Z=KOc+iT+X>EYAZaIoKr7YIHqw+n)Px9g_{Y1VIs&H zfBRb~DJc=te)-E^!n4ml3v=dJzV(auci(-t#D{c`KKdxU^wLZ4^wUqn+O=!NwCA3C z4v?4VU$kfuU>k&Vk3IGnw6?a2X~_S?6HmaO|NLjT?z-zlT}nRWzw55M;K2tUgj;XD zRiu0P;fJBTyj+xlbDC49PKh#5F8(gO@Ipzi!#KyXc47IP6S8SMxXWL(US6EGi%0M5 zbXva~;sk%&w{I7*fq&kA|9$xK%P+7Nd-v`Y@A27R|N2+>{`>FY!w)|c+kiLT zctcD>>@HlmP`t-KD_2_H`+xc6m&Iooe)Q2t;&>c&{p(-8Iek$5Wcu?1w zGiO9P92by$JA{8Xl#hY`F#FqAE%>C%Pz#SUX=wd!juRY2M@Ng;z;yt8hW+lp|NUsX~g8&vuEM(;ltwd|Ni&CA|_D|Vvfkn7QVfE^ypD>4DkBv zuZ!&n(#)JWQ{;Q{$tOkKQ>IK2>AJhSMfqf1V$`TnVw-_7iQO39e*5hr|A`YP#OK)O zZ>vv8GFIop;_5#|otV zKpA+Cb`yEJ@sDNh#_}+!F>_L`W6`;GX+xjoAK z=Rf}m-+c28Y}&L*q{Frdv5$Q<{%{`;>99}7-?3xIBwI-Pf$a{`goK2M^91B4c9C_> zH{X0yY^z80zX`UX4E*7Ig3JwYjDU35CgG2? zarjIV{*`6z;qo%t1C8y0vdmcbbUCtUT=|UF@1Zzi0I&V~_luarb#|PeV_%JZHc7`b zG_St;syHskez>QnN2Div>e!c)IsBeId&IO|yLJJt?c;M?w?j-LAIijgT)W49``&x+ z73UXtk90^+`fO|~koK*&-hwNyyb^G1kL?q&3q$PJzyA7bzJMIi9hGnJ4?G6o`QJ#l#y|SQ z)pbgz&uN?^#_4AmcRKcoosRm0$gveVD&OFDeVwI!Y^yBY^_;ec7k8Ikw)F7qb2QzS z-og6Z(fm4_pXVoM>pNfM@%-xQbiICdwLLufdhOLq&(lBH()H%gpm+aRK$S(z^m_AW&}(lm z=(06@r`>l$!B=$o>WzCkk3-E~Py5T6`f1-gQ??zIx-HF2kW_uc!Srkbc^i z1JN33p2x1Z(OfFXVVWgd!3zscgdsu>@K~A9{02r}Jsl z3EOqT@QvXcULBzEq&Lo!@9cEiK4;4}X2J^%?RF{14_jK;waq4`$n0w$b)G8fWP+o*9@vSLy%{A44sly!_}*A8PqG z>^0gZJ#~PG2R*U|11&EHcMp#3^)p?*dgJ!$brzqi z?bR!vNAIkB4;48)f4Dkbub*6P4^O^cd-c-u^bfXlz4>!BJn~T^!;`PqUcK}@{evxCZ~k0O&-0J7_4D)@>8|_#c3OPv?DD4N zX|Z82(a`qmjq~!NSKd&k=lR1(H}F50>VTtof+CKa6w(|AVOxIEpV`UL2J_*!g++cXj%&h5vJ}yj-o1mao)3818BNcyUMT7f=3R zOLsKC2EX$p&L1hBB4V|Dy4LHDFP0SNSDG8 zQX_-RPy_#s=li~O|M&iGth?^4#o~Quc09G8-p?Ost5W^J{09UAp@OU3*M&eX%0M9J zZ(O^*G}0{-rg zz-S0WPQm|?jh!pP`<5-j(b)sWfopE(xaDjQ<1iA}64H8f58>pj7KlXX1#0Wt1-jZv z+jA($-;(o}0SmYzylrmzySsUyWc*3dp>($4En}?*x9)i& z5x1lTg!%1+goJNNN(k`b4X5tY34uMY><4r%Wo zqkCWFUz>q97>AR$_ahlWK|en~0Y6azPo$%uu(Y(appb~5hzLIz!H){?@V4>i_dwnL z_X_tBC_AL{BX4IZk9?4Bzc;tH6GXTn+z}q$C@@y|KVu&`d3t-IoIL+0OaJHR|KA3Hwpv>M+2g;2 z#ohfsTcEs^eE}N(BFKL^8l@lb2qCD8KzaHg?GVbo0LCAz zsR#cC`Id;7fW)mkM$R7go_;8v|7HT>zKu5m#sRn{!7n7qFCwllEG#1?DI+chUS))Y z{u!#}Y47Y1@ZSxU(iaw$5s{J+2AuwHh60(fxAC_5-ww97lX37wy4wJRo!xC55rU6A z964_Nhm11!Jl#BzU}FHC=x->rv}E8OC~q4NI|Tebj04~-;OuNKVd%iuGFK#1YD}_Kv@gv0Th4>MY zVmAEJk_ZQWI~yTkX(0zG8zCw2f6v!JI)kHSVKi zPj1e)eoKLjjoq1a!#M2D*ov^{_}ACY{{;p9&oKCBSwANPSoD9v?tg}%JRQ9KY>)^g zM?kIrtvCt(&wxkS`2Md!M@Wc@*(0PS`4I@fK_Q7V=1GZ2@=J*dNr{SziQ9=u+WZ^! z{}FT%nKQvV6WrgD`hNrZzsPFmWaHt80J>6;@rhr9elna+Zfs{CHK=&U>p9=0K3@<%HYRobYni8y!u`qeC| zUq?Q;y({|!C|G{Z<^tInR zq&|*Zym66q`f85iq`sl+`n9#qFl8aNs@K@wj1z(bnx!+^-ss6c5K>ZoiJMgB2px%M zaq*k**>qB_$g-EkxZVuH6(+Pum$dlmLw_$i%o0gA!{x!%D2{n?Gw8IQTRH`6`bn_K ztMjtA?^|8Qyw7d0*H||ig{9|o5koB3j?bM<3m0HKFK(oFPGVvEyQ5qhRu{cd8I6$j z{3~M6&{RX%^;}&W zN!LRcSX!=R<^gW~=YmQ!>0W(; zTzw9*6^1eE{Ns}r)o=L5RF;nG^Ngc?u5IgFYi>xiRqkO4Sd}_$sC&alChrq`4_+*z$^sSAO5|s{=gCX6Aes=T#l*V30X;4+q4H?AO<@R?HjApU6#*b=k z?t4&k+bSuJJbQ!3K`%oak4-$8Uxq3qVe4$p|Fd?Vhj>@Rfes>2X^>kl2IpDGh+AN( zXT+|oqut{y%==`QZn*L+3i%a2>th{{rSp0_FxxMOP`CFU9266gipM%Y^bT&G5F4j{ zi@C8xq^9IxMF~@MF1ECo^$&YC@d?%BF8qrU;Ke$0wSwD=k3t!w9SdGJGIxqF; zZi*hhx*WD(rHNGSPyUC?(v-R}FHXBIhn?K!>0XY{XDnooof1UNE~-cG4>&~o4<_&| z$}Tm$;)tvHek1dvmOw75Xj={6drpBnP@%09%D{DOvizGPirF_E#y;7>1@3-qOeAK) zEe(RBc>SqyPH39^fS0>^a5nWyu`Ts;b6j4+${l!nG&lNqolzm^Hl|b9>^FhJL#Nb) zPhi@^TSj^@)!CZD+XA1Z+cN2PvTpM%DrCFtqssH13EnjLJK@zxfPYUy2Fud%Z64k9 zw67lQHZ;@oeIqL>nsF79+X(8VNqt6t>85Z_Iv%%!BUR_7bo<1r|)(D;hk zOO%&DK`I8xh3R3*2$RN8WL^2aov8eU6FMHOP4%juK!-8X6P0sp7X%Ga~E-;Zpakv zN;MQBhEedL>hts{D&;;H1(3*z^XVxK5~gk%p18ud%cO}Yp2u(fcqIM-16xM7G~uH( z*sK>5MZ=*ut}>zbDM4FYide7v>HRqUOfzP!qz;W$iQHvV$2Z@7VQD$joN)Zc^*0tB zDP-Nv*1W5#)#wUxVUU*uU+vt-o$z7dXaevkD5-8XsOXxbY6vbC3V>+jPHub(A2%csz>hL9}L2? zinYWQCIoAE{XPLg+(c+V<%a;m_syt+;)g&X7B$#=CmS#WL}-P1-|DCw`Hc@e_V@DN ze)_Myo=WJ(sDiyzO)?&5kc3QQ@%IM;jC4O$Cub?HYDGfp#oviZBxLBBw|es^CvPuN z-F>Omb^Z*@4obHI`9C*y=$58Z=!^t2H9}YyyXd@1KZr0SDmvP{#P*Lb*kUH z`>1^jdJy{+hY1KUjyRhP>8P1awmoj_^^Nv&E7m5=jL~_$kGeY;z^@$a>KvI#SkoNW zV{ZwDVie-P;t(hebTw7mgF)WAzb8}w@LxAd1S*?fxmN!I{KOb7IG$1e3OijzKUn4H zU6v>RIe-I`!tuE=W?o&`Y|)N>HRAOK?)*sM_r#9SV)#iWG`mb{Rc)QPm3R8O1&6LMzREC$db%o9UaEX>0 z=T?tvM{`iuvC@oO7qDo~TEA8B%X7WWzeu-@T@!E6_1ml{#$H6rnRx|sKF&xip7Hg( zjj3&8_*jMTE`uImqL;WiKErG0pfmJ6*;z(r{*o~|!%%)nE9)W44&=filnS;*}s}{0yao-fp68-$?d^+|ZdZ~3D>6s=X zgL@}^^4Kv#cvcM=*0uAZ(u#Z7Bhp6J`gRvKX72LIoP=9ydC@MgzxN0_hEb#!GhCb5 zZd6B-yocP17uQ>gZmp88VeRF7c1mRfNs9b%l~vQCi9g5pZFCK2hPU9BM)wu3Fb^^L z5+-z8Jx;|kG+&K`!p4G_!Qtt1{i-1S8oL>DI{qqzMBArG{=(M`J#jbgg^|$vB3#3s ze!1?HN#E5q*1W)+y+LSs)2a0R&K4Knf#=XwI$EI~T+3b!s{Kdl_oM5;NeExALfeau zO=-NSO5>3J>nCk$$`;hqh}9~#l9tO)6>a3wmJmeDtf!0^G}DEN_HSOIF7|-=5E+H~ z$RcZ@-~f!gA%+A_zH860t$KDr4g&dA7+>|8;|2acnnCv0ybfpM)#6b|wE_LhDfLSA z8~y8SvT4{-c?tPLH~wX%!FWU?;SR!AfQqFPvHjqFM`C-kYS8ek+AGcjl^*%d7d+&d zMp4-|zXE~a6*fK!x76ON`UcMCVkuW6@7xuqxQ!3c1qw+)QMbYZ<$^DT5bEwlRT@;$uqLPlvR-ZQ`GgvyC+-k84(?2sz0)@MD zAJ#V+>I;aK)4Kzb?}|=HlgJc%yw4T=z4C6W@A{@0?@p>2T%9~9GS@!lCUYsa(<((YbHu()%kac^Krr-PVT20B9 zjcY^xBFX6&A>qo!W*5qPU8dkJ`0CseltsuOYS@`ovmF-*Y)Z<@$i;pioQ!i=Jy~o zEn%~rH&AxZ{c1LW}p&sFRfpY%5k2CrW4dgb>t>o?5MP(**vxMuDu;`$4X@4mU1C2ik2R+E< zWivihdhBfPNkB+%j)`R}ll0N;8#lDMWsE$RFk>+>f1B1 zL##g!Z^PU2{8J-yd92t1V51gu)_)!*GYPBhRpo$v``Y;eNJDwX>*tNxB5fiUN$^m@ z)y$K4Xn;^x$y(Ac$Dsw5&LI?ES5}6Bd^+}CrwT~(37Ktl68tP)?(V=yi7c>#O(ViD zJvLTC57!p%7zmEP_oTwP4&zuE4|7Pg>V}JsynqU$tI|o@AH91C*e>%+0|rx&gRt3XVNO@(PS9Q z#F$OkPGslFlFB)`ocN;dFiCnElp#I)(Wu4gqmbUUl3s{(GG6?dO>!?`{n#JfUgDoa zTu@kA?+cX})vXU(1wveq3LJ%^`E0B-Df#`LSvSdo@ayl;eO`FzcKF2B0OqY5XX9`W zE?fS*OtJiD5&i>Jzq|1unBn1Ai%Fsr-PYzjXoD)4ezA66|6$Wf7^6$@@^i4dOc>5XDy({`uHRJ@`phn+9S5!Hc=c!_^kHaBU8-!nef%-66eW$1OB$np3I3uQZRUBYa-ZFb_^_jYF= z^&v`@E4eU9AN8K}r?78Ti`!={bSlk#ue{YF#%IK4`H{uh3*gAJawpkNO^exzVH7 z#$HHT<|=7NiaOPb1kX?CZE_>Mjmw6%q)*#yLWBQMAt6Os~yzLD?h*4i;kIM9+i23mK-EQP~zpSQEXJ>YmW#~V&S9_hzfh~92q z`6TRZ;n4fdZUvv$1)Ec3Yh6qyh-)p?i>bG`-K*2F3cS+3@rwaQxuLf)tvp}W&P$ur zl+r2He5iP+@Ot3gE157L0(!{JXNzE~%B0%d?B};uIX0<}(o>$2hCWm%H03)PS1{N zXBg-%qiV$6-j%PcWM$`urEus~Xq|*&HtO#(Lm-SZrFM1AY3-Rd?cSaWJ~iAxe<-Du zGw8<5Y~?Zb(EjAh>RHu@3(?pa)KX~&A6pi}An zUw%M)booL;9|-N5@~O_8_e^dnI{`*>r&Y?KIo)^iCc&zF`P;3v!-~@&(}%)Khj!eL zw+xn=M3$V3tE8q!Eskzk%;#3SpscFZoT`gj1r4i$$&!`O#Ju3~(Y)~}M5C-j8ueXE z783FGOvBhXO4OLgdJ3maQra8^5#oSB>_bMYjq+Bqhjy%6b#3J|EwU=74eQf14v)5Q z8u(bg)k%jbslSE)nD(fD8#0{c*w_~_SS18gU5 zn~=re0O^`vkS_JnDe+yW@bnA2Um%%c>LF0sl!k4jU`{rQLWsH4Yj=`4BshY|g3Ndr5QM2JDPfsUM zsHufjn*B^8-5AN3P@J|$oKj48E+I~NQzE#a$(tR##O0|y*hh9|p9P!)$kWN8jR}`zfel8D{fbhBmBb zWgmp|z5ZkmtsCX^M$~{$TtwCF=19@Er4sGcq{q{}RdhVU$&;W&O^xJQUTPoaYUWvV zxoCpxkDMHd8I(o0AUie+ZF9Yw-rV)~gLYkK3aNXz%Y@U$SIwMzw-dqI5*!BunSmV3 zsmV_uk@VI-oY{{v;QivhL-cakk(+3jgvLc-2_>W1*VtGJ%XU#rv4!)n_Xvrz-0G3e zmus>-Kam#c| z0f@H3p6phaV*=VNlA7m5F^MI_pK-?JC3aOkE{#)ZLhd2{@D*Fwih>dT@E%;Ci8EZ- zoHu}!_!gXO)50^Fv0`m|iTg(=*vTwnsa~gnb1k*1VR|S(SOI7FW05VhnV!Cno(R3E zS9jvmr29O^8Mf@YTb>`hpd0QrbDrW1py@9i<|PGkyl%Hi8Hx`Lqq5ZT1!j-q-cNhh z?QK0SJ1=vQCtjdjUteI@(3RfmSBTrW&2hN}$Y_y~pl8SV3zrCIw0LEd=`xTVA+fRbKLIv)V9r z<`3i-3enZU0P&3VsiUH2X^5VPqHO9$DJ^IWI#UPLe>-f|y*Kiqw zr65<>Q3+zHF5QD7(BI0lmK5t(x}#eMZxS#6QB}0;d{k4?Ss867QWXJzuK-+yBW5Q* zl2?gpcC||j;q^>7HSde+OqU}ToN3N(2;jXJ&6gdO4poh~J?Fa7Eza@<+>Ns+GJKGi zWwp6gHM`QSg^(+3^0x<=*IK^i+2R^8IF!`lG3VN}UCmkUxwj^oEbcx3=pcfL=?*v@ z!`c^C3fwZvb)HirmTI$o4t_LLNzJU9E>uj-ZS_MVlM>5!Td!AhuGJ0bz`U+>yp%BLQCEn}l?Mgh9)Y@(a z>mJXK87vxzIWPUAsTjB?L0_KVy?vWSs>G9+lL<)uVmmj?Yy=YJ9rC!TP@|~ZxxDGv z+uR^yOND_&!rcx|mHg&9&rITxCXM_;Y?&cik-J4+=^_Z!lgAEIw_L&t4&^TxOK1o2 zp)1$g$Gd+VUR_HpRkAX_8$fEz3iF7Ce5;th8xW!~0;s&?i#LnDAeGk^znc_0YKi>u z<9U&Py5j1erTkvY&z~x$WEoK1vcA?!kP6lM*LZ|71*>j$&w*j`FVqqfo5{vv=M)zU zXSu@nwp>Rxo`4Vldt#C4NjIJds9F-@=E@X~L@ZUu-(e0c;M=Yn8JC<*Qe53ZPgp$~ z8WFVuN5t(geayL=_K~qHea|@=GDwcek-zE=B_vId#B3QpiMdRydcFIbv+veTv z!dI+xTEf|AxFhF1;xQmfos$LB`IdtsY&3tUCJWo7p*>WR7rd~YR3p@|@FZriHrnoS z#;*~oOzPj#_@tOQzV(g&+MA+=8B>;pM+_jqo-^W0D`L7<40EM~X!aFxfPq`iIb%&y z+QtS7rgh1P(O&;K^{6ZQ6fyF$diXKz4p7!qWx)@{%Nm)AA68`yAvdy?>Kwh3TifHC zde$0?`Um#nLT+SoD#C#5Om{&nild6UZAx2I7m~WZn=%-=1?5!p!3Y}L!hs%=m>+06 zKc@}|>zec4RR|j2h9VP4L;E*2yUQ(x_(P)e z*(BHXKY_o|9CiYb;cH-XDX#LGoG@2URy1Mt$aVLu*@_s<1(UvmNs0VnKN(~Q(uOkT z7s=-EE|?A1Xi$JspXn;U%WNHeD0ahGg4%V;G+D`nb=zrXe$CpievE0H1{y#JpODn& z;(I>mwr^%5idn9b`OJBtz)2P}v(5ti>jzU(AJ4KfG(u5_D{5%on+KGUP#|$RxbXyY z*tfll3Bk2m02I+XS^NQ{r$I5CetGwBK4Z(|E7<7YTyn~(Z4%S=|Fmq20mx>#&#<_o za;n!`w;FnkuXAfywx@3QvtD02x3V1AC0xx<1~GPsygV}k8U32%^-(E$XCgAgo5|$5 zfmefJ*Nqw0wZz)Xn1g6Liz(FLynjc_=D0WLV6ir#;&M}^(9~n^79DDi87|wOi{2p1 zEES6L!-~Fh3=f#vQgQ?xFAg^DAAQ9-#C#AL6)v*|k8iv)rq)uq(6{m{wVdLoM|$*` zT-iXFh1jk<(f+h#NXJ$)pUzo+n)8;-Kc$K+gBDOVoYU8~pCH;H!pq_pqBqjvSHl&@ zJ$!k~FCV+7F!hSqzI2@&<=u+iW1t5nRb#VDcxDJvJq)m^@|xfk_%k?4arJN91{0B* z8M3gmIvNWnL*P!YrQAp*JGuhQ9znFi7_k&;amkxnH>TNlkJMR{)U|9%Yvtyeg96Jg z`02bE{oY4!{ZR%)al@e(-c{ue{_S_?MPF(CGF6@Ua6k)o&uC7M@BLP^o%_%_U$G-! zJVk$c{tg*rnEFC$Yn4}fQgS=4=ny%BK)}J;acA>tZ36%T)!RJDU!O$VZSaTT5PSXN zDfCVcqd=y)CX%cm*KM{O$Xt=v_!R+OjdeH7MtKdGSZVt{P>11czd2}pGOO&^$dGp@ z;`~ZK1VkFsA0X8eV_xl5UgN5EK>myj%**J7yCp8j)ZdLWSw|xXzh#O^MO zBT&l~pNbZdtJ6O(7|9sseCafCFc9UIkTJbR-v2lRoNL8qCZ}wPcv{2Q^4=K7v|4$A z`bB0XL1uEJFY_=-v2)=PW3mKpa)@;r<*$i|xL*?t7Dkrur37A4n3lK$l)ER2`p#zt zW~tiSQn;^6rD4xQIz&v;D&{DKuDIXi7Bhs56)mDDXddm73%imR@g|lgx2;w=`VB0f zyD{t~;`Ik498o1>)6DcusJELmEz{jDZUg(H@9p{&{hHgsQG|ryouNe5=3>=M{_xIs z%oS7mAWg~lYT)wB03>Rp_KbdGjvQoH)=T(EER&9{Z~r3u!wT3Y3jUDxW;=Ntq}uyF zDDCEut_bM?*>TUbekf6P$eD7zZ7EGSo7m`Vmb3fzkMl0A`uIb~FOS7`D2$tKI3+Co zmUpZ0wDm7vY9r~EiY^9V^8d!&c`<5X{)@#`FQ@vh;%?OTpZjqd^gYv)#&^=+*DmXl zi|R|DNCCjJ>bM>d+D{Pa5KD|bsuc#Ih}<4pNgR5((x$ z>`G|c#~)+s4DVi?R72+9#?i0E*Fq=0!T_d?MO*e|ylmEkJ~}Kt2gT&j;!0KS82wn_ z$jLYe>+$mQ=7}&{J{r}I%Gzk^ChvH=uKwG-N-eL8r5%sWE#m!NP$V^{lFp6|XnOZo zM0b(IzQtGoxe(^ehfj$}cAk;48IxLX>N_8sz3^mvv~h7-k=tM(Yw~LV`2%2c!wDie z+wb+o<6M&9YtIDE$w*poNe%09mb2p?P;|=&ba1>20y}P>PYs(Jty6TIl3LdjxXt=5 zX{QMc9>@rf3<0M{R^}HI-#^tS(n$VJTb0+>@`jj4IfmUE7n++()9ybcs2JKxQ%QXW zUJhc&w{O0y$=JhSsnCdy27p7$G<|)|+$*eO(l_u++RiaWHBuJ{ zM!2ttkfa6kYB94y?c5FTwF6I$uIe9b;gx%wGXVqn=Nz!;-^$wF+T&1U&@lR~bb-8hJW$Zw6s#&^Qda3z&XC`@@AIx&_!q1u5I?*$qsh~eAM zqV7FIGlFGtw?=tm;)CM59)54#>4#fdbn%D6#4BP|qi+OPGod>EE5EUo?CsvmQadu# zD`FO`#nZBGr-dP|c@_*X=^M@Q4jYg4zpEQqJZ1o1BUS{6HAHbWF?NIWBDr;_$m@$i z$~9(JgX1!)An$3}D-K6|{Pq;zUaQ=ja_H(on|t#_aF(!;L98u9Jo~1}M{AO>f2khM zudAfS8E&0#TLZo|ja!&D%?;dhXg`?A2d-m(bqWXhBKoL1xc*lSAa zho}IjW@+Z1!|#lI0C}Qr5%5aZ*Tqcqy;=JVN-?)RwRBFEG%b@+!Dz7hLE4m-Q zPBWpx2n?;>TPkQ?cOJ^M22jLFVKsBM;a;tSmM5{!#DoM!Oi8p%8w-+y!X%|`8)u@h zq&0Ig@wKf1s(wv2 z;Urx7SN+WN>h>4Qx5LZ6-Lo6v$^sT?g$>Su1qIOD4Y6K+>`jsUss_glqx8B*04s`H8+^k7-o2@6B( zzf|?I20S=`fefiP8=+~>^AEoaOU8l-X1b}!+#oZR@pd@8Bu|buu&i%F0O_l2P-FCx zw%}B=-bZ4ri*AF!j=chBi<>Iw!0z=a8UA({tbO`@MHG{O5ATgo8k{jRZ};})89y$ zn)u{C%CAzEUtR^=!2p#64&WjMye+t6V+KCR%a+s44<8)Qs7}U*98O#FV`|ZMG+YNo zeU!At(}gG@0NEu2_6J2$tb@QksD<6etE{J#gVIDH+O6TM;`6b@q4DD;koB{Eo>&_; z)HT1S*ceN<!UjcJ1vdpWf+o1OvGP&ln;I+TaK)e;E7v_;joD zy`llktMV18SO`QHQw?pIW1H z`)3xzL;u83bapdU1kW3JZSF9(01`=WQO|TH)Z|8-nCb|}5w3u4i(sKHDT|cDaf2mL z9um5lPAea&SN$wzFcxZbSH4C`Ej5nF6>t(h(cDzNYyr1qUOGPOywbCF)~^**i7hLR z25G}B#1_IB842x4Xn}PPfpX6>b?A5%Nd;sKed@_IOSPv=?2l}(rCAsR{kW{w@hi9) zyLaU#NluV^iVgHeMbU2_jh6BmS_jwX2M(_g7;6BijTSfSUi6tW)fEF^;lkQ=2|JH7 zW_~!l6y;&RNUED5D=4^IRxcbcSpk3r*)d&0=q#;J>#FRsC{I(%1yb+dxH-10;i157 zwe{++rHnwG?gja9DHBE!TaIg)UW9M6uC+?7BZkHBvJ_TPZOEtrL2fP$J7#jaqiipo zDG)&VJBVyWx6zvvFvB!%u@w5WxKpH&lgmJHA~tzy3Lf$jrL_u9d7G$qg&}IN%SQI7 zp-uGHTU>D8&nb3E(CE;$KcgL`aQgi9;nh^qu5Tb)Sn#!oK~)gnELw)Y=bgE<4}+~` zWV#M3$$p-)x$Ul3NF_4`H)EIYTxHH^f4%Kc4%{ieS;o4AjSQB$=83(`HwhuD1K&l1 zeII9Av5b>h&|GLM#O`U;U(&QN3C4{y>IYsiZt|^vOD@iMdDNh`-!)t2?nY;KABy&P zGYu+OFeCak2WOZtn}B@+va@Kcm46w?5`0xhv#a5|gbxQ7qAO*cj!+?iF>Sk+MD7EX z!`dx96V|tVeLH`d8SvA?cBMYGfHY|knK1*)%2ED&4^x^M&w_o+;2h8Rm4$~4A3jn& z-FiH5IqOGH!tv8pP&;IiGBVT z%lg|VT_-Cy*GdlU$TNi&R?CK}Qw$R_)bYK4hW0pc&E(x=v@#$ZNNIBh=y?HKVCNmq0d@e%of1Cx#4su}n7D&f&ix?jHW3gnhs6D)#TG1|V#EAf3pnf*r&=E>Hm^M7s&>WFxQkea^fe`Or~znI;cqjDZK7UJu^DG z_9A|I-;ZjBq#8vEAA^NNMx2Pp%(YwU2+QxCd>55)e!1KB9TzB0vW#wWo89%Or|tjr z*HX}K|C+heeTL-8z+O?>6rO}8m&~8=uQ|;g4~{fV@$cfUB!J#`uxrXg3#f zm+yshX|PyT^752j{atDsN-_sW8{Vct(OlGk&(kLjD~*~@V;e^(8${vqGEWxj)3Fph z4n=J7B|1$LKiLuHW%v@eg_C^(=d%U=nrGaRjKbRO-4{wmE;ry!u zL(AWJzeqd$uES$f`|qTdR*@t?l?Q)4rLV@ZXAAL^(S40?uT&HTjhcxBxe&$$2Xr6o zP)_8&bEJubj^L5;5zrtq-}dw>m#O-7$Bd6a)vEfqa~IiiR_5t9G~vWYYFG-$@{lW~ z!?$(tl{_cg#hu!tc03MgaU$}n)fzVKk%a15wJLEp%2^q=l7)0z0{$X?kZIuPw3deg zb)8)YwCj!XkZ16M^fPD$Xb^FWXJ@J#%4V&bXkO2u93h>`3vK$%$!9 z+>-qRK{|fey#nLue(oze2U^^8V_e+}LXR2{4fshHk5zS&gbprq1#6ys-F&>BewQCv`2czR+%WZABMGHqZu+_Z{&1+{uT#-6!) z5{v^@I>wdeO0l&{=5;GPj<0wGoy`Jo9t*64}4)K{Vfv$>rbPL+{$Kk|N;;%-!K1&O@aHJ2; z%>_8h=^<;IKNw1>kCfASsub%JShXr~tG;MiJ^MP6`B0xj7-atkG%OXnXVbp6STUqv zdd+1uysbS{x4E0_LSrNO=m?Y>ouP?WMF;zKhn<3A^AXgFXWWVLyCpBuGG|ft-J{BZxU5jIW~+=dxwMLb4_O5zQ*T$ zetpzQmzLw1{~2`e+4`>SwV-^RsP{b?%0HZ(!X}BHzowm3cGiD3#X4AKX$t4=XF(Sd zPKLP3n!@Ip=VcxB`tQms9OIV1lSG^1eUU%;?0{2a^6N+?q$vqTYOJMOdTz!;IG$!E z;IyHQoEYwunilyiEK#qdWOuqE%+FaTY+Gf%_3hwEE1Vcl>mAZ>eLC4;Jrq(S%*xV$ z@W%xkMGI%?2>d)GEkPI5gu79~l07J=!F_JN@xQoO`gw;Q}Qk>C;7VUw zCf#dQ700o*@M7Vk%PSVIX5TqK8x_dS_uhOn&E_g22-fVkk+bGZo^?wYYe5w=P9y3U zo1QCm9P4-8a;UP}mJ^YY{0|8Oj8i~dfP zOePi?jgidN?3;rTTQxPny3=B8k8Up^;SPu?EVw`9b>copIA$K#a@5q zOPzul6st4i{yr!QT#*;G}p1nAmd!Oa8tv_ec(NV4{Cm?W>B}AT}3NTxH?0(l#|*#d|;X<&}|P zs@D6OwnAi`>MhkD9AO*G$c7bo|QMY5LXMYK((&2jQ(>b(#(EgzcdhdH9?{pYM)IcID zAp32^6P_2R1NQk7AGWvqxj!Y6A_fu#voH6LgPh03mJ?7sHIjoYyBESvGgsJd6<2yo zK@?d^?R|sVOACUtl_9VHRgg7Czlgqg!}c~N32mpB4UyP@$rOvIlsAu82&HIPo{oSk z6r?K2NaV|O(e()=O5!9Coy)^zb5l#0<<~AMG&}c0H4XQ{MR;3j={X3XC43MXa2Lb9 z^7TT=u6{J8mqCxO)8Bc&nn4eG&7AFos50NU$=xBcKZ2eR|q5WXQUp_*@S6}6H9L)+x%8^*TUDoZ<^>)^OK&+=F(8oLdVao9mjS84X zy0o_wy7o3PRrfZ!X&^T+`&|C=j?8N%ueEI0?;5uhg{av3kXMUM>P?gsTyn5{z!zK6 zgRX->MqLs@L8~*JvfT_%^5<5zsW*zU>s~t-oyr@#*bN=_|1<=`Z*RTh%M~0-wmy9W zG-V77e26EV`aV4^D>Qa6d|BP-3TI3AVxflQ;5?Y>RL@KIpgbl+7up%t))q#-`#*{vkk9oe=boei-}q>CRaBx zL#&S_HgCcQ??$IJq}qxs&EHz%hfC;{XjX|Fb6@>K^PWleKByU&N{;P+pQc<`6Q-xC znV$es2+X9Gbz|(~G*`F)Z=6b<9_8lj=K)SBUt;3wT0095VOB2Y1>opGq_G4gBxlft zYk~aR*9usRWI|;LsfD=UQeuhp?cbGTNfcGojj>|GZbV-&T^fP5`*duanS8A-K8j3G zeh3?@eKPJ}jNPMw9=u+Ru$*D>W}*7%md9x9ueF2Kk4D&*FFO>h&xbstmR&<~;%19~ zsYS!yX0h)QTZG)iPDU9okwfmFDS$#=>T?_G@G7VR?rZtdsiu=N;3!N+9f*`P4JaivtKo+={ZiTo;v zRs;g1-8SFje9bJ|OY=T|WtCiOWIlQcfozJa;oG1?u{)ymg^cyn&O46Nr|qh|m3(&T zVf^IT6(xH|ac#mi^QF@MLB-%oL#H$8mC5$V!2uBNhPq*9Sz0!VX~&vRn}*RLQEZw(m2ypxKN|t0(rGe&--U;Hps6 z7rD;|-)+ne_mYWGe#B#zT2D{PndV4}li0({s=D?%8F0KBx-bZtN!-31s1v<87dv@{ z?r<=b%ln>*+|S+7)Irb2(^mQBBxrmpEUw|!FmhxZ>DiVDmZ(<^5= z`3?_Q`C-jzwz;5PsZAEMDnl><2HvV*61BER*Jo(1iIkSC=1+mWGg)qRZcE%cYoquK ziaWJQE5*-Yudre2?c6llxjG_hujrfVb&y7ABJ>~&sxa|kXzx>2DCWSX-QLsp&afp5 zPj&_e0kY+)+8=EDk%K(bL0|DG_ztF!#(yrWNhmA?^F_=oPy!*N?eJKF0aD>MJ{nwA z_Pn)P_>UL@r$3()`IcVY>Vhad)MQ6-qhHRlL1LArX8rYFyd)3I#sYnWcB*nun0OcE zrxCZcAl=RP2bkn`qE6mtx?>e|N*KbOa?+TD8yZt|}LBC*uXxV3=ogt2`Mb z`NIeu?^7`^j>j3*BI~r2guMurpeG)jjWA3m95gPfqK`FSC=5B_S7_mFN!VICrp}4I zFl(DOa3U5A#D>+2({|3iGqLwJM7;gX7w+5SK50yx{pcopY~ddBx!*121LFi1=rTGc zNKQyz{7kOvyPBUP20ofu26_s%?su zW!9T*7F-*F*5{?>kmjKa>DW~>!o2Ebc6O~-4+*ibkP_Ed2bV|7cKb5)2Rl4ln$~|24wbwEH4t&5VTvdryOu2STQ6-de3d z;mxW1(yr#?;Cm>zcINhCes>RcdXx(fmBp~MWEKyBp;!Yl1&4F5|43){cf9QCF4uuT_4iP-;oSW~TdoXQonkep&ebnvY`rNP1|cgGJLBAb%2hYxr= z3A=ZWcDJE4)JK-!LcApC8hVKCc^Wd7n>Ju9;H^BhkL}_3eA(UT2D_Yetd%@KsmjW! zQOv2mDvjQ++y49^f^N2D9Dm{1CnZ|gE$;xy?$AsQvDkZr7IeW0EuAa|7E~n8Q{H4E zIL+xE9kYwwcis=aZT0T5V)CcU6W z%BR|1AFiY$D;oQLbaO!D2G-u(D2jMg2=KD=A0mTzzjr_F1Ua+WILOt6nVWT`8zPDf zKkyY=3hPU43YeYG`*{n!-Q4Z(opSaZnAtOYfqyD9MYtMCkbRA{#Rym1{CNCO)w_Dp z(lXDkllr~mbCYRpyf3(_q=RRv%wT~GQ-Sh(-G=}Wcw+}Ur;;`lb1Y)}P^Wv4Md*<*UF@X279!uD6z?BkRn z;b9&{@;Of_|2SujLNE78o8Vkd+=ji!1&Q9x*AI`v&yPi=Qv`%8FJ~>`*>9|!BfM9?osy=NzTFehEQ1)B&*fZ}`c>g%6+jo8Fct_}3#*7&E8Q-73A2)mjTS@6P_kD2aC$2+eN> zt(9WOlWZvV{Lw*AtwLW=H)Sxl6)K@q^!j~kS@|uHu&xd`?S$^8=M~8Cg&sY2?5q}k zv{RzFgVLf(w#BiWD?n5-rFl;KRc6Z_1{5m)?aWhBWRjY-O=VH{?eo$R?=SENe^&|% zZov9beA7IVUE9y1o{y!ANJhaeGj@ZdUvZ?ne~n-v1?lCcu{ETwOpT=IQPPn^_`Y;k zSUp%ajV4_PgQsU^O~R4#7$f{(t2~4FjkEBv!mkSFtNGaRq&F*qhL?FQR@>hDko<3t zgG}^)Ig>>wiM#DkM z=*1(kt}kf@WqFq_kZLa>znuCWkIkB&cScR7gm^3AR<~yR_gnlXJ&j|}F*+2x$>IIz zsJwgo7ylle%>_t%{ph1^nh5vr-0c@@a|9mftB2r9GtXn$+ItKraHKhH6+Ne;#Oqx1*?SzT%`>u$wwT1AS$<5mKP&UV_Hh!10mm_d_ zhDFRqy=_6qR-6Y5+y~8Nw}ZJaHH|!Ot8Yc7J*f&j(T`4Q2;Wv1iaI<=UHM{Za*93Fy7DnWJMc# z&<8(>gqlTDK-Qkk*`%NL!9(w2B!|`)fYK{awI%GWg6j?6q3tq-?d|E<$jW-|(bmFn51tncWo#=c z+8{e9+to1@I^O%#qv#Jd=Vt=td#tv;1AnIGUmPu8I<1ACTB5-vRCr~!0Hot>tcaxQ z(SW4}-Yt6B<#YoYc9r&~%?(ndvb@pZv3>}5gJX_@hgN0HK`6Jb+dYX_&f6o6pe0j$ zf;w>QrFDReG%rtbZ3_$o^hq`RCv< z!|}J_+l+NIT25q;8{bXQAeQm8R6~02FPsKNlQMo$S^JVAKl}v64Kv-%>H~_-(2qm? z`#5j~#u$AnjKOhBr*{cdYe;UJ7MtJw1%)~3!7C-LcP~hJDps$#z;uYGx)KZ9?r@XFBG*qG(Z^Mb5!%z5m9bw!!9`Bj#a`QJ&{-cX89KHXsT~-G zUX`0@tpmBYog>}Nq@Cx|#{=L7OCMB_Q(D2TX1zgCwxnP(h!~d15qZ>%Y=F&W4}PHK z?rpm#K?oj-*--Cn_ZnX4Yin;Nwzo^=SCM}Hgjq^|BUzUE>uB{YiRuN$`z#0L=d}=1 zW(r~2wL>ZfJ)Rl(pp|e}Wd4f$H0zS7)y>@lCK9ewUO|Wbr^&i}r_ITVXi(NjYj%Lx zl0PYYsCB9$Cam&9ElZ*Hq}AY3=*h@JNYK#2j6!wO`tCLfWG1uCzg3HrZe+b~3dq2r zBSYKVRu1QpWyKqk-2WdwQ=YG!Td~Uz=Nb*e9!h+Kz)zv%{hg za{J4_KfVMxHxiOVi;a6J`B1(J5Kpeb?1a(BnRJ}rZ66*Qi0N(}vdLad62y4U0RU(O zv2D5JZ8B6oWe3t%&W`Tu6>-|c-mI!uzL^uaoxYqh^jRgA`Qg3awi}gS^xod-1SJBQ zmO2h%*bvoA_p-+_w63J^)M_L$L$Kc9~r)f_~qX%u2~jRQv7t zMBo0~@42K*m@P7X<`^&2$KTf1YMG*>odDj{BCwiq+d>N-$>qW_Ffp=?K;2)qM~flK z{8H8#0z5u_r(jw<5c-&R8Mw;@_;m8thD0>NWlvxBI(WF}yEXa zipyhzuR%LRtLUBbqr!wG(=1cBHO5aB98w63Y*Kv43v21kUAG|)tClhY#obzX4z&3ASo_2lzGmrg&brK=+(K4kz3Fw zy>RXWn{NWtz$3MPLPUg8c;52ElT*HKjK6dqa|0QB5>ZPw*(a-E&=X1B;>ynZKPOD> zK(Y1v)B*Dw@`>hEX4-5nJ(WRy^%_o~R3uJe;Y5y#87~ey_T8NZ_$x`BH3v2!&LEnw zLzi!%9p|{2*TDd4AJfCJDhN_p3m*qs4IQ;1@@K-?kFdvbU>n_Wu$ zZx6i}TeR>hlP_ll>R~)rouBU6^(`}`n9EsACGf70))lWZfRu&7rXoI^?nqkk@Ta3X z4RNIm>R=zl$cIK%nE&!b{RAcZUDu~HsvF1Ck~gi2`3(eD=5uT)l035TJ1!{mRn$op z#2>nFUI$+MVd!rs1S&BIMRQIpIQ^Ie&TO73J3AEE3tcl?_-Fy58lc|ryMO0b1-~d} zE3_DpPltBiDNiUm*WyQYsH8aU83ua|a#>u6tac+&Dt3Os#M{!8 zgvV0&`Eg*|pzLQZBI*k$4S}F_PU2b21bLGoNgkue1v8g|Ey=U~zE6xR=3)KDy8$J8 z#5LNosvc%DGDZyMl~?B=hTxz6%1c#YpDoN(GS?GjNi!iy7BoL7e0Cb z*wA`;{F!dt_k?1dnBz=_Q+=ad_nWV>U3=Zp&1jH_SIHjL(?2)0Mx{Wzz@FX9vL~hS z6F!@zzC1T?^EqddOm)f{s2CsI6;4){vq1Yi!4mRMt5&Wj*{^z4QJ=07xdMy0sU$qL z%{O}DxVFc-o+*zd?S%4w-IAD4fgFSk96l@WX*x`bU)Wu~bcpvvpFQii<}8UuxX*MG z(|aT&midiG9^ng5(aaI0jz+bELtf4Ny;4HmKri4;afks#D7rpbfi_F-_ z;L{lV0hrERNO64>@%u&10O5qf&z>Kv-o8hr&in3fC1!>$rs1`dPaf|(ZFARk$XJfZ z>BS;J*WrKTJEqHO%(OQ>Wo>lUo5I4s0;7MVuYmfrf1cAf}P@o7F?h zD62b;Yr&lQUlNng>!1lskrBSDLUSh8MH|P(+VtZaljNX-29wyW70ffus9v4=N=)+(aaBGULt)H@zj?& z{nu^Jxs)h_@-&Q7gUE`@07Y&Oe)Ok({3dkutSQ+K9Gs9(LQMp*y7uQ& zJdNZWLMpHCZNrPqYpXpt8RZ-1+ync7e#nMc7m#mx$Im-Dm86UQE|-^H3BrfQF7Lpi z+ZjISr!!?05!s?Y{hImVr_#Pe9i<&BJbZ-*y9Vkd8<^8R1}>;tpVZTapAqIoK5s6y-AUN~NZ5MpwC zqM;v14_7Zjckeys-`?Dcg89!Ty>WmX|AbI;&H7##@E<{wS-y>Ofy8bCS zy<3G4FOl9rKn}t0LT21+iO-9)*rO{U5yIkUfY#M_qnih0%H|vlfS&kQ5tGM!sA=Ky2qevHdiZ;*861zE8wWr zakjPBHfk9iR+U<8MjzVZa&`U~#MZaHT*IPVirBntJ@55D7849Beav9yEJWcf$#8C( zNIJI3;e7()dxU`*39MC6T1r(21@aN&X|6@bk) zlDG{FQZh@s|Io?hLdQHnw-wtu)db)Z7^FSfa|0F7RvWv;TX}NYMyLCH2R>Fa2dyTn z_zFZjCJj}5KW(3Ki42csh4w`P648&}lbE)r({3}ZUzzR-_3a`>vBj>lCsLpAV`K#E zL!xevQM}L(ALc&EHT?rMxTH(ViZ1+dEw_;|8MLDnXaF?R=Q9^ol-xJGt6`~>cvoYc z`K7a_sn=H)JwRnu?4H@X4;D{0>)(~*s;@-z#&TYMpl|aS{yB`%z(b*BvM}p?vF}6K zhBe!^l!=!L8dA0y#ye1f*^RkrH7i6LD} zC@8TRo^1$0`(%=*RC7K2o?W1BSsw+dhIpBLO_{PAAh&Wc6Mj(^hmYj-TMwg?0b4tQ zt(F_>ZHu@*>8crj8OEGg@`d=F0a-=a+UA59HQN)iC*d+Ekuf{yyg8^zv|I@Fl|r)^ z2*2pA!q~dV5&XaiD9-KKW^3&o%k@ybwNgieYLM~8XaR+0e^6@~CIQNSLFs)&7Si3G z12!{<(-xW@&g0@;Dv6?F_yKC#qis9UdbTSeYpSXI&_H$@=x#UC?_2W`{`XUgfUo;F zGfmQ@e5Yf9AsSTpW>+89uIi+^ zoLxRnhTwYlHxd;~p?`MhWFn?6KF<3VV^*wKUm{QVb~~(jXY`nf_^s`u=P+EI=~(_?RsO=RcN^;JvC` zl=c3aVAzAT2#Ki|yc)iOvWd&9q0<|2bPMyG(0Ti$c*m0AAVzZ!&&Xz2gRyyO!CJ+e z!eT$dZx=nr>4x+KZwInp_DZl8mP!4sLx-v*3H$8Pg2uiNb1ncQ0w~d-DO(#3oQ?3k z;l5R6PHjLmX}gW(`W>c;1Y_6>nl3#Rngs96pcJnP@wG~2!x}0c{Rw=Qo=SOd0yNaT zM}VT>scNIl;V;OH^#O7+|6|xwVzY<&zcds<-FoA*l$B(<)~Fy`ITq3#vZGVvvq*ue zIF^#JgngV&1kdop0T(*`nU}n*_)|K5ea~tq&LIA_l-l^9nC-in8XGue`WI^(x{B-BlI){L>d3z!77|gKbnz(B6|RFv+(>>Y}s%P5igyk=;{9yR*GO zmPAyxs%c2`XT+}wgY~x)gwQ^xdo?o8kLyi0rpp2|KbFSfo!fZIWv!k4CsPnpPQ>n8 zrtAK&b!d8gS!|_aE&M<0u#aUPdLHslph|5z&az5exIo(CSCDwT(i0s+K&J9NwO4TF zD|=dxZ>1}zf1Ej5<55Aq93~O9Bcq*F&lYtgV%S$NfqX2428Wk&K|)c*Z23$SBI_lF zhs1D{_`-^z``8qKHpLTh-j%zDif$&(Ai3v_TJ38JD;M&zYcAVdZXCm;L(+yOC#9UZ zvES+P4J22bmP4~u6&*b#u(c3E2<~fTgUe+l`V478&m-tt+HrHUo^6iC5KsZU6)3d= zGUR)7#wVYp9L)`zQRKY6JZb}BaGlrM2oE2X;h{cI#Oo2{r8 zXT=)x>O^?6w)3T>Gu+aJ@+qifyqG!5KxE1iGpUy~`&O)~g8gIe_@1|FDwYd?$)O{o zs`mR>k50ePif;K}+}H$^56ZK+h>Fxy4V5rdq7iRSMv#8(``ujcWl{B0h7-=WhI*b_ zel{Xvp8tdyz$y8xdq<^nF~qYvi7R~IM6|v_e?S6m;A#~YBxGCL@wpHhI6a|MzSG!! zooat$nrrZTbJW~PMLf$jH<0#9|9)q71zPr69+_;ve!#(BIUyO3Z+^ksW)?{X_bX`i zQj!0=?d-idvA*!+V%UZpYI9WK?!MxTa_QlCa}1vLv6Dp@--F`S1L1MCt@+>0BOzyv zd=2u&RA)#D;c^!Fvt4s}_A*xJgLI6>OiEiy>uh4~$yBKD3jjtN{jxFurmtPH(mlNH`Qln$rVy*mpm6{kr?rb*~uL`{&?cMQ>it6__SA= zK+7&%@RkMtD9bu>F3ObXUL{6MEfuy|S{)T1hFonZbOUraQ6x(_GQe@*h;(OQOa1E5 z_{dHxa1Tzybb0CWTjkV`=T2R``+RSf zT#pZrVe9A#xL4}R-7l*mEJAok28s@eoN+xg$DL&4$9dAjr*a(qg4J1m4t;9y={IkP zKXXMoMVIJ*SW6DL2Vf6Ztod?KBHUTyHSw!UOpDmYtUcG)P}i0&f;TFF6#`@AWdx;o zfS>IO#impCA=$9fP8akoe(9ugg36>K7@f%_j&oFXVlJn{rhgGn(cOlflD%|`6)MbCAF&_nB5ottK`+t1|Ui)*^+YWP$dnH zer@n>kb7X7fp7VsS5Q}pFPJtK#sYBe>?O!=dGTcWF;S&PT@rmORG&RR8U{J5hU{?? zApjDQeiyi(Bz8t|%lunR&dCDm>JkeQyiG%0rV))lLN^ov)fzDIKc?V-GLxcM>Oqjv zP-_mOlg{s2x-`CAg)$idQ7gKf$o3{7v2IMn$6$^PP*Fdqw&XF_!RN7o-s!Gn<@sKm zR@~zJ`?ot|N?SOz4-`=PU78Z{@4k@MJx`^zOgEwLe9U%G3GmmSt!F>pyV{@UO7vu|C5-k`Xr;9P-EtkhDXTq0orLwMcU5pc-MU_fy)6x4=* zh>q`!1?wM=Pa%f9eflVhB~q|Rl$14?kP_J9tWlA>#DB$37H4Z^?e3`-WK_*G1DUAD z|A3Ks!`%4Vc~uVWKy^m!B1wn~H`W4ktcortXF7Y1`e}1PM+toL$1=e)4@^TGJ|)9P z``kVoi94_#xS|37^6)}uvF!B=mar(gezIx}rusxgbAX|Ov-0`cZ5j08$NDF4MGf{n zWJ&D>BO@!8yv1hYf%XvtwgIFKr2rp~ghX+`9(5w>&xVb<7%r7!s?U4Dj;)`9>xXw< zxxkF_Rs{Okqty1?X7zjpBhQMBadG_8Is~#B6qc-Sm5p8xhlFMDfwP}5_KX#~!TFfj zXl$GV5r!|$xZ< zk3@C_*iLp2`YC!QK(!xzCum3mea6>5O)^5yKy15b5-d;QV!YM z(G}`odGtd3`N(-9&gY_MItYHc4PjO+eLB%)j|QhiO}Jznevgj67?h8@&Y^bGrmcDUlHh@w1iZGaYas7LB(> zSNawks+3+Hl2X~KMjyxU7LjuWgen^iufGH*i`KvJmGp$(3ugti;rQO64yvaQcz#fu z0mBB*lP)UBaXeArgxe1$y0DNt*b*TCl8QD^4aL^!u4d{9@+6PY3;{6ocZ!~}O|@J2 z2B|026bOwD8JuN z!88oYWCRIX=kF#tv;y_(@h*U%7(l8Rm1*;~?JzlhLFNA&Uw#?nV*gy6H1+~RQj0N@ zlJ7riLg(A*k1j@iW*wBT$X-^&NOL@KI*ByzRsx2O__2Sc-O<%HecEuAhZhvX-Z&Yl za@d6XbN!u~60Sbr066Avw9sLfF0q%!c)RJq@%8iaDk5yx%Xnrwijjtw}1GE_^6hS4ZLV5aoZ9-qw%K27!V|tfQF!f zOP_f>Zj?AZB!?>(;Z1rj;TaUOuYdy+PzMD{fEq;nNqWvuP=w&UIz+(~7^hEi6Mp!qJhp4Cq5bAWXIuEKfg~47!09Oq?BNYk)Zlb z$EEKBT|x*E${-1~`E)omuM7~MFQm($%6fF=Ef^69toU!YDc0Dv3t@!z_l6{tIS&IO zWzakT*qA6aC59Iyjv`|4WH8+t?Ux2YQ1nSa_c2SU@cAlza<>`+)BWFGc*vSg`vPr3 z*$4X{4r3(R2WHO~MUlhOPXWPF4>Eypa^mj?#iElS34#Ri1cabyz(p`vf43nBKmYFM zCuVLks9uOBJ+0$EZgL$&8R@ym^T@`*ZOZy{1iEc+rW1r;`J&81?;2>`I*kPXh+G#a-Q z1|?lhUt$A-z@SF&A2{@vRGp7Z%l`1dy2RxXjGjlFWn7(6yBtbdvc)5|^?7yj1g<{>7>5P|&3S zP~df4ZKcT8T8!T%7$!kGnfbP# zWNbA%((M%9erc60oi=*F1n}9Mj!k<)iF-YnRI!Ht9~0~#K zy_OsQfR@YS@MRsue@dHh!u{@JZ)N{ET36=99_yfZW4}))W9|S6avc=+2T&hne05`| z2{Q9OfMeUm1}%I?9J3CWPNj{0HTBFviin&BB!qLog#Vp!5yf)GZMe$>(V0l>v3c$O z(@gkICu3kD*R#@8sPL6YHhO(w7rebp!{r!CsX=@cBCCP7XQy^fR-`f2gVWR;Xe=_~ zdw!o7Ds2tTA+?lBA!{{$Hv7{X-+EVH$Nuz1W-KPk)6ssq;`+7hU_E}p@YQqBObeP3 z0wOj|j^hJu~=Ef$P%1E_Iux%Uo<7 z-z7fI#|Swng`_0RS_rF|s<^Lh+e2!_TX6tf+K4s|j^|>u6Q_+%j1w*qUk*&PxkGd` zEjK0@$Y167_H>yOup^QVG-Y z?&7f}D8nZPy;`dB{C*k>-e|)YTjq6AULXuD&bZAZ3G2W$M&glEl0E%W#jw*1mcXB& zIJ|q#SFrPpQI@!lxpH;UdQ1z)fG6PO)fi${nt*WlUILU4##Y$~c1mGb z7#X!x!FZoeymU@mOsoVJ3OpT+`yP4=uUByJ8ly*L}(Vs(= zmzsg$jg|xdB`J9qo()7WZPDavrd*G8hr4#>2u(cL;^D-jUtk-VwiUL2)>k;WSLOje zQJGIPjezq+Cy^0|&vIed84#=qCW#XkoK}+Beq(%w+Q)%a1Dh^LDBxt*dJKBqynN3d=|bEO-CwZZG(TiocMb_W8_q*0c5gxmkHU#L zul7sbJF=Jl;H-N$`TzErMQV69QH=)AG@^`}bxdN+WiAe6e>}|O|CFZH8AKK*Z}yB5 zWXXv`@$o$TVa04a#+$l>1BC(#1+8JjYUB8y9FmeAn&mIB%H2N3UBtP+H|Z(*2nVT7?k zl^-FZ^|@58?ATyL;7<_6oY=JZ7tQaV5+AuA_q`6c?uy07*h znTJ#xVC8J6KQDn8?t_(Mkc&(mQEfInw-h5&(TDf5oX}%hR$4`zybn^al&Z}VBi6Qa zmlZZMFaBxUj9;j>X&_o;g?SUfPGLl%sfN31sMwimuNMa$eMm`yY58K}0E*&JC6)GY z!7v|on#DqFI=ZD0E~(>m?25KQS!KCnjynYjiD7KEuteY`UppQDOBa_S9RZw*_ZC;S z9|M`;GI&UO=I*&JH3&}gVi&()J%dF{fjoqJ*-VTaLb^46bd^q^IYvYhJy4O#+fmTemU{0_(q-rau$+ffjf+OV`-V zdUzFx6%E?|d$3;23UI$_MBph67!vQY#r?nQY^inuSfCFq)=>)Jy9(ZmysLv#@;qc& zVt%W9=c6ZmuX*kK>ZhaJ2y&Tk5ui{VV6xc zrY#*o@Dz9ooY{IU*ga>d??H0`$u@jNUaxs8hlOpz9iS}iuB_M(@h(l8z~Bg832;A% zj9(~*vJhWP5V8qRdHuZ5y>M|~AM~;2mCJEA>dN7>RN6W-32e4aU+p=D5s+M;zPR6w z${BJ8zC)VEsq1J343JjSP4B1RuO^@H*1fP@VsRMY!CwP@9{OciOx=`0etqr!|)mG6S4G<%w8rjLz2X}74w z`YEMAj||T{YeX@485ZW{-lmK`;tcQZpDWoL!Gg~+(+ksMQP$web(uVL;&i~ z*!`g+F-Z(QhF;Br2}oQodbef7o4VC?rjk>O_WQZX^!5HVH7A<4KJV+x4nkw7yc*NK zDWf^8`?S>*`|ZFAJR$rsffqd@f<45yH#HT$7d6XX+|Of~|KwM`xGyLRZnFS_RGPy1 zOB)Y~BWeU646{hqe4eCQ{d9~*_P+=EaA%8N7;tun6HiEPZiL4#%)I&QtaBJ~4Mp$0 zf7Y-VT{QsvFNP)XROos@`yG&%TV(1UCN84xFORpa2fvXLdSaATen~W~kqi!0 zmQFuF01B3jS-tn$!D6PF5qY}i>syUax&IJs8nMPNSE9dJ&|gpkQ27acXK|NVvRzte40KnqMhu%x*f)?`d#b!QS?AK~o^l;ykGQSH1V50*cJ!8`NN@Q!L20y?bpuF=}c{e2z!Q4!Bu-r4)&Y_q$@k2w`4UroZdMnZm; ztR39~-__J6a%Pvaj2ecOjM4%>m}GOc~v-=@_Xaiu16>t zx$9?*kh5Vmt_O`t_*$5MbmLDe1n7E;r#tI?GJ$+fbQZu8xXZY@ zewZ9^6U6Fi^ZU5~EMs4^6>R4#EpOQ1*{f;eyXrHI9=r6R+GNH6tha-~od?`Opo~b3 zGuJTQUGSr}{`K1nGGsS5kiY|EzK>0pK~L}{+$TJP^4%bZ@;x{bpD?eOT+4@+AvO}W zHl$+ka}asALtwetoONhO)XFd{tr-BGP5TM_t5|HUoG#FBE=$ZZ`Q`u0g^3edrj6^J z9oJWHAbRMjc!W(vo@C6aMfDr~;t0sWW!e8oH(H--a8$&HDqEhpc)q0JCC`UXC;S4^ z`!9iz{!8>n(YOuZY_Vfepcq|TGIIvt^cUembiBZXn1Is(qY_geiC|xe zgs3oWc}S$-L4LJJ3y3S++fB-|g?>@i2CF}w1wpl3MS6$`Legvf!;n;>buPtQW2W+)aWUh~1nYEbpdSJtYHJZ$G))#rU$Kx-{%d zxgxghH!;ROELd3kr8NW@DVOq8GL6GS7NP>=Ozdw9sYtvl>VDjP!aPu#VgBz~$o}0k zILgc)jB8y%kzsk>d(k-%?o!JBmpF8pm-)@}en~!2W8P)H6(RzHK)fX0%Jfdk#sL%U z=TC5qizC_>aC}K^170uq$+i4k1HLh9i+(=hQ}%_hQxps0C1rUhdqYYxJo54(5>;B6 z1fXj`(N3c9J4K*KYLr>QC#YM1^{{7KU3ancJ2P>n$j0falO8x=;E)TI> zmBCQ8rR3G(z5#WSESA;Ky0~C<(+FTY^efNZJuAHEVOHO+S&HJ84eGk;q!U3XitS;etUWzmS&oKYkjXUd&$v(vvWeoqSKn~<{XPCih zHC1VKb9Bb08VnXsj$y!Z$m>+v#k|K?Dj8N9_-g?QC)A3&t59meDsf=15;+CKP8URj zQZI5;DVVbO6W5V@t z10|Z4dm}%!I>0GoDIDmIsWUa-(AKnjbBjr|_`T)Zy3lzLWsS>#_pjhIn98ffFy0Pm z;f~`t{!%CJ8GXglLEHi$zPasySh@c}v%ZUuK27CI{n-Q7(!#52oBa#dIFS6iUDX(l3d|>$GnkVSJQ$D~ZBT8cb3c zd;;o2^r)iS;^Mhqz6pT8#dLez`y;fEJ})Vt8d6 ziXLpFerHbNQATgJ;O;%Jm9lMQuN4k6Nfo^}DkVRt{!MCFp5@`SY8=G7=)F(%{U62*Fysn^&ZVhZU3K+YSA=(vp zMf&@(!C@MO-}=Bh?`};rf?~m`Ark+Xcnq!3nzGjRX9=YF$oFDP0)TY@*Bf6^>~(Uw zsfCXT4ONbXt<>-rDz}32F5}P?aIuoq8`n3JYEsd77r^=>UdTi2h(ckO_pgET5$&C_ zgB#?-k${g)3;kF1bkPjE-vrJYZ}tSY;i@WGwA*i&)ihA+3a={v(r z`UTxg?w4VVFMxSnoiuP-T>xJ;ZjA=S-^%*@0zhD#;8LDBmE>nUC+fphP{H)H&E?#fgu;dl zk0gj_0toyq#7Ks7zDwl9u<+>bf?1!OZqYH-nEr0Ij!cLD+?@?p}jaK*Y zK98_cuWS{++jk_q-ETMM0J}9+$sKJAa?2NKRui*!Kq{>lrqYr3#&y7cxm;A`5qm5T zL(&sQ;Mw%ro%oRtUBGQi9U}gM3uZGiYDyMT8+KjInWMmwN9Qu8!_h|wh9N60CFjOg zFB_9x;WVY?4h2vk1roW7N3Tc+90t_|Q-#6xR0oZlGht4r*elL_Vq);BPLZ>-81wQ> za5`H2wWn%Z`}*er9c@J1DT(Q1!bG zFLV(j7NJEVEN_z79Ep!7hHyF=*d}i{%{!#NQ&{0Ilr-QDt2uqYNOYhwjTd`#<0pZ5OYW{^qZ(JPRZ4u#bUG!Wts;j#eWtWd=G?w}EzaYz+gBZ@67&)>IPf>fmTAmE}&^Dk1_S79?8}4*E2I-^+jD>za zhpaJ_Adc!t=1}lw)qr?cE!e+@1ZtabsjT-#l9xn{y@k*|wOJQ(UU&LYM>wsU$FF%^ zD0dWG;5I(WAl?F}v*dvhAOAh+LbEE~RS2K9_gwENk)rTb^Dy++p=tF2pm$dGx^Y?a z#iJ?oBGPU;8Sf_B@nwP%e)2FpM+em+H**A1UiZ2@!F`u} zr)4euZiWDhJwaVDSCHding-k`H(Wdd5kdaLrz*!*c^upbI$@HyVE|UkxGl&K^7=16 zN4p#%;b`FfYr?dif)cl?B82U2^W%R=LqOv7Gxonz?`rs`?U>-b@Ron<-28gBBhEjj zy$Aw}#?u0WI|0APxa)EFPuJ*+t=3RbRYD`996h4kW^pZ+h9Sw((~UZkL2T7c7iDI@ z46KGyyX?dSja3umJE*1Aj|5xj?(b;`PUW|Y{#1hVkDumY`YpW{XCQm1Q5VPn%xk%C zFyH{}YAKZ82YW)n>HCFx_`0p<`Yly1e_*Bi-Dh4nBT+-q9ZsN<16l>MKB`&y_S;u7 z5t#K9kV(ce*Qn2m;Z7F-9I``g4z>YP-{zZ*_LAsB!Ex<-N}PIolu6bKp<_^?AmGiH zZ2Yr1eN(6I`LSzNfTG_*k?9c$U*kDoC+Ct=@_4evShd=flq~Ed)|%2x+%W|l2Vubk zW=&HtIU$E)obdI&{jnrgF*q=U7vZ3wP;*AS8g}RUk!^M6sQ%D3j zf3f+{$#LI8SxBI#C7vbV!^v}EtSkpex(22=&6HtvDZyVfMlgP0LcL#sou>l&?X0l){vVR}R zaf$-Ptr&DeEPjYC&R8>KWI+zq(zV`%H2$1hn~W&#U4sBKrGjRLZ}F>n`ZEL0-=Ia_ z=DLL&xbuXZ{Da4?-pI*F%({-!&PzKnUMrF;!(ZQ)-hE)?Ql~uQhd1TM-u4DJj{r82 z#w~r}zLR`oAePx%V0x;XXq$DV>{oiUE-=xZDLB8tk6y}!|BU#8$m5I6_3grdx7a&K zb%6TZzLNnG0MNTHyq%l<^X6(9QNRLBn{f;8sU9n|`OSx2ZiwK7lFj=Y?;EVY;1$6s z39E({CcoHv9w9m63oUzo88&0bCM&cfLBuXp22^c@iI*YI#Al_XA*c@--9gt-&$|9+% z-uFyci83tQP~Y=ODDxN*^(*E^>O1(9tT3DE%X18aP+6i~ly9Fz~|87Xnd z2W5c&qh$~BRM({$&@A;lz zX4wad*){0^a-slILqo|v(G!>knu$^-(@%KMap798a{0X(fx_!YXDQvx^d;4DUa-4wz zZ|d0sbe9I7HARQir&2Yg0F1cXevZoiXK6rhrE6SIf%m5P`}+jHYW$*Pf`jWH{=^-o zs`WAdyhU#Y>bFo}5EgQEO{PLcn$()J#**32z15eHdkR}Xt<;XKHlqgYVXw2_rsj;& zV_m&Jxe^*u04QGE&F{(Mkv%%xDVe;Zp=!FPd?cy`%kzTiul%wQ!{B9cb5Extm$~~w zS=%b^=m0gw=sNNaMJBoU$5XklpBdU^9^9+sENuW>l@nK+ELuR>#~wg5on0b&tg6z; zYipbF--A!a*f$QSD|e{fB+woaf@}AFH%D!H3h|%JZmmJtHw}2ap)w9n~|NaT_T)-atH6{yCy9;S5BvxIe^%otq+io5X^E!-2ibmtV0PmP; zaq_iZ&Ge1Za?>2nP9v7!S77=2u;M#dH`8E>HfR+*KXRnc&ez}5oqw;w+-Kgoh<%7NHm-MEr%A~?hD0D za2)GfgruC+=o%MkoTJ+!;%}8L*Ddb2lH7;iv+|q}3*Z>H>(@eQYg- z-)<9~OsJ;rxaOo%DHq{BHWwUmqaYr#yEi^MX|fyU?f&|mn8hs}~`9;JPMxOHL3*M!)$t!Q(9Lu57c*FG;s3X<}?-Wq5f&=Q% zW+?M)gA{iA*Lqoz+Y#`?P9QZ6nEg)IAS%Mg zaVpuj`$tYKhJmitzrfXEAwUX9$(`-Cln&ys>o#t#>l!dNJKg!tB8IuJBFT4cLLC54 zDooFv_TT<%S>iSF%xy}!migxQbUwsQftPiYqkX(Ww?Tog*HEYXM$MQD2j3W9^D7JV z^_8a30bBDjGw+cfYaedeRV5QKe+}QDXF}2e*4Y5*%6mUL@X&sK_lk3wc*n1YW2`_b zvIvyXQVa=n9egl0{5|x?!+EB!L=ONKnPi0KB>dd%6w|tO`1XCm47}9GCWSrSkYTrw znR%N~l-<>5ei*NKI{ixV35+4>)rJMer)(Lf`usWoyr@G&&9SAn@#b#R$p|cnEiLP_ zkl#6EZxYIs(DzImS|a`U1{_s@q>)JTM*dZ$GWlQT%jMK@y_HWou7`NG1T0%*JnFK_ zqD3}l&v})>w1t$!H1-~WT#SyrAXX(4*!nhT2W7MqTh7#E&${jW8QsyKlgNe&=;@Sp zc%hoRs_9ip(GHv*oHsJ%m*K}cMGqhz^eI$1$07EJ^h@s9!*=KAPBSf|JGq35;O6yx zBQ#D}WP^xHX`(mFzJdG3D_TV2*RcntXhYo}e0MxHl(mPq&rUxnU84o~zB8j>n2iEg zS&B5(XPdf;a>7NOLCqJuPiiAs+U7@pH_KxRHei67@H3Z(dO|s7_jqHaZ9_hZYRTWX zRI-5C9_~C*((I~&HWZ&dj$rqCj0H8oXhcd=HGTZ&TuCl%1!!g#_IeScpIiB9KCq zl{D#9p1r<5f5Pa@FFR+cKUP7=-=WefM_2g0sU&7f8fG>YevEtxn@(YQF@GwN2wb=B zw@9eAO8NB~THXVr;suk>oqSxI6CmALN6qe26A*M_+3R%CZFMMv#yRCEn5_zf$A3;{ zGdlDQT%)@f;qMzfqb{s^9er$z4pB4p{S_fyU69o!w?8+xEuO!z_F8Bk$Td;vtN-B| zC0Atzn$To93HugMzHiINE2ZPthU|gB@b&^U`WcXD&fcaxBEYvSe5qA>l~L->d6Q|e zMm~I^b4G6bw&85GIkC5gGOdIj+7{Cc7WR_)_1ymVz)JL*U$inCY^65Dz$XOv!ySEX z`RdJC%eK?zsB0bDt%E!%fJ-1uPam>xz;}?^G+j46+W^i8b@TD@bycD8drw+pNPpYA zh22NWmNd^z{wFBgjZM*o?r4zjo=n2HhnOIl-At?fu|yBdC5V9}j~h5Xn{3 zw^VI6f7W}5Dhn?aUoZhIZgP*M{5wyn*$z-3bk9OETINWXbA{Gp8VYiZ%-0f`fo5@Z zGp@IS^~$wwYt|{P52mc_w0vSpn(L9g?jll2_*;w>hS!bwydR$-&?dsC**DU45S z<=CS1@Ea)7*Gl@5$8#xEMvkLlq7fP`4>i%aeI$`+9@If*n7Smc4|1{K;?A-!fw|zi z;o>RdFtRXro2C`AHka%nnQCFt9%I}4vabl>%F904L53Bp=txpGqC|%`Jwy9IVbF4i zwyDVGG}(-rJj)B$+q)2ZmB#G8AYOn)cpwWFYj~WgtZhd?uJBXFm{C6t1Y4*|I_<~> zG8pc<*l>O=!@JuVvA^_%6`VarHR|dJ1dZTk8=L+5PB-IyeVecU^mG)q0qNNLge10| zcH@=MUW%2E;A(bNL&q1KfC^kB`^hEVT`g(qGhHj^LTtB9W$WIc`z09liYj`7G0{Wk zwNmDEzHHXcxI>_Dgi5%MXQu^6R?CKFO)v*q?(Mum~D zVxouYcmK!}v%F3LQ^9+;`j6u_CtL7qaU04ze8)$2*>Fzdxi~Cy*z_(EwY5yK>#@At;!@INXvEv+=hqSwz9E?I=UV8|VOa2Blyv7pV*@!?e0hgYXZ)8YCFUs^C1xvX| zeq>0!ZDx0p{sw10y>aOHiX^tja-%0prf&dRCe&xd2^-3w5znC}85zLPEyWAQWN zAol_p!q}m_U?;b6z0cZ2^YCmkjcr0v(%c@Q)4ESAGlweEo-f+BGwlI5nGQ7O-n%XE zF*ryd_jyF-nE84M*RnbH`r4p%jx_&@Rq~W0JC?cP_kj-FS$CP=O0G(kE96?}UZUXI zz+@c0GTQH!u$@8YhInsak*?sBoqN)Ng# zVe%*Bj3h{t`*ScC>B6$>R>@_Q+0AOXJhQXHT-WF<%~?T>WT)zNvPxdZQoyum#!%v# zV-c_JSQ=;wtPLdImW;4VaJe?CYACH$3mwXT^B10(86-HQWvIDquAneV@uuSVE` z(mq}STzoNH*k#)A#}Pn{e)TMY-ghp)5?R+a4tC3tV{T9zkWo|Um1!&#=(ZN+J)U0v zdiA11X6!q6{~#A0%WN6eAjnw)?|2PC^mm*+s7kl0vYiGY(F>ZKFFoYo9Q4um0bwoX zPkGFAv%1Ui86zi2Z`%Q#_MrMO{Xp6{zk2ek=lum2FTTMgd%bM?@N773ojG(diSK_J;!MX_sBrYR%v zVpdw|&i!oF>jtD7Rng`O>3hbwME05L2#y1{>dQ<^C-7w5z>UeF&}#9f)_>%}vqe81 zyy%#qjsBI(SPay2ilJGV_3O)XRd%;cKEB${Bq*x%= zhMqoDf6sih|E%sy;6<@oxAMuOPuSWSxn=T%Y6JuS?cDB$7pPYJw#4x&^UKmf-6+~$ z9R?Xa!=S{hK&0s=Ql_eLYGB0MHVz1)+?e32bU9MBu+JFF;}4y&FQ2C$6u4;=H?)Q; z%X^>W_=cwCzi_~$tw97{oM2ZE@=bX`v%0b{iyIuhGE4ZYt+m<<9%;?& z#A*}8clb`5@N3SGreRwZwl2>X^rFN1>cE6$I9FoQ%w;d^$CYS%UDhb#}XU*pR1 z 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 #include "functions.h" #include "variables.h" @@ -13,7 +13,7 @@ extern ActorInfo chPinkEggMedium; extern ActorInfo chPinkEggSmall; extern ActorInfo chPinkEggSmallest; extern ActorInfo chMudHut; -extern ActorInfo chTanktup; +extern ActorInfo gChTanktup; extern ActorInfo gChTanktupLegFrontLeft; extern ActorInfo gChTanktupLegBackLeft; extern ActorInfo gChTanktupLegFrontRight; @@ -23,7 +23,7 @@ extern ActorInfo gChYellowFlibbit; extern ActorInfo D_80390960; extern ActorInfo gChYumblie; extern ActorInfo gChVile; -extern ActorInfo chTiptup; +extern ActorInfo gChTiptup; extern ActorInfo chChoirTurtleYellow; extern ActorInfo chChoirTurtleCyan; extern ActorInfo chChoirTurtleBlue; @@ -35,7 +35,7 @@ extern ActorInfo chLargeCrocodile; extern ActorInfo chLongSwampSwitch; extern ActorInfo chShortSwampSwitch; -void BGS_func_8038F1E0(void){//bgs_updateSpawnableActors +void bgs_updateSpawnableActors(void){//bgs_updateSpawnableActors spawnableActorList_add(&gChCroctus, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_3);//croctus spawnableActorList_add(&gChFlibbit, actor_new, ACTOR_FLAG_UNKNOWN_25 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_0); //flibbit spawnableActorList_add(&chPinkEggLargest, actor_new, ACTOR_FLAG_UNKNOWN_10); //pink_egg_largest @@ -44,7 +44,7 @@ void BGS_func_8038F1E0(void){//bgs_updateSpawnableActors spawnableActorList_add(&chPinkEggSmall, actor_new, ACTOR_FLAG_UNKNOWN_10); //pink_egg_small spawnableActorList_add(&chPinkEggSmallest, actor_new, ACTOR_FLAG_UNKNOWN_10); //pink_egg_smallest spawnableActorList_add(&chMudHut, actor_new, ACTOR_FLAG_NONE); //mudhut_top - spawnableActorList_add(&chTanktup, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_3);//tanktup + spawnableActorList_add(&gChTanktup, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_3);//tanktup spawnableActorList_add(&gChTanktupLegFrontLeft, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_2);//tanktup_leg spawnableActorList_add(&gChTanktupLegBackLeft, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_2);//tanktup_leg spawnableActorList_add(&gChTanktupLegFrontRight, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_2);//tanktup_leg @@ -54,7 +54,7 @@ void BGS_func_8038F1E0(void){//bgs_updateSpawnableActors spawnableActorList_add(&D_80390960, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&gChYumblie, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7); //yumblie spawnableActorList_add(&gChVile, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_1); //mr. vile - spawnableActorList_add(&chTiptup, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup + spawnableActorList_add(&gChTiptup, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup spawnableActorList_add(&chChoirTurtleYellow, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup_chiorMember spawnableActorList_add(&chChoirTurtleCyan, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup_chiorMember spawnableActorList_add(&chChoirTurtleBlue, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup_chiorMember diff --git a/src/BGS/bss_pad.c b/src/BGS/bss_pad.c deleted file mode 100644 index cc6b75e24..000000000 --- a/src/BGS/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_BGS_D_80391230[0x10]; diff --git a/src/BGS/ch/choir_turtle.c b/src/BGS/ch/choirturtle.c similarity index 95% rename from src/BGS/ch/choir_turtle.c rename to src/BGS/ch/choirturtle.c index 6c358bcb3..fe30576bc 100644 --- a/src/BGS/ch/choir_turtle.c +++ b/src/BGS/ch/choirturtle.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_3030.c +// BanjoDecomp: BGS/ch/choirturtle.c #include #include "functions.h" #include "variables.h" @@ -62,7 +62,7 @@ void chChoirTurtle_ow2(ActorMarker *marker, ActorMarker *other_marker){ } Actor *chChoirTurtle_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - func_8033A45C(4, marker->id - 0x19A); + modelRender_setAppendageVisibility(4, marker->id - 0x19A); return actor_draw(marker, gfx, mtx, vtx); } @@ -96,7 +96,7 @@ void chChoirTurtle_update(Actor *this) { } } if (this->state == 1) { - if (local->tiptup_marker != NULL && (func_80388E70(local->tiptup_marker) == local->unk0)) { + if (local->tiptup_marker != NULL && (chTiptup_getUnkB(local->tiptup_marker) == local->unk0)) { chChoirTurtle_setState(this, 2); } } diff --git a/src/BGS/ch/croctus.c b/src/BGS/ch/croctus.c index b589e5a60..6c429088b 100644 --- a/src/BGS/ch/croctus.c +++ b/src/BGS/ch/croctus.c @@ -1,9 +1,14 @@ -// BanjoDecomp: croctus.c +// BanjoDecomp: BGS/ch/croctus.c #include #include "functions.h" #include "variables.h" -extern s32 func_80328748(AnimCtrl *, f32, f32); +#include "port/Patches/Patches.h" + +// Anchor: set while replaying a teammate's feed; suppresses camera/dialog + rebroadcast. +static s32 sCroctusRemote = 0; + +extern void func_80328748(AnimCtrl *, f32, f32); extern void func_8028F94C(s32, f32[3]); extern void func_80324CFC(f32, enum comusic_e, s32); extern void func_803289EC(Actor *, f32, s32); @@ -11,15 +16,15 @@ extern void func_80326310(Actor *); extern void actor_setOpacity(Actor *, s32); extern void gcStaticCamera_activate(s32 arg0); - - void func_80387D18(ActorMarker *, u32); Actor *chCroctus_draw(ActorMarker *, Gfx**, Mtx **, Vtx**); -void chCroctus_updat(Actor *this); +void chCroctus_update(Actor *this); /* .data */ s16 D_803907B0[4] = {0x15, 0x16, 0x17, 0x18}; + ActorMarker *bgs_D_803907B8[5] = {NULL}; + ActorAnimationInfo chCroctusAnimations[] = { {0x000, 0.0f}, {0x14B, 3.3e+7f}, @@ -29,12 +34,23 @@ ActorAnimationInfo chCroctusAnimations[] = { {0x14B, 2.0f}, {0x14B, 2.0f} }; -ActorInfo gChCroctus ={MARKER_FC_CROCTUS, ACTOR_1FA_CROCTUS, ASSET_425_MODEL_CROCTUS, + +ActorInfo gChCroctus ={ + MARKER_FC_CROCTUS, ACTOR_1FA_CROCTUS, ASSET_425_MODEL_CROCTUS, 1, chCroctusAnimations, - chCroctus_updat, actor_update_func_80326224, chCroctus_draw, + chCroctus_update, actor_update_func_80326224, chCroctus_draw, 0, 0, 0.0f, 0 }; +enum chCroctusState { + CHCROCTUS_STATE_1_MOUTH_CLOSED = 1, + CHCROCTUS_STATE_2_MOUTH_OPENING, + CHCROCTUS_STATE_3_MOUTH_OPEN, + CHCROCTUS_STATE_4_MOUTH_CLOSING, + CHCROCTUS_STATE_5_FED, + CHCROCTUS_STATE_6_DESPAWN, +}; + /* .code */ void func_80387C90(Actor *arg0){ anctrl_setDuration(arg0->anctrl, 0.4 + 0.9999999999999999 * ((f32)(5 - arg0->actorTypeSpecificField) * 0.25)); @@ -46,7 +62,7 @@ void func_80387D18(ActorMarker * arg0, u32 arg1){ this = marker_getActor(arg0); nextActPtr = spawn_child_actor(0x6A, &this); - nextActPtr->state = 2; + nextActPtr->state = CHCROCTUS_STATE_2_MOUTH_OPENING; nextActPtr->actorTypeSpecificField = 0x8C; nextActPtr->lifetime_value = 3.0f; nextActPtr->unk38_31 = arg1; @@ -64,18 +80,16 @@ void *chCroctus_jiggySpawn(ActorMarker * arg0){ spawnPos[1] = this->position_y; spawnPos[2] = this->position_z; marker->propPtr->unk8_3 = 0; - gcStaticCamera_activate(0x19); + gcStaticCamera_activate(0x19); //related to temporary switch to fixed camera jiggy_spawn(JIGGY_22_CROCTUS, spawnPos); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - return NULL; } -void func_80387E00(uintptr_t arg0){ - ActorMarker *marker = reinterpret_cast(ActorMarker *, arg0); - Actor * this = marker_getActor(marker); +void func_80387E00(ActorMarker *arg0){ + Actor * this = marker_getActor(arg0); func_803262E4(this); - __spawnQueue_add_2((void (*)(void))func_80387D18, (uintptr_t)marker, 0x1E); + __spawnQueue_add_2((GenFunction_2)func_80387D18, reinterpret_cast(uintptr_t, arg0), 0x1E); } void func_80387E40(ActorMarker * arg0){ @@ -84,22 +98,24 @@ void func_80387E40(ActorMarker * arg0){ if(arg0); } -void func_80387E68(ActorMarker *caller, enum asset_e text_id, s32 arg2){ +void chCroctus_activateNextCroctus(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this; - if(text_id == 0xC86){ + if(text_id == VER_SELECT(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0x9C9, 0, 0)){ this = marker_getActor(caller); timed_playSfx(0.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); timed_playSfx(1.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); func_80324CFC(0.4f, COMUSIC_43_ENTER_LEVEL_GLITTER, 22000); func_80324D2C(4.5f, COMUSIC_43_ENTER_LEVEL_GLITTER); - subaddie_set_state_with_direction(this, 5, 0.79f, 1); + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_5_FED, 0.79f, 1); func_80326310(this); //did not disappear when moved, after cutscene still there with collision but broken - bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = true; - timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, (uintptr_t)bgs_D_803907B8[this->actorTypeSpecificField]); - timed_setStaticCameraToNode(0.8f, 9); - func_80324DBC(3.4f, 0xC87, 0xE, NULL, NULL, func_80387E68, NULL); - __spawnQueue_add_2((void (*)(void))func_80387D18, (uintptr_t)this->marker, 0x46); + bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = TRUE; + timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, reinterpret_cast(uintptr_t, bgs_D_803907B8[this->actorTypeSpecificField])); + if(!sCroctusRemote){ + timed_setStaticCameraToNode(0.8f, 9); + func_80324DBC(3.4f, VER_SELECT(ASSET_C87_DIALOG_CROCTUS_SECOND_SPAWN, 0x9CA, 0, 0), 0xE, NULL, NULL, chCroctus_activateNextCroctus, NULL); + } + __spawnQueue_add_2((GenFunction_2) func_80387D18, reinterpret_cast(uintptr_t, this->marker), 0x46); } else{ timed_exitStaticCamera(0.0f); @@ -107,7 +123,7 @@ void func_80387E68(ActorMarker *caller, enum asset_e text_id, s32 arg2){ } } -void chCroctus_updat(Actor *this){ +void chCroctus_update(Actor *this){ int j; if(!this->volatile_initialized){ @@ -115,12 +131,12 @@ void chCroctus_updat(Actor *this){ marker_despawn(this->marker); return; } - this->volatile_initialized = true; + this->volatile_initialized = TRUE; if(bgs_D_803907B8[this->actorTypeSpecificField - 1] == 0){ bgs_D_803907B8[this->actorTypeSpecificField - 1] = this->marker; - for(j = this->actorTypeSpecificField; j < 5; j++){ + for(j = this->actorTypeSpecificField; j < 6; j++){ if(bgs_D_803907B8[j] != NULL){ - bgs_D_803907B8[j]->propPtr->isNotFeatherEggOrNote = false; + bgs_D_803907B8[j]->propPtr->isNotFeatherEggOrNote = FALSE; actor_setOpacity(marker_getActor(bgs_D_803907B8[j]), 0); } }//L803880C8 @@ -129,105 +145,130 @@ void chCroctus_updat(Actor *this){ if(j >= 0){ - this->marker->propPtr->isNotFeatherEggOrNote = false; + this->marker->propPtr->isNotFeatherEggOrNote = FALSE; actor_setOpacity(this, 0); } - this->marker->propPtr->unk8_3 = true; + this->marker->propPtr->unk8_3 = TRUE; }//L80388144 func_803289EC(this, 0.0f, 1); this->lifetime_value = 0.0f; return; }//L80388160 + // Anchor: teammate finished the chain — despawn our heads unless mid-cutscene (state 5/6). + if(jiggyscore_isSpawned(JIGGY_22_CROCTUS) && this->state != 5 && this->state != 6){ + marker_despawn(this->marker); + return; + } + + // Anchor: replay a teammate's feed of the active head (field 5 handled by the despawn above). + if (this->actorTypeSpecificField < 5 && this->state != 5 && this->state != 6 && !this->unk38_31 + && this->marker->propPtr->isNotFeatherEggOrNote + && (port_puzzleStep_get(ANCHOR_PUZZLE_BGS_CROCTUS) & (1 << (this->actorTypeSpecificField - 1)))) { + sCroctusRemote = 1; + this->unk38_31 = 1; + } + if(this->unk38_31){ - if ((this->state != 5) && (this->state != 6)) { + if ((this->state != CHCROCTUS_STATE_5_FED) && (this->state != CHCROCTUS_STATE_6_DESPAWN)) { + if (!sCroctusRemote) { + port_puzzleStep_orBits(ANCHOR_PUZZLE_BGS_CROCTUS, 1 << (this->actorTypeSpecificField - 1)); + } coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); //TODO ISSUE HERE if (this->actorTypeSpecificField == 1) { - func_8028F94C(2, this->position); - gcdialog_showDialog(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0xE, this->position, this->marker, func_80387E68, NULL); - subaddie_set_state_with_direction(this, 6, 0.79f, 1); + // Anchor: func_8028F94C = look-at, released only by the dialog we skip; don't push when replaying. + if (!sCroctusRemote) { + func_8028F94C(2, this->position); + } + if (sCroctusRemote) { + chCroctus_activateNextCroctus(this->marker, VER_SELECT(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0x9C9, 0, 0), 0); + } else { + gcdialog_showDialog(VER_SELECT(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0x9C9, 0, 0), 0xE, this->position, this->marker, chCroctus_activateNextCroctus, NULL); + } + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_6_DESPAWN, 0.79f, 1); } else { - timed_playSfx(0.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); //0.4f - timed_playSfx(1.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); //1.4f + timed_playSfx(0.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); + timed_playSfx(1.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); func_80324CFC(0.4f, COMUSIC_43_ENTER_LEVEL_GLITTER, 22000); func_80324D2C(4.5f, COMUSIC_43_ENTER_LEVEL_GLITTER); - subaddie_set_state_with_direction(this, 5, 0.79f, 1); + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_5_FED, 0.79f, 1); if (this->actorTypeSpecificField == 5) { - timedFunc_set_1(0.9f, (GenFunction_1) func_80387E40, (uintptr_t)this->marker); + timedFunc_set_1(0.9f, (GenFunction_1) func_80387E40, reinterpret_cast(uintptr_t, this->marker)); } else { func_80326310(this); } if (this->actorTypeSpecificField < 5) { - bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = true; - timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, (uintptr_t)bgs_D_803907B8[this->actorTypeSpecificField]); - gcStaticCamera_activate(D_803907B0[this->actorTypeSpecificField-1]); + bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = TRUE; + timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, reinterpret_cast(uintptr_t, bgs_D_803907B8[this->actorTypeSpecificField])); + if (!sCroctusRemote) gcStaticCamera_activate(D_803907B0[this->actorTypeSpecificField-1]); } else { - timedFunc_set_1(0.8f, (GenFunction_1)chCroctus_jiggySpawn, (uintptr_t)this->marker); + timedFunc_set_1(0.8f, (GenFunction_1)chCroctus_jiggySpawn, reinterpret_cast(uintptr_t, this->marker)); } - __spawnQueue_add_2((void (*)(void))func_80387D18, (uintptr_t)this->marker, 0x46); + __spawnQueue_add_2((GenFunction_2)func_80387D18, reinterpret_cast(uintptr_t, this->marker), 0x46); } } }//L80388348 + sCroctusRemote = 0; switch(this->state){ - case 1:// L80388370 - this->lifetime_value += time_getDelta(); - if(0.7 <= this->lifetime_value){ - subaddie_set_state_with_direction(this, 2, 0.0f, 1); - func_80387C90(this); - this->lifetime_value = 0.0f; - func_80324D54(0.1f, SFX_D0_GRIMLET_SQUEAK, 1.0f, 0x7530, this->position, 0.0f, 1800.0f); - } - break; + case CHCROCTUS_STATE_1_MOUTH_CLOSED:// L80388370 + this->lifetime_value += time_getDelta(); + if(0.7 <= this->lifetime_value){ + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_2_MOUTH_OPENING, 0.0f, 1); + func_80387C90(this); + this->lifetime_value = 0.0f; + func_80324D54(0.1f, SFX_D0_GRIMLET_SQUEAK, 1.0f, 0x7530, this->position, 0.0f, 1800.0f); + } + break; - case 2:// L80388400 - if(actor_animationIsAt(this, 0.62f)){ - subaddie_set_state_with_direction(this, 3, 0.62f, 1); - } - break; - - case 3:// L80388434 - this->lifetime_value += time_getDelta(); - if( this->lifetime_value >= 0.13 + 0.7/4 * (5 - this->actorTypeSpecificField)){ - subaddie_set_state_with_direction(this, 4, 0.62f, 1); - func_80387C90(this); - this->lifetime_value = 0.0f; - func_80324D54(0.3f, 0x406, 1.0f, 0x55f0, this->position, 0.0f, 1800.0f); - } - break; + case CHCROCTUS_STATE_2_MOUTH_OPENING:// L80388400 + if(actor_animationIsAt(this, 0.62f)){ + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_3_MOUTH_OPEN, 0.62f, 1); + } + break; - case 4:// L8038850C - if(actor_animationIsAt(this, 0.0f)){ - subaddie_set_state_with_direction(this, 1, 0.0f, 1); - } - break; - - case 5:// L80388538 - func_80328748(this->anctrl, 0.79f, 0.97f); - if( actor_animationIsAt(this, 0.84f) - && !anctrl_isPlayedForwards(this->anctrl) - && func_802BB270() - ){ - gcsfx_playWithPitch(SFX_C8_CRUNCH, randf2(0.93f, 1.07f), 22000); - } - break; + case CHCROCTUS_STATE_3_MOUTH_OPEN:// L80388434 + this->lifetime_value += time_getDelta(); + if( this->lifetime_value >= 0.13 + 0.7/4 * (5 - this->actorTypeSpecificField)){ + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_4_MOUTH_CLOSING, 0.62f, 1); + func_80387C90(this); + this->lifetime_value = 0.0f; + func_80324D54(0.3f, SFX_406_GOLD_BULLION_TALKING, 1.0f, 0x55f0, this->position, 0.0f, 1800.0f); + } + break; + + case CHCROCTUS_STATE_4_MOUTH_CLOSING:// L8038850C + if(actor_animationIsAt(this, 0.0f)){ + subaddie_set_state_with_direction(this, CHCROCTUS_STATE_1_MOUTH_CLOSED, 0.0f, 1); + } + break; + + case CHCROCTUS_STATE_5_FED:// L80388538 + func_80328748(this->anctrl, 0.79f, 0.97f); + if( actor_animationIsAt(this, 0.84f) + && !anctrl_isPlayedForwards(this->anctrl) + && func_802BB270() + ){ + gcsfx_playWithPitch(SFX_C8_CRUNCH, randf2(0.93f, 1.07f), 22000); + } + break; - case 6:// L803885B0 - func_80328748(this->anctrl, 0.79f, 0.97f); + case CHCROCTUS_STATE_6_DESPAWN:// L803885B0 + func_80328748(this->anctrl, 0.79f, 0.97f); - break; + break; } } void BGS_func_803885DC(void){ s32 i; - for(i = 0; i<5; i++) + for(i = 0; i < 5; i++) bgs_D_803907B8[i] = 0; } Actor *chCroctus_draw(ActorMarker *this, Gfx** gdl, Mtx ** mptr, Vtx **vtx){ Actor *thisActor; thisActor = marker_getActor(this); - func_8033A45C(1, thisActor->actorTypeSpecificField); + modelRender_setAppendageVisibility(1, thisActor->actorTypeSpecificField); return actor_draw(this, gdl, mptr, vtx); } diff --git a/src/BGS/ch/frogminigame.c b/src/BGS/ch/frogminigame.c index 964e069a9..d4752a841 100644 --- a/src/BGS/ch/frogminigame.c +++ b/src/BGS/ch/frogminigame.c @@ -4,7 +4,7 @@ #include "variables.h" -void chfrogminigame_update(Actor *); +void chFrogMinigame_update(Actor *); void chFrogMinigame_setState(Actor * arg0, u32 next_state); void func_8025A58C(u32, u32); void timed_exitStaticCamera(f32); @@ -12,11 +12,20 @@ void timed_exitStaticCamera(f32); ActorInfo chFrogMinigame = {MARKER_C4_YELLOW_FLIBBIT_CTRL, ACTOR_136_YELLOW_FLIBBIT_CONTROLLER, 0x00, 0x00, NULL, - chfrogminigame_update, NULL, func_80325340, + chFrogMinigame_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; +enum chFrogMinigameState { + CH_FROG_MINIGAME_STATE_1_IDLE = 1, + CH_FROG_MINIGAME_STATE_2_ENTER_BATTLE, + CH_FROG_MINIGAME_STATE_3_BATTLE, + CH_FROG_MINIGAME_STATE_4_COMPLETE, + CH_FROG_MINIGAME_STATE_5_SPAWN_JIGGY, + CH_FROG_MINIGAME_STATE_6_DESPAWN +}; + /* .bss */ u8 D_80391240[4]; @@ -37,7 +46,7 @@ static void __chFrogMinigame_textCallback(ActorMarker *marker, enum asset_e text } } -void func_8038CBB4(Actor * arg0){ +void chFrogMinigame_stopFlibbitFightMusic(Actor * arg0){ if(!arg0->bgs_6730.unk4) return; func_8025A58C(-1, 400); @@ -57,13 +66,13 @@ void chFrogMinigame_setState(Actor * arg0, u32 next_state){ mapSpecificFlags_set(0x10, 1); if(!fileProgressFlag_get(FILEPROG_1B_MET_YELLOW_FLIBBITS)){ fileProgressFlag_set(FILEPROG_1B_MET_YELLOW_FLIBBITS, 1); - gcdialog_showDialog(ASSET_C81_DIALOG_YELLOW_FLIBBITS_MEET, 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); + gcdialog_showDialog(VER_SELECT(ASSET_C81_DIALOG_YELLOW_FLIBBITS_MEET, 0x9C4, 0, 0), 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); }else{ if(!arg0->bgs_6730.unk8){ - gcdialog_showDialog(ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0x4, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); + gcdialog_showDialog(VER_SELECT(ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0x9C6, 0, 0), 0x4, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); } else{ - __chFrogMinigame_textCallback(arg0->marker, ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0); + __chFrogMinigame_textCallback(arg0->marker, VER_SELECT(ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0x9C6, 0, 0), 0); return; } } @@ -89,12 +98,12 @@ void chFrogMinigame_setState(Actor * arg0, u32 next_state){ } } else{ - func_8038CBB4(arg0); + chFrogMinigame_stopFlibbitFightMusic(arg0); } } - if (next_state == 4) { - gcdialog_showDialog(ASSET_C82_DIALOG_YELLOW_FLIBBITS_COMPLETE, 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); + if (next_state == CH_FROG_MINIGAME_STATE_4_COMPLETE) { + gcdialog_showDialog(VER_SELECT(ASSET_C82_DIALOG_YELLOW_FLIBBITS_COMPLETE, 0x9C5, 0, 0), 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); } if(next_state == 5){ @@ -128,7 +137,7 @@ void BGS_func_8038CED0(void){ D_80391240[3]++; } -void chfrogminigame_update(Actor *this){ +void chFrogMinigame_update(Actor *this){ f32 player_position[3]; u32 sp28; ActorLocal_BGS_6730 *local; @@ -181,7 +190,7 @@ void chfrogminigame_update(Actor *this){ else{ //L8038D0E0 if(local->unk4 && !local->unk8){ - func_8038CBB4(this); + chFrogMinigame_stopFlibbitFightMusic(this); } } } diff --git a/src/BGS/ch/leafboat.c b/src/BGS/ch/leafboat.c index 4efcf8b16..04d3ac1d0 100644 --- a/src/BGS/ch/leafboat.c +++ b/src/BGS/ch/leafboat.c @@ -153,9 +153,9 @@ void chLeafBoat_update(Actor *this){ local->unk60[1] = this->yaw; local->unk60[2] = this->roll; this->lifetime_value += time_getDelta(); - _player_getPosition(player_position); + playerPosition_get(player_position); if( func_80294660() == 0x100 - && func_8028F20C() + && player_isStableWithExtraSteps() && this->marker->isBanjoOnTop ){ sp44 = local->unk54[0] - player_position[0]; diff --git a/src/BGS/ch/mrvile.c b/src/BGS/ch/mrvile.c index b5c54892a..4ac36b28c 100644 --- a/src/BGS/ch/mrvile.c +++ b/src/BGS/ch/mrvile.c @@ -7,12 +7,12 @@ #include "core2/modelRender.h" #include "port/Enhancements/Events/Hooks/Events.h" -Actor *chvile_draw(ActorMarker*, Gfx **, Mtx **, Vtx **); -void chvile_update(Actor *); -void func_8038BB40(ActorMarker *); +Actor *chMrVile_draw(ActorMarker*, Gfx **, Mtx **, Vtx **); +void chMrVile_update(Actor *); +void chMrVile_attackPlayer(ActorMarker *); extern BKCollisionTriangle *func_80320C94(f32[3], f32[3], f32, f32[3], s32, u32); -extern bool chvilegame_find_closest_piece(ActorMarker *, f32[3], f32, f32[3]); +extern bool chMrVileMinigame_findClosestPiece(ActorMarker *, f32[3], f32, f32[3]); typedef struct chmrvile_s{ u8 unk0; @@ -30,7 +30,7 @@ typedef struct chmrvile_s{ /* .data */ ActorInfo gChVile = {MARKER_C8_MR_VILE, ACTOR_13A_MR_VILE, ASSET_373_MODEL_MR_VILE, 0x00, NULL, - chvile_update, NULL, chvile_draw, + chMrVile_update, NULL, chMrVile_draw, 0, 0, 0.0f, 0 }; @@ -73,13 +73,13 @@ void func_8038B9F0(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3, s32 arg4) { } } -void func_8038BB40(ActorMarker * arg0){ +void chMrVile_attackPlayer(ActorMarker * arg0){ Actor *this; ActorLocal_MrVile *local; this = marker_getActor(arg0); local = (ActorLocal_MrVile *)&this->local; - if(func_8038A9E0(local->game_marker) >= 3){ + if(chMrVileMinigame_getDialogIndex(local->game_marker) >= 3){ item_set(ITEM_14_HEALTH, 0); func_8028F66C(BS_INTR_F); } @@ -89,7 +89,7 @@ void func_8038BB40(ActorMarker * arg0){ } } -void BGS_func_8038BBA0(Actor *this, s32 arg1){ +void chMrVile_setAction(Actor *this, s32 arg1){ ActorLocal_MrVile *local; local = (ActorLocal_MrVile *)&this->local; @@ -109,7 +109,7 @@ void BGS_func_8038BBA0(Actor *this, s32 arg1){ skeletalAnim_swap(this->unk148, 0x124, 0.1f, 0.5f); //0x124 = croc_munch if(this->state == 4){ timed_playSfx(0.31f, SFX_4C_LIP_SMACK, 0.90f, 25000); - timedFunc_set_1(0.31f, (GenFunction_1)func_8038BB40, (uintptr_t)this->marker); + timedFunc_set_1(0.31f, (GenFunction_1)chMrVile_attackPlayer, (uintptr_t)this->marker); } else{ timed_playSfx(0.31f, SFX_4C_LIP_SMACK, 0.90f, 25000); @@ -138,7 +138,7 @@ void func_8038BD84(Actor *this){ local->unk28[0] = 0.0f; local->unk28[1] = 0.0f; local->unk28[2] = 0.0f; - BGS_func_8038BBA0(this, 101); + chMrVile_setAction(this, 101); } void func_8038BDD4(Actor *this) { @@ -195,37 +195,37 @@ void func_8038BDD4(Actor *this) { } } -void chVile_setState(Actor * this, s32 next_state){ +void chMrVile_setState(Actor * this, s32 next_state){ ActorLocal_MrVile *local; local = (ActorLocal_MrVile *)&this->local; if(next_state == 1) - BGS_func_8038BBA0(this, 101); + chMrVile_setAction(this, 101); if(next_state == 2) - BGS_func_8038BBA0(this, 101); + chMrVile_setAction(this, 101); if(next_state == 3) - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); if(next_state == 4) - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); if(next_state == 5){ local->target_position[0] = local->target_position[1] = local->target_position[2] = 0.0f; - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); } if(next_state == 6){ local->target_position[0] = local->target_position[1] = local->target_position[2] = 0.0f; local->unk24 = 300.0f; - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); } this->state = next_state; } -Actor *chvile_draw(ActorMarker *marker, Gfx **gfx, Mtx** mtx, Vtx **vtx){ +Actor *chMrVile_draw(ActorMarker *marker, Gfx **gfx, Mtx** mtx, Vtx **vtx){ Actor *this; ActorLocal_MrVile *local; f32 position[3]; @@ -246,14 +246,14 @@ Actor *chvile_draw(ActorMarker *marker, Gfx **gfx, Mtx** mtx, Vtx **vtx){ return this; } -f32 *chVile_getPostion(ActorMarker *marker){ +f32 *chMrVile_getPostion(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); return this->position; } -bool func_8038C2A8(ActorMarker *marker) { +bool chMrVile_playerWithinRange(ActorMarker *marker) { f32 player_position[3]; Actor *this; ActorLocal_MrVile *local; @@ -268,14 +268,14 @@ bool func_8038C2A8(ActorMarker *marker) { } -bool BGS_func_8038C338(ActorMarker *marker){ +bool chMrVile_isInitialIdle(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); return this->state == 1; } -void chvile_free(Actor *this){ +void chMrVile_free(Actor *this){ ActorLocal_MrVile *local; local = (ActorLocal_MrVile *)&this->local; @@ -283,46 +283,46 @@ void chvile_free(Actor *this){ } -void func_8038C384(ActorMarker *marker){ +void chMrVile_setStateAttackPlayer(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chVile_setState(this, 4); + chMrVile_setState(this, 4); } -void func_8038C3B0(ActorMarker *marker){ +void chMrVile_setStateTalkToPlayer(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chVile_setState(this, 2); + chMrVile_setState(this, 2); } -void func_8038C3DC(ActorMarker *marker){ +void chMrVile_setStatePlayMinigame(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chVile_setState(this, 3); + chMrVile_setState(this, 3); } -void func_8038C408(ActorMarker *marker){ +void chMrVile_setStateIdleWalking(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chVile_setState(this, 5); + chMrVile_setState(this, 5); } -void BGS_func_8038C434(ActorMarker *marker){ +void chMrVile_setStateRunFromPlayer(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chVile_setState(this, 6); + chMrVile_setState(this, 6); } -void BGS_func_8038C460(ActorMarker *arg0){ - chVile_setState(marker_getActor(arg0), 1); +void chMrVile_setInitialIdleStill(ActorMarker *arg0){ + chMrVile_setState(marker_getActor(arg0), 1); } -void chvile_update(Actor *this) { +void chMrVile_update(Actor *this) { f32 player_position[3]; f32 sp90; f32 temp_a0; @@ -341,12 +341,12 @@ void chvile_update(Actor *this) { local = (ActorLocal_MrVile *)&this->local; if (!this->volatile_initialized) { this->volatile_initialized = true; - this->marker->actorFreeFunc = chvile_free; + this->marker->actorFreeFunc = chMrVile_free; local->unk0 = 0; local->unk4 = assetcache_get(0x3F6); local->game_marker = NULL; func_8038BD84(this); - chVile_setState(this, 1); + chMrVile_setState(this, 1); return; } if (local->game_marker == NULL) { @@ -372,18 +372,18 @@ void chvile_update(Actor *this) { if (((sp84 > 50.0f) && (0.05 < sp7C)) || (sp7C < -0.05)) { this->yaw += sp7C * 20.0f; } else { - chVile_setState(this, 1); + chMrVile_setState(this, 1); } } if (this->state == 3) { - var_v1 = chvilegame_find_closest_piece(local->game_marker, this->position, this->yaw, local->target_position) && mapSpecificFlags_get(6); + var_v1 = chMrVileMinigame_findClosestPiece(local->game_marker, this->position, this->yaw, local->target_position) && mapSpecificFlags_get(6); if (!var_v1) { local->target_position[0] = 0.0f; local->target_position[1] = 0.0f; local->target_position[2] = 0.0f; } if (local->game_marker != NULL) { - temp_v0 = chvilegame_get_score_difference(local->game_marker); + temp_v0 = chMrVileMinigame_getScoreDifference(local->game_marker); if (temp_v0 >= 2) { local->unk10 = 200.0f; } else if (temp_v0 >= 0) { @@ -393,29 +393,29 @@ void chvile_update(Actor *this) { } else { local->unk10 = 450.0f; } - local->unk10 *= D_80390A94[func_8038A9E0(local->game_marker)]; + local->unk10 *= D_80390A94[chMrVileMinigame_getDialogIndex(local->game_marker)]; CALL_EVENT(OnMrVileSetSpeed, &local->unk10); } - if (func_8038A9E0(local->game_marker) < 7) { + if (chMrVileMinigame_getDialogIndex(local->game_marker) < 7) { func_80258A4C(this->position, this->yaw - 90.0f, local->target_position, &sp70, &sp6C, &sp68); if (local->unkC == 102) { if ((-0.8 < sp68) && (sp68 < 0.8) && (sp70 <= 150.0f) && var_v1) { - BGS_func_8038BBA0(this, 103); + chMrVile_setAction(this, 103); } } if (local->unkC == 103) { if (sp70 <= 50.0f) { - if (chvilegame_cpu_consume_piece(local->game_marker, local->target_position)) { - BGS_func_8038BBA0(this, 104); + if (chMrVileMinigame_mrVileConsumePiece(local->game_marker, local->target_position)) { + chMrVile_setAction(this, 104); } else { - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); } } else if (skeletalAnim_getLoopCount(this->unk148) >= 3) { - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); } } if ((local->unkC == 104) && (skeletalAnim_getLoopCount(this->unk148) >= 3)) { - BGS_func_8038BBA0(this, 102); + chMrVile_setAction(this, 102); } } } @@ -423,10 +423,10 @@ void chvile_update(Actor *this) { player_getPosition(local->target_position); local->unk10 = 500.0f; if ((local->unkC == 102) && (ml_vec3f_distance(this->position, local->target_position) < 200.0f)) { - BGS_func_8038BBA0(this, 103); + chMrVile_setAction(this, 103); } if ((local->unkC == 103) && (skeletalAnim_getLoopCount(this->unk148) >= 2)) { - chVile_setState(this, 1); + chMrVile_setState(this, 1); } } if (this->state == 5) { @@ -460,7 +460,7 @@ void chvile_update(Actor *this) { // [port] Anchor sync entry points. // Applies a streamed transform + anim mode from the minigame authority. -void chvile_netApplyUpdate(Actor *this, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode){ +void chMrVile_netApplyUpdate(Actor *this, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode){ ActorLocal_MrVile *local = (ActorLocal_MrVile *)&this->local; this->position[0] = position[0]; @@ -470,11 +470,11 @@ void chvile_netApplyUpdate(Actor *this, const f32 position[3], f32 pitch, f32 ya this->yaw = yaw; this->roll = roll; if (local->unkC != anim_mode) { - BGS_func_8038BBA0(this, anim_mode); + chMrVile_setAction(this, anim_mode); } } -s32 chvile_netGetAnimMode(Actor *this){ +s32 chMrVile_netGetAnimMode(Actor *this){ ActorLocal_MrVile *local = (ActorLocal_MrVile *)&this->local; return local->unkC; diff --git a/src/BGS/ch/mudhut.c b/src/BGS/ch/mudhut.c index eccc0113c..dfb64a49b 100644 --- a/src/BGS/ch/mudhut.c +++ b/src/BGS/ch/mudhut.c @@ -6,6 +6,8 @@ #include +#include "port/Patches/Patches.h" + /* TODO move declarations to respective headers*/ extern void player_stateTimer_set(enum state_timer_e, f32); extern f32 player_stateTimer_get(enum state_timer_e); @@ -63,7 +65,7 @@ Actor *chMudHut_draw(ActorMarker *this, Gfx** gdl, Mtx** mtx, Vtx **vtx){ Actor *thisActor; thisActor = marker_getActor(this); - func_8033A45C(1, thisActor->state == 1); + modelRender_setAppendageVisibility(1, thisActor->state == 1); if(thisActor->state == 3) return thisActor; @@ -79,8 +81,34 @@ void chMudHut_spawnExplosion(ActorMarker *this){ if(this); } +static void chMudHut_dropRecordedBundle(Actor *this, s32 tmp, s32 fullBundle){ + f32 pos[3]; + if(tmp < 0 || tmp >= 5){ + return; // jiggy / out of range: handled by JIGGY_SPAWN, not the hut + } + if(!fullBundle && tmp == 2){ + return; // note: spawn live but skip on reload + } + pos[0] = this->position_x; + pos[1] = this->position_y + 130.0f; + pos[2] = this->position_z; + __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, D_80390B50[tmp], reinterpret_cast(s32, pos[0]), reinterpret_cast(s32, pos[1]), reinterpret_cast(s32, pos[2])); +} + +static void chMudHut_replaySmash(Actor *this, s32 tmp){ + sfx_playFadeShorthandDefault(SFX_5B_HEAVY_STUFF_FALLING, 1.0f, 28000, this->position, 0x12C, 0xBB8); + subaddie_set_state(this, 2); + this->marker->propPtr->unk8_3 = 0; + actor_playAnimationOnce(this); + if(tmp == 5){ + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + } + __spawnQueue_add_1((GenFunction_1)chMudHut_spawnExplosion, (uintptr_t)this->marker); + chMudHut_dropRecordedBundle(this, tmp, 1); +} + void chMudHut_update(Actor *this){ - + f32 diffPos[3]; f32 plyrPos[3]; s32 tmp; @@ -89,6 +117,14 @@ void chMudHut_update(Actor *this){ if(!this->initialized){ this->marker->collidable = false; this->initialized = true; + // Anchor: already smashed this session — restore broken, re-drop non-tracked loot. + tmp = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); + if(tmp >= 0){ + this->state = 3; + this->marker->propPtr->unk8_3 = 0; + chMudHut_dropRecordedBundle(this, tmp, 0); + return; + } } switch(this->state){ @@ -98,9 +134,9 @@ void chMudHut_update(Actor *this){ diffPos[0] = plyrPos[0] - this->position_x; diffPos[1] = plyrPos[1] - this->position_y; diffPos[2] = plyrPos[2] - this->position_z; - if( (150.0f < diffPos[1]) - && (player_getActiveHitbox(this->marker) == HITBOX_1_BEAK_BUSTER) - && (func_8028F20C()) + if( (150.0f < diffPos[1]) + && (player_getActiveHitbox(this->marker) == HITBOX_1_BEAK_BUSTER) + && (player_isStableWithExtraSteps()) && (LENGTH_VEC3F(diffPos) < 350.f) ){ tmp = (s32)( (this->position_y - 600.f)/430.0f); @@ -124,6 +160,13 @@ void chMudHut_update(Actor *this){ else { jiggy_spawn(JIGGY_23_BGS_HUTS, diffPos); } + port_hutSmash_record((s32)this->position_x, (s32)this->position_y, (s32)this->position_z, tmp); + } + else { + tmp = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); + if(tmp >= 0){ + chMudHut_replaySmash(this, tmp); + } } break; case 2: diff --git a/src/BGS/ch/pinkegg.c b/src/BGS/ch/pinkegg.c index 7845ccfc6..1e513513d 100644 --- a/src/BGS/ch/pinkegg.c +++ b/src/BGS/ch/pinkegg.c @@ -3,6 +3,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + typedef struct chpinkegg_s{ u32 unk0; u32 unk4; @@ -73,8 +75,8 @@ Actor *chPinkEgg_draw(ActorMarker *this, Gfx ** gdl, Mtx** mptr, Vtx **arg3){ u32 t7; t7 = marker_getActor(this)->state == 3; - func_8033A45C(1, NOT(sp18 = t7)); - func_8033A45C(2, sp18); + modelRender_setAppendageVisibility(1, NOT(sp18 = t7)); + modelRender_setAppendageVisibility(2, sp18); return actor_draw(this, gdl, mptr, arg3); } @@ -90,9 +92,11 @@ void chPinkEgg_collision(ActorMarker *this, ActorMarker *other_marker){ actor_playAnimationOnce(thisActor); this->collidable = false; thisActor->unk124_6 = 0; - if(D_803906C4[(tmp = (ActorLocal_PinkEgg *) &thisActor->local)->unk0] != 0){ - __spawnQueue_add_2((void (*)(void))chPinkEgg_spawnNext, (uintptr_t)thisActor->marker, tmp->unk0); - } else { + tmp = (ActorLocal_PinkEgg *) &thisActor->local; + port_puzzleStep_orBits(ANCHOR_PUZZLE_BGS_PINKEGG, 1 << tmp->unk0); + if(D_803906C4[tmp->unk0] != 0){ + __spawnQueue_add_2((GenFunction_2)chPinkEgg_spawnNext, (uintptr_t)thisActor->marker, tmp->unk0); + } else if(!jiggyscore_isSpawned(JIGGY_21_BGS_PINKEGG)){ jiggy_spawn(JIGGY_21_BGS_PINKEGG, thisActor->position); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); } @@ -105,6 +109,19 @@ void chPinkEgg_update(Actor *this){ this->initialized = true; } + // Anchor: team finished the chain — despawn unless mid-break (state 3). + if(jiggyscore_isSpawned(JIGGY_21_BGS_PINKEGG) && this->state != 3){ + marker_despawn(this->marker); + return; + } + + // Anchor: replay teammates' layer breaks. + if((port_puzzleStep_get(ANCHOR_PUZZLE_BGS_PINKEGG) & (1 << ((ActorLocal_PinkEgg *)&this->local)->unk0)) + && this->state != 3){ + chPinkEgg_collision(this->marker, NULL); + return; + } + switch(this->state){ case 1: if(!((ActorLocal_PinkEgg *) &this->local)->unk4){ diff --git a/src/BGS/ch/swampswitch.c b/src/BGS/ch/swampswitch.c index 382ff6a76..cc9b28f97 100644 --- a/src/BGS/ch/swampswitch.c +++ b/src/BGS/ch/swampswitch.c @@ -40,7 +40,7 @@ void chLongSwampSwitch_update(Actor *this){ if(mapSpecificFlags_get(7)){ mapSpecificFlags_set(7, 0); if(!mapSpecificFlags_get(3) || (item_getCount(0) > 0)){ - func_802D68F0(45); + code_4C020_setHourglassTimer(45); } } if(!mapSpecificFlags_get(5)){ @@ -60,7 +60,7 @@ void chLongSwampSwitch_update(Actor *this){ } //L8038EFB4 if( this->velocity_x != 0.0f && !mapSpecificFlags_get(3) && func_802BB270()){ mapSpecificFlags_set(3,1); - func_802D68F0(45); //adjusts timer + code_4C020_setHourglassTimer(45); //adjusts timer item_set(ITEM_6_HOURGLASS,1); } //L8038EFB4 } @@ -83,7 +83,7 @@ void chShortSwampSwitch_update(Actor *this){ if(mapSpecificFlags_get(8)){ mapSpecificFlags_set(8, 0); if(!mapSpecificFlags_get(0xC) || (item_getCount(0) > 0)){ - func_802D68F0(10); + code_4C020_setHourglassTimer(10); } } if(!mapSpecificFlags_get(9)){ @@ -103,7 +103,7 @@ void chShortSwampSwitch_update(Actor *this){ } //L8038EFB4 if( this->velocity_x != 0.0f && !mapSpecificFlags_get(0xC) && func_802BB270()){ mapSpecificFlags_set(0xC,1); - func_802D68F0(10); //adjusts timer + code_4C020_setHourglassTimer(10); //adjusts timer item_set(ITEM_6_HOURGLASS,1); } //L8038EFB4 } diff --git a/src/BGS/ch/tanktup.c b/src/BGS/ch/tanktup.c index 6dd23ca02..457de1af0 100644 --- a/src/BGS/ch/tanktup.c +++ b/src/BGS/ch/tanktup.c @@ -1,16 +1,15 @@ -// BanjoDecomp: tanktup.c +// BanjoDecomp: BGS/ch/tanktup.c #include #include "functions.h" #include "variables.h" #include "prop.h" -void timed_exitStaticCamera(f32); +#include "port/Patches/Patches.h" -#include "core2/timedfunc.h" +void timed_exitStaticCamera(f32); void func_8028E668(f32[3], f32, f32, f32); -extern void __spawnQueue_add_3(GenFunction_3, uintptr_t, uintptr_t, uintptr_t); void chTanktup_update(Actor *); @@ -29,11 +28,19 @@ ActorAnimationInfo BGS_D_80390C20[] = { {0x107, 1.75f} }; -ActorInfo chTanktup = {MARKER_6C_TANKTUP, ACTOR_E8_TANKTUP, ASSET_3EE_TANKTUP, 0x01, BGS_D_80390C20, +ActorInfo gChTanktup = { + MARKER_6C_TANKTUP, ACTOR_E8_TANKTUP, ASSET_3EE_TANKTUP, + 0x01, BGS_D_80390C20, chTanktup_update, actor_update_func_80326224, actor_draw, 0, 0x80, 0.0f, 0 }; +enum chTanktupState { + CH_TANKTUP_STATE_1_UNK = 1, + CH_TANKTUP_STATE_2_UNK, + CH_TANKTUP_STATE_3_UNK, +}; + /* .code */ void func_8038F470(ActorMarker *this, s32 arg1, enum chtanktup_leg_e leg_id){ Actor* thisActor; @@ -67,9 +74,7 @@ s32 func_8038F570(s16 *arg0){ pos[1] = (f32)arg0[1]; pos[2] = (f32)arg0[2]; spawnPtr = actorArray_findClosestActorFromActorId(pos, ACTOR_E8_TANKTUP, -1, 0); - return spawnPtr->state == 3; - - + return spawnPtr->state == CH_TANKTUP_STATE_3_UNK; } void func_8038F5E4(ActorMarker *marker, enum asset_e text_id, s32 arg2){ @@ -93,138 +98,174 @@ void func_8038F610(Actor *this) { void func_8028F94C(s32, f32[3]); void func_8028F918(s32); +// Anchor: set when state 2 took the head-raise look-at/freeze push; state 3 releases it. +static s32 sTanktupCameraPushed = 0; +static s32 sTanktupPoseCatchUp = 0; + void chTanktup_update(Actor *this) { - ActorLocal_TanktupBody *local = (ActorLocal_TanktupBody *) (&this->local); - f32 sp48[3]; - s32 sp44; - NodeProp *temp_v0; - if (!this->initialized) - { - temp_v0 = nodeprop_findByActorIdAndActorPosition(ACTOR_32B_UNKNOWN, this); - if (temp_v0 == 0) + ActorLocal_TanktupBody *local = (ActorLocal_TanktupBody *) (&this->local); + f32 sp48[3]; + s32 sp44; + NodeProp *temp_v0; + if (!this->initialized) { - local->unk18[0] = 3672.0f; - local->unk18[1] = 100.0f; - local->unk18[2] = 987.0f; - } - else - { - nodeprop_getPosition(temp_v0, local->unk18); - } - this->has_met_before = false; - this->initialized = true; - } - if (!this->volatile_initialized) - { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = 1; - actor_collisionOff(this); - this->scale = 1.0f; - for (sp44 = 0; sp44 < 4; sp44++) - { - if (local->unk0[sp44] == 0) - { - __spawnQueue_add_3((GenFunction_3)func_8038F470, (uintptr_t)this->marker, local->unk0[sp44], sp44); - } - } - - if (local) - { - ; - } - } - switch (this->state) - { - case 1: - func_8038F610(this); - player_getPosition(sp48); - if (!this->has_met_before) - { - if ((((ml_vec3f_distance(local->unk18, sp48) < 250.0f) && (ml_vec3f_distance(local->unk18, sp48) > 80.0f)) && (!player_movementGroup())) && (player_getTransformation() == TRANSFORM_1_BANJO)) - { - gcdialog_showDialog(ASSET_C7E_DIALOG_TANKTUP_MEET, 0, 0, 0, 0, 0); - this->has_met_before = true; - } + temp_v0 = nodeprop_findByActorIdAndActorPosition(ACTOR_32B_UNKNOWN, this); + if (temp_v0 == 0) + { + local->unk18[0] = 3672.0f; + local->unk18[1] = 100.0f; + local->unk18[2] = 987.0f; + } + else + { + nodeprop_getPosition(temp_v0, local->unk18); + } + this->has_met_before = FALSE; + this->initialized = TRUE; } - if (local->unk10) + if (!this->volatile_initialized) { - subaddie_set_state_with_direction(this, 2, 0.0f, -1); - local->unk10 = 0; - sp44 = 0; - (void)&sp44; - local->unk14 = 1; - for (; sp44 < 4; sp44++) - { - if (local->unk0[sp44] == 0) + this->volatile_initialized = TRUE; + this->marker->propPtr->unk8_3 = 1; + actor_collisionOff(this); + this->scale = 1.0f; + sTanktupCameraPushed = 0; + // Anchor: adopt the team's already-retracted legs. { - local->unk14 = 0; + s32 legBits = port_puzzleStep_get(ANCHOR_PUZZLE_BGS_TANKTUP); + for (sp44 = 0; sp44 < 4; sp44++) + { + if (legBits & (1 << sp44)) + { + local->unk0[sp44] = 1; + } + } } - } - - if ((!this->unk138_23) && (!local->unk14)) - { - if (gcdialog_showDialog(ASSET_C80_DIALOG_TANKTUP_HIT, 0, 0, 0, 0, 0)) + for (sp44 = 0; sp44 < 4; sp44++) { - this->unk138_23 = 1; + if (local->unk0[sp44] == 0) + { + __spawnQueue_add_3((GenFunction_3)func_8038F470, reinterpret_cast(uintptr_t, this->marker), local->unk0[sp44], sp44); + } } - } - } - break; - case 2: - func_8038F610(this); - if (actor_animationIsAt(this, 0.6f) && local->unk14) - { - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - func_8028F94C(2, local->unk18); + if (local) + { + ; + } } - if (actor_animationIsAt(this, 0.99f)) + // Anchor: team completed Tanktup but our body is still idle (state 1) — raise the head to match. + if (this->state == CH_TANKTUP_STATE_1_UNK && jiggyscore_isSpawned(JIGGY_26_BGS_TANKTUP)) { - if (!local->unk14) - { - subaddie_set_state_with_direction(this, 1, 0.0f, -1); - } - else - { - subaddie_set_state_with_direction(this, 3, 0.0f, -1); + sTanktupPoseCatchUp = 1; // [port] pose only, no presentation + subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_3_UNK, 0.0f, -1); actor_playAnimationOnce(this); - } } - break; - - case 3: - if (actor_animationIsAt(this, 0.1f) != 0) + switch (this->state) { - timed_setStaticCameraToNode(0.0f, 0xD); - } - if (actor_animationIsAt(this, 0.55f) != 0) - { - func_8030E624(0x797FF885U); - } - if (actor_animationIsAt(this, 0.4f) != 0) - { - f32 sp34[3]; - vec3fArray_get_vec3f(this->marker->unk44, 6, sp34); - bundle_setYaw(this->yaw); - sp34[1] -= 125.0f; - jiggy_spawn(JIGGY_26_BGS_TANKTUP, sp34); - } - if (actor_animationIsAt(this, 0.9f) != 0) - { - func_8028F918(0); - if (jiggyscore_isCollected(JIGGY_26_BGS_TANKTUP) == 0) - { - gcdialog_showDialog(ASSET_C7F_DIALOG_TANKTUP_COMPLETE, 0xF, this->position, this->marker, func_8038F5E4, 0); - } - else - { - func_8038F5E4(this->marker, ASSET_C7F_DIALOG_TANKTUP_COMPLETE, -1); - } - } - break; + case CH_TANKTUP_STATE_1_UNK: + func_8038F610(this); + player_getPosition(sp48); + if (!this->has_met_before) + { + if ((((ml_vec3f_distance(local->unk18, sp48) < 250.0f) && (ml_vec3f_distance(local->unk18, sp48) > 80.0f)) && (!player_movementGroup())) && (player_getTransformation() == TRANSFORM_1_BANJO)) + { + gcdialog_showDialog(VER_SELECT(ASSET_C7E_DIALOG_TANKTUP_MEET, 0x9C1, 0, 0), 0, 0, 0, 0, 0); + this->has_met_before = TRUE; + } + } + if (local->unk10) + { + subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_2_UNK, 0.0f, -1); + local->unk10 = 0; + sp44 = 0; + if(&sp44); + local->unk14 = 1; + for (; sp44 < 4; sp44++) + { + if (local->unk0[sp44] == 0) + { + local->unk14 = 0; + } + } - } + if ((!this->unk138_23) && (!local->unk14)) + { + if (gcdialog_showDialog(VER_SELECT(ASSET_C80_DIALOG_TANKTUP_HIT, 0x9C3, 0, 0), 0, 0, 0, 0, 0)) + { + this->unk138_23 = 1; + } + } + } + break; -} + case CH_TANKTUP_STATE_2_UNK: + func_8038F610(this); + if (actor_animationIsAt(this, 0.6f) && local->unk14) + { + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + func_8028F94C(2, local->unk18); + sTanktupCameraPushed = 1; + } + if (actor_animationIsAt(this, 0.99f)) + { + if (!local->unk14) + { + subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_1_UNK, 0.0f, -1); + } + else + { + sTanktupPoseCatchUp = 0; // [port] solved for real: keep the presentation + subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_3_UNK, 0.0f, -1); + actor_playAnimationOnce(this); + } + } + break; + case CH_TANKTUP_STATE_3_UNK: + { + f32 pp[3]; + s32 near; + player_getPosition(pp); + near = ml_vec3f_distance(local->unk18, pp) < 700.0f; + if (actor_animationIsAt(this, 0.1f) != 0 && near && !sTanktupPoseCatchUp) + { + timed_setStaticCameraToNode(0.0f, 0xD); + } + if (actor_animationIsAt(this, 0.55f) != 0 && !sTanktupPoseCatchUp) + { + func_8030E624(0x797FF885U); // SFX_85_ROUGH_COUGH + } + if (actor_animationIsAt(this, 0.4f) != 0 && jiggyscore_isSpawned(JIGGY_26_BGS_TANKTUP) == 0) + { + f32 sp34[3]; + vec3fArray_get_vec3f(this->marker->unk44, 6, sp34); + bundle_setYaw(this->yaw); + sp34[1] -= 125.0f; + jiggy_spawn(JIGGY_26_BGS_TANKTUP, sp34); + } + if (actor_animationIsAt(this, 0.9f) != 0) + { + // Anchor: release the freeze/look-at if state 2 took it, independent of the proximity check below. + if (sTanktupCameraPushed) + { + func_8028F918(0); + sTanktupCameraPushed = 0; + } + if (near) + { + if (jiggyscore_isCollected(JIGGY_26_BGS_TANKTUP) == 0) + { + gcdialog_showDialog(VER_SELECT(ASSET_C7F_DIALOG_TANKTUP_COMPLETE, 0x9C2, 0, 0), 0xF, this->position, this->marker, func_8038F5E4, 0); + } + else + { + func_8038F5E4(this->marker, VER_SELECT(ASSET_C7F_DIALOG_TANKTUP_COMPLETE, 0x9C2, 0, 0), -1); + } + } + } + break; + } + } +} diff --git a/src/BGS/ch/tanktup_legs.c b/src/BGS/ch/tanktuplegs.c similarity index 75% rename from src/BGS/ch/tanktup_legs.c rename to src/BGS/ch/tanktuplegs.c index b63be8fe1..7ca9610ad 100644 --- a/src/BGS/ch/tanktup_legs.c +++ b/src/BGS/ch/tanktuplegs.c @@ -1,8 +1,9 @@ -// BanjoDecomp: code_9750.c +// BanjoDecomp: BGS/ch/tanktuplegs.c #include #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" void timed_exitStaticCamera(f32); void func_8028E668(f32[3], f32, f32, f32); @@ -60,7 +61,7 @@ ActorInfo gChTanktupLegBackRight = {MARKER_6D_TANKTUP_LEG, ACTOR_EC_TANKTUP_LEG_ }; /* .code */ -void func_8038FB40(ActorMarker *this, s32 arg1){ +void chTanktupLeg_retractLeg(ActorMarker *this, s32 arg1){ Actor * thisActor; thisActor = marker_getActor(this); @@ -69,25 +70,31 @@ void func_8038FB40(ActorMarker *this, s32 arg1){ FUNC_8030E624(SFX_A_BANJO_LANDING_05, 0.8f, 32750); } -void BGS_func_8038FB84(ActorMarker *this, ActorMarker *other_marker){ +void chTanktupLeg_despawn(ActorMarker *this, ActorMarker *other_marker){ Actor *thisActor; thisActor = marker_getActor(this); sfx_playFadeShorthandDefault( SFX_87_TANKTUP_OOOHW, 1.0f, 32750, thisActor->position, 1000, 3000); - timedFunc_set_2(0.65f, (GenFunction_2) func_8038FB40, (uintptr_t) this, (uintptr_t) other_marker); + timedFunc_set_2(0.65f, (GenFunction_2) chTanktupLeg_retractLeg, (uintptr_t) this, (uintptr_t) other_marker); func_8038F51C(thisActor); this->collidable = false; + port_puzzleStep_orBits(ANCHOR_PUZZLE_BGS_TANKTUP, 1 << thisActor->unk10_12); } void chTanktupLeg_update(Actor *this){ if(!this->initialized){ this->initialized = true; this->marker->propPtr->unk8_3 = 1; - marker_setCollisionScripts(this->marker, NULL, NULL, BGS_func_8038FB84); + marker_setCollisionScripts(this->marker, NULL, NULL, chTanktupLeg_despawn); + } + // Anchor: teammate hit this leg remotely — replay the pull-in. + if(this->state == 1 && this->marker->collidable + && (port_puzzleStep_get(ANCHOR_PUZZLE_BGS_TANKTUP) & (1 << this->unk10_12))){ + chTanktupLeg_despawn(this->marker, NULL); } if(this->state == 2){ if(anctrl_isAt(this->anctrl, 0.65f)){ - gcsfx_playAtSampleRate(SFX_7C_CHEBOOF); + gcsfx_play(SFX_7C_CHEBOOF); } if(anctrl_isStopped(this->anctrl)){ marker_despawn(this->marker); diff --git a/src/BGS/ch/tiptup.c b/src/BGS/ch/tiptup.c index c93e4112c..cf2bd5323 100644 --- a/src/BGS/ch/tiptup.c +++ b/src/BGS/ch/tiptup.c @@ -1,4 +1,4 @@ -// BanjoDecomp: ch/code_2270.c +// BanjoDecomp: BGS/ch/tiptup.c #include #include "functions.h" #include "variables.h" @@ -12,34 +12,72 @@ typedef struct{ typedef struct ch_bgs_2270_s{ u32 unk0; - bk_vector(Struct_BGS_2270_0s) *unk4; + bk_vector(Struct_BGS_2270_0s) *unk4; // vector? u8 unk8; u8 unk9; - u8 unkA; + u8 round; u8 unkB; - f32 unkC; + f32 animTimer; } ActorLocal_Tiptup; void chTiptup_update(Actor *this); Actor *actor_draw(ActorMarker *, Gfx **, Mtx **, Vtx **); -ActorInfo chTiptup = { +ActorInfo gChTiptup = { MARKER_19A_TIPTUP, ACTOR_27A_TIPTUP, ASSET_3F8_MODEL_TIPTUP, 0, NULL, chTiptup_update, NULL, actor_draw, 0, 0, 2.5f, 0 }; -s16 D_80390854[] = {0, ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT, ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT, ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT}; //see again texts -s16 D_8039085C[] = {0, ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE, ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE, ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE}; //success texts -u8 D_80390864[] = {3, 3, 5, 7}; //chchoirgame_sequence_length -f32 D_80390868[3] = {0.0f, 100.0f, -1020.0f}; //chchoirgame_jiggy_position -void BGS_func_80388660(ActorMarker *this){ - chTiptup_setState(marker_getActor(this), 6); +s16 chTiptupRepeatDialogs[] = { + 0, // [port] decomp uses NULL; these are asset ids, not pointers + VER_SELECT(ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT, 0x9BB, 0, 0), + VER_SELECT(ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT, 0x9BD, 0, 0), + VER_SELECT(ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT, 0x9BF, 0, 0) +}; + +s16 chTiptupSuccessDialogs[] = { + 0, // [port] decomp uses NULL; these are asset ids, not pointers + VER_SELECT(ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE, 0x9BA, 0, 0), + VER_SELECT(ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE, 0x9BC, 0, 0), + VER_SELECT(ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE, 0x9BE, 0, 0) +}; + +u8 chTiptupSequenceLength[] = {3, 3, 5, 7}; +f32 chTiptupJiggyPosition[3] = {0.0f, 100.0f, -1020.0f}; + +enum chTiptupState { + CH_TIPTUP_STATE_1_IDLE = 1, + CH_TIPTUP_STATE_2_INSTRUCTIONS_DIALOG, + CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE, + CH_TIPTUP_STATE_4_AWAIT_SEQUENCE_COMPLETION, + CH_TIPTUP_STATE_5_WIN_MINIGAME, + CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG +}; + +enum chTiptupSpecificFlag { + CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY, + CH_TIPTUP_SPECIFIC_FLAG_1_TIPTUP_MISS +}; + +enum TiptupRound { + TIPTUP_ROUND_1, + TIPTUP_ROUND_2, + TIPTUP_ROUND_3, + TIPTUP_ROUND_FF +}; + +#define TIPTUP_TIMER 30 // Seconds +#define FIRST_CHOIR_MEMBER 1 +#define LAST_CHOIR_MEMBER 7 + +void chTiptup_minigameComplete(ActorMarker *this){ + chTiptup_setState(marker_getActor(this), CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG); } void chTiptup_jiggySpawn(void){ - jiggy_spawn(JIGGY_27_BGS_TIPTUP, D_80390868); //spawn jiggy after minigame + jiggy_spawn(JIGGY_27_BGS_TIPTUP, chTiptupJiggyPosition); } void chTiptup_activatePattern(ActorMarker *this, s32 arg1){ @@ -61,8 +99,8 @@ void chTiptup_activateTimer(ActorMarker *this){ thisActor = marker_getActor(this); item_set(ITEM_6_HOURGLASS, 1); - item_set(ITEM_0_HOURGLASS_TIMER, 30*60-1); - chTiptup_setState(thisActor, 5); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(TIPTUP_TIMER, 25, 0, 0) * 60 - 1); + chTiptup_setState(thisActor, CH_TIPTUP_STATE_5_WIN_MINIGAME); } void chTiptup_sfxCorrectHit(void){ @@ -78,21 +116,21 @@ void chTiptup_textEvent(ActorMarker *this, enum asset_e text_id, s32 arg2){ thisActor = marker_getActor(this); switch(text_id){ - case ASSET_C72_DIALOG_TIPTUP_MEET_1: - case ASSET_C74_DIALOG_TIPTUP_MEET_3: - chTiptup_setState(thisActor, 3); + case VER_SELECT(ASSET_C72_DIALOG_TIPTUP_MEET_1, 0x9B5, 0, 0): + case VER_SELECT(ASSET_C74_DIALOG_TIPTUP_MEET_3, 0x9B7, 0, 0): + chTiptup_setState(thisActor, CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE); break; - case ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT: - case ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT: - case ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT: - chTiptup_setState(thisActor, 4); + case VER_SELECT(ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT, 0x9BB, 0, 0): + case VER_SELECT(ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT, 0x9BD, 0, 0): + case VER_SELECT(ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT, 0x9BF, 0, 0): + chTiptup_setState(thisActor, CH_TIPTUP_STATE_4_AWAIT_SEQUENCE_COMPLETION); break; - case ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE: - case ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE: + case VER_SELECT(ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE, 0x9BA, 0, 0): + case VER_SELECT(ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE, 0x9BC, 0, 0): func_80324E38(0.0f, 0); - chTiptup_setState(thisActor, 3); + chTiptup_setState(thisActor, CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE); break; - case ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE: + case VER_SELECT(ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE, 0x9BE, 0, 0): timedFunc_set_0(0.0f, chTiptup_jiggySpawn); timed_exitStaticCamera(2.5f); func_80324E38(2.5f, 0); @@ -113,113 +151,164 @@ void chTiptup_correctHit(ActorMarker *this){ return; if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - item_set(ITEM_6_HOURGLASS,0); - volatileFlag_set(VOLATILE_FLAG_3,0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON,1); + item_set(ITEM_6_HOURGLASS, 0); + volatileFlag_set(VOLATILE_FLAG_3, 0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 1); } else{ - BGS_func_80388660(thisActor->marker); + chTiptup_minigameComplete(thisActor->marker); } } -void chTiptup_setState(Actor *this, s32 arg1){ +void chTiptup_setState(Actor *this, s32 next_state){ ActorLocal_Tiptup *unqPtr; f32 sp54; - - f32 tmpf; - s32 i; + f32 sequence_time; + s32 current_member_index; s32 j; s32 prev_member; s32 rand2; Struct_BGS_2270_0s *s1; unqPtr = (ActorLocal_Tiptup *)&this->local; - this->state = arg1; - unqPtr->unkC = 0.0f; - if(this->state == 1){ + this->state = next_state; + unqPtr->animTimer = 0.0f; + if(this->state == CH_TIPTUP_STATE_1_IDLE){ skeletalAnim_set(this->unk148, ASSET_12B_ANIM_TIPTUP_IDLE, 1.0f, 9.0f); - unqPtr->unkC = randf2(5.0f, 15.0f); + unqPtr->animTimer = randf2(5.0f, 15.0f); } - if(this->state == 2){ + if(this->state == CH_TIPTUP_STATE_2_INSTRUCTIONS_DIALOG){ skeletalAnim_set(this->unk148, ASSET_12B_ANIM_TIPTUP_IDLE, 1.0f, 9.0f); - unqPtr->unkC = randf2(5.0f, 15.0f); + unqPtr->animTimer = randf2(5.0f, 15.0f); if (!this->has_met_before) { - this->has_met_before = true; - - if (unqPtr->unkA == 0) { - gcdialog_showDialog(ASSET_C72_DIALOG_TIPTUP_MEET_1, 0xe, this->position, this->marker, chTiptup_textEvent, 0); + this->has_met_before = TRUE; + + if (unqPtr->round == TIPTUP_ROUND_1) { + gcdialog_showDialog( + VER_SELECT(ASSET_C72_DIALOG_TIPTUP_MEET_1, 0x9B5, 0, 0), + 0xe, + this->position, + this->marker, + chTiptup_textEvent, + 0); } else { - gcdialog_showDialog(ASSET_C74_DIALOG_TIPTUP_MEET_3, 0xf, this->position, this->marker, chTiptup_textEvent, 0); + gcdialog_showDialog( + VER_SELECT(ASSET_C74_DIALOG_TIPTUP_MEET_3, 0x9B7, 0, 0), + 0xf, + this->position, + this->marker, + chTiptup_textEvent, + 0); } } else { - gcdialog_showDialog(D_80390854[unqPtr->unkA], 0xf, this->position, this->marker, chTiptup_textEvent, 0); + gcdialog_showDialog( + chTiptupRepeatDialogs[unqPtr->round], + 0xf, + this->position, + this->marker, + chTiptup_textEvent, + 0); } } - if(this->state == 3){ + if(this->state == CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE){ unqPtr->unk0 = 0; bk_vector_clear(unqPtr->unk4); func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.5f, 0); - tmpf = 0.5f; - i = 0; + sequence_time = 0.5f; + current_member_index = 0; prev_member = 0; - for(; i < D_80390864[unqPtr->unkA]; i++){ - tmpf += randf2(1.0f, 1.5f); - while((rand2 = randi2(1,7)) == prev_member); - timedFunc_set_2(tmpf, (GenFunction_2) chTiptup_activatePattern, (uintptr_t)this->marker, rand2); - timedFunc_set_2(tmpf + 0.1, (GenFunction_2)chTiptup_activatePattern, (uintptr_t)this->marker, 0); + for(; current_member_index < chTiptupSequenceLength[unqPtr->round]; current_member_index++){ + sequence_time += randf2(1.0f, 1.5f); + // while loop prevents same choir member in a row + while((rand2 = randi2(FIRST_CHOIR_MEMBER, LAST_CHOIR_MEMBER)) == prev_member); + timedFunc_set_2( + sequence_time, + (GenFunction_2) chTiptup_activatePattern, + reinterpret_cast(uintptr_t, this->marker), + rand2); + timedFunc_set_2( + sequence_time + 0.1, + (GenFunction_2)chTiptup_activatePattern, + reinterpret_cast(uintptr_t, this->marker), + 0); prev_member = rand2; }//L80388B7C - timed_exitStaticCamera(tmpf += 2.5); - if(!unqPtr->unkA && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - func_80324DBC(tmpf + 0.5, ASSET_C73_DIALOG_TIPTUP_MEET_2, 0xe, this->position, this->marker, chTiptup_textEvent, 0); - unqPtr->unkA = 1; + timed_exitStaticCamera(sequence_time += 2.5); + if(!unqPtr->round && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ + func_80324DBC( + sequence_time + 0.5, + VER_SELECT(ASSET_C73_DIALOG_TIPTUP_MEET_2, 0x9B6, 0, 0), + 0xe, + this->position, + this->marker, + chTiptup_textEvent, + 0); + unqPtr->round = TIPTUP_ROUND_2; } - func_80324E38(sp54 = tmpf + 0.6, 0); + func_80324E38(sp54 = sequence_time + 0.6, 0); if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - timedFunc_set_1(sp54, (GenFunction_1)chTiptup_activateTimer, (uintptr_t)this->marker); + timedFunc_set_1( + sp54, + (GenFunction_1)chTiptup_activateTimer, + reinterpret_cast(uintptr_t, this->marker)); }else{ - this->state = 0x05; + this->state = CH_TIPTUP_STATE_5_WIN_MINIGAME; } - mapSpecificFlags_set(0, 0); + mapSpecificFlags_set(CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY, 0); }//L80388C6C - if(this->state == 4){ + if(this->state == CH_TIPTUP_STATE_4_AWAIT_SEQUENCE_COMPLETION){ unqPtr->unk0 = 0; func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.5f, 0); - tmpf = 0.5f; + sequence_time = 0.5f; for(j = 0; j < bk_vector_size(unqPtr->unk4); j++){ s1 = (Struct_BGS_2270_0s *)bk_vector_at(unqPtr->unk4,j); - tmpf += randf2(1.0f, 1.5f); - timedFunc_set_2(tmpf, (GenFunction_2)chTiptup_activatePattern, (uintptr_t)this->marker, s1->unk0); - timedFunc_set_2(tmpf + 0.1, (GenFunction_2)chTiptup_activatePattern, (uintptr_t)this->marker, 0); + sequence_time += randf2(1.0f, 1.5f); + timedFunc_set_2( + sequence_time, + (GenFunction_2)chTiptup_activatePattern, + reinterpret_cast(uintptr_t, this->marker), + s1->unk0); + timedFunc_set_2( + sequence_time + 0.1, + (GenFunction_2)chTiptup_activatePattern, + reinterpret_cast(uintptr_t, this->marker), + 0); } - timed_exitStaticCamera(tmpf += 2.5); - func_80324E38(tmpf + 0.6,0); + timed_exitStaticCamera(sequence_time += 2.5); + func_80324E38(sequence_time + 0.6, 0); bk_vector_clear(unqPtr->unk4); - this->state = 0x05; + this->state = CH_TIPTUP_STATE_5_WIN_MINIGAME; }//L80388D8C - if(this->state == 6){ - if(unqPtr->unkA == 3){ + if(this->state == CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG){ + if(unqPtr->round == TIPTUP_ROUND_FF){ coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); } func_80324E38(0.5f, 3); timed_setStaticCameraToNode(1.5f, 1); - func_80324DBC(2.0f, D_8039085C[unqPtr->unkA++], 0xF, this->position, this->marker, chTiptup_textEvent, 0); + func_80324DBC( + 2.0f, + chTiptupSuccessDialogs[unqPtr->round++], + 0xF, + this->position, + this->marker, + chTiptup_textEvent, + 0); } } -void func_80388E44(ActorMarker *arg0, ActorMarker *arg1){ - func_8028F428(2,arg0); +void chTiptup_bouncePlayerOff(ActorMarker *arg0, ActorMarker *arg1){ + func_8028F428(2, arg0); } -s32 func_80388E70(ActorMarker *this){ +s32 chTiptup_getUnkB(ActorMarker *this){ Actor *ptr; ActorLocal_Tiptup *local; @@ -236,27 +325,34 @@ void chTiptup_choirHitReaction(ActorMarker *this, s32 arg1){ thisActor = marker_getActor(this); unqPtr = (ActorLocal_Tiptup *)&thisActor->local; if((s32)unqPtr->unk0 >= (s32) bk_vector_size(unqPtr->unk4)){ - if(!mapSpecificFlags_get(0) && gcdialog_showDialog(ASSET_C76_DIALOG_CHOIR_MEMBER_HIT_AFTER_JIGGY, 0, 0, 0, 0, 0)) - mapSpecificFlags_set(0,1); + if(!mapSpecificFlags_get(CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY) + && gcdialog_showDialog(VER_SELECT(ASSET_C76_DIALOG_CHOIR_MEMBER_HIT_AFTER_JIGGY, 0x9B9, 0, 0), 0, 0, 0, 0, 0)) + { + mapSpecificFlags_set(CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY, 1); + } }else{ tmp = (Struct_BGS_2270_0s *)bk_vector_at(unqPtr->unk4, unqPtr->unk0); if(arg1 == tmp->unk0){ - timedFunc_set_1(0.5f, (GenFunction_1)chTiptup_correctHit, (uintptr_t)thisActor->marker); + timedFunc_set_1(0.5f, (GenFunction_1)chTiptup_correctHit, reinterpret_cast(uintptr_t, thisActor->marker)); } else{ func_8028F55C(1, thisActor->marker); timedFunc_set_0(0.5f, chTiptup_sfxIncorrectHit); - if(!mapSpecificFlags_get(1) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && gcdialog_showDialog(ASSET_C75_DIALOG_TIPTUP_MISS, 0, NULL, NULL, NULL, NULL)) - mapSpecificFlags_set(1,true); + if(!mapSpecificFlags_get(CH_TIPTUP_SPECIFIC_FLAG_1_TIPTUP_MISS) + && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) + && gcdialog_showDialog(VER_SELECT(ASSET_C75_DIALOG_TIPTUP_MISS, 0x9B8, 0, 0), 0, NULL, NULL, NULL, NULL)) + { + mapSpecificFlags_set(CH_TIPTUP_SPECIFIC_FLAG_1_TIPTUP_MISS, TRUE); + } } } } -void func_80388FC0(Actor *this){ +void chTiptup_setMinigameProgress(Actor *this){ ActorLocal_Tiptup *local; local = (ActorLocal_Tiptup *)&this->local; - fileProgressFlag_setN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, local->unkA, 2); + fileProgressFlag_setN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, local->round, 2); bk_vector_free(local->unk4); } @@ -270,80 +366,88 @@ void func_80388FFC(ActorMarker *this, s32 *arg1, f32* arg2){ *arg2 = 0.52 + (f64)localPtr->unk9 * 0.12; localPtr->unk9++; *arg1 = localPtr->unk9; - } void chTiptup_update(Actor *this){ f32 player_position[3]; ActorLocal_Tiptup *unqPtr; - f32 sp3C; - f32 sp38; - f32 sp34; - f32 sp30; + f32 time_delta; + f32 sp38; // unused + f32 sp34; // unused + f32 sp30; // something about yaw unqPtr = (ActorLocal_Tiptup *)&this->local; - sp3C = time_getDelta(); + time_delta = time_getDelta(); if(!this->volatile_initialized){ - this->volatile_initialized = true; - this->marker->actorFreeFunc = func_80388FC0; - marker_setCollisionScripts(this->marker, func_80388E44, NULL, NULL); + this->volatile_initialized = TRUE; + this->marker->actorFreeFunc = chTiptup_setMinigameProgress; + marker_setCollisionScripts(this->marker, chTiptup_bouncePlayerOff, NULL, NULL); unqPtr->unk0 = 0; unqPtr->unk4 = bk_vector_new(sizeof(Struct_BGS_2270_0s), 8); unqPtr->unk8 = 0; unqPtr->unk9 = 0; - unqPtr->unkA = fileProgressFlag_getN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, 2); + unqPtr->round = fileProgressFlag_getN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, 2); unqPtr->unkB = 0; - unqPtr->unkC = 0.0f; + unqPtr->animTimer = 0.0f; if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - unqPtr->unkA = 3; + unqPtr->round = TIPTUP_ROUND_FF; this->position_y = this->position_y - 300.0f; } - chTiptup_setState(this, 1); - if(jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && !volatileFlag_get(VOLATILE_FLAG_1)) + chTiptup_setState(this, CH_TIPTUP_STATE_1_IDLE); + if(jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP) + && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) + && !volatileFlag_get(VOLATILE_FLAG_1)) + { marker_despawn(this->marker); + } } else{ player_getPosition(player_position); - if(skeletalAnim_getAnimId(this->unk148) == ASSET_12C_ANIM_TIPTUP_TAPPING && skeletalAnim_getLoopCount(this->unk148) > 0){ + if(skeletalAnim_getAnimId(this->unk148) == ASSET_12C_ANIM_TIPTUP_TAPPING + && skeletalAnim_getLoopCount(this->unk148) > 0) + { skeletalAnim_set(this->unk148, ASSET_12B_ANIM_TIPTUP_IDLE, 1.0f, 9.0f); - unqPtr->unkC = randf2(5.0f, 15.0f); + unqPtr->animTimer = randf2(5.0f, 15.0f); } - if(ml_timer_update(&unqPtr->unkC, sp3C)){ + if(ml_timer_update(&unqPtr->animTimer, time_delta)){ skeletalAnim_set(this->unk148, ASSET_12C_ANIM_TIPTUP_TAPPING, 1.0f, 4.0f); } func_80258A4C(this->position, this->yaw - 90.0f, player_position, &sp38, &sp34, &sp30); - this->yaw = this->yaw + 5.0f*sp30; - if(this->state == 1){ + this->yaw = this->yaw + 5.0f * sp30; + if(this->state == CH_TIPTUP_STATE_1_IDLE){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(volatileFlag_get(VOLATILE_FLAG_3)){ - func_80324E38(0.0f,0); - chTiptup_setState(this, 3); + func_80324E38(0.0f, 0); + chTiptup_setState(this, CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE); } } else{ - if(ml_vec3f_distance(this->position, player_position) < 300.0f && player_getTransformation() == TRANSFORM_1_BANJO && !jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP)){ - chTiptup_setState(this, 2); + if(ml_vec3f_distance(this->position, player_position) < 300.0f + && player_getTransformation() == TRANSFORM_1_BANJO + && !jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP)) + { + chTiptup_setState(this, CH_TIPTUP_STATE_2_INSTRUCTIONS_DIALOG); } } } - if(this->state == 5){ + if(this->state == CH_TIPTUP_STATE_5_WIN_MINIGAME){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(item_empty(ITEM_0_HOURGLASS_TIMER)){ - item_set(ITEM_6_HOURGLASS,1); - volatileFlag_set(VOLATILE_FLAG_3,0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON,0); + item_set(ITEM_6_HOURGLASS, 1); + volatileFlag_set(VOLATILE_FLAG_3, 0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); } } //L80389370 else{ if(ml_vec3f_distance(this->position, player_position) >= 300.0f) - chTiptup_setState(this, 1); + chTiptup_setState(this, CH_TIPTUP_STATE_1_IDLE); } }//L803893A0 - if(this->state == 6){ + if(this->state == CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG){ if(ml_vec3f_distance(this->position, player_position) < 300.0f && !unqPtr->unk8){ unqPtr->unk8 = 1; - gcdialog_showDialog(ASSET_C7D_DIALOG_TIPTUP_MEET_AFTER_JIGGY, 4, 0, 0, 0, 0); + gcdialog_showDialog(VER_SELECT(ASSET_C7D_DIALOG_TIPTUP_MEET_AFTER_JIGGY, 0x9C0, 0, 0), 4, 0, 0, 0, 0); } } } diff --git a/src/BGS/ch/yellowflibbit.c b/src/BGS/ch/yellowflibbit.c index d167e5f95..bc30286b9 100644 --- a/src/BGS/ch/yellowflibbit.c +++ b/src/BGS/ch/yellowflibbit.c @@ -360,6 +360,7 @@ void gChYellowFlibbit_update(Actor *this) { local->unk10[0] = (s16) (s32) this->position[0]; local->unk10[1] = (s16) (s32) this->position[1]; local->unk10[2] = (s16) (s32) this->position[2]; + this->state = 0; // [port] Zero-init, which vanilla did not need because of draw distance gChYellowFlibbit_setState(this, 1); if (jiggyscore_isSpawned(JIGGY_24_BGS_FLIBBITS) != 0) { marker_despawn(this->marker); diff --git a/src/BGS/ch/yumblie.c b/src/BGS/ch/yumblie.c index 6c37db606..7b2e90594 100644 --- a/src/BGS/ch/yumblie.c +++ b/src/BGS/ch/yumblie.c @@ -45,7 +45,7 @@ bool func_8038B160(Actor *this){ s32 temp_v0; local = (ActorLocal_Yumblie *)&this->local; - temp_v0 = func_8038A9E0(local->game_marker); + temp_v0 = chMrVileMinigame_getDialogIndex(local->game_marker); if ((temp_v0 == 1) || (temp_v0 == 4)) { return false; @@ -70,7 +70,7 @@ void chyumblie_set_state(Actor* this, enum chyumblie_state_e next_state){ if(next_state == 2){ this->yaw = randf2(0.0f, 360.0f); s0->unk4 = (sNetForcedPieceType >= 0) ? (u8)sNetForcedPieceType : func_8038B160(this); - chvilegame_new_piece(s0->game_marker, this->marker, this->position, s0->unk4); + chMrVileMinigame_newPiece(s0->game_marker, this->marker, this->position, s0->unk4); skeletalAnim_set(this->unk148, (s0->unk4)? ASSET_128_ANIM_GRUMBLIE_APPEAR : ASSET_125_ANIM_YUMBLIE_APPEAR, 0.0f, 1.5f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } @@ -198,7 +198,7 @@ void chyumblie_update(Actor *this){ sp50 = skeletalAnim_getProgress(this->unk148); if(this->state == YUMBLIE_STATE_1_UNDER_GROUND){ if(ml_timer_update(&s0->unk8, sp4C)){ - if(EventSystem_Should(VB_VILE_YUMBLIE_EMERGE, mapSpecificFlags_get(6) && (12 > chvilegame_get_piece_count(s0->game_marker)))){ + if(EventSystem_Should(VB_VILE_YUMBLIE_EMERGE, mapSpecificFlags_get(6) && (12 > chMrVileMinigame_getPieceCount(s0->game_marker)))){ chyumblie_set_state(this, YUMBLIE_STATE_2_APPEAR); } else{ diff --git a/src/BGS/checksums.c b/src/BGS/checksums.c new file mode 100644 index 000000000..d802484b3 --- /dev/null +++ b/src/BGS/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: BGS/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsBGS; diff --git a/src/BGS/crc.c b/src/BGS/crc.c index 96786bf61..86979482f 100644 --- a/src/BGS/crc.c +++ b/src/BGS/crc.c @@ -1,7 +1,8 @@ // BanjoDecomp: crc.c #include +#include "checksums.h" +#include "version.h" -//TODO Implement CRC calculation in Makefile(?) -u32 D_80390B20 = 0x00282B61; //BGS.code CRC1 -u32 D_80390B24 = 0xccdaeea0; //BGS.code CRC2 -u32 D_80390B28 = 0x0002DE6B; //BGS.data CRC1 (with this value = 0) +s32 D_80390B20 = VER_SELECT(0x00282B61, 0x002871C5, 0, 0); // BGS_TEXT_CRC1 +s32 D_80390B24 = VER_SELECT(0xccdaeea0, 0xEDE9F826, 0, 0); // BGS_TEXT_CRC2 +s32 D_80390B28 = VER_SELECT(0x0002DE6B, 0x0002EA91, 0, 0); // BGS_DATA_CRC1 diff --git a/src/BGS/minigame_vile.c b/src/BGS/mrvileminigame.c similarity index 58% rename from src/BGS/minigame_vile.c rename to src/BGS/mrvileminigame.c index 707058982..7b68b78d4 100644 --- a/src/BGS/minigame_vile.c +++ b/src/BGS/mrvileminigame.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_3420.c +// BanjoDecomp: BGS/mrvileminigame.c #include #include "functions.h" #include "bk_math.h" @@ -6,7 +6,7 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/Network/Anchor/VileSync.h" -extern f32 *chVile_getPostion(ActorMarker *); +extern f32 *chMrVile_getPostion(ActorMarker *); extern void bundle_setRandomVelocity(f32); extern void func_802FDCB8(s32); @@ -21,95 +21,122 @@ typedef struct { // u8 pad1[3]; bk_vector(struct vilegame_piece) *game_pieces; BKModelBin *grumblie_model_bin; - u8 unkC; - u8 unkD; + u8 dialogIndex; + u8 mode; u8 player_score; u8 vile_score; f32 type_change_timer; ActorMarker *vile_marker; -}ActorLocal_BGS_3420; +}chMrVileMinigameActor; -void func_8038A068(Actor *this, s32 next_state); -void chvilegame_update(Actor *this); +void chMrVileMinigame_setState(Actor *this, s32 next_state); +void chMrVileMinigame_update(Actor *this); /* .data */ ActorInfo D_80390960 = { MARKER_C6_VILE_GAME_CTRL, ACTOR_138_VILE_GAME_CTRL, 0, 0, NULL, - chvilegame_update, NULL, func_80325340, + chMrVileMinigame_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; // Vile Wins -enum asset_e D_80390984[] = { +enum asset_e chMrVileMinigamePlayerLosesDialog[] = { 0, - ASSET_C66_DIALOG_MR_VILE_WINS_ROUND_1, - ASSET_C68_DIALOG_MR_VILE_WINS_ROUND_2, - ASSET_C6A_DIALOG_MR_VILE_WINS_ROUND_3, - ASSET_C92_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_2, - ASSET_C93_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_3, - ASSET_C94_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_4, + VER_SELECT(ASSET_C66_DIALOG_MR_VILE_WINS_ROUND_1, 0x9A9, 0, 0), + VER_SELECT(ASSET_C68_DIALOG_MR_VILE_WINS_ROUND_2, 0x9AB, 0, 0), + VER_SELECT(ASSET_C6A_DIALOG_MR_VILE_WINS_ROUND_3, 0x9AD, 0, 0), + VER_SELECT(ASSET_C92_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_2, 0x9D5, 0, 0), + VER_SELECT(ASSET_C93_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_3, 0x9D6, 0, 0), + VER_SELECT(ASSET_C94_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_4, 0x9D7, 0, 0), 0 }; // Player Wins -enum asset_e D_803909A4[] = { +enum asset_e chMrVileMinigamePlayerWinsDialog[] = { 0, - ASSET_C67_DIALOG_MR_VILE_ROUND_2_START, - ASSET_C69_DIALOG_MR_VILE_ROUND_3_START, + VER_SELECT(ASSET_C67_DIALOG_MR_VILE_ROUND_2_START, 0x9AA, 0, 0), + VER_SELECT(ASSET_C69_DIALOG_MR_VILE_ROUND_3_START, 0x9AC, 0, 0), 0, - ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, - ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, - ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3 + VER_SELECT(ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, 0x9D8, 0, 0), + VER_SELECT(ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, 0x9D9, 0, 0), + VER_SELECT(ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3, 0x9DA, 0, 0) }; // Player Wins Rematch -enum asset_e D_803909C0[] = { +enum asset_e chMrVileMinigamePlayerWinsRematchDialog[] = { 0, - ASSET_C6E_DIALOG_MR_VILE_LOSE_ROUND_2_REMATCH, - ASSET_C6F_DIALOG_MR_VILE_LOSE_ROUND_3_REMATCH, + VER_SELECT(ASSET_C6E_DIALOG_MR_VILE_LOSE_ROUND_2_REMATCH, 0x9B1, 0, 0), + VER_SELECT(ASSET_C6F_DIALOG_MR_VILE_LOSE_ROUND_3_REMATCH, 0x9B2, 0, 0), 0, - ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, - ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, - ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3 + VER_SELECT(ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, 0x9D8, 0, 0), + VER_SELECT(ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, 0x9D9, 0, 0), + VER_SELECT(ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3, 0x9DA, 0, 0) }; -// Player Declines -enum asset_e D_803909DC[] = { - ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, - ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, - ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, - ASSET_C8F_DIALOG_MR_VILE_PLAYER_DECLINES_EXTRA_CHALLENGE, +enum asset_e chMrVileMinigamePlayerDeclinesDialog[] = { + VER_SELECT(ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, 0x9A8, 0, 0), + VER_SELECT(ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, 0x9A8, 0, 0), + VER_SELECT(ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, 0x9A8, 0, 0), + VER_SELECT(ASSET_C8F_DIALOG_MR_VILE_PLAYER_DECLINES_EXTRA_CHALLENGE, 0x9D2, 0, 0), 0, 0, 0 }; -// Round 1 Regular & Extra Challenge -enum asset_e BGS_D_803909F8[] = { - ASSET_C64_DIALOG_MR_VILE_ROUND_1_START, +enum asset_e chMrVileMinigameRound1AndChallengeDialog[] = { + VER_SELECT(ASSET_C64_DIALOG_MR_VILE_ROUND_1_START, 0x9A7, 0, 0), 0, 0, - ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, + VER_SELECT(ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0x9D1, 0, 0), 0, 0, 0, 0 }; -enum asset_e D_80390A18[] = { - ASSET_C6D_DIALOG_MR_VILE_LOSE_ROUND_1_REMATCH, - ASSET_C70_DIALOG_MR_VILE_WIN_ROUND_2_REMATCH, - ASSET_C71_DIALOG_MR_VILE_WIN_ROUND_3_REMATCH, - ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, +enum asset_e chMrVileMinigameRematchDialog[] = { + VER_SELECT(ASSET_C6D_DIALOG_MR_VILE_LOSE_ROUND_1_REMATCH, 0x9B0, 0, 0), + VER_SELECT(ASSET_C70_DIALOG_MR_VILE_WIN_ROUND_2_REMATCH, 0x9B3, 0, 0), + VER_SELECT(ASSET_C71_DIALOG_MR_VILE_WIN_ROUND_3_REMATCH, 0x9B4, 0, 0), + VER_SELECT(ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0x9D1, 0, 0), 0, 0, 0, 0 }; +enum MrVileMinigameState { + MR_VILE_MINIGAME_STATE_0_NO_INIT = 0, + MR_VILE_MINIGAME_STATE_1_IDLE, + MR_VILE_MINIGAME_STATE_2_YES_OR_NO, + MR_VILE_MINIGAME_STATE_3_DECLINE_MINIGAME, + MR_VILE_MINIGAME_STATE_4_ROUND_INTRO_EXPLANATION, + MR_VILE_MINIGAME_STATE_5_PLAYING_MINIGAME, + MR_VILE_MINIGAME_STATE_6_VILE_WINS, + MR_VILE_MINIGAME_STATE_7_ATTACK_PLAYER, + MR_VILE_MINIGAME_STATE_8_PLAYER_WINS, + MR_VILE_MINIGAME_STATE_9_DROP_JIGGY, + MR_VILE_MINIGAME_STATE_A_DROP_EXTRA_LIVES +}; + +enum MrVileMinigameMode { + MR_VILE_MINIGAME_MODE_0_ROUND_1 = 0, + MR_VILE_MINIGAME_MODE_1_ROUND_2, + MR_VILE_MINIGAME_MODE_2_ROUND_3, + MR_VILE_MINIGAME_MODE_3_CHALLENGE_1_AND_FF, + MR_VILE_MINIGAME_MODE_4_CHALLENGE_2, + MR_VILE_MINIGAME_MODE_4_CHALLENGE_3 +}; + +#define MR_VILE_MINIGAME_TIMER VER_SELECT(3600, 3000, 0, 0) +#define TYPE_CHANGE_TIMER_REGULAR 10.0f +#define TYPE_CHANGE_TIMER_FF 5.0f +#define EXTRA_LIFE_SCORE 35 +#define MAX_DISTANCE_FROM_PIECE 65.25 + /* .code */ -bool BGS_func_80389810(f32 arg0[3]) { +bool chMrVileMinigame_didPlayerConsumePiece(f32 arg0[3]) { if (player_movementGroup() != BSGROUP_7_CROC_ATTACK) { return false; } @@ -117,8 +144,8 @@ bool BGS_func_80389810(f32 arg0[3]) { return true; } -void BGS_func_80389850(Actor *this, s32 arg1) { - ActorLocal_BGS_3420 *local; +void chMrVileMinigame_spawnJiggy(Actor *this, s32 arg1) { + chMrVileMinigameActor *local; Actor *vile; f32 sp94[3]; f32 sp88[3]; @@ -126,7 +153,7 @@ void BGS_func_80389850(Actor *this, s32 arg1) { s32 var_s0; s32 var_v0; - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; vile = marker_getActor(local->vile_marker); if (arg1 != 0) { if (LENGTH_VEC3F(this->position) < 800.0f) { @@ -174,120 +201,127 @@ void BGS_func_80389850(Actor *this, s32 arg1) { ncStaticCamera_setPositionAndRotation(sp94, sp88); } -void func_80389B48(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void chMrVileMinigame_vileOffersMinigame(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); if(arg2 == 1){ - func_8038A068(this, 4); + chMrVileMinigame_setState(this, 4); } else{ - func_8038A068(this, 3); + chMrVileMinigame_setState(this, 3); } } -void func_80389B98(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void chMrVileMinigame_setStateIdleAfterDeclined(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); - func_8038A068(this, 1); + chMrVileMinigame_setState(this, 1); } -void func_80389BC8(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void chMrVileMinigame_setStatePlayingMinigame(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); - func_8038A068(this, 5); + chMrVileMinigame_setState(this, 5); } -void func_80389BF8(ActorMarker *marker, enum asset_e text_id, s32 arg2) { +void chMrVileMinigame_vileAttacksPlayer(ActorMarker *marker, enum asset_e text_id, s32 arg2) { Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - local->unkC--; - func_8038A068(this, 7); + local->dialogIndex--; + chMrVileMinigame_setState(this, 7); } -void func_80389C58(ActorMarker *marker) { +void chMrVileMinigame_vileWinsRound(ActorMarker *marker) { Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; - BGS_func_80389850(this, 0); - gcdialog_showDialog(D_80390984[local->unkC], 0xF, chVile_getPostion(local->vile_marker), this->marker, func_80389BF8, NULL); + local = (chMrVileMinigameActor *)&this->local; + chMrVileMinigame_spawnJiggy(this, 0); + gcdialog_showDialog(chMrVileMinigamePlayerLosesDialog[local->dialogIndex], 0xF, chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_vileAttacksPlayer, NULL); } -void BGS_func_80389CD8(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void chMrVileMinigame_startNextRound(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - func_8038A068(this, 5); + chMrVileMinigame_setState(this, 5); } -void func_80389D20(ActorMarker *marker) { +void chMrVileMinigame_playerWinsRound(ActorMarker *marker) { Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; - BGS_func_80389850(this, 0); - if (local->unkC == local->unkD) { - gcdialog_showDialog(D_803909A4[local->unkC], 0xF, chVile_getPostion(local->vile_marker), this->marker, BGS_func_80389CD8, NULL); + local = (chMrVileMinigameActor *)&this->local; + chMrVileMinigame_spawnJiggy(this, 0); + if (local->dialogIndex == local->mode) { + gcdialog_showDialog(chMrVileMinigamePlayerWinsDialog[local->dialogIndex], 0xF, chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_startNextRound, NULL); } else { - gcdialog_showDialog(D_803909C0[local->unkC], 0xF, chVile_getPostion(local->vile_marker), this->marker, BGS_func_80389CD8, NULL); + gcdialog_showDialog(chMrVileMinigamePlayerWinsRematchDialog[local->dialogIndex], 0xF, chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_startNextRound, NULL); } func_80347A14(0); } -void func_80389DF8(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void chMrVileMinigame_setStateIdleAfterDeclinedAfterJiggy(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - func_8038A068(this, 1); + chMrVileMinigame_setState(this, 1); } -void func_80389E40(ActorMarker *marker) { +void chMrVileMinigame_vileDropsJiggy(ActorMarker *marker) { Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; - - BGS_func_80389850(this, 1); - gcdialog_showDialog(0xC6B, 0xF, chVile_getPostion(local->vile_marker), this->marker, func_80389DF8, NULL); + local = (chMrVileMinigameActor *)&this->local; + + chMrVileMinigame_spawnJiggy(this, 1); + gcdialog_showDialog( + VER_SELECT(ASSET_C6B_DIALOG_MR_VILE_PLAYER_WINS, 0x9AE, 0, 0), + 0xF, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_setStateIdleAfterDeclinedAfterJiggy, + NULL + ); } -void func_80389EAC(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void chMrVileMinigame_setStateIdleAfterExtraLives(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - local->unkC = 3; - func_8038A068(this, 1); + local->dialogIndex = 3; + chMrVileMinigame_setState(this, 1); } -void func_80389F08(ActorMarker *marker) { +void chMrVileMinigame_vileDropsExtraLives(ActorMarker *marker) { Actor *vile; Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; s32 i; s32 var_s2; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; - BGS_func_80389850(this, 0); + local = (chMrVileMinigameActor *)&this->local; + chMrVileMinigame_spawnJiggy(this, 0); var_s2 = actorArray_actorCount(ACTOR_49_EXTRA_LIFE); vile = marker_getActor(local->vile_marker); if (var_s2 > 0) { @@ -303,7 +337,14 @@ void func_80389F08(ActorMarker *marker) { item_inc(ITEM_16_LIFE); } } - gcdialog_showDialog(0xC98, 0xF, chVile_getPostion(local->vile_marker), this->marker, func_80389EAC, NULL); + gcdialog_showDialog( + VER_SELECT(ASSET_C98_DIALOG_MR_VILE_GIVES_PRIZE, 0x9DB, 0, 0), + 0xF, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_setStateIdleAfterExtraLives, + NULL + ); } @@ -311,46 +352,85 @@ void func_8038A044(void){ func_8025A58C(-1, 400); } -void func_8038A068(Actor *this, s32 next_state) { - ActorLocal_BGS_3420 *local; +void chMrVileMinigame_setState(Actor *this, s32 next_state) { + chMrVileMinigameActor *local; - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; mapSpecificFlags_set(6, false); if (next_state == 1) { if (local->vile_marker != NULL) { - func_8038C408(local->vile_marker); + chMrVile_setStateIdleWalking(local->vile_marker); } } - if (next_state == 2) { - func_8038C3B0(local->vile_marker); - if (local->unkC == 3) { - if (local->unkD >= 4) { - gcdialog_showDialog(0xC91, 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389B48, NULL); + if (next_state == MR_VILE_MINIGAME_STATE_2_YES_OR_NO) { + chMrVile_setStateTalkToPlayer(local->vile_marker); + if (local->dialogIndex == 3) { + if (local->mode >= MR_VILE_MINIGAME_MODE_4_CHALLENGE_2) { + gcdialog_showDialog( + VER_SELECT(ASSET_C91_DIALOG_MR_VILE_EXTRA_CHALLENGE_REMATCH_2, 0x9D4, 0, 0), + 0xE, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_vileOffersMinigame, + NULL + ); } else { - gcdialog_showDialog((local->unkC == local->unkD) ? 0xC8D : 0xC90, 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389B48, NULL); + gcdialog_showDialog( + (local->dialogIndex == local->mode) ? + VER_SELECT(ASSET_C8D_DIALOG_MR_VILE_EXTRA_CHALLENGE_INTRO, 0x9D0, 0, 0) : + VER_SELECT(ASSET_C90_DIALOG_MR_VILE_EXTRA_CHALLENGE_REMATCH_1, 0x9D3, 0, 0), + 0xE, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_vileOffersMinigame, + NULL + ); } } else { - gcdialog_showDialog((local->unkC == local->unkD) ? 0xC63 : 0xC6C, 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389B48, NULL); + gcdialog_showDialog( + (local->dialogIndex == local->mode) ? + VER_SELECT(ASSET_C63_DIALOG_MR_VILE_INTRO, 0x9A6, 0, 0) : + VER_SELECT(ASSET_C6C_DIALOG_MR_VILE_TRY_AGAIN, 0x9AF, 0, 0), + 0xE, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_vileOffersMinigame, + NULL + ); } } - if (next_state == 3) { - gcdialog_showDialog(D_803909DC[local->unkC], 4, chVile_getPostion(local->vile_marker), this->marker, func_80389B98, NULL); - } - if (next_state == 4) { - if (local->unkC == local->unkD) { - gcdialog_showDialog(BGS_D_803909F8[local->unkC], 0xE | ((BGS_D_803909F8[local->unkC] == 0xC8E) ? 1 : 0) | 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389BC8, NULL); + if (next_state == MR_VILE_MINIGAME_STATE_3_DECLINE_MINIGAME) { + gcdialog_showDialog( + chMrVileMinigamePlayerDeclinesDialog[local->dialogIndex], + 4, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_setStateIdleAfterDeclined, + NULL + ); + } + if (next_state == MR_VILE_MINIGAME_STATE_4_ROUND_INTRO_EXPLANATION) { + if (local->dialogIndex == local->mode) { + gcdialog_showDialog( + chMrVileMinigameRound1AndChallengeDialog[local->dialogIndex], + 0xE | ((chMrVileMinigameRound1AndChallengeDialog[local->dialogIndex] == VER_SELECT(ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0x9D1, 0, 0)) ? 1 : 0) | 0xE, + chMrVile_getPostion(local->vile_marker), + this->marker, + chMrVileMinigame_setStatePlayingMinigame, + NULL + ); } else { - gcdialog_showDialog(D_80390A18[local->unkC], 0xF , chVile_getPostion(local->vile_marker), this->marker, func_80389BC8, NULL); + gcdialog_showDialog(chMrVileMinigameRematchDialog[local->dialogIndex], 0xF , chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_setStatePlayingMinigame, NULL); } func_80347A14(0); } if (next_state == 5) { - local->unkC++; - if (local->unkD < local->unkC) { - local->unkD = local->unkC; + local->dialogIndex++; + if (local->mode < local->dialogIndex) { + local->mode = local->dialogIndex; } - if (local->unkC == 7) { - BGS_func_8038C434(local->vile_marker); + if (local->dialogIndex == 7) { + chMrVile_setStateRunFromPlayer(local->vile_marker); } else { local->current_type = YUMBLIE; local->player_score = 0; @@ -363,69 +443,69 @@ void func_8038A068(Actor *this, s32 next_state) { item_set(ITEM_0_HOURGLASS_TIMER, 3600-1); item_set(ITEM_6_HOURGLASS, true); mapSpecificFlags_set(6, true); - func_8038C3DC(local->vile_marker); + chMrVile_setStatePlayMinigame(local->vile_marker); func_8025A58C(0, 4000); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_55_BGS_MR_VILE, 28000); } } if (this->state == 5) { - if (local->unkC != 7) { + if (local->dialogIndex != 7) { item_set(ITEM_6_HOURGLASS, false); if ((next_state != 6) && (next_state != 8) && (next_state != 9)) { func_8038A044(); } } - BGS_func_8038C460(local->vile_marker); + chMrVile_setInitialIdleStill(local->vile_marker); func_80347A14(1); } if (next_state == 6) { - func_8038C3B0(local->vile_marker); + chMrVile_setStateTalkToPlayer(local->vile_marker); func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3C_MINIGAME_LOSS, 28000); timedFunc_set_0(4.0f, (GenFunction_0)func_8038A044); - timedFunc_set_1(4.0f, (GenFunction_1)func_80389C58, (uintptr_t)this->marker); + timedFunc_set_1(4.0f, (GenFunction_1)chMrVileMinigame_vileWinsRound, (uintptr_t)this->marker); } if (next_state == 8) { - func_8038C3B0(local->vile_marker); + chMrVile_setStateTalkToPlayer(local->vile_marker); func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3B_MINIGAME_VICTORY, 28000); timedFunc_set_0(3.0f, (GenFunction_0)func_8038A044); - timedFunc_set_1(3.0f, (GenFunction_1)func_80389D20, (uintptr_t)this->marker); + timedFunc_set_1(3.0f, (GenFunction_1)chMrVileMinigame_playerWinsRound, (uintptr_t)this->marker); } if (next_state == 9) { - func_8038C3B0(local->vile_marker); + chMrVile_setStateTalkToPlayer(local->vile_marker); func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3B_MINIGAME_VICTORY, 28000); timedFunc_set_0(3.0f, (GenFunction_0)func_8038A044); - timedFunc_set_1(3.0f, (GenFunction_1)func_80389E40, (uintptr_t)this->marker); + timedFunc_set_1(3.0f, (GenFunction_1)chMrVileMinigame_vileDropsJiggy, (uintptr_t)this->marker); } if (next_state == 0xA) { - func_8038C3B0(local->vile_marker); + chMrVile_setStateTalkToPlayer(local->vile_marker); func_80324E38(0.5f, 3); timedFunc_set_2(1.0f, (GenFunction_2) coMusicPlayer_playMusic, COMUSIC_3B_MINIGAME_VICTORY, 28000); - timedFunc_set_1(3.0f, (GenFunction_1) func_80389F08, (uintptr_t)this->marker); + timedFunc_set_1(3.0f, (GenFunction_1) chMrVileMinigame_vileDropsExtraLives, (uintptr_t)this->marker); } if (next_state == 7) { - func_8038C384(local->vile_marker); + chMrVile_setStateAttackPlayer(local->vile_marker); } this->state = next_state; // [port] Anchor: authority claim/release and round lifecycle react to this event CALL_EVENT(OnVileGameStateChange, next_state); } -void chvilegame_player_consume_piece(Actor *this) { - ActorLocal_BGS_3420 *local; +void chMrVileMinigame_playerConsumePiece(Actor *this) { + chMrVileMinigameActor *local; bool is_correct_type; f32 sp44[3]; struct vilegame_piece *begin; struct vilegame_piece *end; struct vilegame_piece *i_ptr; - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; begin = (struct vilegame_piece *)bk_vector_getBegin(local->game_pieces); end = (struct vilegame_piece *) bk_vector_getEnd(local->game_pieces); - if ((end != begin) && BGS_func_80389810(sp44)){ + if ((end != begin) && chMrVileMinigame_didPlayerConsumePiece(sp44)){ sp44[1] = 0.0f; for(i_ptr = begin; i_ptr < end; i_ptr++){ if ((ml_vec3f_distance(i_ptr->position, sp44) < 65.25) && chyumblie_is_edible(i_ptr->marker)) { @@ -455,15 +535,15 @@ void chvilegame_player_consume_piece(Actor *this) { } } -bool chvilegame_cpu_consume_piece(ActorMarker *marker, f32 position[3]) { +bool chMrVileMinigame_mrVileConsumePiece(ActorMarker *marker, f32 position[3]) { Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; struct vilegame_piece *begin; struct vilegame_piece *end; struct vilegame_piece *i_ptr; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; if (this->state != 5){ return false; } @@ -483,49 +563,49 @@ bool chvilegame_cpu_consume_piece(ActorMarker *marker, f32 position[3]) { BKModelBin *chvilegame_get_grumblie_model(ActorMarker *marker){ Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; return local->grumblie_model_bin; } -s32 chvilegame_get_piece_count(ActorMarker *marker){ +s32 chMrVileMinigame_getPieceCount(ActorMarker *marker){ Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; return bk_vector_size(local->game_pieces); } -s32 func_8038A9E0(ActorMarker *marker){ +s32 chMrVileMinigame_getDialogIndex(ActorMarker *marker){ Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; - return local->unkC; + local = (chMrVileMinigameActor *)&this->local; + return local->dialogIndex; } -s32 chvilegame_get_score_difference(ActorMarker *marker){ +s32 chMrVileMinigame_getScoreDifference(ActorMarker *marker){ Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; return local->vile_score - local->player_score; } -bool chvilegame_find_closest_piece(ActorMarker *marker, f32 position[3], f32 yaw, f32 dst[3]) { +bool chMrVileMinigame_findClosestPiece(ActorMarker *marker, f32 position[3], f32 yaw, f32 dst[3]) { f32 piece_direction[3]; f32 target_direction[3]; Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; struct vilegame_piece *closest_piece; struct vilegame_piece *begin; struct vilegame_piece *end; @@ -534,7 +614,7 @@ bool chvilegame_find_closest_piece(ActorMarker *marker, f32 position[3], f32 yaw f32 angle_diff; this = marker_getActor(marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; target_direction[0] = 0.0f; target_direction[1] = 0.0f; target_direction[2] = 100.0f; @@ -569,13 +649,13 @@ bool chvilegame_find_closest_piece(ActorMarker *marker, f32 position[3], f32 yaw return false; } -void chvilegame_new_piece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type){ +void chMrVileMinigame_newPiece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type){ Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; struct vilegame_piece *temp_v0; this = marker_getActor(game_marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; temp_v0 = (struct vilegame_piece *)bk_vector_pushBackNew(&local->game_pieces); temp_v0->type = yumblie_type; temp_v0->marker = piece_marker; @@ -585,14 +665,14 @@ void chvilegame_new_piece(ActorMarker *game_marker, ActorMarker *piece_marker, f temp_v0->position[1] = 0.0f; } -void chvilegame_free(Actor *this){ - ActorLocal_BGS_3420 *local; +void chMrVileMinigame_free(Actor *this){ + chMrVileMinigameActor *local; - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; // [port] Teardown ordering hazard: if Mr Vile is freed before this controller, its skeletal - // anim (unk148) is already NULL and func_8038A068(this, 0) -> skeletalAnim_set crashes. Skip it. + // anim (unk148) is already NULL and chMrVileMinigame_setState(this, 0) -> skeletalAnim_set crashes. Skip it. #if 0 - func_8038A068(this, 0); + chMrVileMinigame_setState(this, 0); #endif bk_vector_free(local->game_pieces); assetcache_release(local->grumblie_model_bin); @@ -600,13 +680,13 @@ void chvilegame_free(Actor *this){ void chvilegame_remove_piece(ActorMarker *game_marker, ActorMarker *piece_marker) { Actor *this; - ActorLocal_BGS_3420 *local; + chMrVileMinigameActor *local; struct vilegame_piece *begin; struct vilegame_piece *end; struct vilegame_piece *i_ptr; this = marker_getActor(game_marker); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; begin = (struct vilegame_piece *)bk_vector_getBegin(local->game_pieces); end = (struct vilegame_piece *)bk_vector_getEnd(local->game_pieces); for(i_ptr = begin; i_ptr < end; i_ptr++){ @@ -617,8 +697,8 @@ void chvilegame_remove_piece(ActorMarker *game_marker, ActorMarker *piece_marker } } -void chvilegame_update(Actor *this) { - ActorLocal_BGS_3420 *local; +void chMrVileMinigame_update(Actor *this) { + chMrVileMinigameActor *local; f32 sp50; f32 sp4C; u8 temp_v0; @@ -626,28 +706,28 @@ void chvilegame_update(Actor *this) { s32 sp2C; sp50 = time_getDelta(); - local = (ActorLocal_BGS_3420 *)&this->local; + local = (chMrVileMinigameActor *)&this->local; if (!this->volatile_initialized) { this->volatile_initialized = true; - this->marker->actorFreeFunc = &chvilegame_free; + this->marker->actorFreeFunc = &chMrVileMinigame_free; local->game_pieces = bk_vector_new(sizeof(struct vilegame_piece), 0x20); local->grumblie_model_bin = assetcache_get(0x3F7); - local->unkC = 0; + local->dialogIndex = 0; local->vile_marker = NULL; if (this->state == 0) { - local->unkD = 0; + local->mode = 0; } else { this->state = 0; } if (jiggyscore_isSpawned(JIGGY_28_BGS_MR_VILE)) { - local->unkC = 3; - local->unkD = 3; + local->dialogIndex = 3; + local->mode = 3; } if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - local->unkC = 2; - local->unkD = 3; + local->dialogIndex = 2; + local->mode = 3; } - func_8038A068(this, 1); + chMrVileMinigame_setState(this, 1); return; } if (local->vile_marker == NULL) { @@ -656,8 +736,8 @@ void chvilegame_update(Actor *this) { // [port] Anchor: followers are driven by snapshots; only local chomp detection (for // eat requests) and HUD mirroring run here. if (!EventSystem_Should(VB_VILE_GAME_UPDATE, true)) { - if ((this->state == 5) && (local->unkC != 7)) { - chvilegame_player_consume_piece(this); + if ((this->state == 5) && (local->dialogIndex != 7)) { + chMrVileMinigame_playerConsumePiece(this); if (local->type_change_timer > 3.5) { if (local->current_type != 0) { item_adjustByDiffWithHud(ITEM_1D_GRUMBLIE, false); @@ -674,21 +754,21 @@ void chvilegame_update(Actor *this) { if (this->state == 1) { if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { if (volatileFlag_get(VOLATILE_FLAG_3)) { - func_8038A068(this, 5); + chMrVileMinigame_setState(this, 5); } - } else if (func_8038C2A8(local->vile_marker)) { - func_8038A068(this, 2); + } else if (chMrVile_playerWithinRange(local->vile_marker)) { + chMrVileMinigame_setState(this, 2); } } if (this->state == 5) { - if (local->unkC == 7) { + if (local->dialogIndex == 7) { controller_copyFaceButtons(0, sp30); - if ((sp30[FACE_BUTTON(BUTTON_B)] > 0) && func_8038C2A8(local->vile_marker)) { - func_8038A068(this, 0xA); + if ((sp30[FACE_BUTTON(BUTTON_B)] > 0) && chMrVile_playerWithinRange(local->vile_marker)) { + chMrVileMinigame_setState(this, 0xA); } } else { - chvilegame_player_consume_piece(this); - if ((local->unkC == 3) || (local->unkC == 6)) { + chMrVileMinigame_playerConsumePiece(this); + if ((local->dialogIndex == 3) || (local->dialogIndex == 6)) { if (ml_timer_update(&local->type_change_timer, sp50)) { local->current_type = !local->current_type; if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { @@ -715,21 +795,21 @@ void chvilegame_update(Actor *this) { if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { volatileFlag_set(VOLATILE_FLAG_3, 0); volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, BOOL(local->vile_score < local->player_score)); - func_8038A068(this, 1); + chMrVileMinigame_setState(this, 1); } else if (local->vile_score < local->player_score) { - if (local->unkC == 3) { - func_8038A068(this, 9); + if (local->dialogIndex == 3) { + chMrVileMinigame_setState(this, 9); } else { - func_8038A068(this, 8); + chMrVileMinigame_setState(this, 8); } } else { - func_8038A068(this, 6); + chMrVileMinigame_setState(this, 6); } } } } - if ((this->state == 7) && (BGS_func_8038C338(local->vile_marker) != 0)) { - func_8038A068(this, 1); + if ((this->state == 7) && (chMrVile_isInitialIdle(local->vile_marker) != 0)) { + chMrVileMinigame_setState(this, 1); } } @@ -738,7 +818,7 @@ void chvilegame_update(Actor *this) { // Fills a snapshot from the live controller. Only the stable states (idle, playing, and // the round-end results) are broadcast; dialog states cannot be reconstructed remotely. bool chvilegame_netGather(Actor *this, VileGameSnapshot *dst){ - ActorLocal_BGS_3420 *local = (ActorLocal_BGS_3420 *)&this->local; + chMrVileMinigameActor *local = (chMrVileMinigameActor *)&this->local; switch (this->state) { case 1: // idle @@ -752,8 +832,8 @@ bool chvilegame_netGather(Actor *this, VileGameSnapshot *dst){ return false; } dst->gameState = this->state; - dst->round = local->unkC; - dst->maxRound = local->unkD; + dst->round = local->dialogIndex; + dst->maxRound = local->mode; dst->currentType = local->current_type; dst->typeChangeTimer = local->type_change_timer; dst->playerScore = local->player_score; @@ -763,13 +843,13 @@ bool chvilegame_netGather(Actor *this, VileGameSnapshot *dst){ } // Forces the controller to match an authoritative snapshot (followers + late joiners). -// Mirrors the state-5 side effects of func_8038A068 without the dialog/round bookkeeping. +// Mirrors the state-5 side effects of chMrVileMinigame_setState without the dialog/round bookkeeping. void chvilegame_netApply(Actor *this, const VileGameSnapshot *src){ - ActorLocal_BGS_3420 *local = (ActorLocal_BGS_3420 *)&this->local; + chMrVileMinigameActor *local = (chMrVileMinigameActor *)&this->local; s32 drift; - local->unkC = src->round; - local->unkD = src->maxRound; + local->dialogIndex = src->round; + local->mode = src->maxRound; local->current_type = src->currentType; local->type_change_timer = src->typeChangeTimer; local->player_score = src->playerScore; @@ -783,14 +863,14 @@ void chvilegame_netApply(Actor *this, const VileGameSnapshot *src){ item_set(ITEM_6_HOURGLASS, true); mapSpecificFlags_set(6, true); if (local->vile_marker != NULL) { - func_8038C3DC(local->vile_marker); + chMrVile_setStatePlayMinigame(local->vile_marker); } func_8025A58C(0, 4000); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_55_BGS_MR_VILE, 28000); } else { item_set(ITEM_6_HOURGLASS, false); mapSpecificFlags_set(6, false); - // Round-end result presentation, mirroring func_8038A068's timed callbacks + // Round-end result presentation, mirroring chMrVileMinigame_setState's timed callbacks // (dialogs and the static camera stay on the authority). if (src->gameState == 6) { timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3C_MINIGAME_LOSS, 28000); @@ -813,13 +893,13 @@ void chvilegame_netApply(Actor *this, const VileGameSnapshot *src){ } // Authority-side: consume the piece at position on behalf of a remote player. Mirrors -// chvilegame_player_consume_piece without reading the local player's mouth position. -// position[1] must be 0 to match piece positions (see chvilegame_new_piece). +// chMrVileMinigame_playerConsumePiece without reading the local player's mouth position. +// position[1] must be 0 to match piece positions (see chMrVileMinigame_newPiece). // On success, reports the consumed piece's type and whether it matched the required // type so the requesting client can replay the croc's eat feedback (see // chvilegame_netPlayEatFeedback). bool chvilegame_netConsumeRemote(Actor *this, f32 position[3], s32 *out_piece_type, s32 *out_correct_type){ - ActorLocal_BGS_3420 *local = (ActorLocal_BGS_3420 *)&this->local; + chMrVileMinigameActor *local = (chMrVileMinigameActor *)&this->local; bool is_correct_type; struct vilegame_piece *begin; struct vilegame_piece *end; @@ -853,7 +933,7 @@ bool chvilegame_netConsumeRemote(Actor *this, f32 position[3], s32 *out_piece_ty // remote eat request: the croc chomp animation (which carries the chomp SFX) plus // the wrong-type reaction when the eaten piece didn't match the required type. The // score and piece removal are authority-driven and arrive separately; this is the -// cosmetic half of chvilegame_player_consume_piece that the follower otherwise skips. +// cosmetic half of chMrVileMinigame_playerConsumePiece that the follower otherwise skips. void chvilegame_netPlayEatFeedback(s32 piece_type, s32 correct_type){ func_8028F6B8(BS_INTR_17, (piece_type != YUMBLIE) ? ASSET_3F7_MODEL_GRUMBLIE : ASSET_3F6_MODEL_YUMBLIE); if (!correct_type) { diff --git a/src/CC/bss_pad.c b/src/CC/bss_pad.c deleted file mode 100644 index e4ba390c4..000000000 --- a/src/CC/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_CC_D_80389F70[0x10]; diff --git a/src/CC/actor_spawninit.c b/src/CC/ccspawnqueue.c similarity index 98% rename from src/CC/actor_spawninit.c rename to src/CC/ccspawnqueue.c index 58cfe57a2..573976ea3 100644 --- a/src/CC/actor_spawninit.c +++ b/src/CC/ccspawnqueue.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_19B0.c +// BanjoDecomp: CC/ccspawnqueue.c #include #include "functions.h" #include "variables.h" diff --git a/src/CC/ch/clanker.c b/src/CC/ch/ccgrates.c similarity index 73% rename from src/CC/ch/clanker.c rename to src/CC/ch/ccgrates.c index b9043260e..2bfc9f718 100644 --- a/src/CC/ch/clanker.c +++ b/src/CC/ch/ccgrates.c @@ -1,8 +1,11 @@ -// BanjoDecomp: code_3400.c +// BanjoDecomp: CC/ch/ccgrates.c #include #include "functions.h" #include "variables.h" +extern void port_breakable_recordBreak(s32 markerId, s32 x, s32 y, s32 z); +extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); + typedef struct { u8 *unk0; f32 unk4; @@ -65,6 +68,8 @@ void chCCGrate_die(ActorMarker *marker, ActorMarker *other_marker){ if(actor->state == 1){ chCCGrate_setNextState(actor, *local->unk0); + port_breakable_recordBreak((s32)actor->marker->id, (s32)actor->position[0], + (s32)actor->position[1], (s32)actor->position[2]); } } @@ -82,11 +87,18 @@ void chCCGrate_update(Actor * this){ if(this->modelCacheIndex == 0x28E && jiggyscore_isSpawned(JIGGY_18_CC_BOLT)){ marker_despawn(this->marker); } + else if(port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, + (s32)this->position[0], (s32)this->position[1], + (s32)this->position[2])){ + marker_despawn(this->marker); + } return; }//L803899D4 if(this->state == 1){ - if(local->unk8){ + if(local->unk8 || port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, + (s32)this->position[0], (s32)this->position[1], + (s32)this->position[2])){ chCCGrate_setNextState(this, *local->unk0); } }//L80389A10 diff --git a/src/CC/ch/key.c b/src/CC/ch/clankerkey.c similarity index 91% rename from src/CC/ch/key.c rename to src/CC/ch/clankerkey.c index 8ab935b43..6b4793514 100644 --- a/src/CC/ch/key.c +++ b/src/CC/ch/clankerkey.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_530.c +// BanjoDecomp: CC/ch/clankerkey.c #include "functions.h" #include "variables.h" #include @@ -7,7 +7,7 @@ extern void func_8030E730(s32, f32, s32); -void func_80388EA4(void); +void maClanker_raiseClanker(void); typedef struct { @@ -21,12 +21,12 @@ typedef struct { f32 unk14; } ActorLocal_CC_530; -void chClankerKey_update(Actor* this); +void maClankerKey_update(Actor* this); /* .data */ ActorInfo D_80389AD0 = { MARKER_4A_CC_KEY, ACTOR_3C_CC_KEY, ASSET_429_MODEL_CC_KEY, 0, NULL, - chClankerKey_update, actor_update_func_80326224, actor_draw, + maClankerKey_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; @@ -60,7 +60,7 @@ void CC_func_80386920(Actor *this, s32 next_state){ } if(next_state == 4){ - CC_func_8038868C(); + maClanker_raiseClankerCutscene(); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); } @@ -83,7 +83,7 @@ void func_80386AF8(Actor *arg0) { sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); } -void chClankerKey_update(Actor *this){ +void maClankerKey_update(Actor *this){ ActorMarker *marker = this->marker; f32 sp58[3]; ActorLocal_CC_530 * local = (ActorLocal_CC_530 *)&this->local; @@ -117,6 +117,10 @@ void chClankerKey_update(Actor *this){ } } else{//L80386C40 + // Anchor: teammate raised Clanker — snap the key to finished (state 5). + if(this->state == 1 && jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ + CC_func_80386920(this, 5); + } local->unk14 += tick; player_getPosition(sp58); if(local->unk1 && ! local->unk2){ @@ -196,7 +200,7 @@ void chClankerKey_update(Actor *this){ this->pitch = (f32)local->unk10 + 180.0f*(local->unk14/5.0f); if(5.0f <= local->unk14){ CC_func_80386920(this, 5); - func_80388EA4(); + maClanker_raiseClanker(); } }//L80386FC0 } diff --git a/src/CC/ch/screw.c b/src/CC/ch/clankerscrew.c similarity index 88% rename from src/CC/ch/screw.c rename to src/CC/ch/clankerscrew.c index ec6183ee3..e507fc6f6 100644 --- a/src/CC/ch/screw.c +++ b/src/CC/ch/clankerscrew.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_0.c +// BanjoDecomp: CC/ch/clankerscrew.c #include "functions.h" #include "variables.h" #include @@ -22,10 +22,10 @@ ActorInfo D_80389AA0 = { }; /* .code */ -void CC_func_803863F0(Actor *this, s32 next_state){ +void maClankersScrew_setNextState(Actor *this, s32 next_state){ ActorLocal_CC_0 * local = (ActorLocal_CC_0 *)this->local; if(this->state == 4){ - func_80388ED4(0); + maClanker_playScrewNoise(0); } this->state = next_state; local->unkC = 1; @@ -36,7 +36,7 @@ void CC_func_803863F0(Actor *this, s32 next_state){ local->unk4 = 2.0f; } if(this->state == 2){ - func_80388ED4(1); + maClanker_playScrewNoise(1); } if(this->state == 3){ local->unk0 = 1.0f; @@ -57,7 +57,7 @@ void func_803864D4(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; marker->propPtr->unk8_3 = 1; - CC_func_803863F0(this, 1); + maClankersScrew_setNextState(this, 1); }//L80386530 func_80388B4C(sp4C); @@ -74,20 +74,20 @@ void func_803864D4(Actor *this){ local->unk4 = 0.05f; } else{ - CC_func_803863F0(this, 2); + maClankersScrew_setNextState(this, 2); } }//L80386634 if(ml_timer_update(&local->unk0, sp3C)){ - CC_func_803863F0(this, 4); + maClankersScrew_setNextState(this, 4); } if((this->state == 2) && (1.0 <= local->unk8)){ - CC_func_803863F0(this, 3); + maClankersScrew_setNextState(this, 3); }//L803866B4 if((this->state == 4) && (1.0 <= local->unk8)){ - CC_func_803863F0(this, 1); + maClankersScrew_setNextState(this, 1); }//L80386714 if(this->state == 1){ diff --git a/src/CC/ch/clankertoothext.c b/src/CC/ch/clankertoothext.c index a4395f326..d0a1b2a2f 100644 --- a/src/CC/ch/clankertoothext.c +++ b/src/CC/ch/clankertoothext.c @@ -5,26 +5,28 @@ #include +#include "port/Patches/Patches.h" + typedef struct{ s32 unk0; s32 egg_count; f32 unk8; }ActorLocal_CC_BF0; -void chClankerTooth_update(Actor *this); +void maClankerTooth_update(Actor *this); /* .data */ extern ActorInfo D_80389B00 = { MARKER_4C_CLANKER_TOKEN_TOOTH_EXT, ACTOR_44_CLANKER_TOKEN_TOOTH_EXTERIOR, ASSET_309_MODEL_CLANKER_TOKEN_TOOTH_EXTERIOR, 0, NULL, - chClankerTooth_update, actor_update_func_80326224, actor_draw, + maClankerTooth_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; extern ActorInfo D_80389B24 = { MARKER_4D_CLANKER_JIGGY_TOOTH_EXT, ACTOR_45_CLANKER_JIGGY_TOOTH_EXTERIOR, ASSET_30A_MODEL_CLANKER_JIGGY_TOOTH_EXTERIOR, 0, NULL, - chClankerTooth_update, actor_update_func_80326224, actor_draw, + maClankerTooth_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; @@ -32,7 +34,7 @@ extern ActorInfo D_80389B24 = { u8 D_80389F80; /* .code */ -void chClankerTooth_setNextState(Actor *this, s32 next_state){ +void maClankerTooth_setNextState(Actor *this, s32 next_state){ ActorLocal_CC_BF0 *local = (ActorLocal_CC_BF0 *)&this->local; s32 prev_state = this->state; this->state = next_state; @@ -65,7 +67,7 @@ void func_803870EC(s32 arg0) { D_80389F80 = arg0; } -void chClankerTooth_update(Actor *this){ +void maClankerTooth_update(Actor *this){ ActorMarker *marker = this->marker; f32 sp70[3]; ActorLocal_CC_BF0 *local = (ActorLocal_CC_BF0 *)&this->local; @@ -85,11 +87,24 @@ void chClankerTooth_update(Actor *this){ this->roll = 0.0f; local->unk0 = (marker->modelId == 0x309) ? 1 : 2; local->egg_count = 0; - chClankerTooth_setNextState(this, 1); + maClankerTooth_setNextState(this, 1); if(levelSpecificFlags_get((local->unk0 == 1)? LEVEL_FLAG_0_CC_TOKEN_TOOTH_OPEN: LEVEL_FLAG_1_CC_JIGGY_TOOTH_OPEN)){ - chClankerTooth_setNextState(this, 3); + maClankerTooth_setNextState(this, 3); } }//L803871D8 + if(this->state == 1){ + s32 base = (local->unk0 - 1) * 3; + s32 bits = (port_puzzleStep_get(ANCHOR_PUZZLE_CC_CLANKER_TEETH) >> base) & 0x7; + s32 shared = (bits & 1) + ((bits >> 1) & 1) + ((bits >> 2) & 1); + while(this->state == 1 && local->egg_count < shared){ + local->egg_count++; + if(local->egg_count == 3){ + maClankerTooth_setNextState(this, 2); + }else{ + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); + } + } + } player_getPosition(sp70); local->unk8 += sp68; if(this->state == 2){ @@ -121,8 +136,11 @@ void chClankerTooth_update(Actor *this){ if(this->state == 1 && D_80389F80 == local->unk0){ D_80389F80 = 0; local->egg_count++; + // Anchor: broadcast cumulative egg progress. + port_puzzleStep_orBits(ANCHOR_PUZZLE_CC_CLANKER_TEETH, + ((1 << local->egg_count) - 1) << ((local->unk0 - 1) * 3)); if(local->egg_count == 3){ - chClankerTooth_setNextState(this, 2); + maClankerTooth_setNextState(this, 2); }else{ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); } @@ -130,9 +148,19 @@ void chClankerTooth_update(Actor *this){ else if(this->state == 2 && 1.0f <= local->unk8){ flagCnt = levelSpecificFlags_get(LEVEL_FLAG_0_CC_TOKEN_TOOTH_OPEN) + levelSpecificFlags_get(LEVEL_FLAG_1_CC_JIGGY_TOOTH_OPEN); if(!jiggyscore_isCollected(JIGGY_1B_CC_TOOTH)){ - gcdialog_showDialog((local->unk0 == 1)? ((flagCnt == 0)? 0xd30 : 0xd31) : ((flagCnt == 0)? 0xd2e : 0xd2f), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog( + (local->unk0 == 1)? + ((flagCnt == 0)? + VER_SELECT(ASSET_D30_DIALOG_CLANKER_RIGHT_TOOTH_FIRST, 0xA03, 0, 0) : VER_SELECT(ASSET_D31_DIALOG_CLANKER_RIGHT_TOOTH_SECOND, 0xA04, 0, 0)) : + ((flagCnt == 0)? + VER_SELECT(ASSET_D2E_DIALOG_CLANKER_LEFT_TOOTH_FIRST, 0xA01, 0, 0) : VER_SELECT(ASSET_D2F_DIALOG_CLANKER_LEFT_TOOTH_SECOND, 0xA02, 0, 0)), + 4, + NULL, + NULL, + NULL, + NULL); } - chClankerTooth_setNextState(this, 3); + maClankerTooth_setNextState(this, 3); }//L80387474 if(this->state == 3){ diff --git a/src/CC/ch/tooth.c b/src/CC/ch/tooth.c index 654456e8c..073116e40 100644 --- a/src/CC/ch/tooth.c +++ b/src/CC/ch/tooth.c @@ -80,6 +80,9 @@ extern void chTooth_update(Actor * this){ __chTooth_setState(this, 1); } } + else if(this->state == 1 && levelSpecificFlags_get(local->unk0->level_flag)){ + __chTooth_setState(this, 2); + } else if(this->state == 2){//L803876B4 if(local->unk0->jiggy_id && !jiggyscore_isSpawned(local->unk0->jiggy_id)){ player_getPosition(sp24); diff --git a/src/CC/checksums.c b/src/CC/checksums.c new file mode 100644 index 000000000..e6997aa4b --- /dev/null +++ b/src/CC/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: CC/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsCC; diff --git a/src/CC/crc.c b/src/CC/crc.c index 23d6de395..06714581c 100644 --- a/src/CC/crc.c +++ b/src/CC/crc.c @@ -1,8 +1,8 @@ // BanjoDecomp: crc.c #include +#include "checksums.h" +#include "version.h" -/* .data */ -//TODO Implement CRC calculation in Makefile(?) -u32 D_80389BE0 = 0x000D46A1; //CC.code CRC1 -u32 D_80389BE4 = 0x871BA43E; //CC.code CRC2 -u32 D_80389BE8 = 0x0000DF9F; //CC.data CRC1 (with this value = 0) +s32 D_80389BE0 = VER_SELECT(0x000D46A1, 0x000D4EB5, 0, 0); // CC_TEXT_CRC1 +s32 D_80389BE4 = VER_SELECT(0x871BA43E, 0xEE8A9B79, 0, 0); // CC_TEXT_CRC2 +s32 D_80389BE8 = VER_SELECT(0x0000DF9F, 0x0000EACE, 0, 0); // CC_DATA_CRC1 diff --git a/src/CC/ma/clanker.c b/src/CC/ma/clanker.c new file mode 100644 index 000000000..07ecbe059 --- /dev/null +++ b/src/CC/ma/clanker.c @@ -0,0 +1,451 @@ +// BanjoDecomp: CC/ma/clanker.c +#include +#include "core1/core1.h" +#include "functions.h" +#include "variables.h" + +#include "core2/modelRender.h" + +extern BKCollisionTriangle *func_8028EF48(void); +extern void func_8030E9FC(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); +extern void func_8030EA54(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); +extern void func_8031CE28(s32, s32, f32); +void timed_exitStaticCamera(f32); +extern BKCollisionTriangle *collisionList_func_802E805C(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32[3], u32); +extern void func_80340200(Struct83s *, f32[3], f32[3], f32, f32[3], s16[3], BKVertexList *, f32[3]); +extern BKCollisionTriangle *func_802E9118(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32, f32[3], s32, s32); +extern BKCollisionTriangle *func_802E9DD8(BKCollisionList *, BKVertexList *, f32[3], f32 *, f32, f32[3], f32, f32[3], s32); +extern int func_80340020(Struct83s *, f32[3], f32[3], f32, f32[3], BKVertexList *, f32[3], f32[3]); + +extern void boneTransformList_getBoneScale(BoneTransformList *, s32, f32[3]); +extern void boneTransformList_setBoneScale(BoneTransformList *, s32, f32[3]); +extern void func_8033A9A8(BoneTransformList *, s32, f32[3]); +extern void modelRender_setAppendageVisibility(s32, s32); +extern void modelRender_setBoneTransformList(BoneTransformList *); +extern void func_8028FAB0(f32[3]); +extern void baModel_802921D4(f32[3]); + +/* .data */ +f32 maClankerJiggyPosition[3] = {5700.0f, 4300.0f, 0.0f}; +f32 D_80389C0C[3] = {0.0f, 27.0f, 0.0f}; +f32 D_80389C18[3] = {0.0f, -27.0f, 0.0f}; +f32 maClankerRaisedSoundPosition[3] = {4000.0f, 3500.0f, 0.0f}; + +/* .bss */ +struct { + SkeletalAnimation *skeletonAnim; + u8 sfxsourceIdx; + //u8 pad5[0x3]; + f32 unk8; // screw timer? + f32 meetDialogPosition[3]; + Struct83s *unk18; + BKCollisionList *collisionList; + u8 triggerMeetDialog; + u8 currentState; + //u8 pad22[0x2]; + BKModelBin * model; + f32 position[3]; + Vec3fArray *unk34; + f32 timeDelta; + f32 unk3C; // raised sound timer? + BKVertexList *vertexList1; + BKVertexList *vertexList2; + u8 hasMetPlayer; + u8 unk49; + //u8 pad4A[2]; + f32 unk4C; // timer? + s32 unk50; // related to unk4C & unk54 + f32 unk54; // timer? +} maClanker; + +enum maClankerState_e { + MACLANKER_STATE_0_NOT_INITIALIZED, + MACLANKER_STATE_1_IDLE_UNDERWATER, + MACLANKER_STATE_2_LIFTING, + MACLANKER_STATE_3_IDLE_RAISED +}; + +BKCollisionTriangle *__maClanker_getClankerCollisionTris(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3){ // [port] pointer-width args + BKCollisionTriangle *collision_tris; + + collision_tris = collisionList_func_802E805C(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3); + if(collision_tris && func_8029453C()){ + func_80340200(maClanker.unk18, maClanker.position, 0, 1.0f, 0, collision_tris->unk0, maClanker.vertexList1, arg1); + } + return collision_tris; +} + +void __code1F70_func_80388428(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3[3], s32 arg4, u32 arg5){ // [port] pointer-width args + func_802E9118(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3, arg4, arg5); +} + +void func_803884A8(f32 arg0[3], f32 arg1, f32 arg2[3], u32 arg3){ // [port] pointer-width args + func_802E9DD8(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3); +} + +void maClanker_setState(s32 next_state){ + s32 current_state; + if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ + sfxSource_triggerCallbackByIndex(maClanker.sfxsourceIdx); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.6f, 20000); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 20000); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.9f, 20000); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 1.0f, 20000); + }//L80388594 + current_state = maClanker.currentState; + maClanker.currentState = next_state; + maClanker.timeDelta = 0.0f; + if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ + skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); + } + if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ + func_8030DD90(maClanker.sfxsourceIdx, 0); + sfxsource_playSfxAtVolume(maClanker.sfxsourceIdx, 1.0f); + sfxsource_setSfxId(maClanker.sfxsourceIdx, SFX_7D_ANCHOR_LIFTING); + sfxSource_setunk43_7ByIndex(maClanker.sfxsourceIdx, 3); + sfxsource_setSampleRate(maClanker.sfxsourceIdx, 27000); + sfxSource_func_8030E2C4(maClanker.sfxsourceIdx); + } + + if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ + if(current_state != MACLANKER_STATE_2_LIFTING){ + skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); + } + maClanker.position[1] = 1100.0f; + } +} + +void maClanker_spawnJiggy(void) { + jiggy_spawn(JIGGY_17_CC_CLANKER_RAISED, maClankerJiggyPosition); +} + +void maClanker_raiseClankerCutscene(void) { + func_80324E38(0, 3); + timed_setStaticCameraToNode(0, 0); + timed_setStaticCameraToNode(5.5f, 1); + timed_setStaticCameraToNode(7.0f, 2); + timed_setStaticCameraToNode(12.5f, 3); + timedFunc_set_0(13.0f, &maClanker_spawnJiggy); + timed_setStaticCameraToNode(16.0f, 1); + if (jiggyscore_isCollected(JIGGY_17_CC_CLANKER_RAISED) == FALSE) { + func_80324DBC(18.0f, VER_SELECT(ASSET_D2C_DIALOG_CLANKER_KEY_COMPLETE, 0x9FF, 0, 0), 4, NULL, NULL, NULL, 0); + } + timed_exitStaticCamera(18.0f); + func_80324E38(18.0f, 0); +} + + +void maClanker_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ + BKVertexList *tmp_vertex_list; + BoneTransformList *bone_transform_list; + f32 player_position[3]; + f32 viewport_position[3]; + int i; + s32 tmp_s0; + f32 sp84[3]; + s32 pad80; + f32 sp74[3]; + f32 sp68[3]; + f32 sp5C[3]; + + + if(maClanker.currentState == MACLANKER_STATE_0_NOT_INITIALIZED) + return; + + viewport_getPosition_vec3f(viewport_position); + + if(viewport_position[0] < -2600.0f || 11600.0f < viewport_position[0]) + return; + + bone_transform_list = skeletalAnim_getBoneTransformList(maClanker.skeletonAnim); + boneTransformList_getBoneScale(bone_transform_list, 0x40, sp84); + for( i = 0; i < 3; i++){ + sp84[i] = sp84[i] + (1.3 - sp84[i]) * maClanker.unk8; + } + + boneTransformList_setBoneScale(bone_transform_list, 0x40, sp84); + + if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ + func_8033A9A8(bone_transform_list, 0x44, D_80389C0C); + func_8033A9A8(bone_transform_list, 0x45, D_80389C0C); + func_8033A9A8(bone_transform_list, 0x46, D_80389C0C); + + func_8033A9A8(bone_transform_list, 0x47, D_80389C18); + func_8033A9A8(bone_transform_list, 0x48, D_80389C18); + func_8033A9A8(bone_transform_list, 0x49, D_80389C18); + } + + player_getPosition(player_position); + + for(i = 0; i < 2; i++){//L803888FC + vec3fArray_get_vec3f(maClanker.unk34, (i == 0) ? 0x10 : 0xf, sp74); + sp68[0] = player_position[0] - sp74[0]; + sp68[1] = player_position[1] - sp74[1]; + sp68[2] = player_position[2] - sp74[2]; + ml_vec3f_normalize(sp68); + + sp5C[0] = 0.0f; + sp5C[1] = sp68[2] * 45.0f; + sp5C[2] = -sp68[1] * 45.0f; + func_8033A9A8(bone_transform_list, (i == 0) ? 0x42 : 0x43, sp5C); + } + tmp_vertex_list = maClanker.vertexList1; + maClanker.vertexList1 = maClanker.vertexList2; + maClanker.vertexList2 = tmp_vertex_list; + + modelRender_setAppendageVisibility(1, (maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED) ? 1 : 0); + tmp_s0 = (viewport_position[0] < 100.0f)? 0 : 1; + modelRender_setAppendageVisibility(2, 1); + modelRender_setAppendageVisibility(3, 1); + modelRender_setAppendageVisibility(4, tmp_s0); + modelRender_setAppendageVisibility(5, tmp_s0); + modelRender_setAppendageVisibility(6, tmp_s0); + modelRender_setAppendageVisibility(7, tmp_s0); + modelRender_setAppendageVisibility(8, tmp_s0); + if(tmp_s0){ + tmp_s0 = (s32)(maClanker.unk4C * 3.99 + 1.0); + modelRender_setAppendageVisibility(2, tmp_s0); + modelRender_setAppendageVisibility(3, tmp_s0); + } + modelRender_setBoneTransformList(bone_transform_list); + modelRender_setRefPoints(maClanker.unk34); + modelRender_setVertexList(maClanker.vertexList1); + modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); + modelRender_draw(gfx, mtx, maClanker.position, NULL, 1.0f, NULL, maClanker.model); + if(func_80340020(maClanker.unk18, maClanker.position, 0, 1.0f, 0, maClanker.vertexList1, player_position, player_position)){ + func_8028FAB0(player_position); + baModel_802921D4(player_position); + } +} + +void func_80388B4C(f32 arg0[3]) { // [port] pointer-width + vec3fArray_get_vec3f(maClanker.unk34, 5, arg0); +} + +void func_80388B78(f32 arg0[3], f32 arg1[3]){ + vec3fArray_get_vec3f(maClanker.unk34, 7, arg0); + vec3fArray_get_vec3f(maClanker.unk34, 8, arg1); +} + +void func_80388BBC(f32 arg0[3], f32 arg1[3]){ + vec3fArray_get_vec3f(maClanker.unk34, 9, arg0); + vec3fArray_get_vec3f(maClanker.unk34, 10, arg1); +} + +void func_80388C00(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width + func_8031CD20(arg0, 0xb, 3); +} + +void func_80388C28(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width + func_8031CD20(arg0, 0xb, 4); +} + +void func_80388C50(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width + func_8031CD20(arg0, 0xb, 1); +} + +void CC_func_80388C78(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width + func_8031CD20(arg0, 0xb, 2); +} + +int CC_func_80388CA0(void){ + return maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED; +} + +void maClanker_release(void){ + if(maClanker.currentState){ + skeletalAnim_free(maClanker.skeletonAnim); + sfxsource_freeSfxsourceByIndex(maClanker.sfxsourceIdx); + func_80340690(maClanker.unk18); + vec3fArray_free(maClanker.unk34); + if(modelbin_getVtxList(maClanker.model) != maClanker.vertexList1) + vtxList_free(maClanker.vertexList1); + if(modelbin_getVtxList(maClanker.model) != maClanker.vertexList2) + vtxList_free(maClanker.vertexList2); + assetcache_release((void *)maClanker.model); + maClanker.unk34 = NULL; + maClanker.skeletonAnim = NULL; + maClanker.unk18 = NULL; + } +} + +void maClanker_init(void){ + maClanker.currentState = MACLANKER_STATE_0_NOT_INITIALIZED; + if(gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN){ + maClanker.skeletonAnim = skeletalAnim_new(); + maClanker.sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); + maClanker.unk8 = 1.0f; + maClanker.unk18 = func_803406B0(); + maClanker.currentState = MACLANKER_STATE_0_NOT_INITIALIZED; + maClanker.model = assetcache_get(ASSET_88E_MODEL_CLANKER_CHAIN); + maClanker.collisionList = modelbin_getCollisionList(maClanker.model); + maClanker.unk34 = vec3fArray_new(); + maClanker.unk3C = 1.0f; + maClanker.vertexList1 = modelbin_getVtxList(maClanker.model); + maClanker.vertexList2 = vtxList_clone(maClanker.vertexList1); + maClanker.hasMetPlayer = FALSE; + maClanker.unk49 = 0; + maClanker.unk50 = 0; + maClanker.unk4C = 0.0f; + maClanker.unk54 = 1.0f; + maClanker.position[0] = 5500.0f; + maClanker.position[2] = 0.0f; + maClanker.position[1] = 0.0f; + func_80320B24(__maClanker_getClankerCollisionTris, __code1F70_func_80388428, func_803884A8); + if(!nodeProp_findPositionFromActorId(ACTOR_3B_CLANKER_DIALOG_TRIGGER, maClanker.meetDialogPosition)){ + maClanker.meetDialogPosition[0] = 0.0f; + maClanker.meetDialogPosition[1] = -1e+06f; + maClanker.meetDialogPosition[2] = 0.0f; + } + if(jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ + maClanker_setState(MACLANKER_STATE_3_IDLE_RAISED); + } + else{ + maClanker_setState(MACLANKER_STATE_1_IDLE_UNDERWATER); + } + } +} + +void maClanker_raiseClanker(void){ + if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ + maClanker_setState(MACLANKER_STATE_2_LIFTING); + } +} + +void maClanker_playScrewNoise(s32 arg0){ + f32 sp1C[3]; + vec3fArray_get_vec3f(maClanker.unk34, 5, sp1C); + if(arg0 != 0){ + sfx_playFadeShorthandDefault(SFX_91_METALLIC_SOUND, 0.7f, 32675, sp1C, 100, 6000); + } + else{ + sfx_playFadeShorthandDefault(SFX_82_METAL_BREAK, 0.9f, 24000, sp1C, 100, 6000); + } + maClanker.unk8 = 1.0f; +} + +void maClanker_update(void){ + f32 player_position[3]; + f32 time_delta = time_getDelta(); + f32 sp64; + f32 sp60; + f32 sp54[3]; + f32 sp48[3]; + BKCollisionTriangle *tmp_v0; + f32 pad[3]; + + code13C0_checkCCChecksums(); + if(maClanker.currentState != MACLANKER_STATE_0_NOT_INITIALIZED && gsworld_getUnk0() == 2){ + // Anchor: teammate raised Clanker — play the physical raise (no cutscene). + if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER && jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ + maClanker_raiseClanker(); + } + player_getPosition(player_position); + maClanker.triggerMeetDialog = (ml_vec3f_distance(player_position, maClanker.meetDialogPosition) < 200.0f); + + maClanker.timeDelta += time_delta; + sp64 = skeletalAnim_getProgress(maClanker.skeletonAnim); + skeletalAnim_update(maClanker.skeletonAnim, time_delta, 1); + sp60 = skeletalAnim_getProgress(maClanker.skeletonAnim); + if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ + vec3fArray_get_vec3f(maClanker.unk34, 5, sp54); + if(sp60 < sp64){ + sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.6f, 32300, sp54, 1000, 5000); + }//L80389058 + + if(sp64 < 0.3 && 0.3 <= sp60){ + sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.5f, 32300, sp54, 1000, 5000); + } + }//L8038909C + + if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ + maClanker.position[1] += 100.0f * time_delta; + } + + if(0.0f < maClanker.unk8){ + maClanker.unk8 -= time_delta / 2; + if(maClanker.unk8 <= 0.0f) + maClanker.unk8 = 0.0f; + } + + if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ + if(maClanker.triggerMeetDialog && skeletalAnim_getAnimId(maClanker.skeletonAnim) != ASSET_C4_ANIM_CLANKER_BITE){ + skeletalAnim_set(maClanker.skeletonAnim, ASSET_C4_ANIM_CLANKER_BITE, 1.0f, 10.0f); + if(!maClanker.hasMetPlayer){ + gcdialog_showDialog(VER_SELECT(ASSET_D2B_DIALOG_CLANKER_MEET, 0x9FE, 0, 0), 0xE, maClanker.position, NULL, NULL, NULL); + maClanker.hasMetPlayer = TRUE; + } + }//L8038918C + + if(!maClanker.triggerMeetDialog && skeletalAnim_getAnimId(maClanker.skeletonAnim) == ASSET_C4_ANIM_CLANKER_BITE){ + skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 1.0f, 10.0f); + } + }//L803891BC + + if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ + func_803114D0(); + if(1100.0f <= maClanker.position[1]){ + maClanker_setState(MACLANKER_STATE_3_IDLE_RAISED); + } + }//L803891F8 + + if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ + vec3fArray_get_vec3f(maClanker.unk34, 6, sp48); + if(ml_vec3f_distance(sp48, player_position) <= 130.0f && player_position[1] - sp48[1] < 50.0f){ + func_8031D04C(MAP_21_CC_WITCH_SWITCH_ROOM, WARP_CC_WITCH_SWITCH_1_TOP_ENTRANCE); + } + }//L80389260 + + if( maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ + tmp_v0 = func_8028EF48(); + if( tmp_v0 && !maClanker.unk49 + ){ + if(tmp_v0->flags & 2){ + func_8031CE28(0x22, 5, 180.0f); + maClanker.unk49++; + } + else if(tmp_v0->flags & 4){ + func_8031CE28(0x22, 4, 0.0f); + maClanker.unk49++; + } + } + }//L803892DC + if(ml_timer_update(&maClanker.unk3C, time_delta)){ + if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ + func_8030E9FC(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, maClankerRaisedSoundPosition, 2000.0f, 4000.0f); + }else{ + func_8030EA54(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, maClankerRaisedSoundPosition, 2000.0f, 4000.0f); + }//L80389384 + maClanker.unk3C = randf2(3.0f, 6.0f); + }//L803893A0 + if(maClanker.unk50 == 0){ + if(ml_timer_update(&maClanker.unk54, time_delta)) + maClanker.unk50 = 1; + } + + if(maClanker.unk50){ + maClanker.unk4C += maClanker.unk50 * ((time_delta * 30.0) / 4); + if(1.0f < maClanker.unk4C){ + maClanker.unk50 = -1; + maClanker.unk4C = 1.0f; + } + else if(maClanker.unk4C < 0.0f){ + maClanker.unk50 = 0; + maClanker.unk4C = 0.0f; + maClanker.unk54 = randf2(0.1f, 7.0f); + } + } + }//L80389490 + +} + +void maClanker_defrag(void){ + if(maClanker.unk34) + maClanker.unk34 = vec3fArray_defrag(maClanker.unk34); + + if(maClanker.skeletonAnim) + maClanker.skeletonAnim = defrag(maClanker.skeletonAnim); + + if(maClanker.unk18) + maClanker.unk18 = func_803406D4(maClanker.unk18); +} diff --git a/src/CC/ma/clankerrings.c b/src/CC/ma/clankerrings.c new file mode 100644 index 000000000..2c8657806 --- /dev/null +++ b/src/CC/ma/clankerrings.c @@ -0,0 +1,130 @@ +// BanjoDecomp: CC/ma/clankerrings.c +#include +#include "functions.h" +#include "variables.h" +#include "../CC.h" + +extern void port_ccWater_broadcastRise(int32_t map, int32_t waterId, int32_t targetDy, f32 duration); + +/* .data */ +f32 maClankerRingsJiggyPosition[3] = {0.0f, 1300.0f, -2800.0f}; + +#define RINGS_TIMER VER_SELECT(48, 40, 0, 0) // Seconds +#define RING_COUNT 9 + +/* .bss */ +struct { + u8 currentActiveRing; + u8 isMinigameActive; + f32 timer1; + f32 timer2; +} maClankerRings; + +/* .code */ +void func_80387F80(void){ + func_8034E71C((Struct73s *)func_8034C5AC(0x131), 0x190, 0.0f); // [port] cast to match decomp behavior +} + +void maClankerRings_startMinigame(void){ + item_set(ITEM_0_HOURGLASS_TIMER, RINGS_TIMER * 60 - 1); + item_set(ITEM_6_HOURGLASS, 1); + maClankerRings.isMinigameActive = 1; +} + +void maClankerRings_endMinigame(void){ + item_set(ITEM_6_HOURGLASS, 0); + maClankerRings.isMinigameActive = 0; +} + +s32 maClankerRings_isMinigameActive(void){ + if(maClankerRings.currentActiveRing > 0 && maClankerRings.currentActiveRing < 0xA){ + return maClankerRings.currentActiveRing; + } + return 0; +} + +void maClankerRings_passRing(s32 ring_num){ + if(ring_num == maClankerRings.currentActiveRing){ + if(ring_num == 1){ + maClankerRings_startMinigame(); + } + maClankerRings.currentActiveRing++; + if(maClankerRings.currentActiveRing >= RING_COUNT){ + maClankerRings_endMinigame(); + maClankerRings.timer2 = 1.0f; + } + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); + } + else{//L803880BC + coMusicPlayer_playMusic(COMUSIC_2C_BUZZER, 28000); + } +} + +void maClankerRings_release(void){ + if(maClankerRings.currentActiveRing != 0){ + maClankerRings_endMinigame(); + } +} + +void maClankerRings_init(void){ + maClankerRings.currentActiveRing = 0; + if(gsworld_getMap() == MAP_22_CC_INSIDE_CLANKER){ + if(jiggyscore_isSpawned(JIGGY_1C_CC_RINGS)){ + timedFunc_set_0(0.0f, func_80387F80); + } + else{ + maClankerRings.currentActiveRing = 1; + maClankerRings.isMinigameActive = 0; + maClankerRings.timer2 = 0.0f; + maClankerRings.timer1 = 0.0f; + } + } +} + +void maClankerRings_update(void){ + f32 player_position[3]; + f32 time_delta = time_getDelta(); + Struct70s *tmp_v0; // [port] pointer-width + + if(maClankerRings.currentActiveRing != 0){ + if(jiggyscore_isSpawned(JIGGY_1C_CC_RINGS) && maClankerRings.currentActiveRing < RING_COUNT){ + maClankerRings_endMinigame(); + // func_80387F80 snaps water to risen height; VB listener suppresses it when connected (rise already animating). + if(EventSystem_Should(VB_CC_RINGS_SNAP_WATER, true)){ + func_80387F80(); + } + maClankerRings.currentActiveRing = 0; + return; + } + maClankerRings.timer1 += time_delta; + player_getPosition(player_position); + if(ml_timer_update(&maClankerRings.timer2, time_delta)){ + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(2.0f, 0); + timedJiggySpawn(2.1f, JIGGY_1C_CC_RINGS, maClankerRingsJiggyPosition); + func_80324E38(5.0f, 0); + timed_exitStaticCamera(5.0f); + tmp_v0 = func_8034C5AC(0x131); + if(tmp_v0){ + func_8034E78C((Struct73s *)tmp_v0, 0x190, 12.0f); // [port] cast matches decomp behavior + } + port_ccWater_broadcastRise(MAP_22_CC_INSIDE_CLANKER, 0x131, 0x190, 12.0f); + maClankerRings.timer1 = 0.0f; + }//L80388264 + if(!(maClankerRings.currentActiveRing < 2) && maClankerRings.isMinigameActive != 0){ + if( (player_position[0] < -1100.0f && player_position[1] < -40.0f) + || (1560.0f < player_position[0]) + || (2850.0f < player_position[2]) + || (player_position[2] < -3000.0f) + || (maClankerRings.currentActiveRing < RING_COUNT && item_empty(ITEM_6_HOURGLASS)) + ){ + maClankerRings_endMinigame(); + coMusicPlayer_playMusic(COMUSIC_3C_MINIGAME_LOSS, 28000); + maClankerRings_release(); + maClankerRings_init(); + } + }//L8038834C + }//L8038834C +} + diff --git a/src/CC/minigame_rings.c b/src/CC/minigame_rings.c deleted file mode 100644 index 3a243bedf..000000000 --- a/src/CC/minigame_rings.c +++ /dev/null @@ -1,115 +0,0 @@ -// BanjoDecomp: code_1B90.c -#include -#include "functions.h" -#include "variables.h" -#include "CC.h" - -/* .data */ -f32 D_80389BF0[3] = {0.0f, 1300.0f, -2800.0f}; - -/* .bss */ -struct { - u8 unk0; - u8 unk1; - f32 unk4; - f32 unk8; -} D_80389F90; - -/* .code */ -void func_80387F80(void){ - func_8034E71C((Struct73s *)func_8034C5AC(0x131), 0x190, 0.0f); -} - -void CC_func_80387FB0(void){ - item_set(ITEM_0_HOURGLASS_TIMER, 48*60 - 1); - item_set(ITEM_6_HOURGLASS, 1); - D_80389F90.unk1 = 1; -} - -void func_80387FE8(void){ - item_set(ITEM_6_HOURGLASS, 0); - D_80389F90.unk1 = 0; -} - -s32 func_80388010(void){ - if(D_80389F90.unk0 > 0 && D_80389F90.unk0 < 0xA){ - return D_80389F90.unk0; - } - return 0; -} - -void func_8038803C(s32 arg0){ - if(arg0 == D_80389F90.unk0){ - if(arg0 == 1){ - CC_func_80387FB0(); - } - D_80389F90.unk0++; - if(D_80389F90.unk0 >= 9){ - func_80387FE8(); - D_80389F90.unk8 = 1.0f; - } - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - } - else{//L803880BC - coMusicPlayer_playMusic(COMUSIC_2C_BUZZER, 28000); - } -} - -void func_803880D4(void){ - if(D_80389F90.unk0 != 0){ - func_80387FE8(); - } -} - -void func_80388104(void){ - D_80389F90.unk0 = 0; - if(gsworld_getMap() == MAP_22_CC_INSIDE_CLANKER){ - if(jiggyscore_isSpawned(JIGGY_1C_CC_RINGS)){ - timedFunc_set_0(0.0f, func_80387F80); - } - else{ - D_80389F90.unk0 = 1; - D_80389F90.unk1 = 0; - D_80389F90.unk8 = 0.0f; - D_80389F90.unk4 = 0.0f; - } - } -} - -void func_8038817C(void){ - f32 sp24[3]; - f32 sp20 = time_getDelta(); - Struct70s *tmp_v0; - - if(D_80389F90.unk0 != 0){ - D_80389F90.unk4 += sp20; - player_getPosition(sp24); - if(ml_timer_update(&D_80389F90.unk8, sp20)){ - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(2.0f, 0); - timedJiggySpawn(2.1f, JIGGY_1C_CC_RINGS, D_80389BF0); - func_80324E38(5.0f, 0); - timed_exitStaticCamera(5.0f); - tmp_v0 = func_8034C5AC(0x131); - if(tmp_v0){ - func_8034E78C((Struct73s *)tmp_v0, 0x190, 12.0f); - } - D_80389F90.unk4 = 0.0f; - }//L80388264 - if(!(D_80389F90.unk0 < 2) && D_80389F90.unk1 != 0){ - if( (sp24[0] < -1100.0f && sp24[1] < -40.0f) - || (1560.0f < sp24[0]) - || (2850.0f < sp24[2]) - || (sp24[2] < -3000.0f) - || (D_80389F90.unk0 < 9 && item_empty(ITEM_6_HOURGLASS)) - ){ - func_80387FE8(); - coMusicPlayer_playMusic(COMUSIC_3C_MINIGAME_LOSS, 28000); - func_803880D4(); - func_80388104(); - } - }//L8038834C - }//L8038834C -} - diff --git a/src/CC/model_renderstate.c b/src/CC/model_renderstate.c index b44d296cc..921b09134 100644 --- a/src/CC/model_renderstate.c +++ b/src/CC/model_renderstate.c @@ -38,15 +38,15 @@ void func_803877B0(Struct_CC_13C0_1* arg0, void* arg1, f32 position[3], f32 rota return; if (temp_v0 == 0) { - func_8033A45C(1, 1); + modelRender_setAppendageVisibility(1, 1); } else if (temp_v0 == 1) { - func_8033A45C(1, 2); + modelRender_setAppendageVisibility(1, 2); } else if (temp_v0 == 2) { - func_8033A45C(1, 2); + modelRender_setAppendageVisibility(1, 2); rotation[2] += (arg0->unkC * 20.0f); arg4 = arg4*(1.0f - arg0->unkC); } - func_8033A45C(2, 0); + modelRender_setAppendageVisibility(2, 0); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); modelRender_draw(gfx, mtx, position, rotation, arg4, NULL, modeL_ptr); } @@ -109,7 +109,7 @@ void CC_func_80387A40(Struct_CC_13C0_1* arg0, Struct68s* arg1, f32 arg2) { s32 sp28; arg0->unkC += arg2; - temp_v0 = func_80388010(); + temp_v0 = maClankerRings_isMinigameActive(); if (temp_v0 == 0) { func_803878AC(arg0, arg1, 3); } else { @@ -140,7 +140,7 @@ void CC_func_80387A40(Struct_CC_13C0_1* arg0, Struct68s* arg1, f32 arg2) { sp28 = ((sp50[0]*sp44[0] + sp50[1]*sp44[1] + sp50[2]*sp44[2]) >= 0.0f) ? 1 : -1; if (sp28 == -arg0->unk8) { if (LENGTH_VEC3F(sp50) < (func_80351830(arg1) * 250.0f)) { - func_8038803C(arg0->unk0); + maClankerRings_passRing(arg0->unk0); } } arg0->unk8 = sp28; @@ -166,6 +166,18 @@ void code13C0_makeCameraFlipAndTilt(void){ } +void code13C0_checkCCChecksums(void){ +#if ANTI_TAMPER + u32 rom_data; + u32 unused; + osPiReadIo(0x504, &rom_data); + rom_data = (rom_data & 0xffff) + 0xffff5BA0; + if(rom_data){ + code13C0_makeCameraFlipAndTilt(); + } +#endif +} + void CC_func_80387D4C(void){ // [port] anti-tamper: ROM CRC check via osPiReadIo — not applicable on PC #if ANTI_TAMPER diff --git a/src/CC/platform_physics.c b/src/CC/platform_physics.c deleted file mode 100644 index 1e20fd654..000000000 --- a/src/CC/platform_physics.c +++ /dev/null @@ -1,441 +0,0 @@ -// BanjoDecomp: code_1F70.c -#include -#include "core1/core1.h" -#include "functions.h" -#include "variables.h" - -#include "core2/modelRender.h" -#include "core2/bonetransform.h" - -extern BKCollisionTriangle *func_8028EF48(void); -extern void func_8030E9FC(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); -extern void func_8030EA54(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); -extern void func_8031CE28(s32, s32, f32); -void timed_exitStaticCamera(f32); -extern BKCollisionTriangle *collisionList_func_802E805C(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32[3], u32); -extern void func_80340200(Struct83s *, f32[3], f32[3], f32, f32[3], s16[3], BKVertexList *, f32[3]); -extern BKCollisionTriangle *func_802E9118(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32, f32[3], s32, s32); -extern BKCollisionTriangle *func_802E9DD8(BKCollisionList *, BKVertexList *, f32[3], f32 *, f32, f32[3], f32, f32[3], s32); -extern bool func_80340020(Struct83s *, f32[3], f32[3], f32, f32 *, BKVertexList *, f32[3], f32[3]); - -extern void boneTransformList_getBoneScale(BoneTransformList *, s32, f32[3]); -extern void boneTransformList_setBoneScale(BoneTransformList *, s32, f32[3]); -extern void func_8033A9A8(BoneTransformList *, s32, f32[3]); -extern void func_8033A45C(s32, s32); -extern void modelRender_setBoneTransformList(BoneTransformList *); -extern void func_8028FAB0(f32[3]); -extern void baModel_802921D4(f32[3]); - -/* .data */ -f32 D_80389C00[3] = {5700.0f, 4300.0f, 0.0f}; -f32 D_80389C0C[3] = {0.0f, 27.0f, 0.0f}; -f32 D_80389C18[3] = {0.0f, -27.0f, 0.0f}; -f32 D_80389C24[3] = {4000.0f, 3500.0f, 0.0f}; - -/* .bss */ -struct { - SkeletalAnimation *unk0; - u8 sfxsourceIdx; - //u8 pad5[0x3]; - f32 unk8; - f32 unkC[3]; - Struct83s *unk18; - BKCollisionList *unk1C; - u8 unk20; - u8 unk21; - //u8 pad22[0x2]; - BKModelBin * unk24; - f32 unk28[3]; - Vec3fArray *unk34; - f32 unk38; - f32 unk3C; - BKVertexList *unk40; - BKVertexList *unk44; - u8 unk48; - u8 unk49; - //u8 pad4A[2]; - f32 unk4C; - s32 unk50; - f32 unk54; -}D_80389FA0; - -BKCollisionTriangle *__code1F70_func_80388360(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3){ - BKCollisionTriangle *out_v0; - - out_v0 = collisionList_func_802E805C(D_80389FA0.unk1C, D_80389FA0.unk40, D_80389FA0.unk28, 0, 1.0f, arg0, arg1, arg2, arg3); - if(out_v0 && func_8029453C()){ - func_80340200(D_80389FA0.unk18, D_80389FA0.unk28, 0, 1.0f, 0, out_v0->unk0, D_80389FA0.unk40, arg1); - } - return out_v0; -} - -void __code1F70_func_80388428(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3[3], s32 arg4, u32 arg5){ - func_802E9118(D_80389FA0.unk1C, D_80389FA0.unk40, D_80389FA0.unk28, 0, 1.0f, arg0, arg1, arg2, arg3, arg4, arg5); -} - -void func_803884A8(f32 arg0[3], f32 arg1, f32 arg2[3], u32 arg3){ - func_802E9DD8(D_80389FA0.unk1C, D_80389FA0.unk40, D_80389FA0.unk28, 0, 1.0f, arg0, arg1, arg2, arg3); -} - -void func_80388518(s32 arg0){ - s32 sp24; - if(D_80389FA0.unk21 == 2){ - sfxSource_triggerCallbackByIndex(D_80389FA0.sfxsourceIdx); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.6f, 20000); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 20000); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.9f, 20000); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 1.0f, 20000); - }//L80388594 - sp24 = D_80389FA0.unk21; - D_80389FA0.unk21 = arg0; - D_80389FA0.unk38 = 0.0f; - if(D_80389FA0.unk21 == 1){ - skeletalAnim_set(D_80389FA0.unk0, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); - } - if(D_80389FA0.unk21 == 2){ - func_8030DD90(D_80389FA0.sfxsourceIdx, 0); - sfxsource_playSfxAtVolume(D_80389FA0.sfxsourceIdx, 1.0f); - sfxsource_setSfxId(D_80389FA0.sfxsourceIdx, SFX_7D_ANCHOR_LIFTING); - sfxSource_setunk43_7ByIndex(D_80389FA0.sfxsourceIdx, 3); - sfxsource_setSampleRate(D_80389FA0.sfxsourceIdx, 27000); - sfxSource_func_8030E2C4(D_80389FA0.sfxsourceIdx); - } - - if(D_80389FA0.unk21 == 3){ - if(sp24 != 2){ - skeletalAnim_set(D_80389FA0.unk0, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); - } - D_80389FA0.unk28[1] = 1100.0f; - } -} - -void func_80388664(void) { - jiggy_spawn(JIGGY_17_CC_CLANKER_RAISED, D_80389C00); -} - -void CC_func_8038868C(void) { - func_80324E38(0, 3); - timed_setStaticCameraToNode(0, 0); - timed_setStaticCameraToNode(5.5f, 1); - timed_setStaticCameraToNode(7.0f, 2); - timed_setStaticCameraToNode(12.5f, 3); - timedFunc_set_0(13.0f, &func_80388664); - timed_setStaticCameraToNode(16.0f, 1); - if (jiggyscore_isCollected(JIGGY_17_CC_CLANKER_RAISED) == 0) { - func_80324DBC(18.0f, 0xD2C, 4, NULL, NULL, NULL, 0); - } - timed_exitStaticCamera(18.0f); - func_80324E38(18.0f, 0); -} - - -void CC_func_80388760(Gfx **gfx, Mtx **mtx, Vtx **vtx){ - BKVertexList *tmp_v0; - BoneTransformList *s1; - f32 spA4[3]; - f32 sp98[3]; - int i; - s32 tmp_s0; - f32 sp84[3]; - s32 pad80; - f32 sp74[3]; - f32 sp68[3]; - f32 sp5C[3]; - - - if(D_80389FA0.unk21 == 0) - return; - - viewport_getPosition_vec3f(sp98); - - if(sp98[0] < -2600.0f || 11600.0f < sp98[0]) - return; - - s1 = skeletalAnim_getBoneTransformList(D_80389FA0.unk0); - boneTransformList_getBoneScale(s1, 0x40, sp84); - for( i = 0; i < 3; i++){ - sp84[i] = sp84[i] + (1.3 - sp84[i])*D_80389FA0.unk8; - } - - boneTransformList_setBoneScale(s1, 0x40, sp84); - - if(D_80389FA0.unk21 == 1){ - func_8033A9A8(s1, 0x44, D_80389C0C); - func_8033A9A8(s1, 0x45, D_80389C0C); - func_8033A9A8(s1, 0x46, D_80389C0C); - - func_8033A9A8(s1, 0x47, D_80389C18); - func_8033A9A8(s1, 0x48, D_80389C18); - func_8033A9A8(s1, 0x49, D_80389C18); - } - - player_getPosition(spA4); - - for(i = 0; i < 2; i++){//L803888FC - vec3fArray_get_vec3f(D_80389FA0.unk34, (i == 0) ? 0x10 : 0xf, sp74); - sp68[0] = spA4[0] - sp74[0]; - sp68[1] = spA4[1] - sp74[1]; - sp68[2] = spA4[2] - sp74[2]; - ml_vec3f_normalize(sp68); - - sp5C[0] = 0.0f; - sp5C[1] = sp68[2]*45.0f; - sp5C[2] = -sp68[1]*45.0f; - func_8033A9A8(s1, (i == 0)?0x42:0x43, sp5C); - } - tmp_v0 = D_80389FA0.unk40; - D_80389FA0.unk40 = D_80389FA0.unk44; - D_80389FA0.unk44 = tmp_v0; - - func_8033A45C(1, (D_80389FA0.unk21 == 3) ? 1 : 0); - tmp_s0 = (sp98[0] < 100.0f)? 0 : 1; - func_8033A45C(2, 1); - func_8033A45C(3, 1); - func_8033A45C(4, tmp_s0); - func_8033A45C(5, tmp_s0); - func_8033A45C(6, tmp_s0); - func_8033A45C(7, tmp_s0); - func_8033A45C(8, tmp_s0); - if(tmp_s0){ - tmp_s0 = (s32)(D_80389FA0.unk4C*3.99 + 1.0); - func_8033A45C(2, tmp_s0); - func_8033A45C(3, tmp_s0); - } - modelRender_setBoneTransformList(s1); - modelRender_setRefPoints(D_80389FA0.unk34); - modelRender_setVertexList(D_80389FA0.unk40); - modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); - modelRender_draw(gfx, mtx, D_80389FA0.unk28, NULL, 1.0f, NULL, D_80389FA0.unk24); - if(func_80340020(D_80389FA0.unk18, D_80389FA0.unk28, 0, 1.0f, 0, D_80389FA0.unk40, spA4, spA4)){ - func_8028FAB0(spA4); - baModel_802921D4(spA4); - } -} - -void func_80388B4C(f32 arg0[3]) { - vec3fArray_get_vec3f(D_80389FA0.unk34, 5, arg0); -} - -void func_80388B78(f32 arg0[3], f32 arg1[3]){ - vec3fArray_get_vec3f(D_80389FA0.unk34, 7, arg0); - vec3fArray_get_vec3f(D_80389FA0.unk34, 8, arg1); -} - -void func_80388BBC(f32 arg0[3], f32 arg1[3]){ - vec3fArray_get_vec3f(D_80389FA0.unk34, 9, arg0); - vec3fArray_get_vec3f(D_80389FA0.unk34, 10, arg1); -} - -void func_80388C00(NodeProp *arg0, ActorMarker *arg1){ - func_8031CD20(arg0, 0xb, 3); -} - -void func_80388C28(NodeProp *arg0, ActorMarker *arg1){ - func_8031CD20(arg0, 0xb, 4); -} - -void func_80388C50(NodeProp *arg0, ActorMarker *arg1){ - func_8031CD20(arg0, 0xb, 1); -} - -void CC_func_80388C78(NodeProp *arg0, ActorMarker *arg1){ - func_8031CD20(arg0, 0xb, 2); -} - -int CC_func_80388CA0(void){ - return D_80389FA0.unk21 == 3; -} - -void func_80388CB4(void){ - if(D_80389FA0.unk21){ - skeletalAnim_free(D_80389FA0.unk0); - sfxsource_freeSfxsourceByIndex(D_80389FA0.sfxsourceIdx); - func_80340690(D_80389FA0.unk18); - vec3fArray_free(D_80389FA0.unk34); - if(modelbin_getVtxList(D_80389FA0.unk24) != D_80389FA0.unk40) - vtxList_free(D_80389FA0.unk40); - if(modelbin_getVtxList(D_80389FA0.unk24) != D_80389FA0.unk44) - vtxList_free(D_80389FA0.unk44); - assetcache_release((void *)D_80389FA0.unk24); - D_80389FA0.unk34 = NULL; - D_80389FA0.unk0 = NULL; - D_80389FA0.unk18 = NULL; - } -} - -void func_80388D54(void){ - D_80389FA0.unk21 = 0; - if(gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN){ - D_80389FA0.unk0 = skeletalAnim_new(); - D_80389FA0.sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); - D_80389FA0.unk8 = 1.0f; - D_80389FA0.unk18 = func_803406B0(); - D_80389FA0.unk21 = 0; - D_80389FA0.unk24 = assetcache_get(ASSET_88E_MODEL_CLANKER_CHAIN); - D_80389FA0.unk1C = modelbin_getCollisionList(D_80389FA0.unk24); - D_80389FA0.unk34 = vec3fArray_new(); - D_80389FA0.unk3C = 1.0f; - D_80389FA0.unk40 = modelbin_getVtxList(D_80389FA0.unk24); - D_80389FA0.unk44 = vtxList_clone(D_80389FA0.unk40); - D_80389FA0.unk48 = 0; - D_80389FA0.unk49 = 0; - D_80389FA0.unk50 = 0; - D_80389FA0.unk4C = 0.0f; - D_80389FA0.unk54 = 1.0f; - D_80389FA0.unk28[0] = 5500.0f; - D_80389FA0.unk28[2] = 0.0f; - D_80389FA0.unk28[1] = 0.0f; - func_80320B24(__code1F70_func_80388360, __code1F70_func_80388428, func_803884A8); - if(!nodeProp_findPositionFromActorId(0x3B, D_80389FA0.unkC)){ - D_80389FA0.unkC[0] = 0.0f; - D_80389FA0.unkC[1] =-1e+06f; - D_80389FA0.unkC[2] = 0.0f; - } - if(jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ - func_80388518(3); - } - else{ - func_80388518(1); - } - } -} - -void func_80388EA4(void){ - if(D_80389FA0.unk21 == 1){ - func_80388518(2); - } -} - -void func_80388ED4(s32 arg0){ - f32 sp1C[3]; - vec3fArray_get_vec3f(D_80389FA0.unk34, 5, sp1C); - if(arg0 != 0){ - sfx_playFadeShorthandDefault(SFX_91_METALLIC_SOUND, 0.7f, 32675, sp1C, 100, 6000); - } - else{ - sfx_playFadeShorthandDefault(SFX_82_METAL_BREAK, 0.9f, 24000, sp1C, 100, 6000); - } - D_80389FA0.unk8 = 1.0f; -} - -void CC_func_80388F4C(void){ - f32 sp6C[3]; - f32 sp68 = time_getDelta(); - f32 sp64; - f32 sp60; - f32 sp54[3]; - f32 sp48[3]; - BKCollisionTriangle *tmp_v0; - f32 pad[3]; - - CC_func_80387D4C(); - if(D_80389FA0.unk21 != 0 && gsworld_getUnk0() == 2){ - player_getPosition(sp6C); - D_80389FA0.unk20 = (ml_vec3f_distance(sp6C, D_80389FA0.unkC) < 200.0f); - - D_80389FA0.unk38 += sp68; - sp64 = skeletalAnim_getProgress(D_80389FA0.unk0); - skeletalAnim_update(D_80389FA0.unk0, sp68, 1); - sp60 = skeletalAnim_getProgress(D_80389FA0.unk0); - if(D_80389FA0.unk21 == 3){ - vec3fArray_get_vec3f(D_80389FA0.unk34, 5, sp54); - if(sp60 < sp64){ - sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.6f, 32300, sp54, 1000, 5000); - }//L80389058 - - if(sp64 < 0.3 && 0.3 <= sp60){ - sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.5f, 32300, sp54, 1000, 5000); - } - }//L8038909C - - if(D_80389FA0.unk21 == 2){ - D_80389FA0.unk28[1] += 100.0f*sp68; - } - - if(0.0f < D_80389FA0.unk8){ - D_80389FA0.unk8 -= sp68/2; - if(D_80389FA0.unk8 <= 0.0f) - D_80389FA0.unk8 = 0.0f; - } - - if(D_80389FA0.unk21 == 1){ - if(D_80389FA0.unk20 && skeletalAnim_getAnimId(D_80389FA0.unk0) != ASSET_C4_ANIM_CLANKER_BITE){ - skeletalAnim_set(D_80389FA0.unk0, ASSET_C4_ANIM_CLANKER_BITE, 1.0f, 10.0f); - if(!D_80389FA0.unk48){ - gcdialog_showDialog(ASSET_D2B_DIALOG_CLANKER_MEET, 0xE, D_80389FA0.unk28, NULL, NULL, NULL); - D_80389FA0.unk48 = true; - } - }//L8038918C - - if(!D_80389FA0.unk20 && skeletalAnim_getAnimId(D_80389FA0.unk0) == ASSET_C4_ANIM_CLANKER_BITE){ - skeletalAnim_set(D_80389FA0.unk0, ASSET_C3_ANIM_CLANKER_IDLE, 1.0f, 10.0f); - } - }//L803891BC - - if(D_80389FA0.unk21 == 2){ - func_803114D0(); - if(1100.0f <= D_80389FA0.unk28[1]){ - func_80388518(3); - } - }//L803891F8 - - if(D_80389FA0.unk21 == 3){ - vec3fArray_get_vec3f(D_80389FA0.unk34, 6, sp48); - if(ml_vec3f_distance(sp48, sp6C) <= 130.0f && sp6C[1] - sp48[1] < 50.0f){ - func_8031D04C(MAP_21_CC_WITCH_SWITCH_ROOM, WARP_CC_WITCH_SWITCH_1_TOP_ENTRANCE); - } - }//L80389260 - - if( D_80389FA0.unk21 == 3){ - tmp_v0 = func_8028EF48(); - if( tmp_v0 && !D_80389FA0.unk49 - ){ - if(tmp_v0->flags & 2){ - func_8031CE28(0x22, 5, 180.0f); - D_80389FA0.unk49++; - } - else if(tmp_v0->flags & 4){ - func_8031CE28(0x22, 4, 0.0f); - D_80389FA0.unk49++; - } - } - }//L803892DC - if(ml_timer_update(&D_80389FA0.unk3C, sp68)){ - if(D_80389FA0.unk21 == 3){ - func_8030E9FC(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, D_80389C24, 2000.0f, 4000.0f); - }else{ - func_8030EA54(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, D_80389C24, 2000.0f, 4000.0f); - }//L80389384 - D_80389FA0.unk3C = randf2(3.0f, 6.0f); - }//L803893A0 - if(D_80389FA0.unk50 == 0){ - if(ml_timer_update(&D_80389FA0.unk54, sp68)) - D_80389FA0.unk50 = 1; - } - - if(D_80389FA0.unk50){ - D_80389FA0.unk4C += D_80389FA0.unk50 * ((sp68 * 30.0)/4); - if(1.0f < D_80389FA0.unk4C){ - D_80389FA0.unk50 = -1; - D_80389FA0.unk4C = 1.0f; - } - else if(D_80389FA0.unk4C < 0.0f){ - D_80389FA0.unk50 = 0; - D_80389FA0.unk4C = 0.0f; - D_80389FA0.unk54 = randf2(0.1f, 7.0f); - } - } - }//L80389490 - -} - -void func_803894A0(void){ - if(D_80389FA0.unk34) - D_80389FA0.unk34 = vec3fArray_defrag(D_80389FA0.unk34); - - if(D_80389FA0.unk0) - D_80389FA0.unk0 = defrag(D_80389FA0.unk0); - - if(D_80389FA0.unk18) - D_80389FA0.unk18 = func_803406D4(D_80389FA0.unk18); -} diff --git a/src/CCW/actor_spawninit.c b/src/CCW/actor_spawninit.c deleted file mode 100644 index 032d47abd..000000000 --- a/src/CCW/actor_spawninit.c +++ /dev/null @@ -1,157 +0,0 @@ -// BanjoDecomp: code_76C0.c -#include -#include "functions.h" -#include "variables.h" -#include "prop.h" -#include "actor.h" - -extern void func_802D3D54(Actor *); -extern void func_802D3D74(Actor *); -extern void func_80325F84(Actor *); - - -extern ActorInfo D_8038EB50; -extern ActorInfo D_8038EB74; -extern ActorInfo D_8038EBA0; -extern ActorInfo D_8038EBD0; -extern ActorInfo D_8038EC14; -extern ActorInfo D_8038EC70; -extern ActorInfo D_8038ECA0; -extern ActorInfo D_8038ECE8; -extern ActorInfo D_8038EE70; -extern ActorInfo D_8038F130; -extern ActorInfo chCaterpillar; -extern ActorInfo D_8038F190; -extern ActorInfo D_8038F230; -extern ActorInfo D_8038F6F0; -extern ActorInfo D_8038ED50; -extern ActorInfo D_8038ED98; -extern ActorInfo D_8038EDE0; -extern ActorInfo D_8038EE28; -extern ActorInfo D_8038ED74; -extern ActorInfo D_8038EDBC; -extern ActorInfo D_8038EE04; -extern ActorInfo D_8038EE4C; -extern ActorInfo D_8038F270; -extern ActorInfo D_8038F300; -extern ActorInfo D_8038F35C; -extern ActorInfo D_8038F380; -extern ActorInfo D_8038F3A4; -extern ActorInfo D_8038F3C8; -extern ActorInfo D_8038F3EC; -extern ActorInfo D_8038F410; -extern ActorInfo D_8038F434; -extern ActorInfo D_8038F460; -extern ActorInfo D_8038F4A8; -extern ActorInfo D_8038F4D0; -extern ActorInfo D_8038F614; -extern ActorInfo chGnawtyBoulder; -extern ActorInfo D_8038F908; -extern ActorInfo D_8038F8C0; -extern ActorInfo D_8038F720; -extern ActorInfo D_8038F744; -extern ActorInfo D_8038F768; -extern ActorInfo D_8038F78C; -extern ActorInfo chGrublinHood; -extern ActorInfo gChVacationTextTrigger; -extern ActorInfo D_8038F7D4; -extern ActorInfo D_8038F7B0; -extern ActorInfo D_8038F888; -extern ActorInfo D_8038F7F8; -extern ActorInfo D_8038F81C; -extern ActorInfo D_8038F840; -extern ActorInfo D_8038F864; - -void CCW_func_8038DB0C(Actor *this); -void func_8038DAB0(Actor *this); - -/* .data */ -ActorInfo D_8038F720 = { 0x239, 0x25F, 0x4FC, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F744 = { 0x236, 0x260, 0x4F9, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F768 = { 0x237, 0x261, 0x4FA, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F78C = { 0x238, 0x262, 0x4FB, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F7B0 = { 0x243, 0x2E6, 0x533, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F7D4 = { 0x263, 0x2E7, 0x518, 0x1, NULL, func_8038DAB0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F7F8 = { 0x21E, 0x233, 0x3B3, 0x1, NULL, func_802D3D74, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F81C = { 0x26B, 0x2DE, 0x531, 0x1, NULL, CCW_func_8038DB0C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F840 = { 0x26C, 0x2DD, 0x53E, 0x1, NULL, CCW_func_8038DB0C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F864 = { 0x26D, 0x2DC, 0x53F, 0x1, NULL, CCW_func_8038DB0C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8038F888 = { 0x1CC, 0x318, 0x0, 0x0, NULL, func_80325F84, NULL, func_80325340, 0, 0, 0.0f, 0}; - - -/* .code */ -void func_8038DAB0(Actor *this){ - if(!this->initialized){ - func_802D3CE8(this); - this->initialized = true; - - if (levelSpecificFlags_get(LEVEL_FLAG_38_CCW_UNKNOWN)) { - marker_despawn(this->marker); - } - } -} - -void CCW_func_8038DB0C(Actor *this){ - if(!this->initialized){ - func_802D3D74(this); - this->initialized = true; - this->position_x = 325.8f; - this->position_y = 600.0f; - this->position_z = 0.0f; - } -} - -void CCW_func_8038DB6C(void) -{ - spawnableActorList_add(&D_8038EB50, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_8038EB74, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_8038EBA0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); - spawnableActorList_add(&D_8038EBD0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&D_8038EC14, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038EC70, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_8038ECA0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_8038ECE8, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_8038EE70, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F130, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chCaterpillar, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F190, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_8038F230, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F6F0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038ED50, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038ED98, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038EDE0, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038EE28, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038ED74, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038EDBC, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038EE04, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038EE4C, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038F270, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F300, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F35C, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F380, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_8038F3A4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F3C8, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F3EC, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_8038F410, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F434, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F460, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F4A8, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F4D0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_8038F614, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chGnawtyBoulder, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_8038F908, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&D_8038F8C0, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&D_8038F720, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038F744, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038F768, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038F78C, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chGrublinHood, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&gChVacationTextTrigger, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038F7D4, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038F7B0, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038F888, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_8038F7F8, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038F81C, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038F840, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038F864, actor_new, ACTOR_FLAG_UNKNOWN_10); -} diff --git a/src/CCW/bss_pad.c b/src/CCW/bss_pad.c deleted file mode 100644 index 152d079d3..000000000 --- a/src/CCW/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_CCW_8038FDD0[0x10]; diff --git a/src/CCW/ccwspawnqueue.c b/src/CCW/ccwspawnqueue.c new file mode 100644 index 000000000..3519d36f7 --- /dev/null +++ b/src/CCW/ccwspawnqueue.c @@ -0,0 +1,229 @@ +// BanjoDecomp: CCW/ccwspawnqueue.c +#include +#include "functions.h" +#include "variables.h" +#include "prop.h" +#include "actor.h" + +extern void chMMMBreakableWooden_update(Actor *); +extern void func_802D3D74(Actor *); +extern void func_80325F84(Actor *); + + +extern ActorInfo chZubbaDoorSummer; +extern ActorInfo chZubbaDoorAutumn; +extern ActorInfo chZubbaHoneyLump; +extern ActorInfo chZubba; +extern ActorInfo chZubbaDocile; +extern ActorInfo chCCWBeanstalk; +extern ActorInfo chDeadBeanstalk; +extern ActorInfo chCCWGobi; +extern ActorInfo chEyrieEgg; +extern ActorInfo chEyrieBaby; +extern ActorInfo chCaterpillar; +extern ActorInfo chEyrieAdult; +extern ActorInfo chCutsceneAdultEyrie; +extern ActorInfo chSnoreZ; +extern ActorInfo chCCWSpringSwitchDoor; +extern ActorInfo chCCWSummerSwitchDoor; +extern ActorInfo chCCWAutumnSwitchDoor; +extern ActorInfo chCCWWinterSwitchDoor; +extern ActorInfo chCCWSpringSwitch; +extern ActorInfo chCCWSummerSwitch; +extern ActorInfo chCCWAutumnSwitch; +extern ActorInfo chCCWWinterSwitch; +extern ActorInfo chNabnutSpring; +extern ActorInfo chNabnutBellyFull; +extern ActorInfo chAutumnOutdoorNabnut; +extern ActorInfo chMoundOfAcorns; +extern ActorInfo chPinkSquirrel; +extern ActorInfo chNabnutBedsheets; +extern ActorInfo chNabnutBed; +extern ActorInfo chNabnut; +extern ActorInfo chNabnutAutumnEatingAcorns; +extern ActorInfo chCarriedAcorn; +extern ActorInfo chGnawtySwimming; +extern ActorInfo chGnawtySummer; +extern ActorInfo chIndoorsGnawty; +extern ActorInfo chGnawtyBoulder; +extern ActorInfo chSnarebear; +extern ActorInfo chDeadSnarebear; +extern ActorInfo chNabnutWindowSpring; +extern ActorInfo chNabnutWindowSummer; +extern ActorInfo chNabnutWindowAutumn; +extern ActorInfo chNabnutWindowWinter; +extern ActorInfo chGrublinHood; +extern ActorInfo gChVacationTextTrigger; +extern ActorInfo chCCWWhipcrackRoomDoor; +extern ActorInfo chNabnutDoor; +extern ActorInfo D_8038F888; +extern ActorInfo chCCWMumbosHut; +extern ActorInfo chGnawtysDen; +extern ActorInfo chGnawtysBed; +extern ActorInfo chGnawtysShelves; + +void code_76C0_ccwGnawtysStuffUpdate(Actor *this); +void code_76C0_ccwWhipcrackRoomDoorUpdate(Actor *this); + +/* .data */ + +#if VERSION == VERSION_PAL +Actor* cc_pal_unk_draw(ActorMarker *, Gfx **, Mtx **, Vtx **); +#endif + +// Unused +ActorInfo chNabnutWindowSpring = { + MARKER_239_CCW_UNKNOWN_NABNUT_WINDOW, ACTOR_25F_CCW_UNKNOWN_NABNUT_WINDOW, ASSET_4FC_MODEL_CCW_UNKNOWN_NABNUT_WINDOW, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +// Unused +ActorInfo chNabnutWindowSummer = { + MARKER_236_CCW_UNKNOWN_NABNUT_WINDOW, ACTOR_260_CCW_UNKNOWN_NABNUT_WINDOW, ASSET_4F9_MODEL_CCW_UNKNOWN_NABNUT_WINDOW, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chNabnutWindowAutumn = { + MARKER_237_CCW_AUTUMN_NABNUT_WINDOW, ACTOR_261_CCW_AUTUMN_NABNUT_WINDOW, ASSET_4FA_MODEL_CCW_AUTUMN_NABNUT_WINDOW, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chNabnutWindowWinter = { + MARKER_238_CCW_WINTER_NABNUT_WINDOW, ACTOR_262_CCW_WINTER_NABNUT_WINDOW, ASSET_4FB_MODEL_CCW_WINTER_NABNUT_WINDOW, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chNabnutDoor = { + MARKER_243_NABNUT_DOOR, ACTOR_2E6_NABNUT_DOOR, ASSET_533_MODEL_NABNUT_DOOR, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCCWWhipcrackRoomDoor = { + MARKER_263_CCW_WHIPCRACK_ROOM_DOOR, ACTOR_2E7_WHIPCRACK_ROOM_DOOR, ASSET_518_MODEL_CCW_WHIPCRACK_ROOM_DOOR, + 0x1, NULL, + code_76C0_ccwWhipcrackRoomDoorUpdate, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCCWMumbosHut = { + MARKER_21E_CCW_MUMBOS_HUT, ACTOR_233_CCW_MUMBOS_HUT, ASSET_3B3_MODEL_CCW_MUMBOS_HUT, + 0x1, NULL, + func_802D3D74, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chGnawtysDen = { + MARKER_26B_GNAWTYS_DEN, ACTOR_2DE_GNAWTYS_DEN, ASSET_531_MODEL_GNAWTYS_DEN, + 0x1, NULL, + code_76C0_ccwGnawtysStuffUpdate, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chGnawtysBed = { + MARKER_26C_GNAWTYS_BED, ACTOR_2DD_GNAWTYS_BED, ASSET_53E_MODEL_GNAWTY_BED, + 0x1, NULL, + code_76C0_ccwGnawtysStuffUpdate, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chGnawtysShelves = { + MARKER_26D_GNAWTYS_SHELVES, ACTOR_2DC_GNAWTYS_SHELVES, ASSET_53F_MODEL_GNAWTY_SHELVES, + 0x1, NULL, + code_76C0_ccwGnawtysStuffUpdate, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_8038F888 = { + MARKER_1CC_CCW_UNKNOWN, ACTOR_318_CCW_UNKNOWN, 0x0, + 0x0, NULL, + func_80325F84, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +/* .code */ +void code_76C0_ccwWhipcrackRoomDoorUpdate(Actor *this){ + if(!this->initialized){ + func_802D3CE8(this); + this->initialized = true; + } + // Anchor: checked live, not just at spawn. + if (levelSpecificFlags_get(LEVEL_FLAG_38_CCW_UNKNOWN)) { + marker_despawn(this->marker); + } +} + +void code_76C0_ccwGnawtysStuffUpdate(Actor *this){ + if(!this->initialized){ + func_802D3D74(this); + this->initialized = true; + // Position For Gnawty's Den + this->position_x = 325.8f; + this->position_y = 600.0f; + this->position_z = 0.0f; + } +} + +void CCW_func_8038DB6C(void) +{ + spawnableActorList_add(&chZubbaDoorSummer, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chZubbaDoorAutumn, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chZubbaHoneyLump, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); + spawnableActorList_add(&chZubba, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&chZubbaDocile, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chCCWBeanstalk, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chDeadBeanstalk, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chCCWGobi, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chEyrieEgg, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chEyrieBaby, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chCaterpillar, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chEyrieAdult, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chCutsceneAdultEyrie, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chSnoreZ, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chCCWSpringSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chCCWSummerSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chCCWAutumnSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chCCWWinterSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chCCWSpringSwitch, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCCWSummerSwitch, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCCWAutumnSwitch, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCCWWinterSwitch, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chNabnutSpring, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chNabnutBellyFull, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chAutumnOutdoorNabnut, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chMoundOfAcorns, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chPinkSquirrel, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chNabnutBedsheets, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chNabnutBed, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chNabnut, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chNabnutAutumnEatingAcorns, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chCarriedAcorn, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chGnawtySwimming, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chGnawtySummer, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chIndoorsGnawty, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chGnawtyBoulder, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chSnarebear, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chDeadSnarebear, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chNabnutWindowSpring, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chNabnutWindowSummer, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chNabnutWindowAutumn, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chNabnutWindowWinter, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chGrublinHood, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&gChVacationTextTrigger, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCCWWhipcrackRoomDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chNabnutDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038F888, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chCCWMumbosHut, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chGnawtysDen, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chGnawtysBed, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chGnawtysShelves, actor_new, ACTOR_FLAG_UNKNOWN_10); +} diff --git a/src/CCW/ch/acorn.c b/src/CCW/ch/acorn.c index 7602302f5..3c7f23894 100644 --- a/src/CCW/ch/acorn.c +++ b/src/CCW/ch/acorn.c @@ -1,101 +1,143 @@ -// BanjoDecomp: code_61E0.c +// BanjoDecomp: CCW/ch/acorn.c #include #include "functions.h" #include "variables.h" +#include "port/Enhancements/Retention/Retention.h" -extern ActorMarker *func_8028E86C(void); +extern ActorMarker *bacarry_getMarkerWithExtraSteps(void); +extern s32 port_remoteCarry_displayUpdate(Actor *this); +extern void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]); typedef struct { - f32 unk0[3]; - f32 unkC[3]; - f32 unk18; -}ActorLocal_CCW_61E0; + f32 position[3]; + f32 unkC[3]; // some kind of distance + f32 unk18; // something time related +} ActorLocal_ChCarriedAcorn; -void func_8038C7A8(Actor *this); +void chCarriedAcorn_update(Actor *this); /* .data */ -ActorInfo D_8038F460 = { 0x1BC, 0x2A9, 0x48E, 0x0, NULL, func_8038C7A8, NULL, actor_draw, 0, 0, 0.8f, 0}; +ActorInfo chCarriedAcorn = { + MARKER_1BC_CARRIED_ACORN, ACTOR_2A9_ACORN, ASSET_48E_MODEL_ACORN, + 0x0, NULL, + chCarriedAcorn_update, NULL, actor_draw, + 0, 0, 0.8f, 0 +}; + +enum chCarriedAcorn_State_e { + CH_CARRIED_ACORN_STATE_0_NOT_INIT, + CH_CARRIED_ACORN_STATE_1_PULL_OUT, + CH_CARRIED_ACORN_STATE_2_HOLDING, + CH_CARRIED_ACORN_STATE_3_TOSS, + CH_CARRIED_ACORN_STATE_4_GIVEN_TO_NABNUT, + CH_CARRIED_ACORN_STATE_5_DESPAWN +}; /* .code */ -void CCW_func_8038C5D0(ActorMarker* marker) { +void chCarriedAcorn_sfxBoing(ActorMarker* marker) { Actor* actor = marker_getActor(marker); func_8030E878(SFX_3F2_BOING, randf2(0.95f, 1.05f), 26000, actor->position, 500.0f, 1000.0f); } -void CCW_func_8038C638(ActorMarker* marker) { +void chCarriedAcorn_sfxBanjoNoise(ActorMarker* marker) { Actor* actor = marker_getActor(marker); func_8030E878(SFX_5_BANJO_LANDING_01, randf2(0.95f, 1.05f), 22000, actor->position, 500.0f, 1000.0f); } -void CCW_func_8038C6A0(Actor *this, s32 next_state) { - ActorLocal_CCW_61E0 *local; +void chCarriedAcorn_setNextState(Actor *this, s32 next_state) { + ActorLocal_ChCarriedAcorn *local; - local = (ActorLocal_CCW_61E0 *)&this->local; - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x25B, 0.0f, 1.0f); - skeletalAnim_setCallback_1(this->unk148, 0.5f, (GenFunction_1)CCW_func_8038C5D0, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.7f, (GenFunction_1)CCW_func_8038C638, (uintptr_t)this->marker); + local = (ActorLocal_ChCarriedAcorn *)&this->local; + if (next_state == CH_CARRIED_ACORN_STATE_1_PULL_OUT) { + skeletalAnim_set(this->unk148, ASSET_25B_ANIM_ACORN_IDLE, 0.0f, 1.0f); + skeletalAnim_setCallback_1(this->unk148, 0.5f, (GenFunction_1)chCarriedAcorn_sfxBoing, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.7f, (GenFunction_1)chCarriedAcorn_sfxBanjoNoise, (uintptr_t)this->marker); } - if (next_state == 3) { - local->unk0[0] = this->position[0]; - local->unk0[1] = this->position[1]; - local->unk0[2] = this->position[2]; - func_8038BC50(local->unkC); + if (next_state == CH_CARRIED_ACORN_STATE_3_TOSS) { + local->position[0] = this->position[0]; + local->position[1] = this->position[1]; + local->position[2] = this->position[2]; + chAutumnOutsideNabnut_getPosition(local->unkC); local->unk18 = 0.0f; } - if (next_state == 4) { + if (next_state == CH_CARRIED_ACORN_STATE_4_GIVEN_TO_NABNUT) { coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); marker_despawn(this->marker); } - if (next_state == 5) { + if (next_state == CH_CARRIED_ACORN_STATE_5_DESPAWN) { marker_despawn(this->marker); } this->state = next_state; } -void func_8038C7A8(Actor *this) { - bool sp4C; - ActorLocal_CCW_61E0 *local; - f32 sp44; - f32 sp38[3]; +void chCarriedAcorn_update(Actor *this) { + bool player_is_carrying_acorn; + ActorLocal_ChCarriedAcorn *local; + f32 time_delta; + f32 player_position[3]; + + local = (ActorLocal_ChCarriedAcorn *)&this->local; + time_delta = time_getDelta(); + + if (port_remoteCarry_displayUpdate(this)) { + return; + } - local = (ActorLocal_CCW_61E0 *)&this->local; - sp44 = time_getDelta(); if (!this->volatile_initialized) { this->volatile_initialized = true; return; } - sp4C = (func_8028E86C() == this->marker); - if (this->state == 0) { - CCW_func_8038C6A0(this, sp4C ? 2 : 1); + player_is_carrying_acorn = (bacarry_getMarkerWithExtraSteps() == this->marker); + if (this->state == CH_CARRIED_ACORN_STATE_0_NOT_INIT) { + if (player_is_carrying_acorn) { + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_2_HOLDING); + } else { + s32 acornSuppress; + port_carriedSync_register(ANCHOR_COLLECTIBLE_ACORN, this->marker, (s32)this->position[0], + (s32)this->position[1], (s32)this->position[2], &acornSuppress); + if (acornSuppress) { + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); + return; + } + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_1_PULL_OUT); + } } - if (this->state == 1) { - player_getPosition(sp38); - if (ml_vec3f_distance(this->position, sp38) < 50.0f) { - func_8028F030(0x2A9); + if (this->state == CH_CARRIED_ACORN_STATE_1_PULL_OUT) { + if (port_carriedSync_consumeRemoteDespawn(ANCHOR_COLLECTIBLE_ACORN, this->marker)) { + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); + return; + } + player_getPosition(player_position); + if (ml_vec3f_distance(this->position, player_position) < 50.0f) { + bacarriedobj_incWithExtraSteps(ACTOR_2A9_ACORN); sfx_playFadeShorthandDefault(SFX_C5_TWINKLY_POP, 1.0f, 25000, this->position, 500, 2500); - CCW_func_8038C6A0(this, 5); + port_carriedSync_onLocalCollect(ANCHOR_COLLECTIBLE_ACORN, this->marker); + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); } } - if (this->state == 2) { + if (this->state == CH_CARRIED_ACORN_STATE_2_HOLDING) { if (this->unk138_21) { - func_8028F010(0x2A9); - CCW_func_8038C6A0(this, 3); - } else if (!sp4C) { - func_8028F050(0x2A9); - CCW_func_8038C6A0(this, 5); + f32 throwTarget[3]; + chAutumnOutsideNabnut_getPosition(throwTarget); + port_anchor_onCarryThrow(this->marker->id, this->position, throwTarget); + bacarriedobj_decWithExtraSteps(ACTOR_2A9_ACORN); + port_carriedSync_onLocalSpend(ANCHOR_COLLECTIBLE_ACORN); + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_3_TOSS); + } else if (!player_is_carrying_acorn) { + bacarriedobj_displayOnHudWithExtraSteps(ACTOR_2A9_ACORN); + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); } } - if (this->state == 3) { - local->unk18 += 3.3333333333333333 * sp44; + if (this->state == CH_CARRIED_ACORN_STATE_3_TOSS) { + local->unk18 += 3.3333333333333333 * time_delta; local->unk18 = (local->unk18 > 1.0) ? 1.0 : local->unk18; - ml_vec3f_interpolate_fast(this->position, local->unk0, local->unkC, local->unk18); + ml_vec3f_interpolate_fast(this->position, local->position, local->unkC, local->unk18); this->position[1] += 50.0f * sinf(local->unk18 * BAD_PI); if (local->unk18 == 1.0) { - CCW_func_8038C6A0(this, 4); + chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_4_GIVEN_TO_NABNUT); } } } diff --git a/src/CCW/ch/adulteyrie.c b/src/CCW/ch/adulteyrie.c new file mode 100644 index 000000000..a67ebde26 --- /dev/null +++ b/src/CCW/ch/adulteyrie.c @@ -0,0 +1,129 @@ +// BanjoDecomp: CCW/ch/adulteyrie.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 unk0; + f32 unk4; + s16 unk8; + s16 unkA; +}Struct_CCW_4530_0; + +void chEyrieAdult_setNextState(Actor *this, s32 next_state); +Actor *chEyrieAdult_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chEyrieAdult_update(Actor *this); + +/* .data */ +// This is the idle Eyrie in the nest +ActorInfo chEyrieAdult = { + MARKER_1B6_EEYRIE_ADULT, ACTOR_2A3_EEYRIE_ADULT, ASSET_487_MODEL_EAGLE_ADULT, + 0x0, NULL, + chEyrieAdult_update, NULL, chEyrieAdult_draw, + 0, 0, 0.0f, 0 +}; + +Struct_CCW_4530_0 chEyrieAdultSFX[] = { + {0.15f, 0.9f, SFX_A5_EYRIE_CRY, 25000}, + {0.3f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, + {0.6f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, + {0.68f, 0.85f, SFX_2_CLAW_SWIPE, 23000}, + {0.75f, 0.9f, SFX_2_CLAW_SWIPE, 28000}, + {0.8f, 0.95f, SFX_2_CLAW_SWIPE, 30000}, + {0.81f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, + {0.86f, 1.0f, SFX_2_CLAW_SWIPE, 31000}, + {0.93f, 1.0f, SFX_2_CLAW_SWIPE, 32000}, + 0 +}; + +enum chEyrieAdult_State_e { + CH_EERYIE_ADULT_STATE_0_NOT_INIT, + CH_EERYIE_ADULT_STATE_1_WAITING, + CH_EERYIE_ADULT_STATE_2_MEET_DIALOG, + CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF, + CH_EERYIE_ADULT_STATE_4_DESPAWN +}; + +/* .code */ +void chEyrieAdult_setMarkerToState3(ActorMarker* marker, enum asset_e text_id, s32 arg2) { + chEyrieAdult_setNextState(marker_getActor(marker), CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF); +} + +void chEyrieAdult_setNextState(Actor *this, s32 next_state) { + if (next_state == CH_EERYIE_ADULT_STATE_1_WAITING) { + skeletalAnim_set(this->unk148, ASSET_199_ANIM_EEYRIE_ADULT_UNK, 0.0f, 6.5f); + } + if (next_state == CH_EERYIE_ADULT_STATE_2_MEET_DIALOG) { + gcdialog_showDialog(VER_SELECT(ASSET_CDC_DIALOG_ADULT_EYRIE_MEET_WINTER, 0x09F1, 0, 0), VER_SELECT(0xA, 0xE, 0, 0), this->position, this->marker, chEyrieAdult_setMarkerToState3, NULL); + } + if (next_state == CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF) { + skeletalAnim_set(this->unk148, ASSET_19A_ANIM_EEYRIE_ADULT_UNK, 0.0f, 7.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 0); + } + if (next_state == CH_EERYIE_ADULT_STATE_4_DESPAWN) { + mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT, 1); + marker_despawn(this->marker); + } + this->state = next_state; +} + +Actor *chEyrieAdult_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor *this; + + this = marker_getActor(marker); + if(this->state == CH_EERYIE_ADULT_STATE_0_NOT_INIT) + return this; + return actor_draw(marker, gfx, mtx, vtx); +} + +void chEyrieAdult_update(Actor *this) { + f32 player_position[3]; + f32 sp50; + f32 sp4C; + Struct_CCW_4530_0 *iPtr; + f32 sp44; + f32 sp40; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT, false); + if( (!fileProgressFlag_get(FILEPROG_E8_AUTMN_EYRIE_FED) || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) + && !volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) + ) { + marker_despawn(this->marker); + } + else{ + chEyrieAdult_setNextState(this, CH_EERYIE_ADULT_STATE_1_WAITING); + } + return; + } + + if (this->state == CH_EERYIE_ADULT_STATE_1_WAITING) { + skeletalAnim_getProgressRange(this->unk148, &sp50, &sp4C); + if ((sp50 < 0.21) && (0.21 <= sp4C)) { + func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); + } + + if ((sp50 < 0.56) && (0.56 <= sp4C)) { + func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); + } + + player_getPosition(player_position); + if (ml_vec3f_distance(this->position, player_position) < 850.0f) { + chEyrieAdult_setNextState(this, CH_EERYIE_ADULT_STATE_2_MEET_DIALOG); + } + } + if (this->state == CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF) { + skeletalAnim_getProgressRange(this->unk148, &sp44, &sp40); + for(iPtr = &chEyrieAdultSFX[0]; iPtr->unk0 > 0.0f; iPtr++){ + if ((sp44 < iPtr->unk0) && (iPtr->unk0 <= sp40)) { + func_8030E878(iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 500.0f, 2500.0f); + } + } + if (skeletalAnim_getLoopCount(this->unk148) > 0) { + chEyrieAdult_setNextState(this, CH_EERYIE_ADULT_STATE_4_DESPAWN); + } + } +} diff --git a/src/CCW/ch/beanstalk.c b/src/CCW/ch/beanstalk.c new file mode 100644 index 000000000..e7723a5fe --- /dev/null +++ b/src/CCW/ch/beanstalk.c @@ -0,0 +1,239 @@ +// BanjoDecomp: CCW/ch/beanstalk.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + s16 waitingAnim; + u8 waitingAnimBehavior; + u8 isInit; + s16 growingAnim; + s16 grownAnim; + s16 completeFileProgress; + s16 completeSpawnsJiggy; +}Struct_CCW_1B20_0; + +typedef struct{ + Struct_CCW_1B20_0 *unk0; +}ActorLocal_CCW_1B20; + +void chCCWBeanstalk_setNextState(Actor *this, s32 next_state); +Actor *chCCWBeanstalk_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chCCWBeanstalk_update(Actor *this); + +enum chCCWBeanstalk_State_e { + CH_CCW_BEANSTALK_STATE_0_NOT_INIT, + CH_CCW_BEANSTALK_STATE_1_WAITING, + CH_CCW_BEANSTALK_STATE_2_GROWING, + CH_CCW_BEANSTALK_STATE_3_GROWN +}; + +/* .data */ +Struct_CCW_1B20_0 D_8038EC40[4] ={ + { + ASSET_173_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_4_STOPPED, + 0, // Is Initialized + ASSET_173_ANIM_BEANSTALK_UNK, + ASSET_181_ANIM_BEANSTALK_UNK, + FILEPROG_E3_CCW_FLOWER_SPRING, + false + }, + { + ASSET_181_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_1_LOOP, + 1, // Is Initialized + ASSET_174_ANIM_BEANSTALK_UNK, + ASSET_182_ANIM_BEANSTALK_UNK, + FILEPROG_E4_CCW_FLOWER_SUMMER, + false + }, + { + ASSET_182_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_1_LOOP, + 1, // Is Initialized + ASSET_175_ANIM_BEANSTALK_UNK, + ASSET_183_ANIM_BEANSTALK_UNK, + FILEPROG_E5_CCW_FLOWER_AUTUMN, + true + }, + { + ASSET_183_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_1_LOOP, + 1, // Is Initialized + 0, + 0, + 0, + false + } +}; + +// Anchor: set during a remote-water replay; skips camera/fanfare/jiggy spawn. +static s32 sFlowerRemoteGrow = 0; + +ActorInfo chCCWBeanstalk = { + MARKER_1B0_CCW_BEANSTALK, ACTOR_29D_CCW_BEANSTALK, ASSET_447_MODEL_CCW_BEANSTALK, + 0x0, NULL, + chCCWBeanstalk_update, NULL, chCCWBeanstalk_draw, + 0, 0, 1.0f, 0 +}; + +f32 chCCWBeanstalkJiggyPosition[3] = {200.0f, 2120.0f, -5570.0f}; + +/* .code */ +void chCCWBeanstalk_spawnJiggy() { + jiggy_spawn(JIGGY_4D_CCW_FLOWER, chCCWBeanstalkJiggyPosition); +} + +void chCCWBeanstalk_setNextStateByMarker(ActorMarker* marker, s32 next_state) { + chCCWBeanstalk_setNextState(marker_getActor(marker), next_state); +} + +void chCCWBeanstalk_setNextState(Actor *this, s32 next_state){ + ActorLocal_CCW_1B20 *local; + f32 phi_f22; + + local = (ActorLocal_CCW_1B20 *)&this->local; + + if (next_state == CH_CCW_BEANSTALK_STATE_1_WAITING) { + this->marker->propPtr->unk8_3 = local->unk0->isInit; + skeletalAnim_set(this->unk148, local->unk0->waitingAnim, 0.0f, 5.0f); + skeletalAnim_setBehavior(this->unk148, local->unk0->waitingAnimBehavior); + } + if (next_state == CH_CCW_BEANSTALK_STATE_2_GROWING) { + if (gsworld_getMap() == MAP_43_CCW_SPRING && !sFlowerRemoteGrow) { + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + } + fileProgressFlag_set(local->unk0->completeFileProgress, true); + skeletalAnim_set(this->unk148, local->unk0->growingAnim, 0.0f, 6.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + if (gsworld_getMap() == MAP_43_CCW_SPRING && !sFlowerRemoteGrow) { + func_80324E38(0.0f, 3); + } + if (!sFlowerRemoteGrow) { + timed_setStaticCameraToNode(0.0f, 0); + } + for( phi_f22 = 0.0f; phi_f22 <= 1.0f; phi_f22 += 0.1) { + timed_playSfx(phi_f22 * 5.7, 0x2C, phi_f22 * 0.3 + 0.7, (s32) (32000.0f - phi_f22 * 5000.0f)); + } + if (local->unk0->completeSpawnsJiggy != false) { + if (!sFlowerRemoteGrow) { + timed_setStaticCameraToNode(6.0f, 1); + timedFunc_set_0(6.1f, (GenFunction_0)chCCWBeanstalk_spawnJiggy); + } + timedFunc_set_2( + 8.0f, + (GenFunction_2)chCCWBeanstalk_setNextStateByMarker, + (uintptr_t)this->marker, + CH_CCW_BEANSTALK_STATE_3_GROWN); + } else { + if (gsworld_getMap() == MAP_43_CCW_SPRING && !sFlowerRemoteGrow) { + timed_exitStaticCamera(7.0f); + func_80324E38(7.0f, 0); + } + timedFunc_set_2( + 7.0f, + (GenFunction_2)chCCWBeanstalk_setNextStateByMarker, + (uintptr_t)this->marker, + CH_CCW_BEANSTALK_STATE_3_GROWN); + } + } + + if (next_state == CH_CCW_BEANSTALK_STATE_3_GROWN) { + this->marker->propPtr->unk8_3 = true; + skeletalAnim_set(this->unk148, local->unk0->grownAnim, 0.1f, 5.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + this->state = next_state; +} + +s32 func_80388260(ActorMarker *marker, s32 arg1){ + return marker->unk40_31 != 1; +} + +void chCCWBeanstalk_feed(ActorMarker *marker, ActorMarker *other_marker) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); +} + +void chCCWBeanstalk_spawnBeanstalk(ActorMarker* marker, ActorMarker *other_marker) { + Actor* actor = marker_getActor(marker); + + // [port] v1.1 fix: don't allow re-planting flower in Spring after it's already been planted + if (EventSystem_Should(VB_CCW_FLOWER_REPLANT, + gsworld_getMap() == MAP_43_CCW_SPRING && actor->state == CH_CCW_BEANSTALK_STATE_1_WAITING && + !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING))) { + chCCWBeanstalk_setNextState(actor, CH_CCW_BEANSTALK_STATE_2_GROWING); + } +} + +Actor *chCCWBeanstalk_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + s32 sp18; + + this = marker_getActor(marker); + if ((this->state == CH_CCW_BEANSTALK_STATE_1_WAITING) + && !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING)) + { + return func_80325340(marker, gfx, mtx, vtx); + } + + if ((skeletalAnim_getAnimId(this->unk148) == 0x175) + && (0.49 <= skeletalAnim_getProgress(this->unk148))) + { + sp18 = 1; + } else { + sp18 = 0; + } + sp18 = (skeletalAnim_getAnimId(this->unk148) == 0x183)? 1 : sp18; + modelRender_setAppendageVisibility(3, sp18); + modelRender_setAppendageVisibility(4, sp18); + return actor_draw(marker, gfx, mtx, vtx); +} + +void chCCWBeanstalk_growBeanstalk() { + Actor* actor = actorArray_findActorFromActorId(ACTOR_29D_CCW_BEANSTALK); + if (actor && actor->state == CH_CCW_BEANSTALK_STATE_1_WAITING) { + chCCWBeanstalk_setNextState(actor, CH_CCW_BEANSTALK_STATE_2_GROWING); + } +} + +bool chCCWBeanstalk_hasSpawned() { + Actor* actor = actorArray_findActorFromActorId(ACTOR_29D_CCW_BEANSTALK); + if (actor && actor->state == CH_CCW_BEANSTALK_STATE_2_GROWING) { + return true; + } + return false; +} + +void chCCWBeanstalk_update(Actor *this) { + ActorLocal_CCW_1B20 *local; + + local = (ActorLocal_CCW_1B20 *)&this->local; + if (!this->volatile_initialized) { + this->volatile_initialized = true; + func_803300C0(this->marker, (s32 (*)(ActorMarker *, ActorMarker *))func_80388260); + marker_setCollisionScripts(this->marker, NULL, chCCWBeanstalk_feed, chCCWBeanstalk_spawnBeanstalk); + actor_collisionOn(this); + if (!jiggyscore_isSpawned(JIGGY_4D_CCW_FLOWER)) { + fileProgressFlag_set(FILEPROG_E5_CCW_FLOWER_AUTUMN, false); + } + + for(local->unk0 = &D_8038EC40[0]; local->unk0 < D_8038EC40 + 3; local->unk0++){ + if(!fileProgressFlag_get(local->unk0->completeFileProgress)){ + break; + } + } + + if (!fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING) + && (gsworld_getMap() != MAP_43_CCW_SPRING)) + { + marker_despawn(this->marker); + } + else{ + chCCWBeanstalk_setNextState(this, CH_CCW_BEANSTALK_STATE_1_WAITING); + } + return; + } + + if ((this->state == CH_CCW_BEANSTALK_STATE_1_WAITING) && EventSystem_Should(VB_CCW_FLOWER_REMOTE_GROW, false, (s32)local->unk0->completeFileProgress)) { + sFlowerRemoteGrow = 1; + chCCWBeanstalk_setNextState(this, CH_CCW_BEANSTALK_STATE_2_GROWING); + sFlowerRemoteGrow = 0; + } +} diff --git a/src/CCW/ch/nabnut_summer.c b/src/CCW/ch/bellyfullnabnut.c similarity index 61% rename from src/CCW/ch/nabnut_summer.c rename to src/CCW/ch/bellyfullnabnut.c index 8388d0c15..135c17016 100644 --- a/src/CCW/ch/nabnut_summer.c +++ b/src/CCW/ch/bellyfullnabnut.c @@ -1,19 +1,19 @@ -// BanjoDecomp: code_50D0.c +// BanjoDecomp: CCW/ch/bellyfullnabnut.c #include #include "functions.h" #include "variables.h" -void func_8038B87C(Actor *this); +void chNabnutBellyFull_update(Actor *this); /* .data */ -ActorInfo D_8038F300 = { - 0x1BA, 0x2A7, 0x503, +ActorInfo chNabnutBellyFull = { + MARKER_1BA_NABNUT_FULL_BELLY, ACTOR_2A7_NABNUT_FULL_BELLY, ASSET_503_MODEL_NABNUT_BELLY_FULL, 0x0, NULL, - func_8038B87C, NULL, actor_draw, + chNabnutBellyFull_update, NULL, actor_draw, 0, 0, 2.0f, 0 }; -s32 D_8038F324[] = { +s32 chNabnutBellyFullSFX[] = { SFX_97_BLUBBER_BURPS, SFX_3E_POOP_NOISE, SFX_F6_BLUBBER_TALKING_2, @@ -23,23 +23,39 @@ s32 D_8038F324[] = { 0 }; +enum ChNabnutBellyFull_State_e { + CH_NABNUT_BELLY_FULL_STATE_1_UNK = 1 +}; + /* .code */ void func_8038B4C0(ActorMarker *marker) { Actor *this; - static s32 D_8038F340 = 0; + static s32 chNabnutBellyFullSFXIndex = 0; this = marker_getActor(marker); - func_8030E878(D_8038F324[D_8038F340], randf2(1.1f, 1.2f), (s32) randf2(31000.0f, 32000.0f), this->position, 500.0f, 2500.0f); - D_8038F340++; - if (D_8038F324[D_8038F340] == 0) { - D_8038F340 = 0; + func_8030E878( + chNabnutBellyFullSFX[chNabnutBellyFullSFXIndex], + randf2(1.1f, 1.2f), + (s32) randf2(31000.0f, 32000.0f), + this->position, + 500.0f, + 2500.0f); + chNabnutBellyFullSFXIndex++; + if (chNabnutBellyFullSFX[chNabnutBellyFullSFXIndex] == 0) { + chNabnutBellyFullSFXIndex = 0; } } void func_8038B58C(ActorMarker* marker) { Actor* actor = marker_getActor(marker); - func_8030E878(0x81, randf2(1.0f, 1.1f), (s32) randf2(31000.0f, 32000.0f), actor->position, 500.0f, 2500.0f); + func_8030E878( + SFX_81_UUU, + randf2(1.0f, 1.1f), + (s32) randf2(31000.0f, 32000.0f), + actor->position, + 500.0f, + 2500.0f); } void func_8038B610(ActorMarker* marker) { @@ -77,23 +93,23 @@ void func_8038B6DC(ActorMarker *marker) { skeletalAnim_setCallback_1(this->unk148, 0.9f, (GenFunction_1)func_8038B6DC, (uintptr_t)this->marker); } -void func_8038B814(Actor *this, s32 next_state) { - if (next_state == 1) { +void chNabnutBellyFull_setNextState(Actor *this, s32 next_state) { + if (next_state == CH_NABNUT_BELLY_FULL_STATE_1_UNK) { skeletalAnim_set(this->unk148, 0x22B, 0.2f, 11.0f); func_8038B6DC(this->marker); } this->state = next_state; } -void func_8038B87C(Actor *this) { +void chNabnutBellyFull_update(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; this->has_met_before = false; - func_8038B814(this, 1); + chNabnutBellyFull_setNextState(this, CH_NABNUT_BELLY_FULL_STATE_1_UNK); } if (!this->has_met_before && func_803292E0(this)) { - this->has_met_before = true; - gcdialog_showDialog(0xCC9, 0, NULL, NULL, NULL, NULL); + this->has_met_before = TRUE; + gcdialog_showDialog(VER_SELECT(ASSET_CC9_DIALOG_NABNUT_MEET_SUMMER, 0x09DE, 0, 0), 0, NULL, NULL, NULL, NULL); } func_8028E668(this->position, 300.0f, -50.0f, 120.0f); } diff --git a/src/CCW/ch/caterpillar.c b/src/CCW/ch/caterpillar.c index 90049e190..51c8f0777 100644 --- a/src/CCW/ch/caterpillar.c +++ b/src/CCW/ch/caterpillar.c @@ -1,15 +1,18 @@ -// BanjoDecomp: code_3DA0.c +// BanjoDecomp: CCW/ch/caterpillar.c #include #include "functions.h" #include "variables.h" +#include "port/Enhancements/Retention/Retention.h" -extern ActorMarker *func_8028E86C(void); +extern ActorMarker *bacarry_getMarkerWithExtraSteps(void); extern void func_8028F7D4(f32, f32); +extern s32 port_remoteCarry_displayUpdate(Actor *this); +extern void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]); typedef struct { - f32 unk0[3]; - f32 unkC[3]; - f32 unk18[3]; + f32 position[3]; + f32 unkC[3]; // some kind of distance + f32 unk18[3]; // something time related f32 unk24; } ActorLocal_Caterpillar; @@ -24,41 +27,52 @@ ActorInfo chCaterpillar = { 0, 0, 1.0f, 0 }; +enum chCaterpillar_State_e { + CH_CATERPILLAR_STATE_0_NOT_INIT, + CH_CATERPILLAR_STATE_1_PULL_OUT, + CH_CATERPILLAR_STATE_2_HOLDING, + CH_CATERPILLAR_STATE_3_TOSS, + CH_CATERPILLAR_STATE_4_GIVEN_TO_EEYRIE, + CH_CATERPILLAR_STATE_5_DESPAWN +}; + /* .code */ f32 func_8038A190(Actor *this, f32 *arg1) { - f32 temp_f0; - f32 temp_f2; - - temp_f0 = mapModel_getFloorY(arg1); - temp_f2 = this->position[1]; - if (((temp_f2 + 50.0f) < temp_f0) || (temp_f0 < (temp_f2 - 50.0f))) { - return temp_f2; + f32 floor_y_position; + f32 caterpillar_y_position; + + floor_y_position = mapModel_getFloorY(arg1); + caterpillar_y_position = this->position[1]; + if (((caterpillar_y_position + 50.0f) < floor_y_position) + || (floor_y_position < (caterpillar_y_position - 50.0f))) + { + return caterpillar_y_position; } - return temp_f0; + return floor_y_position; } void chcaterpillar_setState(Actor *this, s32 next_state) { ActorLocal_Caterpillar *local = (ActorLocal_Caterpillar *)&this->local; - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x18D, 0.0f, randf2(1.9f, 2.1f)); + if (next_state == CH_CATERPILLAR_STATE_1_PULL_OUT) { + skeletalAnim_set(this->unk148, ASSET_18D_ANIM_CATERPILLAR_UNK, 0.0f, randf2(1.9f, 2.1f)); } - if (next_state == 2) { + if (next_state == CH_CATERPILLAR_STATE_2_HOLDING) { func_8028F7D4(-25.0f, 90.0f); - skeletalAnim_set(this->unk148, 0x18E, 0.2f, 2.0f); + skeletalAnim_set(this->unk148, ASSET_18E_ANIM_CATERPILLAR_IDLE, 0.2f, 2.0f); } - if (next_state == 3) { - skeletalAnim_set(this->unk148, 0x18E, 0.2f, 2.0f); + if (next_state == CH_CATERPILLAR_STATE_3_TOSS) { + skeletalAnim_set(this->unk148, ASSET_18E_ANIM_CATERPILLAR_IDLE, 0.2f, 2.0f); local->unkC[0] = this->position[0]; local->unkC[1] = this->position[1]; local->unkC[2] = this->position[2]; local->unk24 = 0.0f; } - if (next_state == 4) { + if (next_state == CH_CATERPILLAR_STATE_4_GIVEN_TO_EEYRIE) { coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); marker_despawn(this->marker); } - if (next_state == 5) { + if (next_state == CH_CATERPILLAR_STATE_5_DESPAWN) { actor_collisionOff(this); } this->state = next_state; @@ -66,16 +80,16 @@ void chcaterpillar_setState(Actor *this, s32 next_state) { Actor* chcaterpillar_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - if(this->state == 5){ + if(this->state == CH_CATERPILLAR_STATE_5_DESPAWN){ return func_80325340(marker, gfx, mtx, vtx); } return actor_draw(marker, gfx, mtx, vtx); } void chcaterpillar_update(Actor *this){ - bool sp8C; + bool player_is_carrying_caterpillar; ActorLocal_Caterpillar *local = (ActorLocal_Caterpillar *)&this->local; - f32 sp84; + f32 time_delta; enum map_e map_id; f32 sp74[3]; f32 sp70; @@ -86,48 +100,63 @@ void chcaterpillar_update(Actor *this){ f32 sp54[3]; int i; - sp8C = func_8028E86C() == this->marker; - sp84 = time_getDelta(); + if (port_remoteCarry_displayUpdate(this)) { + return; + } + + player_is_carrying_caterpillar = bacarry_getMarkerWithExtraSteps() == this->marker; + time_delta = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = true; - local->unk0[0] = this->position[0]; - local->unk0[1] = this->position[1]; - local->unk0[2] = this->position[2]; - if(sp8C){ - chcaterpillar_setState(this, 2); + local->position[0] = this->position[0]; + local->position[1] = this->position[1]; + local->position[2] = this->position[2]; + if(player_is_carrying_caterpillar){ + chcaterpillar_setState(this, CH_CATERPILLAR_STATE_2_HOLDING); } else{//L8038A408 map_id = gsworld_getMap(); if ( !fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED) || ( map_id == MAP_45_CCW_AUTUMN && !fileProgressFlag_get(FILEPROG_E7_SUMMER_EYRIE_FED)) ) { - chcaterpillar_setState(this, 5); + chcaterpillar_setState(this, CH_CATERPILLAR_STATE_5_DESPAWN); } else { - chcaterpillar_setState(this, 1); + s32 wormSuppress; + port_carriedSync_register(ANCHOR_COLLECTIBLE_WORM, this->marker, (s32)this->position[0], + (s32)this->position[1], (s32)this->position[2], &wormSuppress); + if (wormSuppress) { + marker_despawn(this->marker); + return; + } + chcaterpillar_setState(this, CH_CATERPILLAR_STATE_1_PULL_OUT); }//L8038A45C } }//L8038A45C - if(this->state == 1){ + if(this->state == CH_CATERPILLAR_STATE_1_PULL_OUT){ + if(port_carriedSync_consumeRemoteDespawn(ANCHOR_COLLECTIBLE_WORM, this->marker)){ + marker_despawn(this->marker); + return; + } skeletalAnim_getProgressRange(this->unk148, &sp64, &sp60); player_getPosition(sp74); - if(ml_vec3f_distance(this->position, local->unk0) < 10.0f){ + if(ml_vec3f_distance(this->position, local->position) < 10.0f){ for(i = 0; i < 10; i++){ - local->unk0[0] = randf2(-300.0f, 300.0f) + this->position_x; - local->unk0[1] = this->position_y; - local->unk0[2] = randf2(-300.0f, 300.0f) + this->position_z; - if( !(ml_vec3f_distance(local->unk0, this->position) < 50.0f) && func_80329210(this, &local->unk0)) + local->position[0] = randf2(-300.0f, 300.0f) + this->position_x; + local->position[1] = this->position_y; + local->position[2] = randf2(-300.0f, 300.0f) + this->position_z; + if( !(ml_vec3f_distance(local->position, this->position) < 50.0f) && func_80329210(this, &local->position)) break; }//L8038A544 if(i == 10){ - local->unk0[0] = this->position[0];\ - local->unk0[1] = this->position[1];\ - local->unk0[2] = this->position[2]; + local->position[0] = this->position[0];\ + local->position[1] = this->position[1];\ + local->position[2] = this->position[2]; }//L8038A564 if (i); - local->unk0[1] = func_8038A190(this, local->unk0); + local->position[1] = func_8038A190(this, local->position); }//L8038A570 if(sp64 <= 0.1 && 0.1 < sp60){ @@ -135,8 +164,8 @@ void chcaterpillar_update(Actor *this){ }//L8038A5EC if(0.65 < sp60){ - func_80258A4C(this->position, this->yaw - 90.0f, local->unk0, &sp70, &sp6C, &sp68); - this->yaw += (sp68*100.0f)*sp84; + func_80258A4C(this->position, this->yaw - 90.0f, local->position, &sp70, &sp6C, &sp68); + this->yaw += (sp68*100.0f) * time_delta; }//L8038A668 if(sp60 <= 0.4){ @@ -144,45 +173,50 @@ void chcaterpillar_update(Actor *this){ sp54[2] = 0.0f; sp54[0] = 65.0f; ml_vec3f_yaw_rotate_copy(sp54, sp54, this->yaw - 90.0f); - this->position[0] += sp84*sp54[0]; - this->position[2] += sp84*sp54[2]; + this->position[0] += time_delta * sp54[0]; + this->position[2] += time_delta * sp54[2]; if(this->marker->unk14_21){ this->position[1] = func_8038A190(this, this->position); } }//L8038A714 if(ml_vec3f_distance(this->position, sp74) < 50.0f){ - func_8028F030(ACTOR_2A2_CATERPILLAR); + bacarriedobj_incWithExtraSteps(ACTOR_2A2_CATERPILLAR); if(!volatileFlag_get(VOLATILE_FLAG_B2_HAS_COLLECTED_CATERPILLAR)){ - gcdialog_showDialog(ASSET_CC7_DIALOG_CATERPILLAR_COLLECT, 4, NULL, NULL, NULL, NULL); - volatileFlag_set(VOLATILE_FLAG_B2_HAS_COLLECTED_CATERPILLAR, true); + gcdialog_showDialog(VER_SELECT(ASSET_CC7_DIALOG_CATERPILLAR_COLLECT, 0x09DC, 0, 0), 4, NULL, NULL, NULL, NULL); + volatileFlag_set(VOLATILE_FLAG_B2_HAS_COLLECTED_CATERPILLAR, TRUE); } sfx_playFadeShorthandDefault(SFX_C5_TWINKLY_POP, 1.0f, 25000, this->position, 0x1f4, 0x9c4); + port_carriedSync_onLocalCollect(ANCHOR_COLLECTIBLE_WORM, this->marker); marker_despawn(this->marker); } }//L8038A794 - if(this->state == 2){ + if(this->state == CH_CATERPILLAR_STATE_2_HOLDING){ if(this->unk138_21){ - func_8028F010(ACTOR_2A2_CATERPILLAR); - chcaterpillar_setState(this, 3); + f32 throwTarget[3]; + func_80389BD8(throwTarget); + port_anchor_onCarryThrow(this->marker->id, this->position, throwTarget); + bacarriedobj_decWithExtraSteps(ACTOR_2A2_CATERPILLAR); + port_carriedSync_onLocalSpend(ANCHOR_COLLECTIBLE_WORM); + chcaterpillar_setState(this, CH_CATERPILLAR_STATE_3_TOSS); } - else if(!sp8C){ - func_8028F050(ACTOR_2A2_CATERPILLAR); + else if(!player_is_carrying_caterpillar){ + bacarriedobj_displayOnHudWithExtraSteps(ACTOR_2A2_CATERPILLAR); marker_despawn(this->marker); } }//L8038A804 - if(this->state == 3){ + if(this->state == CH_CATERPILLAR_STATE_3_TOSS){ func_80389BD8(local->unk18); - local->unk24 += 3.3333333333333335*sp84; + local->unk24 += 3.3333333333333335 * time_delta; local->unk24 = (1.0 < local->unk24) ? 1.0 : local->unk24; ml_vec3f_interpolate_fast(this->position, local->unkC, local->unk18, local->unk24); - this->position[1] += 50.0f*sinf(local->unk24*3.141592654); + this->position[1] += 50.0f*sinf(local->unk24 * 3.141592654); if(1.0 == local->unk24){ - chcaterpillar_setState(this, 4); + chcaterpillar_setState(this, CH_CATERPILLAR_STATE_4_GIVEN_TO_EEYRIE); } }//L8038A8FC } diff --git a/src/CCW/ch/gobi_ccw.c b/src/CCW/ch/ccwgobi.c similarity index 55% rename from src/CCW/ch/gobi_ccw.c rename to src/CCW/ch/ccwgobi.c index 4080d3459..3b1525d25 100644 --- a/src/CCW/ch/gobi_ccw.c +++ b/src/CCW/ch/ccwgobi.c @@ -1,89 +1,110 @@ -// BanjoDecomp: code_2270.c +// BanjoDecomp: CCW/ch/ccwgobi.c #include #include "functions.h" #include "variables.h" typedef struct{ s16 map_id; - s16 unk2; - s16 unk4; - s16 unk6; -}Struct_CCW_2270_0; + s16 summerMeetDialog; + s16 summerCompleteDialog; + s16 autumnCompleteDialog; +} CH_CCW_Gobi_Dialogs; typedef struct{ - Struct_CCW_2270_0 *unk0; - SkeletalAnimation *unk4; + CH_CCW_Gobi_Dialogs *dialogs; + SkeletalAnimation *skeletal_anim; BKModelBin *spit_model; -}ActorLocal_chGobiCCW; +} ActorLocal_chGobiCCW; -void CCW_func_8038868C(Actor *this, s32 next_state); +void chCCWGobi_setState(Actor *this, s32 next_state); Actor *chGobiCCW_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chGobiCCW_update(Actor *this); /* .data */ -Struct_CCW_2270_0 D_8038ECD0[] = { - {MAP_44_CCW_SUMMER, 0xCDE, 0xCDF, 0x000}, - {MAP_45_CCW_AUTUMN, 0x000, 0x000, 0xCE0}, - 0 +CH_CCW_Gobi_Dialogs chCCWGobiDialogs[] = { + { + MAP_44_CCW_SUMMER, + VER_SELECT(ASSET_CDE_DIALOG_CCW_GOBI_MEET_SUMMER, 0x09F3, 0, 0), + VER_SELECT(ASSET_CDF_DIALOG_CCW_GOBI_COMPLETE_SUMMER, 0x09F4, 0, 0), + 0 // [port] decomp uses NULL; dialog fields are asset ids, not pointers + }, + { + MAP_45_CCW_AUTUMN, + 0, + 0, + VER_SELECT(ASSET_CE0_DIALOG_CCW_GOBI_COMPLETE_FALL, 0x09F5, 0, 0) + }, + { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion }; -ActorInfo D_8038ECE8 = { +ActorInfo chCCWGobi = { MARKER_1B1_CCW_GOBI, ACTOR_29E_CCW_GOBI, ASSET_3E0_MODEL_GOBI, 0x0, NULL, chGobiCCW_update, chGobiCCW_update, chGobiCCW_draw, 0, 0, 1.0f, 0 }; +enum chccwgobi_state_e { + CH_CCW_GOBI_STATE_0_NOT_INIT, + CH_CCW_GOBI_STATE_1_WAITING, + CH_CCW_GOBI_STATE_2_SPITTING, + CH_CCW_GOBI_STATE_3_GROW_BEANSTALK, + CH_CCW_GOBI_STATE_4_DONE_SPITTING, + CH_CCW_GOBI_STATE_5_GETTING_UP, + CH_CCW_GOBI_STATE_6_RUN_AWAY, + CH_CCW_GOBI_STATE_7_DESPAWN +}; + /* .code */ -void CCW_func_80388660(ActorMarker* marker, s32 arg1) { - CCW_func_8038868C(marker_getActor(marker), arg1); +void chCCWGobi_setStateByMarker(ActorMarker* marker, s32 arg1) { + chCCWGobi_setState(marker_getActor(marker), arg1); } -void CCW_func_8038868C(Actor *this, s32 next_state) { +void chCCWGobi_setState(Actor *this, s32 next_state) { ActorLocal_chGobiCCW *local; local = (ActorLocal_chGobiCCW*)&this->local; - if (next_state == 1) { + if (next_state == CH_CCW_GOBI_STATE_1_WAITING) { skeletalAnim_set(this->unk148, ASSET_F4_ANIM_GOBI_IDLE, 0.5f, 12.0f); } - if (next_state == 2) { - if (local->unk0->unk4 != 0) { - gcdialog_showDialog(local->unk0->unk4, 4, NULL, NULL, NULL, NULL); + if (next_state == CH_CCW_GOBI_STATE_2_SPITTING) { + if (local->dialogs->summerCompleteDialog != 0) { + gcdialog_showDialog(local->dialogs->summerCompleteDialog, 4, NULL, NULL, NULL, NULL); } skeletalAnim_set(this->unk148, ASSET_FC_ANIM_GOBI_SPITTING, 0.2f, 3.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - skeletalAnim_set(local->unk4, ASSET_100_ANIM_GOBI_SPIT, 0.0f, 3.0f); - skeletalAnim_setBehavior(local->unk4, 2); + skeletalAnim_set(local->skeletal_anim, ASSET_100_ANIM_GOBI_SPIT, 0.0f, 3.0f); + skeletalAnim_setBehavior(local->skeletal_anim, 2); func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.0f, (gsworld_getMap() == MAP_44_CCW_SUMMER) ? 1 : 2); timed_playSfx(0.05f, SFX_84_GOBI_CRYING, 1.1f, 32000); timed_playSfx(0.8f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(1.4f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(2.0f, SFX_4B_GULPING, 0.8f, 28000); - timedFunc_set_2(3.2f, (GenFunction_2) CCW_func_80388660, (uintptr_t)this->marker, 3); + timedFunc_set_2(3.2f, (GenFunction_2) chCCWGobi_setStateByMarker, (uintptr_t)this->marker, 3); } - if (next_state == 3) { - func_803883F4(); + if (next_state == CH_CCW_GOBI_STATE_3_GROW_BEANSTALK) { + chCCWBeanstalk_growBeanstalk(); } - if (next_state == 4) { + if (next_state == CH_CCW_GOBI_STATE_4_DONE_SPITTING) { skeletalAnim_set(this->unk148, ASSET_176_ANIM_GOBI_YAWN, 0.5f, 4.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); } - if (next_state == 5) { - if (local->unk0->unk6 != 0) { - gcdialog_showDialog((s32) local->unk0->unk6, 4, NULL, NULL, NULL, NULL); + if (next_state == CH_CCW_GOBI_STATE_5_GETTING_UP) { + if (local->dialogs->autumnCompleteDialog != NULL) { + gcdialog_showDialog((s32) local->dialogs->autumnCompleteDialog, 4, NULL, NULL, NULL, NULL); } skeletalAnim_set(this->unk148, ASSET_FD_ANIM_GOBI2_GETTING_UP, 0.23f, 0.5f); timed_setStaticCameraToNode(0.0f, 3); } - if (next_state == 6) { + if (next_state == CH_CCW_GOBI_STATE_6_RUN_AWAY) { skeletalAnim_set(this->unk148, ASSET_F8_ANIM_GOBI_RUNNING, 0.1f, 0.71f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); } - if (next_state == 7) { + if (next_state == CH_CCW_GOBI_STATE_7_DESPAWN) { timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); marker_despawn(this->marker); @@ -94,9 +115,9 @@ void CCW_func_8038868C(Actor *this, s32 next_state) { void func_8038894C(ActorMarker* marker, ActorMarker *other_marker) { Actor* actor = marker_getActor(marker); - if (actor->state == 1) { + if (actor->state == CH_CCW_GOBI_STATE_1_WAITING) { actor_collisionOff(actor); - timedFunc_set_2(0.5f, (GenFunction_2)CCW_func_80388660, (uintptr_t)actor->marker, 2); + timedFunc_set_2(0.5f, (GenFunction_2)chCCWGobi_setStateByMarker, (uintptr_t)actor->marker, 2); } } @@ -113,7 +134,7 @@ Actor *chGobiCCW_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ sp2C[1] = this->yaw; sp2C[2] = this->roll; - modelRender_setBoneTransformList(skeletalAnim_getBoneTransformList(local->unk4)); + modelRender_setBoneTransformList(skeletalAnim_getBoneTransformList(local->skeletal_anim)); modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); modelRender_draw(gfx, mtx, this->position, sp2C, 1.0f, NULL, local->spit_model); } @@ -123,13 +144,13 @@ Actor *chGobiCCW_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ void chGobiCCW_free(Actor *this){ ActorLocal_chGobiCCW *local = (ActorLocal_chGobiCCW*)&this->local; - skeletalAnim_free(local->unk4); + skeletalAnim_free(local->skeletal_anim); assetcache_release(local->spit_model); } void chGobiCCW_update(Actor *this) { ActorLocal_chGobiCCW *local; - f32 sp48[3]; + f32 player_position[3]; f32 sp44; f32 sp40; @@ -139,54 +160,56 @@ void chGobiCCW_update(Actor *this) { this->marker->propPtr->unk8_3 = true; this->marker->actorFreeFunc = chGobiCCW_free; this->has_met_before = false; - local->unk4 = skeletalAnim_new(); + local->skeletal_anim = skeletalAnim_new(); local->spit_model = assetcache_get(ASSET_3F3_MODEL_GOBI_SPIT); marker_setCollisionScripts(this->marker, NULL, func_8038894C, NULL); if(!jiggyscore_isSpawned(JIGGY_4D_CCW_FLOWER)) { fileProgressFlag_set(FILEPROG_E5_CCW_FLOWER_AUTUMN, false); } - local->unk0 = &D_8038ECD0[0]; - while((local->unk0->map_id != 0) && (gsworld_getMap() != local->unk0->map_id)) { - local->unk0++; + local->dialogs = &chCCWGobiDialogs[0]; + while((local->dialogs->map_id != NULL) && (gsworld_getMap() != local->dialogs->map_id)) { + local->dialogs++; } if( (gsworld_getMap() == MAP_44_CCW_SUMMER) && fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING) && !fileProgressFlag_get(FILEPROG_E4_CCW_FLOWER_SUMMER)) { - CCW_func_8038868C(this, 1); + chCCWGobi_setState(this, CH_CCW_GOBI_STATE_1_WAITING); } else if( (gsworld_getMap() == MAP_45_CCW_AUTUMN) && fileProgressFlag_get(FILEPROG_E4_CCW_FLOWER_SUMMER) && !fileProgressFlag_get(FILEPROG_E5_CCW_FLOWER_AUTUMN) ) { - CCW_func_8038868C(this, 1); + chCCWGobi_setState(this, CH_CCW_GOBI_STATE_1_WAITING); } else{ marker_despawn(this->marker); } return; } - if(this->state == 1){ + if(this->state == CH_CCW_GOBI_STATE_1_WAITING){ if (!this->has_met_before) { - player_getPosition(sp48); - if (ml_vec3f_distance(this->position, sp48) < 600.0f) { - if (local->unk0->unk2 != 0) { - gcdialog_showDialog((s32) local->unk0->unk2, 4, NULL, NULL, NULL, NULL); + player_getPosition(player_position); + if (ml_vec3f_distance(this->position, player_position) < 600.0f) { + if (local->dialogs->summerMeetDialog != NULL) { + gcdialog_showDialog((s32) local->dialogs->summerMeetDialog, 4, NULL, NULL, NULL, NULL); } this->has_met_before = true; } } } - if (this->state == 2) { - skeletalAnim_update(local->unk4, time_getDelta(), 1); + if (this->state == CH_CCW_GOBI_STATE_2_SPITTING) { + skeletalAnim_update(local->skeletal_anim, time_getDelta(), 1); } - if(this->state == 3){ - if (!func_80388438()) { + if(this->state == CH_CCW_GOBI_STATE_3_GROW_BEANSTALK){ + if (!chCCWBeanstalk_hasSpawned()) { if (gsworld_getMap() == MAP_44_CCW_SUMMER) { - CCW_func_8038868C(this, 4); + chCCWGobi_setState(this, CH_CCW_GOBI_STATE_4_DONE_SPITTING); } else { - CCW_func_8038868C(this, 5); + chCCWGobi_setState(this, CH_CCW_GOBI_STATE_5_GETTING_UP); } } } - if (this->state == 4) { - if ((skeletalAnim_getAnimId(this->unk148) == ASSET_176_ANIM_GOBI_YAWN) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { + if (this->state == CH_CCW_GOBI_STATE_4_DONE_SPITTING) { + if ((skeletalAnim_getAnimId(this->unk148) == ASSET_176_ANIM_GOBI_YAWN) + && (skeletalAnim_getLoopCount(this->unk148) > 0)) + { skeletalAnim_set(this->unk148, ASSET_177_ANIM_GOBI_SLEEP, 0.1f, 4.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); } @@ -202,16 +225,16 @@ void chGobiCCW_update(Actor *this) { } } - if (this->state == 5){ + if (this->state == CH_CCW_GOBI_STATE_5_GETTING_UP){ if(skeletalAnim_getLoopCount(this->unk148) > 0) { - CCW_func_8038868C(this, 6); + chCCWGobi_setState(this, CH_CCW_GOBI_STATE_6_RUN_AWAY); } } - if (this->state == 6) { + if (this->state == CH_CCW_GOBI_STATE_6_RUN_AWAY) { actor_update_func_80326224(this); if (0.99 < (f64) this->unk48) { - CCW_func_8038868C(this, 7); + chCCWGobi_setState(this, CH_CCW_GOBI_STATE_7_DESPAWN); } } } diff --git a/src/CCW/ch/cutsceneadulteyrie.c b/src/CCW/ch/cutsceneadulteyrie.c new file mode 100644 index 000000000..986470de2 --- /dev/null +++ b/src/CCW/ch/cutsceneadulteyrie.c @@ -0,0 +1,114 @@ +// BanjoDecomp: CCW/ch/cutsceneadulteyrie.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 unk0; + f32 unk4; + s16 unk8; + s16 unkA; +}Struct_CCW_4960_0; + +Actor *chCutsceneAdultEyrie_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chCutsceneAdultEyrie_update(Actor *this); + +/* .data */ +// This is the flying Eyrie that poops the Jiggy +ActorInfo chCutsceneAdultEyrie = { + MARKER_1C4_CUTSCENE_ADULT_EYRIE, ACTOR_30E_CUTSCENE_ADULT_EYRIE, ASSET_487_MODEL_EAGLE_ADULT, + 0x0, NULL, + chCutsceneAdultEyrie_update, chCutsceneAdultEyrie_update, chCutsceneAdultEyrie_draw, + 0, 0, 0.0f, 0 +}; + +Struct_CCW_4960_0 chCutsceneAdultEyrieSFX[] = { + {0.5f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, + 0 +}; + +enum chCutsceneAdultEyrie_State_e { + CH_CUTSCENE_ADULT_EYRIE_STATE_0_NOT_INIT, + CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK, + CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK, + CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK, + CH_CUTSCENE_ADULT_EYRIE_STATE_4_UNK +}; + +/* .code */ +void chCutsceneAdultEyrie_setNextState(Actor *this, s32 next_state) { + if (next_state == CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK) { + gcdialog_showDialog(VER_SELECT(ASSET_CDD_DIALOG_ADULT_EYRIE_COMPLETE_WINTER, 0x09F2, 0, 0), 0, NULL, NULL, NULL, NULL); + if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK) { + mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT, 0); + timed_setStaticCameraToNode(0.0f, 1); + } + skeletalAnim_set(this->unk148, ASSET_21D_ANIM_ADULT_EYRIE_UNK, 0.2f, 0.5f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + if (next_state == CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK) { + skeletalAnim_set(this->unk148, ASSET_21E_ANIM_ADULT_EYRIE_UNK, 0.2f, 2.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + } + if (next_state == CH_CUTSCENE_ADULT_EYRIE_STATE_4_UNK) { + timed_exitStaticCamera(0.0f); + func_80324E38(0.0f, 0); + marker_despawn(this->marker); + } + this->state = next_state; +} + +Actor *chCutsceneAdultEyrie_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor *this; + + this = marker_getActor(marker); + if(this->state < CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK) + return this; + return actor_draw(marker, gfx, mtx, vtx); +} + +void chCutsceneAdultEyrie_update(Actor *this) { + Struct_CCW_4960_0 *iPtr; + f32 sp38; + f32 sp34; + f32 sp30; + f32 sp2C; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK); + return; + } + if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK){ + if(mapSpecificFlags_get(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT)) { + mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT, false); + chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK); + } + } + if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK) { + actor_update_func_80326224(this); + skeletalAnim_getProgressRange(this->unk148, &sp38, &sp34); + for(iPtr = &chCutsceneAdultEyrieSFX[0]; iPtr->unk0 > 0.0f; iPtr++){ + if ((sp38 < iPtr->unk0) && (iPtr->unk0 <= sp34)) { + func_8030E878((s32) iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 1500.0f, 4500.0f); + } + } + if (mapSpecificFlags_get(CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT)) { + mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT, false); + chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK); + } + if (0.99 < this->unk48) { + chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_4_UNK); + } + } + if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK) { + actor_update_func_80326224(this); + skeletalAnim_getProgressRange(this->unk148, &sp30, &sp2C); + if ((sp30 <= 0.5) && (sp2C >= 0.5) && !jiggyscore_isCollected(JIGGY_49_CCW_EYRIE)) { + jiggy_spawn(JIGGY_49_CCW_EYRIE, this->position); + } + if (skeletalAnim_getLoopCount(this->unk148) > 0) { + chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK); + } + } +} diff --git a/src/CCW/ch/deadbeanstalk.c b/src/CCW/ch/deadbeanstalk.c index b98e15bf3..7f5eca32c 100644 --- a/src/CCW/ch/deadbeanstalk.c +++ b/src/CCW/ch/deadbeanstalk.c @@ -6,8 +6,14 @@ void chDeadBeanstalk_update(Actor *this); /* .data */ -ActorInfo D_8038ECA0 = { - 0x1C2, 0x30B, 0x4E3, + +enum chDeadBeanstalk_state_e { + DEAD_BEANSTALK_STATE_0_NOT_INIT, + DEAD_BEANSTALK_STATE_1_IDLE +}; + +ActorInfo chDeadBeanstalk = { + MARKER_1C2_DEAD_BEANSTALK, ACTOR_30B_DEAD_BEANSTALK, ASSET_4E3_MODEL_DEAD_BEANSTALK, 0x0, NULL, chDeadBeanstalk_update, NULL, actor_draw, 0, 0, 1.0f, 0 @@ -15,7 +21,7 @@ ActorInfo D_8038ECA0 = { /* .code */ void chDeadBeanstalk_setNextState(Actor *this, s32 next_state){ - if(next_state == 1){ + if(next_state == DEAD_BEANSTALK_STATE_1_IDLE){ skeletalAnim_set(this->unk148, 0x219, 0.0f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); } @@ -26,7 +32,7 @@ void chDeadBeanstalk_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; if(fileProgressFlag_get(FILEPROG_E5_CCW_FLOWER_AUTUMN)){ - chDeadBeanstalk_setNextState(this, 1); + chDeadBeanstalk_setNextState(this, DEAD_BEANSTALK_STATE_1_IDLE); } else{ marker_despawn(this->marker); diff --git a/src/CCW/ch/deadsnarebear.c b/src/CCW/ch/deadsnarebear.c new file mode 100644 index 000000000..ab6532cec --- /dev/null +++ b/src/CCW/ch/deadsnarebear.c @@ -0,0 +1,25 @@ +// BanjoDecomp: CCW/ch/deadsnarebear.c +#include +#include "functions.h" +#include "variables.h" + +void chDeadSnarebear_update(Actor *this); + + +ActorAnimationInfo chDeadSnarebearAnimations[] = { + {0x000, 0.0f}, + {ASSET_234_ANIM_DEAD_SNAREBEAR, 2.0f} +}; + +ActorInfo chDeadSnarebear = { + MARKER_251_DEAD_SNAREBEAR, ACTOR_37E_DEAD_SNAREBEAR, ASSET_506_CCW_DEAD_SNAREBEAR, + 0x1, chDeadSnarebearAnimations, + chDeadSnarebear_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +/* .code */ +void chDeadSnarebear_update(Actor *this){ + this->marker->propPtr->unk8_3 = true; + actor_collisionOff(this); +} diff --git a/src/CCW/ch/eyrie_baby.c b/src/CCW/ch/eyrie_baby.c deleted file mode 100644 index 1edf612dd..000000000 --- a/src/CCW/ch/eyrie_baby.c +++ /dev/null @@ -1,301 +0,0 @@ -// BanjoDecomp: code_3310.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 unk0; - s16 unk4; - f32 unk8; - s16 unkC; -}Struct_CCW_3310_1; - -typedef struct { - s16 map_id; - s16 unk2; // enum file_progress_e - s16 unk4; // enum file_progress_e - s16 unk6; - Struct_CCW_3310_1 *unk8; - s16 unkC; - s16 unkE; - Struct_CCW_3310_1 *unk10; - s16 unk14; - // u8 pad16[2]; - Struct_CCW_3310_1 *unk18; - s16 unk1C; - // u8 pad1E[0x2]; - Struct_CCW_3310_1 *unk20; - u8 unk24; - u8 unk25; - s16 unk26; - s16 unk28; - // u8 pad2A[2]; -}Struct_CCW_3310_0; - -typedef struct { - Struct_CCW_3310_0 *unk0; - u8 unk4; - //u8 pad5[3]; - Struct_CCW_3310_1 *unk8; - s32 unkC[3]; -}ActorLocal_CCW_3310; - -Actor *func_80389B24(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void CCW_func_80389BFC(Actor *this); - -/* .data */ -Struct_CCW_3310_1 D_8038EEA0[] = { - {0.11f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, - {0.22f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, - {0.34f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, - {0.55f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, - {0.65f, SFX_2_CLAW_SWIPE, 1.0f, 26000}, - {0.77f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, - {0.87f, SFX_2_CLAW_SWIPE, 1.0f, 24000}, - 0 -}; - -Struct_CCW_3310_1 D_8038EF20[] = { - {0.1f, SFX_80_YUMYUM_CLACK, 0.9f, 15000}, - {0.25f, SFX_4C_LIP_SMACK, 1.0f, 15000}, - {0.31f, SFX_4C_LIP_SMACK, 0.9f, 15000}, - {0.38f, SFX_4C_LIP_SMACK, 1.0f, 15000}, - {0.48f, SFX_4C_LIP_SMACK, 0.9f, 15000}, - {0.55f, SFX_97_BLUBBER_BURPS, 0.9f, 32700}, - {0.6f , SFX_2C_PULLING_NOISE, 0.7f, 25000}, - {0.73f, SFX_2C_PULLING_NOISE, 0.8f, 27000}, - {0.85f, SFX_2C_PULLING_NOISE, 0.9f, 29000}, - 0 -}; - -Struct_CCW_3310_1 D_8038EFC0[] = { - {0.2f , SFX_105_EYRIE_YAWN, 1.1f, 25000}, - {0.27f, SFX_105_EYRIE_YAWN, 1.0f, 25000}, - {0.35f, SFX_105_EYRIE_YAWN, 0.9f, 25000}, - {0.6f , SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, - {0.66f, SFX_106_EYRIE_LIPSMACK, 0.9f, 23000}, - {0.83f, SFX_1D_HITTING_AN_ENEMY_1, 0.7f, 27000}, - 0 -}; - -Struct_CCW_3310_1 D_8038F030[] = { - {0.2f , SFX_5D_BANJO_RAAOWW, 1.0f, 25000}, - {0.72f, SFX_5E_BANJO_PHEWWW, 1.0f, 25000}, - 0 -}; - -Struct_CCW_3310_1 D_8038F060[] = { - {0.95f, SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, - 0 -}; - -Struct_CCW_3310_0 D_8038F080[] = { - {MAP_43_CCW_SPRING, 0, FILEPROG_E6_SPRING_EYRIE_HATCHED, 0, NULL, 3, 0, NULL, 0x18F, D_8038EFC0, 0x190, D_8038F030, 0, 0, 0, 0}, - {MAP_44_CCW_SUMMER, FILEPROG_E6_SPRING_EYRIE_HATCHED, FILEPROG_E7_SUMMER_EYRIE_FED, 0x191, D_8038EEA0, 2, 0x192, D_8038EF20, 0x193, D_8038EFC0, 0x194, D_8038F030, 2, 5, 0x21A, 0xCD7}, - {MAP_45_CCW_AUTUMN, FILEPROG_E7_SUMMER_EYRIE_FED, FILEPROG_E8_AUTMN_EYRIE_FED, 0x195, D_8038EEA0, 2, 0x196, D_8038EF20, 0x197, D_8038EFC0, 0x198, D_8038F030, 4, 0xA, 0x21B, 0xCDA}, - 0 -}; - -ActorInfo D_8038F130 = { MARKER_1B4_EEYRIE_BABY, ACTOR_2A1_EEYRIE_BABY, ASSET_484_MODEL_EAGLE_BABY, 0x0, NULL, CCW_func_80389BFC, NULL, func_80389B24, 0, 0, 0.0f, 0}; - -/* .bss */ -f32 D_8038FDE0[3]; - -/* .code */ -void func_80389700(ActorMarker *marker, enum asset_e text_id, s32 arg2) { - timed_exitStaticCamera(0.5f); - func_80324E38(0.5f, 0); -} - -void func_80389740(ActorMarker *marker) { - Actor *this = marker_getActor(marker); - if (this->marker->unk14_21) { - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x30C, reinterpret_cast(s32, D_8038FDE0[0]), reinterpret_cast(s32, D_8038FDE0[1]), reinterpret_cast(s32, D_8038FDE0[2])); - } -} - -void func_80389798() { - func_8030E6D4(SFX_18C_EYRIE_MAMA); -} - -void func_803897B8(Actor *this, s32 next_state) { - ActorLocal_CCW_3310 *local; - - local = (ActorLocal_CCW_3310 *)&this->local; - local->unk8 = NULL; - if (next_state == 1) { - if (local->unk0->unk6 != 0) { - skeletalAnim_set(this->unk148, local->unk0->unk6, 0.2f, 6.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - local->unk8 = local->unk0->unk8; - } - if ((this->state == 1) && (next_state == 2)) { - fileProgressFlag_set(local->unk0->unk4, true); - } - if (next_state == 5) { - func_8028F784(1); - skeletalAnim_set(this->unk148, local->unk0->unk26, 0.2f, 2.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - local->unk8 = &D_8038F060[0]; - } - - if (next_state == 2) { - skeletalAnim_set(this->unk148, local->unk0->unkE, 0.2f, 8.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_80324E38(0.5f, 3); - timed_setStaticCameraToNode(0.5f, local->unk0->unk24); - timed_exitStaticCamera(16.5f); - func_80324E38(16.5f, 0); - local->unk8 = local->unk0->unk10; - } - if (next_state == 3) { - actor_collisionOff(this); - skeletalAnim_set(this->unk148, local->unk0->unk14, 0.5f, 8.5f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if (local->unk0->map_id == MAP_43_CCW_SPRING) { - gcdialog_showDialog(0xCD6, 4, NULL, NULL, NULL, NULL); - skeletalAnim_setCallback_0(this->unk148, 0.65f, (GenFunction_0)&func_80389798); - } - if (local->unk0->map_id == MAP_44_CCW_SUMMER) { - gcdialog_showDialog(0xCD9, 4, NULL, NULL, NULL, NULL); - } - if (local->unk0->map_id == MAP_45_CCW_AUTUMN) { - gcdialog_showDialog(0xCDB, 4, NULL, NULL, NULL, NULL); - } - local->unk8 = local->unk0->unk18; - } - if (next_state == 4) { - func_8028F784(0); - skeletalAnim_set(this->unk148, local->unk0->unk1C, 0.2f, 6.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - skeletalAnim_setCallback_1(this->unk148, 0.2f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.4f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.72f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.82f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.92f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - local->unk8 = local->unk0->unk20; - } - this->state = next_state; -} - -Actor *func_80389B24(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor *this; - ActorLocal_CCW_3310 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_3310 *)&this->local; - if( (this->state == 0) - || ((this->state == 1) && (local->unk0->unk6 == 0)) - ) { - return this; - } - func_8033A45C(3, (this->state == 4) ? 2 : 1); - actor_draw(marker, gfx, mtx, vtx); - vec3fArray_get_vec3f(func_80329934(), 5, D_8038FDE0); - return this; -} - -void func_80389BD8(f32 dst[3]){ - dst[0] = D_8038FDE0[0]; - dst[1] = D_8038FDE0[1]; - dst[2] = D_8038FDE0[2]; -} - -void CCW_func_80389BFC(Actor *this) { - Struct_CCW_3310_1 *iPtr; - ActorLocal_CCW_3310 *local; - f32 sp5C; - f32 sp58; - f32 sp4C[3]; - - local = (ActorLocal_CCW_3310 *)&this->local; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = true; - this->has_met_before = false; - this->position[0] = -4900.0f; - this->position[1] = 4619.0f; - this->position[2] = 0.0f; - D_8038FDE0[0] = this->position[0]; - D_8038FDE0[1] = this->position[1]; - D_8038FDE0[2] = this->position[2]; - if (this->state == 0) { - local->unk4 = 0U; - } - local->unk0 = &D_8038F080[0]; - while(local->unk0->map_id != 0 && gsworld_getMap() != local->unk0->map_id){ - local->unk0++; - } - - if ((local->unk0->unk2 != 0) && !fileProgressFlag_get(local->unk0->unk2)) { - marker_despawn(this->marker); - } else if (!fileProgressFlag_get(local->unk0->unk4)) { - func_803897B8(this, 1); - } else { - func_803897B8(this, 4); - } - - if (jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE) != 0) { - marker_despawn(this->marker); - } - return; - } - - if (local->unk8) { - skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); - for(iPtr = local->unk8; iPtr->unk0 > 0.0f; iPtr ++){ - if ((sp5C < iPtr->unk0) && (iPtr->unk0 <= sp58)) { - func_8030E878((s32) iPtr->unk4, randf2(iPtr->unk8 - 0.05, iPtr->unk8 + 0.05), iPtr->unkC, this->position, 500.0f, 2500.0f); - } - } - } - if (this->state == 1) { - player_getPosition(sp4C); - if( !this->has_met_before - && (local->unkC[2] >= 6500) - && (sp4C[2] < 6500.0f) - && (local->unk0->unk28 != 0) - ){ - this->has_met_before = true; - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, local->unk0->unk24); - func_80324DBC(0.0f, local->unk0->unk28, 6, NULL, this->marker, func_80389700, NULL); - } - local->unkC[0] = (s32) sp4C[0]; - local->unkC[1] = (s32) sp4C[1]; - local->unkC[2] = (s32) sp4C[2]; - if (item_getCount(ITEM_22_CATERPILLAR) == 0) { - func_8028F784(0); - } - if ((local->unk0->map_id != MAP_43_CCW_SPRING) && ((this->position[0] + 500.0f) < sp4C[0])) { - player_setCarryObjectPoseInCylinder(this->position, 1110.0f, 200.0f, ACTOR_2A2_CATERPILLAR, &this); - if ((local->unk0->unkE != 0) && (carriedObj_getActorId() == ACTOR_2A2_CATERPILLAR) && (ml_vec3f_distance(this->position, sp4C) < 1010.0f) && (player_throwCarriedObject() != 0)) { - player_setThrowTargetPosition(D_8038FDE0); - if ((local->unk0->map_id == MAP_44_CCW_SUMMER) && (local->unk4 == 0)) { - gcdialog_showDialog(0xCD8, 4, NULL, NULL, NULL, NULL); - } - local->unk4++; - if (local->unk4 < local->unk0->unk25) { - func_803897B8(this, 5); - } else { - func_803897B8(this, 2); - } - } - } - if (fileProgressFlag_get(local->unk0->unk4)) { - func_803897B8(this, local->unk0->unkC); - } - } - if ((this->state == 2) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { - func_803897B8(this, 3); - } - if ((this->state == 3) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { - func_803897B8(this, 4); - } - if ((this->state == 5) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { - func_803897B8(this, 1); - } -} diff --git a/src/CCW/ch/eyrie_egg.c b/src/CCW/ch/eyrie_egg.c deleted file mode 100644 index 615630179..000000000 --- a/src/CCW/ch/eyrie_egg.c +++ /dev/null @@ -1,70 +0,0 @@ -// BanjoDecomp: code_3050.c -#include -#include "functions.h" -#include "variables.h" - -Actor *CCW_func_8038954C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_803895F4(Actor *this); - -/* .data */ -ActorInfo D_8038EE70 = { 0x1B3, 0x2A0, 0x483, 0x0, NULL, func_803895F4, NULL, CCW_func_8038954C, 0, 0, 0.0f, 0}; - -/* .code */ -void func_80389440(Actor *this, s32 next_state) { - void *temp_v0; - - if (next_state == 2) { - sfxsource_play(SFX_AA_BGS_EGG_BREAKING_1, 28000); - this->marker->propPtr->unk8_3 = false; - fileProgressFlag_set(FILEPROG_E6_SPRING_EYRIE_HATCHED, true); - skeletalAnim_set(this->unk148, 0x187, 0.0f, 2.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 2); - timed_exitStaticCamera(8.0f); - func_80324E38(8.0f, 0); - } - this->state = next_state; -} - -void func_8038950C(ActorMarker* marker, ActorMarker* other_marker) { - Actor* actor = marker_getActor(marker); - if (actor->state == 1) { - func_80389440(actor, 2); - } -} - -Actor *CCW_func_8038954C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - - this = marker_getActor(marker); - if (this->state == 0) - return this; - - func_8033A45C(3, (this->state < 2) ? 1 : 0); - func_8033A45C(4, (this->state < 2) ? 0 : 1); - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_803895F4(Actor *this) { - f32 sp2C; - f32 sp28; - - if(!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = true; - marker_setCollisionScripts(this->marker, NULL, NULL, &func_8038950C); - func_80389440(this, 1); - if (fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED) || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) { - marker_despawn(this->marker); - } - return; - } - - if (this->state == 2) { - skeletalAnim_getProgressRange(this->unk148, &sp2C, &sp28); - if ((sp2C < 0.5) && (sp28 >= 0.5)) { - func_80326310(this); - } - } -} diff --git a/src/CCW/ch/eyrie_summer.c b/src/CCW/ch/eyrie_summer.c deleted file mode 100644 index 0ba4d601a..000000000 --- a/src/CCW/ch/eyrie_summer.c +++ /dev/null @@ -1,120 +0,0 @@ -// BanjoDecomp: code_4530.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 unk0; - f32 unk4; - s16 unk8; - s16 unkA; -}Struct_CCW_4530_0; - -void func_8038A950(Actor *this, s32 next_state); -Actor *func_8038AA38(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_8038AA8C(Actor *this); - -/* .data */ -ActorInfo D_8038F190 = { - 0x1B6, 0x2A3, 0x487, - 0x0, NULL, - func_8038AA8C, NULL, func_8038AA38, - 0, 0, 0.0f, 0 -}; - -Struct_CCW_4530_0 D_8038F1B4[] = { - {0.15f, 0.9f, SFX_A5_EYRIE_CRY, 25000}, - {0.3f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, - {0.6f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, - {0.68f, 0.85f, SFX_2_CLAW_SWIPE, 23000}, - {0.75f, 0.9f, SFX_2_CLAW_SWIPE, 28000}, - {0.8f, 0.95f, SFX_2_CLAW_SWIPE, 30000}, - {0.81f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, - {0.86f, 1.0f, SFX_2_CLAW_SWIPE, 31000}, - {0.93f, 1.0f, SFX_2_CLAW_SWIPE, 32000}, -0 -}; - -/* .code */ -void func_8038A920(ActorMarker* marker, enum asset_e text_id, s32 arg2) { - func_8038A950(marker_getActor(marker), 3); -} - -void func_8038A950(Actor *this, s32 next_state) { - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x199, 0.0f, 6.5f); - } - if (next_state == 2) { - gcdialog_showDialog(0xCDC, 0xA, this->position, this->marker, func_8038A920, NULL); - } - if (next_state == 3) { - skeletalAnim_set(this->unk148, 0x19A, 0.0f, 7.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 0); - } - if (next_state == 4) { - mapSpecificFlags_set(5, 1); - marker_despawn(this->marker); - } - this->state = next_state; -} - -Actor *func_8038AA38(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor *this; - - this = marker_getActor(marker); - if(this->state == 0) - return this; - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_8038AA8C(Actor *this) { - f32 sp54[3]; - f32 sp50; - f32 sp4C; - Struct_CCW_4530_0 *iPtr; - f32 sp44; - f32 sp40; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - mapSpecificFlags_set(5, false); - if( (!fileProgressFlag_get(FILEPROG_E8_AUTMN_EYRIE_FED) || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) - && !volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - ) { - marker_despawn(this->marker); - } - else{ - func_8038A950(this, 1); - } - return; - } - - if (this->state == 1) { - skeletalAnim_getProgressRange(this->unk148, &sp50, &sp4C); - if ((sp50 < 0.21) && (0.21 <= sp4C)) { - func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); - } - - if ((sp50 < 0.56) && (0.56 <= sp4C)) { - func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); - } - - player_getPosition(sp54); - if (ml_vec3f_distance(this->position, sp54) < 850.0f) { - func_8038A950(this, 2); - } - } - if (this->state == 3) { - skeletalAnim_getProgressRange(this->unk148, &sp44, &sp40); - for(iPtr = &D_8038F1B4[0]; iPtr->unk0 > 0.0f; iPtr++){ - if ((sp44 < iPtr->unk0) && (iPtr->unk0 <= sp40)) { - func_8030E878(iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 500.0f, 2500.0f); - } - } - if (skeletalAnim_getLoopCount(this->unk148) > 0) { - func_8038A950(this, 4); - } - } -} diff --git a/src/CCW/ch/eyrie_winter.c b/src/CCW/ch/eyrie_winter.c deleted file mode 100644 index 92b8bcbf4..000000000 --- a/src/CCW/ch/eyrie_winter.c +++ /dev/null @@ -1,105 +0,0 @@ -// BanjoDecomp: code_4960.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 unk0; - f32 unk4; - s16 unk8; - s16 unkA; -}Struct_CCW_4960_0; - -Actor *func_8038AE64(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_8038AEBC(Actor *this); - -/* .data */ -ActorInfo D_8038F230 = { - 0x1C4, 0x30E, 0x487, - 0x0, NULL, - func_8038AEBC, func_8038AEBC, func_8038AE64, - 0, 0, 0.0f, 0 -}; - -Struct_CCW_4960_0 D_8038F254[] = { - {0.5f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, - 0 -}; - -/* .code */ -void func_8038AD50(Actor *this, s32 next_state) { - if (next_state == 2) { - gcdialog_showDialog(0xCDD, 0, NULL, NULL, NULL, NULL); - if (this->state == 1) { - mapSpecificFlags_set(6, 0); - timed_setStaticCameraToNode(0.0f, 1); - } - skeletalAnim_set(this->unk148, 0x21D, 0.2f, 0.5f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - if (next_state == 3) { - skeletalAnim_set(this->unk148, 0x21E, 0.2f, 2.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - } - if (next_state == 4) { - timed_exitStaticCamera(0.0f); - func_80324E38(0.0f, 0); - marker_despawn(this->marker); - } - this->state = next_state; -} - -Actor *func_8038AE64(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor *this; - - this = marker_getActor(marker); - if(this->state < 2) - return this; - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_8038AEBC(Actor *this) { - Struct_CCW_4960_0 *iPtr; - f32 sp38; - f32 sp34; - f32 sp30; - f32 sp2C; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - func_8038AD50(this, 1); - return; - } - if (this->state == 1){ - if(mapSpecificFlags_get(5)) { - mapSpecificFlags_set(5, false); - func_8038AD50(this, 2); - } - } - if (this->state == 2) { - actor_update_func_80326224(this); - skeletalAnim_getProgressRange(this->unk148, &sp38, &sp34); - for(iPtr = &D_8038F254[0]; iPtr->unk0 > 0.0f; iPtr++){ - if ((sp38 < iPtr->unk0) && (iPtr->unk0 <= sp34)) { - func_8030E878((s32) iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 1500.0f, 4500.0f); - } - } - if (mapSpecificFlags_get(6)) { - mapSpecificFlags_set(6, false); - func_8038AD50(this, 3); - } - if (0.99 < this->unk48) { - func_8038AD50(this, 4); - } - } - if (this->state == 3) { - actor_update_func_80326224(this); - skeletalAnim_getProgressRange(this->unk148, &sp30, &sp2C); - if ((sp30 <= 0.5) && (sp2C >= 0.5)) { - jiggy_spawn(JIGGY_49_CCW_EYRIE, this->position); - } - if (skeletalAnim_getLoopCount(this->unk148) > 0) { - func_8038AD50(this, 2); - } - } -} diff --git a/src/CCW/ch/eyrieegg.c b/src/CCW/ch/eyrieegg.c new file mode 100644 index 000000000..416e03837 --- /dev/null +++ b/src/CCW/ch/eyrieegg.c @@ -0,0 +1,94 @@ +// BanjoDecomp: CCW/ch/eyrieegg.c +#include +#include "functions.h" +#include "variables.h" + +Actor *chEyrieEgg_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chEyrieEgg_update(Actor *this); + +/* .data */ +ActorInfo chEyrieEgg = { + MARKER_1B3_EAGLE_EGG, ACTOR_2A0_EAGLE_EGG, ASSET_483_MODEL_EAGLE_EGG, + 0x0, NULL, + chEyrieEgg_update, NULL, chEyrieEgg_draw, + 0, 0, 0.0f, 0 +}; + +enum chEyrieEgg_State_e { + CH_EYRIE_EGG_STATE_0_NOT_INIT, + CH_EYRIE_EGG_STATE_1_IDLE, + CH_EYRIE_EGG_STATE_2_BREAKING +}; + +// Anchor: set while replaying a teammate's hatch; skips the camera pan. +static s32 sChEyrieEggRemote = 0; + +/* .code */ +void chEyrieEgg_setNextState(Actor *this, s32 next_state) { + void *temp_v0; + + if (next_state == CH_EYRIE_EGG_STATE_2_BREAKING) { + sfxsource_play(SFX_AA_BGS_EGG_BREAKING_1, 28000); + this->marker->propPtr->unk8_3 = false; + fileProgressFlag_set(FILEPROG_E6_SPRING_EYRIE_HATCHED, true); + skeletalAnim_set(this->unk148, 0x187, 0.0f, 2.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + if (!sChEyrieEggRemote) { + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 2); + timed_exitStaticCamera(8.0f); + func_80324E38(8.0f, 0); + } + } + this->state = next_state; +} + +void chEyrieEgg_die(ActorMarker* marker, ActorMarker* other_marker) { + Actor* actor = marker_getActor(marker); + if (actor->state == CH_EYRIE_EGG_STATE_1_IDLE) { + chEyrieEgg_setNextState(actor, CH_EYRIE_EGG_STATE_2_BREAKING); + } +} + +Actor *chEyrieEgg_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + + this = marker_getActor(marker); + if (this->state == CH_EYRIE_EGG_STATE_0_NOT_INIT) + return this; + + modelRender_setAppendageVisibility(3, (this->state < CH_EYRIE_EGG_STATE_2_BREAKING) ? 1 : 0); + modelRender_setAppendageVisibility(4, (this->state < CH_EYRIE_EGG_STATE_2_BREAKING) ? 0 : 1); + return actor_draw(marker, gfx, mtx, vtx); +} + +void chEyrieEgg_update(Actor *this) { + f32 sp2C; + f32 sp28; + + if(!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = true; + marker_setCollisionScripts(this->marker, NULL, NULL, &chEyrieEgg_die); + chEyrieEgg_setNextState(this, CH_EYRIE_EGG_STATE_1_IDLE); + if (fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED) + || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) + { + marker_despawn(this->marker); + } + return; + } + + if (this->state == CH_EYRIE_EGG_STATE_1_IDLE && fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED)) { + sChEyrieEggRemote = 1; + chEyrieEgg_setNextState(this, CH_EYRIE_EGG_STATE_2_BREAKING); + sChEyrieEggRemote = 0; + } + + if (this->state == CH_EYRIE_EGG_STATE_2_BREAKING) { + skeletalAnim_getProgressRange(this->unk148, &sp2C, &sp28); + if ((sp2C < 0.5) && (sp28 >= 0.5)) { + func_80326310(this); + } + } +} diff --git a/src/CCW/ch/fairy.c b/src/CCW/ch/fairy.c deleted file mode 100644 index 9c44ac9d0..000000000 --- a/src/CCW/ch/fairy.c +++ /dev/null @@ -1,129 +0,0 @@ -// BanjoDecomp: code_6620.c -#include -#include "functions.h" -#include "variables.h" - -extern ParticleEmitter *func_802EDD8C(f32[3], f32, f32); - -typedef struct{ - s16 map_id; - s16 unk2; - s16 unk4; -}Struct_CCW_6620_0; - -typedef struct{ - Struct_CCW_6620_0 *unk0; - f32 unk4[3]; -}ActorLocal_CCW_6620; - -Actor *CCW_func_8038CBF0(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_8038CC4C(Actor *this); - -/* .data */ -Struct_CCW_6620_0 D_8038F490[] ={ - {0x43, 0, 0xCCE}, - {0x45, 1, 0xCD1}, - {0x46, 1, 0xCD3}, - 0 -}; - -ActorInfo D_8038F4A8 = { - 0x1BD, 0x2AA, 0x48F, - 0x0, NULL, - func_8038CC4C, NULL, CCW_func_8038CBF0, - 0, 0, 2.2f, 0 -}; - -/* .code */ -void func_8038CA10(ActorMarker *marker) { - Actor *this; - ActorLocal_CCW_6620 *local; - ParticleEmitter *pCtrl; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_6620 *)&this->local; - - if (this->marker->unk14_21) { - if (0.65 < (f64) randf()) { - pCtrl = func_802EDD8C(local->unk4, 0.0f, this->position[1] + 500.0f); - particleEmitter_setStartingScaleRange(pCtrl, 0.04f, 0.05f); - particleEmitter_setFinalScaleRange(pCtrl, 0.18f, 0.2f); - particleEmitter_setSpawnPositionRange(pCtrl, -10.0f, 0.0f, -10.0f, 10.0f, 20.0f, 10.0f); - particleEmitter_setParticleVelocityRange(pCtrl, 0.0f, 31.0f, 0.0f, 0.0f, 37.0f, 0.0f); - particleEmitter_emitN(pCtrl, 1); - } - } -} - -void func_8038CB40(Actor *this, s32 next_state) { - int i; - - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x289, 0.2f, 1.1f); - for(i = 0; i < 10; i++){ - skeletalAnim_setCallback_1(this->unk148, randf(), (GenFunction_1)func_8038CA10, (uintptr_t)this->marker); - } - } - this->state = next_state; -} - - -Actor *CCW_func_8038CBF0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - ActorLocal_CCW_6620 *local; - - this = actor_draw(marker, gfx, mtx, vtx); - local = (ActorLocal_CCW_6620 *)&this->local; - if (this->marker->unk14_21) { - vec3fArray_get_vec3f(func_80329934(), 5, local->unk4); - } - return this; -} - -void func_8038CC4C(Actor *this) { - ActorLocal_CCW_6620 *local; - f32 sp50[3]; - f32 sp4C; - f32 sp48; - f32 sp44; - f32 sp38[3]; - - local = (ActorLocal_CCW_6620 *)&this->local; - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - local->unk0 = &D_8038F490[0]; - while(local->unk0->map_id != 0 && gsworld_getMap() != local->unk0->map_id){ - local->unk0++; - } - func_8038CB40(this, 1); - - if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); - } - - if ((local->unk0->unk2 != 0) && levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN)) { - marker_despawn(this->marker); - } - - return; - } - - if (this->state == 1 && this->marker->unk14_21) { - player_getPosition(sp50); - func_80258A4C(this->position, this->yaw - 90.0f, sp50, &sp4C, &sp48, &sp44); - if (sp4C > 100.0f) { - this->yaw += 30.0f * sp44; - } - } - if (!this->has_met_before) { - player_getPosition(sp38); - if (ml_vec3f_distance(this->position, sp38) < 900.0f) { - if (local->unk0->map_id != MAP_46_CCW_WINTER || func_8028F2FC()) { - gcdialog_showDialog(local->unk0->unk4, 4, NULL, NULL, NULL, NULL); - this->has_met_before = true; - } - } - } -} diff --git a/src/CCW/ch/gnawty.c b/src/CCW/ch/gnawty.c deleted file mode 100644 index 9095dce6e..000000000 --- a/src/CCW/ch/gnawty.c +++ /dev/null @@ -1,143 +0,0 @@ -// BanjoDecomp: code_6AC0.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - f32 unk0; - f32 unk4; - s16 unk8; - s16 unkA; -}Struct_CCW_6AC0_0; - -void func_8038CFB4(Actor *this); - -/* .data */ -ActorInfo D_8038F4D0 = { - 0x1BE, 0x2AB, 0x48F, - 0x0, NULL, - func_8038CFB4, func_8038CFB4, actor_draw, - 0, 0, 2.2f, 0 -}; - -Struct_CCW_6AC0_0 D_8038F4F4[] = { - {0.11f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.23f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.34f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.58f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, - {0.8f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, - 0 -}; - -Struct_CCW_6AC0_0 D_8038F53C[] = { - {0.07f, 1.6f, SFX_56_BANJO_HUI, 32000}, - {0.17f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.22f, 1.6f, SFX_55_BANJO_HOO_2, 32000}, - {0.31f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.33f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, - {0.45f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.49f, 1.7f, SFX_55_BANJO_HOO_2, 32600}, - {0.6f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.63f, 1.7f, SFX_56_BANJO_HUI, 32600}, - {0.74f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.79f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, - {0.9f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - 0 -}; - -Struct_CCW_6AC0_0 D_8038F5D8[] = { - {0.01f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.5f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - 0 -}; - -/* .code */ -void func_8038CEB0(Actor *this, s32 next_state) { - ActorProp *temp_v0; - - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x1A6, 0.2f, 4.5f); - } - if (next_state == 2) { - this->marker->propPtr->unk8_3 = false; - skeletalAnim_set(this->unk148, 0x1A7, 0.2f, 3.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - gcdialog_showDialog(0xCD0, 0x24, NULL, NULL, NULL, NULL); - } - if (next_state == 3) { - skeletalAnim_set(this->unk148, 0x1A8, 0.2f, 0.5f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - if (next_state == 4) { - marker_despawn(this->marker); - } - this->state = next_state; -} - -void func_8038CFB4(Actor *this) { - Struct_CCW_6AC0_0 *phi_s0; - f32 sp70; - f32 sp6C; - f32 sp60[3]; - - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - func_8038CEB0(this, 1); - if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY) != 0) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); - } - if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) != false) { - marker_despawn(this->marker); - } - return; - } - - if (this->state == 1) { - phi_s0 = D_8038F4F4; - } else if (this->state == 2) { - phi_s0 = D_8038F53C; - } else if (this->state == 3) { - phi_s0 = D_8038F5D8; - } else{ - phi_s0 = NULL; - } - - if (phi_s0 != NULL) { - skeletalAnim_getProgressRange(this->unk148, &sp70, &sp6C); - while(phi_s0->unk0 > 0.0f){ - if (((sp70 < phi_s0->unk0) || (sp6C < sp70)) && (phi_s0->unk0 <= sp6C)) { - func_8030E878(phi_s0->unk8, randf2(phi_s0->unk4 - 0.05, phi_s0->unk4 + 0.05), randi2(phi_s0->unkA - 200, phi_s0->unkA + 100), this->position, 500.0f, 1500.0f); - } - phi_s0++; - } - } - - if (this->state == 1) { - if (!this->has_met_before) { - player_getPosition(sp60); - if (ml_vec3f_distance(this->position, sp60) < 900.0f) { - gcdialog_showDialog(0xCCF, 4, NULL, NULL, NULL, NULL); - this->has_met_before = true; - } - } - - if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) != false) { - func_8038CEB0(this, 2); - } - } - - if (this->state == 2){ - if((skeletalAnim_getLoopCount(this->unk148) > 0)) { - func_8038CEB0(this, 3); - } - } - - if (this->state == 3) { - actor_update_func_80326224(this); - if (0.99 < (f64) this->unk48) { - func_8038CEB0(this, 4); - } - } -} diff --git a/src/CCW/ch/gnawtyboulder.c b/src/CCW/ch/gnawtyboulder.c index 344e657b9..03a991b11 100644 --- a/src/CCW/ch/gnawtyboulder.c +++ b/src/CCW/ch/gnawtyboulder.c @@ -4,12 +4,20 @@ #include "variables.h" typedef struct { - f32 unk0; + f32 unk0; // time related } ActorLocal_CCW_7120; void chGnawtyBoulder_update(Actor *this); /* .data */ + +enum chGnawtyBoulder_state_e { + GNAWTY_BOULDER_STATE_0_NOT_INIT, + GNAWTY_BOULDER_STATE_1_IDLE, + GNAWTY_BOULDER_STATE_2_BREAK, + GNAWTY_BOULDER_STATE_3_DESPAWN +}; + ActorInfo chGnawtyBoulder = { 0x1BF, 0x2AC, 0x490, 0x0, NULL, @@ -18,7 +26,7 @@ ActorInfo chGnawtyBoulder = { }; /* .code */ -void CCW_func_8038D510(Actor *this) { +void chGnawtyBoulder_emitSmoke(Actor *this) { static s32 D_8038F664[3] = {0xDE, 0xA7, 0x71}; static ParticleSettingsVelocityPosition D_8038F670 = { {{ 0.0f, 50.0f, 0.0f}, { 70.0f, 100.0f, 70.0f}}, @@ -39,7 +47,7 @@ void CCW_func_8038D510(Actor *this) { particleEmitter_emitN(pCtrl, 6); } -void func_8038D5DC(Actor *this) { +void chGnawtyBoulder_emitRock(Actor *this) { static ParticleSettingsVelocityAccelerationPosition D_8038F6A0 ={ {{-100.0f, -50.0f, -100.0f}, {100.0f, 50.0f, 100.0f}}, {{ 0.0f, -800.0f, 0.0f}, { 0.0f, -800.0f, 0.0f}}, @@ -51,7 +59,7 @@ void func_8038D5DC(Actor *this) { pCtrl = partEmitMgr_newEmitter(30); particleEmitter_func_802EF9F8(pCtrl, 0.6f); particleEmitter_func_802EFA18(pCtrl, 3); - particleEmitter_setModel(pCtrl, 0x896); + particleEmitter_setModel(pCtrl, ASSET_896_MODEL_GOLD_ROCK); particleEmitter_setPosition(pCtrl, this->position); particleEmitter_setStartingScaleRange(pCtrl, 0.05f, 0.3f); particleEmitter_setAngularVelocityRange(pCtrl, @@ -68,35 +76,35 @@ void chGnawtyBoulder_setNextState(Actor *this, s32 next_state) { ActorLocal_CCW_7120 *local = (ActorLocal_CCW_7120 *)&this->local; local->unk0 = 0.0f; - if (next_state == 2) { + if (next_state == GNAWTY_BOULDER_STATE_2_BREAK) { this->marker->propPtr->unk8_3 = false; func_802BB3DC(0, 60.0f, 0.7f); - CCW_func_8038D510(this); - func_8038D5DC(this); + chGnawtyBoulder_emitSmoke(this); + chGnawtyBoulder_emitRock(this); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.3f, 15000); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.5f, 15000); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.7f, 15000); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.9f, 15000); func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.5f, 3); - timedFunc_set_2(0.5f, (GenFunction_2)levelSpecificFlags_set, LEVEL_FLAG_25_CCW_UNKNOWN, true); + timedFunc_set_2(0.5f, (GenFunction_2)levelSpecificFlags_set, LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); timed_exitStaticCamera(4.0f); func_80324E38(4.0f, 0); local->unk0 = 0.5f; marker_despawn(this->marker); } - if (next_state == 3) { + if (next_state == GNAWTY_BOULDER_STATE_3_DESPAWN) { marker_despawn(this->marker); } this->state = next_state; } -void func_8038D81C(ActorMarker* marker, ActorMarker *other_marker) { +void chGnawtyBoulder_die(ActorMarker* marker, ActorMarker *other_marker) { Actor* actor = marker_getActor(marker); - if (actor->state == 1) { + if (actor->state == GNAWTY_BOULDER_STATE_1_IDLE) { // [port] v1.1 fix: rock is indestructible in Spring (prevents sequence break) if (EventSystem_Should(VB_CCW_GNAWTY_SPRING_ROCK, gsworld_getMap() != MAP_43_CCW_SPRING)) { - chGnawtyBoulder_setNextState(actor, 2); + chGnawtyBoulder_setNextState(actor, GNAWTY_BOULDER_STATE_2_BREAK); } } } @@ -109,21 +117,30 @@ void chGnawtyBoulder_update(Actor *this) { if (!this->volatile_initialized) { this->marker->propPtr->unk8_3 = true; this->volatile_initialized = true; - marker_setCollisionScripts(this->marker, NULL, &func_8038D81C, NULL); - chGnawtyBoulder_setNextState(this, 1); + marker_setCollisionScripts(this->marker, NULL, &chGnawtyBoulder_die, NULL); + chGnawtyBoulder_setNextState(this, GNAWTY_BOULDER_STATE_1_IDLE); if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY) != false) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); } - if ((levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) != false) && (gsworld_getMap() != MAP_43_CCW_SPRING)) { + if ((levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) != false) + && (gsworld_getMap() != MAP_43_CCW_SPRING)) + { marker_despawn(this->marker); } return; - } - if(this->state == 2){ + } + // Anchor: teammate broke the boulder — despawn live (no break cutscene). + if (this->state == GNAWTY_BOULDER_STATE_1_IDLE + && levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) + && gsworld_getMap() != MAP_43_CCW_SPRING) { + marker_despawn(this->marker); + return; + } + if(this->state == GNAWTY_BOULDER_STATE_2_BREAK){ if (ml_timer_update(&local->unk0, tick) ) { - chGnawtyBoulder_setNextState(this, 3); + chGnawtyBoulder_setNextState(this, GNAWTY_BOULDER_STATE_3_DESPAWN); } } } diff --git a/src/CCW/ch/grublinhood.c b/src/CCW/ch/grublinhood.c index 2e99ab8aa..0e1ffac87 100644 --- a/src/CCW/ch/grublinhood.c +++ b/src/CCW/ch/grublinhood.c @@ -7,17 +7,9 @@ extern void func_802DABA0(ParticleEmitter *, f32[3], f32, enum asset_e); -extern void func_8033A45C(s32, s32); +extern void modelRender_setAppendageVisibility(s32, s32); extern void humanoidBaddie_ow(ActorMarker *, ActorMarker *); -enum ccw_season_e -{ - SPRING, - SUMMER, - AUTUMN, - WINTER -}; - void chgrublinhood_update(Actor *this); Actor *chgrublinhood_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); @@ -80,18 +72,18 @@ Actor *chgrublinhood_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ this = marker_getActor(marker); local = (Humanoid_Baddies_Actor *)&this->local; - func_8033A45C(3, (local->baddieSpecific == SUMMER) ? 1 : 2); - func_8033A45C(4, (local->baddieSpecific == SUMMER) ? 1 : 2); - func_8033A45C(5, (local->baddieSpecific < AUTUMN) ? 1 : 2); - func_8033A45C(6, (local->baddieSpecific < AUTUMN) ? 1 : 2); - func_8033A45C(7, (local->baddieSpecific < AUTUMN) ? 1 : 2); - func_8033A45C(8, (local->baddieSpecific < AUTUMN) ? 1 : 2); - func_8033A45C(9, (local->baddieSpecific == SUMMER) ? 1 : 0); - func_8033A45C(10, (local->baddieSpecific < AUTUMN) ? 0 : (local->baddieSpecific == AUTUMN) ? 1 : 2); - func_8033A45C(11, (local->baddieSpecific < AUTUMN) ? 0 : (local->baddieSpecific == AUTUMN) ? 1 : 2); - func_8033A45C(12, (local->baddieSpecific == WINTER) ? 2 : 1); - func_8033A45C(13, (local->baddieSpecific == WINTER) ? 1 : 0); - func_8033A45C(14, (this->has_met_before)? false : true); + modelRender_setAppendageVisibility(3, (local->baddieSpecific == CCW_SEASON_1_SUMMER) ? 1 : 2); + modelRender_setAppendageVisibility(4, (local->baddieSpecific == CCW_SEASON_1_SUMMER) ? 1 : 2); + modelRender_setAppendageVisibility(5, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); + modelRender_setAppendageVisibility(6, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); + modelRender_setAppendageVisibility(7, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); + modelRender_setAppendageVisibility(8, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); + modelRender_setAppendageVisibility(9, (local->baddieSpecific == CCW_SEASON_1_SUMMER) ? 1 : 0); + modelRender_setAppendageVisibility(10, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 0 : (local->baddieSpecific == CCW_SEASON_2_AUTUMN) ? 1 : 2); + modelRender_setAppendageVisibility(11, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 0 : (local->baddieSpecific == CCW_SEASON_2_AUTUMN) ? 1 : 2); + modelRender_setAppendageVisibility(12, (local->baddieSpecific == CCW_SEASON_3_WINTER) ? 2 : 1); + modelRender_setAppendageVisibility(13, (local->baddieSpecific == CCW_SEASON_3_WINTER) ? 1 : 0); + modelRender_setAppendageVisibility(14, (this->has_met_before)? false : true); return actor_draw(marker, gfx, mtx, vtx); } @@ -121,14 +113,14 @@ enum ccw_season_e __get_current_season(Actor *this){ case MAP_5B_CCW_SPRING_ZUBBA_HIVE:// 8038E930 case MAP_5E_CCW_SPRING_NABNUTS_HOUSE:// 8038E930 case MAP_65_CCW_SPRING_WHIPCRACK_ROOM:// 8038E930 - return SPRING; + return CCW_SEASON_0_SPRING; case MAP_44_CCW_SUMMER:// 8038E938 case MAP_4B_CCW_SUMMER_MUMBOS_SKULL:// 8038E938 case MAP_5A_CCW_SUMMER_ZUBBA_HIVE:// 8038E938 case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE:// 8038E938 case MAP_66_CCW_SUMMER_WHIPCRACK_ROOM:// 8038E938 - return SUMMER; + return CCW_SEASON_1_SUMMER; case MAP_45_CCW_AUTUMN:// 8038E940 case MAP_4C_CCW_AUTUMN_MUMBOS_SKULL:// 8038E940 @@ -136,7 +128,7 @@ enum ccw_season_e __get_current_season(Actor *this){ case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE:// 8038E940 case MAP_63_CCW_AUTUMN_NABNUTS_WATER_SUPPLY:// 8038E940 case MAP_67_CCW_AUTUMN_WHIPCRACK_ROOM:// 8038E940 - return AUTUMN; + return CCW_SEASON_2_AUTUMN; case MAP_46_CCW_WINTER:// 8038E948 case MAP_4D_CCW_WINTER_MUMBOS_SKULL:// 8038E948 @@ -144,11 +136,10 @@ enum ccw_season_e __get_current_season(Actor *this){ case MAP_62_CCW_WINTER_HONEYCOMB_ROOM:// 8038E948 case MAP_64_CCW_WINTER_NABNUTS_WATER_SUPPLY:// 8038E948 case MAP_68_CCW_WINTER_WHIPCRACK_ROOM:// 8038E948 - return WINTER; + return CCW_SEASON_3_WINTER; default: - return SPRING; - + return CCW_SEASON_0_SPRING; } } diff --git a/src/CCW/ch/indoorsgnawty.c b/src/CCW/ch/indoorsgnawty.c new file mode 100644 index 000000000..325748fa0 --- /dev/null +++ b/src/CCW/ch/indoorsgnawty.c @@ -0,0 +1,98 @@ +// BanjoDecomp: CCW/ch/indoorsgnawty.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + s16 map; + s16 meetBeforeJiggyDialog; + s16 meetAfterJiggyDialog; +} CH_Indoors_Gnawty_Dialogs; + +typedef struct{ + CH_Indoors_Gnawty_Dialogs *dialogs; +} ActorLocal_chIndoorsGnawty; + +void chIndoorsGnawty_update(Actor *this); +Actor *chIndoorsGnawty_draw(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); + +/* .data */ +CH_Indoors_Gnawty_Dialogs chIndoorsGnawtyDialogs[] = { + { + MAP_45_CCW_AUTUMN, + VER_SELECT(ASSET_CD2_DIALOG_GNAWTY_MEET_FALL_INSIDE, 0x9E7, 0, 0), + 0 // [port] decomp uses NULL; dialog fields are asset ids, not pointers + }, + { + MAP_46_CCW_WINTER, + VER_SELECT(ASSET_CD4_DIALOG_GNAWTY_MEET_WINTER_INSIDE_JIGGY, 0x09E9, 0, 0), + VER_SELECT(ASSET_CD5_DIALOG_GNAWTY_MEET_WINTER_INSIDE_AFTER_JIGGY, 0x09EA, 0, 0) + }, + { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion +}; + +ActorInfo chIndoorsGnawty = { + MARKER_1CE_INDOOR_GNAWTY, ACTOR_31A_INDOORS_GNAWTY, ASSET_48F_MODEL_GNAWTY, + 0x0, NULL, + chIndoorsGnawty_update, NULL, chIndoorsGnawty_draw, + 0, 0, 2.2f, 0 +}; + +enum chIndoorsGnawty_State_e { + CH_INDOOR_GNAWTY_STATE_0_NOT_INIT, + CH_INDOOR_GNAWTY_STATE_1_IDLE +}; + +/* .code */ +void chIndoorsGnawty_setNextState(Actor *this, s32 next_state) { + if (next_state == CH_INDOOR_GNAWTY_STATE_1_IDLE) { + skeletalAnim_set(this->unk148, ASSET_1A6_ANIM_GNAWTY_IDLE, 0.2f, 5.5f); + } + + this->state = next_state; +} + +Actor *chIndoorsGnawty_draw(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { + if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) == false) { + return func_80325340(marker, gfx, mtx, vtx); + } + + return actor_draw(marker, gfx, mtx, vtx); +} + +void chIndoorsGnawty_update(Actor *this) { + ActorLocal_chIndoorsGnawty *local; + f32 plyr_pos[3]; + + local = (ActorLocal_chIndoorsGnawty *)&this->local; + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + local->dialogs = chIndoorsGnawtyDialogs; + while (local->dialogs->map != 0 && gsworld_getMap() != local->dialogs->map) { + local->dialogs++; + } + + chIndoorsGnawty_setNextState(this, CH_INDOOR_GNAWTY_STATE_1_IDLE); + if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); + } + return; + } + + if(!this->has_met_before){ + player_getPosition(plyr_pos); + if (ml_vec3f_distance(this->position, plyr_pos) < 600.0f) { + if (!jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { + gcdialog_showDialog(local->dialogs->meetBeforeJiggyDialog, 4, NULL, NULL, NULL, NULL); + } else { + if (local->dialogs->meetAfterJiggyDialog) { + gcdialog_showDialog(local->dialogs->meetAfterJiggyDialog, 4, NULL, NULL, NULL, NULL); + } + } + this->has_met_before = true; + } + } + +} diff --git a/src/CCW/ch/nabnut_autumn.c b/src/CCW/ch/nabnut_autumn.c deleted file mode 100644 index 11c4c56ed..000000000 --- a/src/CCW/ch/nabnut_autumn.c +++ /dev/null @@ -1,172 +0,0 @@ -// BanjoDecomp: code_5540.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - s32 returned_acorn_count; -}ActorLocal_CCW_5540; - -void chnabnut_setState(Actor *this, s32 next_state); -Actor *chnabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chnabnut_update(Actor *this); - -enum nabnut_state_e{ - NABNUT_STATE_1_SAD = 1, - NABNUT_STATE_2_WAIT, - NABNUT_STATE_3_BACKFLIP, - NABNUT_STATE_4_THANK_PLAYER, - NABNUT_STATE_5_EXIT, - NABNUT_STATE_6_DESPAWN -}; - -/* .data */ -f32 D_8038F350[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_8038F35C = { - MARKER_1BB_NABNUT, ACTOR_2A8_NABNUT, ASSET_502_MODEL_NABNUT, - 0x0, NULL, - chnabnut_update, chnabnut_update, chnabnut_draw, - 0, 0, 1.2f, 0 -}; - -/* .code */ -void __chnabnut_setState_method(ActorMarker* marker, s32 next_state) { - chnabnut_setState(marker_getActor(marker), next_state); -} - -void chnabnut_setState(Actor *this, s32 next_state) { - - if (next_state == NABNUT_STATE_1_SAD) { - skeletalAnim_set(this->unk148, ASSET_22C_ANIM_NABNUT_CRY, 0.2f, 10.6f); - } - - if (next_state == NABNUT_STATE_2_WAIT) { - timedFunc_set_2(1.0f, (GenFunction_2)__chnabnut_setState_method, (uintptr_t)this->marker, NABNUT_STATE_3_BACKFLIP); - } - - if (next_state == NABNUT_STATE_3_BACKFLIP) { - this->marker->propPtr->unk8_3 = false; - skeletalAnim_set(this->unk148, ASSET_22D_ANIM_NABNUT_BACKFLIP, 0.2f, 3.13f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 0xB); - gcdialog_showDialog(0xCCC, 0x20, this->position, NULL, NULL, NULL); - } - - if (next_state == NABNUT_STATE_4_THANK_PLAYER) { - skeletalAnim_set(this->unk148, ASSET_22E_ANIM_NABNUT_STAND, 0.2f, 3.53f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - bundle_setYaw(this->yaw - 40.0f); - jiggy_spawn(JIGGY_4A_CCW_NABNUT, this->position); - } - - if (next_state == NABNUT_STATE_5_EXIT) { - skeletalAnim_set(this->unk148, ASSET_22F_ANIM_NABNUT_RUN, 0.2f, 0.34f); - } - - if (next_state == NABNUT_STATE_6_DESPAWN) { - func_80324E38(0.0f, 0); - timed_exitStaticCamera(0.0f); - marker_despawn(this->marker); - } - - this->state = next_state; -} - -Actor *chnabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - Actor *out; - void *sp24; - f32 temp_f2; - - this = marker_getActor(marker); - func_8033A45C(3, 0); - func_8033A45C(4, 0); - func_8033A45C(5, 1); - func_8033A45C(6, 0); - func_8033A45C(7, 1); - func_8033A45C(8, 1); - func_8033A45C(9, 0); - func_8033A45C(0xA, 1); - if (this->state == 1) { - temp_f2 = skeletalAnim_getProgress(this->unk148); - if ((0.116 <= temp_f2) && (temp_f2 <= 0.32)) { - sp24 = this->unk130; - this->unk130 = NULL; - func_8033A45C(1, 4); - out = actor_draw(marker, gfx, mtx, vtx); - out->unk130 = sp24; - return out; - } - } - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_8038BC50(f32 dst[3]){ - dst[0] = D_8038F350[0]; - dst[1] = D_8038F350[1]; - dst[2] = D_8038F350[2]; -} - -void chnabnut_update(Actor *this) { - ActorLocal_CCW_5540 *local; - f32 sp30[3]; - f32 sp2C; - f32 sp28; - f32 sp24; - - local = (ActorLocal_CCW_5540 *)&this->local; - if (!this->volatile_initialized) { - this->volatile_initialized = true; - D_8038F350[0] = this->position[0]; - D_8038F350[1] = this->position[1]; - D_8038F350[2] = this->position[2]; - if (this->state == 0) { - this->has_met_before = false; - local->returned_acorn_count = 0; - } - chnabnut_setState(this, 1); - if(jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT)) { - marker_despawn(this->marker); - } - return; - } - - if (this->state == NABNUT_STATE_1_SAD) { - player_getPosition(sp30); - if (!this->has_met_before && (ml_vec3f_distance(this->position, sp30) < 400.0f)) { - this->has_met_before = true; - gcdialog_showDialog(0xCCA, 0xE, this->position, NULL, NULL, NULL); - } - if (item_getCount(ITEM_23_ACORNS) > 0) { - func_80258A4C(this->position, this->yaw - 90.0f, sp30, &sp2C, &sp28, &sp24); - this->yaw += sp24 * 10.0f; - } - if (this->has_met_before && !gcdialog_hasCurrentTextId()) { - player_setCarryObjectPoseInCylinder(this->position, 500.0f, 200.0f, ACTOR_2A9_ACORN, &this); - if ((carriedObj_getActorId() == ACTOR_2A9_ACORN) && (ml_vec3f_distance(this->position, sp30) < 300.0f) && player_throwCarriedObject()) { - player_setThrowTargetPosition(D_8038F350); - local->returned_acorn_count++; - if (local->returned_acorn_count == 6) { - chnabnut_setState(this, NABNUT_STATE_2_WAIT); - } else if (item_getCount(ITEM_23_ACORNS) == 1) { - gcdialog_showDialog(0xCCB, 0x20, this->position, NULL, NULL, NULL); - } - } - } - } - if ((this->state == NABNUT_STATE_3_BACKFLIP) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { - chnabnut_setState(this, NABNUT_STATE_4_THANK_PLAYER); - } - if ((this->state == NABNUT_STATE_4_THANK_PLAYER) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { - chnabnut_setState(this, NABNUT_STATE_5_EXIT); - } - if (this->state == NABNUT_STATE_5_EXIT) { - actor_update_func_80326224(this); - func_8028FC8C(this->position); - if (0.99 < this->unk48) { - chnabnut_setState(this, NABNUT_STATE_6_DESPAWN); - } - } - func_8028E668(this->position, 300.0f, -50.0f, 120.0f); -} diff --git a/src/CCW/ch/nabnut_dialog.c b/src/CCW/ch/nabnut_dialog.c deleted file mode 100644 index 27565536b..000000000 --- a/src/CCW/ch/nabnut_dialog.c +++ /dev/null @@ -1,85 +0,0 @@ -// BanjoDecomp: code_6EC0.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - s16 map; - s16 unk2; - s16 unk4; -}Struct_CCW_6EC0_0; - -typedef struct{ - Struct_CCW_6EC0_0 *unk0; -}ActorLocal_CCW_6EC0; - -void func_8038D368(Actor *this); -Actor *func_8038D30C(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); - -/* .data */ -Struct_CCW_6EC0_0 D_8038F600[] = { - {MAP_45_CCW_AUTUMN, 0xCD2, 0}, - {MAP_46_CCW_WINTER, 0xCD4, 0xCD5}, - 0 -}; - -ActorInfo D_8038F614 = { - 0x1CE, 0x31A, 0x48F, - 0x0, NULL, - func_8038D368, NULL, func_8038D30C, - 0, 0, 2.2f, 0 -}; - -/* .code */ -void func_8038D2B0(Actor *this, s32 next_state) { - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x1A6, 0.2f, 5.5f); - } - - this->state = next_state; -} - -Actor *func_8038D30C(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { - if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) == false) { - return func_80325340(marker, gfx, mtx, vtx); - } - - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_8038D368(Actor *this) { - ActorLocal_CCW_6EC0 *local; - f32 plyr_pos[3]; - - local = (ActorLocal_CCW_6EC0 *)&this->local; - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - local->unk0 = D_8038F600; - while (local->unk0->map != 0 && gsworld_getMap() != local->unk0->map) { - local->unk0++; - } - - func_8038D2B0(this, 1); - if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); - } - return; - } - - if(!this->has_met_before){ - player_getPosition(plyr_pos); - if (ml_vec3f_distance(this->position, plyr_pos) < 600.0f) { - if (!jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { - gcdialog_showDialog(local->unk0->unk2, 4, NULL, NULL, NULL, NULL); - } else { - if (local->unk0->unk4) { - gcdialog_showDialog(local->unk0->unk4, 4, NULL, NULL, NULL, NULL); - } - } - this->has_met_before = true; - } - } - -} diff --git a/src/CCW/ch/nabnut_spring.c b/src/CCW/ch/nabnut_spring.c deleted file mode 100644 index e502ca7ea..000000000 --- a/src/CCW/ch/nabnut_spring.c +++ /dev/null @@ -1,97 +0,0 @@ -// BanjoDecomp: code_4D00.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 unk0; -}ActorLocal_CCW_4D00; - -typedef struct { - f32 unk0; - f32 unk4; - s16 unk8; - s16 unkA; -}Struct_CCW_4D00_0; - -void func_8038B19C(Actor *this); - -/* .data */ -ActorInfo D_8038F270 = { - 0x1B9, 0x2A6, 0x502, - 0x0, NULL, - func_8038B19C, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -Struct_CCW_4D00_0 D_8038F294[] = { - {0.12f, 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, - {0.21f, 1.7f, SFX_A7_WOODEN_SWOSH, 8500}, - {0.3f , 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, - {0.51f, 1.0f, SFX_4C_LIP_SMACK, 22000}, - {0.65f, 1.05f, SFX_4C_LIP_SMACK, 23000}, - {0.76f, 1.0f, SFX_4C_LIP_SMACK, 22000}, - {0.88f, 1.0f, SFX_4C_LIP_SMACK, 23000}, - 0 -}; - -/* .code */ -void func_8038B0F0(Actor *this, s32 next_state) { - ActorLocal_CCW_4D00 *local = (ActorLocal_CCW_4D00 *)&this->local; - - local->unk0 = 0.0f; - if (next_state == 1) { - skeletalAnim_swap(this->unk148, 0x1A3, 0.2f, 11.0f); - local->unk0 = randf2(3.0f, 10.0f); - } - if (next_state == 2) { - skeletalAnim_set(this->unk148, 0x1A4, 0.2f, 3.0f); - } - this->state = next_state; -} - -void func_8038B19C(Actor *this) { - ActorLocal_CCW_4D00 *local; - f32 tick; - Struct_CCW_4D00_0 *iPtr; - f32 sp50; - f32 sp4C; - - local = (ActorLocal_CCW_4D00 *)&this->local; - tick = time_getDelta(); - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->has_met_before = false; - func_8038B0F0(this, 1); - } - - if ((this->state == 1) && ml_timer_update(&local->unk0, tick)) { - func_8038B0F0(this, 2); - } - - if (this->state == 2) { - skeletalAnim_getProgressRange(this->unk148, &sp50, &sp4C); - for(iPtr = &D_8038F294[0]; iPtr->unk0 > 0.0f; iPtr++){ - if ((sp50 < iPtr->unk0) && (iPtr->unk0 <= sp4C)) { - func_8030E878(iPtr->unk8, randf2(iPtr->unk4 - 0.05, iPtr->unk4 + 0.05), randi2(iPtr->unkA - 0x1F4, iPtr->unkA + 0x1F4), this->position, 500.0f, 2500.0f); - } - } - - if ((sp50 < 0.97) && (0.97 <= sp4C)) { - if (randf() >= 0.5) { - func_8030E878(SFX_AE_YUMYUM_TALKING, randf2(1.8f, 1.85f), randi2(19000, 21000), this->position, 500.0f, 2500.0f); - } else { - func_8030E878(SFX_4B_GULPING, randf2(1.4f, 1.45f), randi2(24000, 26000), this->position, 500.0f, 2500.0f); - } - } - if (skeletalAnim_getLoopCount(this->unk148) > 0) { - func_8038B0F0(this, 1); - } - } - if (!this->has_met_before && func_803292E0(this)) { - this->has_met_before = true; - gcdialog_showDialog(0xCC8, 0, NULL, NULL, NULL, NULL); - } - func_8028E668(this->position, 300.0f, -50.0f, 120.0f); -} diff --git a/src/CCW/ch/nabnut_winter.c b/src/CCW/ch/nabnut_winter.c deleted file mode 100644 index a1aac88c5..000000000 --- a/src/CCW/ch/nabnut_winter.c +++ /dev/null @@ -1,124 +0,0 @@ -// BanjoDecomp: code_5BF0.c -#include -#include "functions.h" -#include "variables.h" - -extern void func_8028E668(f32[3], f32, f32, f32); - -Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); -void func_8038C41C(Actor *this); - -/* .data */ -ActorInfo D_8038F380 = { 0x1C6, 0x310, 0x501, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038F3A4 = { 0x1C7, 0x311, 0x462, 0x0, NULL, func_8038C41C, NULL, func_8038C380, 0, 0, 0.0f, 0}; -ActorInfo D_8038F3C8 = { 0x1C8, 0x312, 0x463, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038F3EC = { 0x1C9, 0x313, 0x464, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038F410 = { 0x1CA, 0x314, 0x502, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 2.0f, 0}; -ActorInfo D_8038F434 = { 0x1CB, 0x315, 0x48D, 0x0, NULL, func_8038C41C, NULL, func_8038C380, 0, 0, 0.0f, 0}; - -/* .code */ -void func_8038BFE0(ActorMarker* marker) { - Actor* sp2C = marker_getActor(marker); - func_8030E878(SFX_5D_BANJO_RAAOWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); -} - -void func_8038C064(ActorMarker* marker) { - Actor* sp2C = marker_getActor(marker); - func_8030E878(SFX_5E_BANJO_PHEWWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); -} - -void func_8038C0E8(ActorMarker* marker) { - Actor* sp24 = marker_getActor(marker); - f32 sp20 = randf2(0.9f, 1.1f); - - func_8030E878(SFX_81_UUU, sp20, (s32)randf2(10000.0f, 31000.0f), sp24->position, 500.0f, 2500.0f); -} - -void CCW_func_8038C16C(Actor *this, s32 next_state) { - Actor *other; - - if (next_state == 1) { - this->position[1] -= 300.0f; - } - - if (this->state == 1) { - this->position[1] += 300.0f; - } - - if (next_state == 2) { - if (this->marker->id == 0x1CA) { - skeletalAnim_set(this->unk148, 0x22E, 0.2f, 3.53f); - skeletalAnim_setCallback_1(this->unk148, 0.1f, (GenFunction_1)func_8038C0E8, (uintptr_t)this->marker); - } - if (this->marker->id == 0x1C7) { - skeletalAnim_set(this->unk148, 0x230, 0.2f, 4.0f); - } - if (this->marker->id == 0x1CB) { - skeletalAnim_set(this->unk148, 0x1A2, 0.2f, 4.0f); - skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_8038BFE0, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.65f, (GenFunction_1)func_8038C064, (uintptr_t)this->marker); - } - if (this->marker->id == 0x1C8) { - skeletalAnim_set(this->unk148, 0x231, 0.2f, 4.0f); - } - if ((this->marker->id == 0x1C7) || (this->marker->id == 0x1CB) || (this->marker->id == 0x1C8)) { - other = actorArray_findActorFromActorId(0x313); - if (other != 0) { - this->position[0] = other->position[0]; - this->position[1] = other->position[1]; - this->position[2] = other->position[2]; - this->pitch = other->pitch; - this->yaw = other->yaw; - this->roll = other->roll; - } - } - } - this->state = next_state; -} - -Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { - func_8033A45C(3, 0); - func_8033A45C(4, 0); - func_8033A45C(5, 0); - func_8033A45C(6, 1); - func_8033A45C(7, 0); - func_8033A45C(8, 0); - func_8033A45C(9, 0); - func_8033A45C(0xA, 1); - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_8038C41C(Actor *this) { - f32 sp2C[3]; - - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - return; - } - - if (this->state == 0) { - if( gsworld_getMap() == MAP_60_CCW_AUTUMN_NABNUTS_HOUSE - && !jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT) - && (this->marker->id == 0x1C6 || this->marker->id == 0x1CA) - ){ - CCW_func_8038C16C(this, 1); - } else { - CCW_func_8038C16C(this, 2); - } - } - - if ((this->marker->id == 0x1CA) && (this->state != 1)) { - func_8028E668(this->position, 300.0f, -50.0f, 120.0f); - } - - if ((this->marker->id == 0x1CB) && (this->state == 2)) { - player_getPosition(sp2C); - if (!this->has_met_before && (ml_vec3f_distance(this->position, sp2C) < 400.0f)) { - this->has_met_before = true; - gcdialog_showDialog(0xCCD, 0, NULL, NULL, NULL, NULL); - } - } -} - diff --git a/src/CCW/ch/outsideautumnnabnut.c b/src/CCW/ch/outsideautumnnabnut.c new file mode 100644 index 000000000..23893dd91 --- /dev/null +++ b/src/CCW/ch/outsideautumnnabnut.c @@ -0,0 +1,226 @@ +// BanjoDecomp: CCW/ch/outsideautumnnabnut.c +#include +#include "functions.h" +#include "variables.h" +#include "port/Patches/Patches.h" + +// Anchor: set during a remote completion replay; skips the finisher's camera/dialog. +static s32 sNabnutRemote = 0; + +typedef struct { + s32 returned_acorn_count; +}ActorLocal_ChAutumnNabnutPosition; + +void chAutumnOutsideNabnut_setState(Actor *this, s32 next_state); +Actor *__chAutumnOutsideNabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chAutumnOutsideNabnut_update(Actor *this); + +enum chautumnoutdoornabnut_state_e{ + CH_AUTUMN_OUTDOOR_NABNUT_STATE_0_NOT_INIT, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_6_DESPAWN +}; + +/* .data */ +f32 chAutumnOutdoorNabnutPosition[3] = {0.0f, 0.0f, 0.0f}; // updates on init + +#define AUTUMN_NABNUT_ACORN_COUNT 6 + +ActorInfo chAutumnOutdoorNabnut = { + MARKER_1BB_NABNUT, ACTOR_2A8_NABNUT, ASSET_502_MODEL_NABNUT, + 0x0, NULL, + chAutumnOutsideNabnut_update, chAutumnOutsideNabnut_update, __chAutumnOutsideNabnut_draw, + 0, 0, 1.2f, 0 +}; + +/* .code */ +void __chAutumnOutsideNabnut_setStateMethod(ActorMarker* marker, s32 next_state) { + chAutumnOutsideNabnut_setState(marker_getActor(marker), next_state); +} + +void chAutumnOutsideNabnut_setState(Actor *this, s32 next_state) { + + if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { + skeletalAnim_set(this->unk148, ASSET_22C_ANIM_NABNUT_CRY, 0.2f, 10.6f); + } + + if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT) { + timedFunc_set_2( + 1.0f, + (GenFunction_2)__chAutumnOutsideNabnut_setStateMethod, + (uintptr_t)this->marker, + CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP); + } + + if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP) { + this->marker->propPtr->unk8_3 = false; + skeletalAnim_set(this->unk148, ASSET_22D_ANIM_NABNUT_BACKFLIP, 0.2f, 3.13f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + if (!sNabnutRemote) { + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 0xB); + gcdialog_showDialog( + VER_SELECT(ASSET_CCC_DIALOG_NABNUT_ACORN_COMPLETE, 0x09E1, 0, 0), + 0x20, this->position, + NULL, NULL, NULL); + } + } + + if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER) { + skeletalAnim_set(this->unk148, ASSET_22E_ANIM_NABNUT_STAND, 0.2f, 3.53f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + bundle_setYaw(this->yaw - 40.0f); + if (!jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT)) { + jiggy_spawn(JIGGY_4A_CCW_NABNUT, this->position); + } + } + + if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT) { + skeletalAnim_set(this->unk148, ASSET_22F_ANIM_NABNUT_RUN, 0.2f, 0.34f); + } + + if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_6_DESPAWN) { + if (!sNabnutRemote) { + func_80324E38(0.0f, 0); + timed_exitStaticCamera(0.0f); + } + marker_despawn(this->marker); + } + + this->state = next_state; +} + +Actor *__chAutumnOutsideNabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + Actor *out; + void *sp24; + f32 temp_f2; + + this = marker_getActor(marker); + modelRender_setAppendageVisibility(3, 0); + modelRender_setAppendageVisibility(4, 0); + modelRender_setAppendageVisibility(5, 1); + modelRender_setAppendageVisibility(6, 0); + modelRender_setAppendageVisibility(7, 1); + modelRender_setAppendageVisibility(8, 1); + modelRender_setAppendageVisibility(9, 0); + modelRender_setAppendageVisibility(0xA, 1); + if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { + temp_f2 = skeletalAnim_getProgress(this->unk148); + if ((0.116 <= temp_f2) && (temp_f2 <= 0.32)) { + sp24 = this->unk130; + this->unk130 = NULL; + modelRender_setAppendageVisibility(1, 4); + out = actor_draw(marker, gfx, mtx, vtx); + out->unk130 = sp24; + return out; + } + } + return actor_draw(marker, gfx, mtx, vtx); +} + +void chAutumnOutsideNabnut_getPosition(f32 dst[3]){ + dst[0] = chAutumnOutdoorNabnutPosition[0]; + dst[1] = chAutumnOutdoorNabnutPosition[1]; + dst[2] = chAutumnOutdoorNabnutPosition[2]; +} + +void chAutumnOutsideNabnut_update(Actor *this) { + ActorLocal_ChAutumnNabnutPosition *local; + f32 player_position[3]; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; + + local = (ActorLocal_ChAutumnNabnutPosition *)&this->local; + if (!this->volatile_initialized) { + this->volatile_initialized = true; + chAutumnOutdoorNabnutPosition[0] = this->position[0]; + chAutumnOutdoorNabnutPosition[1] = this->position[1]; + chAutumnOutdoorNabnutPosition[2] = this->position[2]; + if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_0_NOT_INIT) { + this->has_met_before = false; + local->returned_acorn_count = port_puzzleCount_get(ANCHOR_COUNT_CCW_NABNUT_ACORNS); + sNabnutRemote = 0; + } + chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD); + if(jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT)) { + marker_despawn(this->marker); + } + return; + } + + if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { + player_getPosition(player_position); + if (!this->has_met_before + && (ml_vec3f_distance(this->position, player_position) < 400.0f)) + { + this->has_met_before = true; + gcdialog_showDialog( + VER_SELECT(ASSET_CCA_DIALOG_NABNUT_MEET_FALL, 0x09DF, 0, 0), + 0xE, this->position, + NULL, NULL, NULL); + } + if (item_getCount(ITEM_23_ACORNS) > 0) { + func_80258A4C( + this->position, + this->yaw - 90.0f, + player_position, + &horizontal_distance, + &distance_in_front, + &side_angle_radian); + this->yaw += side_angle_radian * 10.0f; + } + if (this->has_met_before && !gcdialog_hasCurrentTextId()) { + player_setCarryObjectPoseInCylinder(this->position, 500.0f, 200.0f, ACTOR_2A9_ACORN, &this); + if ((carriedObj_getActorId() == ACTOR_2A9_ACORN) + && (ml_vec3f_distance(this->position, player_position) < 300.0f) + && player_throwCarriedObject()) + { + player_setThrowTargetPosition(chAutumnOutdoorNabnutPosition); + port_puzzleCount_add(ANCHOR_COUNT_CCW_NABNUT_ACORNS, 1); + local->returned_acorn_count = port_puzzleCount_get(ANCHOR_COUNT_CCW_NABNUT_ACORNS); + if (local->returned_acorn_count >= AUTUMN_NABNUT_ACORN_COUNT) { + chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT); + } else if (item_getCount(ITEM_23_ACORNS) == 1) { + gcdialog_showDialog( + VER_SELECT(ASSET_CCB_DIALOG_NABNUT_ACORN_CHECK, 0x09E0, 0, 0), + 0x20, this->position, + NULL, NULL, NULL); + } + } + } + if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { + s32 sharedReturned = port_puzzleCount_get(ANCHOR_COUNT_CCW_NABNUT_ACORNS); + if (sharedReturned > local->returned_acorn_count) { + local->returned_acorn_count = sharedReturned; + if (sharedReturned >= AUTUMN_NABNUT_ACORN_COUNT) { + sNabnutRemote = 1; + chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT); + } + } + } + } + if ((this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP) + && (skeletalAnim_getLoopCount(this->unk148) > 0)) + { + chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER); + } + if ((this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER) + && (skeletalAnim_getLoopCount(this->unk148) > 0)) + { + chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT); + } + if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT) { + actor_update_func_80326224(this); + func_8028FC8C(this->position); + if (0.99 < this->unk48) { + chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_6_DESPAWN); + } + } + func_8028E668(this->position, 300.0f, -50.0f, 120.0f); +} diff --git a/src/CCW/ch/seasonswitchdoors.c b/src/CCW/ch/seasonswitchdoors.c new file mode 100644 index 000000000..9882d0946 --- /dev/null +++ b/src/CCW/ch/seasonswitchdoors.c @@ -0,0 +1,245 @@ +// BanjoDecomp: CCW/ch/seasonswitchdoors.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + u8 unk0; + u8 returnMapId; + u8 cameraNode; + u8 returnEntryPoint; +} CH_Season_Switch_Doors_Cutscene_Info; + +void chSeasonSwitchDoors_update(Actor *this); +void chSeasonSwitch_update(Actor *this); + +/* .data */ +CH_Season_Switch_Doors_Cutscene_Info chSeasonSwitchDoorsCutsceneInfo[] = { + {0, MAP_40_CCW_HUB, 0, 5}, + {0, MAP_43_CCW_SPRING, 1, 5}, + {0, MAP_44_CCW_SUMMER, 2, 5}, + {0, MAP_45_CCW_AUTUMN, 3, 15} +}; + +ActorAnimationInfo chSeasonSwitchAnimations[] = { + {0, 0.0f}, + {0, 0.0f}, + {0, 0.0f}, + {0, 0.0f}, + {ASSET_D4_ANIM_SWITCH_DOWN, 0.5f}, + {ASSET_D4_ANIM_SWITCH_DOWN, 100000000.0f} +}; + +ActorInfo chCCWSpringSwitchDoor = { + MARKER_133_CCW_SPRING_SEASON_DOOR, ACTOR_1E3_CCW_SPRING_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, + 0x1, NULL, + chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0x4000, 0.0f, 0 +}; + +ActorInfo chCCWSpringSwitch = { + MARKER_132_CCW_SPRING_SWITCH, ACTOR_1E2_CCW_SPRING_SWITCH, ASSET_4F5_MODEL_CCW_SPRING_SWITCH, + 0x5, chSeasonSwitchAnimations, + chSeasonSwitch_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCCWSummerSwitchDoor = { + MARKER_131_CCW_SUMMER_SEASON_DOOR, ACTOR_16D_CCW_SUMMER_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, + 0x1, NULL, + chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0x4000, 0.0f, 0 +}; + +ActorInfo chCCWSummerSwitch = { + MARKER_130_CCW_SUMMER_SWITCH, ACTOR_16C_CCW_SUMMER_SWITCH, ASSET_4F6_MODEL_CCW_SUMMER_SWITCH, + 0x5, chSeasonSwitchAnimations, + chSeasonSwitch_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCCWAutumnSwitchDoor = { + MARKER_12F_CCW_AUTUMN_SEASON_DOOR, ACTOR_16B_CCW_AUTUMN_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, + 0x1, NULL, + chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0x4000, 0.0f, 0 +}; + +ActorInfo chCCWAutumnSwitch = { + MARKER_12E_CCW_AUTUMN_SWITCH, ACTOR_16A_CCW_AUTUMN_SWITCH, ASSET_4F7_MODEL_CCW_AUTUMN_SWITCH, + 0x5, chSeasonSwitchAnimations, + chSeasonSwitch_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCCWWinterSwitchDoor = { + MARKER_12D_CCW_WINTER_SEASON_DOOR, ACTOR_169_CCW_WINTER_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, + 0x1, NULL, + chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0x4000, 0.0f, 0 +}; + +ActorInfo chCCWWinterSwitch = { + MARKER_12C_CCW_WINTER_SWITCH, ACTOR_168_CCW_WINTER_SWITCH, ASSET_4F8_MODEL_CCW_WINTER_SWITCH, + 0x5, chSeasonSwitchAnimations, + chSeasonSwitch_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +enum chCCWSeasonSwitchDoor_State_e { + CH_CCW_SEASON_SWITCH_DOOR_STATE_0_NOT_INIT, + CH_CCW_SEASON_SWITCH_DOOR_STATE_1_LOWERED, + CH_CCW_SEASON_SWITCH_DOOR_STATE_2_OPENING, + CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED, + CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION +}; + +/* .code */ +s32 chCCWSwitchAndDoor_getSeason(Actor *this){ + switch(this->marker->id){ + case MARKER_133_CCW_SPRING_SEASON_DOOR: //L80388F28 + case MARKER_132_CCW_SPRING_SWITCH: //L80388F28 + return CCW_SEASON_0_SPRING; + + case MARKER_131_CCW_SUMMER_SEASON_DOOR: //L80388F30 + case MARKER_130_CCW_SUMMER_SWITCH: //L80388F30 + return CCW_SEASON_1_SUMMER; + + case MARKER_12F_CCW_AUTUMN_SEASON_DOOR: //L80388F38 + case MARKER_12E_CCW_AUTUMN_SWITCH: //L80388F38 + return CCW_SEASON_2_AUTUMN; + + case MARKER_12D_CCW_WINTER_SEASON_DOOR: //L80388F40 + case MARKER_12C_CCW_WINTER_SWITCH: //L80388F40 + return CCW_SEASON_3_WINTER; + + default: + return CCW_SEASON_0_SPRING; + } +} + + +void chSeasonSwitch_pressed(ActorMarker *marker, ActorMarker *other_marker){ + Actor *this; + + this = marker_getActor(marker); + if ((player_movementGroup() != BSGROUP_1_INTR) && !this->unk38_0) { + this->unk38_0 = true; + actor_collisionOff(this); + subaddie_set_state_with_direction(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION, 0.0f, 1); + actor_playAnimationOnce(this); + func_8030E6D4(SFX_90_SWITCH_PRESS); + } +} + +void chSeasonSwitch_update(Actor *this) { + + if (!this->initialized) { + this->unk138_31 = this->unk124_0 = true; + this->marker->propPtr->unk8_3 = true; + this->unk10_12 = chCCWSwitchAndDoor_getSeason(this); + this->initialized = true; + } + if (!this->volatile_initialized) { + if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { + if (EventSystem_Should(VB_CCW_SEASON_SWITCH_PRESSED_INIT, true, this)) { + actor_playAnimationOnce(this); + subaddie_set_state_with_direction(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION, 0.999f, 1); + } + actor_collisionOff(this); + } else { + marker_setCollisionScripts(this->marker, NULL, &chSeasonSwitch_pressed, NULL); + } + this->unk38_0 = false; + this->volatile_initialized = true; + } + // Anchor: teammate pressed this switch (flag synced) — drop it to match; unk38_0 stays false. + if( this->state != CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION + && fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN) + ){ + actor_playAnimationOnce(this); + subaddie_set_state_with_direction(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION, 0.999f, 1); + actor_collisionOff(this); + } + if( (this->state == CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION) + && this->unk38_0 + && actor_animationIsAt(this, 0.999f) + ){ + func_802D6264( + 1.1f, + 0x40, + this->unk10_12 + 0x3C, + 0x2B, + chSeasonSwitchDoorsCutsceneInfo[this->unk10_12].returnEntryPoint, + this->unk10_12 + 0x8B); + func_80324E38(0.5f, 3); + timedFunc_set_2(1.1f, (GenFunction_2)levelSpecificFlags_set, this->unk10_12 + 7, true); + func_80324E38(5.6f, 0); + } +} + +void chSeasonSwitchDoors_doorOpening(void* marker) { + Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); + actor->unk44_31 = func_8030ED2C(SFX_3EC_CCW_DOOR_OPENING, 3); + func_8030DD90(actor->unk44_31, 0); + sfxsource_setSampleRate(actor->unk44_31, 11000); + sfxsource_playSfxAtVolume(actor->unk44_31, 0.3f); + sfxSource_func_8030E2C4(actor->unk44_31); +} + +void chSeasonSwitchDoors_doorOpened(void* marker) { + Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); + sfxSource_triggerCallbackByIndex(actor->unk44_31); + sfxsource_freeSfxsourceByIndex(actor->unk44_31); + actor->unk44_31 = 0U; + FUNC_8030E624(SFX_6C_LOCKUP_CLOSING, 1.0f, 25000); +} + +void chSeasonSwitchDoors_update(Actor *this) { + ActorProp *temp_v1; + u32 temp_v0; + u32 temp_v1_2; + + if(!this->initialized) { + this->unk58_2 = false; + this->unk10_12 = chCCWSwitchAndDoor_getSeason(this); + this->marker->propPtr->unk8_3 = true; + actor_collisionOff(this); + this->initialized = true; + } + if (!this->volatile_initialized) { + this->unk1C[0] = this->position[0]; + this->unk1C[1] = this->position[1]; + this->unk1C[2] = this->position[2]; + // [port] A savestate-restored door comes back at its raised position with + // volatile_initialized cleared. + if (this->state != CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED) { + this->unk1C[1] += 250.0f; + } + + this->volatile_initialized = true; + if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { + subaddie_set_state(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED); + } + } + + switch (this->state) { /* irregular */ + case CH_CCW_SEASON_SWITCH_DOOR_STATE_1_LOWERED: + if (levelSpecificFlags_get(this->unk10_12 + 7)) { + timedFunc_set_1(0.05f, (GenFunction_1)chSeasonSwitchDoors_doorOpening, (uintptr_t)this->marker); + timedFunc_set_1(4.0f, (GenFunction_1)chSeasonSwitchDoors_doorOpened, (uintptr_t)this->marker); + subaddie_set_state(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_2_OPENING); + } + break; + case CH_CCW_SEASON_SWITCH_DOOR_STATE_2_OPENING: + this->position[1] += 60.0f * time_getDelta(); + if (this->unk1C[1] <= this->position[1]) { + levelSpecificFlags_set(this->unk10_12 + 7, false); + subaddie_set_state(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED); + } + break; + case CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED: + this->position[1] = this->unk1C[1]; + break; + } +} diff --git a/src/CCW/ch/snarebear.c b/src/CCW/ch/snarebear.c index 88af55bee..de8de25c8 100644 --- a/src/CCW/ch/snarebear.c +++ b/src/CCW/ch/snarebear.c @@ -1,24 +1,140 @@ -// BanjoDecomp: code_7BC0.c +// BanjoDecomp: CCW/ch/snarebear.c #include #include "functions.h" #include "variables.h" -void func_8038DFB0(Actor *this); +void chSnarebear_update(Actor *this); -ActorAnimationInfo D_8038F8B0[] = { - {0x000, 0.0f}, - {0x234, 2.0f} +/* .data */ +ActorAnimationInfo chSnarebearAnimations[] = { + {0x000, 0.0f}, + {ASSET_16C_ANIM_SNAREBEAR_IDLE, 2.0f}, + {ASSET_16B_ANIM_SNAREBEAR_ATTACK, 1.2f} }; -ActorInfo D_8038F8C0 = { 0x251, 0x37E, 0x506, - 0x1, D_8038F8B0, - func_8038DFB0, actor_update_func_80326224, actor_draw, +ActorInfo chSnarebear = { + MARKER_1F9_SNARE_BEAR, ACTOR_1E9_SNARE_BEAR, ASSET_440_MODEL_SNAREBEAR, + 0x1, chSnarebearAnimations, + chSnarebear_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; +enum chSnarebear_State_e { + CH_SNAREBEAR_STATE_0_NOT_INIT, + CH_SNAREBEAR_STATE_1_IDLE, + CH_SNAREBEAR_STATE_2_ATTACK +}; + /* .code */ -void func_8038DFB0(Actor *this){ - this->marker->propPtr->unk8_3 = true; - actor_collisionOff(this); +void chSnarebear_idle(Actor* actor) { + subaddie_set_state_with_direction(actor, CH_SNAREBEAR_STATE_1_IDLE, 0.001f, 1); + actor->unk38_31 = randi2(0, 0); +} + +void chSnarebear_attack(Actor* actor) { + subaddie_set_state_with_direction(actor, CH_SNAREBEAR_STATE_2_ATTACK, 0.001f, 1); +} + +void func_8038E060(BoneTransformList *bone_transform_list, ActorMarker *marker){ + Actor *this; + f32 sp28[3]; + s32 pad24; + f32 sp18[4]; // quaternion: func_80345C78 writes 4 floats + + this = marker_getActor(marker); + if(bone_transform_list){ + sp28[0] = 0.0f; + sp28[1] = this->unk1C[0]; + sp28[2] = 0.0f; + + + func_80345C78(sp18, sp28); + func_8033A8F0(bone_transform_list, 1, sp18); + modelRender_setBoneTransformList(bone_transform_list); + } +} + +void chSnarebear_update(Actor *this) { + f32 player_position[3]; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; + f32 time_delta; + + time_delta = time_getDelta(); + + if(!subaddie_playerIsWithinSphere(this, 3000)) return; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + func_8028746C(this->anctrl, (GenFunction_2)func_8038E060); + func_8028748C(this->anctrl, (uintptr_t)this->marker); + this->marker->propPtr->unk8_3 = true; + this->unk1C[0] = 0.0f; + this->unk38_31 = 0; + } + + if (player_getTransformation() == TRANSFORM_6_BEE) { + actor_collisionOff(this); + } else { + actor_collisionOn(this); + player_getPosition(player_position); + func_80258A4C( + this->position, + this->yaw - 90.0f, + player_position, + &horizontal_distance, + &distance_in_front, + &side_angle_radian); + if( (horizontal_distance < 1050.0f) + && (side_angle_radian > -1.0f) + && (side_angle_radian < 1.0f) + ) { + func_80258A4C( + this->position, + this->unk1C[0] + (this->yaw - 90.0f), + player_position, + &horizontal_distance, + &distance_in_front, + &side_angle_radian); + this->unk1C[0] += side_angle_radian * 160.0f * time_delta; + } else { + if (this->unk1C[0] > 0.0f) { + this->unk1C[0] -= (30.0f * time_delta); + this->unk1C[0] = (this->unk1C[0] < 0.0f) ? 0.0f : this->unk1C[0]; + + } else if (this->unk1C[0] < 0.0f) { + this->unk1C[0] += (30.0f * time_delta); + this->unk1C[0] = (this->unk1C[0] > 0.0f) ? 0.0f : this->unk1C[0]; + } + } + } + switch (this->state) { + case CH_SNAREBEAR_STATE_1_IDLE: + if (this->unk38_31 != 0) { + this->unk38_31--; + break; + } + if( subaddie_playerIsWithinSphereAndActive(this, 680) + && (this->unk38_31 == 0) + && (player_getTransformation() == TRANSFORM_1_BANJO) + ) { + chSnarebear_attack(this); + } + break; + + case CH_SNAREBEAR_STATE_2_ATTACK: + if (actor_animationIsAt(this, 0.999f)) { + chSnarebear_idle(this); + break; + } + if( actor_animationIsAt(this, 0.18f) + || actor_animationIsAt(this, 0.47f) + || actor_animationIsAt(this, 0.78f) + ) { + sfx_playFadeShorthandDefault(SFX_80_YUMYUM_CLACK, 1.0f, 32000, this->position, 1500, 3000); + } + break; + } } diff --git a/src/CCW/ch/snore.c b/src/CCW/ch/snore.c index f4159827c..74a08c8fb 100644 --- a/src/CCW/ch/snore.c +++ b/src/CCW/ch/snore.c @@ -6,15 +6,27 @@ void chSnoreZ_update(Actor *this); /* .data */ -ActorInfo D_8038F6F0 = { 0x1C3, 0x30C, 0x4E4, 0x0, NULL, chSnoreZ_update, NULL, actor_draw, 0, 0, 0.0f, 0}; + +enum chSnoreZ_state_e { + SNORE_Z_STATE_0_NOT_INIT, + SNORE_Z_STATE_1_SPAWN_IN, + SNORE_Z_STATE_2_FADE_AWAY +}; + +ActorInfo chSnoreZ = { + MARKER_1C3_SNORE_Z, ACTOR_30C_SNORE_Z, ASSET_4E4_MODEL_SNORE_Z, + 0x0, NULL, + chSnoreZ_update, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; /* .code */ void chSnoreZ_setNextState(Actor *this, s32 next_state) { - if (next_state == 1) { - skeletalAnim_set(this->unk148, 0x21C, 0.0f, 6.0f); + if (next_state == SNORE_Z_STATE_1_SPAWN_IN) { + skeletalAnim_set(this->unk148, ASSET_21C_ANIM_SNORE_Z, 0.0f, 6.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } - if (next_state == 2) { + if (next_state == SNORE_Z_STATE_2_FADE_AWAY) { func_80326310(this); } this->state = next_state; @@ -27,15 +39,15 @@ void chSnoreZ_update(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; - this->depth_mode = 2; + this->depth_mode = MODEL_RENDER_DEPTH_COMPARE; this->marker->unk40_22 = true; - chSnoreZ_setNextState(this, 1); + chSnoreZ_setNextState(this, SNORE_Z_STATE_1_SPAWN_IN); } - if (this->state == 1) { + if (this->state == SNORE_Z_STATE_1_SPAWN_IN) { this = this; skeletalAnim_getProgressRange(this->unk148, &sp24, &sp20); if ((sp24 < 0.25f) && (sp20 >= 0.25f)) { - chSnoreZ_setNextState(this, 2); + chSnoreZ_setNextState(this, SNORE_Z_STATE_2_FADE_AWAY); } } } diff --git a/src/CCW/ch/springnabnut.c b/src/CCW/ch/springnabnut.c new file mode 100644 index 000000000..82023570c --- /dev/null +++ b/src/CCW/ch/springnabnut.c @@ -0,0 +1,110 @@ +// BanjoDecomp: CCW/ch/springnabnut.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 currSFXProgress; +}ActorLocal_CCW_4D00; + +typedef struct { + f32 sfxProgress; + f32 volume; + s16 sfxId; + s16 sampleRate; +} CH_NABNUT_SPRING_SFX; + +void chNabnutSpring_update(Actor *this); + +/* .data */ + +ActorInfo chNabnutSpring = { + MARKER_1B9_NABNUT_SPRING, ACTOR_2A6_NABNUT_SPRING, ASSET_502_MODEL_NABNUT, + 0x0, NULL, + chNabnutSpring_update, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +CH_NABNUT_SPRING_SFX chNabnutSpringSfx[] = { + {0.12f, 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, + {0.21f, 1.7f, SFX_A7_WOODEN_SWOSH, 8500}, + {0.3f , 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, + {0.51f, 1.0f, SFX_4C_LIP_SMACK, 22000}, + {0.65f, 1.05f, SFX_4C_LIP_SMACK, 23000}, + {0.76f, 1.0f, SFX_4C_LIP_SMACK, 22000}, + {0.88f, 1.0f, SFX_4C_LIP_SMACK, 23000}, + 0 +}; + +enum chNabnutSpring_State_e { + CH_NABNUT_SPRING_STATE_0_NOT_INIT, + CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND, + CH_NABNUT_SPRING_STATE_2_EATING +}; + +/* .code */ +void chNabnutSpring_setState(Actor *this, s32 next_state) { + ActorLocal_CCW_4D00 *local = (ActorLocal_CCW_4D00 *)&this->local; + + local->currSFXProgress = 0.0f; + if (next_state == CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND) { + skeletalAnim_swap(this->unk148, ASSET_1A3_ANIM_NABNUT_SPRING_LOOKING_AROUND, 0.2f, 11.0f); + local->currSFXProgress = randf2(3.0f, 10.0f); + } + if (next_state == CH_NABNUT_SPRING_STATE_2_EATING) { + skeletalAnim_set(this->unk148, ASSET_1A4_ANIM_NABNUT_SPRING_EATING, 0.2f, 3.0f); + } + this->state = next_state; +} + +void chNabnutSpring_update(Actor *this) { + ActorLocal_CCW_4D00 *local; + f32 tick; + CH_NABNUT_SPRING_SFX *iPtr; + f32 prev_progress; + f32 curr_progress; + + local = (ActorLocal_CCW_4D00 *)&this->local; + tick = time_getDelta(); + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->has_met_before = false; + chNabnutSpring_setState(this, CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND); + } + + if ((this->state == CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND) && ml_timer_update(&local->currSFXProgress, tick)) { + chNabnutSpring_setState(this, CH_NABNUT_SPRING_STATE_2_EATING); + } + + if (this->state == CH_NABNUT_SPRING_STATE_2_EATING) { + skeletalAnim_getProgressRange(this->unk148, &prev_progress, &curr_progress); + for(iPtr = &chNabnutSpringSfx[0]; iPtr->sfxProgress > 0.0f; iPtr++){ + if ((prev_progress < iPtr->sfxProgress) && (iPtr->sfxProgress <= curr_progress)) { + func_8030E878( + iPtr->sfxId, + randf2(iPtr->volume - 0.05, iPtr->volume + 0.05), + randi2(iPtr->sampleRate - 500, iPtr->sampleRate + 500), + this->position, + 500.0f, + 2500.0f); + } + } + + if ((prev_progress < 0.97) && (0.97 <= curr_progress)) { + if (randf() >= 0.5) { + func_8030E878(SFX_AE_YUMYUM_TALKING, randf2(1.8f, 1.85f), randi2(19000, 21000), this->position, 500.0f, 2500.0f); + } else { + func_8030E878(SFX_4B_GULPING, randf2(1.4f, 1.45f), randi2(24000, 26000), this->position, 500.0f, 2500.0f); + } + } + if (skeletalAnim_getLoopCount(this->unk148) > 0) { + chNabnutSpring_setState(this, CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND); + } + } + if (!this->has_met_before && func_803292E0(this)) { + this->has_met_before = TRUE; + gcdialog_showDialog(VER_SELECT(ASSET_CC8_DIALOG_NABNUT_MEET_SPRING, 0x09DD, 0, 0), 0, NULL, NULL, NULL, NULL); + } + func_8028E668(this->position, 300.0f, -50.0f, 120.0f); +} diff --git a/src/CCW/ch/summeroutsidegnawty.c b/src/CCW/ch/summeroutsidegnawty.c new file mode 100644 index 000000000..4ebb00d9c --- /dev/null +++ b/src/CCW/ch/summeroutsidegnawty.c @@ -0,0 +1,160 @@ +// BanjoDecomp: CCW/ch/summeroutsidegnawty.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + f32 sfxProgress; + f32 volume; + s16 sfxId; + s16 sampleRate; +} CH_Gnawty_Summer_SFX; + +void chGnawtySummer_update(Actor *this); + +/* .data */ + +ActorInfo chGnawtySummer = { + MARKER_1BE_GNAWTY_SUMMER, ACTOR_2AB_GNAWTY_SUMMER, ASSET_48F_MODEL_GNAWTY, + 0x0, NULL, + chGnawtySummer_update, chGnawtySummer_update, actor_draw, + 0, 0, 2.2f, 0 +}; + +CH_Gnawty_Summer_SFX chGnawtySummerIdleSfx[] = { + {0.11f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.23f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.34f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.58f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, + {0.8f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, + 0 +}; + +CH_Gnawty_Summer_SFX chGnawtySummerCheeringSfx[] = { + {0.07f, 1.6f, SFX_56_BANJO_HUI, 32000}, + {0.17f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.22f, 1.6f, SFX_55_BANJO_HOO_2, 32000}, + {0.31f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.33f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, + {0.45f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.49f, 1.7f, SFX_55_BANJO_HOO_2, 32600}, + {0.6f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.63f, 1.7f, SFX_56_BANJO_HUI, 32600}, + {0.74f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.79f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, + {0.9f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + 0 +}; + +CH_Gnawty_Summer_SFX chGnawtySummerRunningSfx[] = { + {0.01f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.5f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + 0 +}; + +enum chGnawtySummer_State_e { + CH_GNAWTY_SUMMER_STATE_0_NOT_INIT, + CH_GNAWTY_SUMMER_STATE_1_IDLE, + CH_GNAWTY_SUMMER_STATE_2_CHEERING, + CH_GNAWTY_SUMMER_STATE_3_RUNNING, + CH_GNAWTY_SUMMER_STATE_4_DESPAWN +}; + +/* .code */ +void chGnawtySummer_setState(Actor *this, s32 next_state) { + ActorProp *temp_v0; + + if (next_state == CH_GNAWTY_SUMMER_STATE_1_IDLE) { + skeletalAnim_set(this->unk148, ASSET_1A6_ANIM_GNAWTY_IDLE, 0.2f, 4.5f); + } + if (next_state == CH_GNAWTY_SUMMER_STATE_2_CHEERING) { + this->marker->propPtr->unk8_3 = false; + skeletalAnim_set(this->unk148, ASSET_1A7_ANIM_GNAWTY_CHEERING, 0.2f, 3.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + gcdialog_showDialog(VER_SELECT(ASSET_CD0_DIALOG_GNAWTY_COMPLETE_SUMMER, 0x9E5, 0, 0), 0x24, NULL, NULL, NULL, NULL); + } + if (next_state == CH_GNAWTY_SUMMER_STATE_3_RUNNING) { + skeletalAnim_set(this->unk148, ASSET_1A8_ANIM_GNAWTY_RUNNING, 0.2f, 0.5f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + if (next_state == CH_GNAWTY_SUMMER_STATE_4_DESPAWN) { + marker_despawn(this->marker); + } + this->state = next_state; +} + +void chGnawtySummer_update(Actor *this) { + CH_Gnawty_Summer_SFX *sfx_list; + f32 prev_progress; + f32 curr_progress; + f32 player_position[3]; + + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_1_IDLE); + if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY) != false) { + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); + } + if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) != false) { + marker_despawn(this->marker); + } + return; + } + + if (this->state == CH_GNAWTY_SUMMER_STATE_1_IDLE) { + sfx_list = chGnawtySummerIdleSfx; + } else if (this->state == CH_GNAWTY_SUMMER_STATE_2_CHEERING) { + sfx_list = chGnawtySummerCheeringSfx; + } else if (this->state == CH_GNAWTY_SUMMER_STATE_3_RUNNING) { + sfx_list = chGnawtySummerRunningSfx; + } else{ + sfx_list = NULL; + } + + if (sfx_list != NULL) { + skeletalAnim_getProgressRange(this->unk148, &prev_progress, &curr_progress); + while(sfx_list->sfxProgress > 0.0f){ + if (((prev_progress < sfx_list->sfxProgress) || (curr_progress < prev_progress)) + && (sfx_list->sfxProgress <= curr_progress)) + { + func_8030E878( + sfx_list->sfxId, + randf2(sfx_list->volume - 0.05, sfx_list->volume + 0.05), + randi2(sfx_list->sampleRate - 200, sfx_list->sampleRate + 100), + this->position, + 500.0f, + 1500.0f); + } + sfx_list++; + } + } + + if (this->state == CH_GNAWTY_SUMMER_STATE_1_IDLE) { + if (!this->has_met_before) { + player_getPosition(player_position); + if (ml_vec3f_distance(this->position, player_position) < 900.0f) { + gcdialog_showDialog(VER_SELECT(ASSET_CCF_DIALOG_GNAWTY_MEET_SUMMER, 0x9E4, 0, 0), 4, NULL, NULL, NULL, NULL); + this->has_met_before = TRUE; + } + } + + if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) != false) { + chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_2_CHEERING); + } + } + + if (this->state == CH_GNAWTY_SUMMER_STATE_2_CHEERING){ + if((skeletalAnim_getLoopCount(this->unk148) > 0)) { + chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_3_RUNNING); + } + } + + if (this->state == CH_GNAWTY_SUMMER_STATE_3_RUNNING) { + actor_update_func_80326224(this); + if (0.99 < (f64) this->unk48) { + chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_4_DESPAWN); + } + } +} diff --git a/src/CCW/ch/swimminggnawty.c b/src/CCW/ch/swimminggnawty.c new file mode 100644 index 000000000..2976ce50e --- /dev/null +++ b/src/CCW/ch/swimminggnawty.c @@ -0,0 +1,140 @@ +// BanjoDecomp: CCW/ch/swimminggnawty.c +#include +#include "functions.h" +#include "variables.h" + +extern ParticleEmitter *func_802EDD8C(f32[3], f32, f32); + +typedef struct{ + s16 map_id; + s16 despawnIfJiggyCollected; + s16 dialog; +} CH_GNAWTY_SWIMMING_DIALOG; + +typedef struct{ + CH_GNAWTY_SWIMMING_DIALOG *dialog; + f32 unk4[3]; +} ActorLocal_CCW_6620; + +Actor *chGnawtySwimming_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chGnawtySwimming_update(Actor *this); + +/* .data */ +CH_GNAWTY_SWIMMING_DIALOG chGnawtySwimmingDialogs[] ={ + {MAP_43_CCW_SPRING, FALSE, VER_SELECT(ASSET_CCE_DIALOG_GNAWTY_MEET_SPRING, 0x09E3, 0, 0)}, + {MAP_45_CCW_AUTUMN, TRUE, VER_SELECT(ASSET_CD1_DIALOG_GNAWTY_MEET_FALL_OUTSIDE, 0x09E6, 0, 0)}, + {MAP_46_CCW_WINTER, TRUE, VER_SELECT(ASSET_CD3_DIALOG_GNAWTY_MEET_WINTER_OUTSIDE, 0x09E8, 0, 0)}, + { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion +}; + +enum chGnawtySwimming_State_e { + CH_GNAWTY_SWIMMING_STATE_0_NOT_INIT, + CH_GNAWTY_SWIMMING_STATE_1_SWIMMING +}; + +ActorInfo chGnawtySwimming = { + MARKER_1BD_GNAWTY_SWIMMING, ACTOR_2AA_GNAWTY_SWIMMING, ASSET_48F_MODEL_GNAWTY, + 0x0, NULL, + chGnawtySwimming_update, NULL, chGnawtySwimming_draw, + 0, 0, 2.2f, 0 +}; + +/* .code */ +void chGnawtySwimming_emitParticles(ActorMarker *marker) { + Actor *this; + ActorLocal_CCW_6620 *local; + ParticleEmitter *pCtrl; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_6620 *)&this->local; + + if (this->marker->unk14_21) { + if (0.65 < (f64) randf()) { + pCtrl = func_802EDD8C(local->unk4, 0.0f, this->position[1] + 500.0f); + particleEmitter_setStartingScaleRange(pCtrl, 0.04f, 0.05f); + particleEmitter_setFinalScaleRange(pCtrl, 0.18f, 0.2f); + particleEmitter_setSpawnPositionRange(pCtrl, -10.0f, 0.0f, -10.0f, 10.0f, 20.0f, 10.0f); + particleEmitter_setParticleVelocityRange(pCtrl, 0.0f, 31.0f, 0.0f, 0.0f, 37.0f, 0.0f); + particleEmitter_emitN(pCtrl, 1); + } + } +} + +void chGnawtySwimming_setState(Actor *this, s32 next_state) { + int i; + + if (next_state == CH_GNAWTY_SWIMMING_STATE_1_SWIMMING) { + skeletalAnim_set(this->unk148, 0x289, 0.2f, 1.1f); + for(i = 0; i < 10; i++){ + skeletalAnim_setCallback_1(this->unk148, randf(), (GenFunction_1)chGnawtySwimming_emitParticles, (uintptr_t)this->marker); + } + } + this->state = next_state; +} + + +Actor *chGnawtySwimming_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + ActorLocal_CCW_6620 *local; + + this = actor_draw(marker, gfx, mtx, vtx); + local = (ActorLocal_CCW_6620 *)&this->local; + if (this->marker->unk14_21) { + vec3fArray_get_vec3f(func_80329934(), 5, local->unk4); + } + return this; +} + +void chGnawtySwimming_update(Actor *this) { + ActorLocal_CCW_6620 *local; + f32 player_pos_1[3]; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; + f32 player_pos_2[3]; + + local = (ActorLocal_CCW_6620 *)&this->local; + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + local->dialog = &chGnawtySwimmingDialogs[0]; + while(local->dialog->map_id != 0 && gsworld_getMap() != local->dialog->map_id){ + local->dialog++; + } + chGnawtySwimming_setState(this, CH_GNAWTY_SWIMMING_STATE_1_SWIMMING); + + if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); + } + + if ((local->dialog->despawnIfJiggyCollected != false) + && levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED)) + { + marker_despawn(this->marker); + } + + return; + } + + if (this->state == CH_GNAWTY_SWIMMING_STATE_1_SWIMMING && this->marker->unk14_21) { + player_getPosition(player_pos_1); + func_80258A4C( + this->position, this->yaw - 90.0f, player_pos_1, + &horizontal_distance, &distance_in_front, &side_angle_radian); + if (horizontal_distance > 100.0f) { + this->yaw += 30.0f * side_angle_radian; + } + } + if (!this->has_met_before) { + player_getPosition(player_pos_2); + if (ml_vec3f_distance(this->position, player_pos_2) < 900.0f) { + if (local->dialog->map_id != MAP_46_CCW_WINTER + || func_8028F2FC()) + { + gcdialog_showDialog(local->dialog->dialog, 4, NULL, NULL, NULL, NULL); + this->has_met_before = true; + } + } + } +} diff --git a/src/CCW/ch/vacationtexttrigger.c b/src/CCW/ch/vacationtexttrigger.c index 474616d49..dbf39717e 100644 --- a/src/CCW/ch/vacationtexttrigger.c +++ b/src/CCW/ch/vacationtexttrigger.c @@ -39,7 +39,7 @@ void chVacationTextTrigger_update(Actor* this) { // Start dialog if player is within trigger if (__playerIsWithinTrigger(0, -107, 188) != 0) { - gcdialog_showDialog(0xDA9, 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_DA9_DIALOG_MUMBO_CCW_VACATION, 0x0A27, 0, 0), 4, NULL, NULL, NULL, NULL); volatileFlag_set(VOLATILE_FLAG_13_HAS_TRIGGERED_MUMBO_VACATION_TEXT, 1); } } diff --git a/src/CCW/ch/zubba.c b/src/CCW/ch/zubba.c deleted file mode 100644 index d3367f084..000000000 --- a/src/CCW/ch/zubba.c +++ /dev/null @@ -1,216 +0,0 @@ -// BanjoDecomp: code_950.c -#include -#include "functions.h" -#include "variables.h" - -extern void func_8030DBFC(u8, f32, f32, f32); - -typedef struct{ - u8 sfxsourceIdx; - //u8 pad1[3]; - ActorMarker *unk4; - f32 unk8[3]; - f32 unk14; - f32 unk18; -}ActorLocal_CCW_950; - -void chwasp_update(Actor *this); - -/* .data */ -ActorInfo D_8038EBD0 = { MARKER_1AE_ZUBBA, ACTOR_29B_ZUBBA, ASSET_446_MODEL_ZUBBA, 0x0, NULL, chwasp_update, NULL, actor_draw, 0, 0, 1.0f, 0}; - -/* .code */ -void chwasp_setState(Actor *this, s32 next_state) { - ActorLocal_CCW_950 *local; - f32 sp50[3]; - f32 sp44[3]; - - local = (ActorLocal_CCW_950 *)&this->local; - local->unk18 = 0.0f; - if (next_state == 1) { - local->unk18 = 800.0f; - skeletalAnim_set(this->unk148, ASSET_16F_ANIM_ZUBBA_FLY_MOVE, 0.0f, 0.65f); - } - if (next_state == 2) { - skeletalAnim_set(this->unk148, ASSET_170_ANIM_ZUBBA_FLY_IDLE, 0.1f, 0.65f); - player_getPosition(sp50); - sp50[1] += 50.0f; - local->unk8[0] = sp50[0] - this->position[0]; - local->unk8[1] = sp50[1] - this->position[1]; - local->unk8[2] = sp50[2] - this->position[2]; - ml_vec3f_normalize(local->unk8); - if ((local->unk8[0] == 0.0f) && (local->unk8[1] == 0.0f) && (local->unk8[2] == 0.0f)) { - local->unk8[1] = -1.0f; - } - } - if (next_state == 3) { - sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); - func_80324D54(randf2(0.1f, 0.4f), 0x3FC, randf2(0.95f, 1.1f), 32000, this->position, 500.0f, 3000.0f); - actor_collisionOff(this); - } - if (next_state == 4) { - skeletalAnim_set(this->unk148, ASSET_171_ANIM_ZUBBA_DIE, 0.1f, 0.2f); - sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); - func_80324D54(0.1f, 0x66, randf2(1.6f, 1.7f), 32000, this->position, 500.0f, 3000.0f); - func_803867C8(local->unk4); - actor_collisionOff(this); - player_getPosition(sp44); - sp44[1] += 50.0f; - local->unk8[0] = this->position[0] - sp44[0]; - local->unk8[1] = this->position[1] - sp44[1]; - local->unk8[2] = this->position[2] - sp44[2]; - ml_vec3f_normalize(local->unk8); - if ((local->unk8[0] == 0.0f) && (local->unk8[1] == 0.0f) && (local->unk8[2] == 0.0f)) { - local->unk8[1] = -1.0f; - } - } - if (next_state == 5) { - func_8030E878(SFX_A_BANJO_LANDING_05, randf2(0.85f, 0.95f), 18000, this->position, 500.0f, 3000.0f); - skeletalAnim_set(this->unk148, ASSET_172_ANIM_ZUBBA_LAND, 0.0f, 1.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - } - if (next_state == 6) { - marker_despawn(this->marker); - } - if (next_state == 7) { - func_80386814(local->unk4); - marker_despawn(this->marker); - } - this->state = next_state; -} - - -void func_80387124(ActorMarker* marker, ActorMarker *other_marker) { - chwasp_setState(marker_getActor(marker), 3); -} - -void CCW_func_80387150(ActorMarker* marker, ActorMarker *other_marker) { - chwasp_setState(marker_getActor(marker), 4); -} - -void func_8038717C(Actor *this){ - ActorLocal_CCW_950 *local; - - local = (ActorLocal_CCW_950 *)&this->local; - sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); -} - -void chwasp_update(Actor *this) { - ActorLocal_CCW_950 *local; - f32 sp68; - Actor *other; - s32 sp60; - s32 sp5C; - f32 sp50[3]; - f32 sp4C; - f32 sp48; - f32 sp44; - f32 temp_f0; - f32 pad; - - - sp68 = time_getDelta(); - local = (ActorLocal_CCW_950 *)&this->local; - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->actorFreeFunc = func_8038717C; - local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); - local->unk4 = 0; - local->unk14 = 1000.0f; - sfxsource_setSfxId(local->sfxsourceIdx, 0x3FA); - sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); - sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); - sfxsource_setSampleRate(local->sfxsourceIdx, 0); - marker_setCollisionScripts(this->marker, func_80387124, NULL, CCW_func_80387150); - chwasp_setState(this, 1); - return; - } - if(local->unk4 == NULL) { - other = actorArray_findActorFromActorId(0x299); - if (other == NULL) { - marker_despawn(this->marker); - return; - } - local->unk4 = other->marker; - func_80386840(local->unk4, &sp60, &sp5C); - local->unk14 = (((f32)sp60 /(f32)sp5C) * 1000.0f) + 1000.0f; - } - - if (this->state == 1) { - temp_f0 = this->position[1]; - this->position[0] += 0.1 * sp68; - this->position[1] += local->unk18 * sp68; - if ((temp_f0 < 0.0f) && (this->position[1] >= 0.0f)) { - func_8030E878(SFX_A_BANJO_LANDING_05, randf2(1.0f, 1.1f), 18000, this->position, 500.0f, 3000.0f); - } - player_getPosition(sp50); - func_80258A4C(this->position, this->yaw - 90.0f, sp50, &sp4C, &sp48, &sp44); - this->yaw += 360.0f * sp44 * sp68; - if (this->position[1] > 150.0f) { - local->unk18 -= 2000.0f * sp68; - if (local->unk18 < 0.0f) { - chwasp_setState(this, 2); - } - } - } - - if (this->state == 2) { - if (local->unk18 < local->unk14) { - local->unk18 += (4.0f * local->unk14 * sp68); - } - this->position[0] += local->unk8[0] * local->unk18 * sp68; - this->position[1] += local->unk8[1] * local->unk18 * sp68; - this->position[2] += local->unk8[2] * local->unk18 * sp68; - if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) - || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) - || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) - ){ - chwasp_setState(this, 7); - } - } - - if (this->state == 3) { - this->position[1] += local->unk18 * sp68; - if (local->unk18 < local->unk14) { - local->unk18 += 2000.0f * sp68; - } - - if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) - || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) - || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) - ) { - chwasp_setState(this, 7); - } - } - - if (this->state == 4) { - this->position[0] += local->unk8[0] * 1000.0f * sp68; - this->position[1] -= local->unk18 * sp68; - this->position[2] += local->unk8[2] * 1000.0f * sp68; - if (local->unk18 < local->unk14) { - local->unk18 += (1000.0f * sp68); - } - if (this->position[1] <= 0.0f) { - this->position[1] = 0.0f; - chwasp_setState(this, 5); - } - } - - if (this->state == 5) { - this->position[1] -= 300.0f * sp68; - if (this->position[1] < -200.0f) { - chwasp_setState(this, 6); - } - } - - if(this->state); - if (this->state == 2) { - func_8030DBFC(local->sfxsourceIdx, 1.0f, 1.1f, 0.05f); - } else { - func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); - } - sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); - sfxsource_set_position(local->sfxsourceIdx, this->position); - sfxSource_func_8030E2C4(local->sfxsourceIdx); - sfxsource_setSampleRate(local->sfxsourceIdx, (s32) ((local->unk18 / local->unk14) * 10000.0f)); -} diff --git a/src/CCW/ch/zubba_hive_npc.c b/src/CCW/ch/zubba_hive_npc.c deleted file mode 100644 index 30c3a34ac..000000000 --- a/src/CCW/ch/zubba_hive_npc.c +++ /dev/null @@ -1,133 +0,0 @@ -// BanjoDecomp: code_14B0.c -#include "functions.h" -#include "variables.h" -#include - -#include - -extern void func_8030DBFC(u8, f32, f32, f32); -extern void sfxsource_setSampleRate(u8, s32); - -typedef struct{ - s16 unk0; - u8 unk2; - u8 unk3; - s16 unk4; -}Struct_CCW_14B0_0; - -typedef struct { - u8 sfxsourceIdx; - // u8 pad1[3]; - Struct_CCW_14B0_0 *unk4; - f32 unk8; - f32 unkC[3]; - f32 unk18[3]; -}ActorLocal_CCW_14B0; - -void CCW_func_80387A40(Actor *this); - -/* .data */ -Struct_CCW_14B0_0 D_8038EC00[] = { - {MAP_5B_CCW_SPRING_ZUBBA_HIVE, 0x7, 0x4C, 0xCE1}, - {MAP_5C_CCW_AUTUMN_ZUBBA_HIVE, 0x8, 0x00, 0xCE5}, - 0 -}; - -ActorInfo D_8038EC14 = { 0x1AF, 0x29C, 0x446, 0x0, NULL, CCW_func_80387A40, NULL, actor_draw, 0, 0, 1.0f, 0}; - -/* .code */ -void func_803878A0(Actor *this, s32 next_state) { - ActorLocal_CCW_14B0 *local = (ActorLocal_CCW_14B0 *)&this->local; - int i; - - if (next_state == 1) { - if (skeletalAnim_getAnimId(this->unk148) != 0x16F) { - skeletalAnim_set(this->unk148, 0x16F, 0.1f, 0.65f); - } - for(i = 0; i < 10; i++){ - local->unkC[0] = randf2(-500.0f, 500.0f); - local->unkC[1] = randf2(400.0f, 900.0f); - local->unkC[2] = randf2(-400.0f, 700.0f); - if(ml_vec3f_distance(this->position, local->unkC) > 800.0f) - break; - } - local->unk8 = randf2(500.0f, 1000.0f); - } - this->state = next_state; -} - -void CCW_func_80387A20(Actor *this){ - ActorLocal_CCW_14B0 *local = (ActorLocal_CCW_14B0 *)&this->local; - sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); -} - -void CCW_func_80387A40(Actor *this) { - ActorLocal_CCW_14B0 *local; - f32 sp68; - f32 sp5C[3]; - f32 sp58; - f32 sp54; - f32 sp50; - f32 sp44[3]; - - local = (ActorLocal_CCW_14B0 *)&this->local; - sp68 = time_getDelta(); - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->actorFreeFunc = CCW_func_80387A20; - local->unk4 = &D_8038EC00[0]; - while((local->unk4->unk0 != 0) && (gsworld_getMap() != local->unk4->unk0)) { - local->unk4++; - } - local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); - local->unk18[0] = local->unk18[1] = local->unk18[2] = 0.0f; - sfxsource_setSfxId(local->sfxsourceIdx, 0x3FA); - sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); - sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); - sfxsource_setSampleRate(local->sfxsourceIdx, 0); - func_803878A0(this, 1); - return; - } - - if (this->state == 1) { - sp5C[0] = local->unkC[0] - this->position[0]; - sp5C[1] = local->unkC[1] - this->position[1]; - sp5C[2] = local->unkC[2] - this->position[2]; - if (ml_vec3f_distance(this->position, local->unkC) < 500.0f) { - ml_vec3f_set_length(sp5C, local->unk8 * 8.0f); - } else { - ml_vec3f_set_length(sp5C, local->unk8 * 2); - } - this->position[0] += (local->unk18[0] * sp68) + (sp5C[0] * sp68 * sp68); - this->position[1] += (local->unk18[1] * sp68) + (sp5C[1] * sp68 * sp68); - this->position[2] += (local->unk18[2] * sp68) + (sp5C[2] * sp68 * sp68); - local->unk18[0] += sp5C[0] * sp68; - local->unk18[1] += sp5C[1] * sp68; - local->unk18[2] += sp5C[2] * sp68; - if (local->unk8 < LENGTH_VEC3F(local->unk18)) { - ml_vec3f_set_length(local->unk18, local->unk8); - } - func_80258A4C(this->position, this->yaw - 90.0f, local->unkC, &sp58, &sp54, &sp50); - this->yaw += 140.0f * sp50 * sp68; - if (ml_vec3f_distance(this->position, local->unkC) < 100.0f) { - func_803878A0(this, 1); - } - } - - if(this->position[0]); - - func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); - sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); - sfxsource_set_position(local->sfxsourceIdx, this->position); - sfxSource_func_8030E2C4(local->sfxsourceIdx); - sfxsource_setSampleRate(local->sfxsourceIdx, 2000.0f + 8000.0f*(LENGTH_VEC3F(local->unk18)/ local->unk8)); - if (!mapSpecificFlags_get(local->unk4->unk2)) { - player_getPosition(sp44); - if (sp44[2] > -600.0f) { - if (!local->unk4->unk3 || !jiggyscore_isCollected(local->unk4->unk3) ) { - gcdialog_showDialog(local->unk4->unk4, 4, NULL, NULL, NULL, NULL); - mapSpecificFlags_set(local->unk4->unk2, true); - } - } - } -} diff --git a/src/CCW/ch/zubbadoor.c b/src/CCW/ch/zubbadoor.c index 3ec863763..b8f6d1a26 100644 --- a/src/CCW/ch/zubbadoor.c +++ b/src/CCW/ch/zubbadoor.c @@ -3,14 +3,31 @@ #include "functions.h" #include "variables.h" -void func_803864B8(Actor *this); +void chZubbaDoor_update(Actor *this); -ActorInfo D_8038EB50 = { 0x1AC, 0x298, 0x444, 0x0, NULL, func_803864B8, NULL, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038EB74 = { 0x1AC, 0x29A, 0x445, 0x0, NULL, func_803864B8, NULL, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chZubbaDoorSummer = { + MARKER_1AC_ZUBBA_DOOR, ACTOR_298_ZUBBA_DOOR_SUMMER, ASSET_444_MODEL_CCW_ZUBBA_DOOR, + 0x0, NULL, + chZubbaDoor_update, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chZubbaDoorAutumn = { + MARKER_1AC_ZUBBA_DOOR, ACTOR_29A_ZUBBA_DOOR_AUTUMN, ASSET_445_MODEL_CCW_ZUBBA_DOOR, + 0x0, NULL, + chZubbaDoor_update, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +enum chZubbaDoor_State_e { + CH_ZUBBA_DOOR_STATE_0_NOT_INIT, + CH_ZUBBA_DOOR_STATE_1_IDLE, + CH_ZUBBA_DOOR_STATE_2_DESPAWN +}; /* .code */ -void CCW_func_803863F0(Actor *this, s32 next_state){ - if(next_state == 2){ +void chZubbaDoor_setState(Actor *this, s32 next_state){ + if(next_state == CH_ZUBBA_DOOR_STATE_2_DESPAWN){ sfx_playFadeShorthandDefault(SFX_2F_ORANGE_SPLAT, 1.0f, 32000, this->position, 500, 3000); levelSpecificFlags_set(LEVEL_FLAG_10_CCW_BREAK_ZUBBA_DOOR, true); marker_despawn(this->marker); @@ -20,17 +37,19 @@ void CCW_func_803863F0(Actor *this, s32 next_state){ void chZubbaDoor_die(ActorMarker* marker, ActorMarker *arg1) { Actor* actor = marker_getActor(marker); - if (actor->state == 1 && gsworld_getMap() == MAP_44_CCW_SUMMER) { - CCW_func_803863F0(actor, 2); + if (actor->state == CH_ZUBBA_DOOR_STATE_1_IDLE + && gsworld_getMap() == MAP_44_CCW_SUMMER) + { + chZubbaDoor_setState(actor, CH_ZUBBA_DOOR_STATE_2_DESPAWN); } } -void func_803864B8(Actor *this){ +void chZubbaDoor_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; this->marker->propPtr->unk8_3 = true; marker_setCollisionScripts(this->marker, NULL, NULL, chZubbaDoor_die); - CCW_func_803863F0(this, 1); + chZubbaDoor_setState(this, CH_ZUBBA_DOOR_STATE_1_IDLE); if (levelSpecificFlags_get(LEVEL_FLAG_10_CCW_BREAK_ZUBBA_DOOR)) { marker_despawn(this->marker); diff --git a/src/CCW/ch/zubbahoneylump.c b/src/CCW/ch/zubbahoneylump.c new file mode 100644 index 000000000..e9180e887 --- /dev/null +++ b/src/CCW/ch/zubbahoneylump.c @@ -0,0 +1,244 @@ +// BanjoDecomp: CCW/ch/zubbahoneylump.c +#include +#include "core1/core1.h" +#include "functions.h" +#include "variables.h" + + + +typedef struct{ + ActorMarker *jiggyMarker; + s32 spawnedZubbaCount; + s32 zubbasDefeated; + f32 unkC; // time related +}ActorLocal_CCW_160; + +void chZubbaFight_setState(Actor *this, s32 next_state); +void chZubbaFight_update(Actor *this); + +/* .data */ +ActorInfo chZubbaHoneyLump = { + MARKER_1AD_ZUBBA_HONEY_LUMP, ACTOR_299_ZUBBA_HONEY_LUMP, ASSET_443_MODEL_ZUBBA_HONEY_LUMP, + 0x0, NULL, + chZubbaFight_update, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +enum chZubbaFight_State_e { + CH_ZUBBA_FIGHT_STATE_0_NOT_INIT, + CH_ZUBBA_FIGHT_STATE_1_IDLE, + CH_ZUBBA_FIGHT_STATE_2_DIALOG, + CH_ZUBBA_FIGHT_STATE_3_FIGHT, + CH_ZUBBA_FIGHT_STATE_4_FIGHT_COMPLETE +}; + +#define NUM_OF_ZUBBAS_TO_DEFEAT 10 + +/* .code */ +void chZubbaFight_jiggy(ActorMarker *marker){ + Actor *this; + ActorLocal_CCW_160 *local; + + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + this->unk124_11 = 2; + this->alpha_124_19 = 0xFF; + if (local->jiggyMarker != NULL) { + actor_collisionOn(marker_getActor(local->jiggyMarker)); + } + coMusicPlayer_playMusic(COMUSIC_3D_JIGGY_SPAWN, 28000); +} + +void chZubbaFight_startFightDialog(ActorMarker* marker, enum asset_e text_id, s32 arg2) { + chZubbaFight_setState(marker_getActor(marker), CH_ZUBBA_FIGHT_STATE_3_FIGHT); +} + +void chZubbaFight_setState(Actor *this, s32 next_state) { + ActorLocal_CCW_160 *local; + + local = (ActorLocal_CCW_160 *)&this->local; + local->unkC = 0.0f; + if (next_state == CH_ZUBBA_FIGHT_STATE_2_DIALOG) { + if (!volatileFlag_getAndSet(VOLATILE_FLAG_B5, 1)) { + gcdialog_showDialog( + VER_SELECT(ASSET_CE2_DIALOG_ZUBBA_MEET_SUMMER, 0x09F7, 0, 0), 4, NULL, this->marker, chZubbaFight_startFightDialog, NULL); + } else { + gcdialog_showDialog(VER_SELECT(ASSET_CE3_DIALOG_ZUBBA_RETURN, 0x09F8, 0, 0), 4, NULL, NULL, NULL, NULL); + chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_3_FIGHT); + return; + } + } + + if (next_state == CH_ZUBBA_FIGHT_STATE_3_FIGHT) { + local->unkC = 0.1f; + func_8025A58C(0, 4000); + coMusicPlayer_playMusic(COMUSIC_4B_CCW_ZUBBA_FIGHT, 30000); + } + + if (next_state == CH_ZUBBA_FIGHT_STATE_4_FIGHT_COMPLETE) { + if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { + item_set(ITEM_6_HOURGLASS, false); + volatileFlag_set(VOLATILE_FLAG_3, 0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 1); + } else { + gcdialog_showDialog(VER_SELECT(ASSET_CE4_DIALOG_ZUBBA_COMPLETE, 0x09F9, 0, 0), 4, NULL, NULL, NULL, NULL); + func_8025A58C(-1, 400); + comusic_8025AB44(COMUSIC_4B_CCW_ZUBBA_FIGHT, 0, 400); + func_8025AABC(COMUSIC_4B_CCW_ZUBBA_FIGHT); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(2.0f, 4); + timedFunc_set_1(2.0f, (GenFunction_1)chZubbaFight_jiggy, (uintptr_t)this->marker); + timed_exitStaticCamera(4.0f); + func_80324E38(4.0f, 0); + } + } + this->state = next_state; +} + +void chZubbaFight_zubbaKilled(ActorMarker *marker){ + Actor *this; + ActorLocal_CCW_160 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + local->zubbasDefeated++; + local->spawnedZubbaCount--; + if(local->zubbasDefeated == NUM_OF_ZUBBAS_TO_DEFEAT){ + chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_4_FIGHT_COMPLETE); + } +} + +void chZubbaFight_zubbaDisappear(ActorMarker *marker){ + Actor *this; + ActorLocal_CCW_160 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + local->spawnedZubbaCount--; +} + +void chZubbaFight_zubbaScore(ActorMarker *marker, s32 *score, s32 *total){ + Actor *this; + ActorLocal_CCW_160 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + + *score = local->zubbasDefeated; + *total = NUM_OF_ZUBBAS_TO_DEFEAT; +} + +void chZubbaFight_update(Actor *this) { + ActorLocal_CCW_160 *local; + f32 time_delta; + Actor *jiggy_actor; + f32 sp78[3]; + f32 sp6C[3]; + s32 pad68; + f32 player_position_1[3]; + s32 phi_s0; + f32 sp4C[3]; + f32 player_position_2[3]; + s32 phi_v0; + f32 tmp; + + time_delta = time_getDelta(); + local = (ActorLocal_CCW_160 *)&this->local; + if(!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = true; + local->jiggyMarker = (ActorMarker *)(uintptr_t)1; // [port] full pointer-width sentinel write + local->spawnedZubbaCount = 0; + local->zubbasDefeated = 0; + local->unkC = 0.0f; + if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { + this->position_y -= 300.0f; + } + chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_1_IDLE); + return; + } + if ((uintptr_t)local->jiggyMarker == 1) { + jiggy_actor = actorArray_findActorFromActorId(ACTOR_46_JIGGY); + if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { + local->jiggyMarker = NULL; + if (jiggy_actor != NULL) { + actor_collisionOff(jiggy_actor); + jiggy_actor->position[1] -= 300.0f; + } + } else if (jiggy_actor != NULL) { + local->jiggyMarker = jiggy_actor->marker; + actor_collisionOff(jiggy_actor); + if (jiggyscore_isCollected(JIGGY_4C_CCW_ZUBBAS) != 0) { + marker_despawn(local->jiggyMarker); + marker_despawn(this->marker); + } + } else { + marker_despawn(this->marker); + } + return; + } + + if (local->jiggyMarker != NULL) { + jiggy_actor = marker_getActor(local->jiggyMarker); + viewport_getPosition_vec3f(sp78); + sp6C[0] = this->position[0] - sp78[0]; + sp6C[1] = this->position[1] - sp78[1]; + sp6C[2] = this->position[2] - sp78[2]; + sp6C[1] = 0.0f; + ml_vec3f_set_length(sp6C, 20.0f); + jiggy_actor->position[0] = this->position[0] + sp6C[0]; + jiggy_actor->position[1] = this->position[1] + sp6C[1]; + jiggy_actor->position[2] = this->position[2] + sp6C[2]; + } + if (ml_timer_update(&local->unkC, time_delta)) { + if ((local->spawnedZubbaCount < 3) && ((local->zubbasDefeated + local->spawnedZubbaCount) < 10)) { + player_getPosition(player_position_1); + for(phi_s0 = 0; phi_s0 < 20; phi_s0++){ + sp4C[0] = randf2(-500.0f, 500.0f); + sp4C[1] = -100.0f; + sp4C[2] = randf2(-500.0f, 900.0f); + + if(ml_vec3f_distance(this->position, sp4C) < 400.0f) + continue; + + tmp = ml_vec3f_distance(player_position_1, sp4C); + phi_v0 = (phi_s0 < 0xA) ? 500 : 200; + if(tmp < (f32) phi_v0) + continue; + + if(viewport_isPointOutsideFrustum_3f(sp4C[0], 0.0f, sp4C[2])) + break; + + } + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_29B_ZUBBA, reinterpret_cast(s32, sp4C[0]), reinterpret_cast(s32, sp4C[1]), reinterpret_cast(s32, sp4C[2])); + local->spawnedZubbaCount++; + } + local->unkC = randf2(0.5 - ((local->zubbasDefeated / 10) * 0.4), 1.0 - ((local->zubbasDefeated / 10) * 0.8)); + } + if (this->state == CH_ZUBBA_FIGHT_STATE_1_IDLE) { + if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) + && volatileFlag_get(VOLATILE_FLAG_3)) + { + item_set(ITEM_6_HOURGLASS, 1); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(1800, 1500, 1, 1) - 1); + chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_3_FIGHT); + } else if ((local->jiggyMarker != NULL) && (gsworld_getMap() == MAP_5A_CCW_SUMMER_ZUBBA_HIVE)) { + player_getPosition(player_position_2); + if ((ml_vec3f_distance(this->position, player_position_2) < 300.0f) + && (player_getTransformation() == TRANSFORM_1_BANJO)) + { + chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_2_DIALOG); + } + } + } + if ((this->state == CH_ZUBBA_FIGHT_STATE_3_FIGHT) + && volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) + && item_empty(ITEM_0_HOURGLASS_TIMER)) + { + item_set(ITEM_6_HOURGLASS, 0); + volatileFlag_set(VOLATILE_FLAG_3, 0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); + } +} diff --git a/src/CCW/checksums.c b/src/CCW/checksums.c new file mode 100644 index 000000000..11836811f --- /dev/null +++ b/src/CCW/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: CCW/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsCCW; diff --git a/src/CCW/eyrie_baby.c b/src/CCW/eyrie_baby.c new file mode 100644 index 000000000..50c384f8e --- /dev/null +++ b/src/CCW/eyrie_baby.c @@ -0,0 +1,382 @@ +// BanjoDecomp: code_3310.c +#include +#include "functions.h" +#include "variables.h" +#include "port/Patches/Patches.h" + +typedef struct { + f32 unk0; + s16 unk4; + f32 unk8; + s16 unkC; +} Eyrie_Baby_SFX; + +typedef struct { + s16 map_id; + s16 requiredFileProgress; + s16 unlocksFileProgress; + s16 waitingAnimation; + Eyrie_Baby_SFX *waitingSFX; + s16 nextStateWhenComplete; // Probably only used for Spring + s16 yawningAnimation; + Eyrie_Baby_SFX *yawnSFX; + s16 goingToSleepAnimation; + // u8 pad16[2]; + Eyrie_Baby_SFX *goingToSleepSFX; + s16 sleepingAnimation; + // u8 pad1E[0x2]; + Eyrie_Baby_SFX *sleepingSFX; + u8 cameraNode; + u8 caterpillarRequirement; + s16 eatingAnimation; + s16 meetDialog; + // u8 pad2A[2]; +} Eyrie_Baby_Dialog; + +typedef struct { + Eyrie_Baby_Dialog *progression; + u8 eatenCount; + //u8 pad5[3]; + Eyrie_Baby_SFX *sfx; + s32 unkC[3]; // something about player position? +} ActorLocal_CCW_3310; + +Actor *chEyrieBaby_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chEyrieBaby_update(Actor *this); + +/* .data */ +enum cheyriebaby_state_e { + CH_EYRIE_BABY_STATE_0_NOT_HATCHED, + CH_EYRIE_BABY_STATE_1_IDLE, + CH_EYRIE_BABY_STATE_2_YAWNING, + CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP, + CH_EYRIE_BABY_STATE_4_SLEEPING, + CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS +}; + +Eyrie_Baby_SFX chEyrieBabyWaitingSFX[] = { + {0.11f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, + {0.22f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, + {0.34f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, + {0.55f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, + {0.65f, SFX_2_CLAW_SWIPE, 1.0f, 26000}, + {0.77f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, + {0.87f, SFX_2_CLAW_SWIPE, 1.0f, 24000}, + 0 +}; + +Eyrie_Baby_SFX chEyrieBabyYawnSFX[] = { + {0.1f, SFX_80_YUMYUM_CLACK, 0.9f, 15000}, + {0.25f, SFX_4C_LIP_SMACK, 1.0f, 15000}, + {0.31f, SFX_4C_LIP_SMACK, 0.9f, 15000}, + {0.38f, SFX_4C_LIP_SMACK, 1.0f, 15000}, + {0.48f, SFX_4C_LIP_SMACK, 0.9f, 15000}, + {0.55f, SFX_97_BLUBBER_BURPS, 0.9f, 32700}, + {0.6f , SFX_2C_PULLING_NOISE, 0.7f, 25000}, + {0.73f, SFX_2C_PULLING_NOISE, 0.8f, 27000}, + {0.85f, SFX_2C_PULLING_NOISE, 0.9f, 29000}, + 0 +}; + +Eyrie_Baby_SFX chEyrieBabyGoingToSleepSFX[] = { + {0.2f , SFX_105_EYRIE_YAWN, 1.1f, 25000}, + {0.27f, SFX_105_EYRIE_YAWN, 1.0f, 25000}, + {0.35f, SFX_105_EYRIE_YAWN, 0.9f, 25000}, + {0.6f , SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, + {0.66f, SFX_106_EYRIE_LIPSMACK, 0.9f, 23000}, + {0.83f, SFX_1D_HITTING_AN_ENEMY_1, 0.7f, 27000}, + 0 +}; + +Eyrie_Baby_SFX chEyrieBabySleepingSFX[] = { + {0.2f , SFX_5D_BANJO_RAAOWW, 1.0f, 25000}, + {0.72f, SFX_5E_BANJO_PHEWWW, 1.0f, 25000}, + 0 +}; + +Eyrie_Baby_SFX chEyrieBabyEatingSFX[] = { + {0.95f, SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, + 0 +}; + +Eyrie_Baby_Dialog chEyrieBabyProgression[] = { + { + MAP_43_CCW_SPRING, // Map + 0, FILEPROG_E6_SPRING_EYRIE_HATCHED, // File Progress + 0, NULL, // Waiting + CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP, // Unk + 0, NULL, // Yawning + 0x18F, chEyrieBabyGoingToSleepSFX, // Going To Sleep + 0x190, chEyrieBabySleepingSFX, // Sleeping + 0, // Camera Node + 0, // Caterpillar Requirement + 0, // Eating Animation + 0 // Meet Dialog + }, + { + MAP_44_CCW_SUMMER, // Map + FILEPROG_E6_SPRING_EYRIE_HATCHED, FILEPROG_E7_SUMMER_EYRIE_FED, // File Progress + 0x191, chEyrieBabyWaitingSFX, // Waiting + CH_EYRIE_BABY_STATE_2_YAWNING, // Unk + 0x192, chEyrieBabyYawnSFX, // Yawning + 0x193, chEyrieBabyGoingToSleepSFX, // Going To Sleep + 0x194, chEyrieBabySleepingSFX, // Sleeping + 2, // Camera Node + 5, // Caterpillar Requirement + 0x21A, // Eating Animation + VER_SELECT(ASSET_CD7_DIALOG_BABY_EYRIE_MEET_SUMMER, 0x09EC, 0, 0) // Meet Dialog + }, + { + MAP_45_CCW_AUTUMN, // Map + FILEPROG_E7_SUMMER_EYRIE_FED, FILEPROG_E8_AUTMN_EYRIE_FED, // File Progress + 0x195, chEyrieBabyWaitingSFX, // Waiting + CH_EYRIE_BABY_STATE_2_YAWNING, // Unk + 0x196, chEyrieBabyYawnSFX, // Yawning + 0x197, chEyrieBabyGoingToSleepSFX, // Going To Sleep + 0x198, chEyrieBabySleepingSFX, // Sleeping + 4, // Camera Node + 10, // Caterpillar Requirement + 0x21B, // Eating Animation + VER_SELECT(ASSET_CDA_DIALOG_BABY_EYRIE_MEET_FALL, 0x09EF, 0, 0) // Meet Dialog + }, + { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion +}; + +ActorInfo chEyrieBaby = { + MARKER_1B4_EEYRIE_BABY, ACTOR_2A1_EEYRIE_BABY, ASSET_484_MODEL_EAGLE_BABY, + 0x0, NULL, + chEyrieBaby_update, NULL, chEyrieBaby_draw, + 0, 0, 0.0f, 0 +}; + +/* .bss */ +f32 chEyrieBabyThrowPosition[3]; + +/* .code */ +void func_80389700(ActorMarker *marker, enum asset_e text_id, s32 arg2) { + timed_exitStaticCamera(0.5f); + func_80324E38(0.5f, 0); +} + +void func_80389740(ActorMarker *marker) { + Actor *this = marker_getActor(marker); + if (this->marker->unk14_21) { + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x30C, reinterpret_cast(s32, chEyrieBabyThrowPosition[0]), reinterpret_cast(s32, chEyrieBabyThrowPosition[1]), reinterpret_cast(s32, chEyrieBabyThrowPosition[2])); + } +} + +void chEyrieBaby_saysMama() { + func_8030E6D4(SFX_18C_EYRIE_MAMA); +} + +void chEyrieBaby_setState(Actor *this, s32 next_state) { + ActorLocal_CCW_3310 *local; + + local = (ActorLocal_CCW_3310 *)&this->local; + local->sfx = NULL; + if (next_state == CH_EYRIE_BABY_STATE_1_IDLE) { + if (local->progression->waitingAnimation != NULL) { + skeletalAnim_set(this->unk148, local->progression->waitingAnimation, 0.2f, 6.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + local->sfx = local->progression->waitingSFX; + } + if ((this->state == CH_EYRIE_BABY_STATE_1_IDLE) + && (next_state == CH_EYRIE_BABY_STATE_2_YAWNING)) { + fileProgressFlag_set(local->progression->unlocksFileProgress, true); + } + if (next_state == CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS) { + func_8028F784(1); + skeletalAnim_set(this->unk148, local->progression->eatingAnimation, 0.2f, 2.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + local->sfx = &chEyrieBabyEatingSFX[0]; + } + + if (next_state == CH_EYRIE_BABY_STATE_2_YAWNING) { + skeletalAnim_set(this->unk148, local->progression->yawningAnimation, 0.2f, 8.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + func_80324E38(0.5f, 3); + timed_setStaticCameraToNode(0.5f, local->progression->cameraNode); + timed_exitStaticCamera(16.5f); + func_80324E38(16.5f, 0); + local->sfx = local->progression->yawnSFX; + } + if (next_state == CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP) { + actor_collisionOff(this); + skeletalAnim_set(this->unk148, local->progression->goingToSleepAnimation, 0.5f, 8.5f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + if (local->progression->map_id == MAP_43_CCW_SPRING) { + gcdialog_showDialog(VER_SELECT(ASSET_CD6_DIALOG_BABY_EYRIE_HATCH, 0x09EB, 0, 0), 4, NULL, NULL, NULL, NULL); + skeletalAnim_setCallback_0(this->unk148, 0.65f, &chEyrieBaby_saysMama); + } + if (local->progression->map_id == MAP_44_CCW_SUMMER) { + gcdialog_showDialog(VER_SELECT(ASSET_CD9_DIALOG_BABY_EYRIE_COMPLETE_SUMMER, 0x09EE, 0, 0), 4, NULL, NULL, NULL, NULL); + } + if (local->progression->map_id == MAP_45_CCW_AUTUMN) { + gcdialog_showDialog(VER_SELECT(ASSET_CDB_DIALOG_BABY_EYRIE_COMPLETE_FALL, 0x09F0, 0, 0), 4, NULL, NULL, NULL, NULL); + } + local->sfx = local->progression->goingToSleepSFX; + } + if (next_state == CH_EYRIE_BABY_STATE_4_SLEEPING) { + func_8028F784(0); + skeletalAnim_set(this->unk148, local->progression->sleepingAnimation, 0.2f, 6.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + skeletalAnim_setCallback_1(this->unk148, 0.2f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.4f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.72f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.82f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.92f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + local->sfx = local->progression->sleepingSFX; + } + this->state = next_state; +} + +Actor *chEyrieBaby_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor *this; + ActorLocal_CCW_3310 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_3310 *)&this->local; + if( (this->state == CH_EYRIE_BABY_STATE_0_NOT_HATCHED) + || ((this->state == CH_EYRIE_BABY_STATE_1_IDLE) + && (local->progression->waitingAnimation == NULL)) + ) { + return this; + } + modelRender_setAppendageVisibility(3, (this->state == CH_EYRIE_BABY_STATE_4_SLEEPING) ? 2 : 1); + actor_draw(marker, gfx, mtx, vtx); + vec3fArray_get_vec3f(func_80329934(), 5, chEyrieBabyThrowPosition); + return this; +} + +void func_80389BD8(f32 dst[3]){ + dst[0] = chEyrieBabyThrowPosition[0]; + dst[1] = chEyrieBabyThrowPosition[1]; + dst[2] = chEyrieBabyThrowPosition[2]; +} + +void chEyrieBaby_update(Actor *this) { + Eyrie_Baby_SFX *iPtr; + ActorLocal_CCW_3310 *local; + f32 sp5C; + f32 sp58; + f32 player_position[3]; + + local = (ActorLocal_CCW_3310 *)&this->local; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = true; + this->has_met_before = false; + this->position[0] = -4900.0f; + this->position[1] = 4619.0f; + this->position[2] = 0.0f; + chEyrieBabyThrowPosition[0] = this->position[0]; + chEyrieBabyThrowPosition[1] = this->position[1]; + chEyrieBabyThrowPosition[2] = this->position[2]; + if (this->state == CH_EYRIE_BABY_STATE_0_NOT_HATCHED) { + local->eatenCount = (u32)port_puzzleCount_get(ANCHOR_COUNT_CCW_EYRIE_FED); + } + local->progression = &chEyrieBabyProgression[0]; + while(local->progression->map_id != NULL && gsworld_getMap() != local->progression->map_id){ + local->progression++; + } + + if ((local->progression->requiredFileProgress != NULL) + && !fileProgressFlag_get(local->progression->requiredFileProgress)) + { + marker_despawn(this->marker); + } else if (!fileProgressFlag_get(local->progression->unlocksFileProgress)) { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_1_IDLE); + } else { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_4_SLEEPING); + } + + if (jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE) != false) { + marker_despawn(this->marker); + } + return; + } + + if (local->sfx) { + skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); + for(iPtr = local->sfx; iPtr->unk0 > 0.0f; iPtr ++){ + if ((sp5C < iPtr->unk0) && (iPtr->unk0 <= sp58)) { + func_8030E878((s32) iPtr->unk4, randf2(iPtr->unk8 - 0.05, iPtr->unk8 + 0.05), iPtr->unkC, this->position, 500.0f, 2500.0f); + } + } + } + if (this->state == CH_EYRIE_BABY_STATE_1_IDLE) { + player_getPosition(player_position); + if( !this->has_met_before + && (local->unkC[2] >= 6500) + && (player_position[2] < 6500.0f) + && (local->progression->meetDialog != NULL) + ){ + this->has_met_before = true; + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, local->progression->cameraNode); + func_80324DBC(0.0f, local->progression->meetDialog, 6, NULL, this->marker, func_80389700, NULL); + } + local->unkC[0] = (s32) player_position[0]; + local->unkC[1] = (s32) player_position[1]; + local->unkC[2] = (s32) player_position[2]; + if (item_getCount(ITEM_22_CATERPILLAR) == 0) { + func_8028F784(0); + } + if ((local->progression->map_id != MAP_43_CCW_SPRING) + && ((this->position[0] + 500.0f) < player_position[0])) + { + player_setCarryObjectPoseInCylinder(this->position, 1110.0f, 200.0f, ACTOR_2A2_CATERPILLAR, &this); + if ((local->progression->yawningAnimation != NULL) + && (carriedObj_getActorId() == ACTOR_2A2_CATERPILLAR) + && (ml_vec3f_distance(this->position, player_position) < 1010.0f) + && (player_throwCarriedObject() != 0)) + { + player_setThrowTargetPosition(chEyrieBabyThrowPosition); + if ((local->progression->map_id == MAP_44_CCW_SUMMER) + && (local->eatenCount == 0)) + { + gcdialog_showDialog(VER_SELECT(ASSET_CD8_DIALOG_BABY_EYRIE_CHECK_SUMMER, 0x09ED, 0, 0), 4, NULL, NULL, NULL, NULL); + } + port_puzzleCount_add(ANCHOR_COUNT_CCW_EYRIE_FED, 1); + local->eatenCount = (u32)port_puzzleCount_get(ANCHOR_COUNT_CCW_EYRIE_FED); + if (local->eatenCount < local->progression->caterpillarRequirement) { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS); + } else { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_2_YAWNING); + } + } + } + // Anchor: teammate fed a worm — play the interim eat animation; final feed handled below. + if (this->state == CH_EYRIE_BABY_STATE_1_IDLE) { + s32 sharedFed = port_puzzleCount_get(ANCHOR_COUNT_CCW_EYRIE_FED); + if (sharedFed > (s32)local->eatenCount) { + local->eatenCount = (u32)sharedFed; + if ((s32)local->eatenCount < (s32)local->progression->caterpillarRequirement) { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS); + } + } + } + if (this->state == CH_EYRIE_BABY_STATE_1_IDLE && fileProgressFlag_get(local->progression->unlocksFileProgress)) { + // Anchor: fed flag synced from a teammate — skip to sleep state (spring keeps its hatch cutscene). + chEyrieBaby_setState(this, (local->progression->map_id == MAP_43_CCW_SPRING) ? local->progression->nextStateWhenComplete : CH_EYRIE_BABY_STATE_4_SLEEPING); + } + } + if ((this->state == CH_EYRIE_BABY_STATE_2_YAWNING) + && (skeletalAnim_getLoopCount(this->unk148) > 0)) + { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP); + } + if ((this->state == CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP) + && (skeletalAnim_getLoopCount(this->unk148) > 0)) + { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_4_SLEEPING); + } + if ((this->state == CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS) + && (skeletalAnim_getLoopCount(this->unk148) > 0)) + { + chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_1_IDLE); + } +} diff --git a/src/CCW/flower.c b/src/CCW/flower.c deleted file mode 100644 index 376fdf2be..000000000 --- a/src/CCW/flower.c +++ /dev/null @@ -1,170 +0,0 @@ -// BanjoDecomp: code_1B20.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - s16 unk0; - u8 unk2; - u8 unk3; - s16 unk4; - s16 unk6; - s16 unk8; // enum file_progress_e - s16 unkA; -}Struct_CCW_1B20_0; - -typedef struct{ - Struct_CCW_1B20_0 *unk0; -}ActorLocal_CCW_1B20; - -void func_80387F64(Actor *this, s32 next_state); -Actor *CCW_func_803882F4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_80388478(Actor *this); - -/* .data */ -Struct_CCW_1B20_0 D_8038EC40[4] ={ - {0x173, 4, 0, 0x173, 0x181, 0xE3, 0}, - {0x181, 1, 1, 0x174, 0x182, 0xE4, 0}, - {0x182, 1, 1, 0x175, 0x183, 0xE5, 1}, - {0x183, 1, 1, 0x000, 0x000, 0x00, 0} -}; - -ActorInfo D_8038EC70 = { 0x1B0, 0x29D, 0x447, 0x0, NULL, func_80388478, NULL, CCW_func_803882F4, 0, 0, 1.0f, 0}; -f32 D_8038EC94[3] = {200.0f, 2120.0f, -5570.0f}; - -/* .code */ -void func_80387F10() { - jiggy_spawn(JIGGY_4D_CCW_FLOWER, D_8038EC94); -} - -void func_80387F38(ActorMarker* marker, s32 arg1) { - func_80387F64(marker_getActor(marker), arg1); -} - -void func_80387F64(Actor *this, s32 next_state){ - ActorLocal_CCW_1B20 *local; - f32 phi_f22; - - local = (ActorLocal_CCW_1B20 *)&this->local; - - if (next_state == 1) { - this->marker->propPtr->unk8_3 = local->unk0->unk3; - skeletalAnim_set(this->unk148, local->unk0->unk0, 0.0f, 5.0f); - skeletalAnim_setBehavior(this->unk148, local->unk0->unk2); - } - if (next_state == 2) { - if (gsworld_getMap() == MAP_43_CCW_SPRING) { - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - } - fileProgressFlag_set(local->unk0->unk8, true); - skeletalAnim_set(this->unk148, local->unk0->unk4, 0.0f, 6.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if (gsworld_getMap() == MAP_43_CCW_SPRING) { - func_80324E38(0.0f, 3); - } - timed_setStaticCameraToNode(0.0f, 0); - for( phi_f22 = 0.0f; phi_f22 <= 1.0f; phi_f22 += 0.1) { - timed_playSfx(phi_f22 * 5.7, 0x2C, phi_f22 * 0.3 + 0.7, (s32) (32000.0f - phi_f22 * 5000.0f)); - } - if (local->unk0->unkA != 0) { - timed_setStaticCameraToNode(6.0f, 1); - timedFunc_set_0(6.1f, (GenFunction_0)func_80387F10); - timedFunc_set_2(8.0f, (GenFunction_2)func_80387F38, (uintptr_t)this->marker, 3); - } else { - if (gsworld_getMap() == MAP_43_CCW_SPRING) { - timed_exitStaticCamera(7.0f); - func_80324E38(7.0f, 0); - } - timedFunc_set_2(7.0f, (GenFunction_2)func_80387F38, (uintptr_t)this->marker, 3); - } - } - - if (next_state == 3) { - this->marker->propPtr->unk8_3 = true; - skeletalAnim_set(this->unk148, local->unk0->unk6, 0.1f, 5.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - this->state = next_state; -} - -s32 func_80388260(ActorMarker *marker, s32 arg1){ - return marker->unk40_31 != 1; -} - -void CCW_func_80388278(ActorMarker *marker, ActorMarker *other_marker) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); -} - -void func_803882A4(ActorMarker* marker, ActorMarker *other_marker) { - Actor* actor = marker_getActor(marker); - - // [port] v1.1 fix: don't allow re-planting flower in Spring after it's already been planted - if (EventSystem_Should(VB_CCW_FLOWER_REPLANT, - gsworld_getMap() == MAP_43_CCW_SPRING && actor->state == 1 && - !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING))) { - func_80387F64(actor, 2); - } -} - -Actor *CCW_func_803882F4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - s32 sp18; - - this = marker_getActor(marker); - if ((this->state == 1) && !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING)) { - return func_80325340(marker, gfx, mtx, vtx); - } - - if ((skeletalAnim_getAnimId(this->unk148) == 0x175) && (0.49 <= skeletalAnim_getProgress(this->unk148))) { - sp18 = 1; - } else { - sp18 = 0; - } - sp18 = (skeletalAnim_getAnimId(this->unk148) == 0x183)? 1 : sp18; - func_8033A45C(3, sp18); - func_8033A45C(4, sp18); - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_803883F4() { - Actor* actor = actorArray_findActorFromActorId(0x29D); - if (actor && actor->state == 1) { - func_80387F64(actor, 2); - } -} - -bool func_80388438() { - Actor* actor = actorArray_findActorFromActorId(0x29D); - if (actor && actor->state == 2) { - return true; - } - return false; -} - -void func_80388478(Actor *this) { - ActorLocal_CCW_1B20 *local; - - local = (ActorLocal_CCW_1B20 *)&this->local; - if (!this->volatile_initialized) { - this->volatile_initialized = true; - func_803300C0(this->marker, (s32 (*)(ActorMarker *, ActorMarker *))func_80388260); - marker_setCollisionScripts(this->marker, NULL, CCW_func_80388278, func_803882A4); - actor_collisionOn(this); - if (!jiggyscore_isSpawned(JIGGY_4D_CCW_FLOWER)) { - fileProgressFlag_set(FILEPROG_E5_CCW_FLOWER_AUTUMN, false); - } - - for(local->unk0 = &D_8038EC40[0]; local->unk0 < D_8038EC40 + 3; local->unk0++){ - if(!fileProgressFlag_get(local->unk0->unk8)){ - break; - } - } - - if (!fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING) && (gsworld_getMap() != MAP_43_CCW_SPRING)) { - marker_despawn(this->marker); - } - else{ - func_80387F64(this, 1); - } - } -} diff --git a/src/CCW/minigame_zubba.c b/src/CCW/minigame_zubba.c deleted file mode 100644 index a1b71edc1..000000000 --- a/src/CCW/minigame_zubba.c +++ /dev/null @@ -1,221 +0,0 @@ -// BanjoDecomp: code_160.c -#include -#include "core1/core1.h" -#include "functions.h" -#include "variables.h" - - - -typedef struct{ - ActorMarker *unk0; - s32 unk4; - s32 unk8; - f32 unkC; -}ActorLocal_CCW_160; - -void func_803865F4(Actor *this, s32 next_state); -void func_8038687C(Actor *this); - -/* .data */ -ActorInfo D_8038EBA0 = { 0x1AD, 0x299, 0x443, 0x0, NULL, func_8038687C, NULL, actor_draw, 0, 0, 0.0f, 0}; - -/* .code */ -void CCW_func_80386550(ActorMarker *marker){ - Actor *this; - ActorLocal_CCW_160 *local; - - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - this->unk124_11 = 2; - this->alpha_124_19 = 0xFF; - if (local->unk0 != NULL) { - actor_collisionOn(marker_getActor(local->unk0)); - } - coMusicPlayer_playMusic(COMUSIC_3D_JIGGY_SPAWN, 28000); -} - -void func_803865C4(ActorMarker* marker, enum asset_e text_id, s32 arg2) { - func_803865F4(marker_getActor(marker), 3); -} - -void func_803865F4(Actor *this, s32 next_state) { - ActorLocal_CCW_160 *local; - - local = (ActorLocal_CCW_160 *)&this->local; - local->unkC = 0.0f; - if (next_state == 2) { - if (!volatileFlag_getAndSet(VOLATILE_FLAG_B5, 1)) { - gcdialog_showDialog(0xCE2, 4, NULL, this->marker, func_803865C4, NULL); - } else { - gcdialog_showDialog(0xCE3, 4, NULL, NULL, NULL, NULL); - func_803865F4(this, 3); - return; - } - } - - if (next_state == 3) { - local->unkC = 0.1f; - func_8025A58C(0, 4000); - coMusicPlayer_playMusic(COMUSIC_4B_CCW_ZUBBA_FIGHT, 30000); - } - - if (next_state == 4) { - if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - item_set(ITEM_6_HOURGLASS, false); - volatileFlag_set(VOLATILE_FLAG_3, 0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 1); - } else { - gcdialog_showDialog(0xCE4, 4, NULL, NULL, NULL, NULL); - func_8025A58C(-1, 400); - comusic_8025AB44(COMUSIC_4B_CCW_ZUBBA_FIGHT, 0, 400); - func_8025AABC(COMUSIC_4B_CCW_ZUBBA_FIGHT); - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(2.0f, 4); - timedFunc_set_1(2.0f, (GenFunction_1)CCW_func_80386550, (uintptr_t)this->marker); - timed_exitStaticCamera(4.0f); - func_80324E38(4.0f, 0); - } - } - this->state = next_state; -} - -void func_803867C8(ActorMarker *marker){ - Actor *this; - ActorLocal_CCW_160 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - local->unk8++; - local->unk4--; - if(local->unk8 == 10){ - func_803865F4(this, 4); - } -} - -void func_80386814(ActorMarker *marker){ - Actor *this; - ActorLocal_CCW_160 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - local->unk4--; -} - -void func_80386840(ActorMarker *marker, s32 *score, s32 *total){ - Actor *this; - ActorLocal_CCW_160 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - - *score = local->unk8; - *total = 10; -} - -void func_8038687C(Actor *this) { - ActorLocal_CCW_160 *local; - f32 sp88; - Actor *other; - f32 sp78[3]; - f32 sp6C[3]; - s32 pad68; - f32 sp5C[3]; - s32 phi_s0; - f32 sp4C[3]; - f32 sp40[3]; - s32 phi_v0; - f32 tmp; - - sp88 = time_getDelta(); - local = (ActorLocal_CCW_160 *)&this->local; - if(!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = true; - reinterpret_cast(s32, local->unk0) = 1; - local->unk4 = 0; - local->unk8 = 0; - local->unkC = 0.0f; - if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - this->position_y -= 300.0f; - } - func_803865F4(this, 1); - return; - } - if ((uintptr_t)local->unk0 == 1) { - other = actorArray_findActorFromActorId(0x46); - if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - local->unk0 = NULL; - if (other != NULL) { - actor_collisionOff(other); - other->position[1] -= 300.0f; - } - } else if (other != NULL) { - local->unk0 = other->marker; - actor_collisionOff(other); - if (jiggyscore_isCollected(JIGGY_4C_CCW_ZUBBAS) != 0) { - marker_despawn(local->unk0); - marker_despawn(this->marker); - } - } else { - marker_despawn(this->marker); - } - return; - } - - if (local->unk0 != NULL) { - other = marker_getActor(local->unk0); - viewport_getPosition_vec3f(sp78); - sp6C[0] = this->position[0] - sp78[0]; - sp6C[1] = this->position[1] - sp78[1]; - sp6C[2] = this->position[2] - sp78[2]; - sp6C[1] = 0.0f; - ml_vec3f_set_length(sp6C, 20.0f); - other->position[0] = this->position[0] + sp6C[0]; - other->position[1] = this->position[1] + sp6C[1]; - other->position[2] = this->position[2] + sp6C[2]; - } - if (ml_timer_update(&local->unkC, sp88)) { - if ((local->unk4 < 3) && ((local->unk8 + local->unk4) < 10)) { - player_getPosition(sp5C); - for(phi_s0 = 0; phi_s0 < 20; phi_s0++){ - sp4C[0] = randf2(-500.0f, 500.0f); - sp4C[1] = -100.0f; - sp4C[2] = randf2(-500.0f, 900.0f); - - if(ml_vec3f_distance(this->position, sp4C) < 400.0f) - continue; - - tmp = ml_vec3f_distance(sp5C, sp4C); - phi_v0 = (phi_s0 < 0xA) ? 500 : 200; - if(tmp < (f32) phi_v0) - continue; - - if(viewport_isPointOutsideFrustum_3f(sp4C[0], 0.0f, sp4C[2])) - break; - - } - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x29B, reinterpret_cast(s32, sp4C[0]), reinterpret_cast(s32, sp4C[1]), reinterpret_cast(s32, sp4C[2])); - local->unk4++; - } - local->unkC = randf2(0.5 - ((local->unk8 / 10) * 0.4), 1.0 - ((local->unk8 / 10) * 0.8)); - } - if (this->state == 1) { - if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && volatileFlag_get(VOLATILE_FLAG_3)) { - item_set(ITEM_6_HOURGLASS, 1); - item_set(ITEM_0_HOURGLASS_TIMER, 1800 - 1); - func_803865F4(this, 3); - } else if ((local->unk0 != NULL) && (gsworld_getMap() == MAP_5A_CCW_SUMMER_ZUBBA_HIVE)) { - player_getPosition(sp40); - if ((ml_vec3f_distance(this->position, sp40) < 300.0f) && (player_getTransformation() == TRANSFORM_1_BANJO)) { - func_803865F4(this, 2); - } - } - } - if ((this->state == 3) && volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && item_empty(ITEM_0_HOURGLASS_TIMER)) { - item_set(ITEM_6_HOURGLASS, 0); - volatileFlag_set(VOLATILE_FLAG_3, 0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); - } -} diff --git a/src/CCW/nabnut_winter.c b/src/CCW/nabnut_winter.c new file mode 100644 index 000000000..13589719b --- /dev/null +++ b/src/CCW/nabnut_winter.c @@ -0,0 +1,174 @@ +// BanjoDecomp: code_5BF0.c +#include +#include "functions.h" +#include "variables.h" + +extern void func_8028E668(f32[3], f32, f32, f32); + +Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); +void func_8038C41C(Actor *this); + +/* .data */ + +ActorInfo chMoundOfAcorns = { + MARKER_1C6_MOUND_OF_ACORNS, ACTOR_310_NABNUT_HOUSE_PILE_OF_ACORNS, ASSET_501_MODEL_MOUND_OF_ACORNS, + 0x0, NULL, + func_8038C41C, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chPinkSquirrel = { + MARKER_1C7_PINK_SQUIRREL, ACTOR_311_PINK_SQUIRREL, ASSET_462_MODEL_PINK_SQUIRREL, + 0x0, NULL, + func_8038C41C, NULL, func_8038C380, + 0, 0, 0.0f, 0 +}; + +ActorInfo chNabnutBedsheets = { + MARKER_1C8_NABNUT_BEDSHEETS, ACTOR_312_NABNUT_BEDSHEETS, ASSET_463_MODEL_NABNUT_BEDSHEETS, + 0x0, NULL, + func_8038C41C, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chNabnutBed = { + MARKER_1C9_NABNUT_BED, ACTOR_313_NABNUT_BED, ASSET_464_MODEL_NABNUT_BED, + 0x0, NULL, + func_8038C41C, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chNabnut = { + MARKER_1CA_NABNUT, ACTOR_314_NABNUT_IN_AUTUMN_HOUSE, ASSET_502_MODEL_NABNUT, + 0x0, NULL, + func_8038C41C, NULL, actor_draw, + 0, 0, 2.0f, 0 +}; + +ActorInfo chNabnutAutumnEatingAcorns = { + MARKER_1CB_NABNUT_EATING_ACORNS, ACTOR_315_NABNUT_EATING_ACORNS, ASSET_48D_MODEL_NABNUT_EATING_ACORNS, + 0x0, NULL, func_8038C41C, + NULL, func_8038C380, + 0, 0, 0.0f, 0 +}; + +enum code_5BF0_state_e { + CODE_5BF0_STATE_0_NOT_INIT, + CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY, + CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY +}; + +/* .code */ +void func_8038BFE0(ActorMarker* marker) { + Actor* sp2C = marker_getActor(marker); + func_8030E878(SFX_5D_BANJO_RAAOWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); +} + +void func_8038C064(ActorMarker* marker) { + Actor* sp2C = marker_getActor(marker); + func_8030E878(SFX_5E_BANJO_PHEWWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); +} + +void func_8038C0E8(ActorMarker* marker) { + Actor* sp24 = marker_getActor(marker); + f32 sp20 = randf2(0.9f, 1.1f); + + func_8030E878(SFX_81_UUU, sp20, (s32)randf2(10000.0f, 31000.0f), sp24->position, 500.0f, 2500.0f); +} + +void code_5BF0_setState(Actor *this, s32 next_state) { + Actor *other; + + if (next_state == CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY) { + this->position[1] -= 300.0f; + } + + if (this->state == CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY) { + this->position[1] += 300.0f; + } + + if (next_state == CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY) { + if (this->marker->id == MARKER_1CA_NABNUT) { + skeletalAnim_set(this->unk148, ASSET_22E_ANIM_NABNUT_STAND, 0.2f, 3.53f); + skeletalAnim_setCallback_1(this->unk148, 0.1f, (GenFunction_1)func_8038C0E8, (uintptr_t)this->marker); + } + if (this->marker->id == MARKER_1C7_PINK_SQUIRREL) { + skeletalAnim_set(this->unk148, ASSET_230_ANIM_PINK_SQUIRREL_UNK, 0.2f, 4.0f); + } + if (this->marker->id == MARKER_1CB_NABNUT_EATING_ACORNS) { + skeletalAnim_set(this->unk148, ASSET_1A2_ANIM_NABNUT_SLEEP, 0.2f, 4.0f); + skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_8038BFE0, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.65f, (GenFunction_1)func_8038C064, (uintptr_t)this->marker); + } + if (this->marker->id == MARKER_1C8_NABNUT_BEDSHEETS) { + skeletalAnim_set(this->unk148, ASSET_231_ANIM_NABNUT_BEDSHEETS_UNK, 0.2f, 4.0f); + } + if ((this->marker->id == MARKER_1C7_PINK_SQUIRREL) + || (this->marker->id == MARKER_1CB_NABNUT_EATING_ACORNS) + || (this->marker->id == MARKER_1C8_NABNUT_BEDSHEETS)) + { + other = actorArray_findActorFromActorId(ACTOR_313_NABNUT_BED); + if (other != 0) { + this->position[0] = other->position[0]; + this->position[1] = other->position[1]; + this->position[2] = other->position[2]; + this->pitch = other->pitch; + this->yaw = other->yaw; + this->roll = other->roll; + } + } + } + this->state = next_state; +} + +Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { + modelRender_setAppendageVisibility(3, 0); + modelRender_setAppendageVisibility(4, 0); + modelRender_setAppendageVisibility(5, 0); + modelRender_setAppendageVisibility(6, 1); + modelRender_setAppendageVisibility(7, 0); + modelRender_setAppendageVisibility(8, 0); + modelRender_setAppendageVisibility(9, 0); + modelRender_setAppendageVisibility(0xA, 1); + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_8038C41C(Actor *this) { + f32 player_position[3]; + + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + return; + } + + if (this->state == CODE_5BF0_STATE_0_NOT_INIT) { + if( gsworld_getMap() == MAP_60_CCW_AUTUMN_NABNUTS_HOUSE + && !jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT) + && (this->marker->id == MARKER_1C6_MOUND_OF_ACORNS + || this->marker->id == MARKER_1CA_NABNUT) + ){ + code_5BF0_setState(this, CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY); + } else { + code_5BF0_setState(this, CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY); + } + } + + if ((this->marker->id == MARKER_1CA_NABNUT) + && (this->state != CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY)) + { + func_8028E668(this->position, 300.0f, -50.0f, 120.0f); + } + + if ((this->marker->id == MARKER_1CB_NABNUT_EATING_ACORNS) + && (this->state == CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY)) + { + player_getPosition(player_position); + if (!this->has_met_before && (ml_vec3f_distance(this->position, player_position) < 400.0f)) { + this->has_met_before = TRUE; + gcdialog_showDialog(VER_SELECT(ASSET_CCD_DIALOG_NABNUT_MEET_WINTER, 0x09E2, 0, 0), 0, NULL, NULL, NULL, NULL); + } + } +} + diff --git a/src/CCW/seasonal_switch.c b/src/CCW/seasonal_switch.c deleted file mode 100644 index e5a397dba..000000000 --- a/src/CCW/seasonal_switch.c +++ /dev/null @@ -1,171 +0,0 @@ -// BanjoDecomp: code_2B00.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - u8 unk0; - u8 unk1; - u8 unk2; - u8 unk3; -}Struct_CCW_2B00_0; - -void func_80389268(Actor *this); -void func_80388FD4(Actor *this); - -/* .data */ -Struct_CCW_2B00_0 D_8038ED10[] = { - {0, 0x40, 0, 5}, - {0, 0x43, 1, 5}, - {0, 0x44, 2, 5}, - {0, 0x45, 3, 15} -}; - -ActorAnimationInfo D_8038ED20[] = { - {0, 0.0f}, - {0, 0.0f}, - {0, 0.0f}, - {0, 0.0f}, - {ASSET_D4_ANIM_SWITCH_DOWN, 0.5f}, - {ASSET_D4_ANIM_SWITCH_DOWN, 100000000.0f} -}; - -ActorInfo D_8038ED50 = { 0x133, 0x1E3, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; -ActorInfo D_8038ED74 = { 0x132, 0x1E2, 0x4F5, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038ED98 = { 0x131, 0x16D, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; -ActorInfo D_8038EDBC = { 0x130, 0x16C, 0x4F6, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038EDE0 = { 0x12F, 0x16B, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; -ActorInfo D_8038EE04 = { 0x12E, 0x16A, 0x4F7, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8038EE28 = { 0x12D, 0x169, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; -ActorInfo D_8038EE4C = { 0x12C, 0x168, 0x4F8, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; - -/* .code */ -s32 func_80388EF0(Actor *this){ - switch(this->marker->id){ - case 0x133: //L80388F28 - case 0x132: //L80388F28 - return 0; - - case 0x131: //L80388F30 - case 0x130: //L80388F30 - return 1; - - case 0x12F: //L80388F38 - case 0x12E: //L80388F38 - return 2; - - case 0x12D: //L80388F40 - case 0x12C: //L80388F40 - return 3; - - default: - return 0; - } -} - - -void func_80388F50(ActorMarker *marker, ActorMarker *other_marker){ - Actor *this; - - this = marker_getActor(marker); - if ((player_movementGroup() != BSGROUP_1_INTR) && !this->unk38_0) { - this->unk38_0 = true; - actor_collisionOff(this); - subaddie_set_state_with_direction(this, 4, 0.0f, 1); - actor_playAnimationOnce(this); - func_8030E6D4(SFX_90_SWITCH_PRESS); - } -} - -void func_80388FD4(Actor *this) { - - if (!this->initialized) { - this->unk138_31 = this->unk124_0 = true; - this->marker->propPtr->unk8_3 = true; - this->unk10_12 = func_80388EF0(this); - this->initialized = true; - } - if (!this->volatile_initialized) { - if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { - actor_playAnimationOnce(this); - subaddie_set_state_with_direction(this, 4, 0.999f, 1); - actor_collisionOff(this); - } else { - marker_setCollisionScripts(this->marker, NULL, &func_80388F50, NULL); - } - this->unk38_0 = false; - this->volatile_initialized = true; - } - if( (this->state == 4) - && this->unk38_0 - && actor_animationIsAt(this, 0.999f) - ){ - func_802D6264(1.1f, 0x40, this->unk10_12 + 0x3C, 0x2B, D_8038ED10[this->unk10_12].unk3, this->unk10_12 + 0x8B); - func_80324E38(0.5f, 3); - timedFunc_set_2(1.1f, (GenFunction_2)levelSpecificFlags_set, this->unk10_12 + 7, true); - func_80324E38(5.6f, 0); - } -} - -void func_803891B0(void* marker) { - Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); - actor->unk44_31 = func_8030ED2C(SFX_3EC_CCW_DOOR_OPENING, 3); - func_8030DD90(actor->unk44_31, 0); - sfxsource_setSampleRate(actor->unk44_31, 0x2AF8); - sfxsource_playSfxAtVolume(actor->unk44_31, 0.3f); - sfxSource_func_8030E2C4(actor->unk44_31); -} - -void func_8038921C(void* marker) { - Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); - sfxSource_triggerCallbackByIndex(actor->unk44_31); - sfxsource_freeSfxsourceByIndex(actor->unk44_31); - actor->unk44_31 = 0U; - FUNC_8030E624(SFX_6C_LOCKUP_CLOSING, 1.0f, 25000); -} - -void func_80389268(Actor *this) { - ActorProp *temp_v1; - u32 temp_v0; - u32 temp_v1_2; - - if(!this->initialized) { - this->unk58_2 = false; - this->unk10_12 = func_80388EF0(this); - this->marker->propPtr->unk8_3 = true; - actor_collisionOff(this); - this->initialized = true; - } - if (!this->volatile_initialized) { - this->unk1C[0] = this->position[0]; - this->unk1C[1] = this->position[1]; - this->unk1C[2] = this->position[2]; - this->unk1C[1] += 250.0f; - - this->volatile_initialized = true; - if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { - subaddie_set_state(this, 3); - } - } - - - switch (this->state) { /* irregular */ - case 1: - if (levelSpecificFlags_get(this->unk10_12 + 7)) { - timedFunc_set_1(0.05f, (GenFunction_1)func_803891B0, (uintptr_t)this->marker); - timedFunc_set_1(4.0f, (GenFunction_1)func_8038921C, (uintptr_t)this->marker); - subaddie_set_state(this, 2); - } - break; - case 2: - this->position[1] += 60.0f * time_getDelta(); - if (this->unk1C[1] <= this->position[1]) { - levelSpecificFlags_set(this->unk10_12 + 7, false); - subaddie_set_state(this, 3); - } - break; - case 3: - this->position[1] = this->unk1C[1]; - break; - } -} diff --git a/src/CCW/snarebear_proximity.c b/src/CCW/snarebear_proximity.c deleted file mode 100644 index 1090a0529..000000000 --- a/src/CCW/snarebear_proximity.c +++ /dev/null @@ -1,122 +0,0 @@ -// BanjoDecomp: code_7BF0.c -#include -#include "functions.h" -#include "variables.h" - - -void func_8038E0C8(Actor *this); - -/* .data */ -ActorAnimationInfo D_8038F8F0[] = { - {0x000, 0.0f}, - {0x16C, 2.0f}, - {0x16B, 1.2f} -}; - -ActorInfo D_8038F908 = { - MARKER_1F9_SNARE_BEAR, ACTOR_1E9_SNARE_BEAR, ASSET_440_MODEL_SNAREBEAR, - 0x1, D_8038F8F0, - func_8038E0C8, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -/* .code */ -void func_8038DFE0(Actor* actor) { - subaddie_set_state_with_direction(actor, 1, 0.001f, 1); - actor->unk38_31 = randi2(0, 0); -} - -void CCW_func_8038E034(Actor* actor) { - subaddie_set_state_with_direction(actor, 2, 0.001f, 1); -} - -void func_8038E060(BoneTransformList *arg0, ActorMarker *marker){ - Actor *this; - f32 sp28[3]; - s32 pad24; - f32 sp18[4]; // quaternion: func_80345C78 writes 4 floats - - this = marker_getActor(marker); - if(arg0){ - sp28[0] = 0.0f; - sp28[1] = this->unk1C[0]; - sp28[2] = 0.0f; - - - func_80345C78(sp18, sp28); - func_8033A8F0(arg0, 1, sp18); - modelRender_setBoneTransformList(arg0); - } -} - -void func_8038E0C8(Actor *this) { - f32 sp44[3]; - f32 sp40; - f32 sp3C; - f32 sp38; - f32 sp34; - - sp34 = time_getDelta(); - - if(!subaddie_playerIsWithinSphere(this, 3000)) return; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - func_8028746C(this->anctrl, (GenFunction_2)func_8038E060); - func_8028748C(this->anctrl, (uintptr_t)this->marker); - this->marker->propPtr->unk8_3 = true; - this->unk1C[0] = 0.0f; - this->unk38_31 = 0; - } - - if (player_getTransformation() == TRANSFORM_6_BEE) { - actor_collisionOff(this); - } else { - actor_collisionOn(this); - player_getPosition(sp44); - func_80258A4C(this->position, this->yaw - 90.0f, sp44, &sp40, &sp3C, &sp38); - if( (sp40 < 1050.0f) - && (sp38 > -1.0f) - && (sp38 < 1.0f) - ) { - func_80258A4C(this->position, this->unk1C[0] + (this->yaw - 90.0f), sp44, &sp40, &sp3C, &sp38); - this->unk1C[0] += sp38 * 160.0f * sp34; - } else { - if (this->unk1C[0] > 0.0f) { - this->unk1C[0] -= (30.0f * sp34); - this->unk1C[0] = (this->unk1C[0] < 0.0f) ? 0.0f : this->unk1C[0]; - - } else if (this->unk1C[0] < 0.0f) { - this->unk1C[0] += (30.0f * sp34); - this->unk1C[0] = (this->unk1C[0] > 0.0f) ? 0.0f : this->unk1C[0]; - } - } - } - switch (this->state) { - case 1: - if (this->unk38_31 != 0) { - this->unk38_31--; - break; - } - if( subaddie_playerIsWithinSphereAndActive(this, 0x2A8) - && (this->unk38_31 == 0) - && (player_getTransformation() == TRANSFORM_1_BANJO) - ) { - CCW_func_8038E034(this); - } - break; - - case 2: - if (actor_animationIsAt(this, 0.999f)) { - func_8038DFE0(this); - break; - } - if( actor_animationIsAt(this, 0.18f) - || actor_animationIsAt(this, 0.47f) - || actor_animationIsAt(this, 0.78f) - ) { - sfx_playFadeShorthandDefault(SFX_80_YUMYUM_CLACK, 1.0f, 32000, this->position, 1500, 3000); - } - break; - } -} diff --git a/src/CCW/zubba.c b/src/CCW/zubba.c new file mode 100644 index 000000000..bb9095edc --- /dev/null +++ b/src/CCW/zubba.c @@ -0,0 +1,240 @@ +// BanjoDecomp: code_950.c +#include +#include "functions.h" +#include "variables.h" + +extern void func_8030DBFC(u8, f32, f32, f32); + +typedef struct{ + u8 sfxsourceIdx; + //u8 pad1[3]; + ActorMarker *honeyLumpMarker; + f32 distanceToPlayer[3]; + f32 unk14; + f32 unk18; // time related +}ActorLocal_CCW_950; + +void chZubba_update(Actor *this); + +/* .data */ +ActorInfo chZubba = { + MARKER_1AE_ZUBBA, ACTOR_29B_ZUBBA, ASSET_446_MODEL_ZUBBA, + 0x0, NULL, + chZubba_update, NULL, actor_draw, + 0, 0, 1.0f, 0 +}; + +enum chzubba_state_e { + CH_ZUBBA_STATE_0_NOT_INIT, + CH_ZUBBA_STATE_1_NON_AGRO_FLYING, + CH_ZUBBA_STATE_2_ATTACK, + CH_ZUBBA_STATE_3_HIT_PLAYER, + CH_ZUBBA_STATE_4_DIE, + CH_ZUBBA_STATE_5_SPLAT, + CH_ZUBBA_STATE_6_DIE_DESPAWN, + CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN +}; + +/* .code */ +void chZubba_setState(Actor *this, s32 next_state) { + ActorLocal_CCW_950 *local; + f32 player_position_1[3]; + f32 player_position_2[3]; + + local = (ActorLocal_CCW_950 *)&this->local; + local->unk18 = 0.0f; + if (next_state == CH_ZUBBA_STATE_1_NON_AGRO_FLYING) { + local->unk18 = 800.0f; + skeletalAnim_set(this->unk148, ASSET_16F_ANIM_ZUBBA_FLY_MOVE, 0.0f, 0.65f); + } + if (next_state == CH_ZUBBA_STATE_2_ATTACK) { + skeletalAnim_set(this->unk148, ASSET_170_ANIM_ZUBBA_FLY_IDLE, 0.1f, 0.65f); + player_getPosition(player_position_1); + player_position_1[1] += 50.0f; + local->distanceToPlayer[0] = player_position_1[0] - this->position[0]; + local->distanceToPlayer[1] = player_position_1[1] - this->position[1]; + local->distanceToPlayer[2] = player_position_1[2] - this->position[2]; + ml_vec3f_normalize(local->distanceToPlayer); + if ((local->distanceToPlayer[0] == 0.0f) + && (local->distanceToPlayer[1] == 0.0f) + && (local->distanceToPlayer[2] == 0.0f)) + { + local->distanceToPlayer[1] = -1.0f; + } + } + if (next_state == CH_ZUBBA_STATE_3_HIT_PLAYER) { + sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); + func_80324D54(randf2(0.1f, 0.4f), SFX_3FC_ZUBBA_UNK, randf2(0.95f, 1.1f), 32000, this->position, 500.0f, 3000.0f); + actor_collisionOff(this); + } + if (next_state == CH_ZUBBA_STATE_4_DIE) { + skeletalAnim_set(this->unk148, ASSET_171_ANIM_ZUBBA_DIE, 0.1f, 0.2f); + sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); + func_80324D54(0.1f, 0x66, randf2(1.6f, 1.7f), 32000, this->position, 500.0f, 3000.0f); + chZubbaFight_zubbaKilled(local->honeyLumpMarker); + actor_collisionOff(this); + player_getPosition(player_position_2); + player_position_2[1] += 50.0f; + local->distanceToPlayer[0] = this->position[0] - player_position_2[0]; + local->distanceToPlayer[1] = this->position[1] - player_position_2[1]; + local->distanceToPlayer[2] = this->position[2] - player_position_2[2]; + ml_vec3f_normalize(local->distanceToPlayer); + if ((local->distanceToPlayer[0] == 0.0f) + && (local->distanceToPlayer[1] == 0.0f) + && (local->distanceToPlayer[2] == 0.0f)) + { + local->distanceToPlayer[1] = -1.0f; + } + } + if (next_state == CH_ZUBBA_STATE_5_SPLAT) { + func_8030E878(SFX_A_BANJO_LANDING_05, randf2(0.85f, 0.95f), 18000, this->position, 500.0f, 3000.0f); + skeletalAnim_set(this->unk148, ASSET_172_ANIM_ZUBBA_LAND, 0.0f, 1.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + } + if (next_state == CH_ZUBBA_STATE_6_DIE_DESPAWN) { + marker_despawn(this->marker); + } + if (next_state == CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN) { + chZubbaFight_zubbaDisappear(local->honeyLumpMarker); + marker_despawn(this->marker); + } + this->state = next_state; +} + + +void chZubba_hitPlayer(ActorMarker* marker, ActorMarker *other_marker) { + chZubba_setState(marker_getActor(marker), CH_ZUBBA_STATE_3_HIT_PLAYER); +} + +void chZubba_die(ActorMarker* marker, ActorMarker *other_marker) { + chZubba_setState(marker_getActor(marker), CH_ZUBBA_STATE_4_DIE); +} + +void chZubba_freeSfx(Actor *this){ + ActorLocal_CCW_950 *local; + + local = (ActorLocal_CCW_950 *)&this->local; + sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); +} + +void chZubba_update(Actor *this) { + ActorLocal_CCW_950 *local; + f32 time_delta; + Actor *honey_lump_actor; + s32 zubbas_defeated; + s32 zubbas_to_defeat; + f32 player_position[3]; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; + f32 temp_f0; + f32 pad; + + + time_delta = time_getDelta(); + local = (ActorLocal_CCW_950 *)&this->local; + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->actorFreeFunc = chZubba_freeSfx; + local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); + local->honeyLumpMarker = 0; + local->unk14 = 1000.0f; + sfxsource_setSfxId(local->sfxsourceIdx, SFX_3FA_HONEYCOMB_TALKING); + sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); + sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); + sfxsource_setSampleRate(local->sfxsourceIdx, 0); + marker_setCollisionScripts(this->marker, chZubba_hitPlayer, NULL, chZubba_die); + chZubba_setState(this, CH_ZUBBA_STATE_1_NON_AGRO_FLYING); + return; + } + if(local->honeyLumpMarker == NULL) { + honey_lump_actor = actorArray_findActorFromActorId(ACTOR_299_ZUBBA_HONEY_LUMP); + if (honey_lump_actor == NULL) { + marker_despawn(this->marker); + return; + } + local->honeyLumpMarker = honey_lump_actor->marker; + chZubbaFight_zubbaScore(local->honeyLumpMarker, &zubbas_defeated, &zubbas_to_defeat); + local->unk14 = (((f32)zubbas_defeated /(f32)zubbas_to_defeat) * 1000.0f) + 1000.0f; + } + + if (this->state == CH_ZUBBA_STATE_1_NON_AGRO_FLYING) { + temp_f0 = this->position[1]; + this->position[0] += 0.1 * time_delta; + this->position[1] += local->unk18 * time_delta; + if ((temp_f0 < 0.0f) && (this->position[1] >= 0.0f)) { + func_8030E878(SFX_A_BANJO_LANDING_05, randf2(1.0f, 1.1f), 18000, this->position, 500.0f, 3000.0f); + } + player_getPosition(player_position); + func_80258A4C( + this->position, this->yaw - 90.0f, player_position, + &horizontal_distance, &distance_in_front, &side_angle_radian); + this->yaw += 360.0f * side_angle_radian * time_delta; + if (this->position[1] > 150.0f) { + local->unk18 -= 2000.0f * time_delta; + if (local->unk18 < 0.0f) { + chZubba_setState(this, CH_ZUBBA_STATE_2_ATTACK); + } + } + } + + if (this->state == CH_ZUBBA_STATE_2_ATTACK) { + if (local->unk18 < local->unk14) { + local->unk18 += (4.0f * local->unk14 * time_delta); + } + this->position[0] += local->distanceToPlayer[0] * local->unk18 * time_delta; + this->position[1] += local->distanceToPlayer[1] * local->unk18 * time_delta; + this->position[2] += local->distanceToPlayer[2] * local->unk18 * time_delta; + if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) + || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) + || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) + ){ + chZubba_setState(this, CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN); + } + } + + if (this->state == CH_ZUBBA_STATE_3_HIT_PLAYER) { + this->position[1] += local->unk18 * time_delta; + if (local->unk18 < local->unk14) { + local->unk18 += 2000.0f * time_delta; + } + + if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) + || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) + || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) + ) { + chZubba_setState(this, CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN); + } + } + + if (this->state == CH_ZUBBA_STATE_4_DIE) { + this->position[0] += local->distanceToPlayer[0] * 1000.0f * time_delta; + this->position[1] -= local->unk18 * time_delta; + this->position[2] += local->distanceToPlayer[2] * 1000.0f * time_delta; + if (local->unk18 < local->unk14) { + local->unk18 += (1000.0f * time_delta); + } + if (this->position[1] <= 0.0f) { + this->position[1] = 0.0f; + chZubba_setState(this, CH_ZUBBA_STATE_5_SPLAT); + } + } + + if (this->state == CH_ZUBBA_STATE_5_SPLAT) { + this->position[1] -= 300.0f * time_delta; + if (this->position[1] < -200.0f) { + chZubba_setState(this, CH_ZUBBA_STATE_6_DIE_DESPAWN); + } + } + + if(this->state); + if (this->state == CH_ZUBBA_STATE_2_ATTACK) { + func_8030DBFC(local->sfxsourceIdx, 1.0f, 1.1f, 0.05f); + } else { + func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); + } + sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); + sfxsource_set_position(local->sfxsourceIdx, this->position); + sfxSource_func_8030E2C4(local->sfxsourceIdx); + sfxsource_setSampleRate(local->sfxsourceIdx, (s32) ((local->unk18 / local->unk14) * 10000.0f)); +} diff --git a/src/CCW/zubba_hive_npc.c b/src/CCW/zubba_hive_npc.c new file mode 100644 index 000000000..d6097dbbb --- /dev/null +++ b/src/CCW/zubba_hive_npc.c @@ -0,0 +1,157 @@ +// BanjoDecomp: code_14B0.c +#include "functions.h" +#include "variables.h" +#include + +#include + +extern void func_8030DBFC(u8, f32, f32, f32); +extern void sfxsource_setSampleRate(u8, s32); + +typedef struct{ + s16 map; + u8 mapFlag; + u8 jiggyId; + s16 textId; +} Zubba_Docile_Dialog; + +typedef struct { + u8 sfxsourceIdx; + // u8 pad1[3]; + Zubba_Docile_Dialog *dialog; + f32 unk8; // random value? + f32 targetPosition[3]; + f32 unk18[3]; // some kind of position? +} ActorLocal_ZubbaDocile; + +void chZubbaDocile_update(Actor *this); + +/* .data */ +Zubba_Docile_Dialog chZubbaDocileDialog[] = { + { + MAP_5B_CCW_SPRING_ZUBBA_HIVE, + CCW_ZUBBA_SPECIFIC_FLAG_7_SPRING_DIALOG, + JIGGY_4C_CCW_ZUBBAS, + VER_SELECT(ASSET_CE1_DIALOG_ZUBBA_MEET_SPRING, 0x09F6, 0, 0) + }, + { + MAP_5C_CCW_AUTUMN_ZUBBA_HIVE, + CCW_ZUBBA_SPECIFIC_FLAG_8_AUTUMN_DIALOG, + 0, // [port] decomp uses NULL; jiggyId is an integer, not a pointer + VER_SELECT(ASSET_CE5_DIALOG_ZUBBA_MEET_FALL, 0x09FA, 0, 0) + }, + { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion +}; + +ActorInfo chZubbaDocile = { + MARKER_1AF_ZUBBA_DOCILE, ACTOR_29C_ZUBBA_DOCILE, ASSET_446_MODEL_ZUBBA, + 0x0, NULL, + chZubbaDocile_update, NULL, actor_draw, + 0, 0, 1.0f, 0 +}; + +enum chzubbadocile_state_e { + CH_ZUBBA_DOCILE_STATE_0_NOT_INIT, + CH_ZUBBA_DOCILE_STATE_1_DOCILE +}; + +/* .code */ +void chZubbaDocile_setState(Actor *this, s32 next_state) { + ActorLocal_ZubbaDocile *local = (ActorLocal_ZubbaDocile *)&this->local; + int i; + + if (next_state == CH_ZUBBA_DOCILE_STATE_1_DOCILE) { + if (skeletalAnim_getAnimId(this->unk148) != ASSET_16F_ANIM_ZUBBA_FLY_MOVE) { + skeletalAnim_set(this->unk148, ASSET_16F_ANIM_ZUBBA_FLY_MOVE, 0.1f, 0.65f); + } + for(i = 0; i < 10; i++){ + local->targetPosition[0] = randf2(-500.0f, 500.0f); + local->targetPosition[1] = randf2(400.0f, 900.0f); + local->targetPosition[2] = randf2(-400.0f, 700.0f); + if(ml_vec3f_distance(this->position, local->targetPosition) > 800.0f) + break; + } + local->unk8 = randf2(500.0f, 1000.0f); + } + this->state = next_state; +} + +void chZubbaDocile_free(Actor *this){ + ActorLocal_ZubbaDocile *local = (ActorLocal_ZubbaDocile *)&this->local; + sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); +} + +void chZubbaDocile_update(Actor *this) { + ActorLocal_ZubbaDocile *local; + f32 time_delta; + f32 distance[3]; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; + f32 player_position[3]; + + local = (ActorLocal_ZubbaDocile *)&this->local; + time_delta = time_getDelta(); + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->actorFreeFunc = chZubbaDocile_free; + local->dialog = &chZubbaDocileDialog[0]; + while((local->dialog->map != 0) && (gsworld_getMap() != local->dialog->map)) { + local->dialog++; + } + local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); + local->unk18[0] = local->unk18[1] = local->unk18[2] = 0.0f; + sfxsource_setSfxId(local->sfxsourceIdx, SFX_3FA_HONEYCOMB_TALKING); + sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); + sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); + sfxsource_setSampleRate(local->sfxsourceIdx, 0); + chZubbaDocile_setState(this, CH_ZUBBA_DOCILE_STATE_1_DOCILE); + return; + } + + if (this->state == CH_ZUBBA_DOCILE_STATE_1_DOCILE) { + distance[0] = local->targetPosition[0] - this->position[0]; + distance[1] = local->targetPosition[1] - this->position[1]; + distance[2] = local->targetPosition[2] - this->position[2]; + if (ml_vec3f_distance(this->position, local->targetPosition) < 500.0f) { + ml_vec3f_set_length(distance, local->unk8 * 8.0f); + } else { + ml_vec3f_set_length(distance, local->unk8 * 2); + } + this->position[0] += (local->unk18[0] * time_delta) + (distance[0] * time_delta * time_delta); + this->position[1] += (local->unk18[1] * time_delta) + (distance[1] * time_delta * time_delta); + this->position[2] += (local->unk18[2] * time_delta) + (distance[2] * time_delta * time_delta); + local->unk18[0] += distance[0] * time_delta; + local->unk18[1] += distance[1] * time_delta; + local->unk18[2] += distance[2] * time_delta; + if (local->unk8 < LENGTH_VEC3F(local->unk18)) { + ml_vec3f_set_length(local->unk18, local->unk8); + } + func_80258A4C( + this->position, this->yaw - 90.0f, local->targetPosition, + &horizontal_distance, &distance_in_front, &side_angle_radian); + this->yaw += 140.0f * side_angle_radian * time_delta; + if (ml_vec3f_distance(this->position, local->targetPosition) < 100.0f) { + chZubbaDocile_setState(this, CH_ZUBBA_DOCILE_STATE_1_DOCILE); + } + } + + if(this->position[0]); + + func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); + sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); + sfxsource_set_position(local->sfxsourceIdx, this->position); + sfxSource_func_8030E2C4(local->sfxsourceIdx); + sfxsource_setSampleRate(local->sfxsourceIdx, 2000.0f + 8000.0f * (LENGTH_VEC3F(local->unk18) / local->unk8)); + if (!mapSpecificFlags_get(local->dialog->mapFlag)) { + player_getPosition(player_position); + if (player_position[2] > -600.0f) { + if (!local->dialog->jiggyId + || !jiggyscore_isCollected(local->dialog->jiggyId)) + { + gcdialog_showDialog(local->dialog->textId, 4, NULL, NULL, NULL, NULL); + mapSpecificFlags_set(local->dialog->mapFlag, true); + } + } + } +} diff --git a/src/FP/bss_pad.c b/src/FP/bss_pad.c deleted file mode 100644 index d073ba296..000000000 --- a/src/FP/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_FP_80392F10[0x10]; diff --git a/src/FP/ch/bearcub.c b/src/FP/ch/bearcub.c index d6ebfc6b6..00b474eaf 100644 --- a/src/FP/ch/bearcub.c +++ b/src/FP/ch/bearcub.c @@ -3,6 +3,9 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" +#include "port/Enhancements/Retention/Retention.h" + extern void func_8028E668(f32[3], f32, f32, f32); extern bool player_setCarryObjectPoseInHorizontalRadius(f32[3], f32, s32, Actor **); @@ -47,6 +50,26 @@ Struct_FP_3E00 D_80391E80[] ={ {LEVEL_FLAG_13_FP_UNKNOWN, MARKER_1FF_RED_PRESENT_COLLECTIBLE, ACTOR_1F1_RED_PRESENT_COLLECTIBLE, 0x1F2} }; +static const struct { + s32 bit; + s32 kind; + s32 item; +} sCubPresentSync[3] = { + { 0x1, ANCHOR_COLLECTIBLE_PRESENT_BLUE, ITEM_20_BLUE_PRESENT }, + { 0x2, ANCHOR_COLLECTIBLE_PRESENT_GREEN, ITEM_1F_GREEN_PRESENT }, + { 0x4, ANCHOR_COLLECTIBLE_PRESENT_RED, ITEM_21_RED_PRESENT }, +}; + +// D_80391E80 row for this cub, or -1. Same mapping the state machine derives inline (sp3C). +static s32 __chBearcub_cubIndex(Actor *this) { + switch (this->marker->id) { + case MARKER_1FA_POLAR_BEAR_CUB_BLUE: return 0; + case MARKER_1FB_POLAR_BEAR_CUB_GREEN: return 1; + case MARKER_1FC_POLAR_BEAR_CUB_RED: return 2; + } + return -1; +} + /* .code */ void func_8038A1F0(Actor **this_ptr, enum marker_e carried_obj_marker_id, enum actor_e actor_id, enum actor_e arg3){ player_setCarryObjectPoseInHorizontalRadius((*this_ptr)->position, 600.0f, actor_id, this_ptr); @@ -55,7 +78,7 @@ void func_8038A1F0(Actor **this_ptr, enum marker_e carried_obj_marker_id, enum a return; } - if (bacarry_get_markerId() != carried_obj_marker_id) { + if (bacarry_getMarkerId() != carried_obj_marker_id) { return; } @@ -79,7 +102,7 @@ void func_8038A274(Actor *this){ } void func_8038A318(ActorMarker *caller, enum asset_e text_id, s32 arg1){ - if(text_id == 0xc19){ + if(text_id == VER_SELECT(ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3, 0x993, 0, 0)){ gcStaticCamera_activate(0x25); jiggy_spawn(JIGGY_2E_FP_PRESENTS, FP_D_80391E74); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 32000); @@ -122,12 +145,41 @@ void func_8038A384(Actor *this){ ){ subaddie_set_state_with_direction(this, 2, randf2(0.0f, 0.9f), 1); } + + // Anchor: reconcile the shared present pool — carried = collected minus delivered. + { + s32 cubIdx = __chBearcub_cubIndex(this); + if (cubIdx >= 0) { + s32 netBits = port_puzzleStep_get(ANCHOR_PUZZLE_FP_PRESENTS); + s32 have = item_getCount(sCubPresentSync[cubIdx].item); + s32 pool = port_carriedSync_collectedCount(sCubPresentSync[cubIdx].kind) - + ((netBits & sCubPresentSync[cubIdx].bit) ? 1 : 0); + if (pool > have) { + item_adjustByDiffWithoutHud(sCubPresentSync[cubIdx].item, pool - have); + } + } + } }//L8038A4E4 + { + s32 cubIdx = __chBearcub_cubIndex(this); + if (cubIdx >= 0) { + s32 netBits; + if (levelSpecificFlags_get(D_80391E80[cubIdx].unk0)) { + port_puzzleStep_orBits(ANCHOR_PUZZLE_FP_PRESENTS, sCubPresentSync[cubIdx].bit); + } + netBits = port_puzzleStep_get(ANCHOR_PUZZLE_FP_PRESENTS); + if ((netBits & sCubPresentSync[cubIdx].bit) && !levelSpecificFlags_get(D_80391E80[cubIdx].unk0)) { + levelSpecificFlags_setEx(D_80391E80[cubIdx].unk0, 1, 0); + subaddie_set_state_with_direction(this, 2, 0.001f, 1); + } + } + } + sp34 = levelSpecificFlags_get(LEVEL_FLAG_11_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_12_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_13_FP_UNKNOWN); - sp38 = (sp34 == 1) ? ASSET_C17_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_1 - : (sp34 == 2) ? ASSET_C18_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_2 - : ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3; + sp38 = (sp34 == 1) ? VER_SELECT(ASSET_C17_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_1, 0x991, 0, 0) + : (sp34 == 2) ? VER_SELECT(ASSET_C18_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_2, 0x992, 0, 0) + : VER_SELECT(ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3, 0x993, 0, 0); this->yaw_ideal = (f32)subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 2.0f); @@ -141,8 +193,8 @@ void func_8038A384(Actor *this){ && !jiggyscore_isCollected(JIGGY_2C_FP_BOGGY_3) && !jiggyscore_isSpawned(JIGGY_2C_FP_BOGGY_3) ){ - if (gcdialog_showDialog(ASSET_C1A_DIALOG_BOGGY_KIDS_MEET, 0x2a, NULL, NULL, NULL, NULL)) { - levelSpecificFlags_set(LEVEL_FLAG_19_FP_UNKNOWN, true); + if (gcdialog_showDialog(VER_SELECT(ASSET_C1A_DIALOG_BOGGY_KIDS_MEET, 0x994, 0, 0), 0x2a, NULL, NULL, NULL, NULL)) { + levelSpecificFlags_set(LEVEL_FLAG_19_FP_UNKNOWN, TRUE); } } } @@ -164,7 +216,7 @@ void func_8038A384(Actor *this){ } if(levelSpecificFlags_get(D_80391E80[sp3C].unk0)){ subaddie_set_state_with_direction(this, 2, 0.001f, 1); - if (sp38 == ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3) { + if (sp38 == VER_SELECT(ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3, 0x993, 0, 0)) { gcdialog_showDialog(sp38, 0x2f, this->position, this->marker, func_8038A318, NULL); } else { diff --git a/src/FP/ch/boggy1.c b/src/FP/ch/boggy1.c index 7c8ff2353..9e2b5b0ff 100644 --- a/src/FP/ch/boggy1.c +++ b/src/FP/ch/boggy1.c @@ -38,8 +38,8 @@ Actor *func_803875E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(!this->unk38_31 || this->state == 5) return this; - func_8033A45C(1, 0); - func_8033A45C(3, 1); + modelRender_setAppendageVisibility(1, 0); + modelRender_setAppendageVisibility(3, 1); this = actor_draw(marker, gfx, mtx, vtx); if(marker->unk14_21){ vec3fArray_get_vec3f(func_80329934(), 5, this->velocity); @@ -86,8 +86,8 @@ void func_803877A8(ActorMarker *caller, enum asset_e text_id, s32 arg2){ void func_80387828(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this = marker_getActor(caller); - if (text_id == 0xc00) { - gcdialog_showDialog(ASSET_C2B_DIALOG_BOGGY_SAVED_2, 0xf, NULL, this->marker, NULL, func_803877A8); + if (text_id == VER_SELECT(ASSET_C00_DIALOG_BOGGY_SAVED, 0x97A, 0, 0)) { + gcdialog_showDialog(VER_SELECT(ASSET_C2B_DIALOG_BOGGY_SAVED_2, 0x9A5, 0, 0), 0xf, NULL, this->marker, NULL, func_803877A8); } } @@ -143,14 +143,14 @@ void func_8038794C(Actor *this){ if(mapSpecificFlags_get(0x1)){ func_8028F94C(1, this->position); timed_setStaticCameraToNode(0.0f, 0x12); - func_80324DBC(1.0f, 0xc00, 0xe, NULL, this->marker, func_80387828, func_803877A8); + func_80324DBC(1.0f, VER_SELECT(ASSET_C00_DIALOG_BOGGY_SAVED, 0x97A, 0, 0), 0xe, NULL, this->marker, func_80387828, func_803877A8); func_803876A4(this); break; }//L80387B38 if(!this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 0x1f4)){ if(!player_movementGroup() || player_movementGroup() == BSGROUP_8_TROT){ - if (gcdialog_showDialog(ASSET_BFF_DIALOG_BOGGY_MEET, 0x2a, this->position, NULL, NULL, NULL)) { + if (gcdialog_showDialog(VER_SELECT(ASSET_BFF_DIALOG_BOGGY_MEET, 0x979, 0, 0), 0x2a, this->position, NULL, NULL, NULL)) { for (i = 0; i < 5; i++) { timedFunc_set_1(D_80391BEC[i], (GenFunction_1) func_8038787C, (uintptr_t)this->marker); } diff --git a/src/FP/ch/boggy2.c b/src/FP/ch/boggy2.c index 4b8110cd3..776954a99 100644 --- a/src/FP/ch/boggy2.c +++ b/src/FP/ch/boggy2.c @@ -64,8 +64,8 @@ Actor *func_80388740(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ ActorLocal_FP_2350 * local = (ActorLocal_FP_2350 *) &this->local; f32 sp2C[3]; - func_8033A45C(1, 1); - func_8033A45C(3, 1); + modelRender_setAppendageVisibility(1, 1); + modelRender_setAppendageVisibility(3, 1); this = actor_draw(marker, gfx, mtx, vtx); if(this->volatile_initialized && marker->unk14_21){ if( this->state == 4 @@ -96,20 +96,20 @@ void FP_func_803888E4(Actor *this){ static f32 D_80391D18[3] = {1463.0f, 635.0f, 5193.0f}; subaddie_set_state_with_direction(this, 0xC, 0.0001f, 1); if(!jiggyscore_isSpawned(JIGGY_30_FP_BOGGY_2)){ - if(mapSpecificFlags_get(5)){ - func_80324DBC(0.1f, 0xc06, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_5_WALRUS_RACE_FAILED)){ + func_80324DBC(0.1f, VER_SELECT(ASSET_C06_DIALOG_BOGGY_SLED_WALRUS_SECOND_START, 0x980, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } else{//L80388964 - func_80324DBC(0.1f, 0xc03, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + func_80324DBC(0.1f, VER_SELECT(ASSET_C03_DIALOG_BOGGY_SLED_WALRUS_START, 0x97D, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } } else{//L803889A0 func_8028F490(D_80391D0C); - if(mapSpecificFlags_get(6)){ - func_80324DBC(0.1f, 0xc29, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_6_BANJO_RACE_FAILED)){ + func_80324DBC(0.1f, VER_SELECT(ASSET_C29_DIALOG_BOGGY_SLED_BEAR_SECOND_START, 0x9A3, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } else{ - func_80324DBC(0.1f, 0xc28, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + func_80324DBC(0.1f, VER_SELECT(ASSET_C28_DIALOG_BOGGY_SLED_BEAR_START, 0x9A2, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } }//L80388A30 mapSpecificFlags_set(5, true); @@ -126,11 +126,11 @@ void func_80388A50(Actor *this){ void func_80388A94(Actor *this){ func_80388A50(this); - if(mapSpecificFlags_get(6)){ - gcdialog_showDialog(ASSET_C0A_DIALOG_BOGGY_SLED_BEAR_MISS_RETRY, 0xe, this->position, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_6_BANJO_RACE_FAILED)){ + gcdialog_showDialog(VER_SELECT(ASSET_C0A_DIALOG_BOGGY_SLED_BEAR_MISS_RETRY, 0x984, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL); } else{ - gcdialog_showDialog(ASSET_C09_DIALOG_BOGGY_SLED_BEAR_ANSWER_TO_START, 0xe, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C09_DIALOG_BOGGY_SLED_BEAR_ANSWER_TO_START, 0x983, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL); } } @@ -138,17 +138,17 @@ void func_80388B18(Actor *this, u8 arg1){ if(arg1 == true){ if(player_getTransformation() == TRANSFORM_4_WALRUS){ func_80388A50(this); - if(mapSpecificFlags_get(5)){ - gcdialog_showDialog(ASSET_C05_DIALOG_BOGGY_SLED_WALRUS_MISS_RETRY, 0xf, this->position, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_5_WALRUS_RACE_FAILED)){ + gcdialog_showDialog(VER_SELECT(ASSET_C05_DIALOG_BOGGY_SLED_WALRUS_MISS_RETRY, 0x97F, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); } else{ - gcdialog_showDialog(ASSET_C02_DIALOG_BOGGY_SLED_WALRUS_MEET, 0xf, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C02_DIALOG_BOGGY_SLED_WALRUS_MEET, 0x97C, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); } } else{//L80388BB8 if(!volatileFlag_get(VOLATILE_FLAG_B3)){ - if(gcdialog_showDialog(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0xe, this->position, this->marker, func_80388D70, NULL)){ - volatileFlag_set(VOLATILE_FLAG_B3, true); + if(gcdialog_showDialog(VER_SELECT(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0x97B, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL)){ + volatileFlag_set(VOLATILE_FLAG_B3, TRUE); func_80388A50(this); } } @@ -157,8 +157,8 @@ void func_80388B18(Actor *this, u8 arg1){ else{//L80388C08 if(player_getTransformation() == TRANSFORM_4_WALRUS){ if(!volatileFlag_get(VOLATILE_FLAG_B4)){ - if(gcdialog_showDialog(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0xe, this->position, this->marker, func_80388D70, NULL)){ - volatileFlag_set(VOLATILE_FLAG_B4, true); + if(gcdialog_showDialog(VER_SELECT(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0x982, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL)){ + volatileFlag_set(VOLATILE_FLAG_B4, TRUE); func_80388A50(this); } } @@ -198,10 +198,10 @@ void func_80388D70(ActorMarker *caller, enum asset_e text_id, s32 arg2){ timed_exitStaticCamera(0.0f); switch(text_id){ - case 0xc03: - case 0xc06: - case 0xc28: - case 0xc29://L80388DC4 + case VER_SELECT(ASSET_C03_DIALOG_BOGGY_SLED_WALRUS_START, 0x97D, 0, 0): + case VER_SELECT(ASSET_C06_DIALOG_BOGGY_SLED_WALRUS_SECOND_START, 0x980, 0, 0): + case VER_SELECT(ASSET_C28_DIALOG_BOGGY_SLED_BEAR_START, 0x9A2, 0, 0): + case VER_SELECT(ASSET_C29_DIALOG_BOGGY_SLED_BEAR_SECOND_START, 0x9A3, 0, 0)://L80388DC4 coMusicPlayer_playMusic(COMUSIC_3A_FP_BOGGY_RACE, 25000); func_8025A58C(0, 4000); core1_ce60_incOrDecCounter(false); @@ -392,7 +392,7 @@ void func_803895E0(void){ : cubeList_findNodePropByActorIdAndPosition_s32(D_80391DB8[i].unk0, D_80391DAC); nodeprop_getPosition(s0, sp64); - f20 = (f32)nodeprop_getYaw(s0); + f20 = (f32)nodeProp_getYaw(s0); f8 = (f32)nodeprop_getScale(s0); f22 = f8*0.01; actor = actor_spawnWithYaw_f32(D_80391DB8[i].actor_id, sp64, (s32)f20); @@ -474,7 +474,7 @@ void func_803896FC(Actor *this){ } else if( subaddie_playerIsWithinSphereAndActive(this, 0x1C2) && player_movementGroup() == BSGROUP_0_NONE - && func_8028F20C() + && player_isStableWithExtraSteps() && func_8028EFC8() && sp3C[FACE_BUTTON(BUTTON_B)] == 1 && !gcdialog_hasCurrentTextId() @@ -483,13 +483,13 @@ void func_803896FC(Actor *this){ && player_getTransformation() != TRANSFORM_4_WALRUS && volatileFlag_get(VOLATILE_FLAG_B3) ){ - gcdialog_showDialog(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0xf, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0x97B, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); } else if( local->unk19 == 2){ if( player_getTransformation() == TRANSFORM_4_WALRUS && volatileFlag_get(VOLATILE_FLAG_B4) ){ - gcdialog_showDialog(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0xf, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0x982, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); } else if( player_getTransformation() != TRANSFORM_4_WALRUS){ func_80388A94(this); diff --git a/src/FP/ch/boggy3.c b/src/FP/ch/boggy3.c index a1e42df6a..6e0e66200 100644 --- a/src/FP/ch/boggy3.c +++ b/src/FP/ch/boggy3.c @@ -27,11 +27,11 @@ Actor *func_80390290(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(this->unk38_31) return this; - if(gcdialog_getCurrentTextId() == 0xC1F || gcdialog_getCurrentTextId() == 0xC1E){ + if(gcdialog_getCurrentTextId() == VER_SELECT(ASSET_C1F_DIALOG_BOGGY_IGLOO_2, 0x999, 0, 0) || gcdialog_getCurrentTextId() == VER_SELECT(ASSET_C1E_DIALOG_BOGGY_IGLOO_1, 0x998, 0, 0)){ sp18 = 1; } - func_8033A45C(1, 0); - func_8033A45C(3, sp18); + modelRender_setAppendageVisibility(1, 0); + modelRender_setAppendageVisibility(3, sp18); return actor_draw(marker, gfx, mtx, vtx); } @@ -53,7 +53,9 @@ void func_80390388(Actor *this){ levelSpecificFlags_set(LEVEL_FLAG_12_FP_UNKNOWN, true); levelSpecificFlags_set(LEVEL_FLAG_13_FP_UNKNOWN, true); } - if(jiggyscore_isCollected(JIGGY_2C_FP_BOGGY_3) || jiggyscore_isSpawned(JIGGY_2C_FP_BOGGY_3)){ + if(EventSystem_Should(VB_BOGGY_HOME_VISIBLE, + jiggyscore_isCollected(JIGGY_2C_FP_BOGGY_3) || jiggyscore_isSpawned(JIGGY_2C_FP_BOGGY_3), + this)){ this->unk38_31 = false; this->marker->propPtr->unk8_3 = true; } @@ -78,15 +80,15 @@ void func_80390388(Actor *this){ && (player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT) ){ if(0.0f == this->unk1C[0] && func_80390334()){ - if(gcdialog_showDialog(ASSET_C1F_DIALOG_BOGGY_IGLOO_2, 0xb, this->position, NULL, NULL, NULL)){ - this->has_met_before = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_C1F_DIALOG_BOGGY_IGLOO_2, 0x999, 0, 0), 0xb, this->position, NULL, NULL, NULL)){ + this->has_met_before = TRUE; this->unk1C[0] = 1.0f; } } else{ if( !this->has_met_before ){ - if(gcdialog_showDialog(ASSET_C1E_DIALOG_BOGGY_IGLOO_1, 0x2b, this->position, NULL, NULL, NULL)){ - this->has_met_before = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_C1E_DIALOG_BOGGY_IGLOO_1, 0x998, 0, 0), 0x2b, this->position, NULL, NULL, NULL)){ + this->has_met_before = TRUE; } } } diff --git a/src/FP/mapstate/slalomctrl.c b/src/FP/ch/boggyraceflag1.c similarity index 94% rename from src/FP/mapstate/slalomctrl.c rename to src/FP/ch/boggyraceflag1.c index 559186760..12be9720e 100644 --- a/src/FP/mapstate/slalomctrl.c +++ b/src/FP/ch/boggyraceflag1.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_19E0.c +// BanjoDecomp: FP/ch/boggyraceflag1.c #include #include "functions.h" #include "variables.h" @@ -34,9 +34,9 @@ Actor *func_80387DD0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(this->velocity[0] == 0.0f || 0.0f != this->velocity[1]) return this; - func_8033A45C(2, this->velocity[0] == 1.0f ? 1 : 0); - func_8033A45C(3, this->velocity[0] == 3.0f ? 1 : 0); - func_8033A45C(4, this->velocity[0] == 2.0f ? 1 : 0); + modelRender_setAppendageVisibility(2, this->velocity[0] == 1.0f ? 1 : 0); + modelRender_setAppendageVisibility(3, this->velocity[0] == 3.0f ? 1 : 0); + modelRender_setAppendageVisibility(4, this->velocity[0] == 2.0f ? 1 : 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/mapstate/slalom2ctrl.c b/src/FP/ch/boggyraceflag2.c similarity index 89% rename from src/FP/mapstate/slalom2ctrl.c rename to src/FP/ch/boggyraceflag2.c index 2c768c47d..795d3d2ab 100644 --- a/src/FP/mapstate/slalom2ctrl.c +++ b/src/FP/ch/boggyraceflag2.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_1FF0.c +// BanjoDecomp: FP/ch/boggyraceflag2.c #include #include "functions.h" #include "variables.h" @@ -29,9 +29,9 @@ Actor *func_803883E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(this->velocity[0] == 0.0f || 0.0f != this->velocity[1]) return this; - func_8033A45C(2, this->velocity[0] == 1.0f ? 1 : 0); - func_8033A45C(3, this->velocity[0] == 3.0f ? 1 : 0); - func_8033A45C(4, this->velocity[0] == 2.0f ? 1 : 0); + modelRender_setAppendageVisibility(2, this->velocity[0] == 1.0f ? 1 : 0); + modelRender_setAppendageVisibility(3, this->velocity[0] == 3.0f ? 1 : 0); + modelRender_setAppendageVisibility(4, this->velocity[0] == 2.0f ? 1 : 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/ch/cavewozza.c b/src/FP/ch/cavewozza.c index b41f13246..d61c7dfe6 100644 --- a/src/FP/ch/cavewozza.c +++ b/src/FP/ch/cavewozza.c @@ -70,15 +70,15 @@ void chCaveWozza_update(Actor *this){ if (subaddie_playerIsWithinSphereAndActive(this, 350)) { if (player_getTransformation() == TRANSFORM_4_WALRUS) { if (!levelSpecificFlags_get(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED)) { - if (gcdialog_showDialog(ASSET_C27_DIALOG_WOZZA_CAVE_MEET_AS_WALRUS, 0x23, NULL, NULL, NULL, NULL)) { - levelSpecificFlags_set(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED, true); + if (gcdialog_showDialog(VER_SELECT(ASSET_C27_DIALOG_WOZZA_CAVE_MEET_AS_WALRUS, 0x9A1, 0, 0), 0x23, NULL, NULL, NULL, NULL)) { + levelSpecificFlags_set(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED, TRUE); } } } else { - if (!levelSpecificFlags_get(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED)) { - if (gcdialog_showDialog(ASSET_C26_DIALOG_WOZZA_CAVE_MEET_AS_BEAR, 0x23, NULL, NULL, NULL, NULL)) { - levelSpecificFlags_set(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED, true); + if (!levelSpecificFlags_get(LEVEL_FLAG_32_FP_WOZZA_BEAR_TALKED)) { + if (gcdialog_showDialog(VER_SELECT(ASSET_C26_DIALOG_WOZZA_CAVE_MEET_AS_BEAR, 0x9A0, 0, 0), 0x23, NULL, NULL, NULL, NULL)) { + levelSpecificFlags_set(LEVEL_FLAG_32_FP_WOZZA_BEAR_TALKED, TRUE); } } } diff --git a/src/FP/ch/racesled.c b/src/FP/ch/racesled.c index 083626892..7bff52d2f 100644 --- a/src/FP/ch/racesled.c +++ b/src/FP/ch/racesled.c @@ -56,7 +56,7 @@ void __chRaceSled_touch(ActorMarker *this_marker, ActorMarker *other_marker){ if(this->state == 2){ player_getPosition(plyr_pos); if( this->position_y + 20.0f < plyr_pos[1] - && func_8028F20C() + && player_isStableWithExtraSteps() && player_getTransformation() == TRANSFORM_4_WALRUS && func_8028F68C(BS_INTR_27_WALRUS_SLED, this->marker) ){ diff --git a/src/FP/ch/snowmanbutton.c b/src/FP/ch/snowmanbutton.c index 08e55fab0..2f536cf12 100644 --- a/src/FP/ch/snowmanbutton.c +++ b/src/FP/ch/snowmanbutton.c @@ -3,6 +3,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + Actor *func_80386B80(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void FP_func_80386CF8(Actor *this); @@ -40,8 +42,8 @@ s32 D_80391B44[3] = {225, 225, 245}; /* .code */ Actor *func_80386B80(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - func_8033A45C(1, this->state == 3); - func_8033A45C(2, modelRender_func_8033A0F0(1) ^ 1); + modelRender_setAppendageVisibility(1, this->state == 3); + modelRender_setAppendageVisibility(2, modelRender_func_8033A0F0(1) ^ 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -89,6 +91,18 @@ void FP_func_80386CF8(Actor *this){ } } + { + s32 bit = 1 << (this->actorTypeSpecificField - 1); + if(this->state == 1 && (port_puzzleStep_get(ANCHOR_PUZZLE_FP_SNOWBUTTONS) & bit)){ + subaddie_set_state_with_direction(this, 2, 0.01f, 1); + actor_collisionOff(this); + maSnowButton_decRemaining(); + } + if(this->state != 1){ + port_puzzleStep_orBits(ANCHOR_PUZZLE_FP_SNOWBUTTONS, bit); + } + } + switch(this->state){ case 1: break; diff --git a/src/FP/ch/twinkly.c b/src/FP/ch/twinkly.c index d5fbd1238..ebdb1e130 100644 --- a/src/FP/ch/twinkly.c +++ b/src/FP/ch/twinkly.c @@ -85,8 +85,8 @@ Actor *func_8038C0B0(ActorMarker *marker, f32 arg1[3], f32 arg2, f32 arg3[3], s3 Actor *chTwinkly_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - func_8033A45C(2, this->unk38_31); - func_8033A45C(1, modelRender_func_8033A0F0(2) ^ 1); + modelRender_setAppendageVisibility(2, this->unk38_31); + modelRender_setAppendageVisibility(1, modelRender_func_8033A0F0(2) ^ 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -337,11 +337,11 @@ void chTwinkly_update(Actor *this){ if(this->unk1C[1] <= this->position_y){ this->position_y = this->unk1C[1]; if(!fileProgressFlag_get(FILEPROG_82_MET_TWINKLIES)){ - gcdialog_showDialog(0xc12, 0x2a, this->position, this->marker, chTwinkly_setUpMinigame, NULL); - fileProgressFlag_set(FILEPROG_82_MET_TWINKLIES, true); + gcdialog_showDialog(VER_SELECT(ASSET_C12_DIALOG_TWINKLIE_MINIGAME_START, 0x98C, 0, 0), 0x2a, this->position, this->marker, chTwinkly_setUpMinigame, NULL); + fileProgressFlag_set(FILEPROG_82_MET_TWINKLIES, TRUE); } else{ - gcdialog_showDialog(0xc25, 0x2b, this->position, this->marker, chTwinkly_setUpMinigame, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C25_DIALOG_TWINKLIE_MINIGAME_RETRY, 0x99F, 0, 0), 0x2b, this->position, this->marker, chTwinkly_setUpMinigame, NULL); } subaddie_set_state(this, 5); this->pitch -= 3.0f; diff --git a/src/FP/ch/twinklybox.c b/src/FP/ch/twinklybox.c index 875777158..dc801194c 100644 --- a/src/FP/ch/twinklybox.c +++ b/src/FP/ch/twinklybox.c @@ -3,6 +3,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + extern void func_80324CD8(f32); extern Actor *actor_spawnWithYaw_f32(enum actor_e, f32[3], s32); @@ -178,7 +180,7 @@ void chTwinklyBox_destroyBox(ActorMarker *marker){ chTwinklyBox_destroyBoxDust(this->position, 12, ASSET_700_SPRITE_DUST); this->velocity[1] = 0.0f; sfx_playFadeShorthandDefault(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, 1000, 3500); - gcdialog_showDialog(0xc13, 0, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C13_DIALOG_TWINKLIE_MINIGAME_COMPLETE, 0x98D, 0, 0), 0, NULL, NULL, NULL, NULL); } void chTwinklyBox_openBox(Actor *this){ @@ -239,7 +241,8 @@ void chTwinklyBox_spawnTwinkly(ActorMarker *marker){ void chTwinklyBox_completeMinigame(ActorMarker *marker){ Actor *this = marker_getActor(marker); - + + port_fpTwinkly_release(); item_set(ITEM_6_HOURGLASS, false); fileProgressFlag_set(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME, true); FUNC_8030E624(SFX_416_ELECTRIC_ZAP, 0.8f, 32000); @@ -257,6 +260,10 @@ void chTwinklyBox_activateBox(ActorMarker *this_marker, ActorMarker *other_marke Actor *this = marker_getActor(this_marker); if(this->state == 1 || this->state == 2){ + // Anchor: only one client may run this minigame at a time — claim it or block if already held. + if(!EventSystem_Should(VB_FP_TWINKLY_START, true)){ + return; + } actor_collisionOff(this); timed_setStaticCameraToNode(0.0f, 0xa); func_80324CD8(0.1f); @@ -365,8 +372,8 @@ void chTwinklyBox_update(Actor *this){ func_8028F784(0); subaddie_set_state_with_direction(this, 4, 0.999f, 1); actor_playAnimationOnce(this); - item_set(ITEM_0_HOURGLASS_TIMER, 80*60 - 1); - item_set(ITEM_6_HOURGLASS, true); + item_set(ITEM_0_HOURGLASS_TIMER, 80*FRAMERATE - 1); + item_set(ITEM_6_HOURGLASS, TRUE); this->unk38_31 = 0xA; item_set(ITEM_24_TWINKLY_SCORE, this->unk38_31); __spawnQueue_add_1((GenFunction_1)chTwinklyBox_spawnSecondAndThirdMuncher, (uintptr_t)this->marker); @@ -394,6 +401,7 @@ void chTwinklyBox_update(Actor *this){ } if(item_empty(ITEM_6_HOURGLASS)){ + port_fpTwinkly_release(); subaddie_set_state_with_direction(this, 1, 0.001f, 0); actor_playAnimationOnce(this); this->unk38_31 = 0; diff --git a/src/FP/ch/twinklymuncher.c b/src/FP/ch/twinklymuncher.c index e35bf10db..1f80cfac3 100644 --- a/src/FP/ch/twinklymuncher.c +++ b/src/FP/ch/twinklymuncher.c @@ -128,7 +128,7 @@ void chTwinklyMuncher_update(Actor *this){ if(this->actorTypeSpecificField == 1 && !fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)){ if(this->state != 6 && this->state != 7 && 0.0f == this->velocity[0]){ timed_setStaticCameraToNode(0.5f, 0xd); - gcdialog_showDialog(ASSET_C15_DIALOG_TWINKLIE_MINIGAME_MISS, 0x2b, this->position, this->marker, chTwinklyMuncher_failMinigameExit, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C15_DIALOG_TWINKLIE_MINIGAME_MISS, 0x98F, 0, 0), 0x2b, this->position, this->marker, chTwinklyMuncher_failMinigameExit, NULL); this->velocity[0] = 1.0f; subaddie_set_state_with_direction(this, 6, 0.03f, 1); actor_loopAnimation(this); @@ -202,8 +202,8 @@ void chTwinklyMuncher_update(Actor *this){ sfx_playFadeShorthandDefault(SFX_27_JINJO_HI, 1.6f, 32000, this->position, 1250, 2500); func_80324D54(0.35f, SFX_110_TWINKLY_DEATH, 1.0f, 32000, this->position, 1250.0f, 2500.0f); marker_despawn(sp38->marker); - if( !mapSpecificFlags_get(0xa) && gcdialog_showDialog(0xc16, 0, NULL, NULL, NULL, NULL)){ - mapSpecificFlags_set(0xa, true); + if( !mapSpecificFlags_get(FP_SPECIFIC_FLAG_A_FIRST_TWINKLY_EATEN) && gcdialog_showDialog(VER_SELECT(ASSET_C16_DIALOG_TWINKLIE_MINIGAME_EATEN, 0x990, 0, 0), 0, NULL, NULL, NULL, NULL)){ + mapSpecificFlags_set(FP_SPECIFIC_FLAG_A_FIRST_TWINKLY_EATEN, TRUE); } } }//L8038E620 diff --git a/src/FP/ch/wozza.c b/src/FP/ch/wozza.c index fefe57902..69dc4fb98 100644 --- a/src/FP/ch/wozza.c +++ b/src/FP/ch/wozza.c @@ -70,11 +70,11 @@ void chWozza_enterCaveFinal(Actor *this){ void chWozza_textCallback(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this = marker_getActor(caller); switch(text_id){ - case 0xC1B: + case VER_SELECT(ASSET_C1B_DIALOG_WOZZA_MEET_AS_BEAR, 0x995, 0, 0): timed_exitStaticCamera(0.0f); break; - case 0xC1C: + case VER_SELECT(ASSET_C1C_DIALOG_WOZZA_MEET_AS_WALRUS, 0x996, 0, 0): timed_exitStaticCamera(0.0f); chWozza_enterCaveFinal(this); break; @@ -107,8 +107,8 @@ void chWozza_firstContact(Actor *this){ subaddie_set_state(this, 2); actor_loopAnimation(this); timed_setStaticCameraToNode(0.0f, 0x2e); - func_80324DBC(0.0f, 0xc1b, 0x2a, this->position, this->marker, chWozza_textCallback, NULL); - timedFunc_set_1(2.5f, (GenFunction_1)chWozza_delayedRetreatToCave, (uintptr_t)this->marker); + func_80324DBC(0.0f, VER_SELECT(ASSET_C1B_DIALOG_WOZZA_MEET_AS_BEAR, 0x995, 0, 0), 0x2a, this->position, this->marker, chWozza_textCallback, NULL); + timedFunc_set_1(2.5f, (GenFunction_1)chWozza_delayedRetreatToCave, reinterpret_cast(uintptr_t, this->marker)); } else{ chWozza_retreatToCave(this); @@ -274,8 +274,8 @@ void chWozza_update(Actor *this){ chWozza_checkForPlayer(this); if(!local->unk30){ - if(gcdialog_showDialog(0xc1d, 0x20, NULL, NULL, NULL, NULL)){ - local->unk30 = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_C1D_DIALOG_WOZZA_RETURN, 0x997, 0, 0), 0x20, NULL, NULL, NULL, NULL)){ + local->unk30 = TRUE; } } break; @@ -301,7 +301,7 @@ void chWozza_update(Actor *this){ } if(subaddie_playerIsWithinSphereAndActive(this, 500) && !this->has_met_before){ - if(gcdialog_showDialog(0xc1c, 0xAA, this->position, this->marker, chWozza_textCallback, chWozza_checkCompletion)){ + if(gcdialog_showDialog(VER_SELECT(ASSET_C1C_DIALOG_WOZZA_MEET_AS_WALRUS, 0x996, 0, 0), 0xAA, this->position, this->marker, chWozza_textCallback, chWozza_checkCompletion)){ timed_setStaticCameraToNode(0.0f, 0x2E); this->has_met_before = true; } diff --git a/src/FP/ch/xmastree.c b/src/FP/ch/xmastree.c index ea658f78c..f753e3c73 100644 --- a/src/FP/ch/xmastree.c +++ b/src/FP/ch/xmastree.c @@ -3,6 +3,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + Actor *chXmasTree_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chXmasTree_update(Actor *this); @@ -18,12 +20,12 @@ ActorInfo chXmasTree = { /* .code */ Actor *chXmasTree_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - func_8033A45C(5, this->unk38_31); - func_8033A45C(6, fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME) && !modelRender_func_8033A0F0(5)); + modelRender_setAppendageVisibility(5, this->unk38_31); + modelRender_setAppendageVisibility(6, fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME) && !modelRender_func_8033A0F0(5)); return actor_draw(marker, gfx, mtx, vtx); } -void __chXmasTree_free(Actor *this){ +void chXmasTree_free(Actor *this){ u8 tmp_a0; item_set(ITEM_6_HOURGLASS, false); @@ -34,30 +36,30 @@ void __chXmasTree_free(Actor *this){ } } -void __chXmasTree_80386EF4(Actor *this, int arg1){ +void chXmasTree_setState(Actor *this, int arg1){ this->unk38_31 = arg1; mapSpecificFlags_set(0, this->unk38_31); } -void __chXmasTree_80386F3C(void){ +void chXmasTree_swapCameraToIce(void){ levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); musicKeepsPlaying(); volatileFlag_set(VOLATILE_FLAG_E, 1); transitionToMap(MAP_53_FP_CHRISTMAS_TREE, WARP_FP_CHRISTMAS_TREE_1_ENTRANCE, 0); } -void __chXmasTree_80386F84(Actor * this){ +void chXmasTree_setLightsOn(Actor * this){ subaddie_set_state(this, 2); - __chXmasTree_80386EF4(this, 0); + chXmasTree_setState(this, 0); } -void __chXmasTree_spawnSwitch(void){ +void chXmasTree_spawnSwitch(void){ static s32 chXmasTree_switch_spawn_position[3] = {-0x1220, 0x6A, 0x1945}; actor_spawnWithYaw_s32(ACTOR_338_XMAS_TREE_SWITCH, &chXmasTree_switch_spawn_position, 350); } -void __chXmasTree_spawnStar(void *marker){ +void chXmasTree_spawnStar(void *marker){ Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, marker)); Actor *child = spawn_child_actor(0x339, &this); s32 pad; @@ -66,22 +68,22 @@ void __chXmasTree_spawnStar(void *marker){ child->position_z += 25.0f; } -void __chXmasTree_80387038(Actor *this){ +void chXmasTree_lightsDeactivatedSounds(Actor *this){ if(func_8030E3FC(this->unk44_31)) sfxSource_triggerCallbackByIndex(this->unk44_31); sfxsource_playSfxAtVolume(this->unk44_31, randf2(0.9f, 1.1f)); sfxSource_func_8030E2C4(this->unk44_31); } -void __chXmasTree_8038709C(Actor *this){ +void chXmasTree_setLightsOff(Actor *this){ if(this->state == 5){ if(!mapSpecificFlags_get(0)) - __chXmasTree_80387038(this); + chXmasTree_lightsDeactivatedSounds(this); return; } if(mapSpecificFlags_get(0) && !func_8030E3FC(this->unk44_31)) - __chXmasTree_80387038(this); + chXmasTree_lightsDeactivatedSounds(this); } void chXmasTree_update(Actor *this){ @@ -92,33 +94,43 @@ void chXmasTree_update(Actor *this){ this->volatile_initialized = true; this->marker->propPtr->unk8_3 = true; this->marker->collidable = false; - marker_setFreeMethod(this->marker, __chXmasTree_free); + marker_setFreeMethod(this->marker, chXmasTree_free); if(this->unk44_31 == 0){ this->unk44_31 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(this->unk44_31, SFX_415_XMAS_LIGHTS_FLICKERING); sfxSource_setunk43_7ByIndex(this->unk44_31, 3); sfxsource_setSampleRate(this->unk44_31, 28000); } - __spawnQueue_add_0(__chXmasTree_spawnSwitch); - __spawnQueue_add_1((GenFunction_1)__chXmasTree_spawnStar, (uintptr_t)this->marker); + __spawnQueue_add_0(chXmasTree_spawnSwitch); + __spawnQueue_add_1((GenFunction_1)chXmasTree_spawnStar, (uintptr_t)this->marker); if(fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)){ - __chXmasTree_80386F84(this); + chXmasTree_setLightsOn(this); mapSpecificFlags_set(2, false); } } this->depth_mode = 1; + // Anchor: teammate finished the star minigame — light the tree locally and stop our countdown if running. + if (!levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE) + && (port_puzzleStep_getForMap(MAP_53_FP_CHRISTMAS_TREE, ANCHOR_PUZZLE_FP_TREE_ICE) & 0x1)) { + levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); + if (this->state == 4) { + item_set(ITEM_6_HOURGLASS, false); + mapSpecificFlags_set(2, false); + } + } + if (jiggyscore_isCollected(JIGGY_2F_FP_XMAS_TREE) || levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { - __chXmasTree_80386EF4(this, 1); + chXmasTree_setState(this, 1); return; } switch(this->state){ case 1: // L80387268 - __chXmasTree_80386EF4(this, 0); + chXmasTree_setState(this, 0); if(fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)){ - __chXmasTree_80386F84(this); + chXmasTree_setLightsOn(this); } break; @@ -129,21 +141,21 @@ void chXmasTree_update(Actor *this){ this->lifetime_value = 2.0f; coMusicPlayer_playMusic(COMUSIC_61_XMAS_TREE_LIGHTS_UP, 28000); gcStaticCamera_activate(0x1A); - gcdialog_showDialog(0xC14, 0, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C14_DIALOG_TWINKLIE_MINIGAME_LIGHT_TREE, 0x98E, 0, 0), 0, NULL, NULL, NULL, NULL); break; case 3: // L803872F0 if(0.0 <= this->lifetime_value){ if( 1.8 < this->lifetime_value){ - __chXmasTree_80386EF4(this, 0); + chXmasTree_setState(this, 0); } else if(this->lifetime_value < 0.2){//L80387340 - __chXmasTree_80386EF4(this, 1); + chXmasTree_setState(this, 1); } else{ if(randf() < 0.2){ - __chXmasTree_80386EF4(this, this->unk38_31 ^ 1); - __chXmasTree_8038709C(this); + chXmasTree_setState(this, this->unk38_31 ^ 1); + chXmasTree_setLightsOff(this); } }//L803873AC this->lifetime_value -= sp2C; @@ -151,9 +163,9 @@ void chXmasTree_update(Actor *this){ else{//L803873BC if(func_802BB270()){ subaddie_set_state(this, 4); - __chXmasTree_80386EF4(this, 1); - item_set(ITEM_0_HOURGLASS_TIMER, 3600 - 1); - item_set(ITEM_6_HOURGLASS, true); + chXmasTree_setState(this, 1); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(3600, 3000, 0, 0) - 1); + item_set(ITEM_6_HOURGLASS, TRUE); } } @@ -162,7 +174,7 @@ void chXmasTree_update(Actor *this){ case 4: // L80387400 if(mapSpecificFlags_get(3)){ subaddie_set_state(this, 6); - __chXmasTree_80386EF4(this, 1); + chXmasTree_setState(this, 1); item_set(ITEM_6_HOURGLASS, false); tmp_a0 = this->unk44_31; if(tmp_a0){ @@ -170,7 +182,7 @@ void chXmasTree_update(Actor *this){ this->unk44_31 = 0; } func_80324E38(0.0f, 3); - timedFunc_set_0(0.5f, __chXmasTree_80386F3C); + timedFunc_set_0(0.5f, chXmasTree_swapCameraToIce); } else{//L80387470 if(item_empty(ITEM_6_HOURGLASS)){ @@ -191,21 +203,21 @@ void chXmasTree_update(Actor *this){ case 5: // L803874EC if(0.0 <= this->lifetime_value){ if( 1.8 < this->lifetime_value){ - __chXmasTree_80386EF4(this, 1); + chXmasTree_setState(this, 1); } else if(this->lifetime_value < 0.2){ - __chXmasTree_80386EF4(this, 0); + chXmasTree_setState(this, 0); } else{ if(randf() < 0.2){ - __chXmasTree_80386EF4(this, this->unk38_31 ^ 1); - __chXmasTree_8038709C(this); + chXmasTree_setState(this, this->unk38_31 ^ 1); + chXmasTree_setLightsOff(this); } } this->lifetime_value -= sp2C; } else{ - __chXmasTree_80386F84(this); + chXmasTree_setLightsOn(this); } break; } diff --git a/src/FP/ch/xmastreeice.c b/src/FP/ch/xmastreeice.c index beaaae180..aa3cc1e63 100644 --- a/src/FP/ch/xmastreeice.c +++ b/src/FP/ch/xmastreeice.c @@ -3,6 +3,12 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + +typedef struct { + u8 initShatter; // took the warped-in cutscene path at init; suppresses the live shatter +} ActorLocal_XmasTreeIce; + Actor *chXmasTreeIce_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chXmasTreeIce_update(Actor *this); @@ -68,6 +74,8 @@ void chXmasTreeIce_shatterIce(ActorMarker *marker){ func_8030E6D4(SFX_B6_GLASS_BREAKING_1); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); this->unk38_31 = 1; + // Anchor: broadcast the shatter; LEVEL_FLAG_29 stays local. + port_puzzleStep_orBits(ANCHOR_PUZZLE_FP_TREE_ICE, 0x1); } void chXmasTreeIce_returnCameraToBanjo(ActorMarker *marker){ @@ -85,6 +93,12 @@ void chXmasTreeIce_initiateShatter(Actor *this){ } void chXmasTreeIce_update(Actor *this) { + ActorLocal_XmasTreeIce *local = (ActorLocal_XmasTreeIce *)&this->local; + + if (!EventSystem_Should(VB_XMAS_TREE_ICE_UPDATE, true, this)) { + return; + } + this->marker->propPtr->unk8_3 = true; actor_collisionOff(this); @@ -94,8 +108,22 @@ void chXmasTreeIce_update(Actor *this) { if (jiggyscore_isCollected(JIGGY_2F_FP_XMAS_TREE)) { marker_despawn(this->marker); } + else if (port_puzzleStep_get(ANCHOR_PUZZLE_FP_TREE_ICE) & 0x1) { + if (!levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { + levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); + } + marker_despawn(this->marker); + } else if (levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { + local->initShatter = 1; chXmasTreeIce_initiateShatter(this); } } + else if (!local->initShatter && this->unk38_31 == 0 + && (port_puzzleStep_get(ANCHOR_PUZZLE_FP_TREE_ICE) & 0x1)) { + if (!levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { + levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); + } + chXmasTreeIce_shatterIce(this->marker); + } } diff --git a/src/FP/ch/xmastreestar.c b/src/FP/ch/xmastreestar.c index a9cc9cddf..a9b001885 100644 --- a/src/FP/ch/xmastreestar.c +++ b/src/FP/ch/xmastreestar.c @@ -27,8 +27,8 @@ f32 D_803935D0[3]; /* .code */ Actor *chXmasTreeStar_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C( 2, mapSpecificFlags_get(0)); - func_8033A45C( 1, mapSpecificFlags_get(0) ^ 1); + modelRender_setAppendageVisibility( 2, mapSpecificFlags_get(0)); + modelRender_setAppendageVisibility( 1, mapSpecificFlags_get(0) ^ 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/ch/xmastreeswitch.c b/src/FP/ch/xmastreeswitch.c index 066f0a56e..1bb552b91 100644 --- a/src/FP/ch/xmastreeswitch.c +++ b/src/FP/ch/xmastreeswitch.c @@ -22,8 +22,8 @@ ActorInfo D_80392420 = { 0x206, 0x338, 0x486, /* .code */ Actor *chXmasTreeSwitch_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C(1, 0); - func_8033A45C(2, 1); + modelRender_setAppendageVisibility(1, 0); + modelRender_setAppendageVisibility(2, 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/checksums.c b/src/FP/checksums.c new file mode 100644 index 000000000..b56783710 --- /dev/null +++ b/src/FP/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: FP/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsFP; diff --git a/src/FP/actor_spawninit.c b/src/FP/fpspawnqueue.c similarity index 99% rename from src/FP/actor_spawninit.c rename to src/FP/fpspawnqueue.c index 119c2a794..bf98e1dec 100644 --- a/src/FP/actor_spawninit.c +++ b/src/FP/fpspawnqueue.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_ABD0.c +// BanjoDecomp: FP/fpspawnqueue.c #include #include "core1/core1.h" #include "functions.h" @@ -213,7 +213,7 @@ void func_80391744(Actor *this, Actor* other){ f32 tmp_f0; sp24 = nodeprop_findByActorIdAndActorPosition(0x22A, this); - tmp_f0 = (f32)nodeprop_getYaw(sp24); + tmp_f0 = (f32)nodeProp_getYaw(sp24); other->yaw = tmp_f0; this->yaw = tmp_f0; ml_vec3f_yaw_rotate_copy(sp28, sp34, tmp_f0); diff --git a/src/FP/mapstate/slalom.c b/src/FP/ma/slalom.c similarity index 91% rename from src/FP/mapstate/slalom.c rename to src/FP/ma/slalom.c index 4f82d9f85..293d651c7 100644 --- a/src/FP/mapstate/slalom.c +++ b/src/FP/ma/slalom.c @@ -127,7 +127,7 @@ void __maSlalom_spawnGate(s32 indx, s32 arg1){ } void maSlalom_spawnGate(s32 indx, s32 arg1){ - __spawnQueue_add_2((void (*)(void))__maSlalom_spawnGate, indx, arg1); + __spawnQueue_add_2((GenFunction_2)__maSlalom_spawnGate, indx, arg1); } void __maSlalom_despawnGate(s32 indx){ @@ -250,23 +250,23 @@ void maSlalom_dialogCallback(ActorMarker *caller, enum asset_e text_id, s32 arg2 } switch(text_id){ - case 0xc04: //8038B318 + case VER_SELECT(ASSET_C04_DIALOG_BOGGY_SLED_WALRUS_MISS, 0x97E, 0, 0): //8038B318 __maSlalom_loseDialogCallback(); break; - case 0xc07: //8038B328 + case VER_SELECT(ASSET_C07_DIALOG_BOGGY_SLED_WALRUS_COMPLETE, 0x981, 0, 0): //8038B328 __maSlalom_winDialogCallback(JIGGY_30_FP_BOGGY_2); break; - case 0xc0b: //8038B338 + case VER_SELECT(ASSET_C0B_DIALOG_BOGGY_SLED_BEAR_MISS, 0x985, 0, 0): //8038B338 __maSlalom_loseDialogCallback(); break; - case 0xc0d: //8038B348 + case VER_SELECT(ASSET_C0D_DIALOG_BOGGY_SLED_BEAR_COMPLETE, 0x987, 0, 0): //8038B348 __maSlalom_winDialogCallback(JIGGY_2C_FP_BOGGY_3); break; - case 0xc10: //8038B358 + case VER_SELECT(ASSET_C10_DIALOG_BOGGY_SLED_EITHER_GIVE_UP, 0x98A, 0, 0): //8038B358 func_8038ABDC(); code_7060_setVoidOutLocation(gsworld_getMap(), 0x11); func_8028F66C(BS_INTR_2A); @@ -300,12 +300,12 @@ void maSlalom_lose(void){ if(!jiggyscore_isCollected(JIGGY_30_FP_BOGGY_2)){ timed_setStaticCameraToNode(0.0f, 1); timed_playSfx(1.0f, SFX_8C_BOGGY_WAHEY, 1.0f, 32000); - func_80324DBC(2.0f, 0xC04, 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, VER_SELECT(ASSET_C04_DIALOG_BOGGY_SLED_WALRUS_MISS, 0x97E, 0, 0), 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); }//L8038B4E0 else{ timed_setStaticCameraToNode(0.0f, 1); timed_playSfx(1.0f, SFX_8C_BOGGY_WAHEY, 1.0f, 32000); - func_80324DBC(2.0f, 0xC0b, 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, VER_SELECT(ASSET_C0B_DIALOG_BOGGY_SLED_BEAR_MISS, 0x985, 0, 0), 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); } } @@ -359,10 +359,10 @@ void maSlalom_update(void){ pntBoggy->unk38_31 = 2; timed_playSfx(1.0f, SFX_8D_BOGGY_OHWW, 1.0f, 32000); if(jiggyscore_isCollected(JIGGY_30_FP_BOGGY_2) || jiggyscore_isSpawned(JIGGY_30_FP_BOGGY_2)){ - func_80324DBC(2.0f, 0xc0d, 0x2a, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, VER_SELECT(ASSET_C0D_DIALOG_BOGGY_SLED_BEAR_COMPLETE, 0x987, 0, 0), 0x2a, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); } else{ - func_80324DBC(2.0f, 0xc07, 0x22, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, VER_SELECT(ASSET_C07_DIALOG_BOGGY_SLED_WALRUS_COMPLETE, 0x981, 0, 0), 0x22, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); } Me.state = MA_SLALOM_STATE_4_LOSE; break; @@ -539,7 +539,7 @@ void maSlalom_setBoggyGate(s32 gate_num){ FP_func_8038AB60(0); if(!player_isDead()){ func_8028F918(2); - gcdialog_showDialog(0xc10, 0x20, NULL, NULL, maSlalom_dialogCallback, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C10_DIALOG_BOGGY_SLED_EITHER_GIVE_UP, 0x98A, 0, 0), 0x20, NULL, NULL, maSlalom_dialogCallback, NULL); }//L8038BD40 Me.state = MA_SLALOM_STATE_4_LOSE; break; @@ -547,7 +547,7 @@ void maSlalom_setBoggyGate(s32 gate_num){ case 3: if(!Me.hasBeenThreeBehind && !player_isDead()){ Me.hasBeenThreeBehind = 1; - gcdialog_showDialog(0xc0f, 0x20, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C0F_DIALOG_BOGGY_SLED_EITHER_TAUNT_2, 0x989, 0, 0), 0x20, NULL, NULL, NULL, NULL); }//L8038BD94 func_8025AEA0(0x3a, 0x411aa); break; @@ -555,7 +555,7 @@ void maSlalom_setBoggyGate(s32 gate_num){ case 2: if(!Me.hasBeenTwoBehind && !player_isDead()){ Me.hasBeenTwoBehind = 1; - gcdialog_showDialog(0xc0e, 0x20, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_C0E_DIALOG_BOGGY_SLED_EITHER_TAUNT_1, 0x988, 0, 0), 0x20, NULL, NULL, NULL, NULL); }//L8038BDF0 func_8025AEA0(0x3a, 0x493e0); break; diff --git a/src/FP/mapstate/snowbutton.c b/src/FP/ma/snowbutton.c similarity index 100% rename from src/FP/mapstate/snowbutton.c rename to src/FP/ma/snowbutton.c diff --git a/src/FP/mapstate/snowy.c b/src/FP/ma/snowy.c similarity index 100% rename from src/FP/mapstate/snowy.c rename to src/FP/ma/snowy.c diff --git a/src/FP/ch/wozza_fire.c b/src/FP/wozza_fire.c similarity index 100% rename from src/FP/ch/wozza_fire.c rename to src/FP/wozza_fire.c diff --git a/src/GV/bss_pad.c b/src/GV/bss_pad.c deleted file mode 100644 index 4d37dc71d..000000000 --- a/src/GV/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_GV_D_80391A20[0x10]; diff --git a/src/GV/ch/cactus.c b/src/GV/cactus.c similarity index 100% rename from src/GV/ch/cactus.c rename to src/GV/cactus.c diff --git a/src/GV/ch/carpet1.c b/src/GV/carpet1.c similarity index 100% rename from src/GV/ch/carpet1.c rename to src/GV/carpet1.c diff --git a/src/GV/ch/carpet2.c b/src/GV/carpet2.c similarity index 90% rename from src/GV/ch/carpet2.c rename to src/GV/carpet2.c index 0ddd062c0..6634a0bfc 100644 --- a/src/GV/ch/carpet2.c +++ b/src/GV/carpet2.c @@ -74,7 +74,7 @@ void func_8038D47C(Actor *this){ player_getPosition(sp3C); if(player_movementGroup() == BSGROUP_0_NONE){ if( ml_vec3f_distance(sp3C, this->unk1C) < 100.0f || ml_vec3f_distance(sp3C, this->velocity) < 100.0f){ - if(gcdialog_showDialog(ASSET_A7B_DIALOG_JINXY_MEET, 0, NULL, NULL, NULL, NULL)){ + if(gcdialog_showDialog(VER_SELECT(ASSET_A7B_DIALOG_JINXY_MEET, 0x937, 0, 0), 0, NULL, NULL, NULL, NULL)){ mapSpecificFlags_set(0x14, 1); } } @@ -89,9 +89,11 @@ void func_8038D47C(Actor *this){ } else if(!mapSpecificFlags_get(0xF) && mapSpecificFlags_get(0) + mapSpecificFlags_get(1) == 2){ mapSpecificFlags_set(0xF, true); - func_8028F918(2); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_JINXY)){ + func_8028F918(2); + gcStaticCamera_activate(0); + } subaddie_set_state_forward(this, 3); - gcStaticCamera_activate(0); } break; case 2: //L8038D78C @@ -103,8 +105,8 @@ void func_8038D47C(Actor *this){ } if( actor_animationIsAt(this, 0.99f) ){ if(--this->unk38_31 == 0){ - gcdialog_showDialog(ASSET_A7C_DIALOG_JINXY_ONE_EGG, 4, NULL, NULL, NULL, NULL); - mapSpecificFlags_set(0x14, true); + gcdialog_showDialog(VER_SELECT(ASSET_A7C_DIALOG_JINXY_ONE_EGG, 0x938, 0, 0), 4, NULL, NULL, NULL, NULL); + mapSpecificFlags_set(0x14, TRUE); subaddie_set_state_forward(this, 1); } } diff --git a/src/GV/ch/ancientone.c b/src/GV/ch/ancientone.c index 6301e28b7..61fee9176 100644 --- a/src/GV/ch/ancientone.c +++ b/src/GV/ch/ancientone.c @@ -1,9 +1,10 @@ -// BanjoDecomp: CH/ancientone.c +// BanjoDecomp: GV/ch/ancientone.c #include #include "functions.h" #include "variables.h" extern void core1_7090_initSfxSource(s32, s32, s32, f32); +extern s32 port_anchor_isWorldSyncActive(void); typedef struct { f32 unk0[3]; @@ -96,7 +97,7 @@ void func_803867F4(void){ void func_80386850(ActorMarker *caller_marker, enum asset_e text_id, s32 arg2){ Actor *caller = marker_getActor(caller_marker); - if(text_id == 0xA80){ + if(text_id == VER_SELECT(0xA80, 0x93C, 0, 0)){ subaddie_set_state_with_direction(caller, 2, 0.0f, 1); actor_playAnimationOnce(caller); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7fff); @@ -120,20 +121,48 @@ void chAncientOne_update(Actor *this){ } } if(!this->initialized){ - if(D_80390C28[this->actorTypeSpecificField - 1]) + if(D_80390C28[this->actorTypeSpecificField - 1] == NULL){ + LOCAL_CH_ANCIENT_ONE(this)->unk1C = this->position_y; + this->position_y -= 1100.0f; + D_80390C28[this->actorTypeSpecificField - 1] = this->marker; + if(this->actorTypeSpecificField != 1){ + this->marker->propPtr->isNotFeatherEggOrNote = false; + } + this->marker->propPtr->unk8_3 = true; + actor_collisionOff(this); + func_80386620(this); + return; + } + // Anchor only. A statue that has not been drawn yet still has to run the + // body below so it can catch up to flags another client set. + if(!port_anchor_isWorldSyncActive()){ return; - - LOCAL_CH_ANCIENT_ONE(this)->unk1C = this->position_y; - this->position_y -= 1100.0f; - D_80390C28[this->actorTypeSpecificField - 1] = this->marker; - if(this->actorTypeSpecificField != 1){ - this->marker->propPtr->isNotFeatherEggOrNote = false; } - this->marker->propPtr->unk8_3 = true; - actor_collisionOff(this); - func_80386620(this); + { + s32 fc = 0, fi; + for(fi = 7; fi < 0xC && mapSpecificFlags_get(fi); fi++) fc++; + if(fc == 0){ + return; + } + } } - else{//L803869B4 + {//L803869B4 + if(jiggyscore_isSpawned(JIGGY_46_GV_ANCIENT_ONES)){ + marker_despawn(this->marker); + return; + } + // Anchor: ring order is randomized per-client; advance by synced-flag count. + if(port_anchor_isWorldSyncActive()){ + s32 fc = 0, fi; + for(fi = 7; fi < 0xC && mapSpecificFlags_get(fi); fi++) fc++; + if(this->state == 1 && this->actorTypeSpecificField <= fc){ + subaddie_set_state_with_direction(this, 2, 0.0f, 1); + actor_playAnimationOnce(this); + if(this->actorTypeSpecificField < 5 && D_80390C28[this->actorTypeSpecificField]){ + D_80390C28[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = true; + } + } + } switch(this->state){ case 1: //L803869E4 player_getPosition(sp44); @@ -150,16 +179,16 @@ void chAncientOne_update(Actor *this){ mapSpecificFlags_set(sp38, true); if(sp38== 0xB){ if(!jiggyscore_isCollected(JIGGY_46_GV_ANCIENT_ONES)){ - gcdialog_showDialog(ASSET_A80_DIALOG_ANCIENT_ONES_DONE, 0xE, NULL, this->marker, func_80386850, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A80_DIALOG_ANCIENT_ONES_DONE, 0x93C, 0, 0), 0xE, NULL, this->marker, func_80386850, NULL); } else{ - func_80386850(this->marker, 0xA80, -1); + func_80386850(this->marker, VER_SELECT(ASSET_A80_DIALOG_ANCIENT_ONES_DONE, 0x93C, 0, 0), -1); } }//L80386B98 else { if(sp38== 7){ if(!jiggyscore_isCollected(JIGGY_46_GV_ANCIENT_ONES)){ - gcdialog_showDialog(ASSET_A7F_DIALOG_ANCIENT_ONES_MEET, 0x4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A7F_DIALOG_ANCIENT_ONES_MEET, 0x93B, 0, 0), 0x4, NULL, NULL, NULL, NULL); } } @@ -225,8 +254,8 @@ Actor *chAncientOne_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **v s32 tmp_v0; sp58 = (this->state == 3) ? 0 : 1; - func_8033A45C(3, sp58); - func_8033A45C(4, sp58); + modelRender_setAppendageVisibility(3, sp58); + modelRender_setAppendageVisibility(4, sp58); actor_draw(this_marker, gfx, mtx, vtx); if( !this->initialized && this_marker->unk14_21){ vec3fArray_get_vec3i(func_80329934(), 5, sp4C); diff --git a/src/GV/ch/buriedpyramid.c b/src/GV/ch/buriedpyramid.c index 42f705b88..0d2634c79 100644 --- a/src/GV/ch/buriedpyramid.c +++ b/src/GV/ch/buriedpyramid.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/buriedpyramid.c +// BanjoDecomp: GV/ch/buriedpyramid.c #include #include "functions.h" #include "variables.h" @@ -67,6 +67,13 @@ void chBuriedPyramid_update(Actor *this){ __chBuriedPyramid_setState(this, 1); }//L8038FE48 + if(this->state == 1){ + s32 flagState = fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2); + if(flagState > local->raised_state){ + chBuriedPyramid_setRaisedAmount(this->marker, flagState); + } + } + if(this->state == 2){ local->transistion_timer += time_getDelta()/3.0f; if(1.0f < local->transistion_timer) diff --git a/src/GV/ch/egg_pot.c b/src/GV/ch/eggpot.c similarity index 95% rename from src/GV/ch/egg_pot.c rename to src/GV/ch/eggpot.c index 32ff46425..05cc9baea 100644 --- a/src/GV/ch/egg_pot.c +++ b/src/GV/ch/eggpot.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_3AA0.c +// BanjoDecomp: GV/ch/eggpot.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/gobi1.c b/src/GV/ch/gobi1.c index 8c8ddc4ff..fdcb99009 100644 --- a/src/GV/ch/gobi1.c +++ b/src/GV/ch/gobi1.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/gobi1.c +// BanjoDecomp: GV/ch/gobi1.c #include #include "functions.h" #include "variables.h" @@ -159,7 +159,7 @@ void chGobi1_update(Actor *this){ timed_playSfx(1.0f, SFX_84_GOBI_CRYING, 1.1f, 30000); timed_playSfx(2.0f, SFX_84_GOBI_CRYING, 1.3f, 30000); timed_playSfx(2.5f, SFX_74_WALKING_NOISE_5, 0.5f, 30000); - func_80324DBC(3.0f, ASSET_A74_DIALOG_GOBI_HELPED, 0x2a, this->position, NULL, NULL, NULL); + func_80324DBC(3.0f, VER_SELECT(ASSET_A74_DIALOG_GOBI_HELPED, 0x930, 0, 0), 0x2a, this->position, NULL, NULL, NULL); timed_playSfx(5.0f, SFX_2E_BIGBUTT_RUNNING, 1.0f, 20000); timed_playSfx(5.6f, SFX_2E_BIGBUTT_RUNNING, 1.0f, 20000); timed_playSfx(6.5f, SFX_2E_BIGBUTT_RUNNING, 1.0f, 20000); @@ -181,7 +181,7 @@ void chGobi1_update(Actor *this){ && subaddie_playerIsWithinSphereAndActive(this, 250) && !subaddie_playerIsWithinSphereAndActive(this, 80) && func_8028F2A0() - && gcdialog_showDialog(0xa73, 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(VER_SELECT(0xa73, 0x92F, 0, 0), 0, NULL, NULL, NULL, NULL) ){ this->has_met_before = true; } diff --git a/src/GV/ch/gobi2.c b/src/GV/ch/gobi2.c index 4f72f936c..ad0fc87a5 100644 --- a/src/GV/ch/gobi2.c +++ b/src/GV/ch/gobi2.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/gobi2.c +// BanjoDecomp: GV/ch/gobi2.c #include #include "functions.h" #include "variables.h" @@ -86,7 +86,7 @@ void chGobi2_setState(Actor *this, s32 next_state){ timed_playSfx(0.8f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(1.4f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(2.0f, SFX_4B_GULPING, 0.8f, 28000); - func_80324DBC(3.0f, ASSET_A72_DIALOG_TRUNKER_HELPED, 0x2A, D_80390CEC, this->marker, func_80387A2C, NULL); + func_80324DBC(3.0f, VER_SELECT(ASSET_A72_DIALOG_TRUNKER_HELPED, 0x92E, 0, 0), 0x2A, D_80390CEC, this->marker, func_80387A2C, NULL); }//L80387C94 if(next_state == 4){ @@ -204,8 +204,8 @@ void chGobi2_update(Actor *this){ if(!this->has_met_before){ if(subaddie_playerIsWithinSphereAndActive(this, 0xFA) && !subaddie_playerIsWithinSphereAndActive(this, 0x50)){ if(func_8028F2A0()){ - if(gcdialog_showDialog(ASSET_A75_DIALOG_GOBI2_MEET, 0, this->position, NULL, NULL, NULL)) - this->has_met_before = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_A75_DIALOG_GOBI2_MEET, 0x931, 0, 0), 0, this->position, NULL, NULL, NULL)) + this->has_met_before = TRUE; } } } diff --git a/src/GV/ch/gobi3.c b/src/GV/ch/gobi3.c index 98ab87eda..c82666e66 100644 --- a/src/GV/ch/gobi3.c +++ b/src/GV/ch/gobi3.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/gobi3.c +// BanjoDecomp: GV/ch/gobi3.c #include "functions.h" #include "variables.h" #include @@ -28,6 +28,7 @@ void __chGobi3_spawnHoneyComb(Actor *this){ bundle_setYaw(this->yaw); func_802CA1CC(HONEYCOMB_C_GV_GOBI_3); bundle_spawn_f32(BUNDLE_D__EMPTY_HONEYCOMB, sp18); + CALL_EVENT(OnHoneycombDropSpawn, HONEYCOMB_C_GV_GOBI_3, BUNDLE_D__EMPTY_HONEYCOMB, sp18[0], sp18[1], sp18[2]); } void __chGobi3_runaway(ActorMarker *caller, enum asset_e text_id, s32 arg2){ @@ -75,7 +76,7 @@ void chGobi3_setState(Actor *this, s32 next_state){ if(next_state == 5){ skeletalAnim_set(this->unk148, 0xd9, 0.5f, 4.0f); - gcdialog_showDialog(ASSET_A77_DIALOG_GOBI3_DONE, 0xe, this->position, this->marker, __chGobi3_runaway, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A77_DIALOG_GOBI3_DONE, 0x933, 0, 0), 0xe, this->position, this->marker, __chGobi3_runaway, NULL); } if(next_state == 4){ diff --git a/src/GV/ch/gobirock.c b/src/GV/ch/gobirock.c index 9875f57a3..29caebd52 100644 --- a/src/GV/ch/gobirock.c +++ b/src/GV/ch/gobirock.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/gobirock.c +// BanjoDecomp: GV/ch/gobirock.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/gobirope.c b/src/GV/ch/gobirope.c index 1c2b5cb71..e934d1f1d 100644 --- a/src/GV/ch/gobirope.c +++ b/src/GV/ch/gobirope.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/gobirope.c +// BanjoDecomp: GV/ch/gobirope.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/grabba.c b/src/GV/ch/grabba.c index 7f04ea682..c1886224b 100644 --- a/src/GV/ch/grabba.c +++ b/src/GV/ch/grabba.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_5570.c +// BanjoDecomp: GV/ch/grabba.c #include #include "functions.h" #include "variables.h" @@ -64,7 +64,7 @@ void func_8038BA08(Actor *this){ if(player_movementGroup() == BSGROUP_6_TURBO_TALON_TRAINERS) player_stateTimer_set(STATE_TIMER_3_TURBO_TALON, 0.0f); - gcdialog_showDialog(ASSET_A79_DIALOG_GRABBA_DEFEAT, 0xf, this->position, this->marker, func_8038B988, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A79_DIALOG_GRABBA_DEFEAT, 0x935, 0, 0), 0xf, this->position, this->marker, func_8038B988, NULL); comusic_8025AB44(COMUSIC_57_TURBO_TRAINERS, 7000, 700); } @@ -246,8 +246,8 @@ void chGrabba_update(Actor *this){ } else{ if(!this->has_met_before){ - if(gcdialog_showDialog(ASSET_A78_DIALOG_GRABBA_MEET, 0, NULL, NULL, NULL, NULL)){ - this->has_met_before = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_A78_DIALOG_GRABBA_MEET, 0x934, 0, 0), 0, NULL, NULL, NULL, NULL)){ + this->has_met_before = TRUE; } } } @@ -277,8 +277,8 @@ void chGrabba_update(Actor *this){ } if(!this->unk138_23){ - if(gcdialog_showDialog(ASSET_A7A_DIALOG_GRABBA_TOO_FAST, 0, NULL, NULL, NULL, NULL)){ - this->unk138_23 = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_A7A_DIALOG_GRABBA_TOO_FAST, 0x936, 0, 0), 0, NULL, NULL, NULL, NULL)){ + this->unk138_23 = TRUE; } } } diff --git a/src/GV/ch/histup.c b/src/GV/ch/histup.c index 4ca545240..34e9cda79 100644 --- a/src/GV/ch/histup.c +++ b/src/GV/ch/histup.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/histup.c +// BanjoDecomp: GV/ch/histup.c #include #include "functions.h" #include "variables.h" @@ -28,10 +28,10 @@ ActorInfo D_80391318 = { MARKER_AA_HISTUP, ACTOR_11C_HISTUP, ASSET_3DE_MODEL_HIS /* .bss */ extern struct { - s32 unk0; + s32 eggCount; s32 unk4; s32 unk8; -}GV_D_80391AB0; +} rubeeEggPot; /* .code */ int func_8038D920(Actor *this, f32 arg1){ @@ -76,19 +76,19 @@ void GV_func_8038DB0C(Actor *this){ } void func_8038DB4C(s32 arg0){ - GV_D_80391AB0.unk0 = arg0; + rubeeEggPot.eggCount = arg0; } void func_8038DB58(s32 arg0){ - GV_D_80391AB0.unk4 = arg0; + rubeeEggPot.unk4 = arg0; } s32 func_8038DB64(void){ - return GV_D_80391AB0.unk4; + return rubeeEggPot.unk4; } void func_8038DB70(void){ - GV_D_80391AB0.unk4++; + rubeeEggPot.unk4++; } @@ -115,7 +115,7 @@ void func_8038DBDC(Actor *this){ actor_collisionOff(this); subaddie_set_state_with_direction(this, 1, 0.99f, 0); anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); - GV_D_80391AB0.unk8 = 0; + rubeeEggPot.unk8 = 0; func_8038DB4C(0); this->unk1C[0] = 0.0f; }//L8038DC90 @@ -135,7 +135,7 @@ void func_8038DBDC(Actor *this){ case 2: //8038DD3C if(!(func_8038E178() < 5)){ func_8038DB88(this); - if(GV_D_80391AB0.unk8){ + if(rubeeEggPot.unk8){ subaddie_set_state_with_direction(this, 3, 0.99f, 0); anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); this->unk1C[0] = 0.0f; @@ -197,7 +197,7 @@ void func_8038DBDC(Actor *this){ anctrl_setDuration(this->anctrl, 1.6f); func_80386608(); func_8038DB4C(0); - GV_D_80391AB0.unk8 = false; + rubeeEggPot.unk8 = FALSE; func_8025A58C(-1, 0x190); func_8025A7DC(COMUSIC_27_GV_RUBEES_SONG); if(!this->unk44_31){ diff --git a/src/GV/ch/jinxy.c b/src/GV/ch/jinxy.c deleted file mode 100644 index 949f52e6a..000000000 --- a/src/GV/ch/jinxy.c +++ /dev/null @@ -1,158 +0,0 @@ -// BanjoDecomp: code_3D90.c -#include -#include "functions.h" -#include "variables.h" - -extern f32 mapModel_getFloorY(f32[3]); - -void func_8038A314(Actor *this); -void func_8038A31C(Actor *this); -Actor *func_8038A180(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); - -/* .data */ -ActorAnimationInfo D_80390FA0[] = { - {0, 0.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, -}; -ActorInfo D_80390FD0 = { MARKER_B0_MAGIC_CARPET_2, ACTOR_123_MAGIC_CARPET_2, ASSET_3DC_MODEL_MAGIC_CARPET, - 0x1, D_80390FA0, - func_8038A314, func_8038A31C, func_8038A180, - 0, 0, 0.0f, 0 -}; -u8 D_80390FF4[6] = {0,0,0,1,1,1}; - -/* .code */ -Actor *func_8038A180(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor * this = marker_getActor(this_marker); - - if(this->unk1C[0] != 0.0f){ - this = actor_draw(this_marker, gfx, mtx, vtx); - - if( this->unk54 == 0.0f - && this->unk48 != this->unk1C[1] - && this_marker->unk14_21 - && subaddie_playerIsWithinSphereAndActive(this, 3000) - ){ - commonParticle_add(this->marker, 6, func_80329904); - commonParticle_new(0xc, this->marker->unk14_21); - } - } - return this; -} - - -f32 func_8038A264(Actor *shadow, Actor* this){ - if(this && shadow){ - return ml_map_f(this->position_y - shadow->position_y, 0.0f, 2200.0f, 1.0f, 0.35f); - } - else{ - return 0.0; - } -} - -void func_8038A2C0(void *this_marker){ - Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, this_marker)); - Actor *shadow = spawn_child_actor(ACTOR_122_MAGIC_CARPET_SHADOW, &this); - s32 pad; - - suSetSpriteScale(shadow, this->scale); - this->partnerActor = shadow->marker; -} - -void func_8038A314(Actor *this){} - -void func_8038A31C(Actor *this){ - Actor *sp24; - if(!this->volatile_initialized){ - this->volatile_initialized = true; - actor_collisionOff(this); - __spawnQueue_add_1((GenFunction_1)func_8038A2C0, (uintptr_t)this->marker); - this->velocity[0] = 0.0f; - } - - if(this->partnerActor) - sp24 = subaddie_getLinkedActor(this); - - this->unk1C[1] = this->unk48; - ; - - switch(code7FF0_getMagicCarpetState(this, 3)) - { - case 1: //L8038A3C0 - func_80343DEC(this); - this->marker->propPtr->unk8_3 = true; - this->unk1C[0] = 1.0; - this->alpha_124_19 = 0xff; - if(this->unk54 != 0.0f){ - subaddie_set_state_with_direction(this, 2, 0.02f, 1); - anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); - } - break; - case 2: //L8038A440 - this->marker->propPtr->unk8_3 = true; - this->unk1C[0] = 1.0; - if(45.0f <= this->velocity[0]){ - subaddie_set_state_with_direction(this, 3, 0.02f, 1); - this->velocity[0] = 0.0f; - } - else{ - if(D_80390FF4[((s32)this->velocity[0])%6] == 0){ - this->alpha_124_19 -= 0x55; - } - else{ - this->alpha_124_19 += 0x55; - } - this->velocity[0] += 1.0f; - } - break; - case 3: //L8038A534 - func_80343DEC(this); - this->marker->propPtr->unk8_3 = false; - this->unk1C[0] = 0.0; - this->alpha_124_19 = 0; - if(this->unk54 == 0.0f){ - subaddie_set_state_with_direction(this, 4, 0.02f, 1); - } - break; - - case 4: //L8038A5A4 - this->marker->propPtr->unk8_3 = true; - this->unk1C[0] = 1.0; - if(45.0f <= this->velocity[0]){ - subaddie_set_state_with_direction(this, 1, 0.02f, 1); - anctrl_setPlaybackType(this->anctrl, ANIMCTRL_LOOP); - this->velocity[0] = 0.0f; - } - else{ - if(D_80390FF4[5 - ((s32)this->velocity[0])%6 ] != 0){ - this->alpha_124_19 += 0x55; - } - else{ - this->alpha_124_19 -= 0x55; - } - this->velocity[0] += 1.0f; - } - - break; - }//L8038A6A4 - this->unk124_11 = 0x3; - this->pitch = 0.0f; - if(this->partnerActor && sp24 && this->partnerActor->id == MARKER_AF_MAGIC_CARPET_SHADOW){ - sp24->position_x = this->position_x; - sp24->position_y = mapModel_getFloorY(this->position) + 60.0f; - sp24->position_z = this->position_z; - sp24->unk1C[0] = func_8038A264(sp24, this); - sp24->yaw = this->yaw; - sp24->velocity[0] = 1.0; - sp24->velocity[1] = this->alpha_124_19; - if (0.0f != this->unk1C[0]) - sp24->unk1C[2] = 1.0; - else - sp24->unk1C[2] = 0.0f; - - }//L8038A780 -} diff --git a/src/GV/mazectrl.c b/src/GV/ch/mazectrl.c similarity index 90% rename from src/GV/mazectrl.c rename to src/GV/ch/mazectrl.c index ffc5b2848..142e298a0 100644 --- a/src/GV/mazectrl.c +++ b/src/GV/ch/mazectrl.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/mazectrl.c +// BanjoDecomp: GV/ch/mazectrl.c #include #include "functions.h" #include "variables.h" @@ -67,8 +67,8 @@ void __chMazeCtrl_setState(Actor *this, s32 next_state){ if(next_state == 2){ func_8025A58C(0, 4000); coMusicPlayer_playMusic(COMUSIC_26_GV_SANDYBUTT_DANGER, 30000); - item_set(ITEM_0_HOURGLASS_TIMER, 0xdd3); - item_set(ITEM_6_HOURGLASS, true); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(0xdd3, 0xb85, 0, 0)); + item_set(ITEM_6_HOURGLASS, TRUE); func_8038F520(1.0f); FUNC_8030E624(SFX_3F6_RUBBING, 0.8f, 25000); FUNC_8030E624(SFX_3F6_RUBBING, 0.7f, 25000); @@ -86,8 +86,8 @@ void __chMazeCtrl_setState(Actor *this, s32 next_state){ } if (!levelSpecificFlags_get(LEVEL_FLAG_16_GV_UNKNOWN)) { - gcdialog_showDialog(ASSET_A82_DIALOG_SANDYBUTT_START_MAZE, 4, NULL, NULL, NULL, NULL); - levelSpecificFlags_set(LEVEL_FLAG_16_GV_UNKNOWN, true); + gcdialog_showDialog(VER_SELECT(ASSET_A82_DIALOG_SANDYBUTT_START_MAZE, 0x93E, 0, 0), 4, NULL, NULL, NULL, NULL); + levelSpecificFlags_set(LEVEL_FLAG_16_GV_UNKNOWN, TRUE); } }//L8038F794 @@ -136,8 +136,8 @@ void __chMazeCtrl_setState(Actor *this, s32 next_state){ coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7fff); if(!levelSpecificFlags_get(LEVEL_FLAG_17_GV_UNKNOWN)){ - gcdialog_showDialog(ASSET_A83_DIALOG_SANDYBUTT_DONE, 4, NULL, NULL, NULL, NULL); - levelSpecificFlags_set(LEVEL_FLAG_17_GV_UNKNOWN, true); + gcdialog_showDialog(VER_SELECT(ASSET_A83_DIALOG_SANDYBUTT_DONE, 0x93F, 0, 0), 4, NULL, NULL, NULL, NULL); + levelSpecificFlags_set(LEVEL_FLAG_17_GV_UNKNOWN, TRUE); } } @@ -179,7 +179,7 @@ void chMazeCtrl_update(Actor *this){ if (!levelSpecificFlags_get(LEVEL_FLAG_15_GV_UNKNOWN) && ml_timer_update(&local->unk8, sp34) - && gcdialog_showDialog(ASSET_A81_DIALOG_SANDYBUTT_ENTER, 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(VER_SELECT(ASSET_A81_DIALOG_SANDYBUTT_ENTER, 0x93D, 0, 0), 0, NULL, NULL, NULL, NULL) ) { levelSpecificFlags_set(LEVEL_FLAG_15_GV_UNKNOWN, true); } diff --git a/src/GV/ch/mummum.c b/src/GV/ch/mummum.c index 53c9a69ab..dbc6ad01b 100644 --- a/src/GV/ch/mummum.c +++ b/src/GV/ch/mummum.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (core2 origin, not from GV overlay) +// BanjoDecomp: core2/ch/mummum.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/sarcophagus.c b/src/GV/ch/sarcophagus.c index 260ffb7b4..bc20521ce 100644 --- a/src/GV/ch/sarcophagus.c +++ b/src/GV/ch/sarcophagus.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/sarcophagus.c +// BanjoDecomp: GV/ch/sarcophagus.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/slappa.c b/src/GV/ch/slappa.c index e1423e092..5d8f275ce 100644 --- a/src/GV/ch/slappa.c +++ b/src/GV/ch/slappa.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_4740.c +// BanjoDecomp: GV/ch/slappa.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/toots.c b/src/GV/ch/toots.c index bf84aa0dd..edeb96f8e 100644 --- a/src/GV/ch/toots.c +++ b/src/GV/ch/toots.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/toots.c +// BanjoDecomp: GV/ch/toots.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/trunker.c b/src/GV/ch/trunker.c index d4a4b4958..93e013092 100644 --- a/src/GV/ch/trunker.c +++ b/src/GV/ch/trunker.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CH/trunker.c +// BanjoDecomp: GV/ch/trunker.c #include #include "functions.h" #include "variables.h" @@ -75,8 +75,8 @@ void chTrunker_update(Actor *this){ && !subaddie_playerIsWithinSphereAndActive(this, 80) && func_8028F2A0() ){ - gcdialog_showDialog(ASSET_A71_DIALOG_TRUNKER_MEET, 0xe, this->position, NULL, NULL, NULL); - this->has_met_before = true; + gcdialog_showDialog(VER_SELECT(ASSET_A71_DIALOG_TRUNKER_MEET, 0x92D, 0, 0), 0xe, this->position, NULL, NULL, NULL); + this->has_met_before = TRUE; }//L80389254 if(this->state == 1 && mapSpecificFlags_get(0xC)){ diff --git a/src/GV/checksums.c b/src/GV/checksums.c new file mode 100644 index 000000000..a89de711c --- /dev/null +++ b/src/GV/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: GV/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsGV; diff --git a/src/GV/crc.c b/src/GV/crc.c index 22cff99bb..8ace3ef7a 100644 --- a/src/GV/crc.c +++ b/src/GV/crc.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_3B10.c +// BanjoDecomp: GV/crc.c #include #include "functions.h" #include "variables.h" @@ -7,11 +7,9 @@ extern void player_stateTimer_set(s32, f32); extern f32 player_stateTimer_get(enum state_timer_e); -/* .data */ -//TODO Implement CRC calculation in Makefile(?) -u32 D_80390F30 = 0x00274530; //GV.code CRC1 -u32 D_80390F34 = 0xAA18BBF3; //GV.code CRC2 -u32 D_80390F38 = 0x0003031C; //GV.data CRC1 (with this value = 0) +s32 D_80390F30 = VER_SELECT(0x00274530, 0x002764CA, 0, 0); // GV_TEXT_CRC1 +s32 D_80390F34 = VER_SELECT(0xAA18BBF3, 0xFB1E80F4, 0, 0); // GV_TEXT_CRC2 +s32 D_80390F38 = VER_SELECT(0x0003031C, 0x00031973, 0, 0); // GV_DATA_CRC1 /* .code */ diff --git a/src/GV/gv_helpers.c b/src/GV/gv_helpers.c index fed404bb2..0c40a25a4 100644 --- a/src/GV/gv_helpers.c +++ b/src/GV/gv_helpers.c @@ -4,25 +4,25 @@ #include "variables.h" struct { - s32 unk0; + s32 eggCount; s32 unk4; s32 unk8; -}GV_D_80391AB0; +} rubeeEggPot; /* .code */ -void func_8038E140(void){ - GV_D_80391AB0.unk0++; +void rubeeEggPot_addedEggToPot(void){ + rubeeEggPot.eggCount++; coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 26000); } s32 func_8038E178(void){ - return GV_D_80391AB0.unk0; + return rubeeEggPot.eggCount; } -s32 func_8038E184(void){ +s32 rubeeEggPot_getEggGoal(void){ return 5; } void func_8038E18C(void){ - GV_D_80391AB0.unk8 = true; + rubeeEggPot.unk8 = TRUE; } diff --git a/src/GV/actor_spawninit.c b/src/GV/gvspawnqueue.c similarity index 84% rename from src/GV/actor_spawninit.c rename to src/GV/gvspawnqueue.c index f96c415f9..0b01ec333 100644 --- a/src/GV/actor_spawninit.c +++ b/src/GV/gvspawnqueue.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_7FF0.c +// BanjoDecomp: GV/gvspawnqueue.c #include #include "core1/core1.h" #include "functions.h" @@ -7,8 +7,10 @@ #include +#include "port/Patches/Patches.h" + extern void core1_7090_initSfxSource(s32, s32, s32, f32); -extern void func_802D3D54(Actor *this); +extern void chMMMBreakableWooden_update(Actor *this); extern void func_802D3D74(Actor *this); extern Actor *func_80325F2C(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); extern void func_8032BC3C(Actor *, f32); @@ -22,20 +24,20 @@ extern ActorInfo chGobiRock; extern ActorInfo chGobi2; extern ActorInfo chGobi3; extern ActorInfo chTrunker; -extern ActorInfo GV_D_80390DD0; +extern ActorInfo chMagicCarpetShadow; extern ActorInfo chSarcophagus; extern ActorInfo chSNSSarcophagus; -extern ActorInfo D_80390ED0; +extern ActorInfo chRubee; extern ActorInfo D_80390F00; -extern ActorInfo D_80390FD0; +extern ActorInfo chMagicCarpet2; extern ActorInfo D_80391010; extern ActorInfo chSlappa; extern ActorInfo chGrabba; extern ActorInfo D_803911C0; -extern ActorInfo D_803911F4; -extern ActorInfo D_80391218; -extern ActorInfo D_8039123C; -extern ActorInfo D_80391260; +extern ActorInfo chJinxyHeadSandybutt1; +extern ActorInfo chJinxyHeadSandybutt2; +extern ActorInfo chJinxyHeadSandybutt3; +extern ActorInfo chSandybuttEggToll; extern ActorInfo D_80391318; extern ActorInfo D_80391358; extern ActorInfo D_803912B8; @@ -109,13 +111,13 @@ ActorInfo D_80391494 = { MARKER_23C_GV_SNS_SWITCH, ACTOR_245_GV_SNS_SWITCH, ASSE ActorInfo D_803914B8 = { MARKER_EB_GV_BANJO_DOOR, ACTOR_6D_GV_BANJO_DOOR, ASSET_3D8_MODEL_GV_BANJO_DOOR, 0x1, 0x0, - func_802D3D54, func_8038E460, func_80325F2C, + chMMMBreakableWooden_update, func_8038E460, func_80325F2C, 0, 0, 0.0f, 0 }; ActorInfo D_803914DC = { MARKER_ED_GV_SUN_DOOR, ACTOR_140_GV_SUN_DOOR, ASSET_3FF_MODEL_GV_SUN_DOOR, 0x1, 0x0, - func_802D3D54, func_8038E4DC, func_80325F2C, + chMMMBreakableWooden_update, func_8038E4DC, func_80325F2C, 0, 0, 0.0f, 0 }; @@ -175,12 +177,23 @@ void func_8038E430(Actor *this){ void func_8038E460(Actor *this){//banjo_door func_802D3D74(this); + // Anchor: flag 0x10 is transient, doesn't survive reload. + if(mapSpecificFlags_get(0x10)){ + if(!(port_puzzleStep_get(ANCHOR_PUZZLE_GV_JINXY_DOOR) & 1)){ + port_puzzleStep_orBits(ANCHOR_PUZZLE_GV_JINXY_DOOR, 1); + } + } else if(port_puzzleStep_get(ANCHOR_PUZZLE_GV_JINXY_DOOR) & 1){ + mapSpecificFlags_set(0x10, true); + mapSpecificFlags_set(2, true); + } if(mapSpecificFlags_get(0x10)){ func_8038E430(this); if(!mapSpecificFlags_get(2)){ mapSpecificFlags_set(2, true); - func_8028F918(0); - func_80324DBC(4.0f, ASSET_A7D_DIALOG_JINXY_HELPED, 4, NULL, NULL, NULL, NULL); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_JINXY)){ + func_8028F918(0); + func_80324DBC(4.0f, VER_SELECT(ASSET_A7D_DIALOG_JINXY_HELPED, 0x939, 0, 0), 4, NULL, NULL, NULL, NULL); + } } } } @@ -218,7 +231,8 @@ void func_8038E4DC(Actor *this){ else{ if(!mapSpecificFlags_get(4)){ mapSpecificFlags_set(4, true); - gcStaticCamera_activate(1); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_SUN)) + gcStaticCamera_activate(1); } } } @@ -231,13 +245,14 @@ void func_8038E648(Actor *this){ case 1: //L8038E690 this->pitch = 0.0f; if(mapSpecificFlags_get(5)){ - gcStaticCamera_activate(2); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_STAR)) + gcStaticCamera_activate(2); subaddie_set_state(this, 6); core1_7090_initSfxSource(0, 0x6A, 0x7ff8, 0.3f); s32 pyramidTimer = 25; CALL_EVENT(OnWaterPyramidTimer, &pyramidTimer); // [port] may extend timer this->unk38_31 = pyramidTimer * 24; // [port] door duration derived from HUD timer (vanilla ratio 600:25) - func_802D68F0(pyramidTimer); + code_4C020_setHourglassTimer(pyramidTimer); item_set(ITEM_6_HOURGLASS, 1); } break; @@ -247,7 +262,7 @@ void func_8038E648(Actor *this){ if(90.0f <= this->pitch){ subaddie_set_state(this, 7); this->pitch = 90.0f; - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); core1_7090_freeSfxSource(0); } break; @@ -265,10 +280,10 @@ void func_8038E648(Actor *this){ if(this->pitch <= 0.0f){ subaddie_set_state(this, 1); this->pitch = 0.0f; - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); mapSpecificFlags_set(5, false); core1_7090_freeSfxSource(0); - volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED); + progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED); } break; }//L8038E904: @@ -320,7 +335,7 @@ void func_8038E97C(Actor *this){ if(this->unk38_31 == 0){ subaddie_set_state(this, 1); core1_7090_freeSfxSource(1); - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); } } @@ -333,7 +348,8 @@ void chKazooieDoor_update(Actor *this){ case 1: //L8038EB98 if(mapSpecificFlags_get(6)){ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, -1); - gcStaticCamera_activate(3); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_KAZOOIE)) + gcStaticCamera_activate(3); subaddie_set_state(this, 6); core1_7090_initSfxSource(1, 0x6a, 0x7ff8, 0.3f); this->unk1C[1] = this->position_y + 210.0f; @@ -346,7 +362,7 @@ void chKazooieDoor_update(Actor *this){ this->position_z -= 1.3319999999999999; if(this->unk1C[1] <= this->position_y){ subaddie_set_state(this, 7); - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); core1_7090_freeSfxSource(1); this->unk38_31 = 450; } @@ -366,7 +382,7 @@ void chKazooieDoor_update(Actor *this){ if(this->position_y <= this->unk1C[0]){ this->position_y = this->unk1C[0]; subaddie_set_state(this, 1); - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); core1_7090_freeSfxSource(1); mapSpecificFlags_set(6, false); } @@ -383,7 +399,7 @@ void chSunSwitch_update(Actor *this){ && func_802BB270() ){ this->velocity_x = 1.0f; - func_802D68F0(10); + code_4C020_setHourglassTimer(10); item_set(ITEM_6_HOURGLASS, 1); }//L8038EDC8 @@ -428,7 +444,7 @@ void chKazooieTarget_update(Actor *this){ && func_802BB270() ){ this->velocity_x = 1.0f; - func_802D68F0(0x15); + code_4C020_setHourglassTimer(0x15); item_set(ITEM_6_HOURGLASS, 1); }//L8038EDC8 @@ -480,20 +496,20 @@ void GV_func_8038F154(void) spawnableActorList_add(&chGobi2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); spawnableActorList_add(&chGobi3, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); spawnableActorList_add(&chTrunker, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&GV_D_80390DD0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chMagicCarpetShadow, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_14); spawnableActorList_add(&chSarcophagus, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10); spawnableActorList_add(&chSNSSarcophagus, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6); - spawnableActorList_add(&D_80390ED0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); + spawnableActorList_add(&chRubee, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&D_80390F00, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390FD0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chMagicCarpet2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_14); spawnableActorList_add(&D_80391010, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_14); spawnableActorList_add(&chSlappa, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_16); spawnableActorList_add(&chGrabba, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6); spawnableActorList_add(&D_803911C0, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&D_803911F4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_80391218, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_8039123C, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&D_80391260, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chJinxyHeadSandybutt1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chJinxyHeadSandybutt2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chJinxyHeadSandybutt3, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chSandybuttEggToll, actor_new, ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&D_80391318, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10); spawnableActorList_add(&D_80391358, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_4 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10); // Big Jinxy Head ? spawnableActorList_add(&D_803912B8, actor_new, ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10); diff --git a/src/GV/ch/handshadow.c b/src/GV/handshadow.c similarity index 100% rename from src/GV/ch/handshadow.c rename to src/GV/handshadow.c diff --git a/src/GV/ch/jinxy_head.c b/src/GV/jinxy_head.c similarity index 100% rename from src/GV/ch/jinxy_head.c rename to src/GV/jinxy_head.c diff --git a/src/GV/magiccarpet2.c b/src/GV/magiccarpet2.c new file mode 100644 index 000000000..bbe7a21b2 --- /dev/null +++ b/src/GV/magiccarpet2.c @@ -0,0 +1,171 @@ +// BanjoDecomp: GV/magiccarpet2.c +#include +#include "functions.h" +#include "variables.h" + +extern f32 mapModel_getFloorY(f32[3]); + +// [port] func_80329904 is declared in functions.h with its real signature. +// void func_80329904(ActorMarker *, s32, void *); + +void chmagiccarpet2_emptyupdate(Actor *this); +void chmagiccarpet2_update(Actor *this); +Actor *chmagiccarpet2_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); + +/* .data */ +ActorAnimationInfo chMagicCarpet2Animations[] = { + {0, 0.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, +}; + +ActorInfo chMagicCarpet2 = { + MARKER_B0_MAGIC_CARPET_2, ACTOR_123_MAGIC_CARPET_2, ASSET_3DC_MODEL_MAGIC_CARPET, + 0x1, chMagicCarpet2Animations, + chmagiccarpet2_emptyupdate, chmagiccarpet2_update, chmagiccarpet2_draw, + 0, 0, 0.0f, 0 +}; + +u8 D_80390FF4[6] = {0, 0, 0, 1, 1, 1}; + +enum chmagicarpet2_state_e { + CHMAGICCARPET2_STATE_0_NOT_INIT, + CHMAGICCARPET2_STATE_1_UNK, + CHMAGICCARPET2_STATE_2_UNK, + CHMAGICCARPET2_STATE_3_UNK, + CHMAGICCARPET2_STATE_4_UNK +}; + +/* .code */ +Actor *chmagiccarpet2_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor * this = marker_getActor(this_marker); + + if(this->unk1C[0] != 0.0f){ + this = actor_draw(this_marker, gfx, mtx, vtx); + + if( this->unk54 == 0.0f + && this->unk48 != this->unk1C[1] + && this_marker->unk14_21 + && subaddie_playerIsWithinSphereAndActive(this, 3000) + ){ + commonParticle_add(this->marker, 6, func_80329904); + commonParticle_new(0xc, this->marker->unk14_21); + } + } + return this; +} + + +f32 func_8038A264(Actor *shadow, Actor* this){ + if(this && shadow){ + return ml_map_f(this->position_y - shadow->position_y, 0.0f, 2200.0f, 1.0f, 0.35f); + } + else{ + return 0.0; + } +} + +void func_8038A2C0(void *this_marker){ + Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, this_marker)); + Actor *shadow = spawn_child_actor(ACTOR_122_MAGIC_CARPET_SHADOW, &this); + s32 pad; + + suSetSpriteScale(shadow, this->scale); + this->partnerActor = shadow->marker; +} + +void chmagiccarpet2_emptyupdate(Actor *this){} + +void chmagiccarpet2_update(Actor *this){ + Actor *sp24; + + if(!this->volatile_initialized){ + this->volatile_initialized = TRUE; + actor_collisionOff(this); + __spawnQueue_add_1((GenFunction_1)func_8038A2C0, reinterpret_cast(uintptr_t, this->marker)); + this->velocity[0] = 0.0f; + } + + if(this->partnerActor) + sp24 = subaddie_getLinkedActor(this); + + this->unk1C[1] = this->unk48; + + switch(code7FF0_getMagicCarpetState(this, CHMAGICCARPET2_STATE_3_UNK)) + { + case CHMAGICCARPET2_STATE_1_UNK: //L8038A3C0 + func_80343DEC(this); + this->marker->propPtr->unk8_3 = TRUE; + this->unk1C[0] = 1.0; + this->alpha_124_19 = 0xff; + if(this->unk54 != 0.0f){ + subaddie_set_state_with_direction(this, 2, 0.02f, 1); + anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); + } + break; + case CHMAGICCARPET2_STATE_2_UNK: //L8038A440 + this->marker->propPtr->unk8_3 = TRUE; + this->unk1C[0] = 1.0; + if(45.0f <= this->velocity[0]){ + subaddie_set_state_with_direction(this, 3, 0.02f, 1); + this->velocity[0] = 0.0f; + } + else{ + if(D_80390FF4[((s32)this->velocity[0]) % 6] == 0){ + this->alpha_124_19 -= 0x55; + } + else{ + this->alpha_124_19 += 0x55; + } + this->velocity[0] += 1.0f; + } + break; + case CHMAGICCARPET2_STATE_3_UNK: //L8038A534 + func_80343DEC(this); + this->marker->propPtr->unk8_3 = FALSE; + this->unk1C[0] = 0.0; + this->alpha_124_19 = 0; + if(this->unk54 == 0.0f){ + subaddie_set_state_with_direction(this, 4, 0.02f, 1); + } + break; + + case CHMAGICCARPET2_STATE_4_UNK: //L8038A5A4 + this->marker->propPtr->unk8_3 = TRUE; + this->unk1C[0] = 1.0; + if(45.0f <= this->velocity[0]){ + subaddie_set_state_with_direction(this, 1, 0.02f, 1); + anctrl_setPlaybackType(this->anctrl, ANIMCTRL_LOOP); + this->velocity[0] = 0.0f; + } + else { + if(D_80390FF4[5 - ((s32)this->velocity[0])%6 ] != 0){ + this->alpha_124_19 += 0x55; + } + else{ + this->alpha_124_19 -= 0x55; + } + this->velocity[0] += 1.0f; + } + break; + }//L8038A6A4 + this->unk124_11 = 0x3; + this->pitch = 0.0f; + if(this->partnerActor && sp24 && this->partnerActor->id == MARKER_AF_MAGIC_CARPET_SHADOW){ + sp24->position_x = this->position_x; + sp24->position_y = mapModel_getFloorY(this->position) + 60.0f; + sp24->position_z = this->position_z; + sp24->unk1C[0] = func_8038A264(sp24, this); + sp24->yaw = this->yaw; + sp24->velocity[0] = 1.0; + sp24->velocity[1] = this->alpha_124_19; + if (0.0f != this->unk1C[0]) + sp24->unk1C[2] = 1.0; + else + sp24->unk1C[2] = 0.0f; + + }//L8038A780 +} diff --git a/src/GV/ch/carpet_shadow.c b/src/GV/magiccarpetshadow.c similarity index 61% rename from src/GV/ch/carpet_shadow.c rename to src/GV/magiccarpetshadow.c index b3fc76eb2..68429daac 100644 --- a/src/GV/ch/carpet_shadow.c +++ b/src/GV/magiccarpetshadow.c @@ -1,25 +1,26 @@ -// BanjoDecomp: code_2EE0.c +// BanjoDecomp: GV/magiccarpetshadow.c #include #include "functions.h" #include "variables.h" -void func_8038938C(Actor *this); -Actor *func_803892D0(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chMagicCarpetShadow_update(Actor *this); +Actor *chMagicCarpetShadow_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); /* .data */ -extern ActorAnimationInfo D_80390DC0[]={ +extern ActorAnimationInfo chMagicCarpetShadowAnimations[] = { {0, 0.0f}, {ASSET_F1_ANIM_MAGIC_CARPET, 2.0f} }; -extern ActorInfo GV_D_80390DD0 = { MARKER_AF_MAGIC_CARPET_SHADOW, ACTOR_122_MAGIC_CARPET_SHADOW, ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW, - 0x1, D_80390DC0, - func_8038938C, actor_update_func_80326224, func_803892D0, +extern ActorInfo chMagicCarpetShadow = { + MARKER_AF_MAGIC_CARPET_SHADOW, ACTOR_122_MAGIC_CARPET_SHADOW, ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW, + 0x1, chMagicCarpetShadowAnimations, + chMagicCarpetShadow_update, actor_update_func_80326224, chMagicCarpetShadow_draw, 2500, 0, 0.0f, 0 }; /* .code */ -Actor *func_803892D0(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *chMagicCarpetShadow_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ f32 rotation[3]; f32 position[3]; Actor *this; @@ -36,7 +37,7 @@ Actor *func_803892D0(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ return this; } -void func_8038938C(Actor *this){ +void chMagicCarpetShadow_update(Actor *this){ if(!this->initialized){ this->initialized = true; this->unk124_11 = 3; diff --git a/src/GV/matchinggame.c b/src/GV/matchinggame.c index fea1e578d..dc36b94f5 100644 --- a/src/GV/matchinggame.c +++ b/src/GV/matchinggame.c @@ -71,9 +71,9 @@ void __matchingGame_setState(s32 next_state){ if(next_state == 2){ item_set(ITEM_6_HOURGLASS, 1); if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) - item_set(ITEM_0_HOURGLASS_TIMER, 4499); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(4499, 0xea5, 0, 0)); else - item_set(ITEM_0_HOURGLASS_TIMER, 5999); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(5999, 0x1387, 0, 0)); } if(matchingGame.state == 2){ item_set(ITEM_6_HOURGLASS, 0); @@ -157,7 +157,7 @@ void gv_matchingGame_update(void){ } if(matchingGame.tile_a == NULL || matchingGame.tile_b == NULL){ - if( player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER && func_8028F20C()){ + if( player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER && player_isStableWithExtraSteps()){ player_getPosition(player_position); sp4C = model_func_8033F3E8(mapModel_getModel(0), player_position, 0x190, 0x1a0); if(sp4C){ diff --git a/src/GV/pyramid_raise.c b/src/GV/pyramid_raise.c index 355f171b7..c92504b67 100644 --- a/src/GV/pyramid_raise.c +++ b/src/GV/pyramid_raise.c @@ -17,32 +17,49 @@ typedef struct { f32 unk24; }ActorLocal_GV_6370; -void func_8038C8A0(Actor *this, s32 next_state); -void func_8038CC98(Actor *this); -Actor *func_8038CC40(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state); +void chJinxyHeadSandybutt_update(Actor *this); +Actor *chJinxyHeadSandybutt_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); /* .data */ -u8 D_803911F0[3] = {0, 1, 2}; -ActorInfo D_803911F4 = { 0xBB, 0x285, 0x3E6, +u8 chJinxyHeadSandybuttIndices[3] = {0, 1, 2}; + +// Jinxy Head 2 +ActorInfo chJinxyHeadSandybutt1 = { + MARKER_BB_JINXY_HEAD_SANDYBUTT, ACTOR_285_JINXY_HEAD_SANDYBUTT_1, ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, 0, NULL, - func_8038CC98, actor_update_func_80326224, func_8038CC40, + chJinxyHeadSandybutt_update, actor_update_func_80326224, chJinxyHeadSandybutt_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80391218 = { 0xBB, 0x286, 0x3E6, +ActorInfo chJinxyHeadSandybutt2 = { + MARKER_BB_JINXY_HEAD_SANDYBUTT, ACTOR_286_JINXY_HEAD_SANDYBUTT_2, ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, 0, NULL, - func_8038CC98, actor_update_func_80326224, func_8038CC40, + chJinxyHeadSandybutt_update, actor_update_func_80326224, chJinxyHeadSandybutt_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_8039123C = { 0xBB, 0x287, 0x3E6, +ActorInfo chJinxyHeadSandybutt3 = { + MARKER_BB_JINXY_HEAD_SANDYBUTT, ACTOR_287_JINXY_HEAD_SANDYBUTT_3, ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, 0, NULL, - func_8038CC98, actor_update_func_80326224, func_8038CC40, + chJinxyHeadSandybutt_update, actor_update_func_80326224, chJinxyHeadSandybutt_draw, 0, 0, 0.0f, 0 }; +enum chjinxyheadsandybutt_state_e { + CHJINXYHEADSANDYBUTT_STATE_0_NOT_INIT, + CHJINXYHEADSANDYBUTT_STATE_1_UNK, + CHJINXYHEADSANDYBUTT_STATE_2_UNK, + CHJINXYHEADSANDYBUTT_STATE_3_UNK, + CHJINXYHEADSANDYBUTT_STATE_4_UNK, + CHJINXYHEADSANDYBUTT_STATE_5_UNK, + CHJINXYHEADSANDYBUTT_STATE_6_FED, + CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY, + CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED +}; + /* .code */ -void func_8038C760(Actor *this, s32 arg1){ +void chJinxyHeadSandybutt_raisePyramid(Actor *this, s32 arg1){ ActorLocal_GV_6370 *local = (ActorLocal_GV_6370 *)&this->local; chBuriedPyramid_setRaisedAmount(local->unk14, arg1); FUNC_8030E624(SFX_3F6_RUBBING, 0.7f, 28000); @@ -63,21 +80,26 @@ void func_8038C760(Actor *this, s32 arg1){ } } -void func_8038C880(Actor *this){ - func_8038C8A0(this, 0); +void chJinxyHeadSandybutt_free(Actor *this){ + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_0_NOT_INIT); } -void func_8038C8A0(Actor *this, s32 next_state){ +void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state){ ActorLocal_GV_6370 *local = (ActorLocal_GV_6370 *)&this->local; local->unk0 = 0; local->unk24 = 0.0f; - this->marker->propPtr->unk8_3 = (next_state == 1) ? false : true; - this->marker->collidable = (next_state == 1) ? false : true; - if(this->state == 4 || this->state == 5) + this->marker->propPtr->unk8_3 = (next_state == CHJINXYHEADSANDYBUTT_STATE_1_UNK) ? FALSE : TRUE; + this->marker->collidable = (next_state == CHJINXYHEADSANDYBUTT_STATE_1_UNK) ? FALSE : TRUE; + if(this->state == CHJINXYHEADSANDYBUTT_STATE_4_UNK + || this->state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) + { sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); + } - if(next_state == 4 || next_state == 5){ + if(next_state == CHJINXYHEADSANDYBUTT_STATE_4_UNK + || next_state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) + { local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(local->sfxsourceIdx, SFX_3EC_CCW_DOOR_OPENING); sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 3); @@ -86,7 +108,7 @@ void func_8038C8A0(Actor *this, s32 next_state){ sfxSource_func_8030E2C4(local->sfxsourceIdx); }//L8038C9B8 - if(next_state == 2){ + if(next_state == CHJINXYHEADSANDYBUTT_STATE_2_UNK){ skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 1.0f, 3.0f); skeletalAnim_setProgress(this->unk148, 0.27f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); @@ -100,28 +122,31 @@ void func_8038C8A0(Actor *this, s32 next_state){ } }//L8038CA6C - if(next_state == 3){ + if(next_state == CHJINXYHEADSANDYBUTT_STATE_3_UNK){ local->unk24 = 3.0f; skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 1.0f, 3.0f); skeletalAnim_setProgress(this->unk148, 0.27f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); }//L8038CAB4 - if(this->state == 3){ + if(this->state == CHJINXYHEADSANDYBUTT_STATE_3_UNK){ skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 0.5f, 3.0f); skeletalAnim_setProgress(this->unk148, 0.99f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if(next_state == 4 || next_state == 5) + if(next_state == CHJINXYHEADSANDYBUTT_STATE_4_UNK + || next_state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) + { sfx_playFadeShorthandDefault(SFX_DE_WOOD_SQUEAK, 1.0f, 32675, this->position, 500, 1500); + } }//L8038CB20 - if(next_state == 6){ + if(next_state == CHJINXYHEADSANDYBUTT_STATE_6_FED){ func_80324E38(0.0f, 3); skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 0.0f, 3.0f); coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); } - if(next_state == 7){ + if(next_state == CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY){ local->unkC = 0.0f; local->unk18[0] = this->position_x; local->unk18[1] = this->position_y; @@ -130,26 +155,26 @@ void func_8038C8A0(Actor *this, s32 next_state){ FUNC_8030E624(SFX_3F6_RUBBING, 0.8f, 30000); } - if(next_state == 8){ - if(this->state == 7){ + if(next_state == CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED){ + if(this->state == CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY){ baMotor_80250D94(0.8f, 0.7f, 3.0f); - func_8038C760(this, *local->unk8 + 1); + chJinxyHeadSandybutt_raisePyramid(this, *local->unk8 + 1); } marker_despawn(this->marker); } this->state = next_state; } -Actor *func_8038CC40(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *chJinxyHeadSandybutt_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(this_marker); - if(this->state == 1) return this; + if(this->state == CHJINXYHEADSANDYBUTT_STATE_1_UNK) return this; return actor_draw(this_marker, gfx, mtx, vtx); } -void func_8038CC98(Actor *this){ +void chJinxyHeadSandybutt_update(Actor *this){ ActorLocal_GV_6370 *local = (ActorLocal_GV_6370 *)&this->local; - f32 sp80 = time_getDelta(); - s32 sp7C; + f32 time_delta = time_getDelta(); + s32 pyramid_file_progress; f32 pad70; f32 sp6C[3]; f32 f12; @@ -159,24 +184,24 @@ void func_8038CC98(Actor *this){ f32 sp48[3]; if(!this->volatile_initialized){ - sp7C = fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2); - this->volatile_initialized = true; - this->marker->actorFreeFunc = func_8038C880; - local->unk8 = &D_803911F0[this->modelCacheIndex - 0x285]; + pyramid_file_progress = fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2); + this->volatile_initialized = TRUE; + this->marker->actorFreeFunc = chJinxyHeadSandybutt_free; + local->unk8 = &chJinxyHeadSandybuttIndices[this->modelCacheIndex - 0x285]; local->unk10 = 0; local->unk14 = 0; local->unkC = 0.0f; local->unk18[0] = this->position_x; local->unk18[1] = this->position_y; local->unk18[2] = this->position_z; - if(*local->unk8 < sp7C){ - func_8038C8A0(this, 8); + if(*local->unk8 < pyramid_file_progress){ + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED); } - else if(sp7C == *local->unk8){ - func_8038C8A0(this, 2); + else if(pyramid_file_progress == *local->unk8){ + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_2_UNK); } else{ - func_8038C8A0(this, 1); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_1_UNK); } return; } @@ -185,17 +210,22 @@ void func_8038CC98(Actor *this){ local->unk14 = actorArray_findActorFromActorId(ACTOR_31D_SANDYBUTT_PYRAMID)->marker; } - if(this->state == 1){ + if(this->state != CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED && fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2) > *local->unk8){ + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED); + return; + } + + if(this->state == CHJINXYHEADSANDYBUTT_STATE_1_UNK){ if(fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2) == *local->unk8){ - func_8038C8A0(this, 2); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_2_UNK); } } - if(this->state == 2){ - local->unkC += 0.5*sp80; + if(this->state == CHJINXYHEADSANDYBUTT_STATE_2_UNK){ + local->unkC += 0.5 * time_delta; if(1.0f <= local->unkC){ local->unkC = 1.0f; - func_8038C8A0(this, 3); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_3_UNK); } sp6C[0] = 0.0f; sp6C[1] = 0.0f; @@ -206,26 +236,28 @@ void func_8038CC98(Actor *this){ this->position_z = local->unk18[2] + sp6C[2]; }//L8038CECC - if(this->state == 3){ + if(this->state == CHJINXYHEADSANDYBUTT_STATE_3_UNK){ if(0.0f < local->unk24){ - local->unk24 -= sp80; + local->unk24 -= time_delta; } else{ if(func_8038D388()) - func_8038C8A0(this, 5); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_5_UNK); } }//L8038CF1C - if(this->state == 4 || this->state == 5){ - local->unkC += ((this->state == 4)? -1 : 1) * sp80; + if(this->state == CHJINXYHEADSANDYBUTT_STATE_4_UNK + || this->state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) + { + local->unkC += ((this->state == 4)? -1 : 1) * time_delta; if(1.0f < local->unkC){ local->unkC = 1.0f; - func_8038C8A0(this, 4); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_4_UNK); return; } else if(local->unkC < -1.0f){ local->unkC = -1.0f; - func_8038C8A0(this, 5); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_5_UNK); return; } sp5C[0] = local->unkC*300.0f; @@ -236,21 +268,21 @@ void func_8038CC98(Actor *this){ this->position_y = local->unk18[1] + sp5C[1]; this->position_z = local->unk18[2] + sp5C[2]; if(0.8 <= local->unkC){ - f12 = 1.0 - (local->unkC - 0.8)/0.2; + f12 = 1.0 - (local->unkC - 0.8) / 0.2; } else if(local->unkC <= -0.8){ - f12 = 1.0 - (-local->unkC - 0.8)/0.2; + f12 = 1.0 - (-local->unkC - 0.8) / 0.2; } else{ f12 = 1.0f; } - func_8030DB04(local->sfxsourceIdx, f12*24000.0f, this->position, 200.0f, 1500.0f); + func_8030DB04(local->sfxsourceIdx, f12 * 24000.0f, this->position, 200.0f, 1500.0f); if(!func_8038D388()){ - func_8038C8A0(this, 3); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_3_UNK); } }//L8038D110 - if(this->state == 6){ + if(this->state == CHJINXYHEADSANDYBUTT_STATE_6_FED){ skeletalAnim_getProgressRange(this->unk148, &sp58, &sp54); if(sp58 < 0.28 && 0.28 <= sp54){ FUNC_8030E624(SFX_4C_LIP_SMACK, 1.0f, 28000); @@ -263,18 +295,18 @@ void func_8038CC98(Actor *this){ } if(0.81 <= sp54){ FUNC_8030E624(SFX_97_BLUBBER_BURPS, 1.0f, 28000); - func_8038C8A0(this, 7); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY); } }//L8038D228 - if(this->state == 7){ - local->unkC += 0.5*sp80; + if(this->state == CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY){ + local->unkC += 0.5 * time_delta; if(1.0f < local->unkC){ - func_8038C8A0(this, 8); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED); } sp48[0] = 0.0f; sp48[1] = 0.0f; - sp48[2] = local->unkC*-600.0f; + sp48[2] = local->unkC * -600.0f; ml_vec3f_yaw_rotate_copy(sp48, sp48, this->yaw); this->position_x = local->unk18[0] + sp48[0]; this->position_y = local->unk18[1] + sp48[1]; @@ -282,11 +314,13 @@ void func_8038CC98(Actor *this){ }//L8038D2F0 if(local->unk0){ - if(this->state == 4 || this->state == 5){ + if(this->state == CHJINXYHEADSANDYBUTT_STATE_4_UNK + || this->state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) + { local->unk0 = 0; local->unk10++; if(local->unk10 == 3){ - func_8038C8A0(this, 6); + chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_6_FED); } else{ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); diff --git a/src/GV/ch/rubee.c b/src/GV/rubee.c similarity index 56% rename from src/GV/ch/rubee.c rename to src/GV/rubee.c index 6bdacb80d..43befb426 100644 --- a/src/GV/ch/rubee.c +++ b/src/GV/rubee.c @@ -3,10 +3,10 @@ #include "functions.h" #include "variables.h" -void func_80389B1C(Actor *this); +void chRubee_update(Actor *this); /* .data */ -ActorAnimationInfo D_80390EA0[] = { +ActorAnimationInfo chRubeeAnimations[] = { {0x00, 0.0f}, {ASSET_DF_ANIM_RUBEE_PET_TOOTS, 4.5f}, {ASSET_E3_ANIM_RUBEE_IDLE, 2.0f}, @@ -15,29 +15,38 @@ ActorAnimationInfo D_80390EA0[] = { {ASSET_DF_ANIM_RUBEE_PET_TOOTS, 4.5f} }; -ActorInfo D_80390ED0 = { MARKER_A9_RUBEE, ACTOR_11B_RUBEE, ASSET_3DD_MODEL_RUBEE, - 0x2, D_80390EA0, - func_80389B1C, actor_update_func_80326224, actor_draw, +ActorInfo chRubee = { + MARKER_A9_RUBEE, ACTOR_11B_RUBEE, ASSET_3DD_MODEL_RUBEE, + 0x2, chRubeeAnimations, + chRubee_update, actor_update_func_80326224, actor_draw, 2500, 0, 1.6f, 0 }; +enum chrubee_state_e { + CH_RUBEE_STATE_0_NOT_INIT, + CH_RUBEE_STATE_1_IDLE, + CH_RUBEE_STATE_2_IDLE, + CH_RUBEE_STATE_3_PLAYING_SONG, + CH_RUBEE_STATE_4_UNK, + CH_RUBEE_STATE_5_UNK +}; /* .code */ void func_80389A20(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this = marker_getActor(caller); func_8038E18C(); - subaddie_set_state_with_direction(this, 3, 0.0f, 1); + subaddie_set_state_with_direction(this, CH_RUBEE_STATE_3_PLAYING_SONG, 0.0f, 1); } void func_80389A60(Actor *this){ - gcdialog_showDialog(ASSET_A70_DIALOG_RUBEE_HELPED, 4, NULL, this->marker, func_80389A20, NULL); - this->has_met_before = true; - subaddie_set_state(this, 5); + gcdialog_showDialog(VER_SELECT(ASSET_A70_DIALOG_RUBEE_HELPED, 0x92C, 0, 0), 4, NULL, this->marker, func_80389A20, NULL); + this->has_met_before = TRUE; + subaddie_set_state(this, CH_RUBEE_STATE_5_UNK); } void func_80389ABC(Actor *this){ if(this->unk138_23){ - func_80389A20(this->marker, ASSET_A70_DIALOG_RUBEE_HELPED, -1); + func_80389A20(this->marker, VER_SELECT(ASSET_A70_DIALOG_RUBEE_HELPED, 0x92C, 0, 0), -1); } else{ this->unk138_23 = true; @@ -46,9 +55,9 @@ void func_80389ABC(Actor *this){ } } -void func_80389B1C(Actor *this){ +void chRubee_update(Actor *this){ if(!this->volatile_initialized){ - this->lifetime_value = (f32) func_8038E184(); + this->lifetime_value = (f32) rubeeEggPot_getEggGoal(); this->has_met_before = jiggyscore_isCollected(JIGGY_43_GV_HISTUP) || mapSpecificFlags_get(0); this->unk138_23 = jiggyscore_isCollected(JIGGY_43_GV_HISTUP) || mapSpecificFlags_get(2); this->volatile_initialized = true; @@ -62,21 +71,26 @@ void func_80389B1C(Actor *this){ anctrl_setTransitionDuration(this->anctrl, 0.15f); - if(this->state == 1 || this->state == 2){ - if(! this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 250) && !subaddie_playerIsWithinSphereAndActive(this, 0x50)){ - gcdialog_showDialog(ASSET_A6F_DIALOG_RUBEE_MEET, 0xe, this->position, NULL, NULL, NULL); - this->has_met_before = true; - mapSpecificFlags_set(0, true); + if(this->state == CH_RUBEE_STATE_1_IDLE + || this->state == CH_RUBEE_STATE_2_IDLE) + { + if(! this->has_met_before + && subaddie_playerIsWithinSphereAndActive(this, 250) + && !subaddie_playerIsWithinSphereAndActive(this, 0x50)) + { + gcdialog_showDialog(VER_SELECT(ASSET_A6F_DIALOG_RUBEE_MEET, 0x92B, 0, 0), 0xE, this->position, NULL, NULL, NULL); + this->has_met_before = TRUE; + mapSpecificFlags_set(0, TRUE); } } switch(this->state){ - case 1://L80389CC4 + case CH_RUBEE_STATE_1_IDLE://L80389CC4 if(this->lifetime_value <= (f32)func_8038E178()){ func_80389ABC(this); } else if(actor_animationIsAt(this, 0.99f)){ - subaddie_maybe_set_state(this, 2, 0.9f); + subaddie_maybe_set_state(this, CH_RUBEE_STATE_2_IDLE, 0.9f); } if( actor_animationIsAt(this, 0.42f) @@ -92,27 +106,27 @@ void func_80389B1C(Actor *this){ } break; - case 2: //L80389DB0 + case CH_RUBEE_STATE_2_IDLE: //L80389DB0 if(this->lifetime_value <= (f32)func_8038E178()){ func_80389ABC(this); } else if(actor_animationIsAt(this, 0.99f)){ - subaddie_maybe_set_state(this, 1, 0.4f); + subaddie_maybe_set_state(this, CH_RUBEE_STATE_1_IDLE, 0.4f); } break; - case 3: //L80389E14 + case CH_RUBEE_STATE_3_PLAYING_SONG: //L80389E14 if( actor_animationIsAt(this, 0.2f)){ func_8025A58C(500, 400); coMusicPlayer_playMusic(COMUSIC_27_GV_RUBEES_SONG, 28000); } if( actor_animationIsAt(this, 0.99f)){ - subaddie_set_state(this, 4); + subaddie_set_state(this, CH_RUBEE_STATE_4_UNK); } break; - case 4: //L80389E64 + case CH_RUBEE_STATE_4_UNK: //L80389E64 if(!func_8038E178()) - subaddie_set_state(this, 2); + subaddie_set_state(this, CH_RUBEE_STATE_2_IDLE); break; }//L80389E80 } diff --git a/src/GV/pyramid_trigger.c b/src/GV/sandybutteggtoll.c similarity index 69% rename from src/GV/pyramid_trigger.c rename to src/GV/sandybutteggtoll.c index 568c38890..cf82896bc 100644 --- a/src/GV/pyramid_trigger.c +++ b/src/GV/sandybutteggtoll.c @@ -1,14 +1,15 @@ -// BanjoDecomp: code_6F80.c +// BanjoDecomp: GV/sandybutteggtoll.c #include #include "functions.h" #include "variables.h" -void func_8038D3AC(Actor *this); +void chSandybuttEggToll_update(Actor *this); /* .data */ -ActorInfo D_80391260 = { 0x1A5, 0x288, 0x402, +ActorInfo chSandybuttEggToll = { + MARKER_1A5_SANDYBUTT_EGG_TOLL, 0x288, ASSET_402_MODEL_EGG_TOLL, 0, NULL, - func_8038D3AC, NULL, func_80325340, + chSandybuttEggToll_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; @@ -20,11 +21,11 @@ void func_8038D370(ActorMarker *this_marker, ActorMarker *other_marker){ D_80391AA0 = 5; } -int func_8038D388(void){ +bool func_8038D388(void){ return D_80391AA0 ? 1 : 0; } -void func_8038D3AC(Actor *this){ +void chSandybuttEggToll_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; marker_setCollisionScripts(this->marker, func_8038D370, NULL, NULL); diff --git a/src/GV/smoke_particle.c b/src/GV/smoke_particle.c index 41f471ae7..371669359 100644 --- a/src/GV/smoke_particle.c +++ b/src/GV/smoke_particle.c @@ -7,7 +7,9 @@ void GV_func_8038A084(Actor *this); /* .data */ -ActorInfo D_80390F40 = { 0x24F, 0x37C, 0x0, +// Hot Sand Smoke Emitter? +ActorInfo D_80390F40 = { + 0x24F, 0x37C, 0x0, 0, NULL, GV_func_8038A084, actor_update_func_80326224, func_80325340, 2000, 0, 0.0f, 0 diff --git a/src/GV/water_pyramidrot.c b/src/GV/water_pyramidrot.c index 67dec578d..ec385dd8f 100644 --- a/src/GV/water_pyramidrot.c +++ b/src/GV/water_pyramidrot.c @@ -4,6 +4,8 @@ #include "variables.h" +static s32 sGvPyramidRaised = 0; + void func_8038FF60(void){} void func_8038FF68(void){ @@ -15,11 +17,27 @@ void func_8038FF68(void){ if(jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID)){ tmp_s70 = func_8034C528(0x190); if(tmp_s70) subaddie_positionMoveVertical(&tmp_s70->type_6D, 0.0f, 270.0f, 0.0f, 1); + sGvPyramidRaised = 1; } else{ tmp_s70 = func_8034C5AC(0x130); if(tmp_s70) func_8034E71C(&tmp_s70->type_73, -1500, 0.0f); + sGvPyramidRaised = 0; } } -void func_8038FFF4(void){} +void func_8038FFF4(void){ + Struct70s *tmp_s70; + + // LEVEL_FLAG_6 = local rise cutscene in progress. + if(sGvPyramidRaised) return; + if(gsworld_getMap() != MAP_12_GV_GOBIS_VALLEY) return; + if(levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN)) return; + if(!jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID)) return; + + tmp_s70 = func_8034C5AC(0x130); + if(tmp_s70) func_8034E71C(&tmp_s70->type_73, 0, 2.5f); + tmp_s70 = func_8034C528(0x190); + if(tmp_s70) subaddie_positionMoveVertical(&tmp_s70->type_6D, 0.0f, 270.0f, 2.5f, 1); + sGvPyramidRaised = 1; +} diff --git a/src/LAIR/bss_pad.c b/src/LAIR/bss_pad.c deleted file mode 100644 index f0c8cfff4..000000000 --- a/src/LAIR/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -static char pad_lair_80395350[0x10]; //padding diff --git a/src/MM/ch/chimpystump.c b/src/MM/ch/chimpystump.c index da6df06c0..951a3a6a9 100644 --- a/src/MM/ch/chimpystump.c +++ b/src/MM/ch/chimpystump.c @@ -33,8 +33,12 @@ void __chchimpystump_updateShaking(Actor *this) { if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_4_SHAKE)) { if (this->unk10_12 == 0) { this->unk10_12 = 1; - func_802BB3DC(1, 3.0f, 1.0f); - core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.2f); + // [port] Vanilla replays Chimpy's walk-off, and with it this rise, on every entry to MM + // once his jiggy has spawned. Both halves are muted for those replays. + if (EventSystem_Should(VB_MM_CHIMPY_STUMP_RUMBLE, true)) { + func_802BB3DC(1, 3.0f, 1.0f); + core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.2f); + } }//L80386D0C this->position_x = ((globalTimer_getTime() & 1) * 2) ^ (s32) this->position_x; @@ -47,7 +51,11 @@ void chchimpystump_update(Actor *this) { actor_collisionOff(this); this->initialized = true; this->actor_specific_1_f = this->position_y; - this->position_y -= 134.0f; + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_0_CHIMPY_STUMP_RAISED)) { + subaddie_set_state(this, CHIMPY_STUMP_STATE_3_RAISED); + } else { + this->position_y -= 134.0f; + } this->marker->propPtr->unk8_3 = 1; } diff --git a/src/MM/ch/conga.c b/src/MM/ch/conga.c index fc6098492..e3d799e09 100644 --- a/src/MM/ch/conga.c +++ b/src/MM/ch/conga.c @@ -1,10 +1,13 @@ -// BanjoDecomp: conga.c -#include "functions.h" +// BanjoDecomp: MM/ch/conga.c +#include #include "rand.h" +#include "functions.h" #include "variables.h" -#include -#include #include + +#include "bk_math.h" // [port] SQ macro +#include "conga.h" + #ifndef MIN #define MIN(s,t) ((s)<(t)?(s):(t)) #endif @@ -22,14 +25,14 @@ void MM_checkMMChecksums(void); void chConga_update(Actor *); -typedef struct chconga_s{ +typedef struct chconga_s { TUPLE(s32, orangeSpawnPosition); s32 unkC; s32 unk10; u8 pad14[0x4]; s32 unk18; s32 unk1C; -}ActorLocal_Conga; +} ActorLocal_Conga; /* .data */ @@ -58,26 +61,26 @@ bool __chConga_isPlayerNearCongaTree(Actor * this){ f32 unused_tmpz; if (gsworld_getMap() != MAP_2_MM_MUMBOS_MOUNTAIN) { - return false; + return FALSE; } if (!this->unk10_12) { - return false; + return FALSE; } player_getPosition(plyr_pos); if (plyr_pos[1] < 300.0f || 600.0f < plyr_pos[1]) { - return false; + return FALSE; } unused_tmpz = plyr_pos[2] - 5029.0f; if (52900.0f < (plyr_pos[0] - -5011.0f) * (plyr_pos[0] - -5011.0f) + (plyr_pos[2] - 5029.0f) * (plyr_pos[2] - 5029.0f)) { - return false; + return FALSE; } - return true; + return TRUE; } void func_80386FB0(Actor *this){ @@ -127,7 +130,7 @@ void func_80387168(ActorMarker *marker, ActorMarker *other_marker){ actorPtr->unk38_31++; actorPtr->unk10_12 = MIN(actorPtr->unk38_31, 0xA); - if( actorPtr->unk38_31 == 3 + if( actorPtr->unk38_31 == 3 && !jiggyscore_isCollected(JIGGY_A_MM_CONGA) ){ subaddie_set_state_with_direction(actorPtr, 8, 0 ,1); @@ -141,7 +144,7 @@ void func_80387168(ActorMarker *marker, ActorMarker *other_marker){ ){ func_8038708C(actorPtr, 2); if(actorPtr->unk38_31 == 1){ - gcdialog_showDialog(ASSET_B39_DIALOG_CONGA_HIT_BY_EGG, 4, actorPtr->position, 0, 0, 0); + gcdialog_showDialog(VER_SELECT(ASSET_B39_DIALOG_CONGA_HIT_BY_EGG, 0x957, 0, 0), 4, actorPtr->position, 0, 0, 0); } } } @@ -151,10 +154,10 @@ void func_80387168(ActorMarker *marker, ActorMarker *other_marker){ int func_803872EC(void){ s32 text_id = gcdialog_getCurrentTextId(); - return text_id == ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE - || text_id == ASSET_B38_DIALOG_CONGA_DEFEAT + return text_id == VER_SELECT(ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE, 0x955, 0, 0) + || text_id == VER_SELECT(ASSET_B38_DIALOG_CONGA_DEFEAT, 0x956, 0, 0) || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - || text_id == ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY + || text_id == VER_SELECT(ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY, 0x959, 0, 0) || text_id == ASSET_B45_DIALOG_JIGGY_COLLECT_10 || text_id == ASSET_B51_DIALOG_BOTTLES_HOW_TO_EXIT_LEVEL; } @@ -210,169 +213,192 @@ void __chConga_sendOrangeProjectile(ActorMarker *congaMarker){ } } -void chConga_update(Actor *this){ +void chConga_update(Actor *this) { + f32 unused; NodeProp *node_prop; s32 sp3C; - this->marker->propPtr->unk8_3 = (timedFuncQueue_is_empty())?1:0; - if(!this->initialized){ + this->marker->propPtr->unk8_3 = timedFuncQueue_is_empty() ? 1 : 0; // [port] def takes no args + + if (!this->initialized) { ((ActorLocal_Conga *)&this->local)->unkC = 1; this->unk16C_0 = 1; - this->initialized = true; + this->initialized = TRUE; this->velocity_x = 0.0f; this->actor_specific_1_f = 0.0f; node_prop = nodeprop_findByActorIdAndActorPosition(0x150, this); ((ActorLocal_Conga *)&this->local)->unk1C = nodeprop_getRadius(node_prop); nodeprop_getPosition_s32(node_prop, &((ActorLocal_Conga *)&this->local)->unk10); } - if(0.0f == this->actor_specific_1_f){ + + if (0.0f == this->actor_specific_1_f) { this->actor_specific_1_f = (actorArray_findActorFromMarkerId(MARKER_36_ORANGE_COLLECTIBLE) != NULL)? 2.0f: 1.0f; } - if(0.0f != this->velocity_x){ + + if (0.0f != this->velocity_x) { this->velocity_x -= 1.0f; if(0.0f == this->velocity_x){ - __spawnQueue_add_1((GenFunction_1)func_80387100, (uintptr_t)this->marker); + __spawnQueue_add_1((GenFunction_1)func_80387100, reinterpret_cast(uintptr_t, this->marker)); } } + marker_setCollisionScripts(this->marker, NULL, NULL, func_80387168); - if( !subaddie_playerIsWithinSphereAndActive(this, 2100) + + if (!subaddie_playerIsWithinSphereAndActive(this, 2100) && this->state != 2 - && this->state != 8 - ){ + && this->state != 8) { + if(this->state > 3 && this->state < 8){ actor_loopAnimation(this); subaddie_set_state_with_direction(this, 1, 0.76f, 1); } + return; } sp3C = subaddie_playerIsWithinSphereAndActive(this, 1000); - if( func_8032A9E4(((ActorLocal_Conga *)&this->local)->unk10, ((ActorLocal_Conga *)&this->local)->unk18, ((ActorLocal_Conga *)&this->local)->unk1C) + + if (func_8032A9E4(((ActorLocal_Conga *)&this->local)->unk10, ((ActorLocal_Conga *)&this->local)->unk18, ((ActorLocal_Conga *)&this->local)->unk1C) && !this->unk138_23 - && gcdialog_showDialog(ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE, 0, 0, 0, 0, 0) - ){ + && gcdialog_showDialog(VER_SELECT(ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE, 0x955, 0, 0), 0, 0, 0, 0, 0)) { this->unk138_23 = 1; - mapSpecificFlags_set(MM_SPECIFIC_FLAG_A_UNKNOWN, true); + mapSpecificFlags_set(MM_SPECIFIC_FLAG_A_UNKNOWN, TRUE); }//L803878F8 - if( sp3C && !this->has_met_before){ - if(gcdialog_showDialog((player_getTransformation()== TRANSFORM_2_TERMITE) ? ASSET_B3E_DIALOG_CONGA_MEET_AS_TERMITE : ASSET_B3C_DIALOG_CONGA_MEET, 0, this->position, 0,0,0)){ - this->has_met_before = true; + if (sp3C && !this->has_met_before) { + if (gcdialog_showDialog((player_getTransformation()== TRANSFORM_2_TERMITE) ? ASSET_B3E_DIALOG_CONGA_MEET_AS_TERMITE : VER_SELECT(ASSET_B3C_DIALOG_CONGA_MEET, 0x95A, 0, 0), 0, this->position, 0,0,0)) { + this->has_met_before = TRUE; } } //L80387968 - switch(this->state){ - case 1://80387990 + switch (this->state) { + case CONGA_STATE_IDLE://80387990 actor_loopAnimation(this); func_80386FB0(this); __chConga_playRandomNoise(); + if(actor_animationIsAt(this, 0.0f) || actor_animationIsAt(this, 0.45f)){ if(randf() < 0.2){ anctrl_setDirection(this->anctrl, anctrl_isPlayedForwards(this->anctrl)?0:1); }; }//L80387A18 - if(actor_animationIsAt(this, 0.66f)){ - subaddie_maybe_set_state_position_direction(this, 6, 0, 1, 0.38f); + + if (actor_animationIsAt(this, 0.66f)) { + subaddie_maybe_set_state_position_direction(this, CONGA_STATE_BEAT_CHEST_STOP, 0, 1, 0.38f); } - if( sp3C + + if (sp3C && player_movementGroup() != BSGROUP_1_INTR && !__chConga_isPlayerNearCongaTree(this) && timedFuncQueue_is_empty() && !func_8032A9E4(((ActorLocal_Conga *)&this->local)->unk10, ((ActorLocal_Conga *)&this->local)->unk18, ((ActorLocal_Conga *)&this->local)->unk1C) - && !func_803872EC() - ){ - subaddie_set_state_with_direction(this, 4, 0.0f, 1); + && !func_803872EC()) { + + subaddie_set_state_with_direction(this, CONGA_STATE_TARGET_GROUND, 0.0f, 1); }//L80387AC0 - if( player_movementGroup() != BSGROUP_1_INTR + + if (player_movementGroup() != BSGROUP_1_INTR && __chConga_isPlayerNearCongaTree(this) && this->unk38_31 != 0 - && !func_803872EC() - ){ - subaddie_set_state_with_direction(this, 7, 0.0f, 1); + && !func_803872EC()) { + + subaddie_set_state_with_direction(this, CONGA_STATE_TARGET_BANJO, 0.0f, 1); } break; - case 6: //L80387B24 + case CONGA_STATE_BEAT_CHEST_STOP: //L80387B24 ((ActorLocal_Conga *)&this->local)->unkC = 1; actor_playAnimationOnce(this); __chConga_playRandomNoise(); - if( anctrl_isPlayedForwards(this->anctrl) == true - && actor_animationIsAt(this, 0.0f) - ){ - subaddie_set_state_with_direction(this, 5, 0.0f, 1); - } - else if( !anctrl_isPlayedForwards(this->anctrl) - && actor_animationIsAt(this, 0.001f) - ){ - subaddie_set_state_with_direction(this, 1, 0.76f, 1); + + if (anctrl_isPlayedForwards(this->anctrl) == TRUE + && actor_animationIsAt(this, 0.0f)) { + + subaddie_set_state_with_direction(this, CONGA_STATE_BEAT_CHEST, 0.0f, 1); + } else if (!anctrl_isPlayedForwards(this->anctrl) + && actor_animationIsAt(this, 0.001f)) { + subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.76f, 1); } + break; - case 5: //L80387BC0 + case CONGA_STATE_BEAT_CHEST: //L80387BC0 ((ActorLocal_Conga *)&this->local)->unkC = 1; actor_loopAnimation(this); __chConga_playRandomNoise(); - if( actor_animationIsAt(this, 0.99f)){ - subaddie_maybe_set_state_position_direction(this, 6, 0.999f, 0, sp3C ? 1.0 : 0.4); + + if (actor_animationIsAt(this, 0.99f)) { + subaddie_maybe_set_state_position_direction(this, CONGA_STATE_BEAT_CHEST_STOP, 0.999f, 0, sp3C ? 1.0 : 0.4); }//L80387C30 - if( actor_animationIsAt(this, 0.9f) - || actor_animationIsAt(this, 0.4f) - ){ + + if (actor_animationIsAt(this, 0.9f) + || actor_animationIsAt(this, 0.4f)) { func_8030E6D4(SFX_3FB_UNKNOWN); } + break; - case 4: //L80387C74 - if(actor_animationIsAt(this, 0.6f)){ + case CONGA_STATE_TARGET_GROUND: //L80387C74 + if (actor_animationIsAt(this, 0.6f)) { func_8030E58C(SFX_2_CLAW_SWIPE, 0.7f); } + func_80386FB0(this); - if( !sp3C + + if (!sp3C || player_is_in_jiggy_jig() || __chConga_isPlayerNearCongaTree(this) || !timedFuncQueue_is_empty() - || func_803872EC() - ){ - subaddie_set_state_with_direction(this, 1, 0.0f, 1); + || func_803872EC()) { + + subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.0f, 1); } + break; - case 2: //L80387D0C + case CONGA_STATE_HIT: //L80387D0C actor_playAnimationOnce(this); - if(actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, 1, 0.0f, 1); + if (actor_animationIsAt(this, 0.99f)) { + subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.0f, 1); } + break; - case 8: //L80387D4C + case CONGA_STATE_ROAR: //L80387D4C actor_playAnimationOnce(this); - if(actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, 3, 0.0f, 1); - gcdialog_showDialog(ASSET_B38_DIALOG_CONGA_DEFEAT, 0xe, this->position, this->marker, func_80387370, NULL); + + if (actor_animationIsAt(this, 0.99f)) { + subaddie_set_state_with_direction(this, CONGA_STATE_MOPEY, 0.0f, 1); + gcdialog_showDialog(VER_SELECT(ASSET_B38_DIALOG_CONGA_DEFEAT, 0x956, 0, 0), 0xe, this->position, this->marker, func_80387370, NULL); } + break; - case 3: //L80387DB8 + case CONGA_STATE_MOPEY: //L80387DB8 actor_loopAnimation(this); - if(jiggyscore_isCollected(JIGGY_A_MM_CONGA)){ - subaddie_set_state_with_direction(this, 1, 0.0f, 1); + + if (jiggyscore_isCollected(JIGGY_A_MM_CONGA)) { + subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.0f, 1); } + break; - case 7: //L80387DF0 - if(this->unk10_12 == 0){ - if(actor_animationIsAt(this, 0.97f)){ + case CONGA_STATE_TARGET_BANJO: //L80387DF0 + if (this->unk10_12 == 0) { + if (actor_animationIsAt(this, 0.97f)) { ((ActorLocal_Conga *)&this->local)->unkC = 1; - subaddie_set_state_with_direction(this, 6, 0.0f, 1); + subaddie_set_state_with_direction(this, CONGA_STATE_BEAT_CHEST_STOP, 0.0f, 1); } } + break; }//L80387E38 - if( (this->state == 4 && actor_animationIsAt(this, 0.56f)) - || (this->state == 7 && actor_animationIsAt(this, 0.468f)) - ){ - vec3fArray_get_vec3i(this->marker->unk44, 5, (s32 *)this->local); - __spawnQueue_add_1((GenFunction_1)__chConga_sendOrangeProjectile, (uintptr_t)this->marker); //spawn orange + + if ((this->state == CONGA_STATE_TARGET_GROUND && actor_animationIsAt(this, 0.56f)) + || (this->state == CONGA_STATE_TARGET_BANJO && actor_animationIsAt(this, 0.468f))) { + + vec3fArray_get_vec3i(this->marker->unk44, 5, (s32 *)&this->local); // [port] writes 3 s32 into actor local + __spawnQueue_add_1((GenFunction_1)__chConga_sendOrangeProjectile, reinterpret_cast(uintptr_t, this->marker)); //spawn orange } } diff --git a/src/MM/ch/conga.h b/src/MM/ch/conga.h new file mode 100644 index 000000000..ede0eeddb --- /dev/null +++ b/src/MM/ch/conga.h @@ -0,0 +1,11 @@ +// BanjoDecomp: MM/ch/conga.h +enum conga_state_s { + CONGA_STATE_IDLE = 1, + CONGA_STATE_HIT = 2, + CONGA_STATE_MOPEY = 3, // After defeat, waiting for Banjo to collect the jiggy + CONGA_STATE_TARGET_GROUND = 4, + CONGA_STATE_BEAT_CHEST = 5, + CONGA_STATE_BEAT_CHEST_STOP = 6, // Though depending on the animation, he'll go back to beating his chest + CONGA_STATE_TARGET_BANJO = 7, // Targeting Banjo when he's at eye level + CONGA_STATE_ROAR = 8 // When Conga is defeated +}; diff --git a/src/MM/ch/hut.c b/src/MM/ch/hut.c index 1a2ad24d5..f4925d563 100644 --- a/src/MM/ch/hut.c +++ b/src/MM/ch/hut.c @@ -8,6 +8,8 @@ #include +#include "port/Patches/Patches.h" + /* extern function declarations */ void bundle_setYaw(f32); @@ -40,7 +42,7 @@ Actor *chhut_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 is_intact_or_destroyed = actorPtr->state == HUT_STATE_0_INTACT || actorPtr->state == HUT_STATE_2_DESTROYED; this->propPtr->unk8_3 = is_intact_or_destroyed; - func_8033A45C(1, is_not_destroyed); + modelRender_setAppendageVisibility(1, is_not_destroyed); return actor_draw(this, gfx, mtx, vtx); } @@ -52,18 +54,43 @@ void __chhut_spawnExplosion(ActorMarker *this) { if (this); } -void chhut_update(Actor *this) { - static enum bundle_e D_803898D8[6] = { - BUNDLE_0_MM_HUT_MUSIC_NOTE, - BUNDLE_1_MM_HUT_BLUE_EGG, - BUNDLE_2_MM_HUT_GRUBLIN, - BUNDLE_3_MM_HUT_JINJO_GREEN, - BUNDLE_6_MM_HUT_EXTRA_LIFE, - BUNDLE_4_MM_HUT_JIGGY - }; +static enum bundle_e mm_hut_bundles[6] = { + BUNDLE_0_MM_HUT_MUSIC_NOTE, + BUNDLE_1_MM_HUT_BLUE_EGG, + BUNDLE_2_MM_HUT_GRUBLIN, + BUNDLE_3_MM_HUT_JINJO_GREEN, + BUNDLE_6_MM_HUT_EXTRA_LIFE, + BUNDLE_4_MM_HUT_JIGGY +}; + +static void chhut_dropRecordedBundle(Actor *this, s32 loot, s32 fullBundle) { + f32 pos[3]; + if (loot < 0 || loot >= 5) { + return; // jiggy / out of range + } + if (!fullBundle && (loot == 0 || loot == 3)) { + return; // note / jinjo: skip on reload + } + pos[0] = this->position_x; + pos[1] = this->position_y + 125.0f; + pos[2] = this->position_z; + __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, mm_hut_bundles[loot], *(s32 *)(&pos[0]), *(s32 *)(&pos[1]), *(s32 *)(&pos[2])); +} + +static void chhut_replaySmash(Actor *this, s32 loot) { + sfxsource_playHighPriority(SFX_5B_HEAVY_STUFF_FALLING); + subaddie_set_state(this, HUT_STATE_1_DAMAGED); + actor_playAnimationOnce(this); + __spawnQueue_add_1((GenFunction_1) __chhut_spawnExplosion, (uintptr_t)this->marker); + bundle_setYaw(this->yaw); + chhut_dropRecordedBundle(this, loot, 1); +} +void chhut_update(Actor *this) { f32 diff_pos[3]; f32 plyr_pos[3]; + s32 loot; + s32 smashIndex; if (gsworld_getUnk0() != 2) { return; @@ -72,6 +99,13 @@ void chhut_update(Actor *this) { if (!this->initialized) { this->marker->collidable = false; this->initialized = true; + loot = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); + if (loot >= 0) { + chhut_dropRecordedBundle(this, loot, 0); + subaddie_set_state(this, HUT_STATE_2_DESTROYED); + this->position_y -= 160.0f; + return; + } } switch (this->state) { @@ -83,7 +117,7 @@ void chhut_update(Actor *this) { if (150.0f < diff_pos[1] && player_getActiveHitbox(this->marker) == HITBOX_1_BEAK_BUSTER - && func_8028F20C() + && player_isStableWithExtraSteps() && LENGTH_VEC3F(diff_pos) < 350.0f ){ diff_pos[0] = this->position_x; @@ -97,14 +131,21 @@ void chhut_update(Actor *this) { __spawnQueue_add_1((GenFunction_1) __chhut_spawnExplosion, (uintptr_t)this->marker); bundle_setYaw(this->yaw); - if (mm_hut_smash_count < 5) { - __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, D_803898D8[mm_hut_smash_count], *(s32 * )(&diff_pos[0]), *(s32 * )(&diff_pos[1]), *(s32 * )(&diff_pos[2])); + smashIndex = port_hutSmash_countForCurrentLevel(); + if (smashIndex < 5) { + __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, mm_hut_bundles[smashIndex], *(s32 * )(&diff_pos[0]), *(s32 * )(&diff_pos[1]), *(s32 * )(&diff_pos[2])); } else { jiggy_spawn(JIGGY_5_MM_HUTS, diff_pos); } - mm_hut_smash_count = (mm_hut_smash_count + 1) % 6; + port_hutSmash_record((s32)this->position_x, (s32)this->position_y, (s32)this->position_z, smashIndex); + } + else { + loot = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); + if (loot >= 0) { + chhut_replaySmash(this, loot); + } } break; diff --git a/src/MM/ch/juju.c b/src/MM/ch/juju.c index 992c8553f..0dda2dd3c 100644 --- a/src/MM/ch/juju.c +++ b/src/MM/ch/juju.c @@ -20,7 +20,6 @@ void chjuju_update(Actor *this); Actor *chjuju_draw(ActorMarker *, Gfx **, Mtx **, Vtx **); /* .bss */ -u8 MM_pad_80389C80[0x10]; s32 mm_juju_count; /* .data */ @@ -210,7 +209,7 @@ void chjuju_update(Actor *this) { switch (jujuPtr->animation_state) { case JUJU_ANIMATION_STATE_1_YAWING: //L80389624 previous_yaw = this->yaw; - this->yaw += ((11 - mm_juju_count * 2) * time_getDelta() * 60.0f) / 2; + this->yaw += ((11 - mm_juju_count * 2) * time_getDelta() * (float)FRAMERATE) / 2; if (360.0f < this->yaw) { has_completed_full_turn = true; diff --git a/src/MM/ch/jujuhitbox.c b/src/MM/ch/jujuhitbox.c index 54fb88cc6..8fb9b5c0d 100644 --- a/src/MM/ch/jujuhitbox.c +++ b/src/MM/ch/jujuhitbox.c @@ -4,11 +4,18 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + /* extern functions */ void __chjujuhitbox_initialize_all(ActorMarker *, s32); s32 subaddie_getYawToPlayer(Actor *); void func_80353580(ActorMarker *); +static s32 mm_juju_sharedKnocked(void) { + s32 bits = port_puzzleStep_get(ANCHOR_PUZZLE_MM_JUJU) & 0xF; + return (bits & 1) + ((bits >> 1) & 1) + ((bits >> 2) & 1) + ((bits >> 3) & 1); +} + typedef struct juju_hitbox_s { u8 pad0[0x4]; s32 unk4; @@ -75,6 +82,7 @@ void func_80388BEC(NodeProp *node, ActorMarker *marker) { if (func_80388B30(temp_v0, 90.0f)) { closest_actor->state = 1; ((ActorLocal_JujuHitbox *) &closest_actor->local)->unk4++; + port_puzzleStep_orBits(ANCHOR_PUZZLE_MM_JUJU, (1 << ((ActorLocal_JujuHitbox *) &closest_actor->local)->unk4) - 1); func_803892A8(((ActorLocal_JujuHitbox *) &closest_actor->local)->jujus); func_80353580(marker); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x58, *(s32 *)&position[0], *(s32 *)&position[1], *(s32 *)&position[2]); @@ -133,7 +141,12 @@ void chjujuhitbox_update(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; - __spawnQueue_add_2((void (*)(void)) __chjujuhitbox_initialize_all, (uintptr_t)this->marker, jujuCtlPtr->unk4); + jujuCtlPtr->unk4 = mm_juju_sharedKnocked(); + if (jujuCtlPtr->unk4 >= 4) { + marker_despawn(this->marker); + return; + } + __spawnQueue_add_2((GenFunction_2) __chjujuhitbox_initialize_all, (uintptr_t)this->marker, jujuCtlPtr->unk4); __chjujuhitbox_playRubbingSfx(this); return; } @@ -161,6 +174,12 @@ void chjujuhitbox_update(Actor *this) { __chjuju_updateCount(jujuCtlPtr->jujus); } + if (this->state == 3 && jujuCtlPtr->unk4 < mm_juju_sharedKnocked()) { + this->state = 1; + jujuCtlPtr->unk4++; + func_803892A8(jujuCtlPtr->jujus); + } + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_9_JUJU_HAS_HALF_TURNED)) { __chjujuhitbox_playRubbingSfx(this); mapSpecificFlags_set(MM_SPECIFIC_FLAG_9_JUJU_HAS_HALF_TURNED, false); diff --git a/src/MM/ch/lmonkey.c b/src/MM/ch/lmonkey.c index a44f276df..90f57159d 100644 --- a/src/MM/ch/lmonkey.c +++ b/src/MM/ch/lmonkey.c @@ -44,7 +44,7 @@ void __chlmonkey_updateBringOrange(Actor **this_ptr) { player_setCarryObjectPoseInHorizontalRadius((*this_ptr)->position, 800.0f, ACTOR_29_ORANGE_COLLECTIBLE, this_ptr); if (subaddie_playerIsWithinSphereAndActive(*this_ptr, 345) && - bacarry_get_markerId() == MARKER_36_ORANGE_COLLECTIBLE && + bacarry_getMarkerId() == MARKER_36_ORANGE_COLLECTIBLE && player_throwCarriedObject()) { func_8028FA34(0xc6, *this_ptr); @@ -98,20 +98,22 @@ void chlmonkey_update(Actor *this) { func_80343DEC(this); } else {//L80388630 - if (subaddie_playerIsWithinSphereAndActive(this, 700) && !gcdialog_hasCurrentTextId()) { + if (subaddie_playerIsWithinSphereAndActive(this, 700) && !gcdialog_hasCurrentTextId() && + EventSystem_Should(VB_MM_CHIMPY_NOISE, true)) { __chlmonkey_playRandomNoise(this); }//L8038865C switch (this->state) { case LMONKEY_STATE_1_IDLE://L80388690 - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED)) { + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED) || jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY)) { subaddie_set_state(this, LMONKEY_STATE_4_LEAVING); - if (!jiggyscore_isCollected(JIGGY_9_MM_CHIMPY)) { - gcdialog_showDialog(ASSET_B40_DIALOG_CHIMPY_COMPLETE, 0xE, this->position, this->marker, __chlmonkey_complete, NULL); + if (jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY)) { + mapSpecificFlags_set(MM_SPECIFIC_FLAG_4_SHAKE, true); + subaddie_set_state(this, LMONKEY_STATE_3_WALKING); } else {//L803886E8 - __chlmonkey_complete(this->marker, ASSET_B40_DIALOG_CHIMPY_COMPLETE, -1); + gcdialog_showDialog(ASSET_B40_DIALOG_CHIMPY_COMPLETE, 0xE, this->position, this->marker, __chlmonkey_complete, NULL); }//L80388898 } else { diff --git a/src/MM/ch/orange.c b/src/MM/ch/orange.c index b5ff73df1..3260f8b81 100644 --- a/src/MM/ch/orange.c +++ b/src/MM/ch/orange.c @@ -31,7 +31,7 @@ f32 D_80389A00[3] = {0.0f, 0.0f, 0.0f}; void __chorange_collisionCallback(ActorMarker *marker, ActorMarker *other_marker) { if (!player_isDead() && !mapSpecificFlags_get(MM_SPECIFIC_FLAG_8_HIT_WITH_ORANGE) && - gcdialog_showDialog(ASSET_B3A_DIALOG_CONGA_HITS_PLAYER, 0, 0, 0, NULL, NULL)) { + gcdialog_showDialog(VER_SELECT(ASSET_B3A_DIALOG_CONGA_HITS_PLAYER, 0x958, 0, 0), 0, 0, 0, NULL, NULL)) { mapSpecificFlags_set(MM_SPECIFIC_FLAG_8_HIT_WITH_ORANGE, true); } diff --git a/src/MM/ch/orangepad.c b/src/MM/ch/orangepad.c index cca3856a3..e87b5a5b6 100644 --- a/src/MM/ch/orangepad.c +++ b/src/MM/ch/orangepad.c @@ -1,28 +1,29 @@ -// BanjoDecomp: orangepad.c +// BanjoDecomp: MM/ch/orangepad.c +#include #include "functions.h" #include "variables.h" -#include +#include "bk_math.h" // [port] TUPLE_ASSIGN + +#include "core2/staticcamera.h" -#include +#include "conga.h" +#include "orangepad.h" -/* extern functions */ -void actor_update_func_80326224(Actor *); -extern void particleEmitter_func_802EFA20(ParticleEmitter *, f32, f32); +extern void port_breakable_recordBreak(s32 markerId, s32 x, s32 y, s32 z); +extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); -/* public functions */ -void chorangepad_update(Actor *); +void chOrangePad_update(Actor *); -/* .data */ ActorInfo chOrangePadInfo = { MARKER_66_ORANGE_PAD, ACTOR_57_ORANGE_PAD, ASSET_2EB_MODEL_ORANGE_PAD, 0, NULL, - chorangepad_update, actor_update_func_80326224, actor_draw, + chOrangePad_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -/*.code */ -void __chorangepad_spawnJiggy(s32 x, s32 y, s32 z) { +void spawnJiggy(s32 x, s32 y, s32 z) { f32 pos[3]; + TUPLE_ASSIGN(pos, x, y, z); jiggy_spawn(JIGGY_8_MM_ORANGE_PADS, pos); } @@ -32,101 +33,115 @@ void handleOrangeCollision(ActorMarker *marker) { Actor *closest_orange_pad; f32 position[3]; ParticleEmitter *p_ctrl; - s32 temp_a0; + s32 camera_id; - position[0] = marker->propPtr->x; + position[0] = marker->propPtr->x; // [port] ActorProp uses x/y/z members position[1] = marker->propPtr->y; position[2] = marker->propPtr->z; - closest_orange_pad = actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, 1, &distance_to_orange_pad); + closest_orange_pad = actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, ORANGE_PAD_STATE_HIT, &distance_to_orange_pad); + + if (!closest_orange_pad || 500.0f < distance_to_orange_pad) { + return; + } + + closest_orange_pad->state = ORANGE_PAD_STATE_HIT; + port_breakable_recordBreak((s32)closest_orange_pad->marker->id, (s32)closest_orange_pad->position[0], (s32)closest_orange_pad->position[1], (s32)closest_orange_pad->position[2]); + + if (actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, ORANGE_PAD_STATE_HIT, &distance_to_orange_pad)) { + // There are still other pads on the ground, play progress ding + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 22000); + } else { // No more pads, dispense jiggy + camera_id = (closest_orange_pad->secondaryId == ORANGE_PAD_RIGHT) ? MM_ORANGE_PAD_JIGGY_SPAWN_RIGHT + : (closest_orange_pad->secondaryId == ORANGE_PAD_LEFT) ? MM_ORANGE_PAD_JIGGY_SPAWN_LEFT + : MM_ORANGE_PAD_JIGGY_SPAWN_TOP; + + gcStaticCamera_activate(camera_id); - if (closest_orange_pad && !(500.0f < distance_to_orange_pad)) { - closest_orange_pad->state = 1; + position[1] += 50.0f; + timedFunc_set_3(0.6f, (GenFunction_3) spawnJiggy, (s32) position[0], (s32) position[1], (s32) position[2]); - if (actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, 1, &distance_to_orange_pad)) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 22000); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); + + if (!jiggyscore_isCollected(JIGGY_8_MM_ORANGE_PADS)) { + gcdialog_showDialog(VER_SELECT(ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY, 0x959, 0, 0), 4, NULL, NULL, NULL, NULL); } - else { - temp_a0 = (closest_orange_pad->secondaryId == 0x106) ? 0x10 - : (closest_orange_pad->secondaryId == 0x76) ? 0xf - : 0xe; - - gcStaticCamera_activate(temp_a0); - position[1] += 50.0f; - timedFunc_set_3(0.6f, (GenFunction_3) __chorangepad_spawnJiggy, (s32) position[0], (s32) position[1], (s32) position[2]); - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - - if (!jiggyscore_isCollected(JIGGY_8_MM_ORANGE_PADS)) { - gcdialog_showDialog(ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY, 4, NULL, NULL, NULL, NULL); - } - }// L803865D8 - - // Emmit sparkles - p_ctrl = partEmitMgr_newEmitter(30); - particleEmitter_setPosition(p_ctrl, closest_orange_pad->position); - particleEmitter_setModel(p_ctrl, ASSET_89F_MODEL_ORANGE_PARTICLE); - particleEmitter_setStartingScaleRange(p_ctrl, 0.09f, 0.19f); - particleEmitter_setFinalScaleRange(p_ctrl, 0.0f, 0.0f); - particleEmitter_setParticleVelocityRange(p_ctrl, -200.0f, 500.0f, -200.0f, 200.0f, 700.0f, 200.0f); - particleEmitter_setAccelerationRange(p_ctrl, 0.0f, -1200.0f, 0.0f, 0.0f, -1200.0f, 0.0f); - particleEmitter_setAngularVelocityRange(p_ctrl, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f); - particleEmitter_setSpawnIntervalRange(p_ctrl, 0.0f, 0.01f); - particleEmitter_setParticleLifeTimeRange(p_ctrl, 4.0f, 4.0f); - particleEmitter_func_802EF9F8(p_ctrl, 0.01f); - particleEmitter_func_802EFA18(p_ctrl, 3); - particleEmitter_func_802EFA20(p_ctrl, 1.0f, 1.3f); - particleEmitter_emitN(p_ctrl, 30); } + + // Spawn orange particles + p_ctrl = partEmitMgr_newEmitter(ORANGE_PARTICLE_COUNT); + + particleEmitter_setPosition(p_ctrl, closest_orange_pad->position); + particleEmitter_setModel(p_ctrl, ASSET_89F_MODEL_ORANGE_PARTICLE); + particleEmitter_setStartingScaleRange(p_ctrl, 0.09f, 0.19f); + particleEmitter_setFinalScaleRange(p_ctrl, 0.0f, 0.0f); + particleEmitter_setParticleVelocityRange(p_ctrl, -200.0f, 500.0f, -200.0f, 200.0f, 700.0f, 200.0f); + particleEmitter_setAccelerationRange(p_ctrl, 0.0f, -1200.0f, 0.0f, 0.0f, -1200.0f, 0.0f); + particleEmitter_setAngularVelocityRange(p_ctrl, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f); + particleEmitter_setSpawnIntervalRange(p_ctrl, 0.0f, 0.01f); + particleEmitter_setParticleLifeTimeRange(p_ctrl, 4.0f, 4.0f); + particleEmitter_func_802EF9F8(p_ctrl, 0.01f); + particleEmitter_func_802EFA18(p_ctrl, 3); + particleEmitter_func_802EFA20(p_ctrl, 1.0f, 1.3f); + + particleEmitter_emitN(p_ctrl, ORANGE_PARTICLE_COUNT); } -void chOrangePad_handleOrangeCollision(NodeProp *arg0, ActorMarker *arg1) { - handleOrangeCollision(arg1); +void chOrangePad_handleOrangeCollision(s32 _, ActorMarker *marker) { + handleOrangeCollision(marker); } -void chorangepad_update(Actor *this) { - Actor *closest_actor; +void chOrangePad_update(Actor *this) { + Actor *conga; f32 unused; f32 min_distance; if (!this->initialized) { this->marker->propPtr->unk8_3 = 1; actor_collisionOff(this); - this->initialized = true; - }//L803867B0 + this->initialized = TRUE; + } if (!this->volatile_initialized) { - this->partnerActor = actorArray_findClosestActorFromActorId(this->position, 8, -1, &min_distance)->marker; - this->volatile_initialized = true; - }//L803867E0 + this->partnerActor = actorArray_findClosestActorFromActorId(this->position, ACTOR_8_CONGA, -1, &min_distance)->marker; + this->volatile_initialized = TRUE; + } + + // Anchor: a teammate already broke this pad — adopt the hit state. + if (this->state != ORANGE_PAD_STATE_HIT + && port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, + (s32)this->position[0], (s32)this->position[1], (s32)this->position[2])) { + this->state = ORANGE_PAD_STATE_HIT; + } if (this->partnerActor) { - closest_actor = marker_getActor(this->partnerActor); + conga = marker_getActor(this->partnerActor); } - if (subaddie_playerIsWithinSphereAndActive(this, 0x28) && - !player_movementGroup() && - !mapSpecificFlags_get(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS) && - closest_actor->state != 3) { + if (subaddie_playerIsWithinSphereAndActive(this, CONGA_WARN_DISTANCE) + && !player_movementGroup() + && !mapSpecificFlags_get(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS) + && conga->state != CONGA_STATE_MOPEY) { - if (gcdialog_showDialog(ASSET_B3D_DIALOG_CONGA_TOUCH_PAD, 0, NULL, NULL, NULL, NULL)) { - mapSpecificFlags_set(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS, true); + if (gcdialog_showDialog(VER_SELECT(ASSET_B3D_DIALOG_CONGA_TOUCH_PAD, 0x95B, 0, 0), 0, NULL, NULL, NULL, NULL)) { + mapSpecificFlags_set(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS, TRUE); } } - if (this->state == 1) { + if (this->state == ORANGE_PAD_STATE_HIT) { if (this->lifetime_value < 72.0f) { commonParticle_add(this->marker, 5, func_80329904); commonParticle_new(9, this->marker->unk14_21); } - this->lifetime_value = MIN(255.0, this->lifetime_value + 7.0); + // Tick up respawn by 7 every update + this->lifetime_value = MIN(ORANGE_PAD_HIT_LIFETIME, this->lifetime_value + ORANGE_PAD_LIFETIME_INCREMENT); - if (255.0 == this->lifetime_value) { + if (ORANGE_PAD_HIT_LIFETIME == this->lifetime_value) { marker_despawn(this->marker); } - } - else { - }//L80386928 + } else { } // Can't remove the else ;.; + // If hit, then fade out actor_setOpacity(this, 0xFF - (s32) this->lifetime_value); -}//*/ +} diff --git a/src/MM/ch/orangepad.h b/src/MM/ch/orangepad.h new file mode 100644 index 000000000..7bf31b536 --- /dev/null +++ b/src/MM/ch/orangepad.h @@ -0,0 +1,14 @@ +// BanjoDecomp: MM/ch/orangepad.h +#define ORANGE_PARTICLE_COUNT 30 +#define CONGA_WARN_DISTANCE 0x28 +#define ORANGE_PAD_HIT_LIFETIME 255.0 +#define ORANGE_PAD_LIFETIME_INCREMENT 7.0 + +enum orange_pad_state_e { + ORANGE_PAD_STATE_HIT = 1 +}; + +enum orange_pad_ids { + ORANGE_PAD_LEFT = 0x76, + ORANGE_PAD_RIGHT = 0x106 +}; diff --git a/src/MM/checksums.c b/src/MM/checksums.c new file mode 100644 index 000000000..4a743d96f --- /dev/null +++ b/src/MM/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: MM/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsMM; diff --git a/src/MM/crc.c b/src/MM/crc.c index 425dffd03..585d2b88d 100644 --- a/src/MM/crc.c +++ b/src/MM/crc.c @@ -4,11 +4,9 @@ #include "functions.h" #include "variables.h" -/* .data */ -//TODO Implement CRC calculation in Makefile(?) -u32 D_803899C0 = 0x000C740C; //MM.code CRC1 -u32 D_803899C4 = 0xCD249CB3; //MM.code CRC2 -u32 D_803899C8 = 0x0000D44F; //MM.data CRC1 (with this value = 0) +s32 D_803899C0 = VER_SELECT(0x000C740C, 0x000C896A, 0, 0); // MM_TEXT_CRC1 +s32 D_803899C4 = VER_SELECT(0xCD249CB3, 0xED04CB8F, 0, 0); // MM_TEXT_CRC2 +s32 D_803899C8 = VER_SELECT(0x0000D44F, 0x0000D9E8, 0, 0); // MM_DATA_CRC1 void chmumbo_func_802D1724(void); diff --git a/src/MM/actor_spawninit.c b/src/MM/mmspawnqueue.c similarity index 97% rename from src/MM/actor_spawninit.c rename to src/MM/mmspawnqueue.c index e348cf674..2642fae14 100644 --- a/src/MM/actor_spawninit.c +++ b/src/MM/mmspawnqueue.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_24C0.c +// BanjoDecomp: MM/mmspawnqueue.c /*!!!DONE!!!*/ #include #include "functions.h" diff --git a/src/MMM/bathroom_particles.c b/src/MMM/bathroom_particles.c index 5b528374f..c8b3d68bf 100644 --- a/src/MMM/bathroom_particles.c +++ b/src/MMM/bathroom_particles.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (core2 origin - unknown exact file) +// BanjoDecomp: core2/code_13A00.c #include #include "functions.h" #include "variables.h" @@ -30,7 +30,7 @@ void func_8029A990(void){ else func_8029C304(1); - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); plyr_pos[1] = floor_getCurrentFloorYPosition(); pCtrl = func_802F4094(plyr_pos, 25.0f); particleEmitter_setParticleVelocityRange(pCtrl, @@ -119,7 +119,7 @@ void func_8029AC34(Struct5Ds *arg0, s32 arg1){ void func_8029ACD4(void){ f32 plyr_pos[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); func_802F4894(D_8037D190, plyr_pos); func_802F4884( D_8037D190, func_80294660(), floor_getCurrentFloorYPosition()); } diff --git a/src/MMM/bss_pad.c b/src/MMM/bss_pad.c deleted file mode 100644 index dfa4ab11e..000000000 --- a/src/MMM/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_D_8038C4C0[0x10]; diff --git a/src/MMM/ch/flowerpot.c b/src/MMM/ch/cemetarypot.c similarity index 73% rename from src/MMM/ch/flowerpot.c rename to src/MMM/ch/cemetarypot.c index f1b13f9df..05989845a 100644 --- a/src/MMM/ch/flowerpot.c +++ b/src/MMM/ch/cemetarypot.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_DC0.c +// BanjoDecomp: MMM/ch/cemetarypot.c #include #include "functions.h" #include "variables.h" @@ -6,6 +6,9 @@ /* public functions */ void chFlowerpot_update(Actor *this); +extern void port_breakable_recordBreak(s32 markerId, s32 x, s32 y, s32 z); +extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); + /* .data */ enum chFlowerpot_state_e { FLOWER_POT_STATE_1_IDLE = 1, @@ -37,11 +40,11 @@ void chFlowerpot_setRemaining(s32 arg0) { void MMM_func_803871FC(Actor *this) { switch (this->state) { case FLOWER_POT_STATE_1_IDLE: - func_8033A45C(3, false); + modelRender_setAppendageVisibility(3, false); break; case FLOWER_POT_STATE_2_FLOWERED: - func_8033A45C(3, true); + modelRender_setAppendageVisibility(3, true); break; } @@ -60,6 +63,14 @@ void chFlowerpot_update(Actor *this) { this->unk130 = MMM_func_803871FC; } + // Anchor: teammate flowered this pot - match visually without decrementing the count. + if (this->state == FLOWER_POT_STATE_1_IDLE + && port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, + (s32)this->position[0], (s32)this->position[1], (s32)this->position[2])) { + subaddie_set_state(this, FLOWER_POT_STATE_2_FLOWERED); + anctrl_setPlaybackType(this->anctrl, ANIMCTRL_ONCE); + } + switch (this->state) { case FLOWER_POT_STATE_1_IDLE: anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); @@ -84,6 +95,7 @@ bool chFlowerpot_eggCollision(ActorMarker *marker) { subaddie_set_state(actor, FLOWER_POT_STATE_2_FLOWERED); anctrl_setPlaybackType(actor->anctrl, ANIMCTRL_ONCE); + port_breakable_recordBreak((s32)marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); remaining = chFlowerpot_getRemaining(); if (remaining != 0) { diff --git a/src/MMM/ch/loggo.c b/src/MMM/ch/loggo.c index c56424ce9..b5fa97e95 100644 --- a/src/MMM/ch/loggo.c +++ b/src/MMM/ch/loggo.c @@ -42,7 +42,7 @@ void __chLoggo_collide(ActorMarker *this_marker, ActorMarker *other_marker) { Actor *this = marker_getActor(this_marker); if ((player_getTransformation() == TRANSFORM_3_PUMPKIN) && !fileProgressFlag_get(FILEPROG_89_ENTERED_LOGGO_AS_PUMPKIN)) { - if (gcdialog_showDialog(ASSET_ADF_DIALOG_ENTER_LOGGO, 0x2B, this->position, this->marker, &__chLoggo_textCallback, 0) != 0) { + if (gcdialog_showDialog(VER_SELECT(ASSET_ADF_DIALOG_ENTER_LOGGO, 0x951, 0, 0), 0x2B, this->position, this->marker, &__chLoggo_textCallback, 0) != 0) { actor_collisionOff(this); fileProgressFlag_set(FILEPROG_89_ENTERED_LOGGO_AS_PUMPKIN, true); } @@ -56,8 +56,8 @@ void __chLoggo_collide(ActorMarker *this_marker, ActorMarker *other_marker) { } if ((player_getTransformation() == TRANSFORM_1_BANJO) && !fileProgressFlag_get(FILEPROG_88_TRIED_LOGGO_AS_BEAR)) { - if (gcdialog_showDialog(ASSET_ADE_DIALOG_LOGGO_AS_BEAR, 0x2A, this->position, NULL, NULL, NULL)) { - fileProgressFlag_set(FILEPROG_88_TRIED_LOGGO_AS_BEAR, true); + if (gcdialog_showDialog(VER_SELECT(ASSET_ADE_DIALOG_LOGGO_AS_BEAR, 0x950, 0, 0), 0x2A, this->position, NULL, NULL, NULL)) { + fileProgressFlag_set(FILEPROG_88_TRIED_LOGGO_AS_BEAR, TRUE); } } } @@ -82,8 +82,8 @@ void chLoggo_update(Actor *this) { this->lifetime_value = 0.0f; if (!fileProgressFlag_get(FILEPROG_8A_EXITED_LOGGO) && levelSpecificFlags_get(LEVEL_FLAG_33_MMM_UNKNOWN)) { - if (gcdialog_showDialog(ASSET_AE0_DIALOG_EXIT_LOGGO, 4, NULL, NULL, NULL, NULL)) { - fileProgressFlag_set(FILEPROG_8A_EXITED_LOGGO, true); + if (gcdialog_showDialog(VER_SELECT(ASSET_AE0_DIALOG_EXIT_LOGGO, 0x952, 0, 0), 4, NULL, NULL, NULL, NULL)) { + fileProgressFlag_set(FILEPROG_8A_EXITED_LOGGO, TRUE); } } } diff --git a/src/MMM/ch/napper.c b/src/MMM/ch/napper.c index fc1e928c4..6497c4eb4 100644 --- a/src/MMM/ch/napper.c +++ b/src/MMM/ch/napper.c @@ -66,8 +66,8 @@ void func_80386ACC(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *this = marker_getActor(this_marker); if(!this->has_met_before){ - if(gcdialog_showDialog(0xad8, 0, NULL, NULL, NULL, NULL)){ - this->has_met_before = true; + if(gcdialog_showDialog(VER_SELECT(0xAD8, 0x94A, 0, 0), 0, NULL, NULL, NULL, NULL)){ + this->has_met_before = TRUE; } } } @@ -77,14 +77,14 @@ Actor *chnapper_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ ActorLocal_Napper *local = (ActorLocal_Napper *)&this->local; if(this->state == 1){ - func_8033A45C(1, true); - func_8033A45C(2, false); - func_8033A45C(3, false); + modelRender_setAppendageVisibility(1, true); + modelRender_setAppendageVisibility(2, false); + modelRender_setAppendageVisibility(3, false); } else { - func_8033A45C(1, false); - func_8033A45C(2, BOOL(local->unk10)); - func_8033A45C(3, (local->unk10) ? false : true); + modelRender_setAppendageVisibility(1, false); + modelRender_setAppendageVisibility(2, BOOL(local->unk10)); + modelRender_setAppendageVisibility(3, (local->unk10) ? false : true); } if(this->state == 1){ //set model alpha diff --git a/src/MMM/ch/portrait.c b/src/MMM/ch/portrait.c index e7a7d9e9d..f7e68c1a3 100644 --- a/src/MMM/ch/portrait.c +++ b/src/MMM/ch/portrait.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_2F60.c +// BanjoDecomp: MMM/ch/portrait.c #include #include "functions.h" #include "variables.h" @@ -63,7 +63,7 @@ ActorInfo chPortraitMinion = { /* .code */ Actor *chPortrait_draw(ActorMarker *marker, Gfx **graphics, Mtx **matrix, Vtx **vertex) { - func_8033A45C(3, marker_getActor(marker)->unk38_31); + modelRender_setAppendageVisibility(3, marker_getActor(marker)->unk38_31); return actor_draw(marker, graphics, matrix, vertex); } diff --git a/src/MMM/ch/portrait_chompa.c b/src/MMM/ch/portraitchompa.c similarity index 98% rename from src/MMM/ch/portrait_chompa.c rename to src/MMM/ch/portraitchompa.c index 6603137f1..788572ddf 100644 --- a/src/MMM/ch/portrait_chompa.c +++ b/src/MMM/ch/portraitchompa.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_16B0.c +// BanjoDecomp: MMM/ch/portraitchompa.c #include #include "functions.h" #include "variables.h" @@ -100,7 +100,7 @@ void __chChompa_die(ActorMarker *this_marker, ActorMarker *other_marker) { chChompa_setState(this, CHOMPA_STATE_5_DYING); } -void __chChompa_spwanPortrait(ActorMarker *marker) { +void __chChompa_spawnPortrait(ActorMarker *marker) { Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, marker)); enum asset_e portrait_id; Actor *portrait; @@ -206,7 +206,7 @@ void chChompa_update(Actor *this) { this->volatile_initialized = true; this->unk16C_0 = true; marker_setCollisionScripts(this->marker, NULL, __chChompa_hit, __chChompa_die); - __spawnQueue_add_1((GenFunction_1) __chChompa_spwanPortrait, (uintptr_t)this->marker); + __spawnQueue_add_1((GenFunction_1) __chChompa_spawnPortrait, (uintptr_t)this->marker); chChompa_setState(this, this->state < CHOMPA_STATE_5_DYING ? CHOMPA_STATE_1_IDLE : CHOMPA_STATE_6_DEAD); }//L803880B4 diff --git a/src/MMM/ch/limbo.c b/src/MMM/ch/skeleton.c similarity index 95% rename from src/MMM/ch/limbo.c rename to src/MMM/ch/skeleton.c index c07aee95d..f0d6464fa 100644 --- a/src/MMM/ch/limbo.c +++ b/src/MMM/ch/skeleton.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (core2 origin - unknown exact file) +// BanjoDecomp: core2/ch/skeleton.c #include #include "functions.h" #include "variables.h" @@ -41,7 +41,7 @@ void func_8035CCA0(ParticleEmitter *pCtrl, Actor *this, enum asset_e model_id) { } -void chskeleton_despawn(ActorMarker *marker, s32 arg1) { +void chLimbo_die(ActorMarker *marker, s32 arg1) { Actor *this; this = marker_getActor(marker); @@ -79,7 +79,7 @@ static void _chskeleton_init(Actor *this) { local->exitInvulnerableStateVolume = 1.0f; local->unkC_28 = true; local->hitFunction = (void (*)(ActorMarker *, ActorMarker *)) humanoidBaddie_enterInvulnerableState; - local->dieFunction = (void (*)(ActorMarker *, ActorMarker *)) chskeleton_despawn; + local->dieFunction = (void (*)(ActorMarker *, ActorMarker *)) chLimbo_die; } diff --git a/src/MMM/ch/tumblar.c b/src/MMM/ch/tumblar.c index 9a22036b5..6a234fe65 100644 --- a/src/MMM/ch/tumblar.c +++ b/src/MMM/ch/tumblar.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_47D0.c +// BanjoDecomp: MMM/ch/tumblar.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -128,7 +128,7 @@ void __chTumblar_congratulationTextCallback(ActorMarker *marker, enum asset_e te void chTumblar_congratulate(void *arg0_, s32 arg1) { Struct_MMM_47D0_0 *arg0 = (Struct_MMM_47D0_0 *)arg0_; - gcdialog_showDialog(ASSET_ADB_DIALOG_TUMBLAR_COMPLETE, 4, NULL, arg0->jiggy_marker, __chTumblar_congratulationTextCallback, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_ADB_DIALOG_TUMBLAR_COMPLETE, 0x94D, 0, 0), 4, NULL, arg0->jiggy_marker, __chTumblar_congratulationTextCallback, NULL); arg0->state = TUMBLAR_STATE_1_CONGRATULATING; } @@ -221,8 +221,8 @@ void chTumblar_update(Struct_MMM_47D0_0 *arg0, Struct68s *arg1, f32 tick) { func_8035179C_copyPosition(arg1, position); if (!mapSpecificFlags_get(MMM_SPECIFIC_FLAG_0_UNKNOWN) && arg0->state == TUMBLAR_STATE_0_IDLE && ml_vec3f_horizontal_distance_zero_likely(position, plyr_pos) < 250.0f) { - if (gcdialog_showDialog(ASSET_ADA_DIALOG_TUMBLAR_MEET, 0, NULL, NULL, NULL, NULL)) { - mapSpecificFlags_set(0, true); + if (gcdialog_showDialog(VER_SELECT(ASSET_ADA_DIALOG_TUMBLAR_MEET, 0x94C, 0, 0), 0, NULL, NULL, NULL, NULL)) { + mapSpecificFlags_set(0, TRUE); } } diff --git a/src/MMM/checksums.c b/src/MMM/checksums.c new file mode 100644 index 000000000..d501a3cda --- /dev/null +++ b/src/MMM/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: MMM/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsMMM; diff --git a/src/MMM/crc.c b/src/MMM/crc.c index 2df0fe00e..f8aca93a3 100644 --- a/src/MMM/crc.c +++ b/src/MMM/crc.c @@ -1,7 +1,8 @@ // BanjoDecomp: crc.c #include +#include "checksums.h" +#include "version.h" -u32 D_8038C300 = 0x00146061; -u32 D_8038C304 = 0xEC79D7B4; -u32 D_8038C308 = 0x0001B98D; -u32 D_8038C30C = 0x0; +s32 D_8038C300 = VER_SELECT(0x00146061, 0x00148214, 0, 0); // MMM_TEXT_CRC1 +s32 D_8038C304 = VER_SELECT(0xEC79D7B4, 0xE11088CE, 0, 0); // MMM_TEXT_CRC2 +s32 D_8038C308 = VER_SELECT(0x0001B98D, 0x0001C16B, 0, 0); // MMM_DATA_CRC1 diff --git a/src/MMM/minigame_organ.c b/src/MMM/minigame_organ.c index d9d1053d2..7333e0340 100644 --- a/src/MMM/minigame_organ.c +++ b/src/MMM/minigame_organ.c @@ -179,7 +179,7 @@ void func_803898EC() { } void func_80389910() { - gcdialog_showDialog(ASSET_AD5_DIALOG_MOTZAND_COMPLETE, 0xE, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_AD5_DIALOG_MOTZAND_COMPLETE, 0x947, 0, 0), 0xE, NULL, NULL, MMM_func_80389810, NULL); timedFunc_set_2(0.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); timed_setStaticCameraToNode(2.0f, 0); timedFunc_set_0(2.1f, (GenFunction_0)MMM_func_803898A0); @@ -200,10 +200,10 @@ void organMinigame_setState(s32 next_state){ if (next_state == 2) { if (Me.pattern == 0) { Me.pattern = 1; - gcdialog_showDialog(ASSET_AD3_DIALOG_MOTZAND_MEET, 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_AD3_DIALOG_MOTZAND_MEET, 0x945, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); } else {//L80389A84 - gcdialog_showDialog(ASSET_AD6_DIALOG_MOTZAND_RETRY, 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_AD6_DIALOG_MOTZAND_RETRY, 0x948, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); } }//L80389A9C @@ -220,13 +220,13 @@ void organMinigame_setState(s32 next_state){ }//L80389AF4 if(next_state == 4){ - gcdialog_showDialog(ASSET_ADD_DIALOG_MOTZAND_MISS, 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_ADD_DIALOG_MOTZAND_MISS, 0x94F, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); func_80387720(Me.motzhand_marker); } if(next_state == 5){ Me.pattern++; - gcdialog_showDialog(ASSET_AD4_DIALOG_MOTZAND_HALFWAY, 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_AD4_DIALOG_MOTZAND_HALFWAY, 0x946, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); func_80387720(Me.motzhand_marker); } diff --git a/src/MMM/minigame_shed.c b/src/MMM/minigame_shed.c index 70ac8f5ea..83b217794 100644 --- a/src/MMM/minigame_shed.c +++ b/src/MMM/minigame_shed.c @@ -84,7 +84,7 @@ void func_8038A140(s32 arg0) { if (MMM_D_8038C510.unk8 == 1) { mapSpecificFlags_set(MMM_SPECIFIC_FLAG_3_UNKNOWN, 1); } - item_set(ITEM_0_HOURGLASS_TIMER, 75*60 - 1); + item_set(ITEM_0_HOURGLASS_TIMER, 75*FRAMERATE - 1); item_set(6, 1); } if (MMM_D_8038C510.unk8 == 3) { diff --git a/src/MMM/actor_spawninit.c b/src/MMM/mmmspawnqueue.c similarity index 55% rename from src/MMM/actor_spawninit.c rename to src/MMM/mmmspawnqueue.c index a8944bb97..21ea8bf39 100644 --- a/src/MMM/actor_spawninit.c +++ b/src/MMM/mmmspawnqueue.c @@ -1,24 +1,26 @@ -// BanjoDecomp: code_2040.c +// BanjoDecomp: MMM/mmmspawnqueue.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "actor.h" -extern ActorInfo D_8038BC28; -extern ActorInfo D_8038BCDC; -extern ActorInfo D_8038BC4C; -extern ActorInfo D_8038BDB4; -extern ActorInfo D_8038BDD8; -extern ActorInfo D_8038BDFC; -extern ActorInfo D_8038BC94; -extern ActorInfo D_8038BC70; -extern ActorInfo D_8038BD00; -extern ActorInfo D_8038BD24; -extern ActorInfo D_8038BD48; -extern ActorInfo D_8038BD6C; -extern ActorInfo D_8038BCB8; -extern ActorInfo D_8038BD90; +#include "core2/dustemitter.h" + +extern ActorInfo chShackDoor; +extern ActorInfo chMansionDoor; +extern ActorInfo chCellarHatch; +extern ActorInfo chChuchGateLeftLock; +extern ActorInfo chHedgeGateRightLock1; +extern ActorInfo chHedgeGateRightLock2; +extern ActorInfo chChuchDoor; +extern ActorInfo ch1881BarrelTop; +extern ActorInfo chXBarrelTop; +extern ActorInfo chMMMWindow; +extern ActorInfo chMMMWideWindow; +extern ActorInfo chMMMTallWindow; +extern ActorInfo chDiningDoor; +extern ActorInfo chMMMClockSwitch; extern ActorInfo chNapper; extern ActorInfo D_8038BA68; extern ActorInfo chMotzhand; @@ -32,20 +34,20 @@ extern ActorInfo chPortraitTeeHee; extern ActorInfo chPortraitMinion; extern ActorInfo D_80367E70; -extern ActorInfo D_80372C3C; +extern ActorInfo chPurpleTeeHee; extern void core1_7090_initSfxSource(s32, s32, s32, f32); extern void func_8025AE0C(s32, f32); extern BKCollisionTriangle *func_80309B48(f32[3], f32[3], f32[3], u32); -void func_802D3D54(Actor *this); -void func_803888B8(Actor *this); -Actor *func_80388994(ActorMarker *marker, Gfx ** gfx, Mtx **mtx, Vtx **vtx); -void func_80388BDC(Actor *this); -void func_80388FE4(Actor *this); -void func_80389004(Actor *this); -void func_80389060(Actor *this); -void func_803890B8(Actor *this); +void chMMMBreakableWooden_update(Actor *this); +void chMMMGate_update(Actor *this); +Actor *chMMMGate_draw(ActorMarker *marker, Gfx ** gfx, Mtx **mtx, Vtx **vtx); +void chChurchDoor_update(Actor *this); +void chMMMClockSwitch_update(Actor *this); +void chMMMWoodenDoor_update(Actor *this); +void chXBarrelTop_update(Actor *this); +void chMMMWindow_update(Actor *this); /* .data */ ActorAnimationInfo D_8038BBE0[] = { @@ -60,101 +62,101 @@ ActorAnimationInfo D_8038BBE0[] = { {0x00, 0.0f} }; -ActorInfo D_8038BC28 = { - 0x9C, 0x109, 0x3CD, +ActorInfo chShackDoor = { + MARKER_9C_SHACK_DOOR, ACTOR_109_SHACK_DOOR, ASSET_3CD_MODEL_SHACK_DOOR, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BC4C = { - 0x9E, 0x10B, 0x3CF, +ActorInfo chCellarHatch = { + MARKER_9E_CELLAR_HATCH, ACTOR_10B_CELLAR_HATCH, ASSET_3CF_MODEL_CELLAR_HATCH, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BC70 = { - 0x9A, 0xCB, 0x3CC, +ActorInfo ch1881BarrelTop = { + MARKER_9A_1881_BARREL_TOP, ACTOR_CB_1881_BARREL_TOP, ASSET_3CC_MODEL_1881_BARREL_TOP, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BC94 = { - 0xA2, 0x114, 0x3D3, +ActorInfo chChuchDoor = { + MARKER_A2_CHURCH_DOOR, ACTOR_114_CHURCH_DOOR, ASSET_3D3_MODEL_CHURCH_DOOR, 0x1, NULL, - func_80388BDC, actor_update_func_80326224, actor_drawFullDepth, + chChurchDoor_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BCB8 = { - 0xE7, 0x265, 0x4DA, +ActorInfo chDiningDoor = { + MARKER_E7_DINING_DOOR, ACTOR_265_DINING_DOOR, ASSET_4DA_MODEL_DINING_DOOR, 0x1, NULL, - func_80389004, actor_update_func_80326224, actor_drawFullDepth, + chMMMWoodenDoor_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BCDC = { - 0x9D, 0x10A, 0x3CE, +ActorInfo chMansionDoor = { + MARKER_9D_MANSION_DOOR, ACTOR_10A_MANSION_DOOR, ASSET_3CE_MODEL_MANSION_DOOR, 0x1, NULL, - func_80389004, actor_update_func_80326224, actor_drawFullDepth, + chMMMWoodenDoor_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BD00 = { - 0xD3, 0x191, 0x50B, +ActorInfo chXBarrelTop = { + MARKER_D3_X_BARREL_TOP, ACTOR_191_X_BARREL_TOP, ASSET_50B_MODEL_X_BARREL_TOP, 0x1, NULL, - func_80389060, actor_update_func_80326224, actor_drawFullDepth, + chXBarrelTop_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BD24 = { -0x123, 0x2E8, 0x4C0, +ActorInfo chMMMWindow = { + MARKER_123_WINDOW, ACTOR_2E8_WINDOW, ASSET_4C0_MODEL_WINDOW, 0x1, NULL, - func_803890B8, actor_update_func_80326224, actor_drawFullDepth, + chMMMWindow_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BD48 = { -0x1F2, 0x2E9, 0x4C1, +ActorInfo chMMMWideWindow = { + MARKER_1F2_WIDE_WINDOW, ACTOR_2E9_WIDE_WINDOW, ASSET_4C1_MODEL_WIDE_WINDOW, 0x1, NULL, - func_803890B8, actor_update_func_80326224, actor_drawFullDepth, + chMMMWindow_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BD6C = { -0x1F3, 0x2EA, 0x4C2, +ActorInfo chMMMTallWindow = { + MARKER_1F3_TALL_WINDOW, ACTOR_2EA_TALL_WINDOW, ASSET_4C2_MODEL_TALL_WINDOW, 0x1, NULL, - func_803890B8, actor_update_func_80326224, actor_drawFullDepth, + chMMMWindow_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BD90 = { - 0xFE, 0x1FD, 0x43D, +ActorInfo chMMMClockSwitch = { + MARKER_FE_MMM_CLOCK_SWITCH, ACTOR_1FD_MMM_CLOCK_SWITCH, ASSET_43D_MODEL_MMM_CLOCK_SWITCH, 0x1, D_8038BBE0, - func_80388FE4, actor_update_func_80326224, actor_draw, + chMMMClockSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BDB4 = { - 0x9F, 0x10C, 0x3D0, +ActorInfo chChuchGateLeftLock = { + MARKER_9F_CHURCH_GATE_LEFT_LOCK, ACTOR_10C_CHURCH_GATE_LEFT_LOCK, ASSET_3D0_MODEL_CHURCH_GATE_LEFT_LOCK, 0x1, NULL, - func_803888B8, actor_update_func_80326224, func_80388994, + chMMMGate_update, actor_update_func_80326224, chMMMGate_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BDD8 = { - 0xA0, 0x10D, 0x3D1, +ActorInfo chHedgeGateRightLock1 = { + MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1, ACTOR_10D_HEDGE_GATE_RIGHT_LOCK_1, ASSET_3D1_MODEL_HEDGE_GATE_RIGHT_LOCK_1, 0x1, NULL, - func_803888B8, actor_update_func_80326224, func_80388994, + chMMMGate_update, actor_update_func_80326224, chMMMGate_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_8038BDFC = { - 0xFF, 0x1FE, 0x43E, +ActorInfo chHedgeGateRightLock2 = { + MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2, ACTOR_1FE_HEDGE_GATE_RIGHT_LOCK_2, ASSET_43E_MODEL_HEDGE_GATE_RIGHT_LOCK_2, 0x1, NULL, - func_803888B8, actor_update_func_80326224, func_80388994, + chMMMGate_update, actor_update_func_80326224, chMMMGate_draw, 0, 0, 0.0f, 0 }; @@ -205,25 +207,28 @@ f32 MMM_func_80388430(Actor *this, s32 arg1, s32 arg2, f32 arg3) { s32 func_80388670(ActorMarker * this_marker, ActorMarker * other_marker){ Actor *this = marker_getActor(this_marker); - f32 sp20[3]; + f32 player_position[3]; - player_getPosition(sp20); + player_getPosition(player_position); switch(this->marker->id){ - case 0x9f: //L803886D0 - return (-335.0f < sp20[0] && sp20[0] < -200.0f) && (-2730.0f < sp20[2] && sp20[2] < -2400.0f); + case MARKER_9F_CHURCH_GATE_LEFT_LOCK: //L803886D0 + return (-335.0f < player_position[0] && player_position[0] < -200.0f) + && (-2730.0f < player_position[2] && player_position[2] < -2400.0f); - case 0xa0: //L80388770 - return (-2915.0f < sp20[0] && sp20[0] < -2584.0f) && ( -500.0f < sp20[2] && sp20[2] < -355.0f); + case MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1: //L80388770 + return (-2915.0f < player_position[0] && player_position[0] < -2584.0f) + && ( -500.0f < player_position[2] && player_position[2] < -355.0f); - case 0xFF: //L80388810 - return (5470.0f < sp20[0] && sp20[0] < 5920.0f) && ( -850.0f < sp20[2] && sp20[2] < -780.0f); + case MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2: //L80388810 + return (5470.0f < player_position[0] && player_position[0] < 5920.0f) + && ( -850.0f < player_position[2] && player_position[2] < -780.0f); default: return false; } } -void func_803888B8(Actor *this){ +void chMMMGate_update(Actor *this){ func_803300C0(this->marker, func_80388670); func_802D3CE8(this); this->lifetime_value = 0.0f; @@ -245,7 +250,7 @@ void func_803888B8(Actor *this){ } } -Actor *func_80388994(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { +Actor *chMMMGate_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { static s32 i; Actor *this; @@ -283,7 +288,7 @@ void func_80388B2C(Actor *this, f32 arg1) { } } -void func_80388BDC(Actor *this) { +void chChurchDoor_update(Actor *this) { f64 phi_f0; func_802D3D74(this); @@ -305,7 +310,8 @@ void func_80388BDC(Actor *this) { case 1: this->yaw = 0.0f; if(mapSpecificFlags_get(MMM_SPECIFIC_FLAG_0_UNKNOWN)) { - gcStaticCamera_activate(0x21); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, MMM_DOOR_CAM_CHURCH)) + gcStaticCamera_activate(0x21); subaddie_set_state(this, 6); core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.3f); mapSpecificFlags_set(MMM_SPECIFIC_FLAG_2_UNKNOWN, false); @@ -319,9 +325,9 @@ void func_80388BDC(Actor *this) { if ((this->yaw <= 270.0f) && (this->yaw > 260.0f)) { subaddie_set_state(this, 7U); this->yaw = 270.0f; - gcsfx_playAtSampleRate(0x7F); + gcsfx_play(0x7F); core1_7090_freeSfxSource(0); - func_802D68F0(0xE); + code_4C020_setHourglassTimer(0xE); item_set(6, 1); } break; @@ -335,10 +341,12 @@ void func_80388BDC(Actor *this) { if( (!this->unk38_31 && item_empty(ITEM_0_HOURGLASS_TIMER)) || ((this->unk38_31) && (this->lifetime_value == 0.0f)) ) { - if (!this->unk38_31) { - gcStaticCamera_activate(0x22); - } else { - gcStaticCamera_activate(0x23); + if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, MMM_DOOR_CAM_CHURCH)){ + if (!this->unk38_31) { + gcStaticCamera_activate(0x22); + } else { + gcStaticCamera_activate(0x23); + } } subaddie_set_state(this, 8); core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.3f); @@ -349,7 +357,7 @@ void func_80388BDC(Actor *this) { if ((this->yaw >= 0.0f) && (this->yaw < 10.0f)) { subaddie_set_state(this, 1U); this->yaw = 0.0f; - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); mapSpecificFlags_set(MMM_SPECIFIC_FLAG_0_UNKNOWN, false); core1_7090_freeSfxSource(0); if (!this->unk38_31) { @@ -358,30 +366,29 @@ void func_80388BDC(Actor *this) { } this->unk38_31 = 0; this->lifetime_value = 0.0f; - volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED); + progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED); } break; } } -void func_80388FE4(Actor *this) { +void chMMMClockSwitch_update(Actor *this) { func_802D4A9C(this,0); } -void func_80389004(Actor *this){ +void chMMMWoodenDoor_update(Actor *this){ func_802D3CE8(this); if (!this->volatile_initialized) { this->volatile_initialized = true; - - if (levelSpecificFlags_get(LEVEL_FLAG_2E_MMM_UNKNOWN)) { - marker_despawn(this->marker); - } + } + if (levelSpecificFlags_get(LEVEL_FLAG_2E_MMM_UNKNOWN)) { + marker_despawn(this->marker); } } -void func_80389060(Actor *this){ - if(!this->initialized && sns_get_item_state(SNS_ITEM_EGG_CYAN, true)){ +void chXBarrelTop_update(Actor *this){ + if(!this->initialized && sns_get_item_state(SNS_ITEM_EGG_CYAN, TRUE)){ marker_despawn(this->marker); } else{ @@ -389,26 +396,26 @@ void func_80389060(Actor *this){ } } -void func_803890B8(Actor *this) { - func_802D3D54(this); +void chMMMWindow_update(Actor *this) { + chMMMBreakableWooden_update(this); chTumblar_checkMMMChecksums(); } void MMM_func_803890E0(void){ - spawnableActorList_add(&D_8038BC28, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038BCDC, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038BC4C, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038BDB4, actor_new, ACTOR_FLAG_UNKNOWN_6); - spawnableActorList_add(&D_8038BDD8, actor_new, ACTOR_FLAG_UNKNOWN_6); - spawnableActorList_add(&D_8038BDFC, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038BC94, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038BC70, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038BD00, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8038BD24, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_8038BD48, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_8038BD6C, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_8038BCB8, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_8038BD90, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chShackDoor, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chMansionDoor, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCellarHatch, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chChuchGateLeftLock, actor_new, ACTOR_FLAG_UNKNOWN_6); + spawnableActorList_add(&chHedgeGateRightLock1, actor_new, ACTOR_FLAG_UNKNOWN_6); + spawnableActorList_add(&chHedgeGateRightLock2, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chChuchDoor, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&ch1881BarrelTop, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chXBarrelTop, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chMMMWindow, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&chMMMWideWindow, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&chMMMTallWindow, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&chDiningDoor, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&chMMMClockSwitch, actor_new, ACTOR_FLAG_UNKNOWN_3); spawnableActorList_add(&chNapper, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_12); spawnableActorList_add(&D_8038BA68, actor_new, ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chMotzhand, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_17); @@ -421,5 +428,5 @@ void MMM_func_803890E0(void){ spawnableActorList_add(&chPortraitTreeAndMoon, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_23); spawnableActorList_add(&chPortraitTeeHee, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_23); spawnableActorList_add(&chPortraitMinion, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_23); - spawnableActorList_add(&D_80372C3C, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chPurpleTeeHee, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_19); } diff --git a/src/MMM/napper_room.c b/src/MMM/napper_room.c index 30603b795..17f2d4264 100644 --- a/src/MMM/napper_room.c +++ b/src/MMM/napper_room.c @@ -55,7 +55,7 @@ void func_803895B0(s32 arg0) { } void func_803895D8(ActorMarker *caller, enum asset_e text_id, s32 arg2) { - if (text_id == 0xAD7) { + if (text_id == VER_SELECT(ASSET_AD7_DIALOG_NAPPER_AWAKE, 0x949, 0, 0)) { timed_playSfx(0.1f, SFX_3F5_UNKNOWN, 1.0f, 30000); timed_exitStaticCamera(1.5f); func_80324E38(1.5f, 0); @@ -82,7 +82,7 @@ void func_8038966C(void){ MMM_D_8038C4E0.unk2 = true; func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.2f, 1); - func_80324DBC(0.2f, 0xad9, 6, NULL, NULL, func_803895D8, NULL); + func_80324DBC(0.2f, VER_SELECT(ASSET_AD9_DIALOG_NAPPER_COMPLETE, 0x94B, 0, 0), 6, NULL, NULL, func_803895D8, NULL); }//L80389700 if(MMM_D_8038C4E0.unk1 != 1) @@ -109,8 +109,8 @@ void func_8038966C(void){ if (!levelSpecificFlags_get(LEVEL_FLAG_1B_MMM_UNKNOWN)) { func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.0f, 0); - func_80324DBC(0.0f, 0xad7, 6, NULL, NULL, func_803895D8, NULL); - levelSpecificFlags_set(LEVEL_FLAG_1B_MMM_UNKNOWN, true); + func_80324DBC(0.0f, VER_SELECT(ASSET_AD7_DIALOG_NAPPER_AWAKE, 0x949, 0, 0), 6, NULL, NULL, func_803895D8, NULL); + levelSpecificFlags_set(LEVEL_FLAG_1B_MMM_UNKNOWN, TRUE); } } } diff --git a/src/RBB/actor_spawninit.c b/src/RBB/actor_spawninit.c deleted file mode 100644 index c7492be54..000000000 --- a/src/RBB/actor_spawninit.c +++ /dev/null @@ -1,231 +0,0 @@ -// BanjoDecomp: code_640.c -#include -#include "core1/core1.h" -#include "functions.h" -#include "variables.h" -#include "prop.h" -#include "actor.h" - -#include "port/Patches/Patches.h" - - -extern ActorInfo D_80390D20; -extern ActorInfo D_80390050; -extern ActorInfo D_80390200; -extern ActorInfo D_80390270; -extern ActorInfo D_80390D50; -extern ActorInfo D_803906E0; -extern ActorInfo D_80390738; -extern ActorInfo D_803907D0; -extern ActorInfo D_803907F4; -extern ActorInfo D_80390818; -extern ActorInfo D_8039083C; -extern ActorInfo D_803904C0; -extern ActorInfo D_803904E4; -extern ActorInfo D_80390508; -extern ActorInfo D_803903B0; -extern ActorInfo D_803903D4; -extern ActorInfo D_803903F8; -extern ActorInfo D_80390640; -extern ActorInfo D_80390664; -extern ActorInfo D_80390688; -extern ActorInfo D_803906B0; -extern ActorInfo D_803908C0; -extern ActorInfo D_803908E4; -extern ActorInfo D_80390908; -extern ActorInfo D_803909B0; -extern ActorInfo D_803909D4; -extern ActorInfo RBB_D_803909F8; -extern ActorInfo D_80390A50; -extern ActorInfo D_80390380; -extern ActorInfo D_80390A80; //anchorswitch -extern ActorInfo RBB_D_80390AB0; //dolphin -extern ActorInfo RBB_D_80390AE0; //anchor -extern ActorInfo RBB_D_80390B10; -extern ActorInfo D_80390B40; //rarewareflag -extern ActorInfo RBB_D_80390BD0; -extern ActorInfo D_80390BF4; -extern ActorInfo D_80390C18; -extern ActorInfo RBB_D_80390C3C; -extern ActorInfo RBB_D_80390CF0; -extern ActorInfo D_80390D88; -extern ActorInfo D_80390DAC; //TNTpart_IDStruct; -extern ActorInfo RBB_D_80390E00; -extern ActorInfo D_80390E34; -extern ActorInfo D_80390E58; -extern ActorInfo D_803900E0; -extern ActorInfo D_80390104; //captcabinwooddoor -extern ActorInfo D_80390128; -extern ActorInfo D_8039014C; -extern ActorInfo D_803901B8; -extern ActorInfo D_803901DC; -extern ActorInfo D_80390170;//skylight -extern ActorInfo D_80390194;//honeycombswitch - - - -extern void func_802D3D54(Actor *); - -void func_80386A7C(Actor *); -void func_80386BF8(Actor *arg0); -Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); - - -/* .data */ -ActorAnimationInfo D_803900C0[4] = { - {0, 0.0f}, - {0, 0.0f}, - {0xD4, 0.15f}, - {0xD5, 0.5f} -}; - -ActorInfo D_803900E0 = { - 0x107, 0x21D, 0x493, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80390104 = { - 0x108, 0x21C, 0x492, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80390128 = { - 0x22D, 0x266, 0x4BA, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_8039014C = { - 0x22E, 0x267, 0x4BB, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80390170 = { - 0x235, 0x23F, 0x4E2, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80390194 = { - 0x15F, 0x18F, 0x42F, 0x1, D_803900C0, - func_80386BF8, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803901B8 = { - 0x22F, 0x263, 0x4DB, 0x1, NULL, - func_80386A7C, actor_update_func_80326224, func_80386B9C, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803901DC = { - 0x230, 0x264, 0x4DE, 0x1, NULL, - func_80386A7C, actor_update_func_80326224, func_80386B9C, - 0, 0, 0.0f, 0 -}; - - -/* .code */ -s32 func_80386A30(f32 arg0[3]){ - s32 r; - - r = (arg0[0] < 0.0f)? 0 : 1; - - return ((arg0[2] < 0.0f)? 0 : 2) + r; -} - -void func_80386A7C(Actor *this){ - f32 viewport[3]; - s32 sp28; - s32 temp_v0; - - func_802D3D74(this); - this->depth_mode = 1; - viewport_getPosition_vec3f(viewport); - sp28 = func_80386A30(this->position); - temp_v0 = func_80386A30(viewport); - this->unk38_0 = 0; - // [port] Extend the bespoke distance cull with draw distance; quadrant occlusion below stays. - f32 cull = 8000.0f * port_drawDistanceMul(); - if(viewport[0] + cull < this->position_x || this->position_x < viewport[0] - cull) - return; - - if( !( (sp28 ^ temp_v0) & 2 - && (-5000.0f < viewport[0] && viewport[0] < 6000.0f) - && (viewport[2] < -600.0f || 600.0f < viewport[2]) - ) - && ( sp28 ^ temp_v0) != 3 - ){ - this->unk38_0 = 1; - } -} - -Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ - Actor *actor = marker_getActor(marker); - - return (actor->unk38_0) ? actor_drawFullDepth(marker, gdl, mptr, arg3): NULL; -} - -void func_80386BF8(Actor *arg0){ - if(!mapSpecificFlags_get(0) && honeycombscore_get(HONEYCOMB_F_RBB_BOAT_HOUSE)) - mapSpecificFlags_set(0, true); - func_802D4A9C(arg0, 0); -} - -void RBB_func_80386C48(void){ - spawnableActorList_add(&D_80390D20, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_80390050, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_80390200, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390270, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390D50, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_27); - spawnableActorList_add(&D_803906E0, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390738, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_803907D0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_803907F4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_80390818, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_8039083C, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_803904C0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_803904E4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_80390508, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_803903B0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_803903D4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_803903F8, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&D_80390640, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_80390664, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_80390688, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_803906B0, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_803908C0, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_803908E4, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390908, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_803909B0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_803909D4, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&RBB_D_803909F8, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_80390A50, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390380, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_80390A80, actor_new, ACTOR_FLAG_UNKNOWN_7); //anchorswitch - spawnableActorList_add(&RBB_D_80390AB0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //dolphin - spawnableActorList_add(&RBB_D_80390AE0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); //anchor - spawnableActorList_add(&RBB_D_80390B10, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390B40, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //rarewareflag - spawnableActorList_add(&RBB_D_80390BD0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_80390BF4, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_80390C18, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&RBB_D_80390C3C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&RBB_D_80390CF0, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390D88, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&D_80390DAC, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&RBB_D_80390E00, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390E34, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80390E58, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_803900E0, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_80390104, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //captcabinwooddoor - spawnableActorList_add(&D_80390128, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_8039014C, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_803901B8, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_803901DC, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_80390170, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //skylight - spawnableActorList_add(&D_80390194, actor_new, ACTOR_FLAG_UNKNOWN_3); //honeycombswitch -} diff --git a/src/RBB/bss_pad.c b/src/RBB/bss_pad.c deleted file mode 100644 index e0e22c075..000000000 --- a/src/RBB/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_RBB_80391270[0x10]; diff --git a/src/RBB/ch/anchor.c b/src/RBB/ch/anchor.c index 53acfa10c..1072d5bb8 100644 --- a/src/RBB/ch/anchor.c +++ b/src/RBB/ch/anchor.c @@ -3,28 +3,35 @@ #include "functions.h" #include "variables.h" -void func_8038BF28(Actor *this); +void chAnchor_update(Actor *this); /* .data */ -ActorInfo RBB_D_80390AE0 = { - 0x31, 0x1C9, 0x41D, 0x0, NULL, - func_8038BF28, NULL, actor_draw, +ActorInfo chAnchor = { + MARKER_31_ANCHOR, ACTOR_1C9_ANCHOR, ASSET_41D_MODEL_ANCHOR, + 0x0, NULL, + chAnchor_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; +enum chanchor_state_e { + CH_ANCHOR_STATE_0_NOT_INIT, + CH_ANCHOR_STATE_1_LOWERED, + CH_ANCHOR_STATE_2_RAISED +}; + /* .code */ -void RBB_func_8038BEA0(Actor *this, s32 arg1){ - if(arg1 == 1) +void chAnchor_setState(Actor *this, s32 next_state){ + if(next_state == CH_ANCHOR_STATE_1_LOWERED) skeletalAnim_set(this->unk148, ASSET_141_ANIM_ANCHOR_LOWERED, 0.0f, 5.5f); - if(arg1 == 2){ + if(next_state == CH_ANCHOR_STATE_2_RAISED){ skeletalAnim_set(this->unk148, ASSET_142_ANIM_ANCHOR_RISING, 0.0f, 8.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } - this->state = arg1; + this->state = next_state; } -void func_8038BF28(Actor *this){ +void chAnchor_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; this->position_x = -5100.0f; @@ -32,14 +39,16 @@ void func_8038BF28(Actor *this){ this->position_z = 1460.0f; this->marker->propPtr->unk8_3 = 1; this->yaw = 0.0f; - RBB_func_8038BEA0(this, 1); + chAnchor_setState(this, CH_ANCHOR_STATE_1_LOWERED); if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)){ marker_despawn(this->marker); } } else{ - if(this->state == 1 && mapSpecificFlags_get(8)){ - RBB_func_8038BEA0(this, 2); + if(this->state == CH_ANCHOR_STATE_1_LOWERED + && mapSpecificFlags_get(8)) + { + chAnchor_setState(this, CH_ANCHOR_STATE_2_RAISED); } } } diff --git a/src/RBB/ch/anchorctrl.c b/src/RBB/ch/anchorctrl.c index 3cc1bc66c..51d4fc3cc 100644 --- a/src/RBB/ch/anchorctrl.c +++ b/src/RBB/ch/anchorctrl.c @@ -4,21 +4,29 @@ #include "variables.h" -void __chAnchorCtrl_setState(Actor *this, s32 new_state); +void __chAnchorCtrl_setState(Actor *this, s32 next_state); void chAnchorCtrl_update(Actor *this); /* .data */ -ActorInfo RBB_D_80390B10 = { - 0x199, 0x1CB, 0x0, 0x0, NULL, +ActorInfo chAnchorCtrl = { + 0x199, 0x1CB, 0x0, + 0x0, NULL, chAnchorCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; +enum chanchorctrl_state_e { + CH_ANCHOR_CTRL_STATE_0_NOT_INIT, + CH_ANCHOR_CTRL_STATE_1_LOWERED, + CH_ANCHOR_CTRL_STATE_2_RAISING, + CH_ANCHOR_CTRL_STATE_3_RAISED +}; + /* .code */ void func_8038C000(void){ s32 sp1C = func_802F9AA8(SFX_7D_ANCHOR_LIFTING); - func_802FA060(sp1C, 0x6978, 0x6978, 0.0f); + func_802FA060(sp1C, 27000, 27000, 0.0f); func_802F9F80(sp1C, 0.5f, 7.0f, 0.5f); } @@ -29,26 +37,27 @@ void func_8038C058(void){ } void __chAnchorCtrl_spawnJiggy(ActorMarker *marker, enum asset_e id, s32 arg2){ - static f32 D_80390B34[3] = {-5100.0f, -2550.0f, 1470.0f}; + static f32 chAnchorCtrlJiggyPosition[3] = {-5100.0f, -2550.0f, 1470.0f}; Actor *actor = marker_getActor(marker); - jiggy_spawn(JIGGY_53_RBB_SNORKEL, D_80390B34); - timed_setStaticCameraToNode(0.5f, 0xb); - __chAnchorCtrl_setState(actor, 3); + jiggy_spawn(JIGGY_53_RBB_SNORKEL, chAnchorCtrlJiggyPosition); + timed_setStaticCameraToNode(0.5f, 0xB); + __chAnchorCtrl_setState(actor, CH_ANCHOR_CTRL_STATE_3_RAISED); } -void __chAnchorCtrl_setState(Actor *this, s32 new_state){ - if(new_state == 2){ +void __chAnchorCtrl_setState(Actor *this, s32 next_state){ + if(next_state == CH_ANCHOR_CTRL_STATE_2_RAISING) + { ncStaticCamera_setToNode(0xC); func_80324E38(0.0f, 3); timedFunc_set_0(1.0f, func_8038C000); - timedFunc_set_2(1.0f, (GenFunction_2)mapSpecificFlags_set, 8, true); + timedFunc_set_2(1.0f, (GenFunction_2)mapSpecificFlags_set, RBB_MAIN_SPECIFIC_FLAG_8_UNK, true); timed_playSfx(2.1f, SFX_3F6_RUBBING, 0.6f, 32700); - timedFunc_set_2(2.7f, (GenFunction_2)mapSpecificFlags_set, 4, true); + timedFunc_set_2(2.7f, (GenFunction_2)mapSpecificFlags_set, RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING, true); timedFunc_set_0(3.0f, func_8038C058); - func_80324DBC(3.0f, ASSET_B9C_DIALOG_SNORKEL_COMPLETE, 7, NULL, this->marker, __chAnchorCtrl_spawnJiggy, NULL); + func_80324DBC(3.0f, VER_SELECT(ASSET_B9C_DIALOG_SNORKEL_COMPLETE, 0x971, 0, 0), 7, NULL, this->marker, __chAnchorCtrl_spawnJiggy, NULL); }//L8038C1D8 - this->state = new_state; + this->state = next_state; } void chAnchorCtrl_update(Actor *this){ @@ -56,17 +65,19 @@ void chAnchorCtrl_update(Actor *this){ this->volatile_initialized = true; if (levelSpecificFlags_getSet(LEVEL_FLAG_30_RBB_UNKNOWN, false)) { - __chAnchorCtrl_setState(this, 2); + __chAnchorCtrl_setState(this, CH_ANCHOR_CTRL_STATE_2_RAISING); } else { - __chAnchorCtrl_setState(this, 1); + __chAnchorCtrl_setState(this, CH_ANCHOR_CTRL_STATE_1_LOWERED); } if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)) marker_despawn(this->marker); }//L8038C27C - if(this->state == 3 && !mapSpecificFlags_get(4)){ + if(this->state == CH_ANCHOR_CTRL_STATE_3_RAISED + && !mapSpecificFlags_get(RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING)) + { timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); timedFunc_set_0(0.0f, musicKeepsPlaying); diff --git a/src/RBB/ch/anchorswitch.c b/src/RBB/ch/anchorswitch.c index 92754c457..0d3aa33e2 100644 --- a/src/RBB/ch/anchorswitch.c +++ b/src/RBB/ch/anchorswitch.c @@ -6,33 +6,40 @@ void chAnchorSwitch_update(Actor *this); /* .data */ -ActorInfo D_80390A80 = { - 0x2F, 0x1C7, 0x41B, 0x0, NULL, +ActorInfo chAnchorSwitch = { + MARKER_2F_ANCHOR_SWITCH, ACTOR_1C7_ANCHOR_SWITCH, ASSET_41B_MODEL_ANCHOR_SWITCH, + 0x0, NULL, chAnchorSwitch_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; +enum chanchorswitch_state_e { + CH_ANCHOR_SWITCH_STATE_0_NOT_INIT, + CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED, + CH_ANCHOR_SWITCH_STATE_2_PRESSED +}; + /* .code */ -void __chAnchorSwitch_setState(Actor *this, s32 arg1){ - if(arg1 == 2){ - if(this->state == 1){ +void __chAnchorSwitch_setState(Actor *this, s32 next_state){ + if(next_state == CH_ANCHOR_SWITCH_STATE_2_PRESSED){ + if(this->state == CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED){ func_8030E6D4(SFX_90_SWITCH_PRESS); } actor_collisionOff(this); this->position_y -= 35.0f; - if(this->state == 1){ + if(this->state == CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED){ levelSpecificFlags_set(LEVEL_FLAG_30_RBB_UNKNOWN, true); volatileFlag_set(VOLATILE_FLAG_E, 1); timedFunc_set_0(1.0f, musicKeepsPlaying); timedFunc_set_3(1.0f, (GenFunction_3)transitionToMap, MAP_31_RBB_RUSTY_BUCKET_BAY, 0, 0); } } - this->state = arg1; + this->state = next_state; } void __chAnchorSwitch_press(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - __chAnchorSwitch_setState(actor, 2); + __chAnchorSwitch_setState(actor, CH_ANCHOR_SWITCH_STATE_2_PRESSED); } void chAnchorSwitch_update(Actor *this){ @@ -41,8 +48,8 @@ void chAnchorSwitch_update(Actor *this){ this->marker->propPtr->unk8_3 = 1; marker_setCollisionScripts(this->marker, NULL, __chAnchorSwitch_press, NULL); if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)) - __chAnchorSwitch_setState(this, 2); + __chAnchorSwitch_setState(this, CH_ANCHOR_SWITCH_STATE_2_PRESSED); else - __chAnchorSwitch_setState(this, 1); + __chAnchorSwitch_setState(this, CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED); } } diff --git a/src/RBB/ch/axle.c b/src/RBB/ch/axle.c index da1f91bab..619da6ef7 100644 --- a/src/RBB/ch/axle.c +++ b/src/RBB/ch/axle.c @@ -6,73 +6,96 @@ /* typedefs and declarations */ typedef struct { s16 unk0; - f32 unk4[3]; - f32 unk10; + f32 position[3]; + f32 startingRoll; f32 unk14; f32 unk18[3]; -}ActorLocal_RBB_2A70_0; +} ActorLocal_ChSpinningFlatPlatform_0; typedef struct { - ActorLocal_RBB_2A70_0 *unk0; - f32 unk4[3]; - f32 unk10[3]; + ActorLocal_ChSpinningFlatPlatform_0 *unk0; + f32 currentRotation[3]; + f32 nextRotation[3]; f32 unk1C; u8 pad20[0x4]; f32 unk24; -}ActorLocal_RBB_2A70; +} ActorLocal_ChSpinningFlatPlatform; -void func_803890BC(Actor *this); +void chSpinningFlatPlatform_update(Actor *this); /* .data */ -ActorLocal_RBB_2A70_0 D_80390430[] = { - {ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, {0.0f, -60.0f, 2450.0f}, 0.0f, 6.0f, { 0.0f, -100.0f, 1900.0f}}, - {ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, {-1600.0f, 730.0f, -700.0f}, 270.0f, 6.0f, { -1600.0f, 810.0f, -1400.0f}}, - {ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, {1600.0f, 730.0f, -700.0f}, 270.0f, 5.0f, { 1600.0f, 810.0f, -1400.0f}}, - 0 +ActorLocal_ChSpinningFlatPlatform_0 chSpinningFlatPlatformTable[] = { + { + ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, + {0.0f, -60.0f, 2450.0f}, + 0.0f, + 6.0f, + {0.0f, -100.0f, 1900.0f} + }, + { + ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, + {-1600.0f, 730.0f, -700.0f}, + 270.0f, + 6.0f, + { -1600.0f, 810.0f, -1400.0f}}, + { + ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, + {1600.0f, 730.0f, -700.0f}, + 270.0f, + 5.0f, + {1600.0f, 810.0f, -1400.0f} + }, + { 0 } // [port] decomp uses NULL; actorId is s16 and clang errors on -Wint-conversion }; -ActorInfo D_803904C0 = { - 0x188, 0x178, 0x40C, 0x0, NULL, - func_803890BC, NULL, actor_draw, +ActorInfo chSpinningFlatPlatform1 = { + MARKER_188_RBB_SPINNING_FLAT_PLATFORM_1, ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, ASSET_40C_MODEL_RBB_SPINNING_FLAT_PLATFORM_1, 0x0, NULL, + chSpinningFlatPlatform_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_803904E4 = { - 0x189, 0x179, 0x40D, 0x0, NULL, - func_803890BC, NULL, actor_draw, +ActorInfo chSpinningFlatPlatform2 = { + MARKER_189_RBB_SPINNING_FLAT_PLATFORM_2, ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, ASSET_40D_MODEL_RBB_SPINNING_FLAT_PLATFORM_2, 0x0, NULL, + chSpinningFlatPlatform_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390508 = { - 0x18A, 0x17A, 0x40E, 0x0, NULL, - func_803890BC, NULL, actor_draw, +ActorInfo chSpinningFlatPlatform3 = { + MARKER_18A_RBB_SPINNING_FLAT_PLATFORM_3, ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, ASSET_40E_MODEL_RBB_SPINNING_FLAT_PLATFORM_3, 0x0, NULL, + chSpinningFlatPlatform_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; +enum chspinningflatplatform_state_e { + CH_SPINNING_FLAT_PLATFORM_STATE_0_NOT_INIT, + CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE, + CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING +}; + /* .code */ -ActorLocal_RBB_2A70_0 *func_80388E60(Actor *this){ - ActorLocal_RBB_2A70_0 * iPtr; - for(iPtr = D_80390430; iPtr->unk0 != 0; iPtr++){ +ActorLocal_ChSpinningFlatPlatform_0 *func_80388E60(Actor *this){ + ActorLocal_ChSpinningFlatPlatform_0 * iPtr; + for(iPtr = chSpinningFlatPlatformTable; iPtr->unk0 != 0; iPtr++){ if(iPtr->unk0 == this->modelCacheIndex) return iPtr; } return NULL; } -void func_80388EB8(Actor *this, s32 arg1){ - ActorLocal_RBB_2A70 *local = (ActorLocal_RBB_2A70 *)&this->local; +void chSpinningFlatPlatform_setState(Actor *this, s32 next_state){ + ActorLocal_ChSpinningFlatPlatform *local = (ActorLocal_ChSpinningFlatPlatform *)&this->local; s32 sp30; - if(this->state == 2) + if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING) sfx_playFadeShorthandDefault(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 32000, this->position, 1000, 2300); - this->state = arg1; + this->state = next_state; local->unk24 = 0.0f; - if(this->state == 1) + if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE) local->unk24 = local->unk0->unk14; - if(this->state == 2){ + if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING){ sp30 = func_802F9AA8(SFX_94_COGS_ROTATING); func_802F9DB8(sp30, 1.0f, 1.0f, 0.0f); func_802F9EC4(sp30, local->unk0->unk18, 1700, 2500); @@ -82,49 +105,52 @@ void func_80388EB8(Actor *this, s32 arg1){ this->yaw += ( 360.0f <= this->yaw) ? -360 : 0; this->roll += ( 360.0f <= this->roll) ? -360 : 0; - local->unk4[0] = this->pitch; - local->unk4[1] = this->yaw; - local->unk4[2] = this->roll; + local->currentRotation[0] = this->pitch; + local->currentRotation[1] = this->yaw; + local->currentRotation[2] = this->roll; - local->unk10[0] = this->pitch; - local->unk10[1] = this->yaw; - local->unk10[2] = this->roll + 360.0f; + local->nextRotation[0] = this->pitch; + local->nextRotation[1] = this->yaw; + local->nextRotation[2] = this->roll + 360.0f; local->unk1C = 0.0f; sfx_playFadeShorthandDefault(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 32000, this->position, 900, 1800); }//L803890A8 } -void func_803890BC(Actor *this){ - ActorLocal_RBB_2A70 *local = (ActorLocal_RBB_2A70 *)&this->local; - f32 sp38 = time_getDelta(); - f32 sp2C[3]; +void chSpinningFlatPlatform_update(Actor *this){ + ActorLocal_ChSpinningFlatPlatform *local = (ActorLocal_ChSpinningFlatPlatform *)&this->local; + f32 time_delta = time_getDelta(); + f32 rotation[3]; + if(!this->volatile_initialized){ actor_collisionOff(this); this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = func_80388E60(this); - this->position[0] = local->unk0->unk4[0]; - this->position[1] = local->unk0->unk4[1]; - this->position[2] = local->unk0->unk4[2]; - this->roll = local->unk0->unk10; - if(this->state == 0) - func_80388EB8(this, 1); + this->position[0] = local->unk0->position[0]; + this->position[1] = local->unk0->position[1]; + this->position[2] = local->unk0->position[2]; + this->roll = local->unk0->startingRoll; + if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_0_NOT_INIT) + chSpinningFlatPlatform_setState(this, CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE); }//L80389164 - if(ml_timer_update(&local->unk24, sp38)) - func_80388EB8(this, (this->state == 1) ? 2 : 1); + if(ml_timer_update(&local->unk24, time_delta)) + chSpinningFlatPlatform_setState(this, + (this->state == CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE) ? + CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING : CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE); //L803891A8 - if(this->state == 2){ - local->unk1C += 0.25 * sp38; + if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING){ + local->unk1C += 0.25 * time_delta; if(1.0f < local->unk1C) local->unk1C = 1.0f; - ml_vec3f_interpolate_fast(sp2C, local->unk4, local->unk10, local->unk1C); - this->pitch = sp2C[0]; - this->yaw = sp2C[1]; - this->roll = sp2C[2]; + ml_vec3f_interpolate_fast(rotation, local->currentRotation, local->nextRotation, local->unk1C); + this->pitch = rotation[0]; + this->yaw = rotation[1]; + this->roll = rotation[2]; if(local->unk1C == 1.0f) - func_80388EB8(this, 1); + chSpinningFlatPlatform_setState(this, CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE); }//L80389264 } diff --git a/src/RBB/ch/bellbuoy.c b/src/RBB/ch/bellbuoy.c index 0ac91646b..04937bccf 100644 --- a/src/RBB/ch/bellbuoy.c +++ b/src/RBB/ch/bellbuoy.c @@ -8,118 +8,127 @@ /* typedefs and declarations */ typedef struct { f32 unk0; - ActorMarker *unk4; - f32 unk8[3]; - f32 unk14[3]; + ActorMarker *jinjoMarker; + f32 position[3]; + f32 rotation[3]; s32 unk20; - f32 unk24[3]; -}ActorLocal_7B20; + f32 timer[3]; +} ActorLocal_7B20; -void func_8038DF6C(Actor* this); +void chBellBuoy_update(Actor* this); /* .data */ -ActorInfo D_80390D20 = { - 0x1AA, 0x296, 0x43B, 0x0, NULL, - func_8038DF6C, NULL, actor_draw, +ActorInfo chBellBuoy = { + MARKER_1AA_BELL_BUOY, ACTOR_296_BELL_BUOY, ASSET_43B_MODEL_BELL_BUOY, + 0x0, NULL, + chBellBuoy_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; +enum chbellbuoy_state_e { + CH_BELL_BUOY_STATE_0_NOT_INIT, + CH_BELL_BUOY_STATE_1_INIT +}; /*.code */ -void func_8038DF10(Actor *this, int arg1){ - if(arg1 == 1){ - skeletalAnim_set(this->unk148, 0x16a, 0, 1.2f); +void chBellBuoy_setState(Actor *this, int next_state){ + if(next_state == CH_BELL_BUOY_STATE_1_INIT){ + skeletalAnim_set(this->unk148, ASSET_16A_ANIM_BELL_BUOY, 0, 1.2f); } - this->state = arg1; + this->state = next_state; } -void func_8038DF6C(Actor* this){ - f32 sp7C[3]; - f32 sp70[3]; +void chBellBuoy_update(Actor* this){ + f32 rotation_delta[3]; + f32 position_delta[3]; f32 sp6C; - f32 sp68 = time_getDelta(); - f32 sp5C[3]; - f32 sp58; + f32 time_delta = time_getDelta(); + f32 new_rotation[3]; + f32 distance; ActorLocal_7B20 *local = (ActorLocal_7B20 *)&this->local; - Actor* other; - int i; + Actor* jinjo; + int actor_id; if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = randf2(80.0f, 100.0f); - local->unk4 = NULL; + local->jinjoMarker = NULL; local->unk20 = 0; - local->unk24[0] = 0.0f; - local->unk24[1] = 1.0f; - local->unk24[2] = 0.5f; - local->unk8[0] = this->position_x; - local->unk8[1] = this->position_y; - local->unk8[2] = this->position_z; - local->unk14[0] = this->pitch; - local->unk14[1] = this->yaw; - local->unk14[2] = this->roll; - func_8038DF10(this, 1); + local->timer[0] = 0.0f; + local->timer[1] = 1.0f; + local->timer[2] = 0.5f; + local->position[0] = this->position_x; + local->position[1] = this->position_y; + local->position[2] = this->position_z; + local->rotation[0] = this->pitch; + local->rotation[1] = this->yaw; + local->rotation[2] = this->roll; + chBellBuoy_setState(this, CH_BELL_BUOY_STATE_1_INIT); }//L8038E050 + if(++local->unk20 == 2){ - for(i = 0x5e; i < 0x63; i++){ + // Actor 0x5E through 0x62 are Jinjos + for(actor_id = 0x5E; actor_id < 0x63; actor_id++){ - other = actorArray_findClosestActorFromActorId(this->position, i, -1, &sp58); - if(sp58 < 300.0f){ - local->unk4 = other->marker; - other->position_x = this->position_x; - other->position_y = this->position_y; - other->position_z = this->position_z; + jinjo = actorArray_findClosestActorFromActorId(this->position, actor_id, -1, &distance); + if(distance < 300.0f){ + local->jinjoMarker = jinjo->marker; + jinjo->position_x = this->position_x; + jinjo->position_y = this->position_y; + jinjo->position_z = this->position_z; break; } } } - if(ml_timer_update(&local->unk24[1], sp68)){ - local->unk24[1] = randf2(1.5f, 2.5f); + + if(ml_timer_update(&local->timer[1], time_delta)){ + local->timer[1] = randf2(1.5f, 2.5f); sfx_playFadeShorthandDefault(SFX_40E_UNKNOWN, 1.5f, 20000, this->position, 500, 1500); }//L8038E118 - if(ml_timer_update(&local->unk24[2], sp68)){ - local->unk24[2] = randf2(3.5f, 5.5f); - func_8030E878(SFX_69_WHIPCRACK_CREAKING, randf2(1.1f, 1.2f), 0x55f0, this->position, 500.0f, 1500.0f); + if(ml_timer_update(&local->timer[2], time_delta)){ + local->timer[2] = randf2(3.5f, 5.5f); + func_8030E878(SFX_69_WHIPCRACK_CREAKING, randf2(1.1f, 1.2f), 22000, this->position, 500.0f, 1500.0f); }//L8038E184 - local->unk24[0] += sp68; - sp70[0] = 0.0f; - sp70[1] = sinf((local->unk24[0]*local->unk0)/ 180.0 * 3.141592654) * 10.0f; - sp70[2] = 0.0f; + local->timer[0] += time_delta; + position_delta[0] = 0.0f; + position_delta[1] = sinf((local->timer[0] * local->unk0) / 180.0 * BAD_PI) * 10.0f; + position_delta[2] = 0.0f; - sp7C[0] = cosf((local->unk24[0]*local->unk0)/ 180.0 * 3.141592654)*7.5; - sp7C[1] = sinf((local->unk24[0]*local->unk0)/ 180.0 * 3.141592654)*3.0; - sp7C[2] = 0.0f; + rotation_delta[0] = cosf((local->timer[0] * local->unk0) / 180.0 * BAD_PI) * 7.5; + rotation_delta[1] = sinf((local->timer[0] * local->unk0) / 180.0 * BAD_PI) * 3.0; + rotation_delta[2] = 0.0f; - this->position_x = local->unk8[0] + sp70[0]; - this->position_y = local->unk8[1] + sp70[1]; - this->position_z = local->unk8[2] + sp70[2]; + this->position_x = local->position[0] + position_delta[0]; + this->position_y = local->position[1] + position_delta[1]; + this->position_z = local->position[2] + position_delta[2]; - sp5C[0] = local->unk14[0] + sp7C[0]; - sp5C[1] = local->unk14[1] + sp7C[1]; - sp5C[2] = local->unk14[2] + sp7C[2]; + new_rotation[0] = local->rotation[0] + rotation_delta[0]; + new_rotation[1] = local->rotation[1] + rotation_delta[1]; + new_rotation[2] = local->rotation[2] + rotation_delta[2]; - this->pitch = sp5C[0]; - this->yaw = sp5C[1]; - this->roll = sp5C[2]; + this->pitch = new_rotation[0]; + this->yaw = new_rotation[1]; + this->roll = new_rotation[2]; - if(local->unk4){ - other = marker_getActor(local->unk4); - if(!(other->state < 7)){ - local->unk4 = NULL; + if(local->jinjoMarker){ + jinjo = marker_getActor(local->jinjoMarker); + // State 7-9 Are Collecting Jinjo States + if(!(jinjo->state < 7)){ + local->jinjoMarker = NULL; }else{ - other->pitch = sp5C[0]; - other->roll = sp5C[2]; - TUPLE_ASSIGN(sp5C, 0.0f, 48.0f, 0.0f); - ml_vec3f_pitch_rotate_copy(sp5C, sp5C, this->pitch); - ml_vec3f_yaw_rotate_copy(sp5C, sp5C, this->yaw); + jinjo->pitch = new_rotation[0]; + jinjo->roll = new_rotation[2]; + TUPLE_ASSIGN(new_rotation, 0.0f, 48.0f, 0.0f); + ml_vec3f_pitch_rotate_copy(new_rotation, new_rotation, this->pitch); + ml_vec3f_yaw_rotate_copy(new_rotation, new_rotation, this->yaw); - other->position_x = sp5C[0] + this->position_x; - other->position_y = sp5C[1] + this->position_y; - other->position_z = sp5C[2] + this->position_z; + jinjo->position_x = new_rotation[0] + this->position_x; + jinjo->position_y = new_rotation[1] + this->position_y; + jinjo->position_z = new_rotation[2] + this->position_z; } }//L8038E39C } diff --git a/src/RBB/ch/boombox.c b/src/RBB/ch/boombox.c index c33cbace4..4d9d66c83 100644 --- a/src/RBB/ch/boombox.c +++ b/src/RBB/ch/boombox.c @@ -15,8 +15,8 @@ typedef struct { f32 *unk0; f32 unk4; f32 unk8[3]; - f32 unk14[3]; - f32 unk20[3]; + f32 currentPosition[3]; + f32 targetPosition[3]; f32 unk2C; f32 unk30; s32 unk34; @@ -24,29 +24,38 @@ typedef struct { u8 unk39; }ActorLocal_RBB_8520; -void func_8038F190(Actor *this, s32 arg1); -Actor *func_8038F4B0(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void func_8038F618(Actor *this); +void chBoomBox_setState(Actor *this, s32 arg1); +Actor *chBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chBoomBox_update(Actor *this); /* .data */ f32 D_80390D80[2] = {1.8f, 1.0f}; -ActorInfo D_80390D88 = { - MARKER_1B7_BOOM_BOX, ACTOR_2A4_BOOM_BOX_SLOW, ASSET_48C_MODEL_BOOM_BOX, 0x0, NULL, - func_8038F618, NULL, func_8038F4B0, +ActorInfo chBoomBoxSlow = { + MARKER_1B7_BOOM_BOX, ACTOR_2A4_BOOM_BOX_SLOW, ASSET_48C_MODEL_BOOM_BOX, + 0x0, NULL, + chBoomBox_update, NULL, chBoomBox_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390DAC = { - MARKER_1B7_BOOM_BOX, ACTOR_30D_BOOM_BOX_FAST, ASSET_48C_MODEL_BOOM_BOX, 0x0, NULL, - func_8038F618, NULL, func_8038F4B0, +ActorInfo chBoomBoxFast = { + MARKER_1B7_BOOM_BOX, ACTOR_30D_BOOM_BOX_FAST, ASSET_48C_MODEL_BOOM_BOX, + 0x0, NULL, + chBoomBox_update, NULL, chBoomBox_draw, 0, 0, 0.0f, 0 }; s32 RBB_D_80390DD0[3] = {0xDE, 0xA7, 0x71}; s32 D_80390DDC[4] = {0xFF, 0xFF, 0xFF, 0xFF}; -f32 D_80390DEC[4] = {0.0f, 0.0f , 0.0f, 0.0f}; +f32 D_80390DEC[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + +enum chboombox_state_e { + CH_BOOM_BOX_STATE_0_NOT_INIT, + CH_BOOM_BOX_STATE_1_UNK, + CH_BOOM_BOX_STATE_2_UNK, + CH_BOOM_BOX_STATE_3_EXPLODE +}; /* .bss */ f32 D_803912A0[3]; @@ -65,13 +74,13 @@ void func_8038E920(Actor *this){ void func_8038E92C(Actor *this){ ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; - if(this->state == 2 && local->unk34 == 0) + if(this->state == CH_BOOM_BOX_STATE_2_UNK && local->unk34 == 0) return; if(ml_timer_update( &local->unk30, time_getDelta())) - func_8038F190(this, 3); + chBoomBox_setState(this, CH_BOOM_BOX_STATE_3_EXPLODE); } -void func_8038E998(Actor *this){ +void chBoomBox_emitSmokeBeforeExplosion(Actor *this){ ParticleEmitter *other = partEmitMgr_newEmitter(2); f32 temp_f0; @@ -87,7 +96,7 @@ void func_8038E998(Actor *this){ particleEmitter_emitN(other, 2); } -void func_8038EAB4(Actor *this){ +void chBoomBox_emitExplosion(Actor *this){ ParticleEmitter *other; func_802BB3DC(0, 60.0f, 0.9f); other = partEmitMgr_newEmitter(1); @@ -105,7 +114,7 @@ void func_8038EAB4(Actor *this){ particleEmitter_emitN(other, 1); } -void func_8038EC14(Actor *this){ +void chBoomBox_emitSmokeAfterExplosion(Actor *this){ ParticleEmitter *other; other = partEmitMgr_newEmitter(6); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); @@ -121,7 +130,7 @@ void func_8038EC14(Actor *this){ particleEmitter_emitN(other, 6); } -void func_8038ED3C(Actor * actor, s32 arg1){ +void chBoomBox_emitModelsAfterExplosion(Actor * actor, s32 arg1){ ParticleEmitter *other = partEmitMgr_newEmitter(0xa); particleEmitter_setAccelerationRange(other, 0.0f, -800.0f, 0.0f, 0.0f, -800.0f, 0.0f); particleEmitter_func_802EF9F8(other, 0.6f); @@ -141,77 +150,77 @@ int func_8038EE90(Actor *this){ f32 sp20[3]; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; - sp2C[0] = local->unk14[0]; - sp2C[1] = local->unk14[1]; - sp2C[2] = local->unk14[2]; + sp2C[0] = local->currentPosition[0]; + sp2C[1] = local->currentPosition[1]; + sp2C[2] = local->currentPosition[2]; - sp20[0] = local->unk20[0]; - sp20[1] = local->unk20[1]; - sp20[2] = local->unk20[2]; + sp20[0] = local->targetPosition[0]; + sp20[1] = local->targetPosition[1]; + sp20[2] = local->targetPosition[2]; sp2C[1] += 75.0f; sp20[1] += 75.0f; return func_803342AC(&sp2C, &sp20, 100.0f); } -int func_8038EF08(Actor *this, f32 position[3], f32 arg2){ - f32 sp54[3]; - int sp50; +bool chBoombox_isValidMovePosition(Actor *this, f32 position[3], f32 speed_multiplier){ + f32 position_diff[3]; + bool ceiling_exists; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; - f32 sp40[3]; - f32 sp3C; - f32 sp30[3]; + f32 ceiling_check_position[3]; + f32 collision_radius; + f32 ceiling_collision_output[3]; - sp54[0] = position[0] - this->position_x; - sp54[1] = position[1] - this->position_y; - sp54[2] = position[2] - this->position_z; - if(180.0 < LENGTH_VEC3F(sp54)) - ml_vec3f_set_length(sp54, 150.0f); + position_diff[0] = position[0] - this->position_x; + position_diff[1] = position[1] - this->position_y; + position_diff[2] = position[2] - this->position_z; + if(180.0 < LENGTH_VEC3F(position_diff)) + ml_vec3f_set_length(position_diff, 150.0f); - local->unk20[0] = sp54[0] + this->position_x; - local->unk20[1] = sp54[1] + this->position_y; - local->unk20[2] = sp54[2] + this->position_z; - - local->unk20[1] = mapModel_getFloorY(local->unk20); - - sp40[0] = local->unk20[0]; - sp40[1] = local->unk20[1] + this->scale*100.0f; - sp40[2] = local->unk20[2]; - sp3C = this->scale*60.0f; - if(func_80309EB0(&sp40, sp3C, &sp30, 0)){ - sp50 = 1; + local->targetPosition[0] = position_diff[0] + this->position_x; + local->targetPosition[1] = position_diff[1] + this->position_y; + local->targetPosition[2] = position_diff[2] + this->position_z; + + local->targetPosition[1] = mapModel_getFloorY(local->targetPosition); + + ceiling_check_position[0] = local->targetPosition[0]; + ceiling_check_position[1] = local->targetPosition[1] + this->scale * 100.0f; + ceiling_check_position[2] = local->targetPosition[2]; + collision_radius = this->scale * 60.0f; + if(func_80309EB0(&ceiling_check_position, collision_radius, &ceiling_collision_output, 0)){ + ceiling_exists = true; }else{ - sp50 = 0; + ceiling_exists = false; } - if( !func_80329210(this, &local->unk20) - || ((local->unk2C + 30.0f) < local->unk20[1]) - || sp50 + if( !func_80329210(this, &local->targetPosition) + || ((local->unk2C + 30.0f) < local->targetPosition[1]) + || ceiling_exists ){ - local->unk20[0] = this->position_x; - local->unk20[1] = this->position_y; - local->unk20[2] = this->position_z; + local->targetPosition[0] = this->position_x; + local->targetPosition[1] = this->position_y; + local->targetPosition[2] = this->position_z; if(local->unk39 < 3 && ++local->unk39 == 3){ local->unk39 = 0; - return 0; + return false; } }else{ local->unk34 = func_8038EE90(this); if(local->unk34 == 0){ - local->unk20[0] = this->position_x; - local->unk20[1] = this->position_y; - local->unk20[2] = this->position_z; + local->targetPosition[0] = this->position_x; + local->targetPosition[1] = this->position_y; + local->targetPosition[2] = this->position_z; } } - skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.1f, randf2(-0.1f, 0.1f) + (1.0/arg2)*0.4); + skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.1f, randf2(-0.1f, 0.1f) + (1.0 / speed_multiplier) * 0.4); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - local->unk14[0] = this->position_x; - local->unk14[1] = this->position_y; - local->unk14[2] = this->position_z; - return 1; + local->currentPosition[0] = this->position_x; + local->currentPosition[1] = this->position_y; + local->currentPosition[2] = this->position_z; + return true; } -void func_8038F190(Actor *this, s32 arg1){ +void chBoomBox_setState(Actor *this, s32 next_state){ f32 player_position[3]; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; @@ -222,68 +231,68 @@ void func_8038F190(Actor *this, s32 arg1){ local->unk34 = false; } - if(arg1 == 1){ + if(next_state == CH_BOOM_BOX_STATE_1_UNK){ skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); }//L8038F204 - if(arg1 == 2){ - int sp3C = 0; + if(next_state == CH_BOOM_BOX_STATE_2_UNK){ + bool is_valid_move_position = false; if(func_80329210(this, &player_position)){ local->unk4 += 0.3; if(*local->unk0 < local->unk4) local->unk4 = *local->unk0; - sp3C = func_8038EF08(this, player_position, local->unk4); + is_valid_move_position = chBoombox_isValidMovePosition(this, player_position, local->unk4); }//L8038F28C - if(!sp3C){ + if(!is_valid_move_position){ func_8038E920(this); local->unk4 -= 0.5; if(local->unk4 < 0.5) local->unk4 = 0.5f; - func_8038EF08(this, local->unk8, local->unk4); + chBoombox_isValidMovePosition(this, local->unk8, local->unk4); } }//L8038F2FC - if(arg1 == 3){ - func_8038FB6C(); + if(next_state == CH_BOOM_BOX_STATE_3_EXPLODE){ + chBoomBoxMinigameCtrl_countDec(); actor_collisionOff(this); func_80324D54(0.0f, SFX_1B_EXPLOSION_1, 1.0f, 0x7d00, this->position, 1000.0f, 2000.0f); skeletalAnim_set(this->unk148, ASSET_148_ANIM_BOOMBOX_DIE, 0.2f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_8038EAB4(this); - func_8038EC14(this); - func_8038ED3C(this, 0x53a); - func_8038ED3C(this, 0x53b); - func_8038ED3C(this, 0x53c); + chBoomBox_emitExplosion(this); + chBoomBox_emitSmokeAfterExplosion(this); + chBoomBox_emitModelsAfterExplosion(this, ASSET_53A_MODEL_SHRAPNAL_PIECE_EYE); + chBoomBox_emitModelsAfterExplosion(this, ASSET_53B_MODEL_SHRAPNAL_PIECE_SPIKE); + chBoomBox_emitModelsAfterExplosion(this, ASSET_53C_MODEL_SHRAPNAL_PIECE_PLATE); func_80326310(this); this->unk10_1 = 0; func_8038E920(this); }//L8038F3C8 - this->state = arg1; + this->state = next_state; } void func_8038F3F0(ActorMarker *marker, ActorMarker *arg1){ Actor* actor = marker_getActor(marker); if(actor->state < 3){ - func_8038F190(actor, 3); + chBoomBox_setState(actor, CH_BOOM_BOX_STATE_3_EXPLODE); } } void func_8038F430(ActorMarker *marker, ActorMarker *arg1){ Actor* actor = marker_getActor(marker); - f32 sp18[3]; + f32 player_position[3]; if(actor->state < 3){ - player_getPosition(sp18); - if(ml_vec3f_distance(actor->position, sp18) < 300.0f) + player_getPosition(player_position); + if(ml_vec3f_distance(actor->position, player_position) < 300.0f) func_8028F55C(5, actor->marker); - func_8038F190(actor, 3); + chBoomBox_setState(actor, CH_BOOM_BOX_STATE_3_EXPLODE); }//L8038F4A4 } -Actor * func_8038F4B0(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ +Actor * chBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ Actor *actor; ActorLocal_RBB_8520 *local; s32 sp28[4]; @@ -292,10 +301,10 @@ Actor * func_8038F4B0(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ actor = marker_getActor(marker); local = (ActorLocal_RBB_8520 *)&actor->local; - func_8033A45C(1,2); - func_8033A45C(3,1); - func_8033A45C(6,1); - func_8033A45C(7,1); + modelRender_setAppendageVisibility(1,2); + modelRender_setAppendageVisibility(3,1); + modelRender_setAppendageVisibility(6,1); + modelRender_setAppendageVisibility(7,1); if(local->unk30 > 0.0f && local->unk30 <= 1.0){ temp_f2 = 2*(3*local->unk30 - (s32)(3*local->unk30)); if (temp_f2 > 1.0f) @@ -313,18 +322,18 @@ Actor * func_8038F4B0(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ return actor_draw(marker, gdl, mptr, arg3); } -void func_8038F618(Actor *this){ - f32 sp7C[3]; +void chBoomBox_update(Actor *this){ + f32 player_position[3]; int sp78; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; f32 sp70 = time_getDelta(); - f32 sp6C; - f32 sp68; - f32 sp5C[3]; + f32 prev_anim_progress; + f32 curr_anim_progress; + f32 this_position[3]; f32 sp50[3]; - f32 sp4C; - f32 sp48; - f32 sp44; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; f32 pad0; @@ -336,33 +345,33 @@ void func_8038F618(Actor *this){ local->unk8[2] = this->position_z; local->unk38 = 0; local->unk39 = 0; - local->unk0 = &D_80390D80[(this->modelCacheIndex == 0x30d)? 1 : 0]; + local->unk0 = &D_80390D80[(this->modelCacheIndex == ACTOR_30D_BOOM_BOX_FAST)? 1 : 0]; local->unk2C = mapModel_getFloorY(this->position); local->unk34 = 0; local->unk4 = 0.5f; local->unk30 = 0.0f; marker_setCollisionScripts(this->marker, func_8038F430, func_8038F3F0, func_8038F430); - func_8038F190(this, 1); + chBoomBox_setState(this, CH_BOOM_BOX_STATE_1_UNK); return; }//L8038F714 - player_getPosition(sp7C); - sp78 = func_80329210(this, &sp7C); + player_getPosition(player_position); + sp78 = func_80329210(this, &player_position); if(!local->unk38){ local->unk38 = true; - func_8038FB54(); + chBoomBoxMinigameCtrl_countInc(); } func_8038E92C(this); - if(this->state == 1){ - if(sp78 && ml_vec3f_distance(this->position, sp7C) < 500.0f){ - func_8038F190(this, 2); + if(this->state == CH_BOOM_BOX_STATE_1_UNK){ + if(sp78 && ml_vec3f_distance(this->position, player_position) < 500.0f){ + chBoomBox_setState(this, CH_BOOM_BOX_STATE_2_UNK); } }//L8038F7A0 - if(this->state == 2){ - sp5C[0] = this->position_x; - sp5C[1] = this->position_y; - sp5C[2] = this->position_z; + if(this->state == CH_BOOM_BOX_STATE_2_UNK){ + this_position[0] = this->position_x; + this_position[1] = this->position_y; + this_position[2] = this->position_z; if(0.0f != local->unk30 && !sp78) func_8038E920(this); @@ -370,28 +379,30 @@ void func_8038F618(Actor *this){ if(0.0f == local->unk30 && sp78) func_8038E910(this); - skeletalAnim_getProgressRange(this->unk148, &sp6C, &sp68); + skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress, &curr_anim_progress); - if(0.1 <= sp68 && sp68 <= 0.6) - ml_vec3f_interpolate_fast(this->position, local->unk14, local->unk20, (sp68 - 0.1) /0.5 ); - if(sp6C < 0.6 && 0.6 <= sp68) + if(0.1 <= curr_anim_progress && curr_anim_progress <= 0.6) + ml_vec3f_interpolate_fast(this->position, local->currentPosition, local->targetPosition, (curr_anim_progress - 0.1) / 0.5); + if(prev_anim_progress < 0.6 && 0.6 <= curr_anim_progress) func_8030E878(SFX_6C_LOCKUP_CLOSING, 1.1 + randf2(-0.05f, 0.05f), 20000, this->position, 500.0f, 1000.0f); - if(sp6C < 0.1 && 0.1 <= sp68) - func_8038E998(this); + if(prev_anim_progress < 0.1 && 0.1 <= curr_anim_progress) + chBoomBox_emitSmokeBeforeExplosion(this); - sp50[0] = local->unk20[0] - local->unk14[0]; - sp50[1] = local->unk20[1] - local->unk14[1]; - sp50[2] = local->unk20[2] - local->unk14[2]; + sp50[0] = local->targetPosition[0] - local->currentPosition[0]; + sp50[1] = local->targetPosition[1] - local->currentPosition[1]; + sp50[2] = local->targetPosition[2] - local->currentPosition[2]; - func_80258A4C(D_80390DEC, this->yaw - 90.0f, sp50, &sp4C, &sp48, &sp44); + func_80258A4C( + D_80390DEC, this->yaw - 90.0f, sp50, + &horizontal_distance, &distance_in_front, &side_angle_radian); - this->yaw += (sp44*400.0f)*sp70; + this->yaw += (side_angle_radian * 400.0f) * sp70; if(skeletalAnim_getLoopCount(this->unk148) > 0){ if(ml_vec3f_distance(this->position, local->unk8) < 10.0f){ - func_8038F190(this, 1); + chBoomBox_setState(this, CH_BOOM_BOX_STATE_1_UNK); }else{ - func_8038F190(this, 2); + chBoomBox_setState(this, CH_BOOM_BOX_STATE_2_UNK); } } }//L8038FA50 diff --git a/src/RBB/ch/bossboombox.c b/src/RBB/ch/bossboombox.c index 0970b3ba9..65192fb93 100644 --- a/src/RBB/ch/bossboombox.c +++ b/src/RBB/ch/bossboombox.c @@ -10,74 +10,78 @@ extern int func_803342AC(f32 (*)[3], f32(*)[3], f32); typedef struct{ - s16 unk0; + s16 actorId; //u8 pad2[2]; - f32 unk4; + f32 spawnPositionDelta; f32 unk8; u8 unkC; u8 unkD; u8 unkE; //u8 padF[1]; f32 unk10; - f32 unk14; -} Struct_RBB_5F80; + f32 volume; +} ActorLocal_ChBossBoomBoxInfo; typedef struct{ - Struct_RBB_5F80 *unk0; + ActorLocal_ChBossBoomBoxInfo *unk0; u8 unk4; u8 pad5[3]; - f32 unk8[3]; - f32 unk14[3]; + f32 currentPosition[3]; + f32 spawnPosition[3]; s32 unk20; f32 unk24; - f32 unk28; -} ActorLocal_RBB_5F80; + f32 turnAngle; +} ActorLocal_ChBossBoomBox; -void RBB_func_8038CC9C(Actor *this, s32 new_state); +void chBossBoomBox_setState(Actor *this, s32 new_state); void func_8038D7E8(ActorMarker *marker, s32 arg1); -Actor *func_8038D638(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3); -void func_8038D8BC(Actor *this); +Actor *chBossBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3); +void chBossBoomBox_update(Actor *this); /* .data */ -Struct_RBB_5F80 D_80390B70[4] = { +ActorLocal_ChBossBoomBoxInfo chBossBoomBoxTable[4] = { {ACTOR_281_BOSS_BOOM_BOX_LARGEST, 1.1f, 1.0f, 0x14, 0x01, 0x5, 0.9f, 0.8f}, {ACTOR_282_BOSS_BOOM_BOX_LARGE, 0.75f, 1.0f, 0xF, 0x02, 0x4, 1.1f, 0.9f}, {ACTOR_283_BOSS_BOOM_BOX_MEDIUM, 0.5f, 2.0f, 0xA, 0x02, 0x3, 1.3f, 1.0f}, {ACTOR_284_BOSS_BOOM_BOX_SMALL, 0.25f, 2.0f, 0x5, 0x02, 0x2, 1.5f, 1.1f}, }; -ActorInfo RBB_D_80390BD0 = { - MARKER_1A1_BOSS_BOOM_BOX_LARGEST, ACTOR_281_BOSS_BOOM_BOX_LARGEST, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, - func_8038D8BC, NULL, func_8038D638, +ActorInfo chBossBoomBoxLargest = { + MARKER_1A1_BOSS_BOOM_BOX_LARGEST, ACTOR_281_BOSS_BOOM_BOX_LARGEST, ASSET_428_MODEL_BOSS_BOOM_BOX, + 0x0, NULL, + chBossBoomBox_update, NULL, chBossBoomBox_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390BF4 = { - MARKER_1A2_BOSS_BOOM_BOX_LARGE, ACTOR_282_BOSS_BOOM_BOX_LARGE, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, - func_8038D8BC, NULL, func_8038D638, +ActorInfo chBossBoomBoxLarge = { + MARKER_1A2_BOSS_BOOM_BOX_LARGE, ACTOR_282_BOSS_BOOM_BOX_LARGE, ASSET_428_MODEL_BOSS_BOOM_BOX, + 0x0, NULL, + chBossBoomBox_update, NULL, chBossBoomBox_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390C18 = { - MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, ACTOR_283_BOSS_BOOM_BOX_MEDIUM, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, - func_8038D8BC, NULL, func_8038D638, +ActorInfo chBossBoomBoxMedium = { + MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, ACTOR_283_BOSS_BOOM_BOX_MEDIUM, ASSET_428_MODEL_BOSS_BOOM_BOX, + 0x0, NULL, + chBossBoomBox_update, NULL, chBossBoomBox_draw, 0, 0, 0.0f, 0 }; -ActorInfo RBB_D_80390C3C = { - MARKER_1A4_BOSS_BOOM_BOX_SMALL, ACTOR_284_BOSS_BOOM_BOX_SMALL, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, - func_8038D8BC, NULL, func_8038D638, +ActorInfo chBossBoomBoxSmall = { + MARKER_1A4_BOSS_BOOM_BOX_SMALL, ACTOR_284_BOSS_BOOM_BOX_SMALL, ASSET_428_MODEL_BOSS_BOOM_BOX, + 0x0, NULL, + chBossBoomBox_update, NULL, chBossBoomBox_draw, 0, 0, 0.0f, 0 }; -s32 D_80390C60[3] = {0xDE, 0xA7, 0x71}; +s32 ChBossBoomBoxSmoke1RGB[3] = {0xDE, 0xA7, 0x71}; ParticleSettingsVelocityAcceleration D_80390C6C = { { {-200.0f, 200.0f, -200.0f}, {200.0f, 500.0f, 200.0f} }, { {0.0f, -800.0f, 0.0f}, {0.0f, -800.0f, 0.0f} } }; -s32 D_80390C9C[3] = {0xDE, 0xA7, 0x71}; +s32 ChBossBoomBoxSmoke2RGB[3] = {0xDE, 0xA7, 0x71}; ParticleSettingsVelocityAccelerationPosition D_80390CA8 = { { {-200.0f, 0.0f, -200.0f}, {200.0f, -50.0f, 200.0f} }, @@ -85,30 +89,42 @@ ParticleSettingsVelocityAccelerationPosition D_80390CA8 = { { {-10.0f, -10.0f, -10.0f}, {10.0f, 10.0f, 10.0f} } }; +enum chbossboombox_state_e { + CH_BOSS_BOOM_BOX_STATE_0_NOT_INIT, + CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER, + CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY, + CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER, + CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK, + CH_BOSS_BOOM_BOX_STATE_5_BREAKING, + CH_BOSS_BOOM_BOX_STATE_6_COMPLETE, + CH_BOSS_BOOM_BOX_STATE_7_UNK, + CH_BOSS_BOOM_BOX_STATE_8_FF_TIMER_RUN_OUT +}; + /* .bss */ u8 D_80391280; s32 pad_80391284; -f32 D_80391288[3]; +f32 chBossBoomBoxJiggyPosition[3]; /* .code */ void RBB_func_8038C370(ActorMarker *marker, s32 arg1){ Actor *actor = marker_getActor(marker); - RBB_func_8038CC9C(actor, arg1); + chBossBoomBox_setState(actor, arg1); } void func_8038C39C(Actor *this){ - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(local->unk0->unkE); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setFade(other, 0.0f, 0.1f); particleEmitter_setStartingFrameRange(other, 0, 7); particleEmitter_setDrawMode(other, 4); particleEmitter_setPosition(other, this->position); - particleEmitter_setStartingScaleRange(other, local->unk0->unk4*1, local->unk0->unk4*3.0f); - particleEmitter_setFinalScaleRange(other, 3.0f*local->unk0->unk4, local->unk0->unk4*7.0f); + particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 1, local->unk0->spawnPositionDelta * 3.0f); + particleEmitter_setFinalScaleRange(other, 3.0f*local->unk0->spawnPositionDelta, local->unk0->spawnPositionDelta * 7.0f); particleEmitter_setSpawnPositionRange(other, - local->unk0->unk4*-200.0f, local->unk0->unk4*100.0f, local->unk0->unk4*-200.0f, - local->unk0->unk4*200.0f, local->unk0->unk4*100.0f, local->unk0->unk4*200.0f + local->unk0->spawnPositionDelta * -200.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * -200.0f, + local->unk0->spawnPositionDelta * 200.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * 200.0f ); particleEmitter_setParticleVelocityRange(other, -50.0f, 100.0f, -50.0f, @@ -119,43 +135,42 @@ void func_8038C39C(Actor *this){ } void RBB_func_8038C538(Actor *this){ - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(3*local->unk0->unkE); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setFade(other, 0.1f, 0.3f); particleEmitter_setDrawMode(other, 4); particleEmitter_setStartingFrameRange(other, 0, 7); particleEmitter_setPosition(other, this->position); - particleEmitter_setStartingScaleRange(other, local->unk0->unk4*1, local->unk0->unk4*6.0f); - particleEmitter_setFinalScaleRange(other, 0.5*local->unk0->unk4, local->unk0->unk4*3.0f); + particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 1, local->unk0->spawnPositionDelta * 6.0f); + particleEmitter_setFinalScaleRange(other, 0.5*local->unk0->spawnPositionDelta, local->unk0->spawnPositionDelta * 3.0f); particleEmitter_setSpawnPositionRange(other, - local->unk0->unk4*-300.0f, local->unk0->unk4*100.0f, local->unk0->unk4*-300.0f, - local->unk0->unk4*300.0f, local->unk0->unk4*300.0f, local->unk0->unk4*300.0f + local->unk0->spawnPositionDelta * -300.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * -300.0f, + local->unk0->spawnPositionDelta * 300.0f, local->unk0->spawnPositionDelta * 300.0f, local->unk0->spawnPositionDelta * 300.0f ); particleEmitter_setParticleVelocityRange(other, -70.0f, 50.0f, -70.0f, 70.0f, 100.0f, 70.0f ); - particleEmitter_setRGB(other, D_80390C60); + particleEmitter_setRGB(other, ChBossBoomBoxSmoke1RGB); particleEmitter_setParticleLifeTimeRange(other, 3.0f, 4.0f); - particleEmitter_emitN(other, 3*local->unk0->unkE); - + particleEmitter_emitN(other, 3 * local->unk0->unkE); } void RBB_func_8038C70C(Actor *this){ - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(0xa); particleEmitter_func_802EF9F8(other, 0.6f); particleEmitter_func_802EFA18(other, 3); particleEmitter_setDrawMode(other, 4); - particleEmitter_setModel(other, 0x427); + particleEmitter_setModel(other, ASSET_427_MODEL_WOODEN_PLANK); particleEmitter_setSpawnPositionRange(other, - local->unk0->unk4 * -300.0f, local->unk0->unk4 * 100.0f, local->unk0->unk4 * -300.0f, - local->unk0->unk4 * 300.0f, local->unk0->unk4 * 200.0f, local->unk0->unk4 * 300.0f + local->unk0->spawnPositionDelta * -300.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * -300.0f, + local->unk0->spawnPositionDelta * 300.0f, local->unk0->spawnPositionDelta * 200.0f, local->unk0->spawnPositionDelta * 300.0f ); particleEmitter_setPosition(other, this->position); - particleEmitter_setStartingScaleRange(other, local->unk0->unk4*0.3, local->unk0->unk4*0.8); + particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 0.3, local->unk0->spawnPositionDelta*0.8); particleEmitter_setAngularVelocityRange(other, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f @@ -168,24 +183,24 @@ void RBB_func_8038C70C(Actor *this){ } void func_8038C8A8(Actor * this){ - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(5); - f32 sp24[3]; + f32 particle_position[3]; - player_getPosition(sp24); - sp24[1] += 50.0f; + player_getPosition(particle_position); + particle_position[1] += 50.0f; particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setFade(other, 0.0, 0.5f); particleEmitter_setDrawMode(other, 4); particleEmitter_setStartingFrameRange(other, 0, 7); - particleEmitter_setPosition(other, sp24); - particleEmitter_setStartingScaleRange(other, local->unk0->unk4*1, local->unk0->unk4*3.0f); - particleEmitter_setFinalScaleRange(other, local->unk0->unk4*3.0f, local->unk0->unk4*6.0f); + particleEmitter_setPosition(other, particle_position); + particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 1, local->unk0->spawnPositionDelta * 3.0f); + particleEmitter_setFinalScaleRange(other, local->unk0->spawnPositionDelta * 3.0f, local->unk0->spawnPositionDelta * 6.0f); particleEmitter_setVelocityAccelerationAndPositionRanges(other, &D_80390CA8); particleEmitter_setParticleLifeTimeRange(other, 1.0f, 2.0f); - particleEmitter_setRGB(other, D_80390C9C); + particleEmitter_setRGB(other, ChBossBoomBoxSmoke2RGB); particleEmitter_emitN(other, 5); } @@ -194,17 +209,17 @@ void chbossboombox_respawnJiggy(s32 position_x, s32 position_y, s32 position_z){ if(jiggy) marker_despawn(jiggy->marker); - D_80391288[0] = (f32)position_x; - D_80391288[1] = (f32)(position_y + 0x28); - D_80391288[2] = (f32)position_z; - jiggy_spawn(JIGGY_56_RBB_BOSS_BOOM_BOX, D_80391288); + chBossBoomBoxJiggyPosition[0] = (f32)position_x; + chBossBoomBoxJiggyPosition[1] = (f32)(position_y + 0x28); + chBossBoomBoxJiggyPosition[2] = (f32)position_z; + jiggy_spawn(JIGGY_56_RBB_BOSS_BOOM_BOX, chBossBoomBoxJiggyPosition); } void func_8038CA70(Actor *this, f32(*arg1)[3]){ f32 tmp_f; - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; - tmp_f = local->unk0->unk4 * 300.0f; + tmp_f = local->unk0->spawnPositionDelta * 300.0f; if( (*arg1)[0] - tmp_f < -1400.0f) (*arg1)[0] = -1400.0f + tmp_f; @@ -221,7 +236,7 @@ void func_8038CA70(Actor *this, f32(*arg1)[3]){ } void func_8038CB34(ActorMarker *marker, enum asset_e arg1, s32 arg2){ - comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, -1, 0x12C); + comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, -1, 300); } void func_8038CB68(ActorMarker *marker, enum asset_e arg1, s32 arg2){ @@ -240,55 +255,52 @@ void chbossboombox_hideJiggy(void){ int RBB_func_8038CBF0(Actor *this){ f32 sp2C[3]; f32 sp20[3]; - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; - sp2C[0] = local->unk8[0]; - sp2C[1] = local->unk8[1]; - sp2C[2] = local->unk8[2]; + sp2C[0] = local->currentPosition[0]; + sp2C[1] = local->currentPosition[1]; + sp2C[2] = local->currentPosition[2]; - sp20[0] = local->unk14[0]; - sp20[1] = local->unk14[1]; - sp20[2] = local->unk14[2]; - - sp2C[1] += 300.0f * local->unk0->unk4; - sp20[1] += 300.0f * local->unk0->unk4; - return func_803342AC(&sp2C, &sp20, local->unk0->unk4 * 400.0f); + sp20[0] = local->spawnPosition[0]; + sp20[1] = local->spawnPosition[1]; + sp20[2] = local->spawnPosition[2]; + sp2C[1] += 300.0f * local->unk0->spawnPositionDelta; + sp20[1] += 300.0f * local->unk0->spawnPositionDelta; + return func_803342AC(&sp2C, &sp20, local->unk0->spawnPositionDelta * 400.0f); } -void RBB_func_8038CC9C(Actor *this, s32 new_state){ - f32 sp8C[3]; +void chBossBoomBox_setState(Actor *this, s32 new_state){ + f32 player_position[3]; f32 sp80[3]; - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; int i; f32 pad; - f32 sp68[3]; - f32 player_position; - f32 sp60; - f32 sp5C; - f32 sp58; - - - - player_getPosition(sp8C); + f32 spawn_position[3]; + f32 position_delta; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; + + player_getPosition(player_position); - sp8C[1] = 0.0f; + player_position[1] = 0.0f; - sp80[0] = sp8C[0] - this->position_x; - sp80[1] = sp8C[1] - this->position_y; - sp80[2] = sp8C[2] - this->position_z; - if(this->state == 2){ + sp80[0] = player_position[0] - this->position_x; + sp80[1] = player_position[1] - this->position_y; + sp80[2] = player_position[2] - this->position_z; + if(this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY){ chbossboombox_hideJiggy(); } - if(this->state == 7){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_7_UNK){ actor_collisionOn(this); } - local->unk8[0] = this->position_x; - local->unk8[1] = this->position_y; - local->unk8[2] = this->position_z; - local->unk24 = local->unk28 = this->yaw; + local->currentPosition[0] = this->position_x; + local->currentPosition[1] = this->position_y; + local->currentPosition[2] = this->position_z; + local->unk24 = local->turnAngle = this->yaw; this->state = new_state; if(local->unk20){ @@ -296,13 +308,13 @@ void RBB_func_8038CC9C(Actor *this, s32 new_state){ local->unk20 = 0; } - if(this->state == 1){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER){ skeletalAnim_set(this->unk148, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR, 0.0f, 2.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); } - if(this->state == 2){ - func_8025A58C(0, 0xfa0); + if(this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY){ + func_8025A58C(0, 4000); coMusicPlayer_playMusic(COMUSIC_62_RBB_BOOMBOX, -1); func_8025AABC(COMUSIC_62_RBB_BOOMBOX); skeletalAnim_set(this->unk148, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR, 0.0f, 2.4f); @@ -321,44 +333,46 @@ void RBB_func_8038CC9C(Actor *this, s32 new_state){ timedFunc_set_2(2.4f, (GenFunction_2)RBB_func_8038C370, (uintptr_t)this->marker, 3); } else{//L8038CEFC - timedFunc_set_3(2.4f, (GenFunction_3)comusic_8025AB44, COMUSIC_62_RBB_BOOMBOX, 0x1f40, 0x12C); - func_80324DBC(2.4f, ASSET_B9E_DIALOG_BOSS_BOOM_BOX_MEET, 4, NULL, this->marker, func_8038CB34, func_8038CB68); + timedFunc_set_3(2.4f, (GenFunction_3)comusic_8025AB44, COMUSIC_62_RBB_BOOMBOX, 8000, 300); + func_80324DBC(2.4f, VER_SELECT(ASSET_B9E_DIALOG_BOSS_BOOM_BOX_MEET, 0x973, 0, 0), 4, NULL, this->marker, func_8038CB34, func_8038CB68); } }//L8038CF60 - if(this->state == 3 || this->state == 4){ - func_8030E878(0x3f2, local->unk0->unk14, 0x6d60, this->position, 500.0f, 1000.0f); - skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2f, (1.0/(local->unk0->unk8)*randf2(1.0f, 1.1f))); + if( this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER + || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK) + { + func_8030E878(SFX_3F2_BOING, local->unk0->volume, 28000, this->position, 500.0f, 1000.0f); + skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2f, (1.0 / (local->unk0->unk8) * randf2(1.0f, 1.1f))); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - ml_vec3f_set_length(sp80, (this->state == 4)? -0x32*(2 + func_80326218()) : 300.0f/local->unk0->unk8); - local->unk14[0] = sp80[0] + this->position_x; - local->unk14[1] = sp80[1] + this->position_y; - local->unk14[2] = sp80[2] + this->position_z; - local->unk14[1] = 0.0f; - func_8038CA70(this, &local->unk14); + ml_vec3f_set_length(sp80, (this->state == 4)? -0x32 * (2 + func_80326218()) : 300.0f / local->unk0->unk8); + local->spawnPosition[0] = sp80[0] + this->position_x; + local->spawnPosition[1] = sp80[1] + this->position_y; + local->spawnPosition[2] = sp80[2] + this->position_z; + local->spawnPosition[1] = 0.0f; + func_8038CA70(this, &local->spawnPosition); }//L8038D0B8 - if(this->state == 5){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_5_BREAKING){ actor_collisionOff(this); - timed_playSfx(0.2f, SFX_D9_WOODEN_CRATE_BREAKING_1, 0.9f, 0x7530); + timed_playSfx(0.2f, SFX_D9_WOODEN_CRATE_BREAKING_1, 0.9f, 30000); skeletalAnim_set(this->unk148, ASSET_148_ANIM_BOOMBOX_DIE, 0.2f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); ml_vec3f_set_length(sp80, -300.f); - local->unk14[0] = sp80[0] + this->position_x; - local->unk14[1] = sp80[1] + this->position_y; - local->unk14[2] = sp80[2] + this->position_z; - local->unk14[1] = 0.0f; - func_8038CA70(this, &local->unk14); + local->spawnPosition[0] = sp80[0] + this->position_x; + local->spawnPosition[1] = sp80[1] + this->position_y; + local->spawnPosition[2] = sp80[2] + this->position_z; + local->spawnPosition[1] = 0.0f; + func_8038CA70(this, &local->spawnPosition); RBB_func_8038C70C(this); RBB_func_8038C538(this); }//L8038D17C - if(this->state == 6){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_6_COMPLETE){ func_80326310(this); - if(local->unk0->unk0 == ACTOR_284_BOSS_BOOM_BOX_SMALL){ + if(local->unk0->actorId == ACTOR_284_BOSS_BOOM_BOX_SMALL){ if(++D_80391280 == 8){ - func_8025A58C(-1, 0x190); - comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, 0, 0x190); + func_8025A58C(-1, 400); + comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, 0, 400); func_8025AABC(COMUSIC_62_RBB_BOOMBOX); if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ item_set(ITEM_6_HOURGLASS, 0); @@ -367,101 +381,116 @@ void RBB_func_8038CC9C(Actor *this, s32 new_state){ } else{//L8038D220 timedFunc_set_3(0.0f, (GenFunction_3)chbossboombox_respawnJiggy, (s32)this->position_x, (s32)this->position_y, (s32)this->position_z); - gcdialog_showDialog(ASSET_B9F_DIALOG_BOSS_BOOM_BOX_COMPLETE, 4, 0, 0, 0, 0); + gcdialog_showDialog(VER_SELECT(ASSET_B9F_DIALOG_BOSS_BOOM_BOX_COMPLETE, 0x974, 0, 0), 4, 0, 0, 0, 0); } }//L8038D278 } else{//L8038D28C - sp68[0] = this->position_x + 200.0f*local->unk0->unk4; - sp68[1] = this->position_y + 80.0f*local->unk0->unk4; - sp68[2] = this->position_z; - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, local->unk0->unk0 + 1, reinterpret_cast(s32, sp68[0]), reinterpret_cast(s32, sp68[1]), reinterpret_cast(s32, sp68[2])); - - sp68[0] = this->position_x - 200.0f*local->unk0->unk4; - sp68[1] = this->position_y + 80.0f*local->unk0->unk4; - sp68[2] = this->position_z; - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, local->unk0->unk0 + 1, reinterpret_cast(s32, sp68[0]), reinterpret_cast(s32, sp68[1]), reinterpret_cast(s32, sp68[2])); + spawn_position[0] = this->position_x + 200.0f * local->unk0->spawnPositionDelta; + spawn_position[1] = this->position_y + 80.0f * local->unk0->spawnPositionDelta; + spawn_position[2] = this->position_z; + __spawnQueue_add_4( + (GenFunction_4)spawnQueue_actor_f32, + local->unk0->actorId + 1, + reinterpret_cast(s32, spawn_position[0]), + reinterpret_cast(s32, spawn_position[1]), + reinterpret_cast(s32, spawn_position[2])); + + spawn_position[0] = this->position_x - 200.0f * local->unk0->spawnPositionDelta; + spawn_position[1] = this->position_y + 80.0f * local->unk0->spawnPositionDelta; + spawn_position[2] = this->position_z; + __spawnQueue_add_4( + (GenFunction_4)spawnQueue_actor_f32, + local->unk0->actorId + 1, + reinterpret_cast(s32, spawn_position[0]), + reinterpret_cast(s32, spawn_position[1]), + reinterpret_cast(s32, spawn_position[2])); } }//L8038D378 - if(this->state == 7){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_7_UNK){ actor_collisionOff(this); func_803262E4(this); skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.0f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - local->unk8[0] = this->position_x; - local->unk8[1] = this->position_y; - local->unk8[2] = this->position_z; + local->currentPosition[0] = this->position_x; + local->currentPosition[1] = this->position_y; + local->currentPosition[2] = this->position_z; - local->unk14[0] = this->position_x; - local->unk14[1] = this->position_y; - local->unk14[2] = this->position_z; + local->spawnPosition[0] = this->position_x; + local->spawnPosition[1] = this->position_y; + local->spawnPosition[2] = this->position_z; local->unk20 = RBB_func_8038CBF0(this); }//L8038D3FC - if(this->state == 3 || this->state == 4 || this->state == 5){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER + || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK + || this->state == CH_BOSS_BOOM_BOX_STATE_5_BREAKING) + { local->unk20 = RBB_func_8038CBF0(this); if( local->unk20 == 0){ - player_position = local->unk0->unk4*300.0f; + position_delta = local->unk0->spawnPositionDelta * 300.0f; for(i = 0; i < 10; i++){ - local->unk14[0] = local->unk8[0] + randf2(-player_position, player_position); - local->unk14[1] = local->unk14[1]; - local->unk14[2] = local->unk8[2] + randf2(-player_position, player_position); - func_8038CA70(this, &local->unk14); + local->spawnPosition[0] = local->currentPosition[0] + randf2(-position_delta, position_delta); + local->spawnPosition[1] = local->spawnPosition[1]; + local->spawnPosition[2] = local->currentPosition[2] + randf2(-position_delta, position_delta); + func_8038CA70(this, &local->spawnPosition); local->unk20 = RBB_func_8038CBF0(this); if(local->unk20) break; } - if(i == 0xa){ - local->unk14[0] = local->unk8[0]; - local->unk14[2] = local->unk8[2]; - local->unk14[1] = 0.0f; + if(i == 10){ + local->spawnPosition[0] = local->currentPosition[0]; + local->spawnPosition[2] = local->currentPosition[2]; + local->spawnPosition[1] = 0.0f; } } }//L8038D4DC - if(this->state == 3){ - func_80258A4C(this->position, this->yaw - 90.0f, sp8C, &sp60, &sp5C, &sp58); - if(0.7 < sp58) - local->unk28 += 90.0f; - else if(sp58 < -0.7){ - local->unk28 -= 90.0f; + if(this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER){ + func_80258A4C( + this->position, this->yaw - 90.0f, player_position, + &horizontal_distance, &distance_in_front, &side_angle_radian); + if(0.7 < side_angle_radian) + local->turnAngle += 90.0f; + else if(side_angle_radian < -0.7){ + local->turnAngle -= 90.0f; } } } -void func_8038D590(ActorMarker *marker, ActorMarker *arg1){ +void chBossBoomBox_hitPlayer(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - RBB_func_8038CC9C(actor, 4); + chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK); } -void func_8038D5BC(ActorMarker *marker, ActorMarker *arg1){ +void chBossBoomBox_ow(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &actor->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &actor->local; - gcsfx_playWithPitch(0x3f5, local->unk0->unk10, 0x4e20); - RBB_func_8038CC9C(actor, 4); + gcsfx_playWithPitch(SFX_3F5_UNKNOWN, local->unk0->unk10, 20000); + chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK); func_8038C8A8(actor); } -void func_8038D608(ActorMarker *marker, ActorMarker *other){ +void chBossBoomBox_die(ActorMarker *marker, ActorMarker *other){ func_8038D7E8(marker, other->id == 1); } -Actor *func_8038D638(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3){ +Actor *chBossBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3){ f32 sp3C[3]; Actor *actor = marker_getActorAndRotation(marker, sp3C); - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &actor->local; - func_8033A45C(1, local->unk0->unkD); + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &actor->local; + modelRender_setAppendageVisibility(1, local->unk0->unkD); if(local->unk0->unkD == 1){ - func_8033A45C(2, (actor->state == 4)? 2: 1); - func_8033A45C(4, (actor->state == 4)? 2: 1); - func_8033A45C(5, (actor->state == 4)? 2: 1); + modelRender_setAppendageVisibility(2, (actor->state == 4)? 2: 1); + modelRender_setAppendageVisibility(4, (actor->state == 4)? 2: 1); + modelRender_setAppendageVisibility(5, (actor->state == 4)? 2: 1); }//L8038D714 else{ - func_8033A45C(3, (actor->state == 4)? 2: 1); - func_8033A45C(6, (actor->state == 4)? 2: 1); - func_8033A45C(7, (actor->state == 4)? 2: 1); + modelRender_setAppendageVisibility(3, (actor->state == 4)? 2: 1); + modelRender_setAppendageVisibility(6, (actor->state == 4)? 2: 1); + modelRender_setAppendageVisibility(7, (actor->state == 4)? 2: 1); } modelRender_setPreDrawCallback( (model_render_pre_draw_callback_f)actor_predrawMethod, (void *)actor); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); @@ -472,15 +501,15 @@ Actor *func_8038D638(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3){ void func_8038D7E8(ActorMarker *marker, s32 arg1){ Actor *actor = marker_getActor(marker); - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &actor->local; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &actor->local; sfx_playFadeShorthandDefault(SFX_1E_HITTING_AN_ENEMY_2, 1.0f, 20000, actor->position, 1000, 2000); gcsfx_playWithPitch(SFX_D7_GRABBA_DEATH, local->unk0->unk10, 0x7530); local->unk4 += (arg1) ? 1 : 5; if(local->unk4 >= local->unk0->unkC) - RBB_func_8038CC9C(actor, 5); + chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_5_BREAKING); else{ - RBB_func_8038CC9C(actor, 4); + chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK); } if(!arg1) @@ -490,13 +519,13 @@ void func_8038D7E8(ActorMarker *marker, s32 arg1){ void func_8038D8B4(Actor *actor){} -void func_8038D8BC(Actor *this){ +void chBossBoomBox_update(Actor *this){ f32 player_position[3]; - ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; - f32 sp5C; - f32 sp58; - f32 sp54; - f32 sp50; + ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + f32 prev_anim_progress1; + f32 curr_anim_progress1; + f32 prev_anim_progress2; + f32 curr_anim_progress2; f32 sp4C; f32 tmp_f2; f32 pad; @@ -504,23 +533,23 @@ void func_8038D8BC(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - local->unk0 = &D_80390B70[this->marker->id - 0x1A1]; + local->unk0 = &chBossBoomBoxTable[this->marker->id - MARKER_1A1_BOSS_BOOM_BOX_LARGEST]; local->unk4 = 0; local->unk20 = 0; this->marker->propPtr->unk8_3 = 0; - this->scale = local->unk0->unk4; - if(local->unk0 == D_80390B70){ + this->scale = local->unk0->spawnPositionDelta; + if(local->unk0 == chBossBoomBoxTable){ this->yaw = 270.0f; } - marker_setCollisionScripts(this->marker, func_8038D590, func_8038D5BC, func_8038D608); + marker_setCollisionScripts(this->marker, chBossBoomBox_hitPlayer, chBossBoomBox_ow, chBossBoomBox_die); marker_setFreeMethod(this->marker, func_8038D8B4); - if(local->unk0->unk0 == ACTOR_281_BOSS_BOOM_BOX_LARGEST){ - RBB_func_8038CC9C(this, 1); + if(local->unk0->actorId == ACTOR_281_BOSS_BOOM_BOX_LARGEST){ + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER); D_80391280 = 0; } else{ - RBB_func_8038CC9C(this, 7); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_7_UNK); } if(jiggyscore_isSpawned(JIGGY_56_RBB_BOSS_BOOM_BOX) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) @@ -533,79 +562,82 @@ void func_8038D8BC(Actor *this){ chbossboombox_hideJiggy(); skeletalAnim_set(this->unk148, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR, 0.0f, 2.4f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - this->state = 2; + this->state = CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY; } return; } player_getPosition(player_position); - if(this->state == 1){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(volatileFlag_get(VOLATILE_FLAG_3)){ - RBB_func_8038CC9C(this, 2); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY); } } else{//L8038DAA8 if(ml_vec3f_distance(this->position, player_position) < 1200.0f){ - RBB_func_8038CC9C(this, 2); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY); } } }//L8038DAD8 - if(this->state == 2){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY){ if(skeletalAnim_getAnimId(this->unk148) == ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR && skeletalAnim_getLoopCount(this->unk148) > 0){ skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); } }//L8038DB30 - if( this->state == 2 || this->state == 3 || this->state == 4){ + if( this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY + || this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER + || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK){ if(skeletalAnim_getAnimId(this->unk148) == ASSET_147_ANIM_BOOMBOX_MOVE){ - skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); - if(sp5C < 0.6 && 0.6 <= sp58){ - func_8030E878(SFX_6C_LOCKUP_CLOSING, randf2(-0.05f, 0.05f) + local->unk0->unk14, 20000, this->position, 500.0f, 1000.0f); + skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress1, &curr_anim_progress1); + if(prev_anim_progress1 < 0.6 && 0.6 <= curr_anim_progress1){ + func_8030E878(SFX_6C_LOCKUP_CLOSING, randf2(-0.05f, 0.05f) + local->unk0->volume, 20000, this->position, 500.0f, 1000.0f); }//L8038DC04 - if(sp5C < 0.1 && 0.1 <= sp58){ + if(prev_anim_progress1 < 0.1 && 0.1 <= curr_anim_progress1){ func_8038C39C(this); } } }//L8038DC48 - if(this->state == 3 || this->state == 4){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER + || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(item_empty(ITEM_0_HOURGLASS_TIMER)){ volatileFlag_set(VOLATILE_FLAG_3, 0); volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); - RBB_func_8038CC9C(this, 8); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_8_FF_TIMER_RUN_OUT); } } - skeletalAnim_getProgressRange(this->unk148, &sp54, &sp50); - if(0.1 <= sp50 && sp50 <= 0.6){ - sp4C = (sp50 - 0.1)/0.5; - ml_vec3f_interpolate_fast(this->position, local->unk8, local->unk14, sp4C); - this->yaw = local->unk24 + sp4C*(local->unk28 - local->unk24); + skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress2, &curr_anim_progress2); + if(0.1 <= curr_anim_progress2 && curr_anim_progress2 <= 0.6){ + sp4C = (curr_anim_progress2 - 0.1) / 0.5; + ml_vec3f_interpolate_fast(this->position, local->currentPosition, local->spawnPosition, sp4C); + this->yaw = local->unk24 + sp4C * (local->turnAngle - local->unk24); } if(skeletalAnim_getLoopCount(this->unk148) > 0) - RBB_func_8038CC9C(this, 3); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER); }//L8038DD64 - if(this->state == 5){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_5_BREAKING){ if(skeletalAnim_getLoopCount(this->unk148) > 0){ - RBB_func_8038CC9C(this, 6); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_6_COMPLETE); }else{ tmp_f2 = skeletalAnim_getProgress(this->unk148); if(tmp_f2 <= 0.3) - tmp_f2 = tmp_f2/0.3; + tmp_f2 = tmp_f2 / 0.3; else tmp_f2 = 1.0f; - ml_vec3f_interpolate_fast(this->position, local->unk8, local->unk14, tmp_f2); + ml_vec3f_interpolate_fast(this->position, local->currentPosition, local->spawnPosition, tmp_f2); } }//L8038DE10 - if(this->state == 7){ + if(this->state == CH_BOSS_BOOM_BOX_STATE_7_UNK){ if(skeletalAnim_getLoopCount(this->unk148) > 0) - RBB_func_8038CC9C(this, 3); + chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER); } } diff --git a/src/RBB/ch/bossboomboxctrl.c b/src/RBB/ch/bossboomboxctrl.c index b81a46f76..c29948315 100644 --- a/src/RBB/ch/bossboomboxctrl.c +++ b/src/RBB/ch/bossboomboxctrl.c @@ -7,12 +7,18 @@ void chBossBoomBoxCtrl_update(Actor *this); /* .data */ -ActorInfo RBB_D_80390CF0 = { - 0x1C0, 0x2AD, 0x0, 0x0, NULL, +ActorInfo chBossBoomBoxCtrl = { + MARKER_1C0_BOSS_BOOMBOX_CTRL, ACTOR_2AD_BOSS_BOOMBOX_CTRL, 0x0, + 0x0, NULL, chBossBoomBoxCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; +enum bossboomboxctrl_state_e { + BOSS_BOOM_BOX_CTRL_STATE_0_NOT_INIT, + BOSS_BOOM_BOX_CTRL_STATE_1_INIT +}; + /* .code */ void __chBossBoomBoxCtrl_setState(Actor *this, s32 new_state){ this->state = new_state; @@ -22,11 +28,13 @@ void chBossBoomBoxCtrl_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - if(jiggyscore_isSpawned(JIGGY_56_RBB_BOSS_BOOM_BOX) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ + if(jiggyscore_isSpawned(JIGGY_56_RBB_BOSS_BOOM_BOX) + && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) + { marker_despawn(this->marker); - }else{ + } else { __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_281_BOSS_BOOM_BOX_LARGEST, reinterpret_cast(s32,this->position_x), reinterpret_cast(s32,this->position_y), reinterpret_cast(s32,this->position_z)); - __chBossBoomBoxCtrl_setState(this, 1); + __chBossBoomBoxCtrl_setState(this, BOSS_BOOM_BOX_CTRL_STATE_1_INIT); } }//L8038DEF4 } diff --git a/src/RBB/ch/cog.c b/src/RBB/ch/cog.c index 38b43adca..e8dd085ac 100644 --- a/src/RBB/ch/cog.c +++ b/src/RBB/ch/cog.c @@ -10,50 +10,61 @@ typedef struct { u8 sfxsourceIdx; }ActorLocal_RBB_27E0; -void func_80388C20(Actor *this); +void chRBBCog_update(Actor *this); /* .data */ -ActorInfo D_803903B0 = { - 0x18B, 0x17B, 0x409, 0x0, NULL, - func_80388C20, NULL, actor_draw, +ActorInfo chRBBSmallCog = { + MARKER_18B_RBB_SMALL_COG, ACTOR_17B_RBB_SMALL_COG, ASSET_409_MODEL_RBB_SMALL_COG, + 0x0, NULL, + chRBBCog_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_803903D4 = { - 0x18C, 0x17C, 0x40A, 0x0, NULL, - func_80388C20, NULL, actor_draw, +ActorInfo chRBBMediumCog = { + MARKER_18C_RBB_MEDIUM_COG, ACTOR_17C_RBB_MEDIUM_COG, ASSET_40A_MODEL_RBB_MEDIUM_COG, + 0x0, NULL, + chRBBCog_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_803903F8 = { - 0x18D, 0x17D, 0x40B, 0x0, NULL, - func_80388C20, NULL, actor_draw, +ActorInfo chRBBLargeCog = { + MARKER_18D_RBB_LARGE_COG, ACTOR_17D_RBB_LARGE_COG, ASSET_40B_MODEL_RBB_LARGE_COG, + 0x0, NULL, + chRBBCog_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -f32 D_8039041C[3] = {40.0f, -30.0f, 20.0f}; //rotation rates (deg/sec); +f32 chRBBCogRotateRates[3] = {40.0f, -30.0f, 20.0f}; //rotation rates (deg/sec); + +enum chrbbcog_state_e { + CH_RBB_COG_STATE_0_NOT_INIT, + CH_RBB_COG_STATE_1_INIT +}; /* .code */ -void func_80388BD0(Actor *this, s32 arg1){ - this->state = arg1; +void chRBBCog_setState(Actor *this, s32 next_state){ + this->state = next_state; } -void func_80388BE8(Actor *actor){ +void chRBBCog_free(Actor *actor){ ActorLocal_RBB_27E0 *local = (ActorLocal_RBB_27E0 *)&actor->local; - if(actor->modelCacheIndex == 0x17b){ + + if(actor->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); } } -void func_80388C20(Actor *this){ +void chRBBCog_update(Actor *this){ ActorLocal_RBB_27E0 *local = (ActorLocal_RBB_27E0 *)&this->local; - f32 sp28 = time_getDelta(); + f32 time_delta = time_getDelta(); + if(!this->volatile_initialized){ actor_collisionOff(this); this->marker->propPtr->unk8_3 = 1; - this->marker->actorFreeFunc = func_80388BE8; + this->marker->actorFreeFunc = chRBBCog_free; this->volatile_initialized = true; - if(this->modelCacheIndex == 0x17B){ + + if(this->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_set_fade_distances(local->sfxsourceIdx, 1000.0f, 2000.0f); sfxsource_set_position(local->sfxsourceIdx, this->position); @@ -63,24 +74,26 @@ void func_80388C20(Actor *this){ sfxsource_setSampleRate(local->sfxsourceIdx, 0); sfxSource_func_8030E2C4(local->sfxsourceIdx); }//L80388CFC - if(this->state == 0){ - if(this->modelCacheIndex == 0x17B){ + + if(this->state == CH_RBB_COG_STATE_0_NOT_INIT){ + if(this->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ TUPLE_ASSIGN(this->position, 0.0f, -50.0f, 700.0f); } - else if(this->modelCacheIndex == 0x17C){//L80388DA8 + else if(this->modelCacheIndex == ACTOR_17C_RBB_MEDIUM_COG){//L80388DA8 TUPLE_ASSIGN(this->position, 0.0f, -50.0f, 500.0f); } - else if(this->modelCacheIndex == 0x17D){ + else if(this->modelCacheIndex == ACTOR_17D_RBB_LARGE_COG){ TUPLE_ASSIGN(this->position, 0.0f, -50.0f, 300.0f); } - func_80388BD0(this, 1); + chRBBCog_setState(this, CH_RBB_COG_STATE_1_INIT); } }//L80388DA8 - if(this->state == 1){ - this->roll += D_8039041C[this->modelCacheIndex - 0x17B]*sp28; + + if(this->state == CH_RBB_COG_STATE_1_INIT){ + this->roll += chRBBCogRotateRates[this->modelCacheIndex - ACTOR_17B_RBB_SMALL_COG] * time_delta; if(360.0f <= this->roll) this->roll -= 360.0f; - if(this->modelCacheIndex == 0x17B){ + if(this->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ func_8030DB04(local->sfxsourceIdx, 25000, this->position, 1000.0f, 2000.0f); } } diff --git a/src/RBB/ch/dolphin.c b/src/RBB/ch/dolphin.c index 8731b461f..1f3bc6b15 100644 --- a/src/RBB/ch/dolphin.c +++ b/src/RBB/ch/dolphin.c @@ -8,48 +8,56 @@ ParticleEmitter *func_802EDD8C(f32 [3], f32, f32); void func_8038B900(Actor *this); /* .data */ -ActorInfo RBB_D_80390AB0 = { - 0x30, 0x1C8, 0x41C, 0x0, NULL, +ActorInfo chSnorkel = { + MARKER_30_SNORKEL, ACTOR_1C8_SNORKEL, ASSET_41C_MODEL_SNORKEL, + 0x0, NULL, NULL, func_8038B900, actor_draw, 0, 0, 0.0f, 0 }; +enum chsnorkel_state_e { + CH_SNORKEL_STATE_0_NOT_INIT, + CH_SNORKEL_STATE_1_TRAPPED, + CH_SNORKEL_STATE_2_FREED, + CH_SNORKEL_STATE_3_DESPAWN +}; + /* .code */ -void func_8038B880(Actor *this, s32 new_state){ - if(new_state == 1) +void chSnorkel_setState(Actor *this, s32 new_state){ + if(new_state == CH_SNORKEL_STATE_1_TRAPPED) skeletalAnim_set(this->unk148, ASSET_13F_ANIM_SNORKEL_STUCK, 0.0f, 5.5f); - if(new_state == 2) + if(new_state == CH_SNORKEL_STATE_2_FREED) skeletalAnim_swap(this->unk148, ASSET_13E_ANIM_SNORKEL_SWIM, 1.0f, 0.65f); this->state = new_state; } void func_8038B900(Actor *this){ - f32 sp5C; - f32 sp58; - f32 sp54; + f32 prev_anim_progress; + f32 curr_anim_progress; + f32 anim_progress; f32 sp48[3]; ParticleEmitter *other; this->marker->propPtr->unk8_3 = 1; if(this->marker->unk14_21){ - sp54 = skeletalAnim_getProgress(this->unk148); + anim_progress = skeletalAnim_getProgress(this->unk148); if( ( globalTimer_getTime() & (1 << 4) ) && ( globalTimer_getTime() & (1 << 2) ) && ( randf() < 0.90 ) ){ - if( ( this->state == 3 - && (0.255 <= sp54 && sp54 <= 0.856) + if( ( this->state == CH_SNORKEL_STATE_3_DESPAWN + && (0.255 <= anim_progress && anim_progress <= 0.856) ) - || ( this->state == 1 - && ( (0.053 <= sp54 && sp54 <= 0.35) - || (0.39 <= sp54 && sp54 <= 0.44999999999999996) - || (0.45999999999999996 <= sp54 && sp54 <= 0.52) - || (0.54 <= sp54 && sp54 <= 0.73) - || (0.76 <= sp54 && sp54 <= 0.8200000000000001) - || (0.84 <= sp54 && sp54 <= 0.9) - || (0.94 <= sp54 && sp54 <= 1.0) + || ( this->state == CH_SNORKEL_STATE_1_TRAPPED + && ( (0.053 <= anim_progress && anim_progress <= 0.35) + || (0.39 <= anim_progress && anim_progress <= 0.44999999999999996) + || (0.45999999999999996 <= anim_progress && anim_progress <= 0.52) + || (0.54 <= anim_progress && anim_progress <= 0.73) + || (0.76 <= anim_progress && anim_progress <= 0.8200000000000001) + || (0.84 <= anim_progress && anim_progress <= 0.9) + || (0.94 <= anim_progress && anim_progress <= 1.0) ) ) ){//L8038BB24 @@ -70,45 +78,45 @@ void func_8038B900(Actor *this){ this->position_y = -2600.0f; this->position_z = 1460.0f; this->yaw = 0.0f; - func_8038B880(this, 1); + chSnorkel_setState(this, CH_SNORKEL_STATE_1_TRAPPED); if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)){ marker_despawn(this->marker); } } else{//L8038BC74 - skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); - if( sp5C < 0.22 && 0.22 <= sp58 ){ + skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress, &curr_anim_progress); + if( prev_anim_progress < 0.22 && 0.22 <= curr_anim_progress ){ func_8030E988(SFX_D1_SNORKEL_WAH, randf2(0.8f, 0.9f), 15000, this->position, 1500.0f, 2000.0f); } - if( sp5C < 0.54 && 0.54 <= sp58 ){ + if( prev_anim_progress < 0.54 && 0.54 <= curr_anim_progress ){ func_8030E988(SFX_D1_SNORKEL_WAH, randf2(0.9f, 1.0f), 19000, this->position, 1500.0f, 2000.0f); } - if(this->state == 1){ + if(this->state == CH_SNORKEL_STATE_1_TRAPPED){ if( !this->has_met_before - && subaddie_playerIsWithinSphereAndActive(this, 0x258) + && subaddie_playerIsWithinSphereAndActive(this, 600) && !player_movementGroup() ){ - gcdialog_showDialog(ASSET_B9B_DIALOG_SNORKEL_MEET, 4, 0, 0, 0, 0); - this->has_met_before = true; + gcdialog_showDialog(VER_SELECT(ASSET_B9B_DIALOG_SNORKEL_MEET, 0x970, 0, 0), 4, 0, 0, 0, 0); + this->has_met_before = TRUE; } } - if(this->state == 1){ - if(mapSpecificFlags_get(4)) - func_8038B880(this, 2); + if(this->state == CH_SNORKEL_STATE_1_TRAPPED){ + if(mapSpecificFlags_get(RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING)) + chSnorkel_setState(this, CH_SNORKEL_STATE_2_FREED); } - if(this->state == 2){ + if(this->state == CH_SNORKEL_STATE_2_FREED){ if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)) - func_8038B880(this, 3); + chSnorkel_setState(this, CH_SNORKEL_STATE_3_DESPAWN); } - if(this->state == 3){ + if(this->state == CH_SNORKEL_STATE_3_DESPAWN){ actor_update_func_80326224(this); if(0.99 < this->unk48){ - mapSpecificFlags_set(4, false); + mapSpecificFlags_set(RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING, false); marker_despawn(this->marker); } } diff --git a/src/RBB/ch/eggtoll1.c b/src/RBB/ch/eggtoll1.c index d91f13410..dbc55fd4c 100644 --- a/src/RBB/ch/eggtoll1.c +++ b/src/RBB/ch/eggtoll1.c @@ -5,79 +5,99 @@ extern void timed_exitStaticCamera(f32); +// Anchor: toll extension stage is actor-local (unk8), no flag; keyed by secondaryId. +extern void port_eggToll_onAdvance(s32 map, s32 secondaryId, s32 stage); +extern s32 port_eggToll_getStage(s32 map, s32 secondaryId); +extern ActorArray *suBaddieActorArray; + /* typedefs and declarations */ typedef struct { - s32 unk0; - s32 unk4; - s32 unk8; - s32 unkC; -}ActorLocal_RBB_0; + s32 eggsPaid; + s32 tollId; + s32 tollNum; // 0 for first toll; 1 for second toll + s32 unkC; // Either 0 or 3? +} ActorLocal_ChRBBEggToll; typedef struct { - u8 unk0; - u8 unk1; - u8 unk2; + u8 cameraNode; + u8 eggCost1; + u8 eggCost2; // Only used in Toll 2 //u8 pad3[1]; f32 unk4; s16 unk8; s16 unkA; s16 unkC; //u8 padE[2]; -}Struct_RBB_0_1; +} chRBBEggTollInfo; -void func_803866F4(Actor *this, s32 arg1); -void func_803868F0(Actor* this); +void chRBBEggToll_setState(Actor *this, s32 next_state); +void chRBBEggToll_update(Actor* this); /* .data */ -ActorInfo D_80390050 = { +ActorInfo chRBBEggToll = { MARKER_182_RBB_EGG_TOLL, ACTOR_172_RBB_EGG_TOLL, ASSET_402_MODEL_EGG_TOLL, 0x0, NULL, - func_803868F0, NULL, func_80325340, + chRBBEggToll_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; -Struct_RBB_0_1 D_80390074[4] = { +chRBBEggTollInfo chRBBEggTollInfoTable[4] = { {0x0, 0x2, 0x4, 3.0f, 550, 200, -300}, {0x1, 0x4, 0x0, 4.0f, -600, 0, 0}, {0x2, 0x6, 0x0, 4.0f, -700, 0, 0}, {0x3, 0x8, 0x0, 4.0f, -1010, 0, 0} }; +enum chrbbeggtoll_state_e { + CH_RBB_EGG_TOLL_STATE_0_NOT_INIT, + CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL, + CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID, + CH_RBB_EGG_TOLL_STATE_3_TOLL_COMPLETE, + CH_RBB_EGG_TOLL_STATE_4_UNK +}; + /* .code */ +static s32 eggToll_countForStage(s32 tollIdx, s32 stage) { + s32 count = 0; + if (stage >= 1) count += chRBBEggTollInfoTable[tollIdx].eggCost1; + if (stage >= 2) count += chRBBEggTollInfoTable[tollIdx].eggCost2; + return count; +} + void RBB_func_803863F0(Actor *actor, s32 arg1){ - ActorLocal_RBB_0 * local = (ActorLocal_RBB_0 *) &actor->local; + ActorLocal_ChRBBEggToll * local = (ActorLocal_ChRBBEggToll *) &actor->local; void *temp_a0; f32 sp3C[3]; f32 sp30[3]; - temp_a0 = func_8034C528(local->unk4 + 0x190); + temp_a0 = func_8034C528(local->tollId + 0x190); if(temp_a0){ - if(local->unk8 == 0){ + if(local->tollNum == 0){ sp3C[2] = 0.0f; sp30[0] = 0.0f; sp30[1] = 0.0f; sp3C[0] = sp3C[1] = sp3C[2]; - sp30[2] = (f32) D_80390074[local->unk4].unk8; + sp30[2] = (f32) chRBBEggTollInfoTable[local->tollId].unk8; } - else if(local->unk8 == 1){ + else if(local->tollNum == 1){ sp3C[0] = 0.0f; sp3C[1] = 0.0f; - sp3C[2] = (f32) D_80390074[local->unk4].unk8; + sp3C[2] = (f32) chRBBEggTollInfoTable[local->tollId].unk8; sp30[1] = 0.0f; sp30[0] = 0.0f; - sp30[2] = (f32) D_80390074[local->unk4].unkA; + sp30[2] = (f32) chRBBEggTollInfoTable[local->tollId].unkA; } else{ sp3C[0] = 0.0f; sp3C[1] = 0.0f; - sp3C[2] = (f32) D_80390074[local->unk4].unkA; + sp3C[2] = (f32) chRBBEggTollInfoTable[local->tollId].unkA; sp30[1] = 0.0f; sp30[0] = 0.0f; - sp30[2] = (f32) D_80390074[local->unk4].unkC; + sp30[2] = (f32) chRBBEggTollInfoTable[local->tollId].unkC; } if(arg1){ - func_8034DDF0(temp_a0, sp3C, sp30, D_80390074[local->unk4].unk4, 1); + func_8034DDF0(temp_a0, sp3C, sp30, chRBBEggTollInfoTable[local->tollId].unk4, 1); func_8034E174(temp_a0); } else{ @@ -87,84 +107,115 @@ void RBB_func_803863F0(Actor *actor, s32 arg1){ } void func_803865A4(ActorMarker *marker, s32 arg1){ - func_803866F4(marker_getActor(marker), arg1); + chRBBEggToll_setState(marker_getActor(marker), arg1); } void func_803865D0(ActorMarker *marker){ Actor* actor = marker_getActor(marker); - ActorLocal_RBB_0 * local = (ActorLocal_RBB_0 *) &actor->local; + ActorLocal_ChRBBEggToll * local = (ActorLocal_ChRBBEggToll *) &actor->local; RBB_func_803863F0(actor, 1); - timed_setStaticCameraToNode(0.0f, D_80390074[local->unk4].unk0); - timedFunc_set_2(0.75*D_80390074[local->unk4].unk4, (GenFunction_2) func_803865A4, (uintptr_t)actor->marker, 4); - timed_exitStaticCamera(0.75*D_80390074[local->unk4].unk4); - func_80324E38(0.75*D_80390074[local->unk4].unk4, 0); - timed_playSfx(D_80390074[local->unk4].unk4, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 0x7fd0); + timed_setStaticCameraToNode(0.0f, chRBBEggTollInfoTable[local->tollId].cameraNode); + timedFunc_set_2(0.75 * chRBBEggTollInfoTable[local->tollId].unk4, (GenFunction_2) func_803865A4, (uintptr_t)actor->marker, 4); + timed_exitStaticCamera(0.75 * chRBBEggTollInfoTable[local->tollId].unk4); + func_80324E38(0.75 * chRBBEggTollInfoTable[local->tollId].unk4, 0); + timed_playSfx(chRBBEggTollInfoTable[local->tollId].unk4, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 0x7FD0); } -void func_803866F4(Actor *this, s32 arg1){ - ActorLocal_RBB_0 *local = (ActorLocal_RBB_0 *) &this->local; +void chRBBEggToll_setState(Actor *this, s32 next_state){ + ActorLocal_ChRBBEggToll *local = (ActorLocal_ChRBBEggToll *) &this->local; - if(arg1 == 2){ + if(next_state == CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID){ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - local = (ActorLocal_RBB_0 *) &this->local; + local = (ActorLocal_ChRBBEggToll *) &this->local; local->unkC = 3; } - if(arg1 == 3){ - local->unk8++; + if(next_state == CH_RBB_EGG_TOLL_STATE_3_TOLL_COMPLETE){ + local->tollNum++; + port_eggToll_onAdvance((s32)gsworld_getMap(), this->secondaryId, local->tollNum); coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); func_80324E38(0.0f, 3); timedFunc_set_2(0.5f, (GenFunction_2) coMusicPlayer_playMusic, COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); timedFunc_set_1(1.0f, (GenFunction_1) func_803865D0, (uintptr_t)this->marker); }//L803867D4 - if(arg1 == 4){ - if(local->unk8 == 1 && D_80390074[local->unk4].unk2 > 0){ - func_803866F4(this, 1); + + if(next_state == CH_RBB_EGG_TOLL_STATE_4_UNK){ + if(local->tollNum == 1 && chRBBEggTollInfoTable[local->tollId].eggCost2 > 0){ + chRBBEggToll_setState(this, CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL); return; } } - this->state = arg1; + this->state = next_state; } void func_8038685C(ActorMarker *marker){ Actor *actor = marker_getActor(marker); - ActorLocal_RBB_0 *local = (ActorLocal_RBB_0 *) &actor->local; + ActorLocal_ChRBBEggToll *local = (ActorLocal_ChRBBEggToll *) &actor->local; - if(actor->state == 1){ - local->unk0++; - if( D_80390074[local->unk4].unk1 == local->unk0 - || D_80390074[local->unk4].unk1 + D_80390074[local->unk4].unk2 == local->unk0 + if(actor->state == CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL){ + local->eggsPaid++; + if( chRBBEggTollInfoTable[local->tollId].eggCost1 == local->eggsPaid + || chRBBEggTollInfoTable[local->tollId].eggCost1 + chRBBEggTollInfoTable[local->tollId].eggCost2 == local->eggsPaid ){ - func_803866F4(actor, 3); + chRBBEggToll_setState(actor, CH_RBB_EGG_TOLL_STATE_3_TOLL_COMPLETE); }else{ - func_803866F4(actor, 2); + chRBBEggToll_setState(actor, CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID); } } } -void func_803868F0(Actor *this){ - ActorLocal_RBB_0 *local = (ActorLocal_RBB_0 *) &this->local; +void chRBBEggToll_update(Actor *this){ + ActorLocal_ChRBBEggToll *local = (ActorLocal_ChRBBEggToll *) &this->local; if(!this->volatile_initialized){ this->volatile_initialized = true; - if(this->state == 0){ - local->unk0 = 0; - local->unk4 = 0; - local->unk8 = 0; + if(this->state == CH_RBB_EGG_TOLL_STATE_0_NOT_INIT){ + local->eggsPaid = 0; + local->tollId = 0; + local->tollNum = 0; local->unkC = 0; - local->unk4 = (this->secondaryId == 0x15)? 0: local->unk4; - local->unk4 = (this->secondaryId == 0x13)? 1: local->unk4; - local->unk4 = (this->secondaryId == 0x14)? 2: local->unk4; - local->unk4 = (this->secondaryId == 0xB)? 3: local->unk4; - func_803866F4(this, 1); + local->tollId = (this->secondaryId == 0x15)? 0: local->tollId; + local->tollId = (this->secondaryId == 0x13)? 1: local->tollId; + local->tollId = (this->secondaryId == 0x14)? 2: local->tollId; + local->tollId = (this->secondaryId == 0x0B)? 3: local->tollId; + local->tollNum = port_eggToll_getStage((s32)gsworld_getMap(), this->secondaryId); + local->eggsPaid = eggToll_countForStage(local->tollId, local->tollNum); + chRBBEggToll_setState(this, CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL); } RBB_func_803863F0(this, 0); }//L803869F4 - if(this->state == 2){ + if(this->state == CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID){ if(--local->unkC <= 0){ - func_803866F4(this, 1); + chRBBEggToll_setState(this, CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL); } } } + +void port_eggToll_remoteApply(s32 map, s32 secondaryId, s32 stage) { + s32 i; + (void)map; + + if (suBaddieActorArray == NULL) { + return; + } + for (i = 0; i < suBaddieActorArray->cnt; i++) { + Actor *actor = &suBaddieActorArray->data[i]; + ActorLocal_ChRBBEggToll *local; + if (actor->marker == NULL || actor->marker->id != MARKER_182_RBB_EGG_TOLL) { + continue; + } + if (actor->secondaryId != secondaryId) { + continue; + } + local = (ActorLocal_ChRBBEggToll *) &actor->local; + if (stage > local->tollNum) { + local->tollNum = stage; + local->eggsPaid = eggToll_countForStage(local->tollId, stage); + RBB_func_803863F0(actor, 1); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); + } + return; + } +} diff --git a/src/RBB/ch/enginefan.c b/src/RBB/ch/enginefan.c index 6c9e30265..86c251635 100644 --- a/src/RBB/ch/enginefan.c +++ b/src/RBB/ch/enginefan.c @@ -22,7 +22,7 @@ typedef struct { f32 unk28; }ActorLocal_RBB_2E90; -void func_8038944C(Actor *this); +void chEngineRoomPropeller_update(Actor *this); /* .data */ @@ -57,24 +57,35 @@ Struct_RBB_2E90_0 D_80390530[] = { {0} }; -ActorInfo D_80390640 = { - MARKER_191_ENGINE_ROOM_PROPELLOR_1, ACTOR_1BB_ENGINE_ROOM_PROPELLOR_1, ASSET_40F_MODEL_ENGINE_ROOM_PROPELLER_1, 0x0, NULL, - func_8038944C, NULL, actor_draw, +ActorInfo chEngineRoomPropeller1 = { + MARKER_191_ENGINE_ROOM_PROPELLOR_1, ACTOR_1BB_ENGINE_ROOM_PROPELLOR_1, ASSET_40F_MODEL_ENGINE_ROOM_PROPELLER_1, + 0x0, NULL, + chEngineRoomPropeller_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390664 = { - MARKER_192_ENGINE_ROOM_PROPELLOR_2, ACTOR_1BC_ENGINE_ROOM_PROPELLOR_2, ASSET_410_MODEL_ENGINE_ROOM_PROPELLER_2, 0x0, NULL, - func_8038944C, NULL, actor_draw, +ActorInfo chEngineRoomPropeller2 = { + MARKER_192_ENGINE_ROOM_PROPELLOR_2, ACTOR_1BC_ENGINE_ROOM_PROPELLOR_2, ASSET_410_MODEL_ENGINE_ROOM_PROPELLER_2, + 0x0, NULL, + chEngineRoomPropeller_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390688 = { - MARKER_193_ENGINE_ROOM_PROPELLOR_3, ACTOR_1BD_ENGINE_ROOM_PROPELLOR_3, ASSET_411_MODEL_ENGINE_ROOM_PROPELLER_3, 0x0, NULL, - func_8038944C, NULL, actor_draw, +ActorInfo chEngineRoomPropeller3 = { + MARKER_193_ENGINE_ROOM_PROPELLOR_3, ACTOR_1BD_ENGINE_ROOM_PROPELLOR_3, ASSET_411_MODEL_ENGINE_ROOM_PROPELLER_3, + 0x0, NULL, + chEngineRoomPropeller_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; +enum chengineroompropeller_state_e { + CH_ENGINE_ROOM_PROPELLER_STATE_0_NOT_INIT, + CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK, + CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK, + CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK, + CH_ENGINE_ROOM_PROPELLER_STATE_4_UNK +}; + /* .code */ Struct_RBB_2E90_0 * func_80389280(Actor *this){ Struct_RBB_2E90_0 * iPtr; @@ -85,13 +96,13 @@ Struct_RBB_2E90_0 * func_80389280(Actor *this){ return NULL; } -void func_803892D8(Actor *this, s32 arg1){ +void chEngineRoomPropeller_setState(Actor *this, s32 next_state){ f32 pad; ActorLocal_RBB_2E90 *local = (ActorLocal_RBB_2E90 *)&this->local; - this->state = arg1; + this->state = next_state; local->unk28 = 0.0f; - if(this->state == 1){ + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK){ local->unk0[2] = 0.0f; local->unk0[1] = 0.0f; local->unk0[0] = 0.0f; @@ -99,19 +110,19 @@ void func_803892D8(Actor *this, s32 arg1){ ml_vec3f_copy(local->unk1C, local->unkC->unk1C); }//L8038935C - if(this->state == 2){ + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK){ ml_vec3f_copy(local->unk0, local->unkC->unk28); ml_vec3f_copy(local->unk1C, local->unkC->unk10); local->unk28 = local->unkC->unk40; }//L803893A8 - if(this->state == 3){ + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK){ ml_vec3f_copy(local->unk0, local->unkC->unk28); ml_vec3f_copy(local->unk1C, local->unkC->unk1C); local->unk28 = local->unkC->unk40; }//L803893F4 - if(this->state == 4){ + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_4_UNK){ ml_vec3f_copy(local->unk0, local->unkC->unk34); ml_vec3f_copy(local->unk10, local->unkC->unk1C); local->unk1C[2] = 0.0f; @@ -120,12 +131,12 @@ void func_803892D8(Actor *this, s32 arg1){ } } -void func_8038944C(Actor *this){ +void chEngineRoomPropeller_update(Actor *this){ ActorLocal_RBB_2E90 *local = (ActorLocal_RBB_2E90 *)&this->local; f32 tick; int i; - f32 sp50[3]; - f32 sp44[3]; + f32 current_rotation[3]; + f32 next_rotation[3]; tick = time_getDelta(); @@ -133,69 +144,72 @@ void func_8038944C(Actor *this){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unkC = func_80389280(this); - if(this->state == 0){ + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_0_NOT_INIT){ ml_vec3f_copy(this->position, local->unkC->unk4); local->unk0[0] = local->unk0[1] = local->unk0[2] = 0.0f; local->unk10[0] = local->unk10[1] = local->unk10[2] = 0.0f; local->unk1C[0] = local->unk1C[1] = local->unk1C[2] = 0.0f; local->unk28 = 0.0f; - func_803892D8(this, 1); + chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK); } }//L80389508 if(ml_timer_update(&local->unk28, tick)){ - if(this->state == 2) - func_803892D8(this, 3); - else if(this->state == 3) - func_803892D8(this, 2); + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK) + chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK); + else if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK) + chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK); }//L80389568 switch (this->state) { - case 1: - case 2: - case 3: - case 4: - sp50[0] = this->pitch; - sp50[1] = this->yaw; - sp50[2] = this->roll; - this->pitch += local->unk10[0]*tick ; - this->yaw += local->unk10[1]*tick ; - this->roll += local->unk10[2]*tick ; - - sp44[0] = this->pitch; - sp44[1] = this->yaw; - sp44[2] = this->roll; - - for(i = 0; i < 3; i++){ - if( (sp50[i] < 90.0f && 90.0f <= sp44[i]) - || (sp50[i] < 270.0f && 270.0f <= sp44[i]) - || (sp50[i] < 180.0f && 180.0f <= sp44[i]) - || (sp50[i] < 360.0f && 360.0f <= sp44[i]) - ){ - sfx_playFadeShorthandDefault(SFX_2_CLAW_SWIPE, 0.4f, 23000, this->position, 50, 1000); - } - } - this->pitch += (360.0f <= this->pitch)? -360 : 0; - this->yaw += (360.0f <= this->yaw)? -360 : 0; - this->roll += (360.0f <= this->roll)? -360 : 0; - - for(i = 0; i < 3; i++){//L803897B8 - if( local->unk10[i] < local->unk1C[i] ){ - local->unk10[i] += local->unk0[i]*tick; - local->unk10[i] = MIN(local->unk1C[i] , local->unk10[i]); + case CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK: + case CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK: + case CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK: + case CH_ENGINE_ROOM_PROPELLER_STATE_4_UNK: + current_rotation[0] = this->pitch; + current_rotation[1] = this->yaw; + current_rotation[2] = this->roll; + + this->pitch += local->unk10[0] * tick; + this->yaw += local->unk10[1] * tick; + this->roll += local->unk10[2] * tick; + + next_rotation[0] = this->pitch; + next_rotation[1] = this->yaw; + next_rotation[2] = this->roll; + + for(i = 0; i < 3; i++){ + if( (current_rotation[i] < 90.0f && 90.0f <= next_rotation[i]) + || (current_rotation[i] < 270.0f && 270.0f <= next_rotation[i]) + || (current_rotation[i] < 180.0f && 180.0f <= next_rotation[i]) + || (current_rotation[i] < 360.0f && 360.0f <= next_rotation[i]) + ){ + sfx_playFadeShorthandDefault(SFX_2_CLAW_SWIPE, 0.4f, 23000, this->position, 50, 1000); + } } - else if( local->unk1C[i] < local->unk10[i]){ - local->unk10[i] -= local->unk0[i]*tick; - local->unk10[i] = MAX(local->unk1C[i] , local->unk10[i]); + this->pitch += (360.0f <= this->pitch)? -360 : 0; + this->yaw += (360.0f <= this->yaw)? -360 : 0; + this->roll += (360.0f <= this->roll)? -360 : 0; + + for(i = 0; i < 3; i++){//L803897B8 + if( local->unk10[i] < local->unk1C[i] ){ + local->unk10[i] += local->unk0[i] * tick; + local->unk10[i] = MIN(local->unk1C[i] , local->unk10[i]); + } + else if( local->unk1C[i] < local->unk10[i]){ + local->unk10[i] -= local->unk0[i] * tick; + local->unk10[i] = MAX(local->unk1C[i] , local->unk10[i]); + } } - } - break; + break; }//L80389860 - if(this->state == 1 && mapSpecificFlags_get(0)){ - func_803892D8(this, 2); + if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK + && mapSpecificFlags_get(RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER)) + { + chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK); } if(tick); } diff --git a/src/RBB/ch/enginefanswitch.c b/src/RBB/ch/enginefanswitch.c index 7238b2b36..8b0937b79 100644 --- a/src/RBB/ch/enginefanswitch.c +++ b/src/RBB/ch/enginefanswitch.c @@ -3,28 +3,37 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + void chEngineFanSwitch_update(Actor *this); /* .data */ -ActorInfo D_803906B0 = { - 0x194, 0x1BE, 0x412, 0x0, NULL, +ActorInfo chRBBGreyPropellerSwitch = { + MARKER_194_RBB_GREY_PROPELLER_SWITCH, ACTOR_1BE_RBB_GREY_PROPELLOR_SWITCH, ASSET_412_MODEL_RBB_GREY_PROPELLER_SWITCH, + 0x0, NULL, chEngineFanSwitch_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; +enum chrbbgreypropellerswitch_state_e { + CH_RBB_GREY_PROPELLER_SWITCH_STATE_0_NOT_INIT, + CH_RBB_GREY_PROPELLER_SWITCH_STATE_1_NOT_PRESSED, + CH_RBB_GREY_PROPELLER_SWITCH_STATE_2_PRESSED +}; + /* .code */ -void RBB_func_803898A0(void){ - mapSpecificFlags_set(0, 1); +void chEngineFanSwitch_setPressedFlag(void){ + mapSpecificFlags_set(RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER, true); } void chEngineFanSwitch_setState(Actor * this, s32 arg1){ this->state = arg1; - if(this->state == 2){ + if(this->state == CH_RBB_GREY_PROPELLER_SWITCH_STATE_2_PRESSED){ func_8030E6D4(SFX_90_SWITCH_PRESS); this->position_y -= 35.0f; func_80324E38(1.0f, 3); timed_setStaticCameraToNode(1.0f, 0); - timedFunc_set_0(1.0f, RBB_func_803898A0); + timedFunc_set_0(1.0f, chEngineFanSwitch_setPressedFlag); timed_exitStaticCamera(5.0f); func_80324E38(5.0f, 0); } @@ -32,8 +41,8 @@ void chEngineFanSwitch_setState(Actor * this, s32 arg1){ void __chEngineFanSwitch_pressCallback(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - if(actor->state == 1){ - chEngineFanSwitch_setState(actor, 2); + if(actor->state == CH_RBB_GREY_PROPELLER_SWITCH_STATE_1_NOT_PRESSED){ + chEngineFanSwitch_setState(actor, CH_RBB_GREY_PROPELLER_SWITCH_STATE_2_PRESSED); } } @@ -41,14 +50,23 @@ void chEngineFanSwitch_update(Actor *this){ if(!this->volatile_initialized){ //initialize this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; - mapSpecificFlags_set(0, 0); + mapSpecificFlags_set(RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER, false); marker_setCollisionScripts(this->marker, NULL, __chEngineFanSwitch_pressCallback, NULL); - if(this->state == 0){ + if(this->state == CH_RBB_GREY_PROPELLER_SWITCH_STATE_0_NOT_INIT){ this->position_x = -3209.95f; this->position_y = 1164.5f; this->position_z = -2649.95f; this->yaw = -90.0f; - chEngineFanSwitch_setState(this, 1); + chEngineFanSwitch_setState(this, CH_RBB_GREY_PROPELLER_SWITCH_STATE_1_NOT_PRESSED); } } + // [port] Anchor temp-persist: the fan slowdown is transient map flag 0, set by pressing this + // switch (RBB_func_803898A0). It syncs live but resets on reload, so persist it + if(mapSpecificFlags_get(0)){ + port_puzzleStep_orBits(ANCHOR_PUZZLE_RBB_ENGINE_FANS, 1); + } else if((this->state == 1) && (port_puzzleStep_get(ANCHOR_PUZZLE_RBB_ENGINE_FANS) & 1)){ + this->position_y -= 35.0f; + this->state = 2; + mapSpecificFlags_set(0, 1); + } } diff --git a/src/RBB/ch/engineparts.c b/src/RBB/ch/engineparts.c index 59ffc0855..6515a0881 100644 --- a/src/RBB/ch/engineparts.c +++ b/src/RBB/ch/engineparts.c @@ -22,7 +22,7 @@ typedef struct { f32 unk1C; }ActorLocal_RBB_40F0; -void func_8038A724(Actor *this); +void chRBBSpinningPipe_update(Actor *this); /* .data */ Struct_RBB_40F0 D_80390760[4] = { @@ -32,65 +32,75 @@ Struct_RBB_40F0 D_80390760[4] = { {{ -300.0f, 641.5f, -400.0f}, {-500.0f, 0.0f, 0.0f}, 0x28, 1}, }; -ActorInfo D_803907D0 = { - 0x187, 0x177, 0x406, 0x0, NULL, - func_8038A724, NULL, actor_draw, +ActorInfo chRBBSpinningSinglePipe1 = { + MARKER_187_RBB_SPINNING_SINGLE_PIPE_1, ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1, ASSET_406_MODEL_RBB_SPINNING_SINGLE_PIPE, 0x0, NULL, + chRBBSpinningPipe_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_803907F4 = { - 0x18E, 0x17E, 0x406, 0x0, NULL, - func_8038A724, NULL, actor_draw, +ActorInfo chRBBSpinningSinglePipe2 = { + MARKER_18E_RBB_SPINNING_SINGLE_PIPE_2, ACTOR_17E_RBB_SPINNING_SINGLE_PIPE_2, ASSET_406_MODEL_RBB_SPINNING_SINGLE_PIPE, + 0x0, NULL, + chRBBSpinningPipe_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80390818 = { - 0x18F, 0x17F, 0x407, 0x0, NULL, - func_8038A724, NULL, actor_draw, +ActorInfo chRBBSpinningDoublePipe1 = { + MARKER_18F_RBB_SPINNING_DOUBLE_PIPE_1, ACTOR_17F_RBB_SPINNING_DOUBLE_PIPE_1, ASSET_407_MODEL_RBB_SPINNING_DOUBLEE_PIPE_RIGHT, + 0x0, NULL, + chRBBSpinningPipe_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_8039083C = { - 0x190, 0x180, 0x408, 0x0, NULL, - func_8038A724, NULL, actor_draw, +ActorInfo chRBBSpinningDoublePipe2 = { + MARKER_190_RBB_SPINNING_DOUBLE_PIPE_2, ACTOR_180_RBB_SPINNING_DOUBLE_PIPE_2, ASSET_408_MODEL_RBB_SPINNING_DOUBLEE_PIPE_LEFT, + 0x0, NULL, + chRBBSpinningPipe_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; f32 D_80390860[3] = {1.0f, 0.5f, 0.5f}; +enum chrbbspinningpipe_state_e { + CH_RBB_SPINNING_PIPE_STATE_0_NOT_INIT, + CH_RBB_SPINNING_PIPE_STATE_1_UNK, + CH_RBB_SPINNING_PIPE_STATE_2_UNK, + CH_RBB_SPINNING_PIPE_STATE_3_UNK +}; + /* .code */ f32 func_8038A4E0(void) { return D_80390860[2 * levelSpecificFlags_get(LEVEL_FLAG_27_RBB_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_28_RBB_UNKNOWN)]; } -void func_8038A524(Actor *this, s32 arg1){ +void chRBBSpinningPipe_setState(Actor *this, s32 next_state){ ActorLocal_RBB_40F0 *local = (ActorLocal_RBB_40F0 *)&this->local; local->unk1C = 0.0f; - if(arg1 == 1){ + if(next_state == CH_RBB_SPINNING_PIPE_STATE_1_UNK){ if(D_80390760[local->unk0].unk1A){ - func_8038A524(this, 2); + chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_2_UNK); return; } - local->unk10[0] = D_80390760[local->unk0].unkC[0]*func_8038A4E0(); - local->unk10[1] = D_80390760[local->unk0].unkC[1]*func_8038A4E0(); - local->unk10[2] = D_80390760[local->unk0].unkC[2]*func_8038A4E0(); + local->unk10[0] = D_80390760[local->unk0].unkC[0] * func_8038A4E0(); + local->unk10[1] = D_80390760[local->unk0].unkC[1] * func_8038A4E0(); + local->unk10[2] = D_80390760[local->unk0].unkC[2] * func_8038A4E0(); } - if(arg1 == 2){ - local->unk10[0] = D_80390760[local->unk0].unkC[0]*func_8038A4E0(); - local->unk10[1] = D_80390760[local->unk0].unkC[1]*func_8038A4E0(); - local->unk10[2] = D_80390760[local->unk0].unkC[2]*func_8038A4E0(); + if(next_state == CH_RBB_SPINNING_PIPE_STATE_2_UNK){ + local->unk10[0] = D_80390760[local->unk0].unkC[0] * func_8038A4E0(); + local->unk10[1] = D_80390760[local->unk0].unkC[1] * func_8038A4E0(); + local->unk10[2] = D_80390760[local->unk0].unkC[2] * func_8038A4E0(); } - if(arg1 == 3){ + if(next_state == CH_RBB_SPINNING_PIPE_STATE_3_UNK){ local->unk10[2] = 0.0f; local->unk10[1] = 0.0f; local->unk10[0] = 0.0f; } - this->state = arg1; + this->state = next_state; } f32 func_8038A6B8(ActorMarker *marker){ @@ -102,13 +112,13 @@ f32 func_8038A6B8(ActorMarker *marker){ for(i = 0; i < 3; i++){ f12 += ABS(local->unk4[i]); } - return f12/500.0f; + return f12 / 500.0f; } -void func_8038A724(Actor *this){ +void chRBBSpinningPipe_update(Actor *this){ ActorLocal_RBB_40F0 *local = (ActorLocal_RBB_40F0 *)&this->local; int i; - f32 sp1C = time_getDelta(); + f32 time_delta = time_getDelta(); if(!this->volatile_initialized){ @@ -116,41 +126,41 @@ void func_8038A724(Actor *this){ this->volatile_initialized = true; actor_collisionOff(this); local->unk0 = 0; - local->unk0 = (this->modelCacheIndex == 0x17E) ? 1: local->unk0; - local->unk0 = (this->modelCacheIndex == 0x17F) ? 2: local->unk0; - local->unk0 = (this->modelCacheIndex == 0x180) ? 3: local->unk0; + local->unk0 = (this->modelCacheIndex == ACTOR_17E_RBB_SPINNING_SINGLE_PIPE_2) ? 1: local->unk0; + local->unk0 = (this->modelCacheIndex == ACTOR_17F_RBB_SPINNING_DOUBLE_PIPE_1) ? 2: local->unk0; + local->unk0 = (this->modelCacheIndex == ACTOR_180_RBB_SPINNING_DOUBLE_PIPE_2) ? 3: local->unk0; this->position_x = D_80390760[local->unk0].unk0[0]; this->position_y = D_80390760[local->unk0].unk0[1]; this->position_z = D_80390760[local->unk0].unk0[2]; - func_8038A524(this, 1); + chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_1_UNK); }//L8038A884 - this->pitch += local->unk4[0]*sp1C; - this->yaw += local->unk4[1]*sp1C; - this->roll += local->unk4[2]*sp1C; + this->pitch += local->unk4[0] * time_delta; + this->yaw += local->unk4[1] * time_delta; + this->roll += local->unk4[2] * time_delta; for(i = 0; i < 3; i++){//L8038A8D4 if(local->unk10[i] < local->unk4[i]){ - local->unk4[i] -= 75.0f*sp1C; + local->unk4[i] -= 75.0f * time_delta; local->unk4[i] = MAX(local->unk10[i], local->unk4[i]); }//L8038A924 else if(local->unk4[i] < local->unk10[i]){ - local->unk4[i] += 75.0f*sp1C; + local->unk4[i] += 75.0f * time_delta; local->unk4[i] = MIN(local->unk10[i], local->unk4[i]); } } - if(this->state == 1){ - local->unk10[0] = D_80390760[local->unk0].unkC[0]*func_8038A4E0(); - local->unk10[1] = D_80390760[local->unk0].unkC[1]*func_8038A4E0(); - local->unk10[2] = D_80390760[local->unk0].unkC[2]*func_8038A4E0(); + if(this->state == CH_RBB_SPINNING_PIPE_STATE_1_UNK){ + local->unk10[0] = D_80390760[local->unk0].unkC[0] * func_8038A4E0(); + local->unk10[1] = D_80390760[local->unk0].unkC[1] * func_8038A4E0(); + local->unk10[2] = D_80390760[local->unk0].unkC[2] * func_8038A4E0(); } - if(this->state == 2){ + if(this->state == CH_RBB_SPINNING_PIPE_STATE_2_UNK){ if(0.0f < local->unk1C){ - if(ml_timer_update(&local->unk1C, sp1C)){ - func_8038A524(this, 3); + if(ml_timer_update(&local->unk1C, time_delta)){ + chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_3_UNK); }//L8038AA8C }else{ if( local->unk4[0] == local->unk10[0] @@ -162,10 +172,10 @@ void func_8038A724(Actor *this){ } }//L8038AB04 - if(this->state == 3){ + if(this->state == CH_RBB_SPINNING_PIPE_STATE_3_UNK){ if(0.0f < local->unk1C){ - if(ml_timer_update(&local->unk1C, sp1C)){ - func_8038A524(this, 2); + if(ml_timer_update(&local->unk1C, time_delta)){ + chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_2_UNK); }//L8038AA8C }else{ if( local->unk4[0] == local->unk10[0] diff --git a/src/RBB/ch/grimlet.c b/src/RBB/ch/grimlet.c index 8005b2884..194a093b8 100644 --- a/src/RBB/ch/grimlet.c +++ b/src/RBB/ch/grimlet.c @@ -14,27 +14,34 @@ typedef struct { f32 unk14; }ActorLocal_RBB_1FC0; -Actor *func_8038846C(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void func_80388620(Actor *this); +Actor *chGrimlet_draw(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chGrimlet_update(Actor *this); /* .data */ -ActorInfo D_80390380 = { - MARKER_2E_GRIMLET, ACTOR_1C6_GRIMLET, ASSET_419_MODEL_GRIMLET, 0x0, NULL, - func_80388620, NULL, func_8038846C, +ActorInfo chGrimlet = { + MARKER_2E_GRIMLET, ACTOR_1C6_GRIMLET, ASSET_419_MODEL_GRIMLET, + 0x0, NULL, + chGrimlet_update, NULL, chGrimlet_draw, 0, 0, 0.0f, 0 }; +enum chgrimlet_state_e { + CH_GRIMLET_STATE_0_NOT_INIT, + CH_GRIMLET_STATE_1_UNK, + CH_GRIMLET_STATE_2_UNK +}; + /* .code */ -void func_803883B0(Actor *this, s32 arg1){ +void chGrimlet_setState(Actor *this, s32 next_state){ ActorLocal_RBB_1FC0 *local = (ActorLocal_RBB_1FC0 *)&this->local; local->unk5 = 0; - if(arg1 == 2){ + if(next_state == CH_GRIMLET_STATE_2_UNK){ FUNC_8030E624(SFX_66_BIRD_AUUGHH, 0.6f, 32675); - skeletalAnim_set(this->unk148, 0x137, 0.0f, 0.8f); + skeletalAnim_set(this->unk148, ASSET_137_ANIM_GRIMLET_ATTACK, 0.0f, 0.8f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } - this->state = arg1; + this->state = next_state; } void RBB_func_80388430(ActorMarker * marker, ActorMarker *other_marker){ @@ -44,7 +51,7 @@ void RBB_func_80388430(ActorMarker * marker, ActorMarker *other_marker){ local->unk5 = 1; } -Actor *func_8038846C(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ +Actor *chGrimlet_draw(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ Actor *actor = marker_getActor(marker); ActorLocal_RBB_1FC0 *local = (ActorLocal_RBB_1FC0 *) &actor->local; BoneTransformList *sp5C; @@ -53,7 +60,7 @@ Actor *func_8038846C(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ f32 sp40[3]; f32 sp34[3]; - if(actor->state == 0){ + if(actor->state == CH_GRIMLET_STATE_0_NOT_INIT){ return actor; } @@ -77,22 +84,22 @@ Actor *func_8038846C(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ func_8033A968(sp5C, 0x12, sp34); skeletalAnim_func_80335918(actor->unk148); } - func_8033A45C(3, (0.0f < local->unk8)? 1 : 0); - func_8033A45C(4, (0.0f < local->unk8)? 1 : 0); + modelRender_setAppendageVisibility(3, (0.0f < local->unk8)? 1 : 0); + modelRender_setAppendageVisibility(4, (0.0f < local->unk8)? 1 : 0); actor_draw(marker, gdl, mptr, vtx); local->unk4 = actor->marker->unk14_21; return actor; } -void func_80388620(Actor *this){ +void chGrimlet_update(Actor *this){ f32 plyr_pos[3]; - f32 sp60; - f32 sp5C; - f32 sp58; + f32 horizontal_distance; + f32 distance_in_front; + f32 side_angle_radian; ActorLocal_RBB_1FC0 *local = (ActorLocal_RBB_1FC0 *)&this->local; - f32 sp50 = time_getDelta(); - f32 sp4C; - f32 sp48; + f32 time_delta = time_getDelta(); + f32 prev_anim_progress; + f32 curr_anim_progress; f32 tmp_f2; if(!this->volatile_initialized){ @@ -105,80 +112,84 @@ void func_80388620(Actor *this){ local->unkC = 0.0f; local->unk10 = 0.0f; local->unk14 = 0.0f; - func_803883B0(this, 1); + chGrimlet_setState(this, CH_GRIMLET_STATE_1_UNK); } player_getPosition(plyr_pos); - func_80258A4C(this->position, this->yaw + -90.0f, plyr_pos, &sp60, &sp5C, &sp58); - if(sp60 < 600.0f) + func_80258A4C( + this->position, this->yaw + -90.0f, plyr_pos, + &horizontal_distance, &distance_in_front, &side_angle_radian); + if(horizontal_distance < 600.0f) local->unk8 = 1.0f; else{ - local->unk8 -= sp50; + local->unk8 -= time_delta; local->unk8 = MAX(0.0f, local->unk8); } if( 500.0f <= local->unk10 - && sp60 < 500.0f - && (sp58 < -0.2 || 0.2 < sp58) + && horizontal_distance < 500.0f + && (side_angle_radian < -0.2 || 0.2 < side_angle_radian) ){ FUNC_8030E624(SFX_C4_TWINKLY_MUNCHER_GRR, 0.8f, 32675); } - local->unk10 = sp60; - local->unk14 = local->unk14 + sp50; + local->unk10 = horizontal_distance; + local->unk14 = local->unk14 + time_delta; - if( sp60 < 600.0f - && -1.0f < sp58 - && sp58 < 1.0f + if( horizontal_distance < 600.0f + && -1.0f < side_angle_radian + && side_angle_radian < 1.0f && plyr_pos[1] < this->position_y + this->scale*200.0f ){ - func_80258A4C(this->position, (this->yaw + -90.0f) + local->unk0, plyr_pos, &sp60, &sp5C, &sp58); - local->unk0 += (sp58*200.0f)*sp50; - if(1.0f < local->unk14 && (sp58 < -0.1 || 0.1 < sp58)){ - gcsfx_playWithPitch(SFX_D0_GRIMLET_SQUEAK, mlAbsF(sp58) * 0.1 + 0.9, 0x4e20); + func_80258A4C( + this->position, (this->yaw + -90.0f) + local->unk0, plyr_pos, + &horizontal_distance, &distance_in_front, &side_angle_radian); + local->unk0 += (side_angle_radian * 200.0f) * time_delta; + if(1.0f < local->unk14 && (side_angle_radian < -0.1 || 0.1 < side_angle_radian)){ + gcsfx_playWithPitch(SFX_D0_GRIMLET_SQUEAK, mlAbsF(side_angle_radian) * 0.1 + 0.9, 0x4e20); local->unk14 = 0.0f; } } else{//L80388964 if(0.0f < local->unk0){ - local->unk0 -= 30.0f*sp50; + local->unk0 -= 30.0f * time_delta; local->unk0 = MAX(0.0f, local->unk0); }//L803889B4 else{ if(local->unk0 < 0.0f){ - local->unk0 += 30.0f*sp50; + local->unk0 += 30.0f * time_delta; local->unk0 = MIN(0.0f, local->unk0); } } }//L803889F8 - if(this->state == 1){ - if( sp60 < 400.0f - && -0.8 <= sp58 - && sp58 <= 0.8 + if(this->state == CH_GRIMLET_STATE_1_UNK){ + if( horizontal_distance < 400.0f + && -0.8 <= side_angle_radian + && side_angle_radian <= 0.8 && (plyr_pos[1] - this->position_y) < 100.0f && -100.0f < (plyr_pos[1] - this->position_y) ){ - func_803883B0(this, 2); + chGrimlet_setState(this, CH_GRIMLET_STATE_2_UNK); } }//L80388AB8 - if(this->state == 2){ - skeletalAnim_getProgressRange(this->unk148, &sp4C, &sp48); - if(0.6 <= sp48) - tmp_f2 = 1.0 - 2*(sp48 - 0.6); + if(this->state == CH_GRIMLET_STATE_2_UNK){ + skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress, &curr_anim_progress); + if(0.6 <= curr_anim_progress) + tmp_f2 = 1.0 - 2 * (curr_anim_progress - 0.6); else - tmp_f2 = sp48*1.6666666666666667; + tmp_f2 = curr_anim_progress * 1.6666666666666667; //L80388B34 - local->unkC = tmp_f2*sp60; + local->unkC = tmp_f2 * horizontal_distance; - if( sp4C < 0.55 - && 0.55 <= sp48 + if( prev_anim_progress < 0.55 + && 0.55 <= curr_anim_progress && !local->unk5 ){ sfx_playFadeShorthandDefault(SFX_20_METAL_CLANK_1, 1.0f, 32000, this->position, 500, 2500); } if(skeletalAnim_getLoopCount(this->unk148) > 0) - func_803883B0(this, 1); + chGrimlet_setState(this, CH_GRIMLET_STATE_1_UNK); }//L80388BB0 } diff --git a/src/RBB/ch/propellor.c b/src/RBB/ch/propellor.c index 881cefc31..4cbff4e22 100644 --- a/src/RBB/ch/propellor.c +++ b/src/RBB/ch/propellor.c @@ -14,27 +14,32 @@ typedef struct { void chPropellor_update(Actor *this); /* .data */ -ActorInfo D_803906E0 = { - MARKER_185_RBB_REAR_PROPELLER, ACTOR_175_MODEL_RUSTY_BUCKET_REAR_PROPELLER, ASSET_403_MODEL_RUSTY_BUCKET_REAR_PROPELLER, +ActorInfo chRBBRearPropeller = { + MARKER_185_RBB_REAR_PROPELLER, ACTOR_175_RUSTY_BUCKET_REAR_PROPELLER, ASSET_403_MODEL_RUSTY_BUCKET_REAR_PROPELLER, 0x0, NULL, chPropellor_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -s32 D_80390704[4] = {0x258, 0x12C, 0x12C, 0}; +s32 chRBBRearPropellerSpeed[4] = {600, 300, 300, 0}; + +enum chrbbrearpropeller_state_e { + CH_RBB_REAR_PROPELLER_STATE_0_NOT_INIT, + CH_RBB_REAR_PROPELLER_STATE_1_UNK +}; /*.code */ f32 __chPropellor_getSpeed(void) { - return (f32) D_80390704[2 * levelSpecificFlags_get(LEVEL_FLAG_27_RBB_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_28_RBB_UNKNOWN)]; + return (f32) chRBBRearPropellerSpeed[2 * levelSpecificFlags_get(LEVEL_FLAG_27_RBB_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_28_RBB_UNKNOWN)]; } -void __chPropellor_setState(Actor *this, s32 arg1){ +void __chPropellor_setState(Actor *this, s32 next_state){ ActorLocal_RBB_36A0 * local = (ActorLocal_RBB_36A0 *)&this->local; - if(arg1 == 1){ + if(next_state == CH_RBB_REAR_PROPELLER_STATE_1_UNK){ local->unkC = __chPropellor_getSpeed(); local->unk4 = __chPropellor_getSpeed(); } - this->state = arg1; + this->state = next_state; } int func_80389B44(ActorMarker* marker, s32 arg1){ @@ -50,10 +55,10 @@ void func_80389B80(Actor *this, f32 arg1){ local->unk0 = func_802F9AA8(0x400); func_802F9DB8(local->unk0, arg1, arg1, 0.0f); func_802F9F80(local->unk0, 0.0f, 8999999488.0f, 0.0f); - func_802FA060(local->unk0, 0x4650, 0x4650, 0.0f); + func_802FA060(local->unk0, 18000, 18000, 0.0f); if (!levelSpecificFlags_get(LEVEL_FLAG_3_RBB_UNKNOWN) && !levelSpecificFlags_get(LEVEL_FLAG_4_RBB_UNKNOWN)) { - func_802F9EC4(local->unk0, this->position, 0x1f4, 0x7d0); + func_802F9EC4(local->unk0, this->position, 500, 2000); func_802FA0B0(local->unk0, 1); } } @@ -65,10 +70,10 @@ void __chPropellor_free(Actor *actor){ } -void chPropellor_update(Actor *this){ +void chPropellor_update(Actor *this){ ActorLocal_RBB_36A0 * local = (ActorLocal_RBB_36A0 *)&this->local; - f32 tmp; - f32 sp34 = time_getDelta(); + f32 prev_pitch; + f32 time_delta = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = true; @@ -91,7 +96,7 @@ void chPropellor_update(Actor *this){ }//L80389D7C local->unk4 = 0.0f; local->unkC = 0.0f; - __chPropellor_setState(this, 1); + __chPropellor_setState(this, CH_RBB_REAR_PROPELLER_STATE_1_UNK); if (levelSpecificFlags_get(local->unk8 ? LEVEL_FLAG_4_RBB_UNKNOWN : LEVEL_FLAG_3_RBB_UNKNOWN)) { ncStaticCamera_setToNode(9); @@ -105,10 +110,10 @@ void chPropellor_update(Actor *this){ } }//L80389EA8 - tmp = this->pitch; - this->pitch -= local->unkC*sp34; - if( (0.0f < tmp && this->pitch <= 0.0f) - || (180.0f < tmp && this->pitch <= 180.0f) + prev_pitch = this->pitch; + this->pitch -= local->unkC * time_delta; + if( (0.0f < prev_pitch && this->pitch <= 0.0f) + || (180.0f < prev_pitch && this->pitch <= 180.0f) ){ if (levelSpecificFlags_get(LEVEL_FLAG_3_RBB_UNKNOWN) || levelSpecificFlags_get(LEVEL_FLAG_4_RBB_UNKNOWN)) { func_8030E760(SFX_2_CLAW_SWIPE, 0.4f, 20000); @@ -123,11 +128,11 @@ void chPropellor_update(Actor *this){ if(this->state == 1){ local->unk4 = __chPropellor_getSpeed(); if(local->unkC < local->unk4){ - local->unkC += 75*sp34; + local->unkC += 75 * time_delta; local->unkC = MIN(local->unk4, local->unkC); }//L8038A03C if(local->unk4 < local->unkC){ - local->unkC -= 75*sp34; + local->unkC -= 75 * time_delta; local->unkC = MAX(local->unk4, local->unkC); } }//L8038A08C diff --git a/src/RBB/ch/propellorswitch.c b/src/RBB/ch/propellorswitch.c index e536c2023..e81a65107 100644 --- a/src/RBB/ch/propellorswitch.c +++ b/src/RBB/ch/propellorswitch.c @@ -28,25 +28,32 @@ Struct_RBB_3CB0 D_80390720[2] = { {{0xF9C0, 0x324, 0xF6A0}, 0x405, 4, 0x28} }; -ActorInfo D_80390738 = { - 0x186, 0x176, 0x404, 0x0, NULL, +ActorInfo chRBBGreenPropellerSwitch = { + MARKER_186_RBB_GREEN_PROPELLER_SWITCH, ACTOR_176_RBB_GREEN_PROPELLOR_SWITCH, ASSET_404_MODEL_RBB_GREEN_PROPELLER_SWITCH, + 0x0, NULL, chPropellorSwitch_update, NULL, chPropellorSwitch_draw, 0, 0, 0.0f, 0 }; +enum chrbbgreenpropellerswitch_state_e { + CH_RBB_GREEN_PROPELLER_SWITCH_STATE_0_NOT_INIT, + CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED, + CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED +}; + /* .code */ -void __chPropellorSwitch_setState(Actor *this, s32 arg1){ +void __chPropellorSwitch_setState(Actor *this, s32 next_state){ ActorLocal_RBB_3CB0 *local = (ActorLocal_RBB_3CB0 *)&this->local; - if(arg1 == 1) - if(this->state == 2) + if(next_state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED) + if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED) this->position_y += 40.0f; - if(arg1 == 2){ - if(this->state == 1) + if(next_state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED){ + if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED) func_8030E6D4(SFX_90_SWITCH_PRESS); this->position_y -= 40.0f; - if(this->state == 1){ + if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED){ levelSpecificFlags_set(local->unk0->unk8, 1); musicKeepsPlaying(); timedFunc_set_1(1.1f, (GenFunction_1)func_8028F9DC, 2); @@ -56,13 +63,13 @@ void __chPropellorSwitch_setState(Actor *this, s32 arg1){ } }//L8038A1A0 - this->state = arg1; + this->state = next_state; } void func_8038A1C8(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); if(actor->state == 1){ - __chPropellorSwitch_setState(actor, 2); + __chPropellorSwitch_setState(actor, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED); } else if(actor->state == 2){ rbb_propellorCtrl_start(); @@ -109,16 +116,16 @@ void chPropellorSwitch_update(Actor *this){ this->position_y = (f32)local->unk0->unk0[1]; this->position_z = (f32)local->unk0->unk0[2]; if(levelSpecificFlags_get(local->unk0->unkA)) - __chPropellorSwitch_setState(this, 2); + __chPropellorSwitch_setState(this, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED); else - __chPropellorSwitch_setState(this, 1); + __chPropellorSwitch_setState(this, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED); }//L8038A47C - if(this->state == 2){ + if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED){ if( !levelSpecificFlags_get(local->unk0->unkA) && !levelSpecificFlags_get(LEVEL_FLAG_3_RBB_UNKNOWN) && !levelSpecificFlags_get(LEVEL_FLAG_4_RBB_UNKNOWN) ){ - __chPropellorSwitch_setState(this, 1); + __chPropellorSwitch_setState(this, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED); } } } diff --git a/src/RBB/ch/rarewareflag.c b/src/RBB/ch/rarewareflag.c index 6cb471e19..9dace4041 100644 --- a/src/RBB/ch/rarewareflag.c +++ b/src/RBB/ch/rarewareflag.c @@ -3,18 +3,19 @@ #include "functions.h" #include "variables.h" -void func_8038C300(Actor *this); +void chRarewareFlag_update(Actor *this); -ActorInfo D_80390B40 = { - 0x198, 0x1ca, 0x41e, 0x0, NULL, - func_8038C300, NULL, actor_draw, +ActorInfo chRarewareFlag = { + MARKER_198_RAREWARE_FLAG, ACTOR_1CA_RAREWARE_FLAG, ASSET_41E_MODEL_RAREWARE_FLAG, + 0x0, NULL, + chRarewareFlag_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -void func_8038C300(Actor *this){ +void chRarewareFlag_update(Actor *this){ if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; - skeletalAnim_set(this->unk148, 0x140, 0.0f, 1.0f); + skeletalAnim_set(this->unk148, ASSET_140_ANIM_RAREWARE_FLAG, 0.0f, 1.0f); } } diff --git a/src/RBB/ch/rowboat.c b/src/RBB/ch/rowboat.c index 871f28c15..a1f30e8f1 100644 --- a/src/RBB/ch/rowboat.c +++ b/src/RBB/ch/rowboat.c @@ -6,19 +6,20 @@ /* typedefs and declarations */ typedef struct { f32 unk0; - f32 unk4[3]; - f32 unk10[3]; - f32 unk1C[3]; - f32 unk28; - f32 unk2C; + f32 playerInfluencedRotationDelta[3]; // something about rotation + f32 position[3]; + f32 rotation[3]; + f32 timeDelta; + f32 creakingSFXTimer; }ActorLocal_RBB_7FD0; -void func_8038E3D8(Actor *this); +void chRowboat_update(Actor *this); /* .data */ -ActorInfo D_80390D50 = { - 0x1ab, 0x297, 0x43C, 0x0, NULL, - func_8038E3D8, NULL, actor_draw, +ActorInfo chRowboat = { + MARKER_1AB_ROWBOAT, ACTOR_297_ROWBOAT, ASSET_43C_MODEL_ROWBOAT, + 0x0, NULL, + chRowboat_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; @@ -28,84 +29,86 @@ void func_8038E3C0(Actor *this, s32 arg1){ this->state = arg1; } -void func_8038E3D8(Actor *this){ - f32 sp74[3]; - f32 sp68[3]; +void chRowboat_update(Actor *this){ + f32 rotation_delta[3]; + f32 position_delta[3]; ActorLocal_RBB_7FD0 *local = (ActorLocal_RBB_7FD0 *) &this->local; - int i; - f32 sp5C = time_getDelta(); - f32 sp50[3]; - f32 sp44[3]; + int rotation_parameter; + f32 time_delta = time_getDelta(); + f32 new_rotation[3]; + f32 player_position[3]; if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = randf2(80.0f, 100.0f); - local->unk28 = 0.0f; - local->unk2C = 0.5f; + local->timeDelta = 0.0f; + local->creakingSFXTimer = 0.5f; this->position_y -= 10.0f; - local->unk4[0] = 0.0f; - local->unk4[1] = 0.0f; - local->unk4[2] = 0.0f; - local->unk10[0] = this->position_x; - local->unk10[1] = this->position_y; - local->unk10[2] = this->position_z; - local->unk1C[0] = this->pitch; - local->unk1C[1] = this->yaw; - local->unk1C[2] = this->roll; + local->playerInfluencedRotationDelta[0] = 0.0f; + local->playerInfluencedRotationDelta[1] = 0.0f; + local->playerInfluencedRotationDelta[2] = 0.0f; + local->position[0] = this->position_x; + local->position[1] = this->position_y; + local->position[2] = this->position_z; + local->rotation[0] = this->pitch; + local->rotation[1] = this->yaw; + local->rotation[2] = this->roll; func_8038E3C0(this, 1); }//L8038E4C8 - if(ml_timer_update(&local->unk2C, sp5C)){ - local->unk2C = randf2(3.5f, 5.5f); + if(ml_timer_update(&local->creakingSFXTimer, time_delta)){ + local->creakingSFXTimer = randf2(3.5f, 5.5f); func_8030E878(SFX_69_WHIPCRACK_CREAKING, randf2(1.1f, 1.2f), 22000, this->position, 500.0f, 1500.0f); }//L8038E544 - if(func_8032DCAC() == this->marker && func_8028F20C()){ - player_getPosition(sp44); - if(sp44[0] < this->position_x - 10.0f && local->unk4[2] < 3.0f) - local->unk4[2] += 5.0f*sp5C; + if(func_8032DCAC() == this->marker && player_isStableWithExtraSteps()){ + player_getPosition(player_position); + if(player_position[0] < this->position_x - 10.0f && local->playerInfluencedRotationDelta[2] < 3.0f) + local->playerInfluencedRotationDelta[2] += 5.0f * time_delta; - if(this->position_x + 10.0f < sp44[0] && -3.0f < local->unk4[2]) - local->unk4[2] -= 5.0f*sp5C; + if(this->position_x + 10.0f < player_position[0] && -3.0f < local->playerInfluencedRotationDelta[2]) + local->playerInfluencedRotationDelta[2] -= 5.0f * time_delta; - if(this->position_z + 10.0f < sp44[2] && local->unk4[0] < 5.0f) - local->unk4[0] += 5.0f*sp5C; + if(this->position_z + 10.0f < player_position[2] && local->playerInfluencedRotationDelta[0] < 5.0f) + local->playerInfluencedRotationDelta[0] += 5.0f * time_delta; - if(sp44[2] < this->position_z - 10.0f && -5.0f < local->unk4[0]) - local->unk4[0] -= 5.0f*sp5C; + if(player_position[2] < this->position_z - 10.0f && -5.0f < local->playerInfluencedRotationDelta[0]) + local->playerInfluencedRotationDelta[0] -= 5.0f * time_delta; } else{ - for(i= 0; i< 3; i++){ - if(0.0f < local->unk4[i]){ - local->unk4[i] -= 2.5*sp5C; - if(local->unk4[i] < 0.0f) - local->unk4[i] = 0.0f; - } else if(local->unk4[i] < 0.0f) { //L8038E710 - local->unk4[i] += 2.5*sp5C; - if(0.0f < local->unk4[i]) - local->unk4[i] = 0.0f; + for(rotation_parameter = 0; rotation_parameter < 3; rotation_parameter++){ + if(0.0f < local->playerInfluencedRotationDelta[rotation_parameter]){ + local->playerInfluencedRotationDelta[rotation_parameter] -= 2.5 * time_delta; + if(local->playerInfluencedRotationDelta[rotation_parameter] < 0.0f) + local->playerInfluencedRotationDelta[rotation_parameter] = 0.0f; + } else if(local->playerInfluencedRotationDelta[rotation_parameter] < 0.0f) { //L8038E710 + local->playerInfluencedRotationDelta[rotation_parameter] += 2.5 * time_delta; + if(0.0f < local->playerInfluencedRotationDelta[rotation_parameter]) + local->playerInfluencedRotationDelta[rotation_parameter] = 0.0f; }//L8038E74C } }//L8038E754 - local->unk28 += sp5C; - sp68[0] = 0.0f; - sp68[1] = 5.0f * sinf((((local->unk28*0.8)*local->unk0)/180.0)*3.141592654); - sp68[2] = 0.0f; - sp74[0] = 4.5 * cosf(((local->unk28*local->unk0)/180.0) * 3.141592654); - sp74[1] = 1.5 * sinf((((local->unk28*0.9)*local->unk0)/180.0)*3.141592654); - sp74[2] = 0.0f; - - this->position_x = local->unk10[0] + sp68[0]; - this->position_y = local->unk10[1] + sp68[1]; - this->position_z = local->unk10[2] + sp68[2]; - - sp50[0] = local->unk1C[0] + sp74[0]; - sp50[1] = local->unk1C[1] + sp74[1]; - sp50[2] = local->unk1C[2] + sp74[2]; - - this->pitch = sp50[0] + local->unk4[0]; - this->yaw = sp50[1] + local->unk4[1]; - this->roll = sp50[2] + local->unk4[2]; + local->timeDelta += time_delta; + + position_delta[0] = 0.0f; + position_delta[1] = 5.0f * sinf((((local->timeDelta * 0.8) * local->unk0) / 180.0) * BAD_PI); + position_delta[2] = 0.0f; + + rotation_delta[0] = 4.5 * cosf(((local->timeDelta * local->unk0) / 180.0) * BAD_PI); + rotation_delta[1] = 1.5 * sinf((((local->timeDelta * 0.9) * local->unk0) / 180.0) * BAD_PI); + rotation_delta[2] = 0.0f; + + this->position_x = local->position[0] + position_delta[0]; + this->position_y = local->position[1] + position_delta[1]; + this->position_z = local->position[2] + position_delta[2]; + + new_rotation[0] = local->rotation[0] + rotation_delta[0]; + new_rotation[1] = local->rotation[1] + rotation_delta[1]; + new_rotation[2] = local->rotation[2] + rotation_delta[2]; + + this->pitch = new_rotation[0] + local->playerInfluencedRotationDelta[0]; + this->yaw = new_rotation[1] + local->playerInfluencedRotationDelta[1]; + this->roll = new_rotation[2] + local->playerInfluencedRotationDelta[2]; } diff --git a/src/RBB/ch/seaman_grublin.c b/src/RBB/ch/seamangrublin.c similarity index 97% rename from src/RBB/ch/seaman_grublin.c rename to src/RBB/ch/seamangrublin.c index ae6adc460..ece17410d 100644 --- a/src/RBB/ch/seaman_grublin.c +++ b/src/RBB/ch/seamangrublin.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (core2 origin - unknown exact file) +// BanjoDecomp: core2/ch/seamangrublin.c #include #include "functions.h" #include "variables.h" diff --git a/src/RBB/ch/siren.c b/src/RBB/ch/siren.c deleted file mode 100644 index b876dbea4..000000000 --- a/src/RBB/ch/siren.c +++ /dev/null @@ -1,61 +0,0 @@ -// BanjoDecomp: code_9840.c -#include -#include "functions.h" -#include "variables.h" - -void func_8038FC48(Actor *this); - -/* typedefs and declarations */ -typedef struct { - s32 unk0; - s16 *unk4; - ActorMarker *unk8; -}ActorLocal_RBB_9840; - -/* .data */ -s16 RBB_D_80390E30[2] = {0x177, 0x17F}; -ActorInfo D_80390E34 = { - 0x1D2, 0x31B, 0x0, 0x0, NULL, - func_8038FC48, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; -ActorInfo D_80390E58 = { - 0x1D3, 0x31C, 0x0, 0x0, NULL, - func_8038FC48, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -/*.code */ -void func_8038FC30(Actor *this, s32 arg1){ - this->state = arg1; -} - -void func_8038FC48(Actor *this){ - ActorLocal_RBB_9840 *local = (ActorLocal_RBB_9840 *)&this->local; - f32 sp20; - f32 tmp_f2; - s32 tmp_a1; - - if(!this->volatile_initialized){ - this->volatile_initialized = true; - actor_collisionOff(this); - local->unk4 = RBB_D_80390E30 + (this->marker->id - 0x1d2); - local->unk8 = NULL; - - local->unk0 = func_802F9AA8(0x400); - func_802F9DB8(local->unk0, 1.0f, 1.0f, 0.0f); - func_802F9EC4(local->unk0, this->position, 0x1f4, 0x3e8); - func_802F9F80(local->unk0, 0.0f, 8999999488.0f, 0.0f); - func_802FA060(local->unk0, 22000, 22000, 0.0f); - func_8038FC30(this, 1); - } - else{//L8038FD34 - if(local->unk8 == NULL) - local->unk8 = actorArray_findActorFromActorId(*local->unk4)->marker; - sp20 = func_8038A6B8(local->unk8); - tmp_f2 = 1.5* sp20 + 0.5; - func_802F9DB8(local->unk0, tmp_f2, tmp_f2, 0.0f); - tmp_a1 = (s32) (sp20*32000.0f); - func_802FA060(local->unk0, tmp_a1, tmp_a1, 0.0f); - } -} diff --git a/src/RBB/ch/whistle.c b/src/RBB/ch/whistle.c index 4517e787e..8b55fc1a7 100644 --- a/src/RBB/ch/whistle.c +++ b/src/RBB/ch/whistle.c @@ -5,45 +5,48 @@ /* typedefs and declarations */ typedef struct { - s16 unk0; - f32 unk4[3]; + s16 actorId; + f32 position[3]; s16 unk10; s16 unk12; s16 unk14; //u8 pad16[2]; -}Struct_RBB_4C70; +} ActorLocal_ChRBBWhistleInfo; typedef struct { - Struct_RBB_4C70 *unk0; - f32 unk4[3]; + ActorLocal_ChRBBWhistleInfo *unk0; + f32 particlePosition[3]; }ActorLocal_RBB_4C70; -Actor *func_8038B230(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); -void func_8038B340(Actor *this); +Actor *chRBBWhistle_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); +void chRBBWhistle_update(Actor *this); /* .data */ -Struct_RBB_4C70 D_80390950[] = { - { 0x1C2, {-3720.0f, 800.0f, -350.0f}, 0x1, 0x136, 0x3FF}, - { 0x1C3, {-3720.0f, 800.0f, 0.0f}, 0x2, 0x135, 0x3FE}, - { 0x1C4, {-3720.0f, 800.0f, 350.0f}, 0x3, 0x134, 0x3FD}, - 0 +ActorLocal_ChRBBWhistleInfo chRBBWhistleInfo[] = { + { ACTOR_1C2_WHISTLE_1, {-3720.0f, 800.0f, -350.0f}, 0x1, 0x136, 0x3FF}, + { ACTOR_1C3_WHISTLE_2, {-3720.0f, 800.0f, 0.0f}, 0x2, 0x135, 0x3FE}, + { ACTOR_1C4_WHISTLE_3, {-3720.0f, 800.0f, 350.0f}, 0x3, 0x134, 0x3FD}, + { 0 } // [port] decomp uses NULL; actorId is s16 and clang errors on -Wint-conversion }; -ActorInfo D_803909B0 = { - 0x2A, 0x1C2, 0x416, 0x0, NULL, - func_8038B340, NULL, func_8038B230, +ActorInfo chRBBWhistle1 = { + MARKER_2A_WHISTLE_1_YELLOW, ACTOR_1C2_WHISTLE_1, ASSET_416_MODEL_WHISTLE, + 0x0, NULL, + chRBBWhistle_update, NULL, chRBBWhistle_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_803909D4 = { - 0x2B, 0x1C3, 0x416, 0x0, NULL, - func_8038B340, NULL, func_8038B230, +ActorInfo chRBBWhistle2 = { + MARKER_2B_WHISTLE_2_YELLOW, ACTOR_1C3_WHISTLE_2, ASSET_416_MODEL_WHISTLE, + 0x0, NULL, + chRBBWhistle_update, NULL, chRBBWhistle_draw, 0, 0, 0.0f, 0 }; -ActorInfo RBB_D_803909F8 = { - 0x2C, 0x1C4, 0x416, 0x0, NULL, - func_8038B340, NULL, func_8038B230, +ActorInfo chRBBWhistle3 = { + MARKER_2C_WHISTLE_3_YELLOW, ACTOR_1C4_WHISTLE_3, ASSET_416_MODEL_WHISTLE, + 0x0, NULL, + chRBBWhistle_update, NULL, chRBBWhistle_draw, 0, 0, 0.0f, 0 }; @@ -56,26 +59,32 @@ ParticleScaleAndLifetimeRanges D_80390A1C = { 0.5f }; +enum chrbbwhistle_state_e { + CH_RBB_WHISTLE_STATE_0_NOT_INIT, + CH_RBB_WHISTLE_STATE_1_IDLE, + CH_RBB_WHISTLE_STATE_2_BLOWING +}; + /* .code */ -Struct_RBB_4C70 *func_8038B060(Actor *this){ - Struct_RBB_4C70 * iPtr; - for(iPtr = D_80390950; iPtr->unk0 != 0; iPtr++){ - if(iPtr->unk0 == this->modelCacheIndex) +ActorLocal_ChRBBWhistleInfo *func_8038B060(Actor *this){ + ActorLocal_ChRBBWhistleInfo * iPtr; + for(iPtr = chRBBWhistleInfo; iPtr->actorId != NULL; iPtr++){ + if(iPtr->actorId == this->modelCacheIndex) return iPtr; } return NULL; } -void RBB_func_8038B0B8(Actor *this, s32 arg1){ +void chRBBWhistle_setState(Actor *this, s32 next_state){ ActorLocal_RBB_4C70 *local = (ActorLocal_RBB_4C70 *)&this->local; ParticleEmitter *other; - this->state = arg1; + this->state = next_state; - if(this->state == 2){ + if(this->state == CH_RBB_WHISTLE_STATE_2_BLOWING){ skeletalAnim_set(this->unk148, local->unk0->unk12, 0.0f, 0.5f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - timed_playSfx(0.1f, local->unk0->unk14, 1.0f, 0x7d00); + timed_playSfx(0.1f, local->unk0->unk14, 1.0f, 32000); other = partEmitMgr_newEmitter(0xa); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setAccelerationRange(other, @@ -87,7 +96,7 @@ void RBB_func_8038B0B8(Actor *this, s32 arg1){ -5.0f, -5.0f, 0.0f, 5.0f, 5.0f, 0.0f ); - particleEmitter_setPosition(other, local->unk4); + particleEmitter_setPosition(other, local->particlePosition); particleEmitter_setParticleVelocityRange(other, -400.0f, 0.0f, -30.0f, -800.0f, 0.0f, 30.0f @@ -97,10 +106,10 @@ void RBB_func_8038B0B8(Actor *this, s32 arg1){ } } -Actor *func_8038B230(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3){ +Actor *chRBBWhistle_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3){ Actor *actor = marker_getActor(marker); ActorLocal_RBB_4C70 *local = (ActorLocal_RBB_4C70 *)&actor->local; - f32 sp3C[3]; + f32 actor_rotation[3]; if(actor->state == 0) return actor; @@ -109,45 +118,45 @@ Actor *func_8038B230(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3){ modelRender_setBoneTransformList(skeletalAnim_getBoneTransformList(actor->unk148)); } - sp3C[0] = actor->pitch; - sp3C[1] = actor->yaw; - sp3C[2] = actor->roll; + actor_rotation[0] = actor->pitch; + actor_rotation[1] = actor->yaw; + actor_rotation[2] = actor->roll; modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)actor); modelRender_setRefPoints(func_80329934()); - modelRender_draw(gdl, mptr, actor->position, sp3C, actor->scale, NULL, marker_loadModelBin(marker)); - vec3fArray_get_vec3f(func_80329934(), 5, local->unk4); - local->unk4[0] -= 60.0f; + modelRender_draw(gdl, mptr, actor->position, actor_rotation, actor->scale, NULL, marker_loadModelBin(marker)); + vec3fArray_get_vec3f(func_80329934(), 5, local->particlePosition); + local->particlePosition[0] -= 60.0f; return actor; } -void func_8038B340(Actor * this){ +void chRBBWhistle_update(Actor * this){ ActorLocal_RBB_4C70 *local = (ActorLocal_RBB_4C70 *)&this->local; if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = func_8038B060(this); - local->unk4[2] = 0.0f; - local->unk4[1] = 0.0f; - local->unk4[0] = 0.0f; + local->particlePosition[2] = 0.0f; + local->particlePosition[1] = 0.0f; + local->particlePosition[0] = 0.0f; - this->position_x = local->unk0->unk4[0]; - this->position_y = local->unk0->unk4[1]; - this->position_z = local->unk0->unk4[2]; + this->position_x = local->unk0->position[0]; + this->position_y = local->unk0->position[1]; + this->position_z = local->unk0->position[2]; this->yaw = -90.0f; this->scale = 0.25f; - RBB_func_8038B0B8(this, 1); + chRBBWhistle_setState(this, CH_RBB_WHISTLE_STATE_1_IDLE); }//L8038B3E4 - if(this->state == 1){ + if(this->state == CH_RBB_WHISTLE_STATE_1_IDLE){ if(mapSpecificFlags_get(local->unk0->unk10)) - RBB_func_8038B0B8(this, 2); + chRBBWhistle_setState(this, CH_RBB_WHISTLE_STATE_2_BLOWING); } - if(this->state == 2){ + if(this->state == CH_RBB_WHISTLE_STATE_2_BLOWING){ if( skeletalAnim_getLoopCount(this->unk148) > 0 ) - RBB_func_8038B0B8(this, 1); + chRBBWhistle_setState(this, CH_RBB_WHISTLE_STATE_1_IDLE); } } diff --git a/src/RBB/ch/whistlectrl.c b/src/RBB/ch/whistlectrl.c index 76d6dc6e7..3cde18b54 100644 --- a/src/RBB/ch/whistlectrl.c +++ b/src/RBB/ch/whistlectrl.c @@ -3,24 +3,31 @@ #include "functions.h" #include "variables.h" -extern ActorInfo D_80390FD0; - typedef struct { - s16 unk0; + s16 currentIndex; s16 unk2; - u8 *unk4; + u8 *codeString; }ActorLocal_RBB_5060; void chWhistleCtrl_update(Actor * this); /* .data */ -ActorInfo D_80390A50 = { - 0x2D, 0x1C5, 0x0, 0x0, NULL, +ActorInfo chRBBWhistleCtrl = { + MARKER_2D_WHISTLE_CTRL, ACTOR_1C5_WHISTLE_CTRL, 0x0, + 0x0, NULL, chWhistleCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; -f32 D_80390A74[3] = {-3820.0f, 850.0f, 0.0f}; //whistle jiggy spawn position +f32 chRBBWhistleCtrlJiggyPosition[3] = {-3820.0f, 850.0f, 0.0f}; + +enum chrbbwhistlectrl_state_e { + CH_RBB_WHISTLE_CTRL_STATE_0_NOT_INIT, + CH_RBB_WHISTLE_CTRL_STATE_1_AWAITING_PLAYER, + CH_RBB_WHISTLE_CTRL_STATE_2_COMPLETE +}; + +#define RBB_WHISTLE_CODE "312111" /* .code */ void __chWhistleCtrl_setState(Actor *actor, s32 arg1){ @@ -29,7 +36,7 @@ void __chWhistleCtrl_setState(Actor *actor, s32 arg1){ void __chWhistleCtrl_soundWhistle(void){ bundle_setYaw(225.0f); - jiggy_spawn(JIGGY_54_RBB_WHISTLE, D_80390A74); + jiggy_spawn(JIGGY_54_RBB_WHISTLE, chRBBWhistleCtrlJiggyPosition); } void __chWhistleCtrl_correct(void){ @@ -53,13 +60,13 @@ void __chWhistleCtrl_complete(void){ s32 chWhistleCtrl_newEvent(Actor *this, s32 whistle_id, Actor *other){ ActorLocal_RBB_5060 *local = (ActorLocal_RBB_5060 *)&this->local; - if(this->state != 1) + if(this->state != CH_RBB_WHISTLE_CTRL_STATE_1_AWAITING_PLAYER) return 0; - if(whistle_id + 0x30 == local->unk4[local->unk0]){ //correct - if(local->unk4[++local->unk0] == 0){ //end of string + if(whistle_id + 0x30 == local->codeString[local->currentIndex]){ //correct + if(local->codeString[++local->currentIndex] == 0){ //end of string timedFunc_set_0(0.6f, __chWhistleCtrl_complete); //spawn jiggy - __chWhistleCtrl_setState(this, 2); + __chWhistleCtrl_setState(this, CH_RBB_WHISTLE_CTRL_STATE_2_COMPLETE); return 3; }else{ timedFunc_set_0(0.6f, __chWhistleCtrl_correct); @@ -68,7 +75,7 @@ s32 chWhistleCtrl_newEvent(Actor *this, s32 whistle_id, Actor *other){ } else{ //wrong timedFunc_set_1(1.0f, (GenFunction_1)__chWhistleCtrl_wrong, (uintptr_t)other->marker); - local->unk0 = 0; + local->currentIndex = 0; return 2; } } @@ -79,10 +86,10 @@ void chWhistleCtrl_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; local->unk2 = 1; - local->unk4 = "312111"; + local->codeString = RBB_WHISTLE_CODE; if(jiggyscore_isSpawned(JIGGY_54_RBB_WHISTLE)) - __chWhistleCtrl_setState(this, 2); + __chWhistleCtrl_setState(this, CH_RBB_WHISTLE_CTRL_STATE_2_COMPLETE); else - __chWhistleCtrl_setState(this, 1); + __chWhistleCtrl_setState(this, CH_RBB_WHISTLE_CTRL_STATE_1_AWAITING_PLAYER); } } diff --git a/src/RBB/ch/whistleswitch.c b/src/RBB/ch/whistleswitch.c index 443d4206f..0305f4fdc 100644 --- a/src/RBB/ch/whistleswitch.c +++ b/src/RBB/ch/whistleswitch.c @@ -3,111 +3,139 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + void vtxList_tintColorsFrom(BKVertexList *dst, s32 target_color[3], f32 amount, BKVertexList *src); BKVertexList *vtxList_clone(BKVertexList *); /* typedefs and declarations */ typedef struct { - s16 unk0; - f32 unk4[3]; - s16 unk10; - u8 pad12[2]; -}Struct_RBB_47D0; + s16 actorId; + f32 position[3]; + s16 mapSpecificFlag; +} Struct_ChWhistleSwitchInfo; typedef struct { u8 unk0; u8 pad1[3]; - Struct_RBB_47D0 *unk4; + Struct_ChWhistleSwitchInfo *whistleSwitchInfo; f32 unk8; BKVertexList *unkC; -}ActorLocal_RBB_47D0; + // [port] Back buffer for unkC. See chRBBWhistleSwitch_draw. + BKVertexList *portVtxBack; +} ActorLocal_RBB_47D0; -Actor *func_8038AD9C(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); -void func_8038AEB8(Actor *this); +Actor *chRBBWhistleSwitch_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); +void chRBBWhistleSwitch_update(Actor *this); /* .data */ -Struct_RBB_47D0 D_80390870[4] = { - {0x1BF, {-3950.0f, 690.0f, -350.0f}, 1}, - {0x1C0, {-3950.0f, 690.0f, 0.0f}, 2}, - {0x1C1, {-3950.0f, 690.0f, 350.0f}, 3}, - 0 +Struct_ChWhistleSwitchInfo chWhistleSwitchTable[4] = { + {ACTOR_1BF_WHISTLE_SWITCH_1, {-3950.0f, 690.0f, -350.0f}, RBB_MAIN_SPECIFIC_FLAG_1_WHISTLE_SWITCH_1}, + {ACTOR_1C0_WHISTLE_SWITCH_2, {-3950.0f, 690.0f, 0.0f}, RBB_MAIN_SPECIFIC_FLAG_2_WHISTLE_SWITCH_2}, + {ACTOR_1C1_WHISTLE_SWITCH_3, {-3950.0f, 690.0f, 350.0f}, RBB_MAIN_SPECIFIC_FLAG_3_WHISTLE_SWITCH_3}, + { 0 } // [port] decomp uses NULL; actorId is s16 and clang errors on -Wint-conversion }; -extern ActorInfo D_803908C0 = { - 0x195, 0x1BF, 0x413, 0x0, NULL, - func_8038AEB8, NULL, func_8038AD9C, +extern ActorInfo chRBBWhistleSwitch1 = { + MARKER_195_WHISTLE_SWITCH_1, ACTOR_1BF_WHISTLE_SWITCH_1, ASSET_413_MODEL_WHISTLE_SWITCH_1, + 0x0, NULL, + chRBBWhistleSwitch_update, NULL, chRBBWhistleSwitch_draw, 0, 0, 0.0f, 0 }; -extern ActorInfo D_803908E4 = { - 0x196, 0x1C0, 0x414, 0x0, NULL, - func_8038AEB8, NULL, func_8038AD9C, + +extern ActorInfo chRBBWhistleSwitch2 = { + MARKER_196_WHISTLE_SWITCH_2, ACTOR_1C0_WHISTLE_SWITCH_2, ASSET_414_MODEL_WHISTLE_SWITCH_2, + 0x0, NULL, + chRBBWhistleSwitch_update, NULL, chRBBWhistleSwitch_draw, 0, 0, 0.0f, 0 }; -extern ActorInfo D_80390908 = { - 0x197, 0x1C1, 0x415, 0x0, NULL, - func_8038AEB8, NULL, func_8038AD9C, +extern ActorInfo chRBBWhistleSwitch3 = { + MARKER_197_WHISTLE_SWITCH_3, ACTOR_1C1_WHISTLE_SWITCH_3, ASSET_415_MODEL_WHISTLE_SWITCH_3, + 0x0, NULL, + chRBBWhistleSwitch_update, NULL, chRBBWhistleSwitch_draw, 0, 0, 0.0f, 0 }; s32 D_8039092C[3] = { 0, 0xFF, 0}; s32 D_80390938[3] = { 0xFF, 0, 0}; +enum chrbbwhistleswitch_state_e { + CH_RBB_WHISTLE_SWITCH_STATE_0_NOT_INIT, + CH_RBB_WHISTLE_SWITCH_STATE_1_UNK, + CH_RBB_WHISTLE_SWITCH_STATE_2_UNK +}; + /* .code */ -Struct_RBB_47D0 *RBB_func_8038ABC0(Actor *arg0){ - Struct_RBB_47D0 *iPtr = D_80390870; - while(iPtr->unk0 != 0){ - if(iPtr->unk0 == arg0->modelCacheIndex) +Struct_ChWhistleSwitchInfo *chWhistleSwitch_getInfoPointer(Actor *this){ + Struct_ChWhistleSwitchInfo *iPtr = chWhistleSwitchTable; + while(iPtr->actorId != NULL){ + if(iPtr->actorId == this->modelCacheIndex) return iPtr; iPtr++; } return NULL; } -void func_8038AC18(Actor *this, s32 new_state){ +void chRBBWhistleSwitch_setState(Actor *this, s32 new_state){ ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&this->local; Actor *whistle_ctrl; local->unk8 = 0.0f; - if(new_state == 2){ + if(new_state == CH_RBB_WHISTLE_SWITCH_STATE_2_UNK){ func_8030E6D4(SFX_90_SWITCH_PRESS); - local->unkC = vtxList_clone(modelbin_getVtxList(marker_loadModelBin(this->marker))); + // [port] Clone once and keep it. Freeing on release hands the buffer back + // while a display list built from this tick may still be queued for the + // render thread. + if(local->unkC == NULL){ + BKVertexList *src = modelbin_getVtxList(marker_loadModelBin(this->marker)); + local->unkC = vtxList_clone(src); + local->portVtxBack = vtxList_clone(src); + } - mapSpecificFlags_set(local->unk4->unk10, true); + mapSpecificFlags_set(local->whistleSwitchInfo->mapSpecificFlag, true); this->position_y -= 30.0f; local->unk8 = 1.0f; - whistle_ctrl = actorArray_findActorFromActorId(0x1c5); + whistle_ctrl = actorArray_findActorFromActorId(ACTOR_1C5_WHISTLE_CTRL); if(whistle_ctrl){ - local->unk0 = chWhistleCtrl_newEvent(whistle_ctrl, this->modelCacheIndex - 0x1be, this); + local->unk0 = chWhistleCtrl_newEvent(whistle_ctrl, this->modelCacheIndex - ACTOR_1BE_RBB_GREY_PROPELLOR_SWITCH, this); } }//L8038ACD0 - if(this->state == 2){ - this->position_x = local->unk4->unk4[0]; - this->position_y = local->unk4->unk4[1]; - this->position_z = local->unk4->unk4[2]; - vtxList_free(local->unkC); + if(this->state == CH_RBB_WHISTLE_SWITCH_STATE_2_UNK){ + this->position_x = local->whistleSwitchInfo->position[0]; + this->position_y = local->whistleSwitchInfo->position[1]; + this->position_z = local->whistleSwitchInfo->position[2]; } this->state = new_state; } -void func_8038AD3C(ActorMarker *marker, ActorMarker *arg1){ +void chRBBWhistleSwitch_press(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); if(actor->state == 1) - func_8038AC18(actor, 2); + chRBBWhistleSwitch_setState(actor, 2); } -void func_8038AD7C(Actor *this){ - func_8038AC18(this, 0); +void chRBBWhistleSwitch_free(Actor *this){ + ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&this->local; + chRBBWhistleSwitch_setState(this, CH_RBB_WHISTLE_SWITCH_STATE_0_NOT_INIT); + if(local->unkC != NULL){ + // [port] No queued display list may still reference these vertices once + // they are handed back to the heap. + port_pipelineSyncPoint(); + vtxList_free(local->unkC); + vtxList_free(local->portVtxBack); + local->unkC = NULL; + local->portVtxBack = NULL; + } } -Actor *func_8038AD9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ +Actor *chRBBWhistleSwitch_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ Actor * actor = marker_getActor(marker); ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&actor->local; BKModelBin *temp_v0; f32 pad0; s32 *sp1C; - if(actor->state == 0) return actor; @@ -115,48 +143,62 @@ Actor *func_8038AD9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ if( actor->state == 2 && local->unk0 != 0 ){ + BKVertexList *swap; + temp_v0 = marker_loadModelBin(marker); sp1C = (local->unk0 == 2) ? D_80390938 : D_8039092C; + + // [port] Alternate between two clones. + swap = local->unkC; + local->unkC = local->portVtxBack; + local->portVtxBack = swap; + vtxList_tintColorsFrom(local->unkC, sp1C, - (local->unk4->unk4[1] - actor->position_y)/30.0, + (local->whistleSwitchInfo->position[1] - actor->position_y) / 30.0, modelbin_getVtxList(temp_v0) ); modelRender_setVertexList(local->unkC); } + return actor_draw(marker, gdl, mptr, arg3); } -void func_8038AEB8(Actor *this){ +void chRBBWhistleSwitch_update(Actor *this){ ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&this->local; - f32 sp20 = time_getDelta(); - s32 tmp; + f32 time_delta = time_getDelta(); + s32 y_position; if(!this->volatile_initialized){ this->volatile_initialized = true; + // [port] The map savestate memcpys `local` wholesale and only nulls the + // Actor's own heap pointers, so these two come back pointing at freed + // vertices. Drop them before anything can reuse or free them again. + local->unkC = NULL; + local->portVtxBack = NULL; this->marker->propPtr->unk8_3 = 1; - this->marker->actorFreeFunc = func_8038AD7C; - marker_setCollisionScripts(this->marker, NULL, func_8038AD3C, NULL); - local->unk4 = RBB_func_8038ABC0(this); - mapSpecificFlags_set(local->unk4->unk10, false); - this->position_x = local->unk4->unk4[0]; - this->position_y = local->unk4->unk4[1]; - this->position_z = local->unk4->unk4[2]; + this->marker->actorFreeFunc = chRBBWhistleSwitch_free; + marker_setCollisionScripts(this->marker, NULL, chRBBWhistleSwitch_press, NULL); + local->whistleSwitchInfo = chWhistleSwitch_getInfoPointer(this); + mapSpecificFlags_set(local->whistleSwitchInfo->mapSpecificFlag, false); + this->position_x = local->whistleSwitchInfo->position[0]; + this->position_y = local->whistleSwitchInfo->position[1]; + this->position_z = local->whistleSwitchInfo->position[2]; this->yaw = -90.0f; - func_8038AC18(this, 1); + chRBBWhistleSwitch_setState(this, CH_RBB_WHISTLE_SWITCH_STATE_1_UNK); }//L8038AF88 - if(ml_timer_update(&local->unk8, sp20)) - func_8038AC18(this, 1); + if(ml_timer_update(&local->unk8, time_delta)) + chRBBWhistleSwitch_setState(this, CH_RBB_WHISTLE_SWITCH_STATE_1_UNK); - if(this->state == 2){ - tmp = (s32)this->position_y; - if(this->position_y < local->unk4->unk4[1]) - this->position_y += 60.0f*sp20; + if(this->state == CH_RBB_WHISTLE_SWITCH_STATE_2_UNK){ + y_position = (s32)this->position_y; + if(this->position_y < local->whistleSwitchInfo->position[1]) + this->position_y += 60.0f * time_delta; - if( tmp < local->unk4->unk4[1] - 15.0f - && local->unk4->unk4[1] - 15.0f <= this->position_y + if( y_position < local->whistleSwitchInfo->position[1] - 15.0f + && local->whistleSwitchInfo->position[1] - 15.0f <= this->position_y ){ - mapSpecificFlags_set(local->unk4->unk10, false); + mapSpecificFlags_set(local->whistleSwitchInfo->mapSpecificFlag, false); } }//L8038B044 } diff --git a/src/RBB/checksums.c b/src/RBB/checksums.c new file mode 100644 index 000000000..37275e9d0 --- /dev/null +++ b/src/RBB/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: RBB/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsRBB; diff --git a/src/RBB/crane_boombox.c b/src/RBB/crane_boombox.c index 326281704..d3bc55879 100644 --- a/src/RBB/crane_boombox.c +++ b/src/RBB/crane_boombox.c @@ -6,14 +6,16 @@ #include + /* typedefs and declarations */ -void func_803881E8(Actor *this, s32 arg1); -void RBB_func_803882F4(Actor *this); +void chTNTDownSwitch_setState(Actor *this, s32 arg1); +void chTNTDownSwitch_update(Actor *this); /* .data */ -ActorInfo D_80390270 = { - 0x184, 0x174, 0x402, 0x0, NULL, - RBB_func_803882F4, NULL, func_80325340, +ActorInfo chTNTDownSwitch = { + MARKER_184_RBB_TNT_DOWN_SWITCH, ACTOR_174_RBB_TNT_DOWN_SWITCH, ASSET_402_MODEL_EGG_TOLL, + 0x0, NULL, + chTNTDownSwitch_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; @@ -22,11 +24,11 @@ s32 D_803902A4[4] = { 0x76, 0, 0, 0xff}; s32 D_803902B4[4] = { 0x76, 0, 0, 0xff}; s32 D_803902C4[4] = { 0xff, 0, 0, 0xff}; - f32 D_803902D4[3] = {4500.0f, 0.0f, 500.0f}; f32 D_803902E0[3] = {4500.0f, 0.0f, 500.0f}; f32 D_803902EC[3] = {4000.0f, -600.0f, 0.0f}; f32 D_803902F8[3] = {4500.0f, 0.0f, 500.0f}; + ParticleScaleAndLifetimeRanges D_80390304 = { { 5.0f, 5.0f}, { 5.0f, 5.0f}, @@ -38,11 +40,18 @@ ParticleScaleAndLifetimeRanges D_80390304 = { f32 D_8039032C[3] = {3700.0f, -300.0f, -300.0f}; f32 D_80390338[3] = {4500.0f, 100.0f, 400.0f}; + ParticleSettingsVelocityAcceleration D_80390344= { {{-700.0f, 200.0f, -700.0f}, {700.0f, 500.0f, 700.0f}}, {{ 0.0f, -800.0f, 0.0f}, { 0.0f, -800.0f, 0.0f}} }; +enum chtntdownswitch_state_e { + CH_TNT_DOWN_SWITCH_STATE_0_NOT_INIT, + CH_TNT_DOWN_SWITCH_STATE_1_NOT_PRESSED, + CH_TNT_DOWN_SWITCH_STATE_2_PRESSED +}; + /*.code */ void RBB_func_80387960(f32 arg0){ f32 sp34[3]; @@ -114,7 +123,7 @@ void func_80387B8C(s32 arg0, s32 arg1){ Struct70s *tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *v0 = &tmp_s70->type_6D; - func_8034DFB0(v0, D_80390294, D_803902A4, (f64)arg1/1000.0); + func_8034DFB0(v0, D_80390294, D_803902A4, (f64)arg1 / 1000.0); } } @@ -124,11 +133,11 @@ void func_80387BEC(s32 arg0, s32 arg1){ tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *v0 = &tmp_s70->type_6D; - func_8034DFB0(v0, D_803902B4, D_803902C4, (f64)arg1/1000.0); + func_8034DFB0(v0, D_803902B4, D_803902C4, (f64)arg1 / 1000.0); } } -void func_80387C5C(void){ +void chTNTDownSwitch_emitExplosion(void){ ParticleEmitter *actor; func_802BB3DC(0, 60.0f, 0.9f); @@ -145,7 +154,7 @@ void func_80387C5C(void){ particleEmitter_emitInVolume(actor, D_803902D4, D_803902E0, 1); } -void func_80387D80(void){ +void chTNTDownSwitch_emitSmoke(void){ ParticleEmitter *actor = partEmitMgr_newEmitter(3); particleEmitter_setSprite(actor, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setStartingFrameRange(actor, 0, 7); @@ -154,11 +163,11 @@ void func_80387D80(void){ particleEmitter_emitInVolume(actor, D_803902EC, D_803902F8, 3); } -void func_80387E20(void){ +void chTNTDownSwitch_emitWoodenPlank(void){ ParticleEmitter *actor = partEmitMgr_newEmitter(0x19); particleEmitter_func_802EF9F8(actor, 0.6f); particleEmitter_func_802EFA18(actor, 3); - particleEmitter_setModel(actor, 0x427); + particleEmitter_setModel(actor, ASSET_427_MODEL_WOODEN_PLANK); particleEmitter_setStartingScaleRange(actor, 0.05f, 0.4f); particleEmitter_setAngularVelocityRange(actor, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f); particleEmitter_setSpawnIntervalRange(actor, 0.0f, 0.01f); @@ -167,67 +176,67 @@ void func_80387E20(void){ particleEmitter_emitInVolume(actor, D_8039032C, D_80390338, 0x19); } -void RBB_func_80387F18(ActorMarker *marker, s32 arg1){ - func_803881E8(marker_getActor(marker), arg1); +void chTNTDownSwitch_setStateByMarker(ActorMarker *marker, s32 next_state){ + chTNTDownSwitch_setState(marker_getActor(marker), next_state); } void RBB_func_80387F44(void){ baMotor_80250E94(0.5f, 1.0f, 1.5f, 0.0f, 1.0f, 1.5f); } -void func_80387F88(ActorMarker *marker){ +void chTNTDownSwitch_emits(ActorMarker *marker){ Actor *actor = marker_getActor(marker); - timedFunc_set_0(0.0f, func_80387C5C); + timedFunc_set_0(0.0f, chTNTDownSwitch_emitExplosion); timed_playSfx(0.1f, SFX_1B_EXPLOSION_1, 1.0f, 22000); timed_playSfx(0.1f, SFX_1B_EXPLOSION_1, 1.0f, 22000); - timedFunc_set_0(0.3f, func_80387E20); + timedFunc_set_0(0.3f, chTNTDownSwitch_emitWoodenPlank); timedFunc_set_0(0.5f, func_80387A54); timedFunc_set_0(0.4f, func_80387B24); timed_playSfx(0.41f, SFX_1B_EXPLOSION_1, 0.8f, 22000); timed_playSfx(0.41f, SFX_1B_EXPLOSION_1, 0.8f, 22000); - timedFunc_set_0(0.55f, func_80387D80); + timedFunc_set_0(0.55f, chTNTDownSwitch_emitSmoke); timed_playSfx(0.71f, SFX_1B_EXPLOSION_1, 0.6f, 22000); timed_playSfx(0.71f, SFX_1B_EXPLOSION_1, 0.6f, 22000); - timedFunc_set_0(0.8f, func_80387D80); + timedFunc_set_0(0.8f, chTNTDownSwitch_emitSmoke); timed_playSfx(1.0f, SFX_1A_BIG_THINGS_FALL_OVER, 1.0f, 22000); timed_playSfx(2.0f, SFX_1A_BIG_THINGS_FALL_OVER, 0.8f, 22000); timed_playSfx(3.0f, SFX_1A_BIG_THINGS_FALL_OVER, 0.6f, 22000); timed_exitStaticCamera(4.0f); func_80324E38(4.0f, 0); - timedFunc_set_2(4.0f, (GenFunction_2) RBB_func_80387F18, (uintptr_t)actor->marker, 3); + timedFunc_set_2(4.0f, (GenFunction_2) chTNTDownSwitch_setStateByMarker, (uintptr_t)actor->marker, 3); } -void func_80388154(ActorMarker *marker){ +void chTNTDownSwitch_dropTNTActions(ActorMarker *marker){ Actor *actor = marker_getActor(marker); func_803879F0(); timedFunc_set_0(0.0f, (GenFunction_0) RBB_func_80387F44); - timed_playSfx(0.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 0x7fc6); + timed_playSfx(0.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 32710); timedFunc_set_2(1.2f, (GenFunction_2) func_80387B8C, 0x19f, 0); timed_setStaticCameraToNode(1.2f, 8); - timedFunc_set_1(1.5f, (GenFunction_1) func_80387F88, (uintptr_t)actor->marker); + timedFunc_set_1(1.5f, (GenFunction_1) chTNTDownSwitch_emits, (uintptr_t)actor->marker); } -void func_803881E8(Actor *this, s32 arg1){ - this->state = arg1; - if(this->state == 2){ +void chTNTDownSwitch_setState(Actor *this, s32 next_state){ + this->state = next_state; + if(this->state == CH_TNT_DOWN_SWITCH_STATE_2_PRESSED){ RBB_func_80387960(0.05f); timedFunc_set_2(0.05f, (GenFunction_2)func_80387BEC, 0x19f, 0x1f4); timedFunc_set_2(0.1f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2B_DING_B, 28000); func_80324E38(0.2f, 3); timed_setStaticCameraToNode(1.1f, 7); - timedFunc_set_1(1.6f, (GenFunction_1)func_80388154, (uintptr_t)this->marker); + timedFunc_set_1(1.6f, (GenFunction_1)chTNTDownSwitch_dropTNTActions, (uintptr_t)this->marker); levelSpecificFlags_set(LEVEL_FLAG_2D_RBB_UNKNOWN, true); } } -void func_803882B4(ActorMarker *marker, ActorMarker *arg1){ +void chTNTDownSwitch_pushSwitch(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - if(actor->state == 1) - func_803881E8(actor, 2); + if(actor->state == CH_TNT_DOWN_SWITCH_STATE_1_NOT_PRESSED) + chTNTDownSwitch_setState(actor, CH_TNT_DOWN_SWITCH_STATE_2_PRESSED); } -void RBB_func_803882F4(Actor *this){ +void chTNTDownSwitch_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; @@ -235,12 +244,19 @@ void RBB_func_803882F4(Actor *this){ func_80387AC0(); RBB_func_80387960(0.0f); func_80387B24(); - func_803881E8(this, 3); + chTNTDownSwitch_setState(this, 3); } else { - marker_setCollisionScripts(this->marker, NULL, func_803882B4, NULL); + marker_setCollisionScripts(this->marker, NULL, chTNTDownSwitch_pushSwitch, NULL); suSetSpriteScale(this, 1.1f); - func_803881E8(this, 1); + chTNTDownSwitch_setState(this, 1); } } + // Anchor: teammate opened the entrance (LEVEL_FLAG_2D) - snap to opened state. + else if (this->state == 1 && levelSpecificFlags_get(LEVEL_FLAG_2D_RBB_UNKNOWN)) { + func_80387AC0(); + RBB_func_80387960(0.0f); + func_80387B24(); + chTNTDownSwitch_setState(this, 3); + } } diff --git a/src/RBB/crane_jiggycage.c b/src/RBB/crane_jiggycage.c index a42412af0..3be35a292 100644 --- a/src/RBB/crane_jiggycage.c +++ b/src/RBB/crane_jiggycage.c @@ -6,13 +6,19 @@ #include /* typedefs and declarations */ -void func_803878B0(Actor *this); -void func_8038756C(Actor *this, s32 arg1); +void chCageUpSwitch_update(Actor *this); +void chCageUpSwitch_setState(Actor *this, s32 arg1); + +// Anchor: set while replaying a teammate's crane action; suppresses camera pans and auto-raise. +static s32 sCraneRemote = 0; +extern void port_jiggyCrane_broadcast(s32 stage); +extern ActorArray *suBaddieActorArray; /* .data */ -ActorInfo D_80390200 = { - 0x183, 0x173, 0x402, 0x0, NULL, - func_803878B0, NULL, func_80325340, +ActorInfo chCageUpSwitch = { + MARKER_183_RBB_CAGE_UP_SWITCH, ACTOR_173_RBB_CAGE_UP_SWITCH, ASSET_402_MODEL_EGG_TOLL, + 0x0, NULL, + chCageUpSwitch_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; @@ -23,16 +29,24 @@ s32 D_80390254[4] = { 0xff, 0, 0, 0xff}; f32 D_80390264[3] = {-4900.0f, 0.0f, 0.0f}; +enum chcageupswitch_state_e { + CH_CAGE_UP_SWITCH_STATE_0_NOT_INIT, + CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED, + CH_CAGE_UP_SWITCH_STATE_2_RAISING_CAGE, + CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE, + CH_CAGE_UP_SWITCH_STATE_4_LOWER_CAGE +}; + /* .code */ -void func_80387090(ActorMarker *marker, s32 arg1){ - func_8038756C(marker_getActor(marker), arg1); +void chCageUpSwitch_setStateByMarker(ActorMarker *marker, s32 next_state){ + chCageUpSwitch_setState(marker_getActor(marker), next_state); } void func_803870BC(s32 arg0, s32 arg1){ Struct70s *tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *temp_v0 = &tmp_s70->type_6D; - func_8034DFB0(temp_v0, D_80390224, D_80390234, (f64)arg1/1000.0); + func_8034DFB0(temp_v0, D_80390224, D_80390234, (f64)arg1 / 1000.0); } } @@ -42,7 +56,7 @@ void func_8038711C(s32 arg0, s32 arg1){ tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *temp_v0 = &tmp_s70->type_6D; - func_8034DFB0(temp_v0, D_80390244, D_80390254, (f64)arg1/1000.0); + func_8034DFB0(temp_v0, D_80390244, D_80390254, (f64)arg1 / 1000.0); } } @@ -59,17 +73,21 @@ void func_8038718C(ActorMarker *marker){ func_8034DDF0(sp44, sp38, sp2C, 4.0f, 1); func_8034E1A4(sp44, SFX_D8_CRANE, 1.0f, 1.0f); } - timed_setStaticCameraToNode(0.0f, 4); - timed_setStaticCameraToNode(2.5f, 5); + if (!sCraneRemote) { + timed_setStaticCameraToNode(0.0f, 4); + timed_setStaticCameraToNode(2.5f, 5); + } timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.5f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.6f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.7f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.9f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 19000);\ - timed_exitStaticCamera(5.0f); - func_80324E38(5.0f, 0); - timedFunc_set_2(5.0f, (GenFunction_2) func_80387090, (uintptr_t) marker, 3); + if (!sCraneRemote) { + timed_exitStaticCamera(5.0f); + func_80324E38(5.0f, 0); + } + timedFunc_set_2(5.0f, (GenFunction_2) chCageUpSwitch_setStateByMarker, (uintptr_t)marker, CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE); } void func_80387308(ActorMarker *marker){ @@ -91,32 +109,35 @@ void func_80387308(ActorMarker *marker){ timed_playSfx(0.5f, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 19000); timed_playSfx(0.5f, SFX_7F_HEAVYDOOR_SLAM, 0.9f, 19000); timed_playSfx(0.5f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 19000); - timedFunc_set_2(0.5f, (GenFunction_2) func_80387090, (uintptr_t)actor->marker, 1); + timedFunc_set_2(0.5f, (GenFunction_2) chCageUpSwitch_setStateByMarker, (uintptr_t)actor->marker, CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED); timedFunc_set_2(1.5f, (GenFunction_2) func_803870BC, 0x19d, 0x1f4); - timed_exitStaticCamera(1.5f); - func_80324E38(1.5f, 0); - + if (!sCraneRemote) { + timed_exitStaticCamera(1.5f); + func_80324E38(1.5f, 0); + } } void func_80387488(ActorMarker *marker){ - f32 sp1C[3]; + f32 player_position[3]; Actor *actor = marker_getActor(marker); - player_getPosition(sp1C); - if(-50.0f < sp1C[1] && sp1C[1] < 600.0f){ - sp1C[1] = 0; - if(ml_vec3f_distance(sp1C, D_80390264) < 500.0f){ + player_getPosition(player_position); + if(-50.0f < player_position[1] && player_position[1] < 600.0f){ + player_position[1] = 0; + if(ml_vec3f_distance(player_position, D_80390264) < 500.0f){ timedFunc_set_1(1.0f, (GenFunction_1) func_80387488, (uintptr_t)actor->marker); return; } } - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 6); + if (!sCraneRemote) { + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 6); + } timedFunc_set_1(0.5f, (GenFunction_1) func_80387308, (uintptr_t)actor->marker); } -void func_8038756C(Actor *this, s32 arg1){ +void chCageUpSwitch_setState(Actor *this, s32 next_state){ f32 sp6C[3]; f32 sp60[3]; void * temp_v0; @@ -127,7 +148,8 @@ void func_8038756C(Actor *this, s32 arg1){ f32 sp30[3]; f32 sp24[3]; - if(arg1 == 1){ + if(next_state == CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED){ + sCraneRemote = 0; if(this->state != 0){ sp6C[0] = 0.0f; sp6C[1] = 0.0f; @@ -142,7 +164,10 @@ void func_8038756C(Actor *this, s32 arg1){ } }//L80387610 - if(arg1 == 2){ + if(next_state == CH_CAGE_UP_SWITCH_STATE_2_RAISING_CAGE){ + if (!sCraneRemote) { + port_jiggyCrane_broadcast(2); + } sp50[0] = sp50[1] = sp50[2] = 0.0f; sp44[0] = 0.0f; sp44[1] = 0.0f; @@ -156,20 +181,25 @@ void func_8038756C(Actor *this, s32 arg1){ timedFunc_set_2(0.1f, (GenFunction_2)func_8038711C, 0x19d, 0x1f4); timedFunc_set_2(0.1f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2B_DING_B, 28000); - func_80324E38(0.2f, 3); + if (!sCraneRemote) { + func_80324E38(0.2f, 3); + } timedFunc_set_1(1.1f, (GenFunction_1)func_8038718C, (uintptr_t)this->marker); }//L80387704 - if(arg1 == 3){ + if(next_state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE){ item_set(ITEM_6_HOURGLASS, 1); - item_set(ITEM_0_HOURGLASS_TIMER, 0x3bf); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(0x3bf, 0x31f, 0, 0)); } - if(this->state == 3){ + if(this->state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE){ item_set(ITEM_6_HOURGLASS, 0); } - if(arg1 == 4){ + if(next_state == CH_CAGE_UP_SWITCH_STATE_4_LOWER_CAGE){ + if (!sCraneRemote) { + port_jiggyCrane_broadcast(4); + } sp3C = func_8034C528(0x19a); if(sp3C){ sp30[0] = 0.0f; @@ -188,32 +218,52 @@ void func_8038756C(Actor *this, s32 arg1){ timedFunc_set_1(4.0f, (GenFunction_1)func_80387488, (uintptr_t)this->marker); }//L80387828 - this->state = arg1; + this->state = next_state; } -void func_80387850(ActorMarker *marker, ActorMarker *arg1){ +void chCageUpSwitch_pushSwitch(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - if(actor->state == 1){ - func_8038756C(actor, 2); + if(actor->state == CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED){ + chCageUpSwitch_setState(actor, CH_CAGE_UP_SWITCH_STATE_2_RAISING_CAGE); } } -void func_80387890(Actor *this){ - func_8038756C(this, 0); +void chCageUpSwitch_free(Actor *this){ + chCageUpSwitch_setState(this, CH_CAGE_UP_SWITCH_STATE_0_NOT_INIT); } -void func_803878B0(Actor *this){ +void chCageUpSwitch_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - this->marker->actorFreeFunc = func_80387890; - marker_setCollisionScripts(this->marker, NULL, func_80387850, NULL); + this->marker->actorFreeFunc = chCageUpSwitch_free; + marker_setCollisionScripts(this->marker, NULL, chCageUpSwitch_pushSwitch, NULL); suSetSpriteScale(this, 1.1f); - func_8038756C(this, 1); + chCageUpSwitch_setState(this, CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED); } - if(this->state == 3){ + if(this->state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE && !sCraneRemote){ if(item_empty(ITEM_0_HOURGLASS_TIMER)){ - func_8038756C(this, 4); + chCageUpSwitch_setState(this, CH_CAGE_UP_SWITCH_STATE_4_LOWER_CAGE); + } + } +} + +void port_jiggyCrane_remoteApply(s32 stage) { + s32 i; + + if (suBaddieActorArray == NULL) { + return; + } + for (i = 0; i < suBaddieActorArray->cnt; i++) { + Actor *actor = &suBaddieActorArray->data[i]; + if (actor->marker == NULL || actor->marker->id != MARKER_183_RBB_CAGE_UP_SWITCH) { + continue; + } + if ((stage == 2 && actor->state == CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED) + || (stage == 4 && actor->state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE)) { + sCraneRemote = 1; + chCageUpSwitch_setState(actor, stage); } + return; } } diff --git a/src/RBB/miniboombox_container.c b/src/RBB/miniboombox_container.c index 0fb74ee1d..f997a4634 100644 --- a/src/RBB/miniboombox_container.c +++ b/src/RBB/miniboombox_container.c @@ -5,59 +5,67 @@ extern -void RBB_func_8038FB84(Actor *this); +void chBoomBoxMinigameCtrl_update(Actor *this); /* .data */ -ActorInfo RBB_D_80390E00 = { - 0x1B8, 0x2A5, 0x0, 0x0, NULL, - RBB_func_8038FB84, NULL, func_80325340, +ActorInfo chBoomBoxMinigameCtrl = { + MARKER_1B8_BOOM_BOX_MINIGAME_CTRL, ACTOR_2A5_BOOM_BOX_MINIGAME_CTRL, 0x0, + 0x0, NULL, + chBoomBoxMinigameCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; +enum chboomboxminigamectrl_state_e { + CH_BOOMBOX_MINIGAME_CTRL_STATE_0_NOT_INIT, + CH_BOOMBOX_MINIGAME_CTRL_STATE_1_INIT, + CH_BOOMBOX_MINIGAME_CTRL_STATE_2_PARTIAL_COMPLETE, + CH_BOOMBOX_MINIGAME_CTRL_STATE_3_COMPLETE +}; + /* .bss */ -u8 D_803912B0; +u8 chBoomBoxMinigameRemainingCount; /* .code */ -void RBB_func_8038FA60(ActorMarker *marker){ +void chBoomBoxMinigameCtrl_spawnExtraLife(ActorMarker *marker){ Actor *actor = marker_getActor(marker); bundle_setYaw(actor->yaw); bundle_spawn_f32(BUNDLE_6_MM_HUT_EXTRA_LIFE, actor->position); } -void func_8038FA9C(Actor *this, s32 arg1){ - if(arg1 == 3){ +void chBoomBoxMinigameCtrl_setState(Actor *this, s32 next_state){ + if(next_state == CH_BOOMBOX_MINIGAME_CTRL_STATE_3_COMPLETE){ func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2B_DING_B, 28000); timed_setStaticCameraToNode(1.8f, 1); - timedFunc_set_1(2.0f, (GenFunction_1) RBB_func_8038FA60, (uintptr_t)this->marker); + timedFunc_set_1(2.0f, (GenFunction_1) chBoomBoxMinigameCtrl_spawnExtraLife, (uintptr_t)this->marker); timed_exitStaticCamera(5.0f); func_80324E38(5.0f, 0); } - this->state = arg1; + this->state = next_state; } -void func_8038FB54(void){ - D_803912B0++; +void chBoomBoxMinigameCtrl_countInc(void){ + chBoomBoxMinigameRemainingCount++; } -void func_8038FB6C(void){ - D_803912B0--; +void chBoomBoxMinigameCtrl_countDec(void){ + chBoomBoxMinigameRemainingCount--; } -void RBB_func_8038FB84(Actor *this){ +void chBoomBoxMinigameCtrl_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - D_803912B0 = 0; - func_8038FA9C(this, 1); + chBoomBoxMinigameRemainingCount = 0; + chBoomBoxMinigameCtrl_setState(this, CH_BOOMBOX_MINIGAME_CTRL_STATE_1_INIT); } - if(this->state == 1){ - if(D_803912B0 > 0) - func_8038FA9C(this, 2); + if(this->state == CH_BOOMBOX_MINIGAME_CTRL_STATE_1_INIT){ + if(chBoomBoxMinigameRemainingCount > 0) + chBoomBoxMinigameCtrl_setState(this, CH_BOOMBOX_MINIGAME_CTRL_STATE_2_PARTIAL_COMPLETE); } - if(this->state == 2){ - if(D_803912B0 == 0) - func_8038FA9C(this, 3); + if(this->state == CH_BOOMBOX_MINIGAME_CTRL_STATE_2_PARTIAL_COMPLETE){ + if(chBoomBoxMinigameRemainingCount == 0) + chBoomBoxMinigameCtrl_setState(this, CH_BOOMBOX_MINIGAME_CTRL_STATE_3_COMPLETE); } } diff --git a/src/RBB/propellorctrl.c b/src/RBB/propellorctrl.c index e9ae4c96d..ec2f6f6e8 100644 --- a/src/RBB/propellorctrl.c +++ b/src/RBB/propellorctrl.c @@ -17,7 +17,7 @@ void __propellorCtrl_setState(s32 arg0){ } if(arg0 == 2){ - item_set(ITEM_3_PROPELLOR_TIMER, 3900 - 1); + item_set(ITEM_3_PROPELLOR_TIMER, VER_SELECT(3900, 3250, 0, 0) - 1); item_set(ITEM_9_PROPELLOR, 1); } @@ -27,7 +27,7 @@ void __propellorCtrl_setState(s32 arg0){ item_set(ITEM_9_PROPELLOR,0); if(arg0 == 3 && !jiggyscore_isCollected(JIGGY_57_RBB_PROPELLOR)){ timedFunc_set_1(0.5f, (GenFunction_1)func_802FAD64, 3); - func_80324DBC(1.0f, ASSET_B9D_DIALOG_GRUNTY_PROPELLER_MISS, 4, NULL, NULL, NULL, NULL); + func_80324DBC(1.0f, VER_SELECT(ASSET_B9D_DIALOG_GRUNTY_PROPELLER_MISS, 0x972, 0, 0), 4, NULL, NULL, NULL, NULL); } else{ func_802FAD64(3); diff --git a/src/RBB/rbbspawnqueue.c b/src/RBB/rbbspawnqueue.c new file mode 100644 index 000000000..211b30172 --- /dev/null +++ b/src/RBB/rbbspawnqueue.c @@ -0,0 +1,241 @@ +// BanjoDecomp: RBB/rbbspawnqueue.c +#include +#include "core1/core1.h" +#include "functions.h" +#include "variables.h" +#include "prop.h" +#include "actor.h" + +#include "port/Patches/Patches.h" + + +extern ActorInfo chBellBuoy; +extern ActorInfo chRBBEggToll; +extern ActorInfo chCageUpSwitch; +extern ActorInfo chTNTDownSwitch; +extern ActorInfo chRowboat; +extern ActorInfo chRBBRearPropeller; +extern ActorInfo chRBBGreenPropellerSwitch; +extern ActorInfo chRBBSpinningSinglePipe1; +extern ActorInfo chRBBSpinningSinglePipe2; +extern ActorInfo chRBBSpinningDoublePipe1; +extern ActorInfo chRBBSpinningDoublePipe2; +extern ActorInfo chSpinningFlatPlatform1; +extern ActorInfo chSpinningFlatPlatform2; +extern ActorInfo chSpinningFlatPlatform3; +extern ActorInfo chRBBSmallCog; +extern ActorInfo chRBBMediumCog; +extern ActorInfo chRBBLargeCog; +extern ActorInfo chEngineRoomPropeller1; +extern ActorInfo chEngineRoomPropeller2; +extern ActorInfo chEngineRoomPropeller3; +extern ActorInfo chRBBGreyPropellerSwitch; +extern ActorInfo chRBBWhistleSwitch1; +extern ActorInfo chRBBWhistleSwitch2; +extern ActorInfo chRBBWhistleSwitch3; +extern ActorInfo chRBBWhistle1; +extern ActorInfo chRBBWhistle2; +extern ActorInfo chRBBWhistle3; +extern ActorInfo chRBBWhistleCtrl; +extern ActorInfo chGrimlet; +extern ActorInfo chAnchorSwitch; //anchorswitch +extern ActorInfo chSnorkel; //dolphin +extern ActorInfo chAnchor; //anchor +extern ActorInfo chAnchorCtrl; +extern ActorInfo chRarewareFlag; //rarewareflag +extern ActorInfo chBossBoomBoxLargest; +extern ActorInfo chBossBoomBoxLarge; +extern ActorInfo chBossBoomBoxMedium; +extern ActorInfo chBossBoomBoxSmall; +extern ActorInfo chBossBoomBoxCtrl; +extern ActorInfo chBoomBoxSlow; +extern ActorInfo chBoomBoxFast; //TNTpart_IDStruct; +extern ActorInfo chBoomBoxMinigameCtrl; +extern ActorInfo chRBBSpinningSinglePipeSfxCtrl; +extern ActorInfo chRBBSpinningDoublePipeSfxCtrl; +extern ActorInfo chEngineRoomDoor; +extern ActorInfo chCabinClosetDoor; //captcabinwooddoor +extern ActorInfo chShipShadowWindow; +extern ActorInfo chShipSunnyWindow; +extern ActorInfo chSunnyLifeboat; +extern ActorInfo chShadowLifeboat; +extern ActorInfo chCrackedSkylight;//skylight +extern ActorInfo chRbbHoneycombSwitch;//honeycombswitch + + + +extern void chMMMBreakableWooden_update(Actor *); + +void func_80386A7C(Actor *); +void func_80386BF8(Actor *arg0); +Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); + + +/* .data */ +ActorAnimationInfo D_803900C0[4] = { + {0, 0.0f}, + {0, 0.0f}, + {0xD4, 0.15f}, + {0xD5, 0.5f} +}; + +ActorInfo chEngineRoomDoor = { + MARKER_107_ENGINE_ROOM_DOOR, ACTOR_21D_ENGINE_ROOM_DOOR, ASSET_493_MODEL_ENGINE_ROOM_DOOR, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCabinClosetDoor = { + MARKER_108_CABIN_CLOSET_DOOR, ACTOR_21C_CABIN_CLOSET_DOOR, ASSET_492_MODEL_CABIN_CLOSET_DOOR, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chShipShadowWindow = { + MARKER_22D_SHIP_SHADOW_WINDOW, ACTOR_266_SHIP_SHADOW_WINDOW, ASSET_4BA_MODEL_SHIP_SHADOW_WINDOW, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chShipSunnyWindow = { + MARKER_22E_SHIP_SUNNY_WINDOW, ACTOR_267_SHIP_SUNNY_WINDOW, ASSET_4BB_MODEL_SHIP_SUNNY_WINDOW, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chCrackedSkylight = { + MARKER_235_CRACKED_SKYLIGHT, ACTOR_23F_CRACKED_SKYLIGHT, ASSET_4E2_MODEL_CRACKED_SKYLIGHT, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chRbbHoneycombSwitch = { + MARKER_15F_RBB_HONEYCOMB_SWITCH, ACTOR_18F_RBB_HONEYCOMB_SWITCH, ASSET_42F_MODEL_RBB_HONEYCOMB_SWITCH, + 0x1, D_803900C0, + func_80386BF8, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chSunnyLifeboat = { + MARKER_22F_SUNNY_LIFEBOAT, ACTOR_263_SUNNY_LIFEBOAT, ASSET_4DB_MODEL_SUNNY_LIFEBOAT, + 0x1, NULL, + func_80386A7C, actor_update_func_80326224, func_80386B9C, + 0, 0, 0.0f, 0 +}; + +ActorInfo chShadowLifeboat = { + MARKER_230_SHADOW_LIFEBOAT, ACTOR_264_SHADOW_LIFEBOAT, ASSET_4DE_MODEL_SHADOW_LIFEBOAT, + 0x1, NULL, + func_80386A7C, actor_update_func_80326224, func_80386B9C, + 0, 0, 0.0f, 0 +}; + + +/* .code */ +s32 func_80386A30(f32 arg0[3]){ + s32 r; + + r = (arg0[0] < 0.0f)? 0 : 1; + + return ((arg0[2] < 0.0f)? 0 : 2) + r; +} + +void func_80386A7C(Actor *this){ + f32 viewport[3]; + s32 sp28; + s32 temp_v0; + + func_802D3D74(this); + this->depth_mode = 1; + viewport_getPosition_vec3f(viewport); + sp28 = func_80386A30(this->position); + temp_v0 = func_80386A30(viewport); + this->unk38_0 = 0; + // [port] Extend the bespoke distance cull with draw distance; quadrant occlusion below stays. + f32 cull = 8000.0f * port_drawDistanceMul(); + if(viewport[0] + cull < this->position_x || this->position_x < viewport[0] - cull) + return; + + if( !( (sp28 ^ temp_v0) & 2 + && (-5000.0f < viewport[0] && viewport[0] < 6000.0f) + && (viewport[2] < -600.0f || 600.0f < viewport[2]) + ) +#if 0 + && ( sp28 ^ temp_v0) != 3 +#endif + ){ + this->unk38_0 = 1; + } +} + +Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ + Actor *actor = marker_getActor(marker); + + return (actor->unk38_0) ? actor_drawFullDepth(marker, gdl, mptr, arg3): NULL; +} + +void func_80386BF8(Actor *arg0){ + if(!mapSpecificFlags_get(RBB_BOAT_ROOM_SPECIFIC_FLAG_0_HONEYCOMB_SPAWNED) && honeycombscore_get(HONEYCOMB_F_RBB_BOAT_HOUSE)) + mapSpecificFlags_set(RBB_BOAT_ROOM_SPECIFIC_FLAG_0_HONEYCOMB_SPAWNED, true); + func_802D4A9C(arg0, 0); +} + +void RBB_func_80386C48(void){ + spawnableActorList_add(&chBellBuoy, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBEggToll, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCageUpSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chTNTDownSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRowboat, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_27); + spawnableActorList_add(&chRBBRearPropeller, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBGreenPropellerSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBSpinningSinglePipe1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBSpinningSinglePipe2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBSpinningDoublePipe1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBSpinningDoublePipe2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chSpinningFlatPlatform1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chSpinningFlatPlatform2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chSpinningFlatPlatform3, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBSmallCog, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBMediumCog, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chRBBLargeCog, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&chEngineRoomPropeller1, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chEngineRoomPropeller2, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chEngineRoomPropeller3, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&chRBBGreyPropellerSwitch, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chRBBWhistleSwitch1, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBWhistleSwitch2, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBWhistleSwitch3, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBWhistle1, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chRBBWhistle2, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chRBBWhistle3, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chRBBWhistleCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chGrimlet, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chAnchorSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); //anchorswitch + spawnableActorList_add(&chSnorkel, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //dolphin + spawnableActorList_add(&chAnchor, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); //anchor + spawnableActorList_add(&chAnchorCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRarewareFlag, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //rarewareflag + spawnableActorList_add(&chBossBoomBoxLargest, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chBossBoomBoxLarge, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chBossBoomBoxMedium, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chBossBoomBoxSmall, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chBossBoomBoxCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chBoomBoxSlow, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&chBoomBoxFast, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&chBoomBoxMinigameCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBSpinningSinglePipeSfxCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chRBBSpinningDoublePipeSfxCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chEngineRoomDoor, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chCabinClosetDoor, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //captcabinwooddoor + spawnableActorList_add(&chShipShadowWindow, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chShipSunnyWindow, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chSunnyLifeboat, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&chShadowLifeboat, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&chCrackedSkylight, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //skylight + spawnableActorList_add(&chRbbHoneycombSwitch, actor_new, ACTOR_FLAG_UNKNOWN_3); //honeycombswitch +} diff --git a/src/RBB/siren.c b/src/RBB/siren.c new file mode 100644 index 000000000..a829ce4ae --- /dev/null +++ b/src/RBB/siren.c @@ -0,0 +1,81 @@ +// BanjoDecomp: code_9840.c +#include +#include "functions.h" +#include "variables.h" + +void chRBBSpinningPipeSfxCtrl_update(Actor *this); + +/* typedefs and declarations */ +typedef struct { + s32 unk0; + s16 *actorId; + ActorMarker *marker; +}ActorLocal_RBB_9840; + +/* +These objects only exist in RBB's engine room. +As the spinning pipes rotate, these controllers +create sound effects based off of the rotation speed. +*/ + +/* .data */ +s16 chRBBSpinningPipeSfxCtrlPipeActors[2] = { + ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1, + ACTOR_17F_RBB_SPINNING_DOUBLE_PIPE_1 +}; + +ActorInfo chRBBSpinningSinglePipeSfxCtrl = { + MARKER_1D2_SPINNING_SINGLE_PIPE_SFX_CTRL, ACTOR_31B_SPINNING_SINGLE_PIPE_SFX_CTRL, 0x0, + 0x0, NULL, + chRBBSpinningPipeSfxCtrl_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo chRBBSpinningDoublePipeSfxCtrl = { + MARKER_1D3_DOUBLE_SINGLE_PIPE_SFX_CTRL, ACTOR_31C_DOUBLE_SINGLE_PIPE_SFX_CTRL, 0x0, + 0x0, NULL, + chRBBSpinningPipeSfxCtrl_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +enum chrbbspinningdoublepipesfxctrl_state_e { + CH_RBB_SPINNING_PIPE_SFX_CTRL_STATE_0_NOT_INIT, + CH_RBB_SPINNING_PIPE_SFX_CTRL_STATE_1_INIT +}; + +/*.code */ +// set state +void chRBBSpinningPipeSfxCtrl_setState(Actor *this, s32 next_state){ + this->state = next_state; +} + +// update +void chRBBSpinningPipeSfxCtrl_update(Actor *this){ + ActorLocal_RBB_9840 *local = (ActorLocal_RBB_9840 *)&this->local; + f32 sp20; + f32 tmp_f2; + s32 tmp_a1; + + if(!this->volatile_initialized){ + this->volatile_initialized = true; + actor_collisionOff(this); + local->actorId = chRBBSpinningPipeSfxCtrlPipeActors + (this->marker->id - 0x1D2); + local->marker = NULL; + + local->unk0 = func_802F9AA8(0x400); + func_802F9DB8(local->unk0, 1.0f, 1.0f, 0.0f); + func_802F9EC4(local->unk0, this->position, 500, 1000); + func_802F9F80(local->unk0, 0.0f, 8999999488.0f, 0.0f); + func_802FA060(local->unk0, 22000, 22000, 0.0f); + chRBBSpinningPipeSfxCtrl_setState(this, CH_RBB_SPINNING_PIPE_SFX_CTRL_STATE_1_INIT); + } + else{//L8038FD34 + if(local->marker == NULL) + local->marker = actorArray_findActorFromActorId(*local->actorId)->marker; + sp20 = func_8038A6B8(local->marker); + tmp_f2 = 1.5 * sp20 + 0.5; + func_802F9DB8(local->unk0, tmp_f2, tmp_f2, 0.0f); + tmp_a1 = (s32) (sp20 * 32000.0f); + func_802FA060(local->unk0, tmp_a1, tmp_a1, 0.0f); + } +} diff --git a/src/SM/ch/bottles_movecheck.c b/src/SM/bottles_movecheck.c similarity index 100% rename from src/SM/ch/bottles_movecheck.c rename to src/SM/bottles_movecheck.c diff --git a/src/SM/ch/ambient_fish.c b/src/SM/ch/ambient_fish.c index e3ed73d93..79a113b1c 100644 --- a/src/SM/ch/ambient_fish.c +++ b/src/SM/ch/ambient_fish.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (unknown origin) +// BanjoDecomp: core2/code_C89C0.c #include #include "functions.h" #include "variables.h" diff --git a/src/SM/ch/attacktutorial.c b/src/SM/ch/attacktutorial.c index 4fb42b15f..79911a42c 100644 --- a/src/SM/ch/attacktutorial.c +++ b/src/SM/ch/attacktutorial.c @@ -8,6 +8,10 @@ extern void timed_exitStaticCamera(f32 time); extern void func_8028F918(s32); +// [port] Spare actor bit repurposed: the claw/roll/rap trio was already known when this +// actor spawned (or a local opt-out just unlocked it). +#define movesKnownAtSpawn unk38_0 + enum ch_attack_tutorial_states { CH_ATTACK_TUTORIAL_STATE_1_UNKNOWN = 0x1, // L80387610 CH_ATTACK_TUTORIAL_STATE_2_APPLY_LEARNED_MOVE, // L803873E0 @@ -59,7 +63,7 @@ static s32 __chAttackTutorial_spawnEnemyActor(Actor *this, s32 already_killed_en : ACTOR_164_COLLYWOBBLE_THE_CAULIFLOWER_A; } - __spawnQueue_add_2((void (*)(void))__chAttackTutorial_spawnEnemyActorForMarker, (uintptr_t)this->marker, sp1C); + __spawnQueue_add_2((GenFunction_2)__chAttackTutorial_spawnEnemyActorForMarker, (uintptr_t)this->marker, sp1C); return 0; } @@ -132,6 +136,16 @@ static bool __chAttackTutorial_areLearnableAbilitiesUnlocked() { && ability_isUnlocked(ABILITY_B_RATATAT_RAP); } +// [port] A local tutorial opt-out unlocks every move mid-session; re-arm the spawn latch. +bool func_802E4A08(void); // non-interactive demo/playback modes + +void chAttackTutorial_onTutorialSkipped(void) { + Actor *tutorial = actorArray_findActorFromActorId(ACTOR_167_ATTACK_TUTORIAL); + if (tutorial != NULL) { + tutorial->movesKnownAtSpawn = 1; + } +} + static void __chAttackTutorial_update(Actor *this) { f32 minimum_distance; Actor *bottles; @@ -153,6 +167,9 @@ static void __chAttackTutorial_update(Actor *this) { ? 1 : 0; + // [port] Latch "moves already known" at spawn. + this->movesKnownAtSpawn = __chAttackTutorial_areLearnableAbilitiesUnlocked(); + this->initialized = true; } @@ -160,8 +177,9 @@ static void __chAttackTutorial_update(Actor *this) { case CH_ATTACK_TUTORIAL_STATE_1_UNKNOWN: if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_4)) __chAttackTutorial_setState(this, CH_ATTACK_TUTORIAL_STATE_5_SHOW_LEARN_MOVE_DIALOG); - - if (__chAttackTutorial_areLearnableAbilitiesUnlocked() || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)) + if (this->movesKnownAtSpawn + || (func_802E4A08() && __chAttackTutorial_areLearnableAbilitiesUnlocked()) + || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)) __chAttackTutorial_setState(this, CH_ATTACK_TUTORIAL_STATE_4_TUTORIAL_COMPLETED); break; diff --git a/src/SM/ch/jumptutorial.c b/src/SM/ch/jumptutorial.c index d8cb0862b..fd704405b 100644 --- a/src/SM/ch/jumptutorial.c +++ b/src/SM/ch/jumptutorial.c @@ -57,8 +57,8 @@ void chJumpTutorial_setState(Actor *this, s32 state) { ability_unlock(ABILITY_A_HOLD_A_JUMP_HIGHER); gcdialog_showDialog(ASSET_DF6_DIALOG_BOTTLES_HIGH_JUMP_LEARN, 0xe, this->unk1C, this->marker, __chJumpTutorial_textCallback, NULL); - this->sm_4070.dialog_id = ASSET_E1A_DIALOG_BOTTLES_UNKNOWN; - mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, false); + this->sm_4070.dialog_id = VER_SELECT(ASSET_E1A_DIALOG_BOTTLES_UNKNOWN, 0xA5C, 0, 0); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, FALSE); } break; @@ -113,8 +113,8 @@ void chJumpTutorial_update(Actor *this) { ability_unlock(ABILITY_7_FEATHERY_FLAP); gcdialog_showDialog(ASSET_DF7_DIALOG_BOTTLES_FEATHERY_FLAP_LEARN, 0xa, this->unk1C, this->marker, __chJumpTutorial_textCallback, NULL); - this->sm_4070.dialog_id = ASSET_E1B_DIALOG_BOTTLES_UNKNOWN; - mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, false); + this->sm_4070.dialog_id = VER_SELECT(ASSET_E1B_DIALOG_BOTTLES_UNKNOWN, 0xA5D, 0, 0); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, FALSE); }//L8038A730 if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_9_ABILITY_FEATHERY_UNLOCKED)) { @@ -122,8 +122,8 @@ void chJumpTutorial_update(Actor *this) { ability_unlock(ABILITY_8_FLAP_FLIP); gcdialog_showDialog(ASSET_DF8_DIALOG_BOTTLES_FLAP_FLIP_LEARN, 0xa, this->unk1C, this->marker, __chJumpTutorial_textCallback, NULL); - this->sm_4070.dialog_id = ASSET_E1C_DIALOG_BOTTLES_UNKNOWN; - mapSpecificFlags_set(SM_SPECIFIC_FLAG_9_ABILITY_FEATHERY_UNLOCKED, false); + this->sm_4070.dialog_id = VER_SELECT(ASSET_E1C_DIALOG_BOTTLES_UNKNOWN, 0xA5E, 0, 0); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_9_ABILITY_FEATHERY_UNLOCKED, FALSE); }//L8038A794 if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_A_ABILITY_FLIP_UNLOCKED)) { @@ -149,7 +149,7 @@ void chJumpTutorial_update(Actor *this) { plyr_pos[2] = this->velocity_z; func_8028FAB0(plyr_pos); - if (func_8028EFC8() && face_buttons[FACE_BUTTON(BUTTON_B)] == true && func_8028F20C()) { + if (func_8028EFC8() && face_buttons[FACE_BUTTON(BUTTON_B)] == TRUE && player_isStableWithExtraSteps()) { if (this->sm_4070.dialog_id) { gcdialog_showDialog(dialog_id = this->sm_4070.dialog_id, 0, NULL, NULL, NULL, NULL); } diff --git a/src/SM/ch/smbottles.c b/src/SM/ch/smbottles.c index 301806e00..cfc4e046f 100644 --- a/src/SM/ch/smbottles.c +++ b/src/SM/ch/smbottles.c @@ -3,7 +3,10 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + /* extern functions */ +void chAttackTutorial_onTutorialSkipped(void); Actor *func_802D94B4(ActorMarker *, Gfx **, Mtx **, Vtx **); void func_8028E668(f32 *, f32, f32, f32); void subaddie_turnToYaw(Actor *, f32); @@ -110,6 +113,19 @@ void __chSmBottles_skipIntroTutorial(void) { ability_unlock(ABILITY_5_CLIMB); __chSmBottles_setHasUsedSpiralMountainAbilities(); mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, true); + // [port] Vanilla parity: a local opt-out pops the bonus Collywobble this session. + chAttackTutorial_onTutorialSkipped(); +} + +// [port] Anchor: a remote unlock completed the SM move set mid-session. Apply the same +// completion state the init block derives from abilities at map load. +void chSmBottles_netApplyTutorialComplete(void) { + mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, true); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_2, true); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_C, true); + mapSpecificFlags_set(SM_SPECIFIC_FLAG_F, true); + chAttackTutorial_onTutorialSkipped(); } /** @@ -496,13 +512,27 @@ void chSmBottles_update(Actor *this) { this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); + // [port] Anchor: ability molehills stay inert until the team's tutorial choice + // is made, so nobody can start a tutorial the pending decision would invalidate. + if (this->actorTypeSpecificField != 1 && this->actorTypeSpecificField != 8 && + !EventSystem_Should(VB_SM_MOLEHILL_ACTIVE, true, this)) { + break; + } + if ((this->actorTypeSpecificField == 1 && !mapSpecificFlags_get(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES)) || (this->actorTypeSpecificField == 8 && !mapSpecificFlags_get(SM_SPECIFIC_FLAG_2)) || (this->actorTypeSpecificField == 8 && mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED) && !mapSpecificFlags_get(SM_SPECIFIC_FLAG_F)) ) {//L80389C50 - if (((ml_vec3f_distance(plyr_pos, this->unk1C) < this->actor_specific_1_f) && func_8028F20C()) || + if (((ml_vec3f_distance(plyr_pos, this->unk1C) < this->actor_specific_1_f) && player_isStableWithExtraSteps()) || mapSpecificFlags_get(SM_SPECIFIC_FLAG_10) ) {//L80389C8C + // [port] Anchor: the intro tutorial offer is a team decision. + if (this->actorTypeSpecificField == 1 && + !EventSystem_Should(VB_SM_TUTORIAL_CHOICE_OPEN, true, this)) { + mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); + break; + } + if (subaddie_playerIsWithinSphereAndActive(this, 0x96)) { func_8028F45C(9, this->position); } @@ -512,7 +542,7 @@ void chSmBottles_update(Actor *this) { } } else {//L80389CBC - if (!subaddie_playerIsWithinSphereAndActive(this, 0xfa) || player_movementGroup() || !func_8028F20C() || func_8028EC04()) { + if (!subaddie_playerIsWithinSphereAndActive(this, 250) || player_movementGroup() || !player_isStableWithExtraSteps() || func_8028EC04()) { break; } @@ -614,6 +644,14 @@ void chSmBottles_update(Actor *this) { }//L8038A218 if (bakey_pressed != -1) { + // [port] Anchor: if the tutorial decision belongs to a teammate (or moves + // are already being learned), fold a local opt-out into an opt-in. + if (bakey_pressed == 0 && !EventSystem_Should(VB_SM_TUTORIAL_CHOICE_OPEN, true, this)) { + bakey_pressed = 1; + } + // Record the answer team-wide the moment it lands, so a second pending + // offer folds even before any move is learned. + port_puzzleStep_orBits(ANCHOR_PUZZLE_SM_TUTORIAL, 1); fileProgressFlag_set(FILEPROG_DB_SKIPPED_TUTORIAL, bakey_pressed ? 0 : 1); gcdialog_showDialog(bakey_pressed ? ASSET_E07_DIALOG_BOTTLES_UNKNOWN : ASSET_E09_DIALOG_BOTTLES_SKIPPED_TUTORIAL, 0xe, this->position, this->marker, __chSmBottles_textCallback,__chSmBottles_textActions); diff --git a/src/SM/ch/vegetables.c b/src/SM/ch/vegetables.c index 67dbcda32..7a0f3a919 100644 --- a/src/SM/ch/vegetables.c +++ b/src/SM/ch/vegetables.c @@ -50,7 +50,7 @@ ActorInfo gChVegetablesTopperA = { }; ActorInfo gChVegetablesTopperB = { - MARKER_1E6_TOPPER_THE_CARROT_B, ACTOR_TOPPER_THE_CARROT_B, ASSET_4ED_MODEL_TOPPER, + MARKER_1E6_TOPPER_THE_CARROT_B, ACTOR_36F_TOPPER_THE_CARROT_B, ASSET_4ED_MODEL_TOPPER, 1, sChCarrotAnimations, __chVegetables_update, actor_update_func_80326224, __chVegetables_draw, 2000, 0, 1.0f, 0 }; @@ -70,7 +70,7 @@ ActorInfo gChVegetablesBawlA = { }; ActorInfo gChVegetablesBawlB = { - MARKER_1E7_BAWL_THE_ONION_B, ACTOR_BAWL_THE_ONION_B, ASSET_4EF_MODEL_BAWL, + MARKER_1E7_BAWL_THE_ONION_B, ACTOR_36E_BAWL_THE_ONION_B, ASSET_4EF_MODEL_BAWL, 1, sChOnionAnimations, __chVegetables_update, actor_update_func_80326224, __chVegetables_draw, 0, 0, 1.0f, 0 }; @@ -90,7 +90,7 @@ ActorInfo gChVegetablesCollywobbleA = { }; ActorInfo gChVegetablesCollywobbleB = { - MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, ACTOR_COLLYWOBBLE_B, ASSET_4EE_MODEL_COLLYWOBBLE, + MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, ACTOR_36D_COLLYWOBBLE_B, ASSET_4EE_MODEL_COLLYWOBBLE, 1, sChCauliflowerAnimations, __chVegetables_update, actor_update_func_80326224, __chVegetables_draw, 0, 0, 2.0f, 0 }; @@ -218,10 +218,12 @@ static void __chVegetables_vegetableDeathParticles(Actor* this) { __chVegetables_setSpriteDustParticles(partEmitMgr_newEmitter(8), particles_position, 8); } - if (this->unk38_31) { + // [port] Anchor: skip the drop if a teammate's synced drop already put one here. + if (this->unk38_31 && !actorArray_findHoneycombMarkerById(HONEYCOMB_17_SM_COLLIWOBBLE)) { this->position_y += 100.0f; func_802CA1CC(HONEYCOMB_17_SM_COLLIWOBBLE); __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, BUNDLE_1F_SM_EMPTY_HONEYCOMB, reinterpret_cast(s32, this->position_x), reinterpret_cast(s32, this->position_y), reinterpret_cast(s32, this->position_z)); + CALL_EVENT(OnHoneycombDropSpawn, HONEYCOMB_17_SM_COLLIWOBBLE, BUNDLE_1F_SM_EMPTY_HONEYCOMB, this->position_x, this->position_y, this->position_z); } timed_mapSpecificFlags_setTrue(1.5f, SM_SPECIFIC_FLAG_7); @@ -244,7 +246,7 @@ static Actor* __chVegetables_draw(ActorMarker* marker, Gfx **gdl, Mtx **mptr, Vt if (actor->has_met_before) modelRender_func_8033A470(3, 7); else - func_8033A45C(3, 0); + modelRender_setAppendageVisibility(3, 0); return actor_draw(marker, gdl, mptr, arg3); } diff --git a/src/SM/checksums.c b/src/SM/checksums.c new file mode 100644 index 000000000..52758c905 --- /dev/null +++ b/src/SM/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: SM/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsSM; diff --git a/src/SM/ch/furniture.c b/src/SM/furniture.c similarity index 100% rename from src/SM/ch/furniture.c rename to src/SM/furniture.c diff --git a/src/SM/ch/quarrie.c b/src/SM/quarrie.c similarity index 94% rename from src/SM/ch/quarrie.c rename to src/SM/quarrie.c index d60843118..83d9c4006 100644 --- a/src/SM/ch/quarrie.c +++ b/src/SM/quarrie.c @@ -112,9 +112,12 @@ void SM_func_80386D68(Actor *this){ func_80386B04(partEmitMgr_newEmitter(0xA), this->position, 0xA, this->scale); func_80386C2C(partEmitMgr_newEmitter(0x10), this->position, 0x10, this->scale); - if (this->partnerActor && codeBF0_shouldSpawnQuarrieHoneyComb(this->partnerActor)) { + // [port] Anchor: skip the drop if a teammate's synced drop already put one here. + if (this->partnerActor && codeBF0_shouldSpawnQuarrieHoneyComb(this->partnerActor) && + !actorArray_findHoneycombMarkerById(HONEYCOMB_18_SM_QUARRIES)) { func_802CA1CC(HONEYCOMB_18_SM_QUARRIES); __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, BUNDLE_1F_SM_EMPTY_HONEYCOMB, reinterpret_cast(s32, this->position[0]), reinterpret_cast(s32, this->position[1]), reinterpret_cast(s32, this->position[2])); + CALL_EVENT(OnHoneycombDropSpawn, HONEYCOMB_18_SM_QUARRIES, BUNDLE_1F_SM_EMPTY_HONEYCOMB, this->position[0], this->position[1], this->position[2]); } marker_despawn(this->marker); diff --git a/src/SM/crc.c b/src/SM/smspawnqueue.c similarity index 80% rename from src/SM/crc.c rename to src/SM/smspawnqueue.c index 0bd8884db..45e81f3b1 100644 --- a/src/SM/crc.c +++ b/src/SM/smspawnqueue.c @@ -1,11 +1,12 @@ -// BanjoDecomp: code_F0.c +// BanjoDecomp: SM/smspawnqueue.c #include #include "functions.h" #include "variables.h" #include "prop.h" #include "actor.h" +#include "checksums.h" + -extern s32 D_80275650; extern ActorInfo gQuarrie; @@ -25,27 +26,11 @@ extern ActorInfo gBanjosChair; extern ActorInfo gBanjosStove; extern ActorInfo gRockTrappingGrunty; -extern u32 gCore1CRCs[4]; - -/* .data */ -s32 D_8038AAE0 = 0x000FE2C1; //compiled SM_code_crc_1 -s32 D_8038AAE4 = 0x8C0992D1; //compiled SM_code_crc_2 -union { - u8 byte[4]; - s32 word; -} D_8038AAE8 = {0x00, 0x01, 0xEB, 0x56}; //compiled SM_data_crc_1 (with this disabled out) +s32 D_8038AAE0 = VER_SELECT(0x000FE2C1, 0x00109339, 0, 0); // SM_TEXT_CRC1 +s32 D_8038AAE4 = VER_SELECT(0x8C0992D1, 0xC3A58E96, 0, 0); // SM_TEXT_CRC2 +s32 D_8038AAE8 = VER_SELECT(0x0001EB56, 0x00020B4D, 0, 0); // SM_DATA_CRC1 s32 D_8038AAEC = 0; -/* .bss */ -struct { - s32 unk0; //calculated SM_code_crc1 - s32 unk4; //calculated SM_code_crc2 - s32 unk8; //calculated SM_data_crc1 - s32 unkC; //calculated SM_data_crc2 -} D_8038B320; - -static bool __codeF0_areRomCrcsCorrect(); -static bool __codeF0_areCrcsValid(); /* .code */ static u32 *__codeF0_getLearnedAbilitiesAddress(){ @@ -115,16 +100,14 @@ void __codeF0_pad_func_80386614(u8 *arg0, u8 *arg1, s32 *arg2, s32 *arg3){ *arg3 = temp_v1; } -extern u8 crc_ROM_START[]; - static bool __codeF0_areRomCrcsCorrect(){ #if ANTI_TAMPER u32 sp24; - if( (osPiReadIo((u32)crc_ROM_START + 8, &sp24), sp24 == gCore1CRCs[0]) - && (osPiReadIo((u32)crc_ROM_START + 12, &sp24), sp24 == gCore1CRCs[1]) - && (osPiReadIo((u32)crc_ROM_START + 16, &sp24), sp24 == gCore1CRCs[2]) - && (osPiReadIo((u32)crc_ROM_START + 20, &sp24), sp24 == gCore1CRCs[3]) + if( (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_TEXT_CHECKSUM1, &sp24), sp24 == gChecksumsCore1.text_checksum1) + && (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_TEXT_CHECKSUM2, &sp24), sp24 == gChecksumsCore1.text_checksum2) + && (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_DATA_CHECKSUM1, &sp24), sp24 == gChecksumsCore1.data_checksum1) + && (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_DATA_CHECKSUM2, &sp24), sp24 == gChecksumsCore1.data_checksum2) ){ return true; } @@ -136,10 +119,10 @@ static bool __codeF0_areRomCrcsCorrect(){ static bool __codeF0_areCrcsValid(){ #if ANTI_TAMPER - if( D_8038B320.unk0 == D_8038AAE0 - && D_8038B320.unk4 == D_8038AAE4 - && D_8038B320.unkC == D_80275650 - && D_8038B320.unk8 == D_8038AAE8.word + D_8038AAE8.byte[0] + D_8038AAE8.byte[1] + D_8038AAE8.byte[2] + D_8038AAE8.byte[3] + if( gChecksumsSM.text_checksum1 == D_8038AAE0 + && gChecksumsSM.text_checksum2 == D_8038AAE4 + && gChecksumsSM.data_checksum2 == D_80275650 + && gChecksumsSM.data_checksum1 == D_8038AAE8 + ((u8 *) &D_8038AAE8)[0] + ((u8 *) &D_8038AAE8)[1] + ((u8 *) &D_8038AAE8)[2] + ((u8 *) &D_8038AAE8)[3] ){ return true; } diff --git a/src/SM/version_compat.c b/src/SM/version_compat.c index 7b9d27953..4765cf76a 100644 --- a/src/SM/version_compat.c +++ b/src/SM/version_compat.c @@ -3,65 +3,111 @@ #include "functions.h" #include "variables.h" -#define US_1_0 0 -#define PAL 1 - -u8 D_8038BFC2; - - -#if VERSION == US_1_0 -int func_8038AAB0(void){return 0;} - -#elif VERSION == PAL -#if 0 -void func_8038AAB0(s32 arg0, s32 arg1){ - if(arg1 < 0){ - func_8031A844(); - } - else{ - D_8038BFC2 = arg1; - func_8038B4D0(3); - } - } - - #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038A8F0.s") - void func_8038A8F0(s32 arg0) { - u8 temp_v0; - - switch (arg0) { /* irregular */ - case 1: - D_8038BFC1 = 1; - func_80319400(); - break; - case 2: - D_8038BFC8->unk0 = (s32) D_8038BD38; - D_8038BFC8->unk4 = (s32) D_8038BD3C; - D_8038BFC8->unk10 = (s32) D_8038BD40; - D_8038BFC8->unk20 = (s32) D_8038BD44; - D_8038BFC8->unk30 = (s32) D_8038BD48; - func_8031A5E4(&D_8038BD30, &D_8038BD34, (void *)0x8038BFC8, 0xA, &D_8038B490); - break; - case 3: - temp_v0 = *(u8 *)0x8038BFC2; - if (temp_v0 != 0) { - func_8031B9A4(temp_v0 - 1, 0x80390000); - } - func_802FAF44(0); - D_8038BFC1 = 0; - break; - } - D_8038BFC0 = (s8) arg0; - } - - - #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038A9E4.s") - - #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AA30.s") - - #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AA64.s") - - #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AA74.s") - - #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AAE8.s") -#endif +#if VERSION == VERSION_USA_1_0 + +int func_8038AAB0(void) { + return 0; +} + +#elif VERSION == VERSION_PAL + +struct language_selection_screen_s { + u8 *unk0; + u8 *unk4; + u64 unk8; + + u8 *unk10; + u32 unk14; + u64 unk18; + + u8 *unk20; + u32 unk24; + u64 unk28; + + u8 *unk30; + u32 unk34; + u64 unk38; +}; + +/* data */ +u32 D_8038BD30_pal = 0x0C68696A; +u32 D_8038BD34_pal = 0x02010101; +u8 *D_8038BD38_pal = "WHICH LANGUAGE WOULD"; +u8 *D_8038BD3C_pal = "YOU LIKE TO USE?"; +u8 *D_8038BD40_pal = "ENGLISH"; +u8 *D_8038BD44_pal = "FRANaAIS"; +u8 *D_8038BD48_pal = "DEUTSCH"; + +/* bss */ +u8 D_8038BFC0_pal; +u8 D_8038BFC1_pal; +u8 D_8038BFC2_pal; +struct language_selection_screen_s D_8038BFC8_pal; + +/* text */ +void func_8038B4D0_pal(s32 arg0); + +void func_8038B490_pal(s32 arg0, s32 arg1) { + if (arg1 < 0) { + /*func_8031A844_pal*/gcquiz_func_8031A48C(); + return; + } + D_8038BFC2_pal = arg1; + func_8038B4D0_pal(3); +} + +void func_8038B4D0_pal(s32 arg0) { + switch (arg0) { /* irregular */ + case 1: + D_8038BFC1_pal = 1; + /*func_80319400_pal*/gcquiz_init(); + break; + case 2: + D_8038BFC8_pal.unk0 = D_8038BD38_pal; + D_8038BFC8_pal.unk4 = D_8038BD3C_pal; + D_8038BFC8_pal.unk10 = D_8038BD40_pal; + D_8038BFC8_pal.unk20 = D_8038BD44_pal; + D_8038BFC8_pal.unk30 = D_8038BD48_pal; + /*func_8031A5E4_pal*/__gcquiz_unused(&D_8038BD30_pal, &D_8038BD34_pal, &D_8038BFC8_pal, 0xA, &func_8038B490_pal); + break; + case 3: + if (D_8038BFC2_pal) { + func_8031B5C4(D_8038BFC2_pal - 1); + } + func_802FAD64(ITEM_0_HOURGLASS_TIMER); + D_8038BFC1_pal = 0; + break; + } + D_8038BFC0_pal = (s8) arg0; +} + +void func_8038B5C4_pal(void) { + if (gsworld_getMap() == MAP_91_FILE_SELECT) { + func_8038B4D0_pal(func_8031B638() ? 3 : 1); + } +} + +void func_8038B610_pal(void) { + if (gsworld_getMap() == MAP_91_FILE_SELECT) { + /*func_80319540_pal*/gcquiz_free(); + } +} + +void func_8038B644_pal(s32 arg0, s32 arg1, s32 arg2) { +} + +void func_8038B654_pal(void) { + if ((D_8038BFC1_pal) && (getGameMode() == 3)) { + /*func_8031A25C_pal*/gcquiz_func_80319EA4(); + if (D_8038BFC0_pal == 1) { + timedFunc_set_1(1.0f, func_8038B4D0_pal, 2); + func_8038B4D0_pal(0); + } + } +} + +u8 func_8038B6C8_pal(void) { + return D_8038BFC1_pal; +} + #endif diff --git a/src/TTC/actor_spawninit.c b/src/TTC/actor_spawninit.c index d6b94daf3..ea46aa3ec 100644 --- a/src/TTC/actor_spawninit.c +++ b/src/TTC/actor_spawninit.c @@ -26,7 +26,7 @@ extern ActorInfo gChTreasurehuntRedQuestionMark; extern ActorInfo gChTreasurehuntRedX; extern ActorInfo gChTreasure; -extern void func_802D3D54(Actor *this); +extern void chMMMBreakableWooden_update(Actor *this); static void __code26D0_genericUpdateFunc(Actor *this); static void __code26D0_palmTreeUpdateFunc(Actor *this); @@ -37,14 +37,14 @@ static void __code26D0_sharkfoodIslandUpdateFunc(Actor *this); ActorInfo gBlubberShipTopHatch = { MARKER_A1_BLUBBER_SHIP_TOP_HATCH, ACTOR_10E_BLUBBER_SHIP_TOP_HATCH, ASSET_3D2_MODEL_BLUBBER_SHIP_TOP_HATCH, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; ActorInfo gLighthouseDoor = { MARKER_EA_LIGHTHOUSE_DOOR, ACTOR_13E_LIGHTHOUSE_DOOR, ASSET_3D6_MODEL_LIGHTHOUSE_DOOR, 0x1, NULL, - func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; @@ -77,7 +77,7 @@ ActorInfo gStairs1 = { }; ActorInfo gStairs2 = { - MARKER_269_STAIRS_2, ACTOR_2E1_TTC_STAIRS_2, ASSET_3B7_MODEL_TTC_STAIRS_1, + MARKER_269_STAIRS_2, ACTOR_2E1_TTC_STAIRS_2, ASSET_3B7_MODEL_TTC_STAIRS_2, 0x1, NULL, __code26D0_genericUpdateFunc, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 diff --git a/src/TTC/ch/blubber.c b/src/TTC/ch/blubber.c index 9f6fe29a3..e71349ade 100644 --- a/src/TTC/ch/blubber.c +++ b/src/TTC/ch/blubber.c @@ -3,6 +3,9 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" +#include "port/Enhancements/Retention/Retention.h" + extern void func_8028E668(f32 arg0[3], f32 arg1, f32 arg2, f32 arg3); extern s32 func_802E0970(s32, f32, f32, f32, s32, s32, f32[3]); @@ -63,7 +66,7 @@ static void __chBlubber_showTextCallback(ActorMarker *caller, enum asset_e text_ Actor *this = marker_getActor(caller); ActorLocal_Blubber *local = (ActorLocal_Blubber*)&this->local; - if(text_id == ASSET_A0D_DIALOG_BLUBBER_COMPLETE || text_id == ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED){ + if(text_id == VER_SELECT(ASSET_A0D_DIALOG_BLUBBER_COMPLETE, 0x90D, 0, 0) || text_id == ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED){ local->unk24 = 0; } else{ @@ -89,7 +92,7 @@ static void __chBlubber_showJiggySpawnedText(ActorMarker *marker){ this->actor_specific_1_f = 0.0f; if(!mapSpecificFlags_get(TTC_SPECIFIC_FLAG_2_BLUBBER_JIGGY_SPAWNED_TEXT_SHOWN)) { - text_id = jiggyscore_isCollected(JIGGY_14_TTC_BLUBBER) ? ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED : ASSET_A0D_DIALOG_BLUBBER_COMPLETE; + text_id = jiggyscore_isCollected(JIGGY_14_TTC_BLUBBER) ? ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED : VER_SELECT(ASSET_A0D_DIALOG_BLUBBER_COMPLETE, 0x90D, 0, 0); gcdialog_showDialog(text_id, 0xf, this->position, this->marker, __chBlubber_showTextCallback, __chBlubber_showTextCallback2); mapSpecificFlags_set(TTC_SPECIFIC_FLAG_2_BLUBBER_JIGGY_SPAWNED_TEXT_SHOWN, true); } @@ -121,7 +124,7 @@ static void __func_80387774(Actor **this_ptr){ player_setCarryObjectPoseInCylinder(local->throw_target_position, local->throw_target_radius, 100.0f, ACTOR_2A_GOLD_BULLION, this_ptr); if( subaddie_playerIsWithinSphereAndActive(*this_ptr, 200) - && bacarry_get_markerId() == MARKER_37_GOLD_BULLION + && bacarry_getMarkerId() == MARKER_37_GOLD_BULLION && player_throwCarriedObject() ) { func_8028FA34(!mapSpecificFlags_get(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN) ? ACTOR_149_TTC_BLUBBER_UNKNOWN : ACTOR_14A_TTC_BLUBBER_UNKNOWN, *this_ptr); @@ -140,13 +143,49 @@ static void __func_80387830(Actor *this , f32 arg1, f32 arg2){ static void __chBlubber_updateFunc(Actor *this){ ActorLocal_Blubber *local; + s32 netBits; this->marker->propPtr->unk8_3 = true; func_8028E668(this->position, 90.0f, -10.0f, 110.0f); + + netBits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_BLUBBER); + if (mapSpecificFlags_get(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN)) { + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_BLUBBER, 0x1); + } + if (mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN)) { + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_BLUBBER, 0x3); + } + if (!this->volatile_initialized && (netBits & 0x2) && !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN)) { + marker_despawn(this->marker); + return; + } + if ((netBits & 0x1) && !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN)) { + mapSpecificFlags_set(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN, true); + this->unk138_23 = true; // half-gold dialog belongs to the deliverer + this->has_met_before = true; + } + if (this->initialized && (netBits & 0x2) && !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN)) { + local = (ActorLocal_Blubber *)&this->local; + mapSpecificFlags_set(TTC_SPECIFIC_FLAG_1_UNKNOWN, true); + mapSpecificFlags_set(TTC_SPECIFIC_FLAG_2_BLUBBER_JIGGY_SPAWNED_TEXT_SHOWN, true); + mapSpecificFlags_set(TTC_SPECIFIC_FLAG_3_BLUBBER_SHOW_JIGGY_SPAWNED_TEXT_FLAG, true); + subaddie_set_state(this, CH_BLUBBER_STATE_4_UNKNOWN); + actor_loopAnimation(this); + this->actor_specific_1_f = 0.0f; + local->unk24 = 0; + } + if(!mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN) && !subaddie_playerIsWithinSphereAndActive(this, 2500)) return; if(!this->volatile_initialized){ + // Anchor: rebuild local gold count as collected - delivered (carried gold is transient). + s32 goldBits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_BLUBBER); + s32 delivered = ((goldBits & 0x1) ? 1 : 0) + ((goldBits & 0x2) ? 1 : 0); + s32 pool = port_carriedSync_collectedCount(ANCHOR_COLLECTIBLE_GOLD) - delivered; + if (pool > item_getCount(ITEM_18_GOLD_BULLIONS)) { + item_adjustByDiffWithoutHud(ITEM_18_GOLD_BULLIONS, pool - item_getCount(ITEM_18_GOLD_BULLIONS)); + } if(this->state == CH_BLUBBER_STATE_3_UNKNOWN){ subaddie_set_state_with_direction(this, CH_BLUBBER_STATE_2_UNKNOWN, 0.0f, 1); } @@ -157,8 +196,8 @@ static void __chBlubber_updateFunc(Actor *this){ && !this->has_met_before && item_getCount(ITEM_18_GOLD_BULLIONS) == 0 ){ - gcdialog_showDialog(ASSET_A0B_DIALOG_BLUBBER_FIRST_MEET, 0xe, this->position, this->marker, __chBlubber_showTextCallback, NULL); - this->has_met_before = true; + gcdialog_showDialog(VER_SELECT(ASSET_A0B_DIALOG_BLUBBER_FIRST_MEET, 0x90B, 0, 0), 0xe, this->position, this->marker, __chBlubber_showTextCallback, NULL); + this->has_met_before = TRUE; subaddie_set_state_forward(this, CH_BLUBBER_STATE_3_UNKNOWN); } @@ -166,7 +205,7 @@ static void __chBlubber_updateFunc(Actor *this){ && !this->unk138_23 ){ if (item_getCount(ITEM_18_GOLD_BULLIONS) == 0) { - gcdialog_showDialog(ASSET_A0C_DIALOG_BLUBBER_HALF_GOLD, 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A0C_DIALOG_BLUBBER_HALF_GOLD, 0x90C, 0, 0), 4, NULL, NULL, NULL, NULL); } this->unk138_23 = true; @@ -256,6 +295,6 @@ static void __chBlubber_update2Func(Actor *this){ } static Actor *__chBlubber_drawFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C(4, 0); + modelRender_setAppendageVisibility(4, 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/TTC/ch/clam.c b/src/TTC/ch/clam.c index 30e8cec20..ba46220e0 100644 --- a/src/TTC/ch/clam.c +++ b/src/TTC/ch/clam.c @@ -101,7 +101,7 @@ static bool __chClam_rotateTowardTarget(Actor *this, s32 arg1) { anctrl_setDuration(this->anctrl, 1.0f); - sp2C = (s32) ((f64) (60.0f / (f32) time_getDeltaReal_frames()) * 0.5); + sp2C = (s32) ((f64) ((float)FRAMERATE / (f32) time_getDeltaReal_frames()) * 0.5); if ((this->unk1C[0] != 0.0f) || !__chClam_updateFuncTarget(this, sp2C)) { if (((f64) anctrl_getAnimTimer(this->anctrl) < 0.1) && ((f64) randf() < 0.5)) { if (this->unk1C[0] != 0.0f) { @@ -230,7 +230,7 @@ static void __chClam_takeDamage(ActorMarker *this_marker, ActorMarker *other_mar __chClam_emitLargeShellParticles(this->position, 2); __chClam_emitEyeParticles(this->position, 2); __chClam_emitSmallShellParticles(this->position, 0xC); - func_803115C4(0xa14); + func_803115C4(VER_SELECT(ASSET_A14_DIALOG_CLAM_TAUNT, 0x914, 0, 0)); marker_despawn(this->marker); } @@ -247,8 +247,8 @@ static void __chClam_attackOther(ActorMarker *this_marker, ActorMarker *other_ma if(baiFrame_getState() == 3) return; - if( !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN) && gcdialog_showDialog(ASSET_A14_DIALOG_CLAM_TAUNT, 0, NULL, NULL, NULL, NULL)){ - mapSpecificFlags_set(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN, true); + if( !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN) && gcdialog_showDialog(VER_SELECT(ASSET_A14_DIALOG_CLAM_TAUNT, 0x914, 0, 0), 0, NULL, NULL, NULL, NULL)){ + mapSpecificFlags_set(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN, TRUE); } // [port] Match JP: only drop while fewer than 8 eggs / 5 red feathers are on the diff --git a/src/TTC/ch/leaky.c b/src/TTC/ch/leaky.c index 567414556..20002471d 100644 --- a/src/TTC/ch/leaky.c +++ b/src/TTC/ch/leaky.c @@ -57,11 +57,21 @@ static void __chLeaky_updateFunc(Actor *this) { } } - if( this->state == 1 + // Anchor: teammate finished feeding Leaky (LEVEL_FLAG_2) - lower water here too. + if (this->state == 1 && this->unk38_31 < 2 && levelSpecificFlags_get(LEVEL_FLAG_2_TTC_UNKNOWN)) { + Struct70s *water = func_8034C5AC(300); + if (water != NULL) { + func_8034E7B8(&water->type_73, -600, 4.0f, 2, 10.0f); + } + timedFunc_set_0(1.0f, __func_80388F88); + subaddie_set_state(this, 2); + } + + if( this->state == 1 && !this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 250) && !subaddie_playerIsWithinSphereAndActive(this, 160) - && !player_movementGroup() - && gcdialog_showDialog(ASSET_A1A_DIALOG_LEAKY_FIRST_MEET, 0, NULL, NULL, NULL, NULL) + && !player_movementGroup() + && gcdialog_showDialog(VER_SELECT(ASSET_A1A_DIALOG_LEAKY_FIRST_MEET, 0x91A, 0, 0), 0, NULL, NULL, NULL, NULL) ){ this->has_met_before = true; } @@ -117,8 +127,8 @@ bool chLeaky_eggCollision(ActorMarker *marker){ return true; } - levelSpecificFlags_set(2, true); - levelSpecificFlags_set(5, true); - gcdialog_showDialog(ASSET_A28_DIALOG_LEAKY_DONE, 0x2a, this->position, this->marker, __chLeaky_showDoneText, NULL); - return true; + levelSpecificFlags_set(2, TRUE); + levelSpecificFlags_set(5, TRUE); + gcdialog_showDialog(VER_SELECT(ASSET_A28_DIALOG_LEAKY_DONE, 0x928, 0, 0), 0x2a, this->position, this->marker, __chLeaky_showDoneText, NULL); + return TRUE; } diff --git a/src/TTC/ch/lockup.c b/src/TTC/ch/lockup.c index 6ead9bebb..ab8f0467b 100644 --- a/src/TTC/ch/lockup.c +++ b/src/TTC/ch/lockup.c @@ -57,8 +57,8 @@ static s32 sLockup_CloseVelocity[3] = {0,0,0}; /* .code */ static Actor *__chLockup_drawFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor * actor = marker_getActor(marker); - func_8033A45C(3, actor->unk38_31); - func_8033A45C(4, actor->unk38_31); + modelRender_setAppendageVisibility(3, actor->unk38_31); + modelRender_setAppendageVisibility(4, actor->unk38_31); return actor_draw(marker, gfx, mtx, vtx); } @@ -87,9 +87,9 @@ static void __chLockup_updateFunc(Actor *this){ && subaddie_playerIsWithinSphereAndActive(this, 320) && !subaddie_playerIsWithinSphereAndActive(this, 160) && !player_movementGroup() - && gcdialog_showDialog(ASSET_A15_DIALOG_LOCKUP_SPAWNED, 0, NULL, NULL, NULL, NULL) - ){ - this->has_met_before = true; + && gcdialog_showDialog(VER_SELECT(ASSET_A15_DIALOG_LOCKUP_SPAWNED, 0x915, 0, 0), 0, NULL, NULL, NULL, NULL)) { + + this->has_met_before = TRUE; } if(!this->volatile_initialized){ diff --git a/src/TTC/ch/lockup.h b/src/TTC/ch/lockup.h new file mode 100644 index 000000000..dc17d5d73 --- /dev/null +++ b/src/TTC/ch/lockup.h @@ -0,0 +1,23 @@ +// BanjoDecomp: TTC/ch/lockup.h +#define LOCKUP_WITH_JIGGY_ID 0xA + +#define LOCKUP_CYCLE_TICKS_SLOW 0x1E +#define LOCKUP_CYCLE_TICKS_MEDIUM 0x14 +#define LOCKUP_CYCLE_TICKS_FAST 0xA +#define LOCKUP_CYCLE_TICKS_DEFAULT 10000 + +typedef struct { + s32 closedTicksCounter; + s32 openTicksCounter; +} ActorLocal_Lockup; + +static Actor *chLockup_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx); +static void chLockup_update(Actor *this); + +enum ch_lockup_states_e { + CH_LOCKUP_STATE_CLOSED = 1, + CH_LOCKUP_STATE_OPENING = 2, + CH_LOCKUP_STATE_OPEN = 3, + CH_LOCKUP_STATE_CLOSING = 4, + CH_LOCKUP_STATE_CLOSING2 = 5 +}; diff --git a/src/TTC/ch/nipper.c b/src/TTC/ch/nipper.c index a214258db..c9f0a2da3 100644 --- a/src/TTC/ch/nipper.c +++ b/src/TTC/ch/nipper.c @@ -3,6 +3,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + static void __chNipper_updateFunc(Actor *this); static Actor *__chNipper_animFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); @@ -16,6 +18,24 @@ enum ch_nipper_states_e { CH_NIPPER_STATE_7_UNKNOWN // already dead? L80388A20 }; +static s32 __chNipper_sharedHits(void) { + s32 bits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_NIPPER) & 0x7; + return (bits & 1) + ((bits >> 1) & 1) + ((bits >> 2) & 1); +} + +static s32 __chNipper_localHits(Actor *this) { + if (this->state == CH_NIPPER_STATE_6_DEAD || this->state == CH_NIPPER_STATE_7_UNKNOWN) { + return 3; + } + if (this->lifetime_value == 80.0f) { + return 1; + } + if (this->lifetime_value == 40.0f) { + return 2; + } + return 0; +} + /* .data */ ActorAnimationInfo gChNipperAnimations[8] = { {0, 0.0}, @@ -69,7 +89,7 @@ static Actor *__chNipper_animFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx Actor *this; this = marker_getActor(marker); - func_8033A45C(3, (this->state == 7)? 0 : 1); + modelRender_setAppendageVisibility(3, (this->state == 7)? 0 : 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -137,6 +157,7 @@ static void __chNipper_dieFunc(ActorMarker *this_marker, ActorMarker *other_mark func_8032B4DC(this, other_marker, 7); if (this->lifetime_value == 40.0f) { + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_NIPPER, 0x7); subaddie_set_state_with_direction(this, CH_NIPPER_STATE_6_DEAD, 0.01f, 1); actor_playAnimationOnce(this); for(i = 0; i < 3; i++){ @@ -148,16 +169,18 @@ static void __chNipper_dieFunc(ActorMarker *this_marker, ActorMarker *other_mark gcStaticCamera_activate(0x1C); return; } - + if (this->lifetime_value == 80.0f) { + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_NIPPER, 0x3); __chNipper_playDeathAnimation(this); this->lifetime_value = 40.0f; return; } + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_NIPPER, 0x1); __chNipper_playDeathAnimation(this); this->lifetime_value = 80.0f; - gcdialog_showDialog(ASSET_A10_DIALOG_NIPPER_HURT, 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A10_DIALOG_NIPPER_HURT, 0x910, 0, 0), 4, NULL, NULL, NULL, NULL); return; } @@ -178,7 +201,7 @@ static void __chNipper_ow2Func(ActorMarker * this_marker, ActorMarker *other_mar this = marker_getActor(this_marker); if( !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN) && this->has_met_before - && gcdialog_showDialog(ASSET_A0F_DIALOG_NIPPER_HIT_BY_EGG, 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(VER_SELECT(ASSET_A0F_DIALOG_NIPPER_HIT_BY_EGG, 0x90F, 0, 0), 0, NULL, NULL, NULL, NULL) ){ mapSpecificFlags_set(TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN, true); } @@ -189,7 +212,7 @@ static void __chNipper_owFunc(ActorMarker * this_marker, ActorMarker *other_mark Actor *this = marker_getActor(this_marker); if( !this->unk138_23 && this->has_met_before - && gcdialog_showDialog(ASSET_A11_DIALOG_NIPPER_ATTACK, 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(VER_SELECT(ASSET_A11_DIALOG_NIPPER_ATTACK, 0x911, 0, 0), 0, NULL, NULL, NULL, NULL) ){ this->unk138_23 = true; } @@ -201,6 +224,7 @@ static void __chNipper_updateFunc(Actor *this){ s32 xVelocity; f32 playerPosition[3]; enum bsgroup_e player_movement_group; + s32 sharedHits; player_getPosition(playerPosition); xVelocity = func_80309D58(playerPosition, 1); @@ -225,6 +249,24 @@ static void __chNipper_updateFunc(Actor *this){ this->velocity_x = xVelocity; } + if (this->initialized && this->state != CH_NIPPER_STATE_4_DIEING && this->state != CH_NIPPER_STATE_6_DEAD && + this->state != CH_NIPPER_STATE_7_UNKNOWN) { + sharedHits = __chNipper_sharedHits(); + if (__chNipper_localHits(this) < sharedHits) { + if (sharedHits >= 3) { + this->lifetime_value = 40.0f; + subaddie_set_state_with_direction(this, CH_NIPPER_STATE_6_DEAD, 0.01f, 1); + actor_playAnimationOnce(this); + sfx_playFadeShorthandDefault(SFX_78_EAGLECRY, 0.7f, 20000, this->position, 1500, 3000); + comusic_8025AB44(COMUSIC_12_TTC_NIPPER, 0, 300); + func_8025AABC(COMUSIC_12_TTC_NIPPER); + func_8032BB88(this, -1, 300); + } else { + this->lifetime_value = (sharedHits == 1) ? 80.0f : 40.0f; + } + } + } + switch(this->state){ case CH_NIPPER_STATE_1_UNKNOWN: if(!this->initialized){ @@ -244,8 +286,8 @@ static void __chNipper_updateFunc(Actor *this){ && player_movement_group != BSGROUP_A_FLYING ){ subaddie_set_state_with_direction(this, CH_NIPPER_STATE_5_SPAWNED, 0.01f, 1); - if(gcdialog_showDialog(ASSET_A0E_DIALOG_NIPPER_SPAWNED, 0xf, this->position, this->marker, __chNipper_spawnedShowTextCallback, NULL)){ - this->has_met_before = true; + if(gcdialog_showDialog(VER_SELECT(ASSET_A0E_DIALOG_NIPPER_SPAWNED, 0x90E, 0, 0), 0xf, this->position, this->marker, __chNipper_spawnedShowTextCallback, NULL)){ + this->has_met_before = TRUE; } comusic_8025AB44(COMUSIC_12_TTC_NIPPER, 5000, 300); ncStaticCamera_setToNode(11); diff --git a/src/TTC/ch/treasure.c b/src/TTC/ch/treasure.c index 018059318..3ae54cf0d 100644 --- a/src/TTC/ch/treasure.c +++ b/src/TTC/ch/treasure.c @@ -25,7 +25,7 @@ static void __chTreasure_die(ActorMarker *marker, ActorMarker *otherMarker){ Actor *this = marker_getActor(marker); __spawnQueue_add_4((GenFunction_4) spawnQueue_actor_f32, 0x4C, reinterpret_cast(s32, this->position[0]), reinterpret_cast(s32, this->position[1]), reinterpret_cast(s32, this->position[2])); func_802EE278(this, 3, 0xf, 0x3C, 0.2f, 1.2f); - func_803115C4(0xA19); + func_803115C4(VER_SELECT(0xA19, 0x919, 0, 0)); jiggy_spawn(JIGGY_11_TTC_RED_X, this->position); marker_despawn(marker); } diff --git a/src/TTC/ch/treasurehunt.c b/src/TTC/ch/treasurehunt.c index d7379f5d3..ca861780c 100644 --- a/src/TTC/ch/treasurehunt.c +++ b/src/TTC/ch/treasurehunt.c @@ -3,6 +3,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + extern f32 mapModel_getFloorY(f32[3]); // func_8028F45C declared in port_prototypes.h (returns bool) @@ -13,7 +15,7 @@ typedef struct { static void __chTreasurehunt_updateFunc(Actor *this); static Actor *__chTreasurehunt_animFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -extern u32 CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; +extern u32 chtreasureHunt_puzzleCurrentStep; /* .data */ static f32 sChTreasurehunt_stepPositions[6][3] = { @@ -80,7 +82,7 @@ static bool __chTreasurehunt_isActiveHitboxBeakBusterHitbox(void) { if (player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER) { comusic_id = COMUSIC_2B_DING_B; music_volume = 28000; - if (CH_TREASUREHUNT_PUZZLE_CURRENT_STEP == 5) { + if (chtreasureHunt_puzzleCurrentStep == 5) { comusic_id = COMUSIC_2D_PUZZLE_SOLVED_FANFARE; music_volume = 0x7FFF; } @@ -94,10 +96,10 @@ static void __chTreasurehunt_spawnRedXForNextStep(void) { Actor *actor; ActorLocal_TreasureHunt *local; - actor = actor_spawnWithYaw_f32(ACTOR_55_RED_X, sChTreasurehunt_stepPositions[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP], 0); + actor = actor_spawnWithYaw_f32(ACTOR_55_RED_X, sChTreasurehunt_stepPositions[chtreasureHunt_puzzleCurrentStep], 0); local = (ActorLocal_TreasureHunt *)&actor->local; - actor->yaw = sChTreasurehunt_StepRedXYaws[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP]; - local->unk0 = CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; + actor->yaw = sChTreasurehunt_StepRedXYaws[chtreasureHunt_puzzleCurrentStep]; + local->unk0 = chtreasureHunt_puzzleCurrentStep; actor->lifetime_value = 0.0f; actor->state = 0; } @@ -106,24 +108,25 @@ static void __chTreasurehunt_spawnActorForNextStep(void) { Actor *actor; ActorLocal_TreasureHunt *local; - actor = actor_spawnWithYaw_f32((sChTreasurehunt_StepActors - 1)[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP], sChTreasurehunt_stepPositions[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP - 1], 0); + actor = actor_spawnWithYaw_f32((sChTreasurehunt_StepActors - 1)[chtreasureHunt_puzzleCurrentStep], sChTreasurehunt_stepPositions[chtreasureHunt_puzzleCurrentStep - 1], 0); local = (ActorLocal_TreasureHunt *)&actor->local; - actor->yaw = sChTreasurehunt_StepYaws[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP - 1]; - local->unk0 = CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; + actor->yaw = sChTreasurehunt_StepYaws[chtreasureHunt_puzzleCurrentStep - 1]; + local->unk0 = chtreasureHunt_puzzleCurrentStep; actor->lifetime_value = 0.0f; actor->state = 0; } static void __chTreasurehunt_checkStepProgress(s32 currentStep){ - if(CH_TREASUREHUNT_PUZZLE_CURRENT_STEP == currentStep && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ + if(chtreasureHunt_puzzleCurrentStep == currentStep && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ if(currentStep == 0 && !jiggyscore_isCollected(JIGGY_11_TTC_RED_X)){ - gcdialog_showDialog(ASSET_A18_DIALOG_TREASUREHUNT_FOLLOW_CLUES, 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A18_DIALOG_TREASUREHUNT_FOLLOW_CLUES, 0x918, 0, 0), 4, NULL, NULL, NULL, NULL); } else if(currentStep == 4){ - gcdialog_showDialog(ASSET_A19_DIALOG_TREASUREHUNT_SECOND_STEP, 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_A19_DIALOG_TREASUREHUNT_SECOND_STEP, 0x919, 0, 0), 4, NULL, NULL, NULL, NULL); } - CH_TREASUREHUNT_PUZZLE_CURRENT_STEP++; + chtreasureHunt_puzzleCurrentStep++; + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_XHUNT, (1 << chtreasureHunt_puzzleCurrentStep) - 1); __spawnQueue_add_0(__chTreasurehunt_spawnActorForNextStep); __spawnQueue_add_0(__chTreasurehunt_spawnRedXForNextStep); } @@ -153,7 +156,7 @@ void chTreasurehunt_checkStepProgress5(NodeProp *this, ActorMarker *arg1){ static ParticleEmitter *particleEmitter; static f32 particleTargetPosition[3]; - if(CH_TREASUREHUNT_PUZZLE_CURRENT_STEP == 5 && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ + if(chtreasureHunt_puzzleCurrentStep == 5 && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ particleTargetPosition[0] = (f32)this->x; particleTargetPosition[1] = (f32)this->y; particleTargetPosition[2] = (f32)this->z; @@ -171,13 +174,48 @@ void chTreasurehunt_checkStepProgress5(NodeProp *this, ActorMarker *arg1){ gcpausemenu_80314AC8(0); timedFunc_set_2(0.1f, (GenFunction_2) func_8028F45C, 9, (uintptr_t)&particleTargetPosition); timedFunc_set_1(0.1f, (GenFunction_1) gcpausemenu_80314AC8, 1); - gcdialog_showDialog(ASSET_A17_DIALOG_BURIED_TREASURE_SPAWNED, 4, NULL, NULL, NULL, NULL); - CH_TREASUREHUNT_PUZZLE_CURRENT_STEP++; + gcdialog_showDialog(VER_SELECT(ASSET_A17_DIALOG_BURIED_TREASURE_SPAWNED, 0x917, 0, 0), 4, NULL, NULL, NULL, NULL); + chtreasureHunt_puzzleCurrentStep++; + port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_XHUNT, 0x3F); } } void chTreasurehunt_resetProgress(void){ - CH_TREASUREHUNT_PUZZLE_CURRENT_STEP = 0; + chtreasureHunt_puzzleCurrentStep = 0; +} + +// Anchor: replay teammates' hunt steps, one per frame; called each frame in TTC (PuzzleStep.cpp). +void chTreasurehunt_netTick(void){ + static f32 sNetTreasurePosition[3]; + s32 bits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_XHUNT) & 0x3F; + s32 sharedStep = 0; + + while(bits & 1){ + sharedStep++; + bits >>= 1; + } + if((s32)chtreasureHunt_puzzleCurrentStep >= sharedStep){ + return; + } + + if(chtreasureHunt_puzzleCurrentStep < 5){ + chtreasureHunt_puzzleCurrentStep++; + __spawnQueue_add_0(__chTreasurehunt_spawnActorForNextStep); + __spawnQueue_add_0(__chTreasurehunt_spawnRedXForNextStep); + } + else{ + chtreasureHunt_puzzleCurrentStep++; + if(!jiggyscore_isSpawned(JIGGY_11_TTC_RED_X) && !jiggyscore_isCollected(JIGGY_11_TTC_RED_X)){ + sNetTreasurePosition[0] = sChTreasurehunt_stepPositions[5][0]; + sNetTreasurePosition[1] = sChTreasurehunt_stepPositions[5][1]; + sNetTreasurePosition[2] = sChTreasurehunt_stepPositions[5][2]; + sNetTreasurePosition[1] = mapModel_getFloorY(sNetTreasurePosition); + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_F4_BURIED_TREASURE, + reinterpret_cast(s32, sNetTreasurePosition[0]), + reinterpret_cast(s32, sNetTreasurePosition[1]), + reinterpret_cast(s32, sNetTreasurePosition[2])); + } + } } static void __chTreasurehunt_updateFunc(Actor *this){ @@ -199,7 +237,7 @@ static void __chTreasurehunt_updateFunc(Actor *this){ } break; case 1: - if(local->unk0 < CH_TREASUREHUNT_PUZZLE_CURRENT_STEP){ + if(local->unk0 < chtreasureHunt_puzzleCurrentStep){ this->state = 2; } break; diff --git a/src/TTC/checksums.c b/src/TTC/checksums.c new file mode 100644 index 000000000..d920d19ab --- /dev/null +++ b/src/TTC/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: TTC/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsTTC; diff --git a/src/TTC/crc.c b/src/TTC/crc.c index 9ee04e8bb..74fbbf619 100644 --- a/src/TTC/crc.c +++ b/src/TTC/crc.c @@ -2,24 +2,11 @@ #include #include "functions.h" #include "variables.h" +#include "checksums.h" -extern s32 D_80276CB0; - -/* .data */ -// code crc0 -s32 D_8038C750 = 0x0016D2FD; -// code crc1 -s32 D_8038C754 = 0xFB70B01D; -// data crc -s32 D_8038C758 = 0x0004EFAC; - -/* .bss */ -struct { - u8 pad0[4]; - s32 unk4; - u8 pad8[4]; - s32 unkC; -} sD_8038D6F0; +s32 D_8038C750 = VER_SELECT(0x0016D2FD, 0x0016D2D7, 0, 0); // TTC_TEXT_CRC1 +s32 D_8038C754 = VER_SELECT(0xFB70B01D, 0xFCA4DD1E, 0, 0); // TTC_TEXT_CRC2 +s32 D_8038C758 = VER_SELECT(0x0004EFAC, 0x0004FD17, 0, 0); // TTC_DATA_CRC1 /* .code */ void __code3040_makeBanjoAlwaysSlippery(){ @@ -31,7 +18,7 @@ void __code3040_makeBanjoAlwaysSlippery(){ void code3040_checkTTCChecksums(void){ // [port] This crc check makes the ground in TTC slippery #if ANTI_TAMPER - if(sD_8038D6F0.unk4 != D_8038C754 || sD_8038D6F0.unkC != D_80276CB0){ + if(gChecksumsTTC.text_checksum2 != D_8038C754 || gChecksumsTTC.data_checksum2 != D_80276CB0){ __code3040_makeBanjoAlwaysSlippery(); } #endif diff --git a/src/TTC/castle.c b/src/TTC/ma/castle.c similarity index 98% rename from src/TTC/castle.c rename to src/TTC/ma/castle.c index 13902c4df..11e5c35cb 100644 --- a/src/TTC/castle.c +++ b/src/TTC/ma/castle.c @@ -170,12 +170,12 @@ static void __maCastle_setupCheatCodeTimer(s32 new_timer_state) if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { // set timer to 50 seconds - item_set(ITEM_0_HOURGLASS_TIMER, 2999); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(2999, 2499, 0, 0)); } else { // set timer to 100 seconds - item_set(ITEM_0_HOURGLASS_TIMER, 5999); + item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(5999, 4999, 0, 0)); } item_set(ITEM_6_HOURGLASS, true); @@ -332,11 +332,11 @@ static u32 __maCastle_cheatoCodeUnlocked(s32 cheato_code_index) static void __maCastle_setVolatileFlags(u32 arg0) { int i; - volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_C2_NOBONUS_TEXT); + progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_C2_NOBONUS_TEXT); // wish washy banjo cheat code if (arg0 & 0x400) { - volatileFlag_setAndTriggerDialog_E(VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT); + progressDialog_setAndTriggerDialog_E(VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT); } volatileFlag_set(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS, 0); for (i = 4; i < 11; i++) @@ -623,7 +623,7 @@ void maCastle_update(void) } if ((sMapState.banjoKazooieCodeEnteredState == 0) || (sMapState.banjoKazooieCodeEnteredState == 3)) { - if ((levelSpecificFlags_get(LEVEL_FLAG_2_TTC_UNKNOWN) || volatileFlag_get(VOLATILE_FLAG_3)) && (player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER) && func_8028F20C()) + if ((levelSpecificFlags_get(LEVEL_FLAG_2_TTC_UNKNOWN) || volatileFlag_get(VOLATILE_FLAG_3)) && (player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER) && player_isStableWithExtraSteps()) { mesh_id_closest_to_player = model_func_8033F3C0(sMapState.model1, player_position); if (mesh_id_closest_to_player != 0) @@ -1038,7 +1038,7 @@ static void __maCastle_eraseGameplayDialogCallback(ActorMarker *caller, enum ass { __maCastle_setNumberOfBannedCheatcodesEntered(3); __maCastle_checkSecretCheatCodeIndex(sThirdForbiddenSecretCheatCodeIndex); - gcdialog_showDialog(ASSET_FBF_DIALOG_ERASED_SAVE, 0xC, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_FBF_DIALOG_ERASED_SAVE, 0xB25, 0, 0), 0xC, NULL, NULL, NULL, NULL); gameFile_clear(gameSelect_getGameNumber()); gameFile_8033CFD4(gameSelect_getGameNumber()); gameSelect_setGameNumber(-1); @@ -1073,11 +1073,11 @@ static void __maCastle_checkIfBannedCheatCodeEntered(s32 secret_cheat_code_index __maCastle_setNumberOfBannedCheatcodesEntered(2); __maCastle_checkSecretCheatCodeIndex(secret_cheat_code_index); __maCastle_resetSecretCheatCodeProgress(); - gcdialog_showDialog(ASSET_FBE_DIALOG_CHEATING_ERASE_SAVE_WARNING, 0xC, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_FBE_DIALOG_CHEATING_ERASE_SAVE_WARNING, 0xB24, 0, 0), 0xC, NULL, NULL, NULL, NULL); return; case 2: sThirdForbiddenSecretCheatCodeIndex = secret_cheat_code_index; - gcdialog_showDialog(ASSET_E38_DIALOG_CHEATING_ERASE_SAVE_CONFIRMATION, 0xC, NULL, NULL, __maCastle_eraseGameplayDialogCallback, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_E38_DIALOG_CHEATING_ERASE_SAVE_CONFIRMATION, 0xA7A, 0, 0), 0xC, NULL, NULL, __maCastle_eraseGameplayDialogCallback, NULL); return; } return; diff --git a/src/boot/bk_boot_1050.c b/src/boot/bk_boot_1050.c index 837606bb7..d2e5b21af 100644 --- a/src/boot/bk_boot_1050.c +++ b/src/boot/bk_boot_1050.c @@ -2,6 +2,7 @@ #include "boot/overlaytable.h" #include "boot/rarezip.h" #include "core1/main.h" +#include "checksums.h" #define ENTRY_STACK_LEN 0x2000 @@ -9,7 +10,6 @@ u8 gEntryStack[ENTRY_STACK_LEN]; extern u8 gHeapBase[]; extern u8 core1_VRAM[]; -extern u32 gCore1CRCs[4]; /// @brief Entry point of the game /// @param arg0 unused/unknown parameter @@ -34,12 +34,12 @@ void func_80000450(s32 arg0) { rarezip_init(); rarezip_uncompress_file_and_update_pointers(&in, &out); - gCore1CRCs[0] = inflate_crc1; - gCore1CRCs[1] = inflate_crc2; + gChecksumsCore1.text_checksum1 = inflate_crc1; + gChecksumsCore1.text_checksum2 = inflate_crc2; rarezip_uncompress_file_and_update_pointers(&in, &out); - gCore1CRCs[2] = inflate_crc1; - gCore1CRCs[3] = inflate_crc2; + gChecksumsCore1.data_checksum1 = inflate_crc1; + gChecksumsCore1.data_checksum2 = inflate_crc2; overlaytable_init(); diff --git a/src/core1/audio_instruments.c b/src/core1/audio_instruments.c index e30440c74..b7830b253 100644 --- a/src/core1/audio_instruments.c +++ b/src/core1/audio_instruments.c @@ -3,6 +3,7 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "port/ShipUtils.h" // gPortResetPending #include "music.h" #include @@ -16,11 +17,6 @@ extern void func_8025F570(ALCSPlayer *, u8); extern void func_8025F510(ALCSPlayer *, u8, u8); extern void func_8025F5C0(ALCSPlayer *, u8); -extern OSIoMesg *func_802405D0(void); -extern OSMesgQueue *func_802405C4(void); -extern ALHeap *func_802405B8(void); -extern void func_8023FA64(ALSeqpConfig *arg0); - extern u8 *soundfont2ctl_ROM_START; extern u8 *soundfont2ctl_ROM_END; extern u8 *soundfont2tbl_ROM_START; @@ -257,11 +253,11 @@ void musicInstruments_init(void){ D_802820E8.maxVoices = 0x18; D_802820E8.maxEvents = 0x55; D_802820E8.maxChannels = 0x10; - D_802820E8.heap = func_802405B8(); + D_802820E8.heap = audioManager_getALHeapInfo(); D_802820E8.initOsc = NULL; D_802820E8.updateOsc = NULL; D_802820E8.stopOsc = NULL; - func_8023FA64(&D_802820E8); + audioManager_setupSeqp(&D_802820E8); for(i = 0; i < 6; i++){ n_alCSPNew((N_ALCSPlayer *)&D_80281720[i].cseqp, &D_802820E8); } @@ -515,14 +511,14 @@ s32 gcMusic_getDefaultVolumeForTrack(s32 track_id){ return 0; } -void func_80250048(s32 track_id, u16 arg1){ +void gcMusic_setDefaultVolumeForTrack(s32 track_id, u16 arg1){ if (track_id >= 0 && track_id < 0xB0) { D_80275D40[track_id].volume = arg1; } } //song_getName -char *func_80250060(s32 track_id){ +char *gcMusic_getNameForTrack(s32 track_id){ if (track_id >= 0 && track_id < 0xB0) { return D_80275D40[track_id].name; } diff --git a/src/core1/audio_manager.c b/src/core1/audio_manager.c index 711a203b1..091412825 100644 --- a/src/core1/audio_manager.c +++ b/src/core1/audio_manager.c @@ -7,8 +7,13 @@ //#include "PR/sched.h" #include "n_audio/PR/n_libaudio.h" //#include "PR/os_system.h" +#include "port/DevTools/ThreadWatchdog.h" +#include "port/OS/OS.h" +#include "port/Patches/Patches.h" #include "port/ShipUtils.h" +#define DMA_BLOCK_SIZE VER_SELECT(0x200, 0x270, 0x200, 0x200) + // [port] BK audio - SDK calls stubbed, functions preserved for game code // [port] 64-bit structs with pointers are larger — double the heap @@ -17,70 +22,58 @@ #else #define AUDIO_HEAP_SIZE VER_SELECT(0x21000, 0x23A00, 0x21000, 0x21000) #endif -#define AUDIOMANAGER_THREAD_STACK_SIZE 0xE78 - -extern void n_alInit(N_ALGlobals *, ALSynConfig *); - +#define AUDIOMANAGER_THREAD_STACK_SIZE 3704 +#define NUM_SAMPLES 184 // n_audio has fixed sample count of 184 +#define NUM_OSC_STATES 48 +#define NUM_AUDIO_CMDS_PER_SECOND 150000 + +struct audio_info_mesg_data_s { + s16 unk0; + struct audio_info_s *audio_info_ptr; +}; -typedef struct AudioInfo_s { - short *data; /* Output data pointer */ - short frameSamples; /* # of samples synthesized in this frame */ - u8 pad4[2]; - s16 unk8; - u8 padA[2]; - struct AudioInfo_s *unkC; +typedef struct audio_info_s { + s16 *data; /* Output data pointer */ + s16 frame_samples; /* number of samples synthesized in this frame */ + struct audio_info_mesg_data_s reply_mesg_data; } AudioInfo; -typedef struct Struct_1D00_1_s{ - void *unk0; - u8 pad4[4]; - s16 unk8; - u8 pada[2]; - struct Struct_1D00_1_s *unkC; -} Struct_1D00_1; - -typedef struct { - u8 pad0[4]; - AudioInfo *unk4; -} Struct_1D00_2; - -typedef struct Struct_1D00_3_s{ - ALLink unk0; - uintptr_t unk8; +struct dma_state_data_s { + ALLink link; + uintptr_t unk8; // device address uintptr_t unkC; - uintptr_t unk10; -} Struct_1D00_3; + uintptr_t heap; +}; typedef struct{ u8 pad0[0x18]; }Struct_core1_1D00_4; -typedef struct struct_core1_1D00_5_s{ - struct struct_core1_1D00_5_s * next; +typedef struct osc_state_s { + struct osc_state_s *next; u8 type; - // u8 pad5[1]; - u16 unk6; - u16 unk8; - union{ - struct{u8 unk0; u8 unk1;}type1; - struct{f32 unk0;}type80; - }unkC; -}OscState; + u16 unk6; // current value + u16 unk8; // max value + union { + struct { u8 unk0; u8 unk1; } type1; + struct { f32 cents; } type80; + } unkC; +} OscState; void audioManager_create(void); void audioManagerThread_entry(void *arg); -// void func_802403B8(void); void audioManager_handleDoneMsg(AudioInfo *info); -void *func_802403B8(void *state); -void func_802403F0(void); +ALDMAproc audioManager_DMAInitProc(void *state); +void audioManager_func_802403F0(void); void audioManager_startThread(void); bool audioManager_handleFrameMsg(AudioInfo *info, AudioInfo *prev_info); s32 D_80275770 = 0; -s32 D_80275774 = 0; +bool sAudioManagerThreadStarted = false; u8 D_80275778 = 0; -s32 D_8027577C[] = { + +s32 sEffectsChain[] = { 6, /* number of sections in this effect */ 0x1900, /* total allocated memory */ /* SECTION 1 */ @@ -139,57 +132,47 @@ s32 D_8027577C[] = { 0x4500 /* low-pass filter */ }; -Struct_1D00_2 *D_80275844 = NULL; -AudioInfo *D_80275848 = NULL; -// extern int D_8027584C;//static int D_8027584C = 0; - -extern s32 osViClock; //0x80277128 +struct audio_info_mesg_data_s *D_80275844 = NULL; +AudioInfo *sPrevFinishedAudioInfo = NULL; -extern f32 D_80277620; -extern f64 D_80277628; -extern f64 D_80277630; -extern f32 D_80277638; +extern s32 osViClock; struct { - Acmd* ACMDList[2]; - AudioInfo *audioInfo[3]; + Acmd *ACMDList[2]; + AudioInfo *audio_info[3]; OSThread thread; OSMesgQueue audioFrameMsgQ; OSMesg audioFrameMsgBuf[8]; OSMesgQueue audioReplyMsgQ; OSMesg audioReplyMsgBuf[8]; + u8 thread_stack[AUDIOMANAGER_THREAD_STACK_SIZE]; } audioManager; -u8 sAudioManagerThreadStack[AUDIOMANAGER_THREAD_STACK_SIZE]; -ALHeap D_8027CFF0; -u8 * D_8027D000; -s32 D_8027D004; -OSMesgQueue D_8027D008; -OSMesg D_8027D020[3000/FRAMERATE]; -OSIoMesg D_8027D0E8; -Struct_core1_1D00_4 D_8027D100[3000/FRAMERATE]; +ALHeap sALHeapInfo; +u8 *sALHeapBuffer; +s32 pad_8027D004; +OSMesgQueue audioDMANotifyMsgQ; +OSMesg audioDMANotifyMsgBuf[3000 / FRAMERATE]; +OSIoMesg sExtraDMAMesg; +Struct_core1_1D00_4 sDMAMesgBlocks[3000 / FRAMERATE]; struct { - u8 unk0; - Struct_1D00_3 *unk4; - Struct_1D00_3 *unk8; - u8 padC[0x4]; -} D_8027D5B0; -Struct_1D00_3 D_8027D5C0[90]; -s32 D_8027DCC8; -s32 D_8027DCCC; -s32 D_8027DCD0; -N_ALGlobals D_8027DCD8; -ALSynConfig D_8027DD50; -s32 D_8027DD74; -s32 D_8027DD78; -s32 D_8027DD7C; -s32 D_8027DD80; + u8 initialized; + struct dma_state_data_s *unk4; + struct dma_state_data_s *unk8; +} sDMAState; +struct dma_state_data_s sDMAStateData[90]; +s32 sAudioInfoID; +s32 sNumDMATransfers; // DMA IO Message blocks index +s32 sCmdBufferIndex; +N_ALGlobals sn_alGlobals; +ALSynConfig sn_alConfig; +s32 sFrameSize; +s32 sMinFrameSize; +s32 sMaxFrameSize; +s32 sNumAudioCmdsPerFrame; OscState *freeOscStateList; -OscState oscStates[48]; - +OscState oscStates[NUM_OSC_STATES]; -/* .code */ -f32 _depth2Cents(u8 depth) -{ +f32 depth2Cents(u8 depth) { f32 x = 1.03099298f; f32 cents = 1.0f; @@ -205,8 +188,7 @@ f32 _depth2Cents(u8 depth) return cents; } -ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 oscDepth, u8 oscDelay, u8 arg6) -{ +ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 oscDepth, u8 oscDelay) { OscState *state; ALMicroTime result = 0; @@ -218,97 +200,99 @@ ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 os result = oscDelay << 14; switch (oscType) { - case 1: - state->unk8 = 0; - state->unk6 = 259 - oscRate; - state->unkC.type1.unk0 = oscDepth >> 1; - state->unkC.type1.unk1 = 127 - state->unkC.type1.unk0; - *initVal = state->unkC.type1.unk1; - break; - case 0x80: - state->unkC.type80.unk0 = _depth2Cents(oscDepth); - state->unk8 = 0; - state->unk6 = 259 - oscRate; - *initVal = 1.0f; - break; - default: - break; + case 1: + state->unk8 = 0; + state->unk6 = 259 - oscRate; + state->unkC.type1.unk0 = oscDepth >> 1; + state->unkC.type1.unk1 = 127 - state->unkC.type1.unk0; + *initVal = state->unkC.type1.unk1; + break; + + case 0x80: + state->unkC.type80.cents = depth2Cents(oscDepth); + state->unk8 = 0; + state->unk6 = 259 - oscRate; + *initVal = 1.0f; + break; + + default: + break; } } return result; } -ALMicroTime updateOsc(void *oscState, f32 *updateVal) -{ +ALMicroTime updateOsc(void *oscState, f32 *updateVal) { f32 sp2c; OscState *state = oscState; ALMicroTime result = AL_USEC_PER_FRAME; switch (state->type) { - case 0x01: - state->unk8++; + case 0x01: + state->unk8++; - if (state->unk8 >= state->unk6) { - state->unk8 = 0; - } + if (state->unk8 >= state->unk6) { + state->unk8 = 0; + } - sp2c = (f32)state->unk8 / (f32)state->unk6; - sp2c = sinf(sp2c * BAD_TAU); - sp2c = sp2c * state->unkC.type1.unk0; - *updateVal = state->unkC.type1.unk1 + sp2c; - break; + sp2c = (f32)state->unk8 / (f32)state->unk6; + sp2c = sinf(sp2c * BAD_TAU); + sp2c = sp2c * state->unkC.type1.unk0; + *updateVal = state->unkC.type1.unk1 + sp2c; + break; - case 0x80: - state->unk8++; + case 0x80: + state->unk8++; - if (state->unk8 >= state->unk6) { - state->unk8 = 0; - } + if (state->unk8 >= state->unk6) { + state->unk8 = 0; + } - sp2c = (f32)state->unk8 / (f32)state->unk6; - sp2c = sinf(sp2c * BAD_TAU) * state->unkC.type80.unk0; - *updateVal = alCents2Ratio(sp2c); - break; - default: - break; + sp2c = (f32)state->unk8 / (f32)state->unk6; + sp2c = sinf(sp2c * BAD_TAU) * state->unkC.type80.cents; + *updateVal = alCents2Ratio(sp2c); + break; + default: + break; } return result; } -void stopOsc(OscState *oscState){ +void stopOsc(OscState *oscState) { oscState->next = freeOscStateList; freeOscStateList = oscState; } -void func_8023FA64(ALSeqpConfig *arg0) { +void audioManager_setupSeqp(ALSeqpConfig *config) { OscState *item; - s32 i; + int i; - freeOscStateList = &oscStates[0]; + freeOscStateList = &oscStates[0]; item = &oscStates[0]; - for(i = 0; i< 0x2F; i++){ - item->next = &oscStates[i+1]; + for (i = 0; i < NUM_OSC_STATES - 1; i++) { + item->next = &oscStates[i + 1]; item = item->next; } item->next = NULL; - arg0->initOsc = initOsc; - arg0->updateOsc = updateOsc; - arg0->stopOsc = stopOsc; + + config->initOsc = initOsc; + config->updateOsc = updateOsc; + config->stopOsc = stopOsc; } extern s32 osTvType; -void audioManager_init(void){ - D_8027D000 = (u8 *) bk_malloc(AUDIO_HEAP_SIZE); - bzero(D_8027D000, AUDIO_HEAP_SIZE); - alHeapInit(&D_8027CFF0, D_8027D000, AUDIO_HEAP_SIZE); +void audioManager_init(void) { + sALHeapBuffer = (u8 *) bk_malloc(AUDIO_HEAP_SIZE); + bzero(sALHeapBuffer, AUDIO_HEAP_SIZE); + alHeapInit(&sALHeapInfo, sALHeapBuffer, AUDIO_HEAP_SIZE); #if VERSION == VERSION_USA_1_0 - if(osTvType != OS_TV_NTSC) - osViClock = 0x2e6025c; + if (osTvType != OS_TV_NTSC) + osViClock = VI_MPAL_CLOCK; #elif VERSION == VERSION_PAL - osViClock = 0x2f5b2d2; + osViClock = VI_PAL_CLOCK; #endif audioManager_create(); sfxInstruments_init(); @@ -318,351 +302,346 @@ void audioManager_init(void){ void audioManager_create(void) { int i; - f32 var_f0; + f32 fsize; - osCreateMesgQueue(&D_8027D008, D_8027D020, 3000/FRAMERATE); - osCreateMesgQueue(&audioManager.audioReplyMsgQ, audioManager.audioReplyMsgBuf, 8); //audioReplyMesgQueue + osCreateMesgQueue(&audioDMANotifyMsgQ, audioDMANotifyMsgBuf, 3000 / FRAMERATE); + osCreateMesgQueue(&audioManager.audioReplyMsgQ, audioManager.audioReplyMsgBuf, 8); osCreateMesgQueue(&audioManager.audioFrameMsgQ, audioManager.audioFrameMsgBuf, 8); - var_f0 = 44000.0f/FRAMERATE; - D_8027DD74 = (s32)var_f0; - if ((f32) D_8027DD74 < var_f0) { - D_8027DD74++; + + fsize = 44000.0f / FRAMERATE; + sFrameSize = fsize; + if (sFrameSize < fsize) { + sFrameSize++; } - D_8027DD74 = ((D_8027DD74 / 0xB8) * 0xB8) + 0xB8; - D_8027DD78 = D_8027DD74 - 0xB8; - D_8027DD7C = D_8027DD74; - D_8027DD50.maxVVoices = 0x18; - D_8027DD50.maxPVoices = 0x18; - D_8027DD50.maxUpdates = 0x100; // [port] doubled — 64-bit param slots are larger, demand-based audio may call n_alAudioFrame multiple times per game frame - D_8027DD50.dmaproc = (void*)func_802403B8; - D_8027DD50.fxType = AL_FX_CUSTOM; - D_8027DD50.params = (void*) &D_8027577C; - D_8027DD50.heap = &D_8027CFF0; - D_8027DD50.outputRate = osAiSetFrequency(22000); - n_alInit(&D_8027DCD8, &D_8027DD50); - D_8027D5C0[0].unk0.prev = NULL; - D_8027D5C0[0].unk0.next = NULL; - for(i = 0; i < 89; i++){ - alLink((ALLink *)&D_8027D5C0[i+1], (ALLink *)&D_8027D5C0[i]); - D_8027D5C0[i].unk10 = (uintptr_t)alHeapDBAlloc(0, 0, D_8027DD50.heap, 1, VER_SELECT(0x200, 0x270, 0x200, 0x200)); + sFrameSize = ((sFrameSize / NUM_SAMPLES) + 1) * NUM_SAMPLES; + sMinFrameSize = sFrameSize - NUM_SAMPLES; + sMaxFrameSize = sFrameSize; + + sn_alConfig.maxVVoices = 24; + sn_alConfig.maxPVoices = 24; + sn_alConfig.maxUpdates = 0x100; // [port] doubled — 64-bit param slots are larger, demand-based audio may call n_alAudioFrame multiple times per game frame + sn_alConfig.dmaproc = (void *) audioManager_DMAInitProc; + sn_alConfig.fxType = AL_FX_CUSTOM; + sn_alConfig.params = sEffectsChain; + sn_alConfig.heap = &sALHeapInfo; + sn_alConfig.outputRate = osAiSetFrequency(22000); + n_alInit(&sn_alGlobals, &sn_alConfig); + + sDMAStateData[0].link.prev = NULL; + sDMAStateData[0].link.next = NULL; + + for (i = 0; i < 89; i++) { + alLink(&sDMAStateData[i + 1].link, &sDMAStateData[i].link); + sDMAStateData[i].heap = (uintptr_t)alHeapDBAlloc(0, 0, sn_alConfig.heap, 1, DMA_BLOCK_SIZE); } - D_8027D5C0[i].unk10 = (uintptr_t)alHeapDBAlloc(0, 0, D_8027DD50.heap, 1, VER_SELECT(0x200, 0x270, 0x200, 0x200)); - for(i = 0; i < 2; i++){ - audioManager.ACMDList[i] = bk_malloc(1200000/FRAMERATE); + + sDMAStateData[i].heap = (uintptr_t)alHeapDBAlloc(0, 0, sn_alConfig.heap, 1, DMA_BLOCK_SIZE); + + for (i = 0; i < 2; i++) { + audioManager.ACMDList[i] = bk_malloc(NUM_AUDIO_CMDS_PER_SECOND * sizeof(Acmd) / FRAMERATE); } - D_8027DD80 = 150000/FRAMERATE; - for(i = 0; i < 3; i++){ - audioManager.audioInfo[i] = alHeapDBAlloc(0, 0, D_8027DD50.heap, 1, 0x10); - audioManager.audioInfo[i]->unk8 = 0; - audioManager.audioInfo[i]->unkC = audioManager.audioInfo[i]; - audioManager.audioInfo[i]->data = bk_malloc(D_8027DD7C * 4); + sNumAudioCmdsPerFrame = NUM_AUDIO_CMDS_PER_SECOND / FRAMERATE; + + for (i = 0; i < 3; i++) { + audioManager.audio_info[i] = alHeapDBAlloc(0, 0, sn_alConfig.heap, 1, sizeof(AudioInfo)); + audioManager.audio_info[i]->reply_mesg_data.unk0 = 0; + audioManager.audio_info[i]->reply_mesg_data.audio_info_ptr = audioManager.audio_info[i]; + audioManager.audio_info[i]->data = bk_malloc(4 * sMaxFrameSize); } - osCreateThread(&audioManager.thread, 4, &audioManagerThread_entry, 0, sAudioManagerThreadStack + AUDIOMANAGER_THREAD_STACK_SIZE, 50); + osCreateThread(&audioManager.thread, 4, &audioManagerThread_entry, 0, audioManager.thread_stack + AUDIOMANAGER_THREAD_STACK_SIZE, 50); } void audioManagerThread_entry(void *arg) { - s32 phi_s1; + s32 skip_handle_done_mesg = 1; - phi_s1 = 1; - while(1){ + while (true) { osRecvMesg(&audioManager.audioFrameMsgQ, NULL, OS_MESG_BLOCK); - if (audioManager_handleFrameMsg(audioManager.audioInfo[D_8027DCC8 % 3], D_80275848)){ - if(phi_s1 == 0){ - osRecvMesg(&audioManager.audioReplyMsgQ, (OSMesg *)&D_80275844, OS_MESG_BLOCK); - audioManager_handleDoneMsg(D_80275844->unk4); - D_80275848 = D_80275844->unk4; - }else{ - phi_s1 += -1; + if (OS_ThreadShouldExit()) { // [port] cooperative shutdown + return; + } + ThreadWatchdog_Beat(WATCHDOG_AUDIO_MANAGER); // [port] one beat per audio frame + // [port] Pump messages backlog while a stall blocks this thread + // and then burst. + if (osAiGetLength() / 4 >= sMaxFrameSize) { + continue; + } + if (audioManager_handleFrameMsg(audioManager.audio_info[sAudioInfoID % 3], sPrevFinishedAudioInfo)) { + if (skip_handle_done_mesg == 0) { + osRecvMesg(&audioManager.audioReplyMsgQ, (OSMesg *) &D_80275844, OS_MESG_BLOCK); + audioManager_handleDoneMsg(D_80275844->audio_info_ptr); + sPrevFinishedAudioInfo = D_80275844->audio_info_ptr; + } else { + skip_handle_done_mesg--; } } + // [port] The N64 pacing is open-loop (pump cadence x frame size vs the + // DAC, same crystal), so a pump missed on PC drains the playback + // cushion for tens of seconds. Self-post one extra frame at a time, + // re-deciding on the fresh buffer level after each push, until the + // cushion is rebuilt. + if (port_audioCatchupFrames() > 0) { + osSendMesgPtr(&audioManager.audioFrameMsgQ, NULL, OS_MESG_NOBLOCK); + } } } -void func_8023FFAC(void){ - D_80275770 = osAiGetLength()/4; +void audioManager_func_8023FFAC(void) { + D_80275770 = osAiGetLength() / 4; } -void func_8023FFD4(s32 arg0, s32 arg1, s32 arg2){ - return; -} +void audioManager_func_8023FFD4(s32 arg0, s32 arg1, s32 arg2) {} bool audioManager_handleFrameMsg(AudioInfo *info, AudioInfo *prev_info){ s16 *outbuffer; - Acmd *sp38; - s32 sp34; + Acmd *command_list_end; + s32 command_list_len; + s32 ret; + f32 pad; + #if VERSION == VERSION_USA_1_0 - s32 sp30 = 0; -#else - s32 sp30; + ret = 0; #endif - f32 pad; - outbuffer = (s16 *)osVirtualToPhysical(info->data); - func_802403F0(); - func_8023FFAC(); - if(prev_info){ - sp30 = osAiSetNextBuffer(prev_info->data, prev_info->frameSamples*4); - }//L8024003C + // [port] On N64 nothing could run concurrently with this thread: one core, + // and the game brackets its audio writes with osSetIntMask, which blocks + // preemption. On PC those brackets map to a lock, and the engine advance + // here has to take the same one. + port_lockAudio(); + + outbuffer = (s16 *) osVirtualToPhysical(info->data); + audioManager_func_802403F0(); + audioManager_func_8023FFAC(); + if (prev_info) { + ret = osAiSetNextBuffer(prev_info->data, 4 * prev_info->frame_samples); + } #if VERSION == VERSION_USA_1_0 - if(sp30 == -1){ - func_80247F24(2, 0x7d2); - func_80247F9C(prev_info->frameSamples); - func_80247F9C(info->frameSamples); + if (ret == -1) { + gcdebugText_showLargeValue(2, 2002); + func_80247F9C(prev_info->frame_samples); + func_80247F9C(info->frame_samples); gcdebugText_pauseThread(); - } + } #endif - if((D_80275770 >= 0x139) & !D_80275778){ - info->frameSamples = D_8027DD78; + if ((D_80275770 > 312) & !D_80275778) { + info->frame_samples = sMinFrameSize; D_80275778 = 2; - } - else{ - info->frameSamples = D_8027DD74; - if(D_80275778) + } else { + info->frame_samples = sFrameSize; + if (D_80275778) D_80275778--; } - if(info->frameSamples < D_8027DD78){ - info->frameSamples = D_8027DD78; + if (info->frame_samples < sMinFrameSize) { + info->frame_samples = sMinFrameSize; } - sp38 = n_alAudioFrame(audioManager.ACMDList[D_8027DCD0], &sp34, outbuffer, info->frameSamples); + command_list_end = n_alAudioFrame(audioManager.ACMDList[sCmdBufferIndex], &command_list_len, outbuffer, info->frame_samples); #if VERSION == VERSION_USA_1_0 - if(D_8027DD80 < sp34){ - func_80247F24(2, 2000); - func_80247F9C(sp34); - func_80247F9C(D_8027DD80); + if (sNumAudioCmdsPerFrame < command_list_len) { + gcdebugText_showLargeValue(2, 2000); + func_80247F9C(command_list_len); + func_80247F9C(sNumAudioCmdsPerFrame); gcdebugText_pauseThread(); } #endif - if(sp34 == 0){ - return 0; - }else{ - core1_15B30_addAudioTaskData((Gfx **)audioManager.ACMDList[D_8027DCD0], (Gfx **)sp38, &audioManager.audioReplyMsgQ, &info->unk8); + if (command_list_len == 0) { + port_unlockAudio(); // [port] + return false; + } else { + core1_15B30_addAudioTaskData(audioManager.ACMDList[sCmdBufferIndex], command_list_end, &audioManager.audioReplyMsgQ, OS_MESG_PTR(&info->reply_mesg_data)); // [port] OSMesg is a union on PC func_80250650(); - D_8027DCD0 ^= 1; - return 1; + port_unlockAudio(); // [port] + sCmdBufferIndex ^= 1; + return true; } } -void audioManager_handleDoneMsg(AudioInfo *info) -{ - static int D_8027584C = true; - if (osAiGetLength() >> 2 == 0 && D_8027584C == false) { - D_8027584C = false; +void audioManager_handleDoneMsg(AudioInfo *info) { + static bool debug_var = true; + + if ((osAiGetLength() / 4) == 0 && (!debug_var)) { + debug_var = false; } } -#if VERSION == VERSION_USA_1_0 -uintptr_t func_80240204(uintptr_t addr, s32 len, void *state) -{ - void *sp44; - uintptr_t sp40; - Struct_1D00_3 *phi_s0; - Struct_1D00_3 *phi_v0; - uintptr_t new_var; - Struct_1D00_3 *sp30; - - phi_s0 = D_8027D5B0.unk4; +uintptr_t func_80240204(uintptr_t addr, s32 len, void *state) { // [port] pointer-width for 64-bit ALDMAproc + void *dest_vaddr; + uintptr_t dev_addr_low_bit; + uintptr_t dev_addr_end; + struct dma_state_data_s *phi_s0, *phi_v0, *sp30; + +#if VERSION == VERSION_PAL + phi_v0 = sDMAState.unk4; +#endif sp30 = NULL; - while (phi_s0 != NULL ) { - new_var = (phi_s0->unk8 + 0x200); - if ((phi_s0->unk8 > addr)) break; - sp30 = phi_s0; - if ((addr + len) <= new_var) { - phi_s0->unkC = (uintptr_t) D_8027DCC8; - return osVirtualToPhysical((void*)(phi_s0->unk10 + (addr - phi_s0->unk8))); - } - phi_s0 = (Struct_1D00_3 *)phi_s0->unk0.next; +#if VERSION == VERSION_USA_1_0 + for (phi_s0 = sDMAState.unk4; phi_s0 != NULL; phi_s0 = (struct dma_state_data_s *) phi_s0->link.next) { +#elif VERSION == VERSION_PAL + for (phi_s0 = phi_v0; phi_s0 != NULL; phi_s0 = (struct dma_state_data_s *) phi_s0->link.next) { +#endif + dev_addr_end = phi_s0->unk8 + DMA_BLOCK_SIZE; - } - phi_s0 = D_8027D5B0.unk8; - if (phi_s0 == NULL) { - func_80247F24(2, 0x7D1); - gcdebugText_pauseThread(); - return osVirtualToPhysical(D_8027D5B0.unk4); - } - D_8027D5B0.unk8 = (Struct_1D00_3 *)phi_s0->unk0.next; - alUnlink((ALLink *)phi_s0); - if (sp30 != NULL) { - alLink((ALLink *)phi_s0, (ALLink *)sp30); - } else { - phi_v0 = D_8027D5B0.unk4; - if (phi_v0 != NULL) { - D_8027D5B0.unk4 = phi_s0; - phi_s0->unk0.next = (ALLink *)phi_v0; - phi_s0->unk0.prev = NULL; - phi_v0->unk0.prev = (ALLink *)phi_s0; - } else { - D_8027D5B0.unk4 = phi_s0; - phi_s0->unk0.next = NULL; - phi_s0->unk0.prev = NULL; + if (phi_s0->unk8 > addr) { + break; } - } - sp44 = (void*)phi_s0->unk10; - sp40 = addr & 1; - addr -= sp40; - phi_s0->unk8 = addr; - phi_s0->unkC = (uintptr_t) D_8027DCC8; - osPiStartDma((OSIoMesg *)&D_8027D100[D_8027DCCC++], 1, 0, addr, sp44, 0x200U, &D_8027D008); - return osVirtualToPhysical(sp44) + sp40; -} -#elif VERSION == VERSION_PAL -#ifndef NONMATCHING -uintptr_t func_80240204(uintptr_t addr, s32 len, void *state); -#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_1D00/func_80240204.s") -#else -uintptr_t func_80240204(uintptr_t addr, s32 len, void *state){ - void *sp44; - uintptr_t sp40; - Struct_1D00_3 *phi_s0; - Struct_1D00_3 *phi_v0; - uintptr_t new_var; - Struct_1D00_3 *sp30; - - phi_v0 = D_8027D5B0.unk4; - sp30 = NULL; - for(phi_s0 = phi_v0; phi_s0 != NULL; phi_s0 = (Struct_1D00_3 *)phi_s0->unk0.next) { - sp40 = (phi_s0->unk8 + 0x270); - if ((phi_s0->unk8 > addr)) break; sp30 = phi_s0; - if ((addr + len) <= sp40) { - phi_s0->unkC = (uintptr_t) D_8027DCC8; - return osVirtualToPhysical((void*)(phi_s0->unk10 + (addr - phi_s0->unk8))); + + if ((addr + len) <= dev_addr_end) { + phi_s0->unkC = sAudioInfoID; +#if VERSION == VERSION_USA_1_0 + return osVirtualToPhysical((u8 *) phi_s0->heap + (addr - phi_s0->unk8)); +#elif VERSION == VERSION_PAL + dev_addr_low_bit = (s32) (u8 *) phi_s0->heap + (addr - phi_s0->unk8); + return osVirtualToPhysical((void *) dev_addr_low_bit); +#endif } } - phi_s0 = D_8027D5B0.unk8; + + phi_s0 = sDMAState.unk8; if (phi_s0 == NULL) { +#if VERSION == VERSION_USA_1_0 + gcdebugText_showLargeValue(2, 2001); + gcdebugText_pauseThread(); + return osVirtualToPhysical(sDMAState.unk4); +#elif VERSION == VERSION_PAL return osVirtualToPhysical(phi_v0); +#endif } - D_8027D5B0.unk8 = (Struct_1D00_3 *)phi_s0->unk0.next; - alUnlink((ALLink *)phi_s0); + + sDMAState.unk8 = (struct dma_state_data_s *) phi_s0->link.next; + alUnlink((ALLink *) phi_s0); + if (sp30 != NULL) { - alLink((ALLink *)phi_s0, (ALLink *)sp30); + alLink((ALLink *) phi_s0, (ALLink *) sp30); } else { - phi_v0 = D_8027D5B0.unk4; + phi_v0 = sDMAState.unk4; if (phi_v0 != NULL) { - D_8027D5B0.unk4 = phi_s0; - phi_s0->unk0.next = (ALLink *)phi_v0; - phi_s0->unk0.prev = NULL; - phi_v0->unk0.prev = (ALLink *)phi_s0; + sDMAState.unk4 = phi_s0; + phi_s0->link.next = (ALLink *) phi_v0; + phi_s0->link.prev = NULL; + phi_v0->link.prev = (ALLink *) phi_s0; } else { - D_8027D5B0.unk4 = phi_s0; - phi_s0->unk0.next = NULL; - phi_s0->unk0.prev = NULL; + sDMAState.unk4 = phi_s0; + phi_s0->link.next = NULL; + phi_s0->link.prev = NULL; } } - new_var = addr & 1; - addr = addr - new_var; + dest_vaddr = (void *) phi_s0->heap; + dev_addr_low_bit = addr & 1; + addr -= dev_addr_low_bit; phi_s0->unk8 = addr; - phi_s0->unkC = (uintptr_t) D_8027DCC8; - sp44 = (void*)phi_s0->unk10; - osPiStartDma((OSIoMesg *)&D_8027D100[D_8027DCCC++], 1, 0, phi_s0->unk8, (void*)phi_s0->unk10, 0x270U, &D_8027D008); - return osVirtualToPhysical(sp44) + new_var; + phi_s0->unkC = (uintptr_t) sAudioInfoID; + osPiStartDma((OSIoMesg *)&sDMAMesgBlocks[sNumDMATransfers++], OS_MESG_PRI_HIGH, OS_READ, addr, dest_vaddr, DMA_BLOCK_SIZE, &audioDMANotifyMsgQ); + return osVirtualToPhysical(dest_vaddr) + dev_addr_low_bit; } -#endif -#endif -void *func_802403B8(void *state) { - if (D_8027D5B0.unk0 == 0) { - D_8027D5B0.unk4 = NULL; - D_8027D5B0.unk8 = &D_8027D5C0[0]; - D_8027D5B0.unk0 = 1; +ALDMAproc audioManager_DMAInitProc(void *state) { + if (!sDMAState.initialized) { + sDMAState.unk4 = NULL; + sDMAState.unk8 = sDMAStateData; + sDMAState.initialized = true; } - *(void **)state = &D_8027D5B0; - return &func_80240204; + *(void **)state = (void *) &sDMAState; + return func_80240204; } -void func_802403F0(void) { - u32 phi_s0; - OSMesg sp40; - Struct_1D00_3 *phi_s1; - Struct_1D00_3 *phi_s0_2; - - sp40.ptr = NULL; - for(phi_s0 = 0; phi_s0 < D_8027DCCC; phi_s0++){ +void audioManager_func_802403F0(void) { + u32 i; + OSMesg temp_mesg; + struct dma_state_data_s *phi_s1; + struct dma_state_data_s *phi_s0_2; + temp_mesg.ptr = NULL; + for (i = 0; i < sNumDMATransfers; i++) { #if VERSION == VERSION_USA_1_0 - if (osRecvMesg(&D_8027D008, &sp40, 0) == -1) { + if (osRecvMesg(&audioDMANotifyMsgQ, &temp_mesg, OS_MESG_NOBLOCK) == -1) { #if 0 // [port] DMA is synchronous on PC (memcpy), no completion messages to drain - func_80247F24(2, 0x7D5); - func_80247F9C(D_8027DCCC); - func_80247F9C(phi_s0); + gcdebugText_showLargeValue(2, 2005); + func_80247F9C(sNumDMATransfers); + func_80247F9C(i); gcdebugText_pauseThread(); #else break; #endif } #else - osRecvMesg(&D_8027D008, &sp40, 0); + osRecvMesg(&audioDMANotifyMsgQ, &temp_mesg, OS_MESG_NOBLOCK); #endif } - phi_s0_2 = D_8027D5B0.unk4; - while(phi_s0_2 != NULL){ - phi_s1 = (Struct_1D00_3 *)phi_s0_2->unk0.next; - if (phi_s0_2->unkC + 1 < D_8027DCC8) { - if (phi_s0_2 == D_8027D5B0.unk4) { - D_8027D5B0.unk4 = (Struct_1D00_3 *)phi_s0_2->unk0.next; + + phi_s0_2 = sDMAState.unk4; + + while (phi_s0_2 != NULL) { + phi_s1 = (struct dma_state_data_s *) phi_s0_2->link.next; + if (phi_s0_2->unkC + 1 < sAudioInfoID) { + if (phi_s0_2 == sDMAState.unk4) { + sDMAState.unk4 = (struct dma_state_data_s *)phi_s0_2->link.next; } - alUnlink((ALLink *)phi_s0_2); - if (D_8027D5B0.unk8 != NULL) { - alLink(&phi_s0_2->unk0, &D_8027D5B0.unk8->unk0); + alUnlink(&phi_s0_2->link); + if (sDMAState.unk8 != NULL) { + alLink(&phi_s0_2->link, &sDMAState.unk8->link); } else { - D_8027D5B0.unk8 = phi_s0_2; - phi_s0_2->unk0.next = NULL; - phi_s0_2->unk0.prev = NULL; + sDMAState.unk8 = phi_s0_2; + phi_s0_2->link.next = NULL; + phi_s0_2->link.prev = NULL; } } phi_s0_2 = phi_s1; } - D_8027DCCC = 0; - D_8027DCC8 += 1; + + sNumDMATransfers = 0; + sAudioInfoID++; } #if VERSION == VERSION_PAL -void *audioManager_getThread_PAL(void){ +OSThread *audioManager_getThread_PAL(void) { return &audioManager.thread; } #endif -void audioManager_stopThread(void){ - if(D_80275774){ - D_80275774 = 0; +void audioManager_stopThread(void) { + if (sAudioManagerThreadStarted) { + sAudioManagerThreadStarted = false; osStopThread(&audioManager.thread); } } -void audioManager_startThread(void){ - if(D_80275774 == 0){ - D_80275774 = 1; - port_audioStartThread(); +void audioManager_startThread(void) { + if (!sAudioManagerThreadStarted) { + sAudioManagerThreadStarted = true; + osStartThread(&audioManager.thread); } } -OSThread * audioManager_getThread(void){ +OSMesgQueue *audioManager_getReplyMesgQueue(void) { + return &audioManager.audioReplyMsgQ; +} + +OSThread *audioManager_getThread(void) { return &audioManager.thread; } -ALHeap * func_802405B8(void){ - return &D_8027CFF0; +ALHeap *audioManager_getALHeapInfo(void) { + return &sALHeapInfo; } -OSMesgQueue * func_802405C4(void){ - return &D_8027D008; +OSMesgQueue *audioManager_getDMANotifyMesgQueue(void) { + return &audioDMANotifyMsgQ; } -OSIoMesg * func_802405D0(void){ - return &D_8027D0E8; +OSIoMesg *audioManager_getExtraDMAMesg(void) { + return &sExtraDMAMesg; } -OSMesgQueue * audioManager_getFrameMesgQueue(void){ +OSMesgQueue *audioManager_getFrameMesgQueue(void) { return &audioManager.audioFrameMsgQ; } diff --git a/src/core1/io/bamotor.c b/src/core1/bamotor.c similarity index 78% rename from src/core1/io/bamotor.c rename to src/core1/bamotor.c index 8d5a23acc..84111a3a3 100644 --- a/src/core1/io/bamotor.c +++ b/src/core1/bamotor.c @@ -5,10 +5,10 @@ #include "variables.h" #include "version.h" +#include "port/DevTools/ThreadWatchdog.h" +#include "port/OS/OS.h" #include "port/Patches/Patches.h" -//#include - #define RUMBLE_THREAD_STACK_SIZE 0x200 void func_8024F35C(s32); @@ -75,6 +75,10 @@ void rumbleThread_entry(void *arg) { do{ osRecvMesg(&D_80282390, NULL, 1); + if (OS_ThreadShouldExit()) { // [port] cooperative shutdown + return; + } + ThreadWatchdog_Beat(WATCHDOG_RUMBLE); // [port] one beat per retrace signal D_802827E0++; if (!D_802823B0 && ((D_802827E0 % FRAMERATE) == 0)) { func_80250930(); @@ -109,43 +113,12 @@ void __baMotor_80250BA4(s32 arg0, s32 arg1, s32 arg2){ } void baMotor_80250C08(void) { - // [port] Rumble thread logic inlined — N64 thread/VBlank model replaced by per-frame update - static s32 sFrameCounter; - static s32 sRumbleState; - if (D_802823AC != 0) { - s32 prev_state; - D_80282424 = MIN(D_80282420, D_80282424 + time_getDelta()); - - prev_state = sRumbleState; - sFrameCounter++; - - if (D_80282424 != D_80282420) { - f32 temp_f2 = D_80282428 + ((D_8028242C - D_80282428) * D_80282424 / D_80282420); - s32 var_v0 = (s32)(((1.0 - temp_f2) * 8.0) + 1); - if (var_v0 < 2) { - sRumbleState = var_v0; - } else { - sRumbleState = (sFrameCounter % var_v0) == 0; - } - } else { - sRumbleState = 0; - } - - if (sRumbleState != prev_state) { - if (sRumbleState) { - __baMotor_startRumble(); - } else { - __baMotor_stopRumble(); - } - } } } void baMotor_init(void) { - // [port] Bypass N64 PFS probing and rumble thread — LUS handles motor directly. -#if 0 s32 pfs_status; func_8024F35C(4); @@ -159,14 +132,20 @@ void baMotor_init(void) { D_802823B0 = D_802823AC; if(D_802823AC){ osCreateMesgQueue(&D_80282390, &D_802823A8, 1); + // [port] The thread parks on that queue between retraces, so it has to + // block on it, and its entry needs allowlisting before osStartThread + // will really launch it. + OS_SetQueueBlocking(&D_80282390, 1); + OS_EnableThreadEntry((void*)rumbleThread_entry); osCreateThread(&sRumbleThread, 8, rumbleThread_entry, NULL, sRumbleThreadStack + RUMBLE_THREAD_STACK_SIZE, 25); osStartThread(&sRumbleThread); - viMgr_registerSignalMesg(&D_80282390, OS_MESG_32(NULL)); + viMgr_registerSignalMesg(&D_80282390, OS_MESG_32(0)); } -#endif - osMotorInit(NULL, &D_802823B8, 0); - D_802823AC = 1; - D_802823B0 = 1; +} + +// [port] Watchdog diagnostics +OSMesgQueue *baMotor_getRetraceQueue(void){ + return &D_80282390; } void __baMotor_80250D8C(void){} @@ -176,9 +155,7 @@ void baMotor_80250D94(f32 arg0, f32 arg1, f32 arg2){ if(arg2 != 0.0f && D_802823AC){ if(func_802E4A08() == 0){ if(!(0.1 < D_80282420 - D_80282424) || !(arg0 + arg1 < D_80282428 + D_8028242C)){ - // [port] Scale intensity by ImGui rumble setting. - // Original N64 values are ~50% of max (duty cycling a binary motor). - f32 scale = port_getRumbleScale() * 2.0f; + f32 scale = port_getRumbleScale(); D_80282420 = arg2; D_80282424 = 0.0f; D_80282428 = MIN(arg0 * scale, 1.0f); diff --git a/src/core1/debugtext.c b/src/core1/debugtext.c index 5babb3b1c..36a329bc1 100644 --- a/src/core1/debugtext.c +++ b/src/core1/debugtext.c @@ -253,7 +253,7 @@ void func_80247D80(s32 arg0, s32 arg1, s32 arg2) { } } -void func_80247F24(s32 arg0, s32 arg1) { +void gcdebugText_showLargeValue(s32 arg0, s32 arg1) { D_80275BD0 = 0; D_80275BCC = arg0; D_80275BBC = 0xE; diff --git a/src/core1/defragmanager.c b/src/core1/defragmanager.c index 85585d207..3aa61c63c 100644 --- a/src/core1/defragmanager.c +++ b/src/core1/defragmanager.c @@ -28,13 +28,13 @@ void defragManager_free(void){ osDestroyThread(&sDefragThread); } -void defragManager_80240874(void){ +void defragManager_resume(void){ if(func_8023E000() == 3){ osSendMesgPtr(&sDefragThreadResumeSyncQueue, NULL, OS_MESG_BLOCK); } } -void defragManager_802408B0(void){ +void defragManager_pause(void){ if(func_8023E000() == 3){ osSendMesgPtr(&sDefragThreadPauseSyncQueue, NULL, OS_MESG_BLOCK); } diff --git a/src/core1/depthbuffer.c b/src/core1/depthbuffer.c index dc2db7807..2fc2381a5 100644 --- a/src/core1/depthbuffer.c +++ b/src/core1/depthbuffer.c @@ -7,67 +7,69 @@ #include struct { - void *data; - int unk4; + u16 *data; + bool unk4; } sDepthBuffer; -void func_80253190(Gfx **gfx) { - func_80253208(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, gFramebuffers[getActiveFramebuffer()]); +void depthbuffer_clear(Gfx **gfx) { + depthbuffer_clearRegion(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, gFramebuffers[getActiveFramebuffer()]); } -void func_80253208(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer){ - if( sDepthBuffer.data != NULL && (getGameMode() != GAME_MODE_4_PAUSED || gsworld_getEnableDraw())){ - //draw z_buffer +void depthbuffer_clearRegion(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer) { + if ((sDepthBuffer.data != NULL) && ((getGameMode() != GAME_MODE_4_PAUSED) || gsworld_getEnableDraw())) { gDPPipeSync((*gfx)++); gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(sDepthBuffer.data)); gDPSetCycleType((*gfx)++, G_CYC_FILL); gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2); - gDPSetFillColor((*gfx)++, 0xFFFCFFFC); + gDPSetFillColor((*gfx)++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16) | GPACK_ZDZ(G_MAXFBZ, 0)); gDPScisFillRectangle((*gfx)++, x, y, x + w - 1, y + h - 1); - - //draw color_buffer + gDPPipeSync((*gfx)++); gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(color_buffer)); } } -int func_80253400(void){ +bool depthbuffer_getUnk4(void) { return sDepthBuffer.unk4; } -bool depthBuffer_isPointerSet(void) { +bool depthbuffer_isDataPtrSet(void) { return sDepthBuffer.data != NULL; } -void depthBuffer_stub(void) {} +void depthbuffer_stub(void) {} -void func_80253428(int arg0) { +void depthbuffer_enable(bool enable) { u16 *var_v0; - int new_var; - if (arg0) { - var_v0 = (sDepthBuffer.data = &D_8000E800); - while (((uintptr_t) sDepthBuffer.data) % 0x40) { - var_v0 = (sDepthBuffer.data = var_v0 + 1); + + if (enable) { + sDepthBuffer.data = (u16 *) D_8000E800; + + var_v0 = sDepthBuffer.data; + while (((uintptr_t) sDepthBuffer.data) % 64) { // [port] pointer-width + sDepthBuffer.data = var_v0 + 1; + var_v0 = sDepthBuffer.data; } - (void)&D_8000E800; // decomp match - }else{ + do { } while ((D_8000E800 && 1) * 0); //remove this + } else { sDepthBuffer.data = NULL; } - sDepthBuffer.unk4 = false; + + sDepthBuffer.unk4 = FALSE; } -void func_802534A8(int arg0) { - sDepthBuffer.unk4 = (sDepthBuffer.data != NULL && arg0); +void depthbuffer_setUnk4(bool value) { + sDepthBuffer.unk4 = sDepthBuffer.data && value; } -void zBuffer_set(Gfx **gfx) { +void depthbuffer_set(Gfx **gfx) { if (sDepthBuffer.data && getGameMode() != GAME_MODE_4_PAUSED) { gDPPipeSync((*gfx)++); gDPSetDepthImage((*gfx)++, sDepthBuffer.data); } } -void *zBuffer_get(void) { +void *depthbuffer_getDataPtr(void) { return sDepthBuffer.data; } diff --git a/src/core1/display_list.c b/src/core1/display_list.c index 4305dba31..49d18e32e 100644 --- a/src/core1/display_list.c +++ b/src/core1/display_list.c @@ -2,6 +2,7 @@ #include "core1/core1.h" #include #include "functions.h" +#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "port/Engine.h" #include @@ -20,7 +21,7 @@ static s32 sStackSelector; #define MTX_STACK_COUNT 2100 #define VTX_STACK_COUNT 1290 -s32 gTextureFilterPoint; +bool sUseTexturePointFilter; struct ucode_task_data_s sUcodeTaskData[20]; s32 sCurrentUcodeTaskDataID; OSMesgQueue sTaskDataListLockMesgQueue; @@ -29,7 +30,7 @@ u16 gScissorBoxLeft; u16 gScissorBoxRight; u16 gScissorBoxTop; u16 gScissorBoxBottom; -Gfx *D_80283214; +Gfx *D_80283214; // never used void core1_15B30_requestLockForTaskDataID(void) { osRecvMesg(&sTaskDataListLockMesgQueue, NULL, OS_MESG_BLOCK); @@ -39,7 +40,7 @@ void core1_15B30_requestReleaseForTaskDataID(void) { osSendMesgPtr(&sTaskDataListLockMesgQueue, NULL, OS_MESG_BLOCK); } -void core1_15B30_addAudioTaskData(Gfx **arg0, Gfx **arg1, void *arg2, void *arg3) { +void core1_15B30_addAudioTaskData(Acmd *arg0, Acmd *arg1, OSMesgQueue *arg2, OSMesg arg3) { struct ucode_task_data_s *task_data; core1_15B30_requestLockForTaskDataID(); @@ -49,60 +50,53 @@ void core1_15B30_addAudioTaskData(Gfx **arg0, Gfx **arg1, void *arg2, void *arg3 task_data->task_type = UCODE_TASK_TYPE_AUDIO; task_data->data_ptr = arg0; task_data->data_ptr_end = arg1; - task_data->unk10 = arg2; - task_data->unk14 = (s32)(intptr_t)arg3; + task_data->audio_mesg_queue = arg2; + task_data->audio_mesg = arg3; thread5_sendTaskToQueue(OS_MESG_PTR(task_data)); } - -void func_80253640(Gfx ** gdl, void *arg1){ - D_80283214 = *gdl; - gSPSegment((*gdl)++, 0x00, 0x00000000); - gDPSetRenderMode((*gdl)++, G_RM_NOOP, G_RM_NOOP2); - gSPClearGeometryMode((*gdl)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); - gDPPipeSync((*gdl)++); - gDPPipelineMode((*gdl)++, G_PM_NPRIMITIVE); - gDPSetAlphaCompare((*gdl)++, G_AC_NONE); - gDPSetColorDither((*gdl)++, G_CD_MAGICSQ); - gDPSetScissor((*gdl)++, G_SC_NON_INTERLACE, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom); - func_80253208(gdl, 0, 0, gFramebufferWidth, gFramebufferHeight, arg1); - gDPSetColorImage((*gdl)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(arg1)); - gDPSetCycleType((*gdl)++, G_CYC_1CYCLE); - gDPSetTextureConvert((*gdl)++, G_TC_FILT); - gDPSetTextureDetail((*gdl)++, G_TD_CLAMP); - if(gTextureFilterPoint){ - gDPSetTextureFilter((*gdl)++, G_TF_POINT); +void setupFramebuffer(Gfx **gfx, void *color_buffer) { + D_80283214 = *gfx; + gSPSegment((*gfx)++, 0x00, 0x00000000); + gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2); + gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); + gDPPipeSync((*gfx)++); + gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE); + gDPSetAlphaCompare((*gfx)++, G_AC_NONE); + gDPSetColorDither((*gfx)++, G_CD_MAGICSQ); + gDPSetScissor((*gfx)++, G_SC_NON_INTERLACE, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom); + depthbuffer_clearRegion(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, color_buffer); + gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(color_buffer)); + gDPSetCycleType((*gfx)++, G_CYC_1CYCLE); + gDPSetTextureConvert((*gfx)++, G_TC_FILT); + gDPSetTextureDetail((*gfx)++, G_TD_CLAMP); + if (sUseTexturePointFilter) { + gDPSetTextureFilter((*gfx)++, G_TF_POINT); }else{ - gDPSetTextureFilter((*gdl)++, G_TF_BILERP); + gDPSetTextureFilter((*gfx)++, G_TF_BILERP); } - gDPSetTextureLOD((*gdl)++, G_TL_TILE); - gDPSetTextureLUT((*gdl)++, G_TT_NONE); - gDPSetTexturePersp((*gdl)++, G_TP_PERSP); - zBuffer_set(gdl); + gDPSetTextureLOD((*gfx)++, G_TL_TILE); + gDPSetTextureLUT((*gfx)++, G_TT_NONE); + gDPSetTexturePersp((*gfx)++, G_TP_PERSP); + depthbuffer_set(gfx); } -void scissorBox_SetForGameMode(Gfx **gdl, s32 framebuffer_idx) { +void setupFramebufferForGamemode(Gfx **gdl, s32 framebuffer_idx) { if(getGameMode() == GAME_MODE_8_BOTTLES_BONUS || getGameMode() == GAME_MODE_A_SNS_PICTURE) { - // [port] Redirect rendering to GPU-side aux FB via gsSPSetFB. - // On N64, gDPSetColorImage pointed to D_80382450 (CPU buffer). - // gsSPResetFB is emitted in func_802E39D0 after the scene draw. - s32 auxFb = port_getAuxGpuFbId(); - if (auxFb >= 0) { - gsSPSetFB((*gdl)++, auxFb); - } - scissorBox_setSmall(); - func_80253640(gdl, func_8030C704()); + EventSystem_Should(VB_PICTUREBOX_TARGET_FB, true, gdl); + picturebox_setScissorBox(); + setupFramebuffer(gdl, picturebox_getColorBuffer()); } else{ scissorBox_setDefault(); - func_80253640(gdl, gFramebuffers[framebuffer_idx]); + setupFramebuffer(gdl, gFramebuffers[framebuffer_idx]); } } -void setupScissorBoxAndFramebuffer(Gfx **gfx, uintptr_t framebuffer_address){ +void setupScissorBoxAndFramebuffer(Gfx **gfx, void *color_buffer) { gSPSegment((*gfx)++, 0x00, 0x00000000); - gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_PHYSICAL_TO_K0(framebuffer_address)); + gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_PHYSICAL_TO_K0(color_buffer)); gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); gSPTexture((*gfx)++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); gSPSetGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH); @@ -119,7 +113,7 @@ void setupScissorBoxAndFramebuffer(Gfx **gfx, uintptr_t framebuffer_address){ void setupDefaultScissorBoxAndFramebuffer(Gfx **gfx, s32 framebuffer_idx){ scissorBox_setDefault(); - setupScissorBoxAndFramebuffer(gfx, (uintptr_t)gFramebuffers[framebuffer_idx]); + setupScissorBoxAndFramebuffer(gfx, gFramebuffers[framebuffer_idx]); } void core1_15B30_finishDList_renderThread(Gfx **gfx) { @@ -197,13 +191,13 @@ void core1_15B30_init(void) { scissorBox_setDefault(); } -void drawRectangle2D(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, s32 r, s32 g, s32 b){ +void drawRectangle2D(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, s32 r, s32 g, s32 b) { gDPPipeSync((*gfx)++); gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE); gDPSetCycleType((*gfx)++, G_CYC_FILL); gDPSetFillColor((*gfx)++, GPACK_RGBA5551(r, g, b, 1) << 16 | GPACK_RGBA5551(r, g, b, 1)); gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2); - gDPScisFillRectangle((*gfx)++, x, y, x + w -1, y + h -1); + gDPScisFillRectangle((*gfx)++, x, y, x + w - 1, y + h - 1); } void graphicsCache_release(void) { @@ -218,8 +212,16 @@ void graphicsCache_release(void) { } } -void graphicsCache_init(void){ - if(sGfxStack[0] == NULL){ +void graphicsCache_init(void) { + if (sGfxStack[0] == NULL) { +#if 0 + sGfxStack[0] = (Gfx *)malloc(29600); // 3700 dlist commands + sGfxStack[1] = (Gfx *)malloc(29600); + sMtxStack[0] = (Mtx *)malloc(44800); // 700 matrices + sMtxStack[1] = (Mtx *)malloc(44800); + sVtxStack[0] = (Vtx *)malloc(6880); // 430 vertices + sVtxStack[1] = (Vtx *)malloc(6880); +#endif sGfxStack[0] = (Gfx *)GameEngine_Malloc(GFX_STACK_COUNT * sizeof(Gfx)); sGfxStack[1] = (Gfx *)GameEngine_Malloc(GFX_STACK_COUNT * sizeof(Gfx)); sMtxStack[0] = (Mtx *)GameEngine_Malloc(MTX_STACK_COUNT * sizeof(Mtx)); @@ -228,15 +230,13 @@ void graphicsCache_init(void){ sVtxStack[1] = (Vtx *)GameEngine_Malloc(VTX_STACK_COUNT * sizeof(Vtx)); dummy_func_80254464(); } + + sStackSelector = 0; - gTextureFilterPoint = 0; + sUseTexturePointFilter = FALSE; } -// [port] Verify the frame's dlist emission fit within the static stack -// capacities. If it didn't, we've already written past the buffer and -// corrupted the heap, but logging it loudly (instead of silently deferring -// to a CRT debug-heap break at the next malloc/free) makes the root cause -// obvious. Mirrors Shipwright's THGA_IsCrash() canary pattern. +// [port] Verify the frame's dlist emission fit within the static stack capacities. void graphicsCache_checkFrame(Gfx *gfxStart, Gfx *gfxEnd, Mtx *mtxStart, Mtx *mtxEnd, Vtx *vtxStart, Vtx *vtxEnd) { s32 gfxUsed = (s32)(gfxEnd - gfxStart); s32 mtxUsed = (s32)(mtxEnd - mtxStart); @@ -279,12 +279,11 @@ void core1_15B30_addTask7TaskData(s32 framebuffer_id) { thread5_sendTaskToQueue(OS_MESG_PTR(task_data)); } -void toggleTextureFilterPoint(void){ - u32 ret_val = gTextureFilterPoint; - gTextureFilterPoint = ret_val < 1; +void core1_15B30_toggleTexturePointFilter(void) { + sUseTexturePointFilter = !sUseTexturePointFilter; } -void getGraphicsStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx){ +void graphicscache_swapAndGetStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx) { sStackSelector = (1 - sStackSelector); *gfx = sGfxStack[sStackSelector]; *mtx = sMtxStack[sStackSelector]; diff --git a/src/core1/graphics_thread.c b/src/core1/graphics_thread.c index 3c6de06b4..63e6ba620 100644 --- a/src/core1/graphics_thread.c +++ b/src/core1/graphics_thread.c @@ -1,4 +1,4 @@ -// BanjoDecomp: thread5 (osCreateThread OSId 5) +// BanjoDecomp: core1/code_8C50.c // Needs to be included here because interrupt.h contains: // typedef u32 OSIntMask; and u32 isn't defined before that. @@ -7,6 +7,9 @@ #include #include "core1/core1.h" #include "functions.h" +#include "port/DevTools/ThreadWatchdog.h" +#include "port/OS/OS.h" +#include "port/Patches/Patches.h" #include "libultraship/libultra/rcp.h" #include "libultraship/libultra/sptask.h" #include "libultraship/libultra/types.h" @@ -90,11 +93,24 @@ static OSTimer sControllerTimer; static bool sEnableControllerTimer; void thread5_startNextAudioTask(void); +void osSpTaskLoad(OSTask* task); +void osSpTaskStartGo(OSTask* task); /* .code */ + +// [port] The queues are static; Game.cpp opts them into blocking before +// thread5_create runs. +OSMesgQueue* thread5_getTaskQueue(void) { + return &sThread5MesgQueue; +} +OSMesgQueue* thread5_getSyncQueue(void) { + return &sThread5SyncMesgQueue; +} + void thread5_sendTaskToQueue(OSMesg arg0) { static bool clear_freeze = true; + port_thread5_onSubmit(arg0.ptr); // [port] carry the interpolation pair with the task osSendMesg(&sThread5MesgQueue, arg0, 1); // Lighthouse [port] Adjustment here to account for our OSMesg union definition if (arg0.data32 == THREAD5_MESSAGE_EVENT_SYNC) { @@ -125,28 +141,29 @@ void thread5_insertGfxTaskData(OSMesg arg0) { } void thread5_startAudioTask(struct ucode_task_data_s *task_data) { -#if 0 +#if 0 // [port] microcode boot pointers, there is no RSP to load them into ucode_getPtrAndSize(&sAudTask.t.ucode_boot, &sAudTask.t.ucode_boot_size); sAudTask.t.ucode = n_aspMainTextStart; sAudTask.t.ucode_data = n_aspMainDataStart; +#endif sAudTask.t.data_ptr = (void*) task_data->data_ptr; - sAudTask.t.data_size = (task_data->data_ptr_end - task_data->data_ptr) >> 3 << 3; + sAudTask.t.data_size = ((u8 *)task_data->data_ptr_end - (u8 *)task_data->data_ptr) >> 3 << 3; osWritebackDCache(sAudTask.t.data_ptr , sAudTask.t.data_size); osWritebackDCache(&sAudTask, sizeof(OSTask)); sActiveAudioTaskDataPtr = task_data; osSpTaskLoad(&sAudTask); osSpTaskStartGo(&sAudTask); sUnkFlag1 = UNKFLAG1_AUDIO_TASK; -#endif } void thread5_startF3DEXTask(struct ucode_task_data_s *task_data) { -#if 0 +#if 0 // [port] microcode boot pointers, there is no RSP to load them into ucode_getPtrAndSize(&sGfxTask.t.ucode_boot, &sGfxTask.t.ucode_boot_size); sGfxTask.t.ucode = gSPF3DEX_fifoTextStart; sGfxTask.t.ucode_data = gSPF3DEX_fifoDataStart; +#endif sGfxTask.t.data_ptr = (void*) task_data->data_ptr; - sGfxTask.t.data_size = (task_data->data_ptr_end - task_data->data_ptr) >> 3 << 3; + sGfxTask.t.data_size = ((u8 *)task_data->data_ptr_end - (u8 *)task_data->data_ptr) >> 3 << 3; osWritebackDCache(sGfxTask.t.data_ptr , sGfxTask.t.data_size); osWritebackDCache(&sGfxTask, sizeof(OSTask)); osSpTaskLoad(&sGfxTask); @@ -157,16 +174,16 @@ void thread5_startF3DEXTask(struct ucode_task_data_s *task_data) { sUnkFlag2_Saved = sUnkFlag2; sUnkCounter3 = 30; } -#endif } void thread5_startL3DEXTask(struct ucode_task_data_s *task_data) { -#if 0 +#if 0 // [port] microcode boot pointers, there is no RSP to load them into ucode_getPtrAndSize(&sGfxTask.t.ucode_boot, &sGfxTask.t.ucode_boot_size); sGfxTask.t.ucode = gSPL3DEX_fifoTextStart; sGfxTask.t.ucode_data = gSPL3DEX_fifoDataStart; +#endif sGfxTask.t.data_ptr = (void*) task_data->data_ptr; - sGfxTask.t.data_size = (task_data->data_ptr_end - task_data->data_ptr) >> 3 << 3; + sGfxTask.t.data_size = ((u8 *)task_data->data_ptr_end - (u8 *)task_data->data_ptr) >> 3 << 3; osWritebackDCache(sGfxTask.t.data_ptr , sGfxTask.t.data_size); osWritebackDCache(&sGfxTask, sizeof(OSTask)); osSpTaskLoad(&sGfxTask); @@ -177,11 +194,9 @@ void thread5_startL3DEXTask(struct ucode_task_data_s *task_data) { sUnkFlag2_Saved = sUnkFlag2; sUnkCounter3 = 30; } -#endif } void thread5_startGfxTask(struct ucode_task_data_s *task_data) { -#if 0 switch (task_data->task_type) { case 1: thread5_startF3DEXTask(task_data); @@ -191,11 +206,15 @@ void thread5_startGfxTask(struct ucode_task_data_s *task_data) { thread5_startL3DEXTask(task_data); break; } -#endif } void thread5_handleAudioTaskMesg(OSMesg msg) { thread5_insertAudioTaskData(msg); + if ((sUnkFlag1 == UNKFLAG1_NO_TASK) && (sActiveAudioTaskDataID != sSelectedAudioTaskDataID)) { + struct ucode_task_data_s *ptr = sAudioTaskDataList[sActiveAudioTaskDataID]; + sActiveAudioTaskDataID = (sActiveAudioTaskDataID + 1) % 20; + thread5_startAudioTask(ptr); + } } void thread5_handleF3DEXTaskMesg(OSMesg msg) { @@ -215,7 +234,6 @@ void thread5_handleL3DEXTaskMesg(OSMesg msg) { } void thread5_handleSyncEvent(void) { -#if 0 if ((sUnkFlag1 == UNKFLAG1_NO_TASK) && (sUnkFlag2_Saved == 2) && (sActiveGfxTaskDataID == sSelectedGfxTaskDataID) @@ -226,13 +244,11 @@ void thread5_handleSyncEvent(void) { else { sSyncCounter++; } -#endif } extern u64 osClockRate; void thread5_handleDPEvent(void) { -#if 0 if ((sUnkFlag2 << 1) < 0) { osDpSetStatus(DPC_SET_FREEZE); sCurrentFramebuffer = osViGetCurrentFramebuffer(); @@ -250,12 +266,9 @@ void thread5_handleDPEvent(void) { sSyncCounter--; } } -#endif } void thread5_handleVIRetraceEvent(void) { -#if 0 - static s32 audiotimer_trigger = 0; s32 sp2C = (sSyncCounter != 0) && (sActiveGfxTaskDataID == sSelectedGfxTaskDataID) && (sUnkFlag2 == 2) && (sUnkFlag1 == UNKFLAG1_NO_TASK); volatile s32 sp30; @@ -265,7 +278,7 @@ void thread5_handleVIRetraceEvent(void) { osDpSetStatus(DPC_CLR_FREEZE); sUnkFlag2_Saved = sUnkFlag2; - dummy_func_8025AFB8(); + // dummy_func_8025AFB8(); if (sUnkFlag2_Saved & 1) { sUnkCounter3 = 30; @@ -295,25 +308,23 @@ void thread5_handleVIRetraceEvent(void) { } } sTask7Handled = false; + static s32 audiotimer_trigger = 0; audiotimer_trigger++; if (!(audiotimer_trigger & 1)) { osStopTimer(&sAudioTimer); osSetTimer(&sAudioTimer, 280000, 0, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_AUDIO_TIMER)); } - - if (sEnableControllerTimer) { + if (sEnableControllerTimer && OS_SiPumpLive()) { osStopTimer(&sControllerTimer); #if VERSION == VERSION_USA_1_0 osSetTimer(&sControllerTimer, ((osClockRate / 60)* 2) / 3, 0, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_CONT_TIMER)); #elif VERSION == VERSION_PAL - osSetTimer(&sControllerTimer, ((osClockRate / 60.0)* 2) / 3, 0, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_CONT_TIMER); + osSetTimer(&sControllerTimer, ((osClockRate / 60.0)* 2) / 3, 0, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_CONT_TIMER)); #endif } -#endif } void thread5_handleSPEvent(void) { -#if 0 struct ucode_task_data_s *active_audio_task; s32 temp_v1; @@ -328,7 +339,10 @@ void thread5_handleSPEvent(void) { } if (sUnkFlag1 == UNKFLAG1_AUDIO_TASK) { - osSendMesg(&sActiveAudioTaskDataPtr->task_type, sActiveAudioTaskDataPtr->unk4, 0); + // [port] The raw decomp sends through the first two struct fields; + // with the struct typed, these are the reply queue and message set by + // core1_15B30_addAudioTaskData. + osSendMesg(sActiveAudioTaskDataPtr->audio_mesg_queue, sActiveAudioTaskDataPtr->audio_mesg, 0); } if ((sUnkFlag1 == UNKFLAG1_AUDIO_TASK) && (sGfxTaskYielded != 0)) { @@ -350,7 +364,6 @@ void thread5_handleSPEvent(void) { osSendMesgPtr(&sThread5SyncMesgQueue, NULL, 0); sSyncCounter--; } -#endif } void thread5_handleTask7Mesg(OSMesg arg0) { @@ -358,6 +371,11 @@ void thread5_handleTask7Mesg(OSMesg arg0) { } void thread5_handleAudioTimerEvent(void) { + // [port] While the demo audio hold is up, skip the frame message so the + // engine does not consume sfx cues queued for the demo's first frame. + if (port_audioHeld() || port_audioStallHold()) { + return; + } osSendMesgPtr(audioManager_getFrameMesgQueue(), NULL, OS_MESG_NOBLOCK); thread5_startNextAudioTask(); } @@ -466,40 +484,48 @@ void thread5_checkAndExecutePreNMI(void) { //thread5 entry void thread5_entry(void *arg) { -#if 0 - OSMesg msg = NULL; + // [port] Only adjustment: OSMesg is a union here, + // so event words read through .data32 and tasks through .ptr + OSMesg msg; + msg.ptr = NULL; do { osRecvMesg(&sThread5MesgQueue, &msg, OS_MESG_BLOCK); + // [port] Shutdown released the queue rather than delivering anything, so msg + // holds nothing worth dispatching. Leave before the engine goes away. + if (OS_ThreadShouldExit()) { + return; + } + ThreadWatchdog_Beat(WATCHDOG_THREAD5); // [port] one beat per serviced message thread5_checkAndExecutePreNMI(); - if ((s32)msg == THREAD5_MESSAGE_EVENT_SYNC) { thread5_handleSyncEvent(); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_VI_RETRACE) { thread5_handleVIRetraceEvent(); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_DP) { thread5_handleDPEvent(); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_SP) { thread5_handleSPEvent(); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_AUDIO_TIMER) { thread5_handleAudioTimerEvent(); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_FAULT) { do{}while(1); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_PRENMI) { thread5_handlePreNMIEvent(); } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_DEBUG) { } - else if ((u32)msg == THREAD5_MESSAGE_EVENT_CONT_TIMER) { pfsManager_getStartReadData(); } - else if ((u32)msg >= 100) { - if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_AUDIO) { thread5_handleAudioTaskMesg(msg); } - else if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_F3DEX) { thread5_handleF3DEXTaskMesg(msg); } - else if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_L3DEX) { thread5_handleL3DEXTaskMesg(msg); } - else if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_FRAMEBUFFER_CHANGED) { thread5_handleTask7Mesg(msg); } + if ((uintptr_t)msg.ptr < 100) { + if (msg.data32 == THREAD5_MESSAGE_EVENT_SYNC) { thread5_handleSyncEvent(); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_VI_RETRACE) { thread5_handleVIRetraceEvent(); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_DP) { thread5_handleDPEvent(); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_SP) { thread5_handleSPEvent(); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_AUDIO_TIMER) { thread5_handleAudioTimerEvent(); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_FAULT) { do{}while(1); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_PRENMI) { thread5_handlePreNMIEvent(); } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_DEBUG) { } + else if (msg.data32 == THREAD5_MESSAGE_EVENT_CONT_TIMER) { pfsManager_getStartReadData(); } + } + else { + if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_AUDIO) { thread5_handleAudioTaskMesg(msg); } + else if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_F3DEX) { thread5_handleF3DEXTaskMesg(msg); } + else if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_L3DEX) { thread5_handleL3DEXTaskMesg(msg); } + else if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_FRAMEBUFFER_CHANGED) { thread5_handleTask7Mesg(msg); } } } while (1); -#endif } //thread5 create void thread5_create(void) { -#if 0 u8 *yield_data_ptr; - osCreateMesgQueue(&sThread5MesgQueue, &sThread5MesgBuffer, 20); - osCreateMesgQueue(&sThread5SyncMesgQueue, &sThread5SyncMesgBufer, 10); - osSetEventMesg(OS_EVENT_DP, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_DP); - osSetEventMesg(OS_EVENT_SP, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_SP); - osSetEventMesg(OS_EVENT_FAULT, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_FAULT); - osSetEventMesg(OS_EVENT_PRENMI, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_PRENMI); + osCreateMesgQueue(&sThread5MesgQueue, sThread5MesgBuffer, 20); + osCreateMesgQueue(&sThread5SyncMesgQueue, sThread5SyncMesgBufer, 10); + osSetEventMesg(OS_EVENT_DP, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_DP)); + osSetEventMesg(OS_EVENT_SP, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_SP)); + osSetEventMesg(OS_EVENT_FAULT, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_FAULT)); + osSetEventMesg(OS_EVENT_PRENMI, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_PRENMI)); viMgr_registerSignalMesg(&sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_VI_RETRACE)); sSyncCounter = 0; sTask7Handled = 0; @@ -516,7 +542,6 @@ void thread5_create(void) { sGfxTask.t.yield_data_ptr = (u64 *) yield_data_ptr; osCreateThread(&sThread5, THREAD5_ID, thread5_entry, NULL, &sThread5Stack[2048], THREAD5_PRI); osStartThread(&sThread5); -#endif } void thread5_enableControllerTimer(void) { @@ -539,3 +564,20 @@ OSMesgQueue *__thread5_getMessageQueue(void) { OSThread *__thread5_getThreadObject(void) { return &sThread5; } + +// [port] Watchdog diagnostics: unsynchronized snapshot of the pipeline state. +void thread5_getWatchdogState(Thread5WatchdogState *out) { + out->unkFlag1 = sUnkFlag1; + out->unkFlag2 = sUnkFlag2; + out->unkFlag2Saved = sUnkFlag2_Saved; + out->syncCounter = sSyncCounter; + out->task7Handled = sTask7Handled; + out->gfxActiveId = sActiveGfxTaskDataID; + out->gfxSelectedId = sSelectedGfxTaskDataID; + out->audioActiveId = sActiveAudioTaskDataID; + out->audioSelectedId = sSelectedAudioTaskDataID; + out->taskQueueCount = sThread5MesgQueue.validCount; + out->taskQueueCap = sThread5MesgQueue.msgCount; + out->syncQueueCount = sThread5SyncMesgQueue.validCount; + out->syncQueueCap = sThread5SyncMesgQueue.msgCount; +} diff --git a/src/core1/math/ml.c b/src/core1/gu_matrix.c similarity index 99% rename from src/core1/math/ml.c rename to src/core1/gu_matrix.c index 79eec3915..acf6c05fd 100644 --- a/src/core1/math/ml.c +++ b/src/core1/gu_matrix.c @@ -1,4 +1,4 @@ -// BanjoDecomp: ml.c +// BanjoDecomp: core1/code_3250.c #include "core1/core1.h" #include #include diff --git a/src/core1/math/mlmtx.c b/src/core1/gu_perspective.c similarity index 93% rename from src/core1/math/mlmtx.c rename to src/core1/gu_perspective.c index b04304b3c..d17f00c60 100644 --- a/src/core1/math/mlmtx.c +++ b/src/core1/gu_perspective.c @@ -1,4 +1,4 @@ -// BanjoDecomp: mlmtx.c +// BanjoDecomp: core1/code_7F60.c #include #include #include "core1/core1.h" @@ -8,11 +8,12 @@ static void _guMtxIdentF(float mf[4][4]); -#if VERSION == VERSION_USA_1_0 -u8 D_80275900[8] = {0xCF, 0xAD, 0xA2, 0x90, 0x93, 0x4A, 0x83, 0xF1}; -#elif VERSION == VERSION_PAL -u8 D_80275900[8] = {0xD3, 0x9E, 0xA6, 0x20, 0xC7, 0x7E, 0xD5, 0xC6}; -#endif +s32 D_802758F0 = VER_SELECT(0xAD7FF2F3, 0xB585BADA, 0, 0); // BGS_DATA_CRC2 +s32 D_802758F4 = VER_SELECT(0xD884D8AC, 0xD731B7E2, 0, 0); // FP_DATA_CRC2 +s32 D_802758F8 = 0; +s32 D_802758FC = 0; +s32 D_80275900 = VER_SELECT(0xCFADA290, 0xD39EA620, 0, 0); // LAIR_DATA_CRC2 +s32 D_80275904 = VER_SELECT(0x934A83F1, 0xC77ED5C6, 0, 0); // GV_DATA_CRC2 f32 D_80275908 = BAD_DTOR; diff --git a/src/core1/init.c b/src/core1/init.c index 9686e2ad1..e7073d9df 100644 --- a/src/core1/init.c +++ b/src/core1/init.c @@ -3,23 +3,22 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "port/ShipUtils.h" // gPortResetPending #include "version.h" #include "gc/gctransition.h" #define MAIN_THREAD_STACK_SIZE 0x17F0 -extern void audioManager_init(void); - #if VERSION == VERSION_PAL extern s32 D_80000300; #endif s32 D_80275610 = 0; s32 D_80275614 = 0; -u32 gGlobalTimer = 0; +s32 gGlobalTimer = 0; u32 sDebugVar_8027561C[] = { 0x9, 0x4, 0xA, 0x3, 0xB, 0x2, 0xC, 0x5, 0x0, 0x1, 0x6, 0xD, -1 }; // never used -u32 D_80275650 = VER_SELECT(0xAD019D3C, 0xA371A8F3, 0, 0); //SM_DATA_CRC_1 -u32 D_80275654 = VER_SELECT(0xD381B72F, 0xD0709154, 0, 0); //SM_DATA_CRC_2 +s32 D_80275650 = VER_SELECT(0xAD019D3C, 0xA371A8F3, 0, 0); //SM_DATA_CRC2 +s32 D_80275654 = VER_SELECT(0xD381B72F, 0xD0709154, 0, 0); //MM_DATA_CRC2 char sDebugVar_80275658[] = VER_SELECT("HjunkDire:218755", "HjunkDire:300875", "HjunkDire:", "HjunkDire:"); /* .bss */ @@ -71,7 +70,7 @@ void func_8023DA9C(s32 arg0){ ucode_stub1(); } -u32 globalTimer_getTimeMasked(u32 mask){ +s32 globalTimer_getTimeMasked(s32 mask) { return gGlobalTimer & mask; } @@ -118,7 +117,7 @@ void core1_init(void) { // [port] Irrelevant and replaced with system malloc // heap_init(); core1_15B30_init(); - dummy_func_8025AFB0(); + // dummy_func_8025AFB0(); // [port] Irrelevant and replaced with system malloc // allocUnusedBlock(); assetCache_init(); @@ -159,7 +158,7 @@ void mainLoop(void){ // [port] Don't need this #if 0 if(!mapSpecificFlags_validateCRC1()){ - eeprom_writeBlocks(0, 0, 0x80397AD0, 0x40); + eeprom_writeBlocks(0, 0, (void *) PHYS_TO_K0(0x00397AD0), EEPROM_MAXBLOCKS); } #endif @@ -172,7 +171,7 @@ void mainLoop(void){ func_80255ACC(); spawnQueue_func_802C3A18(); if(func_802E4424()) - game_draw(0); + game_draw(FALSE); spawnQueue_flush(); break; }//L8023DE34 @@ -193,7 +192,7 @@ void mainLoop(void){ //render weird CRC failure image for(y= 0x1e; y < gFramebufferHeight - 0x1e; y++){//L8023DEB4 for(x = 0x14; x < 0xeb; x++){ - tmp = ((8 * globalTimer_getTime()) + ((x*x) + (y*y))); + tmp = ((globalTimer_getTime() << 3) + x * x + y * y); r = _SHIFTL(x>>3, 11, 5); g = _SHIFTL(y>>3, 6, 5); @@ -210,10 +209,12 @@ void mainLoop(void){ }//L8023DF70 #endif + port_actorDespawn_beginDefer(); CALL_EVENT(GameFrameUpdate); + port_actorDespawn_endDefer(); } -void mainThread_entry(void *arg) { +void mainThread_entry(void *arg) { core1_init(); sns_write_payload_over_heap(); diff --git a/src/core1/math/longlong_arith.c b/src/core1/math/longlong_arith.c deleted file mode 100644 index a3cff6547..000000000 --- a/src/core1/math/longlong_arith.c +++ /dev/null @@ -1,63 +0,0 @@ -// BanjoDecomp: (unknown decomp origin) -/* MSVC provides these as compiler intrinsics, so only define them for other compilers */ -#ifndef _MSC_VER - -unsigned long long __ull_rshift(unsigned long long a0, unsigned long long a1) -{ - return a0 >> a1; -} - -unsigned long long __ll_lshift(unsigned long long a0, unsigned long long a1) -{ - return a0 << a1; -} - -long long __ll_rshift(long long a0, long long a1) -{ - return a0 >> a1; -} - -#endif /* _MSC_VER */ - -/* These are not MSVC intrinsics, so define them for all compilers */ -unsigned long long __ull_rem(unsigned long long a0, unsigned long long a1) -{ - return a0 % a1; -} - -unsigned long long __ull_div(unsigned long long a0, unsigned long long a1) -{ - return a0 / a1; -} - -long long __ll_rem(unsigned long long a0, long long a1) -{ - return a0 % a1; -} - -long long __ll_div(long long a0, long long a1) -{ - return a0 / a1; -} - -unsigned long long __ll_mul(unsigned long long a0, unsigned long long a1) -{ - return a0 * a1; -} - -void __ull_divremi(unsigned long long *div, unsigned long long *rem, unsigned long long a2, unsigned short a3) -{ - *div = a2 / a3; - *rem = a2 % a3; -} - -long long __ll_mod(long long a0, long long a1) -{ - long long tmp = a0 % a1; - if ((tmp < 0 && a1 > 0) || (tmp > 0 && a1 < 0)) - { - - tmp += a1; - } - return tmp; -} diff --git a/src/core1/math/longlong_convert.c b/src/core1/math/longlong_convert.c deleted file mode 100644 index 8fe014dbe..000000000 --- a/src/core1/math/longlong_convert.c +++ /dev/null @@ -1,40 +0,0 @@ -// BanjoDecomp: (unknown decomp origin) -long long __d_to_ll(double a0) -{ - return a0; -} - -long long __f_to_ll(float a0) -{ - return a0; -} - -unsigned long long __d_to_ull(double a0) -{ - return a0; -} - -unsigned long long __f_to_ull(float a0) -{ - return a0; -} - -double __ll_to_d(long long a0) -{ - return a0; -} - -float __ll_to_f(long long a0) -{ - return a0; -} - -double __ull_to_d(unsigned long long a0) -{ - return a0; -} - -float __ull_to_f(unsigned long long a0) -{ - return a0; -} diff --git a/src/core1/math/vector.c b/src/core1/ml.c similarity index 88% rename from src/core1/math/vector.c rename to src/core1/ml.c index 6b2302e1d..72e4be8ee 100644 --- a/src/core1/math/vector.c +++ b/src/core1/ml.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (unknown decomp origin) +// BanjoDecomp: core1/ml.c #include #include "core1/core1.h" #include "functions.h" @@ -6,13 +6,8 @@ #include "version.h" #include "bk_math.h" -#if VERSION == VERSION_USA_1_0 -u32 D_80276CB0 = 0xD22FFFD8; //WHAT IS THIS? -u32 D_80276CB4 = 0xDEFEF692; //WHAT IS THIS? -#elif VERSION == VERSION_PAL -u32 D_80276CB0 = 0x90FA97CB; //WHAT IS THIS? -u32 D_80276CB4 = 0x8D96D002; //WHAT IS THIS? -#endif +s32 D_80276CB0 = VER_SELECT(0xD22FFFD8, 0x90FA97CB, 0, 0); // TTC_DATA_CRC2 +s32 D_80276CB4 = VER_SELECT(0xDEFEF692, 0x8D96D002, 0, 0); // RBB_DATA_CRC2 u16 *D_80276CB8 = NULL; //! ml_acosPrecValTblPtr @@ -122,37 +117,39 @@ f32 ml_vec3f_distance(f32 vec1[3], f32 vec2[3]) { return LENGTH_VEC3F(diff); } -f32 ml_func_802560D0(f32 arg0[3], f32 arg1[3], f32 arg2[3]) { - f32 sp4C[3]; - f32 pad48; - f32 sp3C[3]; - f32 sp38; - f32 sp34; - f32 sp30; - f32 sp24[3]; - f32 sp20; - f32 pad58; +f32 ml_vec3f_distance_to_point(f32 line_start_position[3], f32 line_end_position[3], f32 point_position[3]) { + f32 closestPointOnLine[3]; + f32 pad48; // unused + f32 pointOffsetFromLineStart[3]; + f32 pointDistanceFromLineStart; + f32 projectionFactor; + f32 projectionDistance; + f32 lineDirection[3]; + f32 lineLength; + f32 pad58; // unused - TUPLE_DIFF_COPY(sp24, arg1, arg0) - sp20 = LENGTH_VEC3F(sp24); + TUPLE_DIFF_COPY(lineDirection, line_end_position, line_start_position) + lineLength = LENGTH_VEC3F(lineDirection); - if (sp20 < 0.01) { - return ml_vec3f_distance(arg0, arg2); + if (lineLength < 0.01) { + return ml_vec3f_distance(line_start_position, point_position); } - TUPLE_DIFF_COPY(sp3C, arg2, arg0) - sp38 = LENGTH_VEC3F(sp3C); + TUPLE_DIFF_COPY(pointOffsetFromLineStart, point_position, line_start_position) + pointDistanceFromLineStart = LENGTH_VEC3F(pointOffsetFromLineStart); - if (sp38 < 0.01) { - return sp38; + if (pointDistanceFromLineStart < 0.01) { + return pointDistanceFromLineStart; } - sp34 = ((sp24[0]*sp3C[0] + sp24[1]*sp3C[1] + sp24[2]*sp3C[2]) / (sp20 * sp38)); - sp30 = (sp34 *sp38) / sp20; - sp4C[0] = arg0[0] + (sp24[0] * sp30); - sp4C[1] = arg0[1] + (sp24[1] * sp30); - sp4C[2] = arg0[2] + (sp24[2] * sp30); - return ml_vec3f_distance(sp4C, arg2); + projectionFactor = ((lineDirection[0] * pointOffsetFromLineStart[0] + + lineDirection[1] * pointOffsetFromLineStart[1] + + lineDirection[2] * pointOffsetFromLineStart[2]) / (lineLength * pointDistanceFromLineStart)); + projectionDistance = (projectionFactor * pointDistanceFromLineStart) / lineLength; + closestPointOnLine[0] = line_start_position[0] + (lineDirection[0] * projectionDistance); + closestPointOnLine[1] = line_start_position[1] + (lineDirection[1] * projectionDistance); + closestPointOnLine[2] = line_start_position[2] + (lineDirection[2] * projectionDistance); + return ml_vec3f_distance(closestPointOnLine, point_position); } f32 ml_distanceSquared_vec3f(f32 vec1[3], f32 vec2[3]) @@ -238,16 +235,14 @@ void ml_vec3f_set_length_copy(f32 dst[3], f32 src[3], f32 len) ml_vec3f_copy(dst, src); } -void func_80256664(f32 ptr[3]) -{ - u32 i; +void ml_vec3f_clamp_deg360(f32 ptr[3]) { + int i; - for (i = 0; i < 3; i++) - { + for (i = 0; i < 3; i++) { if (ptr[i] >= 0) - ptr[i] = (s32)ptr[i] % 360; + ptr[i] = (s32) ptr[i] % 360; else - ptr[i] += ((360 - (s32)ptr[i]) / 360) * 360; + ptr[i] += ((360 - (s32) ptr[i]) / 360) * 360; } } @@ -462,7 +457,7 @@ f32 func_80257248(f32 vec1[3], f32 vec2[3]) return func_8025715C(vec2[0] - vec1[0], vec2[2] - vec1[2]); } -void func_8025727C(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2) +void ml_horizontal_and_vertical_angles(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2) { f32 dz; f32 dy; // unused @@ -1193,15 +1188,15 @@ void func_8025901C(f32 arg0, f32 arg1[3], f32 arg2[3], f32 arg3){ }//L80259184 } -f32 func_80259198(f32 arg0, f32 arg1) +f32 ml_clamp_abs_f(f32 value, f32 max_abs_value) { - if (arg0 > arg1) - return arg1; + if (value > max_abs_value) + return max_abs_value; - if (arg0 < -arg1) - return -arg1; + if (value < -max_abs_value) + return -max_abs_value; - return arg0; + return value; } f32 mlDiffDegF(f32 arg0, f32 arg1) @@ -1269,48 +1264,51 @@ void ml_sub_delta_time(f32 *x) { *x = 0; } -void func_8025947C(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]) +// Perpendicular projection of point onto line using xz coordinates +void ml_project_point_onto_vecf3( + f32 closest_point_on_line[3], f32 line_start_position[3], + f32 line_end_position[3], f32 point_to_project[3]) { - f32 f0; - f32 f12; - f32 f16; - f32 f8; - f32 f18; - f32 f4; + f32 line_dx_xz; + f32 line_dz_xz; + f32 line_slope_xz; + f32 intersection_x_xz; + f32 line_intercept_xz; + f32 perpendicular_intercept_xz; - a0[1] = a1[1]; + closest_point_on_line[1] = line_start_position[1]; - f0 = a2[0] - a1[0]; + line_dx_xz = line_end_position[0] - line_start_position[0]; - if (f0 == 0) + if (line_dx_xz == 0) { - a0[0] = a1[0]; - a0[2] = a3[2]; + closest_point_on_line[0] = line_start_position[0]; + closest_point_on_line[2] = point_to_project[2]; return; } - f12 = a2[2] - a1[2]; + line_dz_xz = line_end_position[2] - line_start_position[2]; - if (f12 == 0) + if (line_dz_xz == 0) { - a0[0] = a3[0]; - a0[2] = a1[2]; + closest_point_on_line[0] = point_to_project[0]; + closest_point_on_line[2] = line_start_position[2]; return; } - f16 = f12 / f0; - f18 = a1[2] - (a1[0] * f16); + line_slope_xz = line_dz_xz / line_dx_xz; + line_intercept_xz = line_start_position[2] - (line_start_position[0] * line_slope_xz); - f8 = -1.0 / f16; + intersection_x_xz = -1.0 / line_slope_xz; - f4 = a3[2] - (a3[0] * f8); + perpendicular_intercept_xz = point_to_project[2] - (point_to_project[0] * intersection_x_xz); - f8 = (f4 - f18) / (f16 - f8); + intersection_x_xz = (perpendicular_intercept_xz - line_intercept_xz) / (line_slope_xz - intersection_x_xz); - a0[0] = f8; - a0[2] = f8 * f16 + f18; + closest_point_on_line[0] = intersection_x_xz; + closest_point_on_line[2] = intersection_x_xz * line_slope_xz + line_intercept_xz; } diff --git a/src/core1/math/matrix_stack.c b/src/core1/mlmtx.c similarity index 95% rename from src/core1/math/matrix_stack.c rename to src/core1/mlmtx.c index ba78ce751..b2f8a9101 100644 --- a/src/core1/math/matrix_stack.c +++ b/src/core1/mlmtx.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (unknown decomp origin) +// BanjoDecomp: core1/mlmtx.c #include #include "core1/core1.h" @@ -12,13 +12,9 @@ void _guRotateF(f32 mf[4][4], f32, f32, f32, f32); f32 func_80263FF0(f32); f32 cosf(f32); -#if VERSION == VERSION_USA_1_0 - s32 D_80276570 = 0xFF62C2B8; //WHAT IS THIS? - s32 D_80276574 = 0x84D7B4F8; //CORE2_DATA_CRC2 -#elif VERSION == VERSION_PAL - s32 D_80276570 = 0xF71CBE76; //WHAT IS THIS? - s32 D_80276574 = 0xA2B6F47C; //CORE2_DATA_CRC2 -#endif +s32 D_80276570 = VER_SELECT(0xFF62C2B8, 0xF71CBE76, 0, 0); // CC_DATA_CRC2 +s32 D_80276574 = VER_SELECT(0x84D7B4F8, 0xA2B6F47C, 0, 0); // CORE2_DATA_CRC2 + f32 D_80276578 = BAD_DTOR; f32 D_8027657C = BAD_DTOR; @@ -221,7 +217,6 @@ void mlMtx_push_multiplied_2(MtxF * l_mtx, MtxF * r_mtx) { } } s_mtx_stack = (dst + 0); - FrameInterpolation_RecordMatrixMult(l_mtx->mf, r_mtx->mf); } //mlMtx @@ -237,7 +232,6 @@ void mlMtxIdent(void){ v0 += 5; } v0[0] = 1.0f; - FrameInterpolation_RecordMatrixIdent(); } void func_80251B5C(f32 x, f32 y, f32 z){ @@ -260,7 +254,6 @@ void mlMtxSet(MtxF* arg0) { *dst++ = *src++; } } - FrameInterpolation_RecordMatrixSet(arg0->mf); } void mlMtxRotate(f32 a, f32 x, f32 y, f32 z) { @@ -274,7 +267,6 @@ void mlMtxRotPitch(f32 arg0) { f32 var_f10; f32 var_f18; - FrameInterpolation_RecordMatrixRotPitch(arg0); if (arg0 != 0.0f) { arg0 *= D_80276578; sin = sinf(arg0); @@ -303,7 +295,6 @@ void mlMtxRotYaw(f32 arg0) { f32 var_f18; s32 i; - FrameInterpolation_RecordMatrixRotYaw(arg0); if (arg0 != 0.0f) { arg0 *= BAD_DTOR; sin = sinf(arg0); @@ -323,7 +314,6 @@ void mlMtxRotRoll(f32 arg0) { f32 var_f10; f32 var_f18; - FrameInterpolation_RecordMatrixRotRoll(arg0); if (arg0 != 0.0f) { arg0 *= D_8027657C; sin = sinf(arg0); @@ -395,7 +385,6 @@ void mlMtxRotatePYR(f32 pitch, f32 yaw, f32 roll){ void mlMtxScale_xyz(f32 x, f32 y, f32 z){ int i; - FrameInterpolation_RecordMatrixScale(x, y, z); for(i = 0; i < 3; i++){ s_mtx_stack->mf[0][i] *= x; s_mtx_stack->mf[1][i] *= y; @@ -405,7 +394,6 @@ void mlMtxScale_xyz(f32 x, f32 y, f32 z){ void mlMtxScale(f32 scale){ int i; - FrameInterpolation_RecordMatrixScale(scale, scale, scale); for(i = 0; i < 3; i++){ s_mtx_stack->mf[0][i] *= scale; s_mtx_stack->mf[1][i] *= scale; @@ -520,7 +508,6 @@ void mlMtxTranslate(f32 x, f32 y, f32 z) { f32 phi_f16; s32 phi_v1; - FrameInterpolation_RecordMatrixTranslate(x, y, z); for(phi_v1 = 0; phi_v1 < 3; phi_v1++){ phi_f18 = s_mtx_stack->mf[0][phi_v1] * x; phi_f16 = s_mtx_stack->mf[1][phi_v1] * y; diff --git a/src/core1/musicplayer.c b/src/core1/musicplayer.c index d7ff3d29b..ba238ec90 100644 --- a/src/core1/musicplayer.c +++ b/src/core1/musicplayer.c @@ -3,6 +3,7 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "musicplayer.h" #include "version.h" @@ -15,7 +16,7 @@ void musicTrack_setVolume(u8, s32); void func_8024FC1C(u8, s32); void func_8025AC20(enum comusic_e, s32, s32, f32, char*, s32); void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void *arg4, char *arg5, s32 arg6); -void comusicPlayer_free(void); +void coMusicPlayer_free(void); void func_8025A55C(s32, s32, s32); void func_8025A7DC(enum comusic_e); void func_8025ABB8(enum comusic_e, s32, s32, s32); @@ -32,7 +33,7 @@ int D_80276E34 = 0; * @param track_id * @return CoMusic* */ -CoMusic *__find_track(enum comusic_e track_id) { +CoMusic *findTrack(enum comusic_e track_id) { CoMusic *iMusPtr; CoMusic *freeSlotPtr; @@ -76,12 +77,12 @@ void func_802599B4(CoMusic *this){ func_8024FC1C(this - D_80276E30, -1); } -void comusicPlayer_init(void){ +void coMusicPlayer_init(void){ CoMusic * iPtr; s32 i; if(D_80276E30 != NULL) - comusicPlayer_free(); + coMusicPlayer_free(); D_80276E30 = (CoMusic *) bk_malloc(6*sizeof(CoMusic)); for(iPtr = D_80276E30; iPtr < D_80276E30 + 6; iPtr++){ @@ -101,7 +102,7 @@ void comusicPlayer_init(void){ } //comusic_freeAll -void comusicPlayer_free(void){ +void coMusicPlayer_free(void){ CoMusic *iPtr; func_8024FB8C(); func_8024F83C(); @@ -113,7 +114,7 @@ void comusicPlayer_free(void){ D_80276E30 = NULL; } -s32 comusic_active_track_count(void){ +s32 coMusicPlayer_getTrackCount(void){ CoMusic * iPtr; s32 cnt = 0; for(iPtr = D_80276E30; iPtr < D_80276E30 + 6; iPtr++){ @@ -123,7 +124,7 @@ s32 comusic_active_track_count(void){ return cnt; } -void comusicPlayer_update(void) { +void coMusicPlayer_update(void) { s32 temp_lo; CoMusic *var_s0; f32 dt; @@ -366,7 +367,7 @@ void func_8025A58C(u32 arg0, u32 arg1){ } -void func_8025A5AC(enum comusic_e comusic_id, s32 volume, s32 arg2){ +void playMusic(enum comusic_e comusic_id, s32 volume, s32 arg2){ CoMusic *tmp_a2; s32 sp20; @@ -374,7 +375,7 @@ void func_8025A5AC(enum comusic_e comusic_id, s32 volume, s32 arg2){ volume = gcMusic_getDefaultVolumeForTrack(comusic_id); } - tmp_a2 = __find_track(comusic_id); + tmp_a2 = findTrack(comusic_id); if(tmp_a2 == NULL) return; @@ -402,11 +403,11 @@ void func_8025A5AC(enum comusic_e comusic_id, s32 volume, s32 arg2){ } void coMusicPlayer_playMusicWeak(enum comusic_e track_id, s32 volume){ - func_8025A5AC(track_id, volume, 0); + playMusic(track_id, volume, 0); } void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume){ - func_8025A5AC(track_id, volume, 1); + playMusic(track_id, volume, 1); } //comusic_queueTrack @@ -414,7 +415,7 @@ void comusic_playTrack(enum comusic_e track_id){ CoMusic *trackPtr; s32 indx; - trackPtr = __find_track(track_id); + trackPtr = findTrack(track_id); if(trackPtr == NULL) return; @@ -437,7 +438,7 @@ void func_8025A788(enum comusic_e comusic_id, f32 delay1, f32 delay2){ void func_8025A7DC(enum comusic_e track_id){ CoMusic *trackPtr; - trackPtr = __find_track(track_id); + trackPtr = findTrack(track_id); if (trackPtr != NULL && trackPtr->track_id >= 0){ func_802599B4(trackPtr); } @@ -454,7 +455,7 @@ s32 func_8025A818(void){ s32 func_8025A864(enum comusic_e track_id){ CoMusic *trackPtr; - trackPtr = __find_track(track_id); + trackPtr = findTrack(track_id); if (trackPtr != NULL && trackPtr->unkC == 0 && trackPtr->volume <= 0){ func_802599B4(trackPtr); return 1; @@ -465,7 +466,7 @@ s32 func_8025A864(enum comusic_e track_id){ void func_8025A8B8(enum comusic_e track_id, s32 arg1){ CoMusic *trackPtr; - trackPtr = __find_track(track_id); + trackPtr = findTrack(track_id); if (trackPtr != NULL){ trackPtr->unk14 = arg1; } @@ -525,7 +526,7 @@ void func_8025AA48(void){ void func_8025AABC(enum comusic_e track_id){ CoMusic *trackPtr; - if(trackPtr = __find_track(track_id)){ + if(trackPtr = findTrack(track_id)){ trackPtr->unk15 = 1; if(!trackPtr->volume) func_802599B4(trackPtr); @@ -545,17 +546,17 @@ void comusic_8025AB44(enum comusic_e comusic_id, s32 arg1, s32 arg2){ } void comusic_8025AB78(enum comusic_e comusic_id, s32 arg1, s32 arg2, s32 arg3){ - CoMusic *track = __find_track(comusic_id); + CoMusic *track = findTrack(comusic_id); if (!track) return; func_8025AC7C(comusic_id, arg1, arg2, 0.0f, &track->unk1C[arg3], "comusic.c", VER_SELECT(0x3a3, 0x3a4, 0, 0)); } void func_8025ABB8(enum comusic_e comusic_id, s32 arg1, s32 arg2, s32 arg3){ - func_8025AC7C(comusic_id, arg1, arg2, 0.0f, &(__find_track(comusic_id)->unk1C[arg3]), "comusic.c", VER_SELECT(0x3aa, 0x3ab,0,0)); + func_8025AC7C(comusic_id, arg1, arg2, 0.0f, &(findTrack(comusic_id)->unk1C[arg3]), "comusic.c", VER_SELECT(0x3aa, 0x3ab,0,0)); } void func_8025AC20(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, char* arg4, s32 char5){ - func_8025AC7C(comusic_id, arg1, arg2, 0.0f, __find_track(comusic_id)->unk1C, "comusic.c", VER_SELECT(0x3b1, 0x3b2,0,0)); + func_8025AC7C(comusic_id, arg1, arg2, 0.0f, findTrack(comusic_id)->unk1C, "comusic.c", VER_SELECT(0x3b1, 0x3b2,0,0)); } void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void *arg4, char* arg5, s32 arg6){ @@ -564,7 +565,7 @@ void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void s32 *fadeSlot = (s32 *)arg4; //get track location - trackPtr = __find_track(comusic_id); + trackPtr = findTrack(comusic_id); if(trackPtr == NULL) return; @@ -590,7 +591,7 @@ void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void //comusic_trackQueued int func_8025AD7C(enum comusic_e arg0){ - CoMusic * trackPtr = __find_track(arg0); + CoMusic * trackPtr = findTrack(arg0); return (trackPtr == NULL || trackPtr->track_id == -1)? 0 : 1; } @@ -600,7 +601,7 @@ int func_8025ADBC(enum comusic_e arg0){ } s32 func_8025ADD4(enum comusic_e id){ - CoMusic * ptr = __find_track(id); + CoMusic * ptr = findTrack(id); return ptr - D_80276E30; } @@ -615,7 +616,7 @@ void func_8025AE50(s32 arg0, f32 arg1){ } void func_8025AEA0(enum comusic_e track_id, s32 arg1){ - CoMusic *ptr = __find_track(track_id); + CoMusic *ptr = findTrack(track_id); if(!ptr) return; func_8024FDDC(ptr - D_80276E30, arg1); diff --git a/src/core1/musicplayer.h b/src/core1/musicplayer.h new file mode 100644 index 000000000..1fd913058 --- /dev/null +++ b/src/core1/musicplayer.h @@ -0,0 +1,7 @@ +// BanjoDecomp: core1/musicplayer.h +#ifndef BANJO_KAZOOIE_MUSICPLAYER_H +#define BANJO_KAZOOIE_MUSICPLAYER_H + +#define MAX_MUSIC_STRUCT_COUNT 6 + +#endif // BANJO_KAZOOIE_MUSICPLAYER_H diff --git a/src/core1/n_audio/n_csplayer.c b/src/core1/n_audio/n_csplayer.c index 7a2cf5eda..a92c0852d 100644 --- a/src/core1/n_audio/n_csplayer.c +++ b/src/core1/n_audio/n_csplayer.c @@ -9,7 +9,7 @@ #include #include -extern void __assert(const char *, const char *, int); +//extern void __assert(const char *, const char *, int); void n_alSynSetVol( N_ALVoice *v, s16 volume, ALMicroTime t); s16 __n_vsVol(ALVoiceState *voice, ALSeqPlayer *seqp); ALVoiceState *__n_lookupVoice(ALSeqPlayer *, u8, u8); diff --git a/src/core1/n_audio/n_env.c b/src/core1/n_audio/n_env.c index aafaea970..c1671f37b 100644 --- a/src/core1/n_audio/n_env.c +++ b/src/core1/n_audio/n_env.c @@ -3,7 +3,7 @@ #include "n_synth.h" #include "functions.h" #include "variables.h" -#include "assert.h" +#include "ultra_assert.h" Acmd *n_alResamplePull(N_PVoice *e, s16 *outp, Acmd *p); diff --git a/src/core1/n_audio/n_seqplayer.c b/src/core1/n_audio/n_seqplayer.c index 5577b44de..71735dac4 100644 --- a/src/core1/n_audio/n_seqplayer.c +++ b/src/core1/n_audio/n_seqplayer.c @@ -2,7 +2,7 @@ #include #include "n_synth.h" #include "file_and_line.h" -#include "assert.h" +#include "ultra_assert.h" //#include #include // #include "functions.h" diff --git a/src/core1/overlay.c b/src/core1/overlay.c index a727190ae..c5a76f83e 100644 --- a/src/core1/overlay.c +++ b/src/core1/overlay.c @@ -2,8 +2,7 @@ #include #include "boot/overlaytable.h" #include "core1/core1.h" -#include "functions.h" -#include "variables.h" +#include "checksums.h" extern u8 gHeapBase; extern u32 D_8027BF2C; @@ -20,7 +19,7 @@ void overlay_load( #if 0 void *compressed_buffer; u32 crc2, crc1; - u32 *tmp; + struct overlay_checksums_s *checksums; osWritebackDCacheAll(); osInvalDCache(ram_start, ram_end - ram_start); @@ -50,11 +49,11 @@ void overlay_load( bzero(bss_start, bss_end - bss_start); osWritebackDCacheAll(); - tmp = (u32*) bss_start; - tmp[0] = crc1; - tmp[1] = crc2; - tmp[2] = D_8027BF2C; - tmp[3] = D_8027BF30; + checksums = (struct overlay_checksums_s *) bss_start; + checksums->text_checksum1 = crc1; + checksums->text_checksum2 = crc2; + checksums->data_checksum1 = D_8027BF2C; + checksums->data_checksum2 = D_8027BF30; } #endif } diff --git a/src/core1/io/pfsmanager.c b/src/core1/pfsmanager.c similarity index 93% rename from src/core1/io/pfsmanager.c rename to src/core1/pfsmanager.c index 0c56322bc..8d87bdebb 100644 --- a/src/core1/io/pfsmanager.c +++ b/src/core1/pfsmanager.c @@ -2,33 +2,24 @@ #include #include "core1/core1.h" #include "functions.h" +#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "core1/pfsmanager.h" #include "version.h" +#include "checksums.h" +#include "port/DevTools/ThreadWatchdog.h" +#include "port/OS/OS.h" #include "port/Patches/Patches.h" #define PFSMANAGER_THREAD_STACK_SIZE 0x200 -extern struct { - u8 pad0[4]; - s32 unk4; - u8 pad8[4]; - s32 unkC; -} D_80379B90; - extern s32 D_803727F4; extern s32 D_80276574; -/* .data */ -#if VERSION == VERSION_USA_1_0 - s32 D_80275D30 = 0xC3A68832; //WHAT IS THIS? - s32 D_80275D34 = 0xDDC3A724; //WHAT IS THIS? -#elif VERSION == VERSION_PAL - s32 D_80275D30 = 0xED7BCDB7; //WHAT IS THIS? - s32 D_80275D34 = 0xF82DC7AC; //WHAT IS THIS? -#endif +s32 D_80275D30 = VER_SELECT(0xC3A68832, 0xED7BCDB7, 0, 0); // CCW_DATA_CRC2 +s32 D_80275D34 = VER_SELECT(0xDDC3A724, 0xF82DC7AC, 0, 0); // FIGHT_DATA_CRC2 static s32 D_80275D38 = 0; @@ -65,7 +56,7 @@ f32 func_8024E420(s32 arg0, s32 arg1, s32 arg2) { // instead of 1.0), making it impossible to reach the 0.7 threshold used by // gameSelect.c and other input consumers. Bypassed. #if ANTI_TAMPER - if ((D_80379B90.unk4 != D_803727F4) || (D_80379B90.unkC != D_80276574)) { + if ((gChecksumsCore2.text_checksum2 != D_803727F4) || (gChecksumsCore2.data_checksum2 != D_80276574)) { phi_f2 = 0.00625f; } #endif @@ -176,10 +167,9 @@ void pfsManager_update(void) { osSetThreadPri(0, 0x29); - // [port] On N64, pfsManager_getStartReadData() is called from the RSP/GFX thread - // (code_8C50.c:490) which is #if 0'd on PC. Without it, pfsManagerBusy is never set, - // pfsManager_readData() never fires, and osContGetReadData() never fills the pad data. - // Poll LUS input directly here each frame instead. + // [port] Re-read the latched transaction so the pad data is stable for the + // whole tick; the SI completes reads at its own cadence, and the shaping + // below rewrites this buffer in place. osContGetReadData(pfsManagerContPadData); // [port] Control-scheme input shaping: right stick -> C-button conversion, @@ -306,19 +296,22 @@ void pfsManager_update(void) { } } + CALL_EVENT(OnControllerUpdate); osSetThreadPri(0, 0x14); } void pfsManager_readData(){ func_8024F35C(0); - if(!pfsManagerContStatus.err_no) - osContGetReadData(pfsManagerContPadData); } void pfsManager_entry(void *arg) { do { osRecvMesg(&pfsManagerContPollingMsqQ, 0, 1); + if (OS_ThreadShouldExit()) { // [port] cooperative shutdown + return; + } + ThreadWatchdog_Beat(WATCHDOG_PFSMANAGER); // [port] one beat per SI completion if(pfsManagerBusy == true){ pfsManager_readData(); } @@ -408,6 +401,12 @@ OSMesgQueue *pfsManager_getFrameMesgQ(void){ return &pfsManagerContPollingMsqQ; } +// [port] Watchdog diagnostics: the SI event-registration lock queue +// (func_8024F450 parks here), so blocked waits get a name. +OSMesgQueue *pfsManager_getSiLockQueue(void){ + return &D_802816E8; +} + void func_8024F35C(s32 arg0) { if(!arg0) func_8024F4AC(); @@ -415,7 +414,7 @@ void func_8024F35C(s32 arg0) { func_8024F450(); if(arg0 || D_802816E8.validCount == 1){ - pfsManagerBusy = arg0; + pfsManagerBusy = arg0; } } @@ -435,6 +434,7 @@ OSContPad *func_8024F3F4(void){ void func_8024F400(void) { D_80275D38 = true; osCreateMesgQueue(&D_802816E8, D_80281700, 5); + OS_SetQueueBlocking(&D_802816E8, 1); osSendMesgPtr(&D_802816E8, NULL, OS_MESG_NOBLOCK); } diff --git a/src/core1/stopnswop_payload.c b/src/core1/sns.c similarity index 99% rename from src/core1/stopnswop_payload.c rename to src/core1/sns.c index 2168c8848..6c0e115c9 100644 --- a/src/core1/stopnswop_payload.c +++ b/src/core1/sns.c @@ -1,4 +1,4 @@ -// BanjoDecomp: sns.c +// BanjoDecomp: core1/sns.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core1/stopnswop.c b/src/core1/stopnswop.c index 4564357f4..e5165fac8 100644 --- a/src/core1/stopnswop.c +++ b/src/core1/stopnswop.c @@ -1,4 +1,4 @@ -// BanjoDecomp: sns.c +// BanjoDecomp: core1/code_1D5D0.c #include #include "core1/core1.h" #include "functions.h" @@ -217,7 +217,7 @@ void sns_generate_payload(struct SnsPayload *payload) void sns_write_payload_over_heap(void) { // [port] SNS writes payload to hardcoded N64 RDRAM for cartridge-swap. - // Non-functional on PC — all base payload pointers are NULL. + // Non-functional on PC. #if 0 s32 val2; u32 i; diff --git a/src/core1/syncprintf.c b/src/core1/syncprintf.c deleted file mode 100644 index ae7baf1de..000000000 --- a/src/core1/syncprintf.c +++ /dev/null @@ -1,17 +0,0 @@ -// BanjoDecomp: (unknown decomp origin) -#include -// Lighthouse [port] These functions aren't used so we can remove these includes -//#include -//#include - -void osSyncPrintf(const char *fmt, ...) -{ - int ans; - va_list ap; - // these functions intentionally left blank. ifdeffed out in rom release -} -void rmonPrintf(const char *fmt, ...) -{ - int ans; - va_list ap; -} diff --git a/src/core1/viewport.c b/src/core1/viewport.c index bf5591aed..04a1e2976 100644 --- a/src/core1/viewport.c +++ b/src/core1/viewport.c @@ -45,7 +45,7 @@ f32 viewport_getDistance(f32 arg0[3]) { return ml_vec3f_distance(arg0, sViewportPosition); } -void viewport_getLookbk_vector(f32 arg0[3]) { +void viewport_getLookVector(f32 arg0[3]) { ml_vec3f_copy(arg0, sViewportLookbk_vector); } @@ -100,12 +100,12 @@ void viewport_setRenderPerspectiveMatrix(Gfx **gfx, Mtx **mtx, f32 near, f32 far near = MAX(sViewportNear, near); far = MIN(sViewportFar, far); - // [port] This is either anti-tamper or a legit camera adjustment - // based on NTSC or PAL, because PAL runs at 50Hz instead of 60Hz - // if(*(u32*)OS_PHYSICAL_TO_K1(0x1D8) + 0x53D4FFF0) { - // near = 750.0f; - // far = 1250.0f; - // } +#if ANTI_TAMPER + if ((*(u32*) OS_PHYSICAL_TO_K1(0x000001D8)) + 0x53D4FFF0) { + near = 750.0f; + far = 1250.0f; + } +#endif guPerspective(*mtx, &perspNorm, sViewportFOVy, sViewportAspect, near, far, 0.5f); gSPPerspNormalize((*gfx)++, perspNorm); @@ -490,7 +490,7 @@ f32 viewport_transformCoordinate(f32 x, f32 y, f32 viewport_translation[3], f32 f32 sViewportBackupPosition[3]; f32 sViewportBackupRotation[3]; f32 sViewportBackupFrustumPlanes[4][4]; -f32 sViewportBackupLookbk_vector[3]; +f32 sViewportBackupLookVector[3]; MtxF sViewportBackupMatrix; // ?? @@ -537,7 +537,7 @@ void viewport_backupState(void) { viewport_getPosition_vec3f(sViewportBackupPosition); viewport_getRotation_vec3f(sViewportBackupRotation); viewport_getFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]); - viewport_getLookbk_vector(sViewportBackupLookbk_vector); + viewport_getLookVector(sViewportBackupLookVector); for(i = 0; i < 4; i++){ for(j = 0; j < 4; j++){ @@ -552,7 +552,7 @@ void viewport_restoreState(void) { viewport_setPosition_vec3f(sViewportBackupPosition); viewport_setRotation_vec3f(sViewportBackupRotation); viewport_setFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]); - ml_vec3f_copy(sViewportLookbk_vector, sViewportBackupLookbk_vector); + ml_vec3f_copy(sViewportLookbk_vector, sViewportBackupLookVector); for(i = 0; i < 4; i++){ for(j = 0; j < 4; j++){ diff --git a/src/core1/vimgr.c b/src/core1/vimgr.c index dec23b0aa..257477efd 100644 --- a/src/core1/vimgr.c +++ b/src/core1/vimgr.c @@ -6,7 +6,9 @@ #include "version.h" #include "libultraship/libultra/rcp.h" +#include "port/DevTools/ThreadWatchdog.h" #include "port/Patches/Patches.h" +#include "port/OS/OS.h" #define VIMANAGER_THREAD_STACK_SIZE 0x400 @@ -139,6 +141,9 @@ void viMgr_init(void) { osCreateMesgQueue(&sMesgQueue2, sMesgBuffer2, 1); osCreateMesgQueue(&sMesgQueue3, sMesgBuffer3, FRAMERATE); osViSetEvent(&sMesgQueue1, OS_MESG_PTR(NULL), 1); + OS_SetQueueBlocking(&sMesgQueue1, 1); // viMgr_entry parks here between retraces + OS_SetQueueBlocking(&sMesgQueue2, 1); // the tick parks here for the frame token + OS_SetQueueBlocking(&sMesgQueue3, 1); // and here for its retraces sActiveFramebuffer = 0; D_80280724 = 1; @@ -169,47 +174,42 @@ void viMgr_func_8024BFAC(void){ void viMgr_func_8024BFD8(s32 arg0){ // [port] Set D_80280724 to the actual VI count so time_func_8033DDB8() returns - // the correct delta for demo/playback zoomboxes. On N64 this was set from the - // VI wait loop counter which reflected real rendering time (including lag). - // During demo playback, sDemoViCount includes the N64's original rendering lag - // for maps that ran slow, which the zoombox dialog system needs to pace text. + // the correct delta for demo/playback zoomboxes. s32 demoVi = port_getDemoViCount(); - D_80280724 = (demoVi > 0) ? demoVi : time_getDeltaReal_frames(); -#if 0 static s32 D_80280E90; - + s32 viBudget = (demoVi > 2) ? demoVi : 2; + osSetThreadPri(NULL, 0x7f); defragManager_setPriority(DEFRAGMANAGER_THREAD_PRIORITY_HIGH); - defragManager_80240874(); + defragManager_resume(); if(arg0){ osRecvMesg(&sMesgQueue2, NULL, OS_MESG_BLOCK); } - while(D_802808D8 < viMgr_func_8024BFA0() - D_80280E90){ + while(D_802808D8 < viBudget - D_80280E90){ osRecvMesg(&sMesgQueue3, NULL, OS_MESG_BLOCK); } while(sMesgQueue3.validCount){ osRecvMesg(&sMesgQueue3, NULL, OS_MESG_NOBLOCK); } - + osViSwapBuffer(gFramebuffers[sActiveFramebuffer = getOtherFramebuffer()]); D_80280E90 = 0; while(!(osDpGetStatus() & 2) && osViGetCurrentFramebuffer() != osViGetNextFramebuffer()){ osRecvMesg(&sMesgQueue3, NULL, OS_MESG_BLOCK); D_80280E90++; }//L8024C178 - D_80280724 = D_802808D8; + D_80280724 = (demoVi > 0) ? demoVi : D_802808D8; D_802808D8 = 0; - defragManager_802408B0(); + defragManager_pause(); osSetThreadPri(NULL, 0x14); defragManager_setPriority(DEFRAGMANAGER_THREAD_PRIORITY); -#endif } void viMgr_func_8024C1B4(void){ viMgr_func_8024BFD8(0); - dummy_func_8025AFB8(); + // dummy_func_8025AFB8(); } void viMgr_func_8024C1DC(void){ @@ -237,6 +237,10 @@ void viMgr_entry(void *arg0){ OSMesg sp48; do{ osRecvMesg(&sMesgQueue1, &sp48, OS_MESG_BLOCK); + if (OS_ThreadShouldExit()) { // [port] cooperative shutdown + return; + } + ThreadWatchdog_Beat(WATCHDOG_VIMGR); // [port] one beat per retrace thread5_checkAndExecutePreNMI(); D_802808D8++; if(D_802808D8 == 420){ @@ -256,7 +260,6 @@ void viMgr_entry(void *arg0){ void viMgr_setScreenBlack(s32 active) { osViBlack(active); - port_setViBlack(active); } void viMgr_clearFramebuffers(void) { @@ -271,6 +274,25 @@ s32 viMgr_func_8024C4E8(void) { return D_802808D8; } +// [port] Watchdog diagnostics: unsynchronized snapshot of the pacing state. +void viMgr_getWatchdogState(ViMgrWatchdogState *out) { + out->retraceCount = D_802808D8; + out->q1Count = sMesgQueue1.validCount; + out->q2Count = sMesgQueue2.validCount; + out->q3Count = sMesgQueue3.validCount; +} + +// [port] Watchdog diagnostics: queue identities, so blocked waits get names. +OSMesgQueue *viMgr_getRetraceQueue(void) { + return &sMesgQueue1; +} +OSMesgQueue *viMgr_getFrameTokenQueue(void) { + return &sMesgQueue2; +} +OSMesgQueue *viMgr_getTickRetraceQueue(void) { + return &sMesgQueue3; +} + void viMgr_func_8024C4F8(s32 arg0) { D_802808D8 = arg0; } diff --git a/src/core2/abilityprogress.c b/src/core2/abilityprogress.c index a79fc8c97..5d08de3a5 100644 --- a/src/core2/abilityprogress.c +++ b/src/core2/abilityprogress.c @@ -14,6 +14,12 @@ static struct { #define abilityprogress_learnedAbilities abilityprogress.learned #define abilityprogress_usedAbilities abilityprogress.used +// [port] The tutorial's flags and dialogs belong to Spiral Mountain, but a romhack may +// place it in any map of that level, so gate on the level rather than one map id. +static s32 inSpiralMountain(void){ + return map_getLevel(gsworld_getMap()) == LEVEL_B_SPIRAL_MOUNTAIN; +} + void ability_use(s32 arg0){ s32 sp2C; s32 sp28; @@ -27,32 +33,32 @@ void ability_use(s32 arg0){ switch(arg0){ case ABILITY_USED_JUMP: // [port] guard with SM check — flags collide with map-specific usage in other worlds (e.g. BGS switches) - if (gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) + if (inSpiralMountain()) mapSpecificFlags_set(8, true); sp28 = 1; break; case ABILITY_USED_FLAP: - if (gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) + if (inSpiralMountain()) mapSpecificFlags_set(9, true); sp28 = 1; break; case ABILITY_USED_FLIP: - if (gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) + if (inSpiralMountain()) mapSpecificFlags_set(0xa, true); sp28 = 1; break; case ABILITY_USED_SWIM: - if(gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN){ + if(inSpiralMountain()){ sp2C = ASSET_DFC_BOTTLES_UNDERWATER_TUTORIAL; } break; case ABILITY_USED_CLIMB: - if(gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN){ + if(inSpiralMountain()){ sp2C = ASSET_E02_DIALOG_BOTTLES_CLIMB_OTHER; } break; case ABILITY_USED_BEAK_BARGE: - if(gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN){ + if(inSpiralMountain()){ sp2C = ASSET_E05_DIALOG_BOTTLES_KAZOOIE_BARGE; } break; @@ -115,12 +121,20 @@ void ability_clearAll(void){ abilityprogress_usedAbilities = 0; } -void ability_setLearned(s32 move, s32 val){ +void ability_setLearnedEx(s32 move, s32 val, s32 triggerEvent){ + s32 prev = (abilityprogress_learnedAbilities >> move) & 1; if(val){ abilityprogress_learnedAbilities |= (1 << move); }else{ abilityprogress_learnedAbilities &= ~(1 << move); } + if(triggerEvent && prev != (val ? 1 : 0)){ + CALL_EVENT(OnAbilityLearned, move, val ? 1 : 0); + } +} + +void ability_setLearned(s32 move, s32 val){ + ability_setLearnedEx(move, val, 1); } void ability_setAllLearned(s32 val){ diff --git a/src/core2/actor_array.c b/src/core2/actor_array.c index e681a9dab..7c6aa9ee8 100644 --- a/src/core2/actor_array.c +++ b/src/core2/actor_array.c @@ -1,11 +1,14 @@ +// BanjoDecomp: core2/code_9E370.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" #include "actor.h" #include "prop.h" -#include "port/Enhancements/NoteRetention/NoteRetention.h" +#include "port/Enhancements/Retention/Retention.h" +#include "port/Patches/Patches.h" extern s32 D_80370990; extern f32 GameEngine_GetAspectRatio(void); @@ -28,7 +31,6 @@ f32 player_getYaw(void); extern void func_8032B3A0(Actor *, ActorMarker *); extern void func_8032EE0C(GenFunction_2, uintptr_t); extern void func_8032EE20(void); -extern void __spawnQueue_add_5(GenFunction_5, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); void func_8032A6A8(Actor *arg0); @@ -53,6 +55,12 @@ typedef struct { s16 unkE; }Actorlocal_Core2_9E370; +// [port] Sized ahead of demand so actor_new never bk_reallocs (relocates) the array mid-map. +// The marker pool is the binding limit (see ACTOR_POOL_SIZE); the grow chunk only exists so +// the array stays large enough to hold whatever the pool handed out, never the other way round. +#define ACTOR_ARRAY_INITIAL_CAP ACTOR_POOL_SIZE +#define ACTOR_ARRAY_GROW_CHUNK 128 + /* .data */ ActorArray *suBaddieActorArray = NULL; //actorArrayPtr s32 D_8036E564 = 0; @@ -187,13 +195,13 @@ void func_803255FC(Actor *this) { } break; } - func_8033A45C(1, this->unk124_3 + 1); - func_8033A45C(2, this->unk124_3 + 1); + modelRender_setAppendageVisibility(1, this->unk124_3 + 1); + modelRender_setAppendageVisibility(2, this->unk124_3 + 1); } void func_80325760(Actor *this) { - func_8033A45C(1, 4); - func_8033A45C(2, 4); + modelRender_setAppendageVisibility(1, 4); + modelRender_setAppendageVisibility(2, 4); } // [port] In widescreen, actors outside the 4:3 frustum are still drawn but @@ -371,6 +379,7 @@ Actor *func_80325F2C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { return actor_drawFullDepth(marker, gfx, mtx, vtx); } +// CCW Unknown Update Function void func_80325F84(Actor *this){} void func_80325F8C(void) { @@ -437,6 +446,8 @@ void actorArray_free(void) { // [port] Note retention: every note actor is about to be freed, so drop our // live-actor tracking (markers are being released here). port_noteRetention_onActorsFreed(); + port_remoteCarry_reset(); + port_anchorDummies_onActorsFreed(); if (suBaddieActorArray != NULL) { for(var_s0 = suBaddieActorArray->data; var_s0 < &suBaddieActorArray->data[suBaddieActorArray->cnt]; var_s0++){ @@ -568,12 +579,15 @@ void func_803268B4(void) { if (!actor->despawn_flag) { if (marker->unk2C_2) { marker->actorUpdate2Func(actor); + // [port] Update may have spawned actors, reallocating the array; re-fetch the slot. + actor = &suBaddieActorArray->data[temp_v1]; if (anim_ctrl != NULL) { actor->sound_timer = anctrl_getAnimTimer(anim_ctrl); } } else if (!temp_s1 || (temp_s1 && func_803296D8(actor, temp_s1))) { if ( marker->actorUpdateFunc != NULL) { marker->actorUpdateFunc(actor); + actor = &suBaddieActorArray->data[temp_v1]; // [port] re-fetch: see above if (anim_ctrl != NULL) { actor->sound_timer = anctrl_getAnimTimer(anim_ctrl); } @@ -788,6 +802,8 @@ void func_803272D0(f32 arg0[3], f32 arg1, s32 arg2, int (*arg3)(Actor *)){ } Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ + // [port] Romhacks rewrite spawn args per actor id before the real work + romhack_RewriteActorSpawn(actorInfo, &flags); ActorAnimationInfo * sp54; s32 i; f32 sp44[3]; @@ -801,13 +817,13 @@ Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ s32 pos_copy[3] = { pos_x, pos_y, pos_z }; if(suBaddieActorArray == NULL){ - suBaddieActorArray = (ActorArray *)bk_malloc(sizeof(ActorArray) + 20*sizeof(Actor)); + suBaddieActorArray = (ActorArray *)bk_malloc(sizeof(ActorArray) + ACTOR_ARRAY_INITIAL_CAP*sizeof(Actor)); suBaddieActorArray->cnt = 0; - suBaddieActorArray->max_cnt = 20; + suBaddieActorArray->max_cnt = ACTOR_ARRAY_INITIAL_CAP; } if(suBaddieActorArray->cnt + 1 > suBaddieActorArray->max_cnt){ - suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 5; + suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + ACTOR_ARRAY_GROW_CHUNK; suBaddieActorArray = (ActorArray *)bk_realloc(suBaddieActorArray, sizeof(ActorArray) + suBaddieActorArray->max_cnt*sizeof(Actor)); } @@ -1084,11 +1100,7 @@ static void __actor_free(ActorMarker *arg0, Actor *arg1){ //remove last actor from actor array suBaddieActorArray->cnt--; - //shrink actor array capacity - if(suBaddieActorArray->cnt + 8 <= suBaddieActorArray->max_cnt){ - suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 4; - suBaddieActorArray = (ActorArray *)bk_realloc(suBaddieActorArray, suBaddieActorArray->max_cnt*sizeof(Actor) + sizeof(ActorArray)); - } + // [port] Never shrink the array; keeps the pre-sized headroom from actor_new so pointers stay stable. marker_free(arg0); } @@ -1158,13 +1170,38 @@ void marker_despawn(ActorMarker *marker){ } } else{ + // [port] Shadow-link cleanup for immediate-mode despawns. + if(actor->unk104){ + if(actor->modelCacheIndex != 0x108){ + // Freeing a shadow-owner: unlink and free its shadow too. + ActorMarker *shadowMarker = actor->unk104; + Actor *shadow = marker_getActor(shadowMarker); + shadow->unk104 = NULL; + actor->unk104 = NULL; + __actor_free(shadowMarker, shadow); + // Swap-remove may have relocated this actor; re-fetch through the marker. + actor = marker_getActor(marker); + } + else{ + // Freeing a shadow directly: sever the owner's link too. + marker_getActor(actor->unk104)->unk104 = NULL; + actor->unk104 = NULL; + } + } __actor_free(marker, actor); } } void func_803283BC(void){ D_8036E574 = 1; - D_8036E578 = 0; +} + +void port_actorDespawn_beginDefer(void){ + D_8036E574 = 1; +} + +void port_actorDespawn_endDefer(void){ + D_8036E574 = 0; } //actorArray_flushDespawns @@ -1509,14 +1546,14 @@ bool func_803292E0(Actor *this){ return 1; } - _player_getPosition(player_position); + playerPosition_get(player_position); return func_80307258(player_position, this->unk10_25 - 1, this->unk10_18 - 1) != -1; } bool func_80329354(Actor *this){ f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); return func_80329260(this, sp1C); } @@ -1526,7 +1563,7 @@ bool func_80329384(Actor *this, f32 arg1){ if(this->unk10_25 == 0) return true; - _player_getPosition(sp1C); + playerPosition_get(sp1C); return func_80307258(sp1C, this->unk10_25 - 1, this->unk10_18 - 1) != -1 && (sp1C[1] < (this->position[1] + arg1)) @@ -1573,14 +1610,14 @@ bool subaddie_playerIsWithinSphereAndActive(Actor *this, s32 dist){ bool subaddie_playerIsWithinSphere(Actor *this, s32 dist){ f32 sp24[3]; - f32 sp18[3]; + f32 player_position[3]; func_8028E964(sp24); - _player_getPosition(sp18); - sp24[1] = sp18[1]; - if( ( (this->position_x - sp24[0])*(this->position_x - sp24[0]) - + (this->position_y - sp24[1])*(this->position_y - sp24[1]) - + (this->position_z - sp24[2])*(this->position_z - sp24[2]) + playerPosition_get(player_position); + sp24[1] = player_position[1]; + if( ( (this->position_x - sp24[0]) * (this->position_x - sp24[0]) + + (this->position_y - sp24[1]) * (this->position_y - sp24[1]) + + (this->position_z - sp24[2]) * (this->position_z - sp24[2]) ) < dist*dist ){ return true; @@ -1619,7 +1656,7 @@ s32 func_8032970C(Actor *this){ f32 plyr_pos[3]; func_8028E964(sp24); - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); sp24[1] = plyr_pos[1]; return (s32) DIST_SQ_VEC3F(this->position, sp24); } @@ -1636,12 +1673,12 @@ s32 subaddie_getYawToPosition(Actor *arg0, f32 arg1[3]){ } void func_803297FC(Actor *arg0, f32 *o1, f32 *o2){ - f32 sp2C[3]; + f32 player_pos[3]; - _player_getPosition(sp2C); - func_8025727C( + playerPosition_get(player_pos); + ml_horizontal_and_vertical_angles( arg0->position[0], arg0->position[1], arg0->position[2], - sp2C[0], sp2C[1], sp2C[2], + player_pos[0], player_pos[1], player_pos[2], o1, o2 ); *o1 = 360.0f - *o1; @@ -1901,9 +1938,13 @@ void actors_applyFromSavestate(void *savestate_ptr, ActorListSaveState *savestat pad = savestate_actor->yaw; CALL_CANCELLABLE_EVENT(OnLoadActorSaveState, savestate_actor, sp50[0], sp50[1], sp50[2]) { temp_v0_6 = actor_spawnWithYaw_s32(savestate_actor->modelCacheIndex, &sp50, pad); - actor_copy(savestate_actor, temp_v0_6); - func_80329B68(temp_v0_6); - func_803299B4(temp_v0_6); + // [port] The spawn is nullable: the id may not be spawnable here, and a + // cancelled OnActorSpawn returns whatever the listener supplied, including NULL. + if (temp_v0_6 != NULL) { + actor_copy(savestate_actor, temp_v0_6); + func_80329B68(temp_v0_6); + func_803299B4(temp_v0_6); + } } } savestate_actor++; @@ -1977,7 +2018,7 @@ void func_8032A82C(Actor *arg0, s32 arg1) { sp1C = (Actorlocal_Core2_9E370 *)arg0->local; sp24 = nodeprop_findByActorIdAndActorPosition(arg1, arg0); if (sp24 != NULL) { - sp1C->unkC = nodeprop_getYaw(sp24); + sp1C->unkC = nodeProp_getYaw(sp24); nodeprop_getPosition(sp24, sp1C->unk0); sp1C->unkE = func_80341EC4(sp1C->unk0); } @@ -2218,6 +2259,36 @@ ActorMarker *func_8032B16C(enum jiggy_e jiggy_id) { } } +ActorMarker *actorArray_findHoneycombMarkerById(enum honeycomb_e id) { + Actor* base; + Actor* var_s0; + + if (suBaddieActorArray != NULL) { + base = &suBaddieActorArray->data[0]; + for (var_s0 = base; (var_s0 - base) < suBaddieActorArray->cnt; var_s0++) { + if ((var_s0->marker->id == MARKER_53_EMPTY_HONEYCOMB) && (func_802CA1C4(var_s0) == id)) { + return var_s0->marker; + } + } + } + return NULL; +} + +ActorMarker *actorArray_findMumboTokenMarkerById(enum mumbotoken_e id) { + Actor* base; + Actor* var_s0; + + if (suBaddieActorArray != NULL) { + base = &suBaddieActorArray->data[0]; + for (var_s0 = base; (var_s0 - base) < suBaddieActorArray->cnt; var_s0++) { + if ((var_s0->marker->id == MARKER_39_MUMBO_TOKEN) && (func_802E0CB0(var_s0) == id)) { + return var_s0->marker; + } + } + } + return NULL; +} + void func_8032B258(Actor *this, enum collision_e arg1) { f32 sp44; f32 sp38[3]; diff --git a/src/core2/actor_cleanup.c b/src/core2/actor_cleanup.c index 152b831b7..8b0a8f89d 100644 --- a/src/core2/actor_cleanup.c +++ b/src/core2/actor_cleanup.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_DC4B0.c #include #include "functions.h" #include "variables.h" @@ -5,7 +6,9 @@ void func_80363500(Actor *this); /* .data */ -ActorInfo D_80373DC0= { +// Next To SM Bridge Bottles +// Gets removed when player learns all SM Moves +ActorInfo D_80373DC0 = { 0x1EE, ACTOR_3BA_UNKNOWN, 0, 0, NULL, func_80363500, actor_update_func_80326224, func_80325340, diff --git a/src/core2/actor_cubepropsystem.c b/src/core2/actor_cubepropsystem.c index 466e31455..4f778b6f4 100644 --- a/src/core2/actor_cubepropsystem.c +++ b/src/core2/actor_cubepropsystem.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/code_A5BC0.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "enums.h" +#include "actor.h" #include #include "port/Patches/Patches.h" @@ -12,8 +14,8 @@ extern int ResourceMgr_IsModelAsset(uint32_t assetId); #define AssetCacheSize 0x3D5 -// Port Expand Marker Pool for Rando Allocation -#define MARKER_POOL_SIZE 0x1C0 +// [port] Expand Marker Pool for Rando Allocation +#define MARKER_POOL_SIZE ACTOR_POOL_SIZE #define MARKER_BITMAP_BYTES (MARKER_POOL_SIZE / 8) extern bool func_802E74A0(f32[3], f32, f32[3], f32[3]); @@ -28,7 +30,7 @@ extern BKCollisionTriangle *collisionList_func_802E805C(BKCollisionList *, BKVer extern NodeProp *func_803080C8(s32 arg0); extern Cube *func_80308224(void); extern Cube *func_8030364C(void); -extern Cube *cube_atPosition_s32(s32 position[3]); +extern Cube *cubeList_GetCubeAtPosition_s32(s32 position[3]); extern f32 propModelList_getScale(Prop *); extern void propModelList_setScale(Prop *, f32); @@ -118,7 +120,7 @@ BKCollisionTriangle *D_80383420; u8 D_80383428[MARKER_BITMAP_BYTES]; s32 D_80383444; int D_80383448; -s32 D_80383450[0x40]; +s32 D_80383450[CUBE_SORT_SCRATCH_SIZE]; bk_vector(ActorMarker *) *D_80383550; bk_vector(ActorMarker *) *D_80383554; Method_Core2_A5BC0 D_80383558; @@ -137,6 +139,11 @@ void __cube_sort(Cube *cube, bool global) { s32 i; Prop *new_var; + // [port] Sorting is only draw order; skip rather than overrun the scratch. + if (cube->prop2Cnt > CUBE_SORT_SCRATCH_SIZE) { + return; + } + if (cube->prop2Cnt >= 2) { if (global == 0) { viewport_getPosition_vec3w(ref_position); //distance from viewport @@ -155,6 +162,9 @@ void __cube_sort(Cube *cube, bool global) { } //sort prop list + // [port] Cancelled by PerfPatches.cpp, which sorts the same distances + // with a stable insertion sort instead of this exchange sort. + if (EventSystem_Should(VB_CUBE_PROP_SORT, true, cube)) { start_prop = cube->prop2Ptr; var_t0 = cube->prop2Ptr + (cube->prop2Cnt - 1); do { @@ -193,6 +203,7 @@ void __cube_sort(Cube *cube, bool global) { i++; } } while (start_prop != NULL); + } code_A5BC0_initCubePropActorProp(cube); } } @@ -275,8 +286,7 @@ void func_8032CD60(Prop *prop) { } else { sp3C = prop->spriteProp.isMirrored; } - if (1); - break; + if (1) break; } break; @@ -314,7 +324,7 @@ static void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx){ f32 draw_dist_f; f32 percentage; - FrameInterpolation_RecordOpenChild(this, this->actrArrayIdx); + FrameInterpolation_RecordOpenChildHash3("marker", (uintptr_t)this, (uintptr_t)this->actrArrayIdx, 0); if(!this->unk3E_0){ this->drawFunc(this, gfx, mtx, vtx); @@ -364,17 +374,19 @@ void func_8032D3A8(void){ bk_vector_clear(D_80383554); } -void func_8032D3D8(Gfx **gdl, Mtx **mptr, Vtx **vptr){ +void core2_A5BC0_drawUnknownMarkers(Gfx **gfx, Mtx **mtx, Vtx **vtx) { // further investigation needed what's drawn here int i; - for(i = 0; i < bk_vector_size(D_80383550); i++){ - __marker_draw(*(ActorMarker **) bk_vector_at(D_80383550, i), gdl, mptr, vptr); + + for (i = 0; i < bk_vector_size(D_80383550); i++) { + __marker_draw(*(ActorMarker **) bk_vector_at(D_80383550, i), gfx, mtx, vtx); } } -void func_8032D474(Gfx **gdl, Mtx **mptr, Vtx **vptr){ +void core2_A5BC0_drawScreenOverlayMarkers(Gfx **gfx, Mtx **mtx, Vtx **vtx) { int i; - for(i = 0; i < bk_vector_size(D_80383554); i++){ - __marker_draw(*(ActorMarker **) bk_vector_at(D_80383554, i), gdl, mptr, vptr); + + for (i = 0; i < bk_vector_size(D_80383554); i++) { + __marker_draw(*(ActorMarker **) bk_vector_at(D_80383554, i), gfx, mtx, vtx); } } @@ -509,14 +521,20 @@ s32 func_8032D9C0(Cube *cube, Prop* prop){ s32 tmp; sp24 = 0; - if(cube->prop2Cnt != 0){ + if(cube != NULL && cube->prop2Cnt != 0 && prop != NULL && cube->prop2Ptr != NULL){ + ptrdiff_t index = prop - cube->prop2Ptr; + // [port] A stale propPtr makes elementsAfter enormous; drop the removal instead. + if (index < 0 || index >= (ptrdiff_t)cube->prop2Cnt) { + port_warnPropNotInCube((s32)index, (s32)cube->prop2Cnt); + return sp24; + } + sp24 = prop->unk8_1; if(func_80305D14()){ func_80305CD8(func_803058C0(prop->unk4[1]), -1); } // port - Rando manipulation of prop2Ptr results in mismatched data, this corrects that. - ptrdiff_t index = prop - cube->prop2Ptr; ptrdiff_t elementsAfter = (cube->prop2Cnt - 1) - index; if (elementsAfter > 0) { memmove(prop, prop + 1, elementsAfter * sizeof(Prop)); @@ -939,6 +957,11 @@ static void __codeA5BC0_initPropPointerForCube(NodeProp *node, Cube *cube, s32 c } } + // [port] unk0_4 is the front index of this partition; :5 wrapped it here. + if(cube->unk0_4 > 31){ + port_warnNodePropSplit(cube->unk0_4, cnt); + } + bk_free(node); for(i = 0; i < cnt; i++){ @@ -999,6 +1022,9 @@ void code7AF80_initCubeFromFile(File *file_ptr, Cube *cube) { // bitfield structs across endianness boundaries. if (file_isNextByteExpected(file_ptr, CUBE_PROP_2_LIST_START_INDICATOR)) { s32 i; + // [port] A vetoed prop must not keep its slot. Compact + // instead, writing only the props we keep. + s32 writeIdx = 0; memset(cube->prop2Ptr, 0, sp47 * sizeof(Prop)); for (i = 0; i < sp47; i++) { u8 raw[12]; @@ -1029,58 +1055,60 @@ void code7AF80_initCubeFromFile(File *file_ptr, Cube *cube) { bool b4 = (flags >> 4) & 1; // unk8_4 bool b5 = (flags >> 5) & 1; // unk8_5 // Set position and flags via anonymous struct - cube->prop2Ptr[i].unk4[0] = pos[0]; - cube->prop2Ptr[i].unk4[1] = pos[1]; - cube->prop2Ptr[i].unk4[2] = pos[2]; - cube->prop2Ptr[i].markerFlag = mf; - cube->prop2Ptr[i].unk8_1 = b1; - cube->prop2Ptr[i].unk8_2 = b2; - cube->prop2Ptr[i].unk8_3 = b3; - cube->prop2Ptr[i].unk8_4 = b4; - cube->prop2Ptr[i].unk8_5 = b5; + cube->prop2Ptr[writeIdx].unk4[0] = pos[0]; + cube->prop2Ptr[writeIdx].unk4[1] = pos[1]; + cube->prop2Ptr[writeIdx].unk4[2] = pos[2]; + cube->prop2Ptr[writeIdx].markerFlag = mf; + cube->prop2Ptr[writeIdx].unk8_1 = b1; + cube->prop2Ptr[writeIdx].unk8_2 = b2; + cube->prop2Ptr[writeIdx].unk8_3 = b3; + cube->prop2Ptr[writeIdx].unk8_4 = b4; + cube->prop2Ptr[writeIdx].unk8_5 = b5; if (mf) { // ActorProp: marker=NULL (set at actor spawn), position - cube->prop2Ptr[i].actorProp.marker = NULL; - cube->prop2Ptr[i].actorProp.x = pos[0]; - cube->prop2Ptr[i].actorProp.y = pos[1]; - cube->prop2Ptr[i].actorProp.z = pos[2]; + cube->prop2Ptr[writeIdx].actorProp.marker = NULL; + cube->prop2Ptr[writeIdx].actorProp.x = pos[0]; + cube->prop2Ptr[writeIdx].actorProp.y = pos[1]; + cube->prop2Ptr[writeIdx].actorProp.z = pos[2]; // SpriteProp unk8_10/unk8_15 overlap anonymous pad8_15 - cube->prop2Ptr[i].actorProp.frame = (flags >> 11) & 0x1F; - cube->prop2Ptr[i].actorProp.unk8_10 = (flags >> 6) & 0x1F; + cube->prop2Ptr[writeIdx].actorProp.frame = (flags >> 11) & 0x1F; + cube->prop2Ptr[writeIdx].actorProp.unk8_10 = (flags >> 6) & 0x1F; } else if (b1) { // ModelProp: word0 = { u16 unk0, u8 unk0_15, u8 unk0_7 } // [port] Set through bitfield accessor, not raw u16, for LE correctness - cube->prop2Ptr[i].modelProp.modelId = (word0 >> 20) & 0xFFF; - cube->prop2Ptr[i].modelProp.pad0_19 = (word0 >> 16) & 0xF; - cube->prop2Ptr[i].modelProp.yaw = (u8)(word0 >> 8); - cube->prop2Ptr[i].modelProp.roll = (u8)(word0); + cube->prop2Ptr[writeIdx].modelProp.modelId = (word0 >> 20) & 0xFFF; + cube->prop2Ptr[writeIdx].modelProp.pad0_19 = (word0 >> 16) & 0xF; + cube->prop2Ptr[writeIdx].modelProp.yaw = (u8)(word0 >> 8); + cube->prop2Ptr[writeIdx].modelProp.roll = (u8)(word0); // ModelProp flags at offset 10-11 - cube->prop2Ptr[i].modelProp.scale = (u8)(flags >> 8); - cube->prop2Ptr[i].modelProp.unkB_5 = (flags >> 5) & 1; - cube->prop2Ptr[i].modelProp.unkB_4 = (flags >> 4) & 1; + cube->prop2Ptr[writeIdx].modelProp.scale = (u8)(flags >> 8); + cube->prop2Ptr[writeIdx].modelProp.unkB_5 = (flags >> 5) & 1; + cube->prop2Ptr[writeIdx].modelProp.unkB_4 = (flags >> 4) & 1; } else { // SpriteProp: word0 is a u32 with bitfields - cube->prop2Ptr[i].spriteProp.spriteId = (word0 >> 20) & 0xFFF; - cube->prop2Ptr[i].spriteProp.unk0_19 = (word0 >> 19) & 1; - cube->prop2Ptr[i].spriteProp.rgb_remove_red = (word0 >> 16) & 7; - cube->prop2Ptr[i].spriteProp.rgb_remove_green = (word0 >> 13) & 7; - cube->prop2Ptr[i].spriteProp.rgb_remove_blue = (word0 >> 10) & 7; - cube->prop2Ptr[i].spriteProp.scale = (word0 >> 2) & 0xFF; - cube->prop2Ptr[i].spriteProp.isMirrored = (word0 >> 1) & 1; - cube->prop2Ptr[i].spriteProp.pad0_0 = word0 & 1; + cube->prop2Ptr[writeIdx].spriteProp.spriteId = (word0 >> 20) & 0xFFF; + cube->prop2Ptr[writeIdx].spriteProp.unk0_19 = (word0 >> 19) & 1; + cube->prop2Ptr[writeIdx].spriteProp.rgb_remove_red = (word0 >> 16) & 7; + cube->prop2Ptr[writeIdx].spriteProp.rgb_remove_green = (word0 >> 13) & 7; + cube->prop2Ptr[writeIdx].spriteProp.rgb_remove_blue = (word0 >> 10) & 7; + cube->prop2Ptr[writeIdx].spriteProp.scale = (word0 >> 2) & 0xFF; + cube->prop2Ptr[writeIdx].spriteProp.isMirrored = (word0 >> 1) & 1; + cube->prop2Ptr[writeIdx].spriteProp.pad0_0 = word0 & 1; // SpriteProp flags - cube->prop2Ptr[i].spriteProp.frame = (flags >> 11) & 0x1F; - cube->prop2Ptr[i].spriteProp.unk8_10 = (flags >> 6) & 0x1F; + cube->prop2Ptr[writeIdx].spriteProp.frame = (flags >> 11) & 0x1F; + cube->prop2Ptr[writeIdx].spriteProp.unk8_10 = (flags >> 6) & 0x1F; } } //Prop* ptr = cube->prop2Ptr + i * sizeof(Prop); - CALL_EVENT(OnPropInit, &cube->prop2Ptr[i]); + CALL_EVENT(OnPropInit, &cube->prop2Ptr[writeIdx]); + writeIdx++; } } + cube->prop2Cnt = writeIdx; } - for(var_v1_2 = cube->prop2Ptr; var_v1_2 < cube->prop2Ptr + sp47; var_v1_2++){ + for(var_v1_2 = cube->prop2Ptr; var_v1_2 < cube->prop2Ptr + cube->prop2Cnt; var_v1_2++){ var_v1_2->unk8_4 = 1; if (var_v1_2->unk8_1) { var_v1_2->unk8_5 = 0; @@ -1220,7 +1248,7 @@ void func_8032F21C(Cube *cube, s32 position[3], ActorMarker *marker, bool arg3) } void func_8032F3D4(s32 arg0[3], ActorMarker *marker, s32 arg2){ - func_8032F21C((marker->unk40_23)? func_8030364C() : cube_atPosition_s32(arg0), arg0, marker, arg2); + func_8032F21C((marker->unk40_23)? func_8030364C() : cubeList_GetCubeAtPosition_s32(arg0), arg0, marker, arg2); } void marker_free(ActorMarker *this){ @@ -1235,7 +1263,7 @@ void func_8032F464(bool arg0){ void func_8032F470(s32 *pos, ActorMarker *arg1){ Cube *cubePtr; - cubePtr = (arg1->unk40_23)? func_8030364C(): cube_atPosition_s32(pos); + cubePtr = (arg1->unk40_23)? func_8030364C(): cubeList_GetCubeAtPosition_s32(pos); if(cubePtr == arg1->cubePtr){ arg1->propPtr->x = pos[0]; @@ -1785,7 +1813,7 @@ BKSpriteDisplayData *func_80330E54(ActorMarker *marker, BKSprite **sprite_ptr) { return 0; } model_cache_ptr = &modelCache[marker_getActor(marker)->modelCacheIndex]; - if (model_cache_ptr->unk4 == 0) { + if (model_cache_ptr->unk4 == 00 || marker->id == MARKER_300_CUSTOM_COLLECTIBLE) { model_cache_ptr->unk4 = codeB3A80_getSprite(marker->modelId, &model_cache_ptr->unk8); } model_cache_ptr->unk10 = globalTimer_getTime(); @@ -1805,19 +1833,19 @@ BKSprite *func_80330F50(ActorMarker * marker){ return sp1C; } -s32 codeA5BC0_getNodePropUnkA(NodeProp *arg0){ +s32 codeA5BC0_getNodePropMarkerId(NodeProp *arg0){ return arg0->unkA; //marker_id } -s32 codeA5BC0_getNodePropBit6(NodeProp *arg0){ +s32 codeA5BC0_getNodePropCategory(NodeProp *arg0){ return arg0->bit6; } -s32 codeA5BC0_getNodePropUnk8(NodeProp *arg0){ +s32 codeA5BC0_getNodePropActorId(NodeProp *arg0){ return arg0->unk8; } -s32 codeA5BC0_getPositionAndReturnRadius(void *arg0_, s32 arg1[3]){ +s32 codeA5BC0_getPositionAndSelectorOrRadius(void *arg0_, s32 arg1[3]){ NodeProp *arg0 = (NodeProp *)arg0_; arg1[0] = arg0->x; arg1[1] = arg0->y; @@ -2203,6 +2231,9 @@ f32 func_80331E64(ActorMarker *marker) { if (marker->modelId == 0) { return 0.0f; } + if (marker->id == MARKER_300_CUSTOM_COLLECTIBLE) { + return 150.0f; + } sp24 = func_80331D20(func_80330F50(marker)); marker->unk38[1] = (s16) (sp24 / 2); if (marker->unk3E_0) { @@ -2426,8 +2457,8 @@ void func_80332894(void) { s32 size; s32 i; - size = 0x579; - D_8036E7C4 = bk_malloc(size); + size = VER_SELECT(0x579, 0x391, 0, 0); + D_8036E7C4 = malloc(size); i = 0; do{ D_8036E7C4[i] = 0; diff --git a/src/core2/actor_motioncurve.c b/src/core2/actor_motioncurve.c index a914ff3a3..eb3518980 100644 --- a/src/core2/actor_motioncurve.c +++ b/src/core2/actor_motioncurve.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_EF50.c #include #include "functions.h" #include "variables.h" @@ -82,15 +83,15 @@ enum bs_e func_80295EE0(enum bs_e arg0){ enum bs_e __get_rebound_state_id(void){ switch(bsStoredState_getTransformation()){ case TRANSFORM_3_PUMPKIN:// L8029606C - return BS_PUMPKIN_BOUNCE; + return BS_A0_ANT_BOUNCE; case TRANSFORM_2_TERMITE:// L80296074 - return BS_ANT_BOUNCE; + return BS_9F_ANT_BOUNCE; case TRANSFORM_5_CROC:// L8029607C - return BS_CROC_BOUNCE; + return BS_A1_CROC_BOUNCE; case TRANSFORM_4_WALRUS:// L80296084 - return BS_WALRUS_BOUNCE; + return BS_A2_WALRUS_BOUNCE; case TRANSFORM_6_BEE:// L8029608C - return BS_BEE_BOUNCE; + return BS_A3_BEE_BOUNCE; case TRANSFORM_1_BANJO:// L80296094 default: if(player_movementGroup() == BSGROUP_A_FLYING) @@ -147,7 +148,7 @@ void func_8029622C(void){ f32 sp34[3]; f32 sp28[3]; - _player_getPosition(sp28); + playerPosition_get(sp28); func_80256E24(sp34, 0.0f, yaw_get(), 0.0f, 0.0f, 100.0f); sp28[0] += sp34[0]; sp28[1] += sp34[1]; @@ -175,29 +176,29 @@ enum bs_e func_802962BC(u32 arg0){ return BS_4E_PUMPKIN_DIE; case TRANSFORM_5_CROC: //L80296344 if(sp1C) - return BS_CROC_OW; + return BS_63_CROC_OW; else - return BS_CROC_OW; + return BS_63_CROC_OW; case TRANSFORM_4_WALRUS: //L8029635C if(sp1C) - return BS_WALRUS_OW; + return BS_6C_WALRUS_OW; else - return BS_WALRUS_DIE; + return BS_6D_WALRUS_DIE; case TRANSFORM_6_BEE: //L80296374 if(sp1C) - return BS_BEE_OW; - return BS_BEE_DIE; + return BS_89_BEE_OW; + return BS_8A_BEE_DIE; case TRANSFORM_1_BANJO: //L8029638C default: if(sp1C){ if(bsbtrot_inSet(bs_getState())) - return BS_BTROT_OW; + return BS_7B_BTROT_OW; if(player_getWaterState() == BSWATERGROUP_2_UNDERWATER) return BS_7F_DIVE_OW; if(player_movementGroup() == BSGROUP_A_FLYING) - return BS_FLY_OW; + return BS_91_FLY_OW; return BS_E_OW; } return BS_41_DIE; @@ -427,7 +428,10 @@ void func_80296608(void){ break; case BS_INTR_35: //L80296984 baflag_set(BA_FLAG_1A_OPEN_NOTEDOOR); - next_state = func_8029B504(); + // The dance masks the fall/land this normally forces; when it's skipped + // (listener clears the flag here), leave the state unchanged so Banjo keeps moving. + if(EventSystem_Should(VB_PLAY_NOTEDOOR_DANCE, true)) + next_state = func_8029B504(); sp2C = 2; break; case BS_INTR_34: //L802969A4 diff --git a/src/core2/actor_updatestub.c b/src/core2/actor_updatestub.c index 7a58ba2f1..d9717b32e 100644 --- a/src/core2/actor_updatestub.c +++ b/src/core2/actor_updatestub.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_4BE10.c #include #include "functions.h" #include "variables.h" @@ -6,13 +7,23 @@ void func_802D2DA0(Actor *this); /* .data */ ActorInfo D_803675F0 = { - 0x16, 0x6A, 0x0, + MARKER_16_UNKNOWN, ACTOR_6A_UNKNOWN, 0x0, 0x1, NULL, func_802D2DA0, func_80326244, func_80325340, 0, 0, 0.0f, 0 }; + s16 D_80367614[] = {3,2,3,4,3,5,3,0}; -ParticleScaleAndLifetimeRanges D_80367624 = {{0.7f, 0.3f}, {0.01f, 0.01f}, {0.05f, 0.05f}, {0.2f, 0.2f}, 0.0f, 0.01f}; + +ParticleScaleAndLifetimeRanges D_80367624 = { + {0.7f, 0.3f}, // particle_starting_scale_range + {0.01f, 0.01f}, // particle_starting_scale_range + {0.05f, 0.05f}, // particle_spawn_interval_range + {0.2f, 0.2f}, // particle_lifetime_range + 0.0f, // particle_fade_in + 0.01f // particle_fade_in +}; + ParticleSettingsVelocityPosition D_8036764C = { {{-100.0f, 400.0f, -100.0f}, { 100.0f, 800.0f, 100.0f}}, {{-100.0f, 0.0f, -100.0f}, { 100.0f, 0.0f, 100.0f}} diff --git a/src/core2/anim/controller.c b/src/core2/anim/anctrl.c similarity index 99% rename from src/core2/anim/controller.c rename to src/core2/anim/anctrl.c index ddfe5013a..0f6a95404 100644 --- a/src/core2/anim/controller.c +++ b/src/core2/anim/anctrl.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/anctrl.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anim_bonetransform.c b/src/core2/anim/anim_bonetransform.c index 6cda545db..f9a2d5f62 100644 --- a/src/core2/anim/anim_bonetransform.c +++ b/src/core2/anim/anim_bonetransform.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B3A80.c #include #include "functions.h" #include "variables.h" @@ -230,8 +231,13 @@ void func_8033B1BC(void){ } void func_8033B268(void){ +#if VERSION == VERSION_USA_1_0 D_80383CE0[0] = (bk_vector(struct21s) *)defrag(D_80383CE0[0]); D_80383CE0[1] = (bk_vector(struct21s) *)defrag(D_80383CE0[1]); +#else + D_80383CE0[0] = (bk_vector(struct21s) *)bk_vector_defrag(D_80383CE0[0]); + D_80383CE0[1] = (bk_vector(struct21s) *)bk_vector_defrag(D_80383CE0[1]); +#endif } void func_8033B2A4(s32 arg0) { diff --git a/src/core2/anim/anim_buffer.c b/src/core2/anim/anim_buffer.c index 97b3f4933..563e0aeca 100644 --- a/src/core2/anim/anim_buffer.c +++ b/src/core2/anim/anim_buffer.c @@ -1,5 +1,7 @@ +// BanjoDecomp: core2/code_2240.c #include #include "functions.h" +#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "animation.h" diff --git a/src/core2/anim/anim_defrag.c b/src/core2/anim/anim_defrag.c index a700817d9..33b82d692 100644 --- a/src/core2/anim/anim_defrag.c +++ b/src/core2/anim/anim_defrag.c @@ -1,5 +1,7 @@ +// BanjoDecomp: core2/code_630D0.c #include #include "functions.h" +#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "animation.h" @@ -31,7 +33,7 @@ MtxF *animMtxList_get(AnimMtxList *this, s32 arg1){ } // [port] bounds check - on N64 this never happens but corrupt data can cause OOB if (arg1 < 0 || arg1 >= this->size) { - BK_LOG_WARN("[port] animMtxList_get: OOB index %d (size=%d)", arg1, this->size); + BK_LOG_WARN("animMtxList_get: OOB index %d (size=%d)", arg1, this->size); return &this->default_matrix; // fallback to identity } return &this->data[arg1]; diff --git a/src/core2/anim/anim_driver.c b/src/core2/anim/anim_driver.c index fdba789b0..7baf7ebe9 100644 --- a/src/core2/anim/anim_driver.c +++ b/src/core2/anim/anim_driver.c @@ -1,66 +1,88 @@ +// BanjoDecomp: core2/code_DA760.c #include #include "functions.h" #include "variables.h" -void func_80361870(Actor *this); +void lairBottlesDialog_update(Actor *this); /* .data */ -ActorInfo D_803731B0 = { +ActorInfo lairBottlesDialog = { 0x1E4, 0x373, 0, 0, NULL, - func_80361870, actor_update_func_80326224, func_80325340, + lairBottlesDialog_update, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 -}; +}; + +enum lairbottlesdialog_specificfield_e { + LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_1_MM = 1, + LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_2_TTC, + LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_3_CC, + LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_4_BGS, + LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_5_FP, + LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_6_GV +}; /* .code */ -int func_803616F0(Actor *this){ +bool lairBottlesDialog_levelOpenedAndNotLearnedAllMoves(Actor *this){ switch(this->actorTypeSpecificField){ - case 1:// L80361728 + case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_1_MM:// L80361728 return fileProgressFlag_get(FILEPROG_31_MM_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_1_MUMBOS_MOUNTAIN); - case 2:// L80361750 + case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_2_TTC:// L80361750 return fileProgressFlag_get(FILEPROG_32_TTC_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_2_TREASURE_TROVE_COVE); - case 3:// L80361778 + case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_3_CC:// L80361778 return fileProgressFlag_get(FILEPROG_33_CC_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_3_CLANKERS_CAVERN); - case 4:// L803617A0 + case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_4_BGS:// L803617A0 return fileProgressFlag_get(FILEPROG_34_BGS_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_4_BUBBLEGLOOP_SWAMP); - case 5:// L803617C8 + case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_5_FP:// L803617C8 return fileProgressFlag_get(FILEPROG_35_FP_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_5_FREEZEEZY_PEAK); - case 6:// L803617F0 + case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_6_GV:// L803617F0 return fileProgressFlag_get(FILEPROG_36_GV_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_7_GOBIS_VALLEY); default: return false; } } -void func_80361828(Actor *this){ - if(volatileFlag_get(VOLATILE_FLAG_16) && level_get() == LEVEL_6_LAIR){ +void lairBottlesDialog_free(Actor *this){ + if(volatileFlag_get(VOLATILE_FLAG_16) + && level_get() == LEVEL_6_LAIR) + { volatileFlag_set(VOLATILE_FLAG_16, 0); } } -void func_80361870(Actor *this){ - s32 text_id; - s32 sp28; +void lairBottlesDialog_update(Actor *this){ + s32 podium_text_id; + s32 didnt_learn_moves_text_id; if(!this->volatile_initialized){ - marker_setFreeMethod(this->marker, func_80361828); - this->volatile_initialized = true; + marker_setFreeMethod(this->marker, lairBottlesDialog_free); + this->volatile_initialized = TRUE; } - if(!this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 400) && !subaddie_playerIsWithinSphereAndActive(this, 50)){ - if(this->actorTypeSpecificField == 1 && !fileProgressFlag_get(FILEPROG_31_MM_OPEN) && level_get() == LEVEL_6_LAIR){ - text_id = fileProgressFlag_get(FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT)? 0xF80 : 0xF7F; - if(gcdialog_showDialog(text_id, 0, 0, 0, 0, 0)){ - this->has_met_before = true; + if(!this->has_met_before + && subaddie_playerIsWithinSphereAndActive(this, 400) + && !subaddie_playerIsWithinSphereAndActive(this, 50)) + { + if(this->actorTypeSpecificField == 1 + && !fileProgressFlag_get(FILEPROG_31_MM_OPEN) + && level_get() == LEVEL_6_LAIR) + { + podium_text_id = fileProgressFlag_get(FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT) ? + VER_SELECT(ASSET_F80_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_AFTER_PODIUM, 0x0AE6, 0, 0) : VER_SELECT(ASSET_F7F_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_BEFORE_PODIUM, 0x0AE5, 0, 0); + if(gcdialog_showDialog(podium_text_id, 0, 0, 0, 0, 0)){ + this->has_met_before = TRUE; } } - else if(func_803616F0(this)){ - sp28 = (volatileFlag_get(VOLATILE_FLAG_16)?0xf6e:0xf68) + this->actorTypeSpecificField - 1; - if(!volatileFlag_get(VOLATILE_FLAG_16) && level_get() == LEVEL_6_LAIR){ - this->has_met_before = true; + else if(lairBottlesDialog_levelOpenedAndNotLearnedAllMoves(this)){ + didnt_learn_moves_text_id = (volatileFlag_get(VOLATILE_FLAG_16) ? VER_SELECT(ASSET_F6E_DIALOG_DIDNT_LEARN_ALL_MOVES_FROM_MM, 0xAD4, 0, 0) : VER_SELECT(ASSET_F68_DIALOG_MM_THREE_NEW_MOVES_TO_LEARN, 0x0ACE, 0, 0)) + this->actorTypeSpecificField - 1; + if(!volatileFlag_get(VOLATILE_FLAG_16) + && level_get() == LEVEL_6_LAIR) + { + this->has_met_before = TRUE; } - else{ - if(gcdialog_showDialog(sp28, 0, 0, 0, 0, 0)){ - this->has_met_before = true; + else{ + if(gcdialog_showDialog(didnt_learn_moves_text_id, 0, 0, 0, 0, 0)) + { + this->has_met_before = TRUE; volatileFlag_set(VOLATILE_FLAG_16, 0); } } diff --git a/src/core2/anim/anim_sequencehandler.c b/src/core2/anim/anim_sequencehandler.c index f82bb92a9..77a79ed2d 100644 --- a/src/core2/anim/anim_sequencehandler.c +++ b/src/core2/anim/anim_sequencehandler.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_DAAA0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/anim/anim_cache.c b/src/core2/anim/animcache.c similarity index 98% rename from src/core2/anim/anim_cache.c rename to src/core2/anim/animcache.c index b617f2341..ee7d459d5 100644 --- a/src/core2/anim/anim_cache.c +++ b/src/core2/anim/animcache.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/animcache.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anim_texturecache.c b/src/core2/anim/animtexturecache.c similarity index 98% rename from src/core2/anim/anim_texturecache.c rename to src/core2/anim/animtexturecache.c index 306efc82c..268aa0270 100644 --- a/src/core2/anim/anim_texturecache.c +++ b/src/core2/anim/animtexturecache.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/animtexturecache.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/sequence.c b/src/core2/anim/anseq.c similarity index 99% rename from src/core2/anim/sequence.c rename to src/core2/anim/anseq.c index b686aaba4..cd53ced72 100644 --- a/src/core2/anim/sequence.c +++ b/src/core2/anim/anseq.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/anseq.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anim_sequencestruct.c b/src/core2/anim/betavent.c similarity index 88% rename from src/core2/anim/anim_sequencestruct.c rename to src/core2/anim/betavent.c index 197d87cd7..823d85860 100644 --- a/src/core2/anim/anim_sequencestruct.c +++ b/src/core2/anim/betavent.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/betavent.c #include #include "core1/core1.h" #include "functions.h" @@ -8,22 +9,22 @@ typedef struct { f32 unk4; } ActorLocal_Core2_DA3A0; -void func_8036158C(Actor *this); +void chBetaVent_update(Actor *this); /* .data */ u8 D_80373130[] = {0, 1, 0, 0}; -ActorInfo D_80373134 = { - 0x1a6, 0x289, 0x431, +ActorInfo chBetaVent1 = { + MARKER_1A6_BETA_VENT, ACTOR_289_BETA_VENT, ASSET_431_MODEL_BETA_VENT, 0x0, NULL, - func_8036158C, NULL, actor_draw, + chBetaVent_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80373158 = { - 0x1a6, 0x28f, 0x431, +ActorInfo chBetaVent2 = { + MARKER_1A6_BETA_VENT, ACTOR_28F_BETA_VENT, ASSET_431_MODEL_BETA_VENT, 0x0, NULL, - func_8036158C, NULL, actor_draw, + chBetaVent_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; @@ -76,7 +77,7 @@ void func_80361330(Actor *this, s32 next_state){ this->state = next_state; } -void func_8036158C(Actor *this){ +void chBetaVent_update(Actor *this){ ActorLocal_Core2_DA3A0 *local = (ActorLocal_Core2_DA3A0 *)&this->local; f32 sp30; f32 sp24[3]; diff --git a/src/core2/anim/bonetransformlist.c b/src/core2/anim/bonetransformlist.c index 011bc75a4..1465fbc12 100644 --- a/src/core2/anim/bonetransformlist.c +++ b/src/core2/anim/bonetransformlist.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B3580.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anim_spriteframe.c b/src/core2/anim/chumpfish.c similarity index 99% rename from src/core2/anim/anim_spriteframe.c rename to src/core2/anim/chumpfish.c index 92872bd6c..ca6bdc710 100644 --- a/src/core2/anim/anim_spriteframe.c +++ b/src/core2/anim/chumpfish.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/chumpfish.c #include #include "functions.h" #include "variables.h" @@ -27,7 +28,7 @@ ActorAnimationInfo D_80372EA0[] = { {0x2C0, 1.5f} }; -ActorInfo D_80372EE0 = { +ActorInfo chChumpFish = { MARKER_69_CHUMP_FISH, ACTOR_A_CHUMP_FISH, ASSET_36B_CHUMP_FISH, 0x2, D_80372EA0, chchumpfish_update, actor_update_func_80326224, actor_draw, diff --git a/src/core2/anim/skeletal.c b/src/core2/anim/skeletalanim.c similarity index 99% rename from src/core2/anim/skeletal.c rename to src/core2/anim/skeletalanim.c index 04cbd309f..493db4e50 100644 --- a/src/core2/anim/skeletal.c +++ b/src/core2/anim/skeletalanim.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/skeletalanim.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/sprite.c b/src/core2/anim/sprite.c index eb0542a28..778bbd349 100644 --- a/src/core2/anim/sprite.c +++ b/src/core2/anim/sprite.c @@ -3,11 +3,11 @@ #include "functions.h" #include "variables.h" +#include "checksums.h" /* .bss */ -u8 D_80379B90[0x10]; static AnimSprite s_animsprite_list[40]; /* .code */ diff --git a/src/core2/ba/ba_anim.c b/src/core2/ba/anim.c similarity index 88% rename from src/core2/ba/ba_anim.c rename to src/core2/ba/anim.c index a96e5912d..c0fe50101 100644 --- a/src/core2/ba/ba_anim.c +++ b/src/core2/ba/anim.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/anim.c #include #include "functions.h" #include "variables.h" @@ -74,61 +75,68 @@ void __baanim_oscillateScale(f32 dst[3], f32 x, f32 min, f32 osc_size) { }; } -void __baanim_applyBottlesBonus(uintptr_t arg0, uintptr_t arg1) { +void baanim_applyBottlesBonusMask(uintptr_t arg0, s32 mask) { f32 scale[3]; - f32 sp28; - s32 phi_s0; - static s32 D_8037BF4C; - + f32 sp28 = func_802E4B38(); - sp28 = func_802E4B38(); - if (volatileFlag_get(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS) == 0) { - D_8037BF4C = 0; - } else { - for(phi_s0 = 0; phi_s0 < 7; phi_s0++){ - if (volatileFlag_get(phi_s0 + VOLATILE_FLAG_97_SANDCASTLE_BOTTLES_BONUS_1)) { - D_8037BF4C = D_803635EC[phi_s0]; - } - } - } - if ((D_8037BF4C & 1)) {//either big hands or big feet + if (mask & 1) {//either big hands or big feet __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 6, scale); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x14, scale); } - if (D_8037BF4C & 2) {//either big hands or big feet + if (mask & 2) {//either big hands or big feet __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x10, scale); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x1E, scale); } - if (D_8037BF4C & BAANIM_BIGHEAD) { + if (mask & BAANIM_BIGHEAD) { __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x12, scale); } - if (D_8037BF4C & BAANIM_SMALLHEAD) { + if (mask & BAANIM_SMALLHEAD) { __baanim_oscillateScale(scale, sp28, 0.2f, 0.5f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x12, scale); } - if (D_8037BF4C & BAANIM_LONGBODY) { + if (mask & BAANIM_LONGBODY) { func_8033A968((BoneTransformList *)arg0, 1, D_803635E0); } - if (D_8037BF4C & BAANIM_BIGKAZOOIEHEAD) { + if (mask & BAANIM_BIGKAZOOIEHEAD) { __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x6C, scale); } - if (D_8037BF4C & BAANIM_BIGWINGS) { + if (mask & BAANIM_BIGWINGS) { __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x64, scale); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x67, scale); } - if (gsworld_getMap() == MAP_A_TTC_SANDCASTLE) { - if ((D_8037BF4C & BAANIM_WISHYWASHY) && (player_getTransformation() != TRANSFORM_7_WISHWASHY)) { - func_8028FB88(TRANSFORM_7_WISHWASHY); - } - if (!(D_8037BF4C & BAANIM_WISHYWASHY) && (player_getTransformation() == TRANSFORM_7_WISHWASHY)) { - func_8028FB88(TRANSFORM_1_BANJO); +} + +s32 baanim_getActiveBottlesBonusMask(void) { + s32 mask = 0; + s32 i; + + if (volatileFlag_get(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS) == 0) { + return 0; + } + for (i = 0; i < 7; i++) { + if (volatileFlag_get(i + VOLATILE_FLAG_97_SANDCASTLE_BOTTLES_BONUS_1)) { + mask = D_803635EC[i]; } } + return mask; +} + +void __baanim_applyBottlesBonus(uintptr_t arg0, uintptr_t arg1) { + s32 mask = baanim_getActiveBottlesBonusMask(); + + baanim_applyBottlesBonusMask(arg0, mask); + + if ((mask & BAANIM_WISHYWASHY) && (player_getTransformation() == TRANSFORM_1_BANJO)) { + player_transform(TRANSFORM_7_WISHWASHY); + } + if (!(mask & BAANIM_WISHYWASHY) && (player_getTransformation() == TRANSFORM_7_WISHWASHY)) { + player_transform(TRANSFORM_1_BANJO); + } if (baAnimModifyFunction != NULL) { baAnimModifyFunction(arg0, arg1); } @@ -229,7 +237,7 @@ void baanim_setUpdateType(enum baanim_update_type_e arg0){ void baanim_80289F30(void){ f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); anctrl_drawSetup(playerAnimCtrl, sp1C, 1); } @@ -270,7 +278,7 @@ void baanim_playForDuration_loop(enum asset_e anim_id, f32 duration){ anctrl_start(playerAnimCtrl, "baanim.c", 0x193); } -void baanim_playForDuration_loopStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ +void baanim_playForDuration_loopSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ anctrl_reset(playerAnimCtrl); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); @@ -279,17 +287,15 @@ void baanim_playForDuration_loopStartingAt(enum asset_e anim_id, f32 duration, f anctrl_start(playerAnimCtrl, "baanim.c", 0x19e); } -void baanim_playForDuration_once(enum asset_e anim_id, f32 duration){ +void baanim_playForDuration_onceSmooth(enum asset_e anim_id, f32 duration){ anctrl_reset(playerAnimCtrl); - // [port] smooth should be off, isn't in decomp - anctrl_setSmoothTransition(playerAnimCtrl, false); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); anctrl_setPlaybackType(playerAnimCtrl, ANIMCTRL_ONCE); anctrl_start(playerAnimCtrl, "baanim.c", 0x1a8); } -void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ +void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ anctrl_reset(playerAnimCtrl); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); @@ -298,17 +304,16 @@ void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f anctrl_start(playerAnimCtrl, "baanim.c", 0x1b3); } -void baanim_playForDuration_onceSmooth(enum asset_e anim_id, f32 duration){ +void baanim_playForDuration_once(enum asset_e anim_id, f32 duration){ anctrl_reset(playerAnimCtrl); - // [port] possible decomp/src bug? smooth should be on here, and off above - // anctrl_setSmoothTransition(playerAnimCtrl, false); + anctrl_setSmoothTransition(playerAnimCtrl, false); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); anctrl_setPlaybackType(playerAnimCtrl, ANIMCTRL_ONCE); anctrl_start(playerAnimCtrl, "baanim.c", 0x1bd); } -void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ +void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ anctrl_reset(playerAnimCtrl); anctrl_setSmoothTransition(playerAnimCtrl, false); anctrl_setIndex(playerAnimCtrl, anim_id); diff --git a/src/core2/ba/ba_animcache.c b/src/core2/ba/ba_animcache.c index ee2f4f126..feebc996a 100644 --- a/src/core2/ba/ba_animcache.c +++ b/src/core2/ba/ba_animcache.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_1550.c /** * @file anim/commoncache.c * @brief This file controls a cache of common animations consisting of diff --git a/src/core2/ba/ba_animstate.c b/src/core2/ba/ba_animstate.c deleted file mode 100644 index 9b5527b17..000000000 --- a/src/core2/ba/ba_animstate.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" - -void func_8029E070(bool); -void func_8029E064(bool); -void func_8029E058(bool); -void func_8029E0C4(f32); -void func_8029E0D0(f32); -void func_8029E0DC(bool); -void func_8029E0F4(bool); -void func_8029E0E8(bool); - -/* .bss */ -f32 D_8037D230; -u8 D_8037D234; -u8 D_8037D235; -u8 D_8037D236; -u8 D_8037D237; -u8 D_8037D238; -u8 D_8037D239; -u8 D_8037D23A; -f32 D_8037D23C; -f32 D_8037D240; - -/* .code */ -void func_8029DBF0(void){ - s32 temp_s0; - switch(baModel_getModelId()){ - case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: //L8029DC24 - case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: //L8029DC24 - temp_s0 = (s32) ml_interpolate_f(D_8037D23C, 1.0f, 8.0f); - func_8033A45C(0x1B, temp_s0); - func_8033A45C(0x1D, temp_s0); - func_8033A45C(0x1F, temp_s0); - func_8033A45C(0x21, temp_s0); - temp_s0 = (s32) ml_interpolate_f(D_8037D240, 1.0f, 8.0f); - func_8033A45C(0x1A, temp_s0); - func_8033A45C(0x1C, temp_s0); - func_8033A45C(0x1E, temp_s0); - func_8033A45C(0x20, temp_s0); - break; - - case ASSET_34F_MODEL_BANJO_TERMITE: //L8029DCCC - case ASSET_359_MODEL_BANJO_WALRUS: //L8029DCCC - case ASSET_36F_MODEL_BANJO_PUMPKIN: //L8029DCCC - case ASSET_374_MODEL_BANJO_CROC: //L8029DCCC - func_8033A45C(0x1B, (s32) ml_interpolate_f(D_8037D23C, 1.0f, 6.0f)); - func_8033A45C(0x1A, (s32) ml_interpolate_f(D_8037D240, 1.0f, 6.0f)); - break; - - case ASSET_356_MODEL_BANJO_WISHYWASHY: //L8029DD2C - func_8033A45C(1, (s32) ml_interpolate_f(D_8037D240, 1.0f, 4.0f)); - break; - } -} - -void func_8029DD6C(void) { - s32 temp_s0; // [port] must hold values > 1 for geo selector branches - - modelRender_func_8033A1FC(); - switch (baModel_getModelId()) { - case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: - case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: - func_8033A45C(1, D_8037D238); - func_8033A45C(9, D_8037D238); - func_8033A45C(0xC, D_8037D238); - func_8033A45C(0xF, D_8037D238); - func_8033A45C(2, D_8037D236); - func_8033A45C(0xA, D_8037D236); - func_8033A45C(0xD, D_8037D236); - func_8033A45C(0x10, D_8037D236); - func_8033A45C(8, D_8037D235); - func_8033A45C(0xB, D_8037D235); - func_8033A45C(0xE, D_8037D235); - func_8033A45C(0x11, D_8037D235); - temp_s0 = D_8037D237 + 1; - func_8033A45C(0x12, temp_s0); - func_8033A45C(0x14, temp_s0); - func_8033A45C(0x16, temp_s0); - func_8033A45C(0x18, temp_s0); - func_8033A45C(0x13, temp_s0); - func_8033A45C(0x15, temp_s0); - func_8033A45C(0x17, temp_s0); - func_8033A45C(0x19, temp_s0); - temp_s0 = D_8037D239 + 1; - func_8033A45C(0x22, temp_s0); - func_8033A45C(0x24, temp_s0); - func_8033A45C(0x26, temp_s0); - func_8033A45C(0x28, temp_s0); - func_8033A45C(0x23, temp_s0); - func_8033A45C(0x25, temp_s0); - func_8033A45C(0x27, temp_s0); - func_8033A45C(0x29, temp_s0); - break; - case ASSET_359_MODEL_BANJO_WALRUS: - func_8033A45C(3, D_8037D23A); - break; - case ASSET_374_MODEL_BANJO_CROC: - temp_s0 = D_8037D237 + 1; - func_8033A45C(4, temp_s0); - func_8033A45C(5, temp_s0); - func_8033A45C(6, temp_s0); - func_8033A45C(7, temp_s0); - break; - } - func_8029DBF0(); -} - -bool func_8029DFA4(void){ - return D_8037D235; -} - -bool func_8029DFB0(void){ - return D_8037D236; -} - -bool func_8029DFBC(void){ - return D_8037D238; -} - -f32 func_8029DFC8(void){ - return D_8037D23C; -} - -f32 func_8029DFD4(void){ - return D_8037D240; -} - -bool func_8029DFE0(void){ - return D_8037D237; -} - -bool func_8029DFEC(void){ - return D_8037D239; -} - -void func_8029DFF8(void) { - func_8029E070(0); - func_8029E064(0); - func_8029E058(0); - func_8029E0C4(0.0f); - func_8029E0D0(0.0f); - func_8029E0DC(0); - func_8029E0F4(0); - func_8029E0E8(0); - CALL_EVENT(OnPlayerAnimReset); -} - -void func_8029E058(bool arg0){ - D_8037D235 = arg0; -} - -void func_8029E064(bool arg0){ - D_8037D236 = arg0; -} - -void func_8029E070(bool arg0) { - func_8029E090(arg0, 0.0f); -} - -void func_8029E090(bool arg0, f32 arg1) { - D_8037D230 = arg1; - D_8037D234 = arg0; - if (arg1 == 0.0f) { - D_8037D238 = arg0; - } -} - -void func_8029E0C4(f32 arg0){ - D_8037D23C = arg0; -} - -void func_8029E0D0(f32 arg0){ - D_8037D240 = arg0; -} - -void func_8029E0DC(bool arg0){ - D_8037D237 = arg0; -} - -void func_8029E0E8(bool arg0){ - D_8037D23A = arg0; -} - -void func_8029E0F4(bool arg0){ - D_8037D239 = arg0; -} - -void func_8029E100(void) { - if (D_8037D230 != 0.0f) { - D_8037D230 -= time_getDelta(); - if (D_8037D230 <= 0.0f) { - D_8037D238 = D_8037D234; - } - } -} diff --git a/src/core2/ba/ba_camera.c b/src/core2/ba/ba_camera.c index 71bf5d378..d91fcd45b 100644 --- a/src/core2/ba/ba_camera.c +++ b/src/core2/ba/ba_camera.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9BD0.c #include #include "functions.h" #include "variables.h" @@ -112,7 +113,7 @@ int func_80290E8C(void){ ncDynamicCamera_setState(3); func_80291488(0xB); if( gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN - && player_getYPosition() < 1201.0f + && playerPosition_getY() < 1201.0f ){ func_802C1B20(1100.0f); } diff --git a/src/core2/ba/ba_eyeblink_data.c b/src/core2/ba/ba_eyeblink_data.c index 0c959a60f..7d4179659 100644 --- a/src/core2/ba/ba_eyeblink_data.c +++ b/src/core2/ba/ba_eyeblink_data.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_90E0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_eyemouth_data.c b/src/core2/ba/ba_eyemouth_data.c index 4d9c9b6f7..bbc2c81ca 100644 --- a/src/core2/ba/ba_eyemouth_data.c +++ b/src/core2/ba/ba_eyemouth_data.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_400F0.c #include #include "functions.h" #include "variables.h" @@ -101,16 +102,16 @@ void func_802C71F0(Actor *actor){ case 0x8E: case 0xAC: case 0xB8://L802C7254 - func_8033A45C(0x1, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 6.0f)); - func_8033A45C(0x2, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 6.0f)); + modelRender_setAppendageVisibility(0x1, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 6.0f)); + modelRender_setAppendageVisibility(0x2, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 6.0f)); break; case 0x195: case 0x196: case 0x197://L802C72B0 case 0x2FB://L802C72B4 - func_8033A45C(0x1C, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 8.0f)); - func_8033A45C(0x1D, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 8.0f)); + modelRender_setAppendageVisibility(0x1C, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 8.0f)); + modelRender_setAppendageVisibility(0x1D, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 8.0f)); break; } } diff --git a/src/core2/ba/ba_falling.c b/src/core2/ba/ba_falling.c index 4c7df9dc4..ed93cf78f 100644 --- a/src/core2/ba/ba_falling.c +++ b/src/core2/ba/ba_falling.c @@ -1,8 +1,8 @@ +// BanjoDecomp: core2/code_C97F0.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" - #include "port/Interpolation/FrameInterpolation.h" @@ -211,7 +211,7 @@ void func_80350CA4(void) { sp24[0] = sp30[0] + sp48[0]; sp24[1] = sp30[1] + sp48[1]; sp24[2] = sp30[2] + sp48[2]; - if (func_8028F170()) { // [port] decomp passed sp48[1],sp48[2] but actual def is (void) + if (player_isInFirstPersonView()) { // [port] decomp passes sp48[1],sp48[2]; actual def takes none var_v0 = func_80320B98(sp30, sp24, sp3C, 0x01000000); } else { var_v0 = func_80309B48(sp30, sp24, sp3C, 0x01000000); diff --git a/src/core2/ba/ba_health.c b/src/core2/ba/ba_health.c index 0e8864f5d..31f21e56f 100644 --- a/src/core2/ba/ba_health.c +++ b/src/core2/ba/ba_health.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9290.c #include #include "functions.h" #include "variables.h" @@ -15,7 +16,7 @@ void func_80290220(void){ D_8037C010 = D_8037C014 = -1; D_8037C02C = 0; D_8037C018 = -1; - _player_getPosition(D_8037C020); + playerPosition_get(D_8037C020); } void func_8029026C(s32 arg0, s32 arg1){ @@ -36,7 +37,7 @@ void func_80290298(void) { sp30 = (func_8028B528() && !is_pumpkin) ? 6 : 1; sp24 = func_8028B528() && !is_pumpkin; if (D_8037C02C || player_isStable() || sp24 || player_movementGroup() == BSGROUP_5_CLIMB || bs_getState() == BS_B_UNKOWN) { - _player_getPosition(D_8037C020); + playerPosition_get(D_8037C020); } if (player_movementGroup() == BSGROUP_A_FLYING) { diff --git a/src/core2/ba/ba_hitbox.c b/src/core2/ba/ba_hitbox.c index 56c0c35a0..74f7889f0 100644 --- a/src/core2/ba/ba_hitbox.c +++ b/src/core2/ba/ba_hitbox.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6B30.c #include #include "functions.h" #include "variables.h" @@ -36,19 +37,19 @@ enum hitbox_e hitbox_getHitboxForActor(ActorMarker *arg0){ switch(bs_getState()){ case BS_F_BBUSTER: //8028DBA4 - return __maybe(bsbbuster_hitboxActive(),HITBOX_1_BEAK_BUSTER); + return __maybe(bsbbuster_hitboxActive(), HITBOX_1_BEAK_BUSTER); break; - case BS_BBARGE://8028DBC0 - return __maybe(bsbbarge_hitboxActive(),HITBOX_2_BEAK_BARGE); + case BS_13_BBARGE://8028DBC0 + return __maybe(bsbbarge_hitboxActive(), HITBOX_2_BEAK_BARGE); break; - case BS_BOMB://8028DBDC - return __maybe(bsbfly_bombHitboxActive(),HITBOX_3_BEAK_BOMB); + case BS_2A_BOMB://8028DBDC + return __maybe(bsbfly_bombHitboxActive(), HITBOX_3_BEAK_BOMB); break; - case BS_CLAW://8028DBF8 + case BS_6_CLAW://8028DBF8 if(arg0 && !func_8028AED4(marker_getActor(arg0)->position, 90.0f)) return HITBOX_0_NONE; - retVal = __maybe(bsclaw_hitboxActive(),HITBOX_4_CLAW); + retVal = __maybe(bsclaw_hitboxActive(), HITBOX_4_CLAW); if(retVal != 0) return retVal; return HITBOX_8_CLAW_DOWN; @@ -68,7 +69,7 @@ enum hitbox_e hitbox_getHitboxForActor(ActorMarker *arg0){ return HITBOX_6_WONDERWING; break; //8028DCA0 - case BS_ROLL: + case BS_31_ROLL: return __maybe(bstwirl_hitboxActive(),HITBOX_7_ROLL); break; case BS_6E_CROC_BITE://L8028DCBC diff --git a/src/core2/ba/ba_intensity.c b/src/core2/ba/ba_intensity.c index a09751769..bb0f5d7d7 100644 --- a/src/core2/ba/ba_intensity.c +++ b/src/core2/ba/ba_intensity.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_A600.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_lookdir.c b/src/core2/ba/ba_lookdir.c index d78aea99a..0a30418f7 100644 --- a/src/core2/ba/ba_lookdir.c +++ b/src/core2/ba/ba_lookdir.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_7060.c #include #include "functions.h" #include "variables.h" @@ -11,10 +12,10 @@ #include "core2/snackerctl.h" -extern int player_isInHorizontalRadius(f32[3], f32); +extern bool player_isInHorizontalRadius(f32[3], f32); extern bool player_isInVerticalRange(f32[3], f32); extern void func_80295A8C(void); -extern void climbSet(f32[3], f32[3], f32, u32); +extern void climb_set(f32[3], f32[3], f32, u32); extern void func_80296C90(f32); extern void func_80296C9C(f32); extern void func_8029B73C(f32 arg0[3], f32 arg1, f32 arg2, f32 arg3, f32 arg4); @@ -185,10 +186,10 @@ void func_8028E4B0(void) { D_8037BFBA = true; D_8037BFB9 = false; - func_80295914(); + bsmethods_reset(); sp20 = gsworld_getExit(); D_8037BFB8 = 0; - player_setPosition(D_803636C0); + playerPosition_set(D_803636C0); if (volatileFlag_get(VOLATILE_FLAG_E) || func_802D686C() || (sp20 == 0x65)){ return; } @@ -270,7 +271,7 @@ u32 player_getTransformation(void){ } void func_8028E7EC(f32 arg0[3]){ - climbGetBottom(arg0); + climb_getBottom(arg0); } f32 player_stateTimer_get(enum state_timer_e timer_id){ @@ -285,14 +286,14 @@ void func_8028E84C(f32 arg0[3]){ func_80294480(arg0); } -ActorMarker *func_8028E86C(void){ - return bacarry_get_marker(); +ActorMarker *bacarry_getMarkerWithExtraSteps(void){ + return bacarry_getMarker(); } -enum marker_e bacarry_get_markerId(void){ +enum marker_e bacarry_getMarkerId(void){ ActorMarker *marker; - marker = bacarry_get_marker(); + marker = bacarry_getMarker(); if(marker){ return marker->id; } @@ -303,7 +304,7 @@ enum actor_e carriedObj_getActorId(void){ ActorMarker *marker; Actor *actor; - marker = bacarry_get_marker(); + marker = bacarry_getMarker(); if(marker != NULL){ actor = marker_getActor(marker); @@ -333,7 +334,7 @@ f32 func_8028E984(void){ } void player_getPosition(f32 dst[3]){ - _player_getPosition(dst); + playerPosition_get(dst); } void func_8028E9C4(s32 arg0, f32 arg1[3]) { @@ -355,7 +356,7 @@ void func_8028E9C4(s32 arg0, f32 arg1[3]) { break; case 5: //L8028EA2C - _player_getPosition(arg1); + playerPosition_get(arg1); switch(bsStoredState_getTransformation()){ case TRANSFORM_3_PUMPKIN: //L8028EA68 if(gsworld_getMap() == MAP_1B_MMM_MAD_MONSTER_MANSION){ @@ -397,12 +398,12 @@ void func_8028E9C4(s32 arg0, f32 arg1[3]) { } -void player_getPosition_s32(s32 arg0[3]){ +void player_getPosition_s32(s32 position_s32[3]){ f32 plyr_pos[3]; player_getPosition(plyr_pos); - arg0[0] = (s32)plyr_pos[0]; - arg0[1] = (s32)plyr_pos[1]; - arg0[2] = (s32)plyr_pos[2]; + position_s32[0] = (s32)plyr_pos[0]; + position_s32[1] = (s32)plyr_pos[1]; + position_s32[2] = (s32)plyr_pos[2]; } f32 player_getYaw(void){ @@ -431,7 +432,7 @@ f32 func_8028EC64(f32 arg0[3]){ f32 sp1C; f32 sp18; func_80293D2C(&sp18, &sp1C); - _player_getPosition(arg0); + playerPosition_get(arg0); arg0[1] += sp18; return sp1C; } @@ -466,7 +467,7 @@ enum bsgroup_e player_movementGroup(void) { case BS_E_OW: //L8028EE00 case BS_34_JIG_NOTEDOOR: //L8028EE00 case BS_3C_TALK: //L8028EE00 - case BS_3F: //L8028EE00 + case BS_3F_UNKNOWN: //L8028EE00 case BS_41_DIE: //L8028EE00 case BS_44_JIG_JIGGY: //L8028EE00 return BSGROUP_1_INTR; @@ -548,7 +549,7 @@ f32 func_8028EF88(void){ if(floor_isCurrentFloorunk59()){ return floor_getCurrentFloorYPosition(); } - return player_getYPosition(); + return playerPosition_getY(); } bool func_8028EFC8(void){ @@ -559,15 +560,15 @@ bool func_8028EFEC(void){ return bakey_getAndSetState(BUTTON_A, 2); } -void func_8028F010(enum actor_e actor_id){ +void bacarriedobj_decWithExtraSteps(enum actor_e actor_id){ bacarriedobj_dec(actor_id); } -void func_8028F030(enum actor_e actor_id){ +void bacarriedobj_incWithExtraSteps(enum actor_e actor_id){ bacarriedobj_inc(actor_id); } -void func_8028F050(enum actor_e actor_id){ +void bacarriedobj_displayOnHudWithExtraSteps(enum actor_e actor_id){ bacarriedobj_displayOnHud(actor_id); } @@ -588,7 +589,7 @@ bool func_8028F098(void){ } } -bool func_8028F0D4(void){ +bool player_isBanjoOrWishywashy(void){ enum transformation_e xform_id; xform_id = bsStoredState_getTransformation(); @@ -608,11 +609,11 @@ bool func_8028F150(void){ return baModel_isVisible(); } -bool func_8028F170(void){ +bool player_isInFirstPersonView(void){ return baflag_isTrue(BA_FLAG_17_FIRST_PERSON_VIEW); } -int ability_isUnlocked(enum ability_e uid){ +bool ability_isUnlocked(enum ability_e uid){ return ability_hasLearned(uid); } @@ -628,7 +629,7 @@ bool func_8028F1E0(void){ return bsList_getInterruptMethod(bs_getState()) != NULL; } -bool func_8028F20C(void){ +bool player_isStableWithExtraSteps(void){ return player_isStable(); } @@ -689,9 +690,13 @@ void func_8028F408(f32 arg0[3]){ } bool func_8028F428(s32 arg0, ActorMarker *marker) { + s32 handled = 2; func_80296CB4(arg0); func_80296CA8(marker); - return bs_checkInterrupt(BS_INTR_24) == 2; + if (EventSystem_Should(VB_BUMP_REBOUNDS_PLAYER, true, marker)) { + handled = bs_checkInterrupt(BS_INTR_24); + } + return handled == 2; } bool func_8028F45C(s32 arg0, f32 arg1[3]) { @@ -776,7 +781,7 @@ void player_stateTimer_set(enum state_timer_e timer_id, f32 value){ } void player_setClimbParams(f32 bottom[3], f32 top[3], f32 radius, u32 arg3){ - climbSet(bottom, top, radius, arg3); + climb_set(bottom, top, radius, arg3); } void func_8028F760(s32 arg0, f32 arg1, f32 arg2){ @@ -884,7 +889,7 @@ void func_8028FA74(f32 dst[3]){ f32 plyr_pos[3]; f32 sp18[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); playerPosition_getOffset(sp18); ml_vec3f_add(dst, plyr_pos, sp18); } @@ -893,7 +898,7 @@ void func_8028FAB0(f32 arg0[3]){ f32 plyr_pos[3]; f32 diff[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); ml_vec3f_diff_copy(diff, arg0, plyr_pos); playerPosition_setOffset(diff); } @@ -916,7 +921,7 @@ void func_8028FB68(void){ func_80295D74(); } -bool func_8028FB88(enum transformation_e xform_id) { +bool player_transform(enum transformation_e xform_id) { if (wishyWashyFlag_get() && xform_id == TRANSFORM_1_BANJO) { xform_id = TRANSFORM_7_WISHWASHY; } @@ -935,7 +940,7 @@ bool func_8028FBD4(f32 arg0[3]) { } bool player_throwCarriedObject(void){ - if (func_8028E86C() && bscarry_inSet(bs_getState())) { + if (bacarry_getMarkerWithExtraSteps() && bscarry_inSet(bs_getState())) { return bs_checkInterrupt(BS_INTR_16_THROW_CARRIED_OBJ) == 2; } @@ -964,3 +969,9 @@ void func_8028FCE8(void) { D_8037BFCC = yaw_get(); D_8037BFD0 = D_8037BFBC; } + +void player_setWarpDestination(f32 position[3], f32 yaw, s32 exit_id) { + ml_vec3f_copy(D_8037BFC0, position); + D_8037BFCC = yaw; + D_8037BFD0 = (f32) exit_id; +} diff --git a/src/core2/ba/ba_momentum.c b/src/core2/ba/ba_momentum.c index 8d005015a..1ba3f16cf 100644 --- a/src/core2/ba/ba_momentum.c +++ b/src/core2/ba/ba_momentum.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9450.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_musicstate.c b/src/core2/ba/ba_musicstate.c index 825ff4e2c..b6dcfd3bf 100644 --- a/src/core2/ba/ba_musicstate.c +++ b/src/core2/ba/ba_musicstate.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9A9D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_recoil.c b/src/core2/ba/ba_recoil.c index db60a03ea..ed23a9804 100644 --- a/src/core2/ba/ba_recoil.c +++ b/src/core2/ba/ba_recoil.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_D9B0.c #include #include "functions.h" #include "variables.h" @@ -101,7 +102,7 @@ void func_80294B00(int arg0){ } void func_80294B0C(void){ - f32 sp1C = player_getYPosition(); + f32 sp1C = playerPosition_getY(); enum bsgroup_e player_movement_group = player_movementGroup(); if( player_isStable() || player_inWater() @@ -173,12 +174,12 @@ void func_80294BDC(void) { void func_80294DD8(void){ ml_vec3f_clear(D_8037C2A0); ml_vec3f_clear(D_8037C2B0); - _player_getPosition(D_8037C2D8); + playerPosition_get(D_8037C2D8); D_8037C2ED = 0; D_8037C2E4 = 0.0f; D_8037C2EC = 1; D_8037C2F0.unk8 = 0; - D_8037C2F0.unk4 = D_8037C2F0.unk0 = player_getYPosition(); + D_8037C2F0.unk4 = D_8037C2F0.unk0 = playerPosition_getY(); } void func_80294E54(int arg0){ @@ -187,7 +188,7 @@ void func_80294E54(int arg0){ void func_80294E60(void){ if(player_isStable()){ - _player_getPosition(D_8037C2D8); + playerPosition_get(D_8037C2D8); } if(player_isStable() || bsclimb_inSet(bs_getState())){ diff --git a/src/core2/ba/ba_state.c b/src/core2/ba/ba_state.c deleted file mode 100644 index 43a6c6abe..000000000 --- a/src/core2/ba/ba_state.c +++ /dev/null @@ -1,331 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" -#include "bsint.h" -#include "bs_funcs.h" -#include "core2/statetimer.h" -#include "core2/ba/physics.h" -#include "core2/snackerctl.h" - -u8 D_80363820 = 0; -bsMap D_80363824[] ={ - {BS_1_IDLE, bsstand_init, bsstand_update, bsstand_end, func_802B5350}, - {BS_2_WALK_SLOW, bswalk_slow_init, bswalk_slow_upate, NULL, func_802B5350}, - {BS_WALK, bswalk_init, bswalk_update, NULL, func_802B5350}, - {BS_4_WALK_FAST, bswalk_fast_init, bswalk_fast_update, bswalk_fast_end, func_802B5350}, - {BS_5_JUMP, bsjump_init, bsjump_update, bsjump_end, func_80296608}, - {BS_CLAW, bsclaw_init, bsclaw_update, bsclaw_end, func_80296608}, - {BS_CROUCH, bscrouch_init, bscrouch_update, bscrouch_end, func_802B5350}, - {BS_8_BTROT_JUMP, bsbtrot_jump_init, bsbtrot_jump_update,bsbtrot_jump_end, func_802B5350}, - {BS_SKID, bsturn_init, bsturn_update, bsturn_end, func_802B5350}, - {BS_D_TIMEOUT, func_802B63F8, func_802B64D0, func_802B6500, func_80296590}, - {BS_E_OW, bsow_init, bsow_update, bsow_end, func_80296590}, - {BS_F_BBUSTER, bsbbuster_init, bsbbuster_update, bsbbuster_end, func_80296608}, - {BS_BFLAP, bsbflap_init, bsbflap_update, bsbflap_end, func_80296608}, - {BS_11_BPECK, bsbpeck_init, bsbpeck_update, bsbpeck_end, func_80296608}, - {BS_12_BFLIP, bsbflip_init, bsbflip_update, bsbflip_end, func_80296608}, - {BS_BBARGE, bsbarge_init, bsbarge_update, bsbarge_end, func_80296608}, - {BS_14_BTROT_ENTER, bsbtrot_enter_init, bsbtrot_enter_update, bsbtrot_enter_end, func_802B5350}, - {BS_15_BTROT_IDLE, bsbtrot_stand_init, bsbtrot_stand_update, bsbtrot_stand_end, func_802B5350}, - {BS_16_BTROT_WALK, bsbtrot_walk_init, bsbtrot_walk_update, bsbtrot_walk_end, func_802B5350}, - {BS_17_BTROT_EXIT, bsbtrot_exit_init, bsbtrot_exit_update, bsbtrot_exit_end, func_802B5350}, - {BS_18_FLY_KNOCKBACK, func_802A4D90, func_802A4EC8, func_802A4F44, func_80296608}, - {BS_1A_WONDERWING_ENTER, bsbwhirl_enter_init, bsbwhirl_enter_update, bsbwhirl_enter_end, func_80296608}, - {BS_1B_WONDERWING_IDLE, bsbwhirl_stand_init, bsbwhirl_stand_update, bsbwhirl_stand_end, func_80296608}, - {BS_1C_WONDERWING_WALK, bsbwhirl_walk_init, bsbwhirl_walk_update, bsbwhirl_walk_end, func_80296608}, - {BS_1D_WONDERWING_JUMP, bsbwhirl_jump_init, bsbwhirl_jump_update, bsbwhirl_jump_end, func_80296608}, - {BS_1E_WONDERWING_EXIT, bsbwhirl_exit_init, bsbwhirl_exit_update, bsbwhirl_exit_end, func_80296608}, - {BS_9_EGG_HEAD, bsegghead_init, bsegghead_update, bsegghead_end, func_802B5350}, - {BS_A_EGG_ASS, bseggass_init, bseggass_update, bseggass_end, func_802B5350}, - {BS_WALK_CREEP, bswalk_creep_init, bswalk_creep_update, NULL, func_802B5350}, - {BS_20_LANDING, bsstand_landing_init, bsstand_landing_update, NULL, func_802B5350}, - {BS_BSHOCK_CHARGE, bsbshock_charge_init, bsbshock_charge_update, bsbshock_charge_end, func_80296608}, - {BS_BSHOCK_JUMP, bsbshock_init, bsbshock_update, bsbshock_end, func_80296608}, - {BS_23_FLY_ENTER, bsbfly_enter_init, bsbfly_enter_update, bsbfly_enter_end, func_802A505C}, - {BS_24_FLY, bsbfly_init, bsbfly_update, func_802A3F70, func_802A505C}, - {BS_25_LONGLEG_ENTER, bsblongleg_enter_init, bsblongleg_enter_update, bsblongleg_enter_end, func_802B5350}, - {BS_26_LONGLEG_IDLE, bsblongleg_stand_enter, bsblongleg_stand_update, bsblongleg_stand_end, func_802B5350}, - {BS_LONGLEG_WALK, bsblongleg_walk_init, bsblongleg_walk_update, bsblongleg_walk_end, func_802B5350}, - {BS_LONGLEG_JUMP, bsblongleg_jump_init, bsblongleg_jump_update, bsblongleg_jump_end, func_80296608}, - {BS_LONGLEG_EXIT, bsblongleg_exit_init, bsblongleg_exit_update, bsblongleg_exit_end, func_802B5350}, - {BS_BOMB, func_802A3F9C, func_802A411C, func_802A4404, func_802A505C}, - {BS_2B_DIVE_IDLE, func_802A762C, func_802A7674, func_802A7718, func_80296608}, - {BS_2C_DIVE_B, func_802A7738, func_802A7838, func_802A7A2C, func_80296608}, - {BS_2D_SWIM_IDLE, bsswim_idle_init, bsswim_idle_update, bsswim_idle_end, func_80296608}, - {BS_2E_SWIM, bsswim_swim_init, bsswim_swim_update, bsswim_swim_end, func_80296608}, - {BS_2F_FALL, bsjump_fall_init, bsjump_fall_update, bsjump_fall_end, func_80296608}, - {BS_30_DIVE_ENTER, bsSwim_dive_init, func_802A7E2C, func_802A7F4C, func_80296608}, - {BS_ROLL, bstwirl_init, bstwirl_update, bstwirl_end, func_802B5350}, - {BS_SLIDE, bsslide_init, bsslide_update, bsslide_end, func_802B5350}, - {0x33, func_802B9ACC, func_802B9B14, func_802B9AAC, func_802B9D00}, - {BS_34_JIG_NOTEDOOR, bsjig_notedoor_init, bsjig_notedoor_update, bsjig_notedoor_end, func_80296590}, - {BS_35_ANT_IDLE, bsant_idle_init, bsant_idle_update, bsant_idle_end, func_802B5350}, - {BS_ANT_WALK, bsant_walk_init, bsant_walk_update, bsant_walk_end, func_802B5350}, - {BS_ANT_JUMP, bsant_jump_init, bsant_jump_update, bsant_jump_end, func_802B5350}, - {BS_39_DIVE_A, func_802A7A54, func_802A7AB0, func_802A7BA8, func_80296608}, - {BS_3A_CARRY_IDLE, bscarry_idle_init, bscarry_idle_update, bscarry_idle_end, bscarry_interrupt}, - {BS_3B_CARRY_WALK, bscarry_walk_init, bscarry_walk_update, bscarry_walk_end, bscarry_interrupt}, - {BS_3C_TALK, bstalk_init, bstalk_update, bstalk_end, bstalk_interrupt}, - {BS_3D_FALL_TUMBLING, bsjump_tumble_init, bsjump_tumble_update, bsjump_tumble_end, func_80296608}, - {BS_38_ANT_FALL, bsant_fall_init, bsant_fall_update, bsant_fall_end, func_80296590}, - {BS_3E_ANT_OW, bsant_ow_init, bsant_ow_update, bsant_ow_end, func_80296590}, - {0x3F, func_802B1BF4, func_802B1CF8, func_802B1DA4, func_80296590}, - {BS_40_PUMPKIN_FLUSH, func_802B2BF0, func_802B2C58, func_802B2D50, func_80296590}, - {BS_41_DIE, bsdie_init, bsdie_update, bsdie_end, func_80296590}, - {BS_42_DINGPOT, func_802A5120, func_802A5190, func_802A51C0, func_80296590}, - {BS_43_ANT_DIE, bsant_die_init, bsant_die_update, bsant_die_end, func_80296590}, - {BS_44_JIG_JIGGY, bsjig_jiggy_init, bsjig_jiggy_update, bsjig_jiggy_end, bsjig_jiggy_interrupt}, - {BS_45_BTROT_SLIDE, bsbtrot_slide_init, bsbtrot_slide_update, bsbtrot_slide_end, func_802B5350}, - {0x46, func_802A2098, func_802A2130, func_802A2054, func_80296590}, - {BS_48_PUMPKIN_IDLE, bspumpkin_idle_init, bspumpkin_idle_update, bspumpkin_idle_end, func_802B5350}, - {BS_49_PUMPKIN_WALK, bspumpkin_walk_init, bspumpkin_walk_update, bspumpkin_walk_end, func_802B5350}, - {BS_4A_PUMPKIN_JUMP, bspumpkin_jump_init, bspumpkin_jump_update, bspumpkin_jump_end, func_802B5350}, - {BS_4B_PUMPKIN_FALL, bspumpkin_fall_init, bspumpkin_fall_update, bspumpkin_fall_end, func_802B5350}, - {BS_4C_LANDING_IN_WATER, func_802A846C, func_802A85EC, func_802A872C, func_80296608}, - {BS_4D_PUMPKIN_OW, __bspumpkin_ow_init, __bspumpkin_ow_update, __bspumpkin_ow_end, func_80296590}, - {BS_4E_PUMPKIN_DIE, bspumpkin_die_init, bspumpkin_die_update, bspumpkin_die_end, func_80296590}, - {BS_4F_CLIMB_IDLE, bsclimb_idle_init, bsclimb_idle_update, bsclimb_idle_end, func_802ABD60}, - {BS_50_CLIMB_MOVE, bsclimb_move_init, bsclimb_move_update, bsclimb_move_end, func_802ABD60}, - {BS_51_CLIMB_EXIT, func_802B1928, func_802B1A54, func_802B1BCC, func_80296608}, - {0x52, func_802B5FD0, func_802B6064, func_802B60D0, func_802B60D8}, - {BS_53_TIMEOUT, func_802B6270, func_802B6314, func_802B63C8, func_80296590}, - {BS_LONGLEG_SLIDE, bsblongleg_slide_init, bsblongleg_slide_update, bsblongleg_slide_end, func_802B5350}, - {BS_56_RECOIL, func_802B3868, func_802B3954, func_802B3A20, func_80296590}, - {BS_57_BOMB_END, func_802A4430, func_802A4548, func_802A4664, func_802A505C}, - {BS_58_BEAKBOMB_CRASH, bsbfly_beakbomb_crash_init, func_802A48B4, func_802A4A40, func_80296590}, - {0x59, func_802A4CD0, func_802A4CF0, func_802A4D10, func_802A505C}, - {BS_54_SWIM_DIE, func_802A7F6C, func_802A8098, func_802A82D4, func_80296590}, - {BS_CARRY_THROW, bsthrow_init, bsthrow_update, bsthrow_end, bsthrow_interrupt}, - {BS_5E_CROC_IDLE, bscroc_idle_init, bscroc_idle_update, bscroc_idle_end, func_802B5350}, - {BS_CROC_WALK, bscroc_walk_init, bscroc_walk_update, bscroc_walk_end, func_802B5350}, - {BS_CROC_JUMP, bscroc_jump_init, bscroc_jump_update, bscroc_jump_end, func_802B5350}, - {BS_61_CROC_FALL, bscroc_fall_init, bscroc_fall_update, bscroc_fall_end, func_802B5350}, - {BS_62_LONGLEG_LOCKED, func_802A6394, func_802A63F0, func_802A6450, func_80296608}, - {BS_CROC_OW, bscroc_ow_init, bscroc_ow_update, bscroc_ow_end, func_80296590}, - {BS_CROC_OW, bscroc_die_init, bscroc_die_update, bscroc_die_end, func_80296590}, - {BS_67_WALRUS_IDLE, bswalrus_idle_init, bswalrus_idle_update, bswalrus_idle_end, func_802B5350}, - {BS_WALRUS_WALK, bswalrus_walk_init, bswalrus_walk_update, bswalrus_walk_end, func_802B5350}, - {BS_WALRUS_JUMP, bswalrus_jump_init, bswalrus_jump_update, bswalrus_jump_end, func_802B5350}, - {BS_6A_WALRUS_FALL, bswalrus_fall_init, bswalrus_fall_update, bswalrus_fall_end, func_802B5350}, - {0x6B, func_802A1F6C, func_802A1FC8, func_802A2014, func_80296608}, - {BS_WALRUS_OW, bswalrus_ow_init, bswalrus_ow_update, bswalrus_ow_end, func_80296590}, - {BS_WALRUS_DIE, bswalrus_die_init, bswalrus_die_update, bswalrus_die_end, func_80296590}, - {BS_6E_CROC_BITE, bscroc_bite_init, bscroc_bite_update, bscroc_bite_end, func_802B5350}, - {BS_CROC_EAT_BAD, bscroc_eat_bad_init, bscroc_eat_bad_update, bscroc_eat_bad_end, func_802B5350}, - {BS_70_CROC_EAT_GOOD, bscroc_eat_good_init, bscroc_eat_good_update, bscroc_eat_good_end, func_802B5350}, - {BS_71_BTROT_FALL, bsbtrot_fall_init, bsbtrot_fall_update, bsbtrot_fall_end, func_80296608}, - {BS_SPLAT, bssplat_init, bssplat_update, bssplat_end, func_80296590}, - {0x00000073, func_802B3CEC, func_802B3D1C, func_802B3D6C, func_80296608}, - {0x00000074, func_802B3E2C, func_802B3E64, func_802B3EF4, func_80296608}, - {0x00000075, func_802B3D8C, func_802B3DBC, func_802B3E0C, func_80296608}, - {0x00000076, func_802A4F74, func_802A4FC8, func_802A503C, func_80296608}, - {0x00000077, bsswim_lookat_init, bsswim_lookat_update, bsswim_lookat_end, func_80296608}, - {0x00000078, bsbswim_lookat_init, bsbswim_lookat_update, bsbswim_lookat_end, func_80296608}, - {0x00000079, bsbtrot_unk79_init, bsbtrot_unk79_update, bsbtrot_unk79_end, func_80296608}, - {BS_WALK_MUD, bswalk_mud_init, bswalk_mud_update, NULL, func_80296608}, - {BS_BTROT_OW, bsbtrot_ow_init, bsbtrot_ow_update, bsbtrot_ow_end, func_80296590}, - {BS_7C_SLED, bssled_init, bssled_update, bssled_end, bssled_interrupt}, - {BS_7D_WALRUS_SLED, bswalrus_sled_init, bswalrus_sled_update, bswalrus_sled_end, func_802B98C0}, - {BS_7E_WALRUS_SLED, bswalrus_sled_jump_init, bswalrus_sled_jump_update, bswalrus_sled_jump_end, func_802B98C0}, - {BS_7F_DIVE_OW, func_802A7BD0, func_802A7CA8, func_802A7D74, func_80296590}, - {0x00000080, bswalrus_timeout_init, func_802B9830, func_802B9880, func_80296590}, - {0x00000081, func_802B90D0, func_802B9130, func_802B917C, func_802B98C0}, - {0x00000082, func_802B95A0, func_802B963C, func_802B976C, func_802B98C0}, - {BS_85_BEE_IDLE, func_802A1080, func_802A10D4, func_802A117C, func_802B5350}, - {BS_BEE_WALK, func_802A11A4, func_802A1214, func_802A12D4, func_802B5350}, - {BS_BEE_JUMP, func_802A12FC, func_802A1438, func_802A163C, func_802B5350}, - {BS_88_BEE_FALL, func_802A1664, func_802A170C, func_802A18C8, func_802B5350}, - {BS_BEE_OW, func_802A1B68, func_802A1B88, func_802A1BA8, func_802B5350}, - {BS_BEE_DIE, bsbeemain_die_init, func_802A1DD8, func_802A1F2C, func_80296590}, - {0x0000008B, func_802A0590, func_802A0630, func_802A0704, func_802B5350}, - {BS_BEE_FLY, bsbeefly_enter, bsbeefly_update, bsbeefly_end, func_802B5350}, - {BS_8D_CROC_LOCKED, bscroc_locked_enter, bscroc_locked_update, bscroc_locked_end, func_802B5350}, - {0x0000008E, func_8029F398, func_8029F3F4, func_8029F440, func_802B5350}, - {BS_8F_PUMPKIN_LOCKED, func_802B34A0, func_802B34F8, func_802B353C, func_802B5350}, - {BS_FLY_OW, func_802A4D30, func_802A4D50, func_802A4D70, func_802A505C}, - {BS_92_ANT_DRONE, bsant_drone_init, bsant_drone_update, bsant_drone_end, bsdrone_interrupt}, - {BS_93_PUMPKIN_DRONE, bspumpkin_drone_init, bspumpkin_drone_update, bspumpkin_drone_end, bsdrone_interrupt}, - {BS_94_CROC_DRONE, bscroc_drone_init, bscroc_drone_update, bscroc_drone_end, bsdrone_interrupt}, - {BS_95_WALRUS_DRONE, bswalrus_drone_init, bswalrus_drone_update, bswalrus_drone_end, bsdrone_interrupt}, - {BS_96_SWIM_DRONE, bsswim_drone_init, bsswim_drone_update, bsswim_drone_end, bsdrone_interrupt}, - {BS_97_DIVE_DRONE, bsbswim_drone_init, bsbswim_drone_update, bsbswim_drone_end, bsdrone_interrupt}, - {BS_98_WALK_DRONE, bswalk_drone_init, bswalk_drone_update, bswalk_drone_end, bsdrone_interrupt}, - {0x00000099, func_802A50B0, func_802A50D8, func_802A50F8, bsdrone_interrupt}, - {BS_9A_BTROT_DRONE, bsbtrot_drone_init, bsbtrot_drone_update, bsbtrot_drone_end, bsdrone_interrupt}, - {BS_9B_LONGLEG_DRONE, bsblongleg_drone_init, bsblongleg_drone_update, bsblongleg_drone_end, bsdrone_interrupt}, - {0x0000009C, bswalrus_sled_drone_init, bswalrus_sled_drone_update, bswalrus_sled_drone_end, bsdrone_interrupt}, - {BS_9D_BEE_DRONE, bsbee_drone_init, bsbee_drone_update, bsbee_drone_end, bsdrone_interrupt}, - {0x0000009E, func_802ABCCC, func_802ABD0C, func_802ABD40, func_802ABD60}, - {BS_ANT_BOUNCE, bsant_bounce_init, bsant_bounce_update, bsant_bounce_end, func_80296590}, - {BS_PUMPKIN_BOUNCE, bspumpkin_rebound_init, bspumpkin_rebound_update, bspumpkin_rebound_end, func_80296590}, - {BS_CROC_BOUNCE, bscroc_bounce_init, bscroc_bounce_update, bscroc_bounce_end, func_80296590}, - {BS_WALRUS_BOUNCE, bswalrus_bounce_init, bswalrus_bounce_update, bswalrus_bounce_end, func_80296590}, - {BS_BEE_BOUNCE, func_802A1BC8, func_802A1BE8, func_802A1C08, func_80296590}, - {BS_A4_WONDERWING_DRONE, bsbwhirl_drone_init, bsbwhirl_drone_update, bsbwhirl_drone_end, func_80296608}, - {BS_A5_WONDERWING_UNKA5, func_802AADBC, func_802AAE08, func_802AAE4C, func_80296608}, - {0} -}; - -/* .bss */ -void (*D_8037C3B0)(); - -/* .code */ -void func_802958A0(void){ - s32 i; - bsMap *iPtr; - - for(i = 0; D_80363824[i].uid != 0; i++){ - bsList_setInitMethod(D_80363824[i].uid, D_80363824[i].behavior.init_func); - bsList_setUpdateMethod(D_80363824[i].uid, D_80363824[i].behavior.update_func); - bsList_setEndMethod(D_80363824[i].uid, D_80363824[i].behavior.end_func); - bsList_setInterruptMethod(D_80363824[i].uid, D_80363824[i].behavior.interrupt_func); - } -} - -void func_80295914(void){ - D_80363820 = 1; - D_8037C3B0 = NULL; - update_void_return_Location(); - playerPosition_init(); - snackerctl_reset(); - func_80291910(); - badrone_init(); - bafalldamage_init(); - baflag_clearAll(); - func_8028B6FC(); - func_80291590(); - bakey_reset(); - bastick_reset(); - bainput_reset(); - bsList_clearAll(); - bs_clearState(); - babounds_init(); - func_80296C30(); - baphysics_init(); - baiFrame_reset(); - pitch_reset(); - climbClear(); - balookat_init(); - roll_reset(); - func_802992F0(); - func_80294DD8(); - func_8029CF6C(); - func_8029DFF8(); - func_80290B6C(); - baeyes_reset(); - func_80290070(); - func_80290664(); - stateTimer_init(); - eggShatter_init(); - bacarry_init(); - func_80293DA4(); - baAnim_init(); - baModel_reset(); - baMarker_init(); - basfx_reset(); - func_8029A4D0(); - func_8029ADCC(); - hazards_reset(); - func_802958A0(); -} - -void func_80295A8C(void){ - - stateTimer_set(STATE_TIMER_2_LONGLEG, bsStoredState_getLongLegTimer()); - stateTimer_set(STATE_TIMER_3_TURBO_TALON, bsStoredState_getTurboTimer()); - if(func_8028ADB4()) - bs_setState(badrone_enter()); - else - bs_setState(bs_getIdleState()); - -} - -void func_80295B04(void){ - f32 sp24; - enum bs_e sp20 = bs_getState(); - bool is_in_talon_trot; - - sp24 = (bslongleg_inSet(sp20)) ? stateTimer_get(STATE_TIMER_2_LONGLEG) : 0.0f; - bsStoredState_setLongLegTimer(sp24); - sp24 = 0.0f; - is_in_talon_trot = false; - if(bsbtrot_inSet(sp20)){ - sp24 = stateTimer_get(STATE_TIMER_3_TURBO_TALON); - is_in_talon_trot = true; - } - - bsStoredState_setTrot(is_in_talon_trot); - bsStoredState_setTurboTimer(sp24); - bs_setState(BS_5A_LOADZONE); - baMarker_free(); - func_8029065C(); - stateTimer_free(); - eggShatter_free(); - baModel_free(); - baAnim_free(); - func_80293E88(); - bacarry_end(); - basfx_free(); - func_8029A54C(); - func_8029ADA8(); - freeHazardSfxId(); - D_80363820 = 0; -} - -void func_80295C08(void (* arg0)(void)){ - D_8037C3B0 = arg0; -} - -void func_80295C14(void){ - func_802964B8(); - balookat_update(); - stateTimer_update(); - func_8029E100(); - pfsManager_update();//controller_update - disableInput_set(); - bakey_update(); - bastick_update(); - bainput_update(); //dive_cooldown_update - bs_updateState(); - baphysics_update(); - playerPosition_applyOffset(); - bafalldamage_update(); - func_80293F0C(); - pitch_update(); - roll_update(); - func_802993C8();//yaw update - func_802906D8(); - baAnim_update(); - func_8029A554(); - func_80298344(); //climb_cooldown_update - func_80290108(); - eggShatter_update(); - baeyes_update(); - baModel_update(); - playerPosition_func_8029842C(); - baMarker_update(); - bacarry_update(); - snackerctl_update(); - func_8028B71C(); - hazards_update(); - baiFrame_update(); - func_80294E60(); - cameraMode_update(); - func_802919A0(); - if(D_8037C3B0){ - D_8037C3B0(); - D_8037C3B0 = NULL; - } - basfx_update(); - babounds_update();//voidOut_update -} - -void func_80295D74(void){ - if(D_80363820){ - baAnim_defrag(); - baModel_defrag(); - eggShatter_defrag(); - func_80294750(); - func_8029AF1C(); - } -} diff --git a/src/core2/ba/ba_statusflags.c b/src/core2/ba/ba_statusflags.c index c0707812e..866f0e15d 100644 --- a/src/core2/ba/ba_statusflags.c +++ b/src/core2/ba/ba_statusflags.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9C170.c #include #include "functions.h" #include "variables.h" @@ -329,7 +330,7 @@ void func_8032417C(struct56s *arg0, f32 arg1, f32 arg2[3], f32 arg3[3]) { func_80341180(var_f0, sp64, 3, sp60, sp44); ml_vec3f_diff_copy(arg2, sp44, sp50); ml_vec3f_normalize(arg2); - func_8025727C(sp44[0], sp44[1], sp44[2], sp50[0], sp50[1], sp50[2], &arg3[0], &arg3[1]); + ml_horizontal_and_vertical_angles(sp44[0], sp44[1], sp44[2], sp50[0], sp50[1], sp50[2], &arg3[0], &arg3[1]); arg3[0] = mlNormalizeAngle(-arg3[0]); arg3[2] = 0.0f; } diff --git a/src/core2/ba/ba_stickinterp.c b/src/core2/ba/ba_stickinterp.c index f1c65a47f..1090b41fa 100644 --- a/src/core2/ba/ba_stickinterp.c +++ b/src/core2/ba/ba_stickinterp.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_11040.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_underwater.c b/src/core2/ba/ba_underwater.c index 00febdde0..b5f0b42b9 100644 --- a/src/core2/ba/ba_underwater.c +++ b/src/core2/ba/ba_underwater.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_15F20.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_yaw.c b/src/core2/ba/ba_yaw.c index dc08799af..1fd1402d2 100644 --- a/src/core2/ba/ba_yaw.c +++ b/src/core2/ba/ba_yaw.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_12360.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_bounds.c b/src/core2/ba/babounds.c similarity index 93% rename from src/core2/ba/ba_bounds.c rename to src/core2/ba/babounds.c index ebf619b7e..45bdd0a39 100644 --- a/src/core2/ba/ba_bounds.c +++ b/src/core2/ba/babounds.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/babounds.c #include #include "functions.h" #include "variables.h" @@ -32,7 +33,7 @@ void babounds_init(void){ void babounds_update(void){ f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); if(!ml_vec3f_inside_box_vec3f(sp1C, D_8037C3C0.unkC, D_8037C3C0.unk0)){ if(D_8037C3C0.unk18 == 0){ D_8037C3C0.unk18 = 1; diff --git a/src/core2/ba/ba_buzz.c b/src/core2/ba/babuzz.c similarity index 98% rename from src/core2/ba/ba_buzz.c rename to src/core2/ba/babuzz.c index 216cf5abb..87e6371cb 100644 --- a/src/core2/ba/ba_buzz.c +++ b/src/core2/ba/babuzz.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/babuzz.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_eyes.c b/src/core2/ba/baeyes.c similarity index 88% rename from src/core2/ba/ba_eyes.c rename to src/core2/ba/baeyes.c index 18e972bd4..ac8d357e0 100644 --- a/src/core2/ba/ba_eyes.c +++ b/src/core2/ba/baeyes.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/baeyes.c #include #include "functions.h" #include "variables.h" @@ -13,9 +14,9 @@ BaEyes baEyes[4]; f32 baeyes_getEyePosition(s32 id){ switch (id) { case 0: - return func_8029DFC8(); + return modelAppendages_showBanjosLeftEye(); case 1: - return func_8029DFD4(); + return modelAppendages_showBanjosRightEye(); case 2: return 0.0f; case 3: @@ -29,10 +30,10 @@ f32 baeyes_getEyePosition(s32 id){ void baeyes_setEyePosition(s32 id, f32 position){ switch(id){ case 0: - func_8029E0C4(position); + modelAppendages_setBanjosLeftEyeVisibility(position); break; case 1: - func_8029E0D0(position); + modelAppendages_setBanjosRightEyeVisibility(position); break; case 2: break; @@ -99,7 +100,7 @@ void baeyes_update(void){ break; case 3://L80292FBC case 4://L80292FBC - eye_position -= dt/baEyes[i].duration; + eye_position -= dt / baEyes[i].duration; if(eye_position < 0.0){ eye_position = 0.0f; baEyes[i].state = 0; diff --git a/src/core2/ba/ba_flag.c b/src/core2/ba/baflag.c similarity index 95% rename from src/core2/ba/ba_flag.c rename to src/core2/ba/baflag.c index 0ada884b8..64dc73ede 100644 --- a/src/core2/ba/ba_flag.c +++ b/src/core2/ba/baflag.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/baflag.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_input.c b/src/core2/ba/bainput.c similarity index 98% rename from src/core2/ba/ba_input.c rename to src/core2/ba/bainput.c index e87349cb0..b85165166 100644 --- a/src/core2/ba/ba_input.c +++ b/src/core2/ba/bainput.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bainput.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_key.c b/src/core2/ba/bakey.c similarity index 98% rename from src/core2/ba/ba_key.c rename to src/core2/ba/bakey.c index 2100bb0eb..605791360 100644 --- a/src/core2/ba/ba_key.c +++ b/src/core2/ba/bakey.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bakey.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_lookat.c b/src/core2/ba/balookat.c similarity index 98% rename from src/core2/ba/ba_lookat.c rename to src/core2/ba/balookat.c index afd917717..ba4281efa 100644 --- a/src/core2/ba/ba_lookat.c +++ b/src/core2/ba/balookat.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/balookat.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_sfx.c b/src/core2/ba/basfx.c similarity index 99% rename from src/core2/ba/ba_sfx.c rename to src/core2/ba/basfx.c index c7c10fe34..d091e2a98 100644 --- a/src/core2/ba/ba_sfx.c +++ b/src/core2/ba/basfx.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/basfx.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_stick.c b/src/core2/ba/bastick.c similarity index 98% rename from src/core2/ba/ba_stick.c rename to src/core2/ba/bastick.c index 63b2ce6e2..4e56e29ff 100644 --- a/src/core2/ba/ba_stick.c +++ b/src/core2/ba/bastick.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bastick.c #include #include "core1/core1.h" #include "functions.h" @@ -139,7 +140,7 @@ void bastick_setZoneMax(s32 zone_id, f32 value){ f32 bastick_getAngleRelativeToBanjo(void){ f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); return viewport_adjustAngleToRight(sp1C, bastick_getAngle()); } diff --git a/src/core2/ba/ba_timer.c b/src/core2/ba/batimer.c similarity index 93% rename from src/core2/ba/ba_timer.c rename to src/core2/ba/batimer.c index eec243169..87cc37caa 100644 --- a/src/core2/ba/ba_timer.c +++ b/src/core2/ba/batimer.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/batimer.c #include #include "functions.h" #include "variables.h" @@ -15,10 +16,10 @@ void batimer_incrementBy(s32 id, f32 inc_value_sec){ s_batimer.value[id] += inc_value_sec; } -int batimer_decrement(s32 id){ +bool batimer_decrement(s32 id){ s_batimer.last[id] = s_batimer.value[id]; if(0.0f == s_batimer.value[id]){ - return 0; + return false; } s_batimer.value[id] = ml_max_f(0.0f, s_batimer.value[id] - time_getDelta()); return s_batimer.value[id] == 0.0f; diff --git a/src/core2/ba/bsmethods.c b/src/core2/ba/bsmethods.c new file mode 100644 index 000000000..25e520266 --- /dev/null +++ b/src/core2/ba/bsmethods.c @@ -0,0 +1,335 @@ +// BanjoDecomp: core2/bsmethods.c +#include +#include "functions.h" +#include "variables.h" +#include "bsint.h" +#include "bs_funcs.h" +#include "core2/statetimer.h" +#include "core2/ba/physics.h" +#include "core2/snackerctl.h" + +u8 D_80363820 = 0; + +bsMap bsMethodsTable[] = { + //Banjo States Initialize Funcitons Update Functions End Functions Interrupt Functions + {BS_1_IDLE, bsstand_init, bsstand_update, bsstand_end, func_802B5350}, + {BS_2_WALK_SLOW, bswalk_slow_init, bswalk_slow_upate, NULL, func_802B5350}, + {BS_3_WALK, bswalk_init, bswalk_update, NULL, func_802B5350}, + {BS_4_WALK_FAST, bswalk_fast_init, bswalk_fast_update, bswalk_fast_end, func_802B5350}, + {BS_5_JUMP, bsjump_init, bsjump_update, bsjump_end, func_80296608}, + {BS_6_CLAW, bsclaw_init, bsclaw_update, bsclaw_end, func_80296608}, + {BS_7_CROUCH, bscrouch_init, bscrouch_update, bscrouch_end, func_802B5350}, + {BS_8_BTROT_JUMP, bsbtrot_jump_init, bsbtrot_jump_update, bsbtrot_jump_end, func_802B5350}, + {BS_C_SKID, bsturn_init, bsturn_update, bsturn_end, func_802B5350}, + {BS_D_TIMEOUT_TRANSFORMATION, timeout_transformation_init, timeout_transformation_update, timeout_transformation_end, func_80296590}, + {BS_E_OW, bsow_init, bsow_update, bsow_end, func_80296590}, + {BS_F_BBUSTER, bsbbuster_init, bsbbuster_update, bsbbuster_end, func_80296608}, + {BS_10_BFLAP, bsbflap_init, bsbflap_update, bsbflap_end, func_80296608}, + {BS_11_BPECK, bsbpeck_init, bsbpeck_update, bsbpeck_end, func_80296608}, + {BS_12_BFLIP, bsbflip_init, bsbflip_update, bsbflip_end, func_80296608}, + {BS_13_BBARGE, bsbarge_init, bsbarge_update, bsbarge_end, func_80296608}, + {BS_14_BTROT_ENTER, bsbtrot_enter_init, bsbtrot_enter_update, bsbtrot_enter_end, func_802B5350}, + {BS_15_BTROT_IDLE, bsbtrot_stand_init, bsbtrot_stand_update, bsbtrot_stand_end, func_802B5350}, + {BS_16_BTROT_WALK, bsbtrot_walk_init, bsbtrot_walk_update, bsbtrot_walk_end, func_802B5350}, + {BS_17_BTROT_EXIT, bsbtrot_exit_init, bsbtrot_exit_update, bsbtrot_exit_end, func_802B5350}, + {BS_18_FLY_KNOCKBACK, bsbfly_knockback_init, bsbfly_knockback_update, bsbfly_knockback_end, func_80296608}, + {BS_1A_WONDERWING_ENTER, bsbwhirl_enter_init, bsbwhirl_enter_update, bsbwhirl_enter_end, func_80296608}, + {BS_1B_WONDERWING_IDLE, bsbwhirl_stand_init, bsbwhirl_stand_update, bsbwhirl_stand_end, func_80296608}, + {BS_1C_WONDERWING_WALK, bsbwhirl_walk_init, bsbwhirl_walk_update, bsbwhirl_walk_end, func_80296608}, + {BS_1D_WONDERWING_JUMP, bsbwhirl_jump_init, bsbwhirl_jump_update, bsbwhirl_jump_end, func_80296608}, + {BS_1E_WONDERWING_EXIT, bsbwhirl_exit_init, bsbwhirl_exit_update, bsbwhirl_exit_end, func_80296608}, + {BS_9_EGG_HEAD, bsegghead_init, bsegghead_update, bsegghead_end, func_802B5350}, + {BS_A_EGG_ASS, bseggass_init, bseggass_update, bseggass_end, func_802B5350}, + {BS_1F_WALK_CREEP, bswalk_creep_init, bswalk_creep_update, NULL, func_802B5350}, + {BS_20_LANDING, bsstand_landing_init, bsstand_landing_update, NULL, func_802B5350}, + {BS_21_BSHOCK_CHARGE, bsbshock_charge_init, bsbshock_charge_update, bsbshock_charge_end, func_80296608}, + {BS_22_BSHOCK_JUMP, bsbshock_init, bsbshock_update, bsbshock_end, func_80296608}, + {BS_23_FLY_ENTER, bsbfly_enter_init, bsbfly_enter_update, bsbfly_enter_end, func_802A505C}, + {BS_24_FLY, bsbfly_init, bsbfly_update, bsbfly_end, func_802A505C}, + {BS_25_LONGLEG_ENTER, bsblongleg_enter_init, bsblongleg_enter_update, bsblongleg_enter_end, func_802B5350}, + {BS_26_LONGLEG_IDLE, bsblongleg_stand_enter, bsblongleg_stand_update, bsblongleg_stand_end, func_802B5350}, + {BS_27_LONGLEG_WALK, bsblongleg_walk_init, bsblongleg_walk_update, bsblongleg_walk_end, func_802B5350}, + {BS_28_LONGLEG_JUMP, bsblongleg_jump_init, bsblongleg_jump_update, bsblongleg_jump_end, func_80296608}, + {BS_29_LONGLEG_EXIT, bsblongleg_exit_init, bsblongleg_exit_update, bsblongleg_exit_end, func_802B5350}, + {BS_2A_BOMB, bsbfly_bomb_init, bsbfly_bomb_update, bsbfly_bomb_end, func_802A505C}, + {BS_2B_DIVE_IDLE, bsbdive_idle_init, bsbdive_idle_update, bsbdive_idle_end, func_80296608}, + {BS_2C_DIVE_B, bsbdiveb_init, bsbdiveb_update, bsbdiveb_end, func_80296608}, + {BS_2D_SWIM_IDLE, bsswim_idle_init, bsswim_idle_update, bsswim_idle_end, func_80296608}, + {BS_2E_SWIM, bsswim_swim_init, bsswim_swim_update, bsswim_swim_end, func_80296608}, + {BS_2F_FALL, bsjump_fall_init, bsjump_fall_update, bsjump_fall_end, func_80296608}, + {BS_30_DIVE_ENTER, bsSwim_dive_init, bsSwim_dive_update, bsSwim_dive_end, func_80296608}, + {BS_31_ROLL, bstwirl_init, bstwirl_update, bstwirl_end, func_802B5350}, + {BS_32_SLIDE, bsslide_init, bsslide_update, bsslide_end, func_802B5350}, + {BS_33_WASHY_UNKNOWN, bswashy_init, bswashy_update, bswashy_end, func_802B9D00}, + {BS_34_JIG_NOTEDOOR, bsjig_notedoor_init, bsjig_notedoor_update, bsjig_notedoor_end, func_80296590}, + {BS_35_ANT_IDLE, bsant_idle_init, bsant_idle_update, bsant_idle_end, func_802B5350}, + {BS_36_ANT_WALK, bsant_walk_init, bsant_walk_update, bsant_walk_end, func_802B5350}, + {BS_37_ANT_WALK, bsant_jump_init, bsant_jump_update, bsant_jump_end, func_802B5350}, + {BS_39_DIVE_A, bsswim_divea_init, bsswim_divea_update, bsswim_divea_end, func_80296608}, + {BS_3A_CARRY_IDLE, bscarry_idle_init, bscarry_idle_update, bscarry_idle_end, bscarry_interrupt}, + {BS_3B_CARRY_WALK, bscarry_walk_init, bscarry_walk_update, bscarry_walk_end, bscarry_interrupt}, + {BS_3C_TALK, bstalk_init, bstalk_update, bstalk_end, bstalk_interrupt}, + {BS_3D_FALL_TUMBLING, bsjump_tumble_init, bsjump_tumble_update, bsjump_tumble_end, func_80296608}, + {BS_38_ANT_FALL, bsant_fall_init, bsant_fall_update, bsant_fall_end, func_80296590}, + {BS_3E_ANT_OW, bsant_ow_init, bsant_ow_update, bsant_ow_end, func_80296590}, + {BS_3F_UNKNOWN, func_802B1BF4, func_802B1CF8, func_802B1DA4, func_80296590}, + {BS_40_PUMPKIN_FLUSH, bspumpkin_flush_init, bspumpkin_flush_update, bspumpkin_flush_end, func_80296590}, + {BS_41_DIE, bsdie_init, bsdie_update, bsdie_end, func_80296590}, + {BS_42_DINGPOT, bsfly_dingpotLaunch_init, bsfly_dingpotLaunch_update, bsfly_dingpotLaunch_end, func_80296590}, + {BS_43_ANT_DIE, bsant_die_init, bsant_die_update, bsant_die_end, func_80296590}, + {BS_44_JIG_JIGGY, bsjig_jiggy_init, bsjig_jiggy_update, bsjig_jiggy_end, bsjig_jiggy_interrupt}, + {BS_45_BTROT_SLIDE, bsbtrot_slide_init, bsbtrot_slide_update, bsbtrot_slide_end, func_802B5350}, + {BS_46_UNKNOWN, func_802A2098, func_802A2130, func_802A2054, func_80296590}, + {BS_48_PUMPKIN_IDLE, bspumpkin_idle_init, bspumpkin_idle_update, bspumpkin_idle_end, func_802B5350}, + {BS_49_PUMPKIN_WALK, bspumpkin_walk_init, bspumpkin_walk_update, bspumpkin_walk_end, func_802B5350}, + {BS_4A_PUMPKIN_JUMP, bspumpkin_jump_init, bspumpkin_jump_update, bspumpkin_jump_end, func_802B5350}, + {BS_4B_PUMPKIN_FALL, bspumpkin_fall_init, bspumpkin_fall_update, bspumpkin_fall_end, func_802B5350}, + {BS_4C_LANDING_IN_WATER, bsbswim_landingInWater_init, bsbswim_landingInWater_update, bsbswim_landingInWater_end, func_80296608}, + {BS_4D_PUMPKIN_OW, __bspumpkin_ow_init, __bspumpkin_ow_update, __bspumpkin_ow_end, func_80296590}, + {BS_4E_PUMPKIN_DIE, bspumpkin_die_init, bspumpkin_die_update, bspumpkin_die_end, func_80296590}, + {BS_4F_CLIMB_IDLE, bsclimb_idle_init, bsclimb_idle_update, bsclimb_idle_end, func_802ABD60}, + {BS_50_CLIMB_MOVE, bsclimb_move_init, bsclimb_move_update, bsclimb_move_end, func_802ABD60}, + {BS_51_CLIMB_EXIT, bsjump_climbExit_init, bsjump_climbExit_update, bsjump_climbExit_end, func_80296608}, + {BS_52_SURF, bssurf_init, bssurf_update, bssurf_end, func_802B60D8}, + {BS_53_TIMEOUT_BANJO, timeout_banjo_init, timeout_banjo_update, timeout_banjo_end, func_80296590}, + {BS_55_LONGLEG_SLIDE, bsblongleg_slide_init, bsblongleg_slide_update, bsblongleg_slide_end, func_802B5350}, + {BS_56_RECOIL, rebound_init, rebound_update, rebound_end, func_80296590}, + {BS_57_BOMB_END, bsbfly_beakbombend_init, bsbfly_beakbombend_update, bsbfly_beakbombend_end, func_802A505C}, + {BS_58_BEAKBOMB_CRASH, bsbfly_beakbomb_crash_init, func_802A48B4, func_802A4A40, func_80296590}, + {BS_59_BFLY_UNK59, func_802A4CD0, func_802A4CF0, func_802A4D10, func_802A505C}, + {BS_54_SWIM_DIE, bsbswim_die_init, bsbswim_die_update, bsbswim_die_end, func_80296590}, + {BS_5B_CARRY_THROW, bsthrow_init, bsthrow_update, bsthrow_end, bsthrow_interrupt}, + {BS_5E_CROC_IDLE, bscroc_idle_init, bscroc_idle_update, bscroc_idle_end, func_802B5350}, + {BS_5F_CROC_WALK, bscroc_walk_init, bscroc_walk_update, bscroc_walk_end, func_802B5350}, + {BS_60_CROC_JUMP, bscroc_jump_init, bscroc_jump_update, bscroc_jump_end, func_802B5350}, + {BS_61_CROC_FALL, bscroc_fall_init, bscroc_fall_update, bscroc_fall_end, func_802B5350}, + {BS_62_LONGLEG_LOCKED, bsblongleg_locked_init, bsblongleg_locked_update, bsblongleg_locked_end, func_80296608}, + {BS_63_CROC_OW, bscroc_ow_init, bscroc_ow_update, bscroc_ow_end, func_80296590}, + {BS_64_CROC_DIE, bscroc_die_init, bscroc_die_update, bscroc_die_end, func_80296590}, + {BS_67_WALRUS_IDLE, bswalrus_idle_init, bswalrus_idle_update, bswalrus_idle_end, func_802B5350}, + {BS_68_WALRUS_WALK, bswalrus_walk_init, bswalrus_walk_update, bswalrus_walk_end, func_802B5350}, + {BS_69_WALRUS_JUMP, bswalrus_jump_init, bswalrus_jump_update, bswalrus_jump_end, func_802B5350}, + {BS_6A_WALRUS_FALL, bswalrus_fall_init, bswalrus_fall_update, bswalrus_fall_end, func_802B5350}, + {BS_6B_BEE_LOCKED, bsbee_locked_init, bsbee_locked_update, bsbee_locked_end, func_80296608}, + {BS_6C_WALRUS_OW, bswalrus_ow_init, bswalrus_ow_update, bswalrus_ow_end, func_80296590}, + {BS_6D_WALRUS_DIE, bswalrus_die_init, bswalrus_die_update, bswalrus_die_end, func_80296590}, + {BS_6E_CROC_BITE, bscroc_bite_init, bscroc_bite_update, bscroc_bite_end, func_802B5350}, + {BS_6F_CROC_EAT_BAD, bscroc_eat_bad_init, bscroc_eat_bad_update, bscroc_eat_bad_end, func_802B5350}, + {BS_70_CROC_EAT_GOOD, bscroc_eat_good_init, bscroc_eat_good_update, bscroc_eat_good_end, func_802B5350}, + {BS_71_BTROT_FALL, bsbtrot_fall_init, bsbtrot_fall_update, bsbtrot_fall_end, func_80296608}, + {BS_72_SPLAT, bssplat_init, bssplat_update, bssplat_end, func_80296590}, + {BS_73_UNKNOWN, bsrest_bs73unknown_init, bsrest_bs73unknown_update, bsrest_bs73unknown_end, func_80296608}, + {BS_74_UNKNOWN, bsrest_bs74unknown_init, bsrest_bs74unknown_update, bsrest_bs74unknown_end, func_80296608}, + {BS_75_UNKNOWN, bsrest_bs75unknown_init, bsrest_bs75unknown_update, bsrest_bs75unknown_end, func_80296608}, + {BS_76_BFLY_LOCKED, bsbfly_locked_init, bsbfly_locked_update, bsbfly_locked_end, func_80296608}, + {BS_77_SWIM_LOOKAT_DRONE, bsswim_lookat_init, bsswim_lookat_update, bsswim_lookat_end, func_80296608}, + {BS_78_DIVE_LOOKAT_DRONE, bsbswim_lookat_init, bsbswim_lookat_update, bsbswim_lookat_end, func_80296608}, + {BS_79_BTROT_LOCKED, bsbtrot_locked_init, bsbtrot_locked_update, bsbtrot_locked_end, func_80296608}, + {BS_7A_WALK_MUD, bswalk_mud_init, bswalk_mud_update, NULL, func_80296608}, + {BS_7B_BTROT_OW, bsbtrot_ow_init, bsbtrot_ow_update, bsbtrot_ow_end, func_80296590}, + {BS_7C_SLED, bssled_init, bssled_update, bssled_end, bssled_interrupt}, + {BS_7D_WALRUS_SLED, bswalrus_sled_init, bswalrus_sled_update, bswalrus_sled_end, func_802B98C0}, + {BS_7E_WALRUS_SLED, bswalrus_sled_jump_init, bswalrus_sled_jump_update, bswalrus_sled_jump_end, func_802B98C0}, + {BS_7F_DIVE_OW, bsbswim_ow_init, bsbswim_ow_update, bsbswim_ow_end, func_80296590}, + {BS_80_WALRUS_SLED_LOSE, bswalrus_timeout_init, bswalrus_timeout_update, bswalrus_timeout_end, func_80296590}, + {BS_81_WALRUS_SLED_LOCKED, bswalrus_sledlocked_init, bswalrus_sledlocked_update, bswalrus_sledlocked_end, func_802B98C0}, + {BS_82_WALRUS_SLED_LOSE_IN_AIR,bswalrus_sledloseinair_init, bswalrus_sledloseinair_update, bswalrus_sledloseinair_end, func_802B98C0}, + {BS_85_BEE_IDLE, bsbeemain_idle_init, bsbeemain_idle_update, bsbeemain_idle_end, func_802B5350}, + {BS_86_BEE_WALK, bsbeemain_walk_init, bsbeemain_walk_update, bsbeemain_walk_end, func_802B5350}, + {BS_87_BEE_JUMP, bsbeemain_jump_init, bsbeemain_jump_update, bsbeemain_jump_end, func_802B5350}, + {BS_88_BEE_FALL, bsbeemain_fall_init, bsbeemain_fall_update, bsbeemain_fall_end, func_802B5350}, + {BS_89_BEE_OW, bsbeemain_ow_init, bsbeemain_ow_update, bsbeemain_ow_end, func_802B5350}, + {BS_8A_BEE_DIE, bsbeemain_die_init, bsbeemain_die_update, bsbeemain_die_end, func_80296590}, + {BS_8B_UNKNOWN, bsbeefly_bs8Bunknown_init, bsbeefly_bs8Bunknown_update, bsbeefly_bs8Bunknown_end, func_802B5350}, + {BS_8C_BEE_FLY, bsbeefly_enter, bsbeefly_update, bsbeefly_end, func_802B5350}, + {BS_8D_CROC_LOCKED, bscroc_locked_enter, bscroc_locked_update, bscroc_locked_end, func_802B5350}, + {BS_8E_ANT_LOCKED, bsant_locked_init, bsant_locked_update, bsant_locked_end, func_802B5350}, + {BS_8F_PUMPKIN_LOCKED, bspumpkin_locked_init, bspumpkin_locked_update, bspumpkin_locked_end, func_802B5350}, + {BS_91_FLY_OW, bsbfly_ow_init, bsbfly_ow_update, bsbfly_ow_end, func_802A505C}, + {BS_92_ANT_DRONE, bsant_drone_init, bsant_drone_update, bsant_drone_end, bsdrone_interrupt}, + {BS_93_PUMPKIN_DRONE, bspumpkin_drone_init, bspumpkin_drone_update, bspumpkin_drone_end, bsdrone_interrupt}, + {BS_94_CROC_DRONE, bscroc_drone_init, bscroc_drone_update, bscroc_drone_end, bsdrone_interrupt}, + {BS_95_WALRUS_DRONE, bswalrus_drone_init, bswalrus_drone_update, bswalrus_drone_end, bsdrone_interrupt}, + {BS_96_SWIM_DRONE, bsswim_drone_init, bsswim_drone_update, bsswim_drone_end, bsdrone_interrupt}, + {BS_97_DIVE_DRONE, bsbswim_drone_init, bsbswim_drone_update, bsbswim_drone_end, bsdrone_interrupt}, + {BS_98_WALK_DRONE, bswalk_drone_init, bswalk_drone_update, bswalk_drone_end, bsdrone_interrupt}, + {BS_99_BFLY_DRONE, bsbfly_drone_init, bsbfly_drone_update, bsbfly_drone_end, bsdrone_interrupt}, + {BS_9A_BTROT_DRONE, bsbtrot_drone_init, bsbtrot_drone_update, bsbtrot_drone_end, bsdrone_interrupt}, + {BS_9B_LONGLEG_DRONE, bsblongleg_drone_init, bsblongleg_drone_update, bsblongleg_drone_end, bsdrone_interrupt}, + {BS_9C_WALRUS_SLED_DRONE, bswalrus_sled_drone_init, bswalrus_sled_drone_update, bswalrus_sled_drone_end, bsdrone_interrupt}, + {BS_9D_BEE_DRONE, bsbee_drone_init, bsbee_drone_update, bsbee_drone_end, bsdrone_interrupt}, + {BS_9E_CLIMB_LOCKED, bsclimb_locked_init, bsclimb_locked_update, bsclimb_locked_end, func_802ABD60}, + {BS_9F_ANT_BOUNCE, bsant_bounce_init, bsant_bounce_update, bsant_bounce_end, func_80296590}, + {BS_A0_ANT_BOUNCE, bspumpkin_rebound_init, bspumpkin_rebound_update, bspumpkin_rebound_end, func_80296590}, + {BS_A1_CROC_BOUNCE, bscroc_bounce_init, bscroc_bounce_update, bscroc_bounce_end, func_80296590}, + {BS_A2_WALRUS_BOUNCE, bswalrus_bounce_init, bswalrus_bounce_update, bswalrus_bounce_end, func_80296590}, + {BS_A3_BEE_BOUNCE, bsbeemain_bounce_init, bsbeemain_bounce_update, bsbeemain_bounce_end, func_80296590}, + {BS_A4_WONDERWING_DRONE, bsbwhirl_drone_init, bsbwhirl_drone_update, bsbwhirl_drone_end, func_80296608}, + {BS_A5_WONDERWING_UNKA5, bsbwhirl_bsA5unknown_init, bsbwhirl_bsA5unknown_update, bsbwhirl_bsA5unknown_end, func_80296608}, + {0} +}; + +/* .bss */ +void (*D_8037C3B0)(); + +/* .code */ +void bsmethods_setMethods(void){ + s32 index; + bsMap *iPtr; + + for(index = 0; bsMethodsTable[index].uid != 0; index++){ + bsList_setInitMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.init_func); + bsList_setUpdateMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.update_func); + bsList_setEndMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.end_func); + bsList_setInterruptMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.interrupt_func); + } +} + +void bsmethods_reset(void){ + D_80363820 = 1; + D_8037C3B0 = NULL; + update_void_return_Location(); + playerPosition_init(); + snackerctl_reset(); + func_80291910(); + badrone_init(); + bafalldamage_init(); + baflag_clearAll(); + func_8028B6FC(); + func_80291590(); + bakey_reset(); + bastick_reset(); + bainput_reset(); + bsList_clearAll(); + bs_clearState(); + babounds_init(); + func_80296C30(); + baphysics_init(); + baiFrame_reset(); + pitch_reset(); + climb_clear(); + balookat_init(); + roll_reset(); + func_802992F0(); + func_80294DD8(); + func_8029CF6C(); + modelAppendages_reset(); + func_80290B6C(); + baeyes_reset(); + func_80290070(); + func_80290664(); + stateTimer_init(); + eggShatter_init(); + bacarry_init(); + func_80293DA4(); + baAnim_init(); + baModel_reset(); + baMarker_init(); + basfx_reset(); + func_8029A4D0(); + func_8029ADCC(); + hazards_reset(); + bsmethods_setMethods(); +} + +void func_80295A8C(void) +{ + stateTimer_set(STATE_TIMER_2_LONGLEG, bsStoredState_getLongLegTimer()); + stateTimer_set(STATE_TIMER_3_TURBO_TALON, bsStoredState_getTurboTimer()); + if(func_8028ADB4()) + bs_setState(badrone_enter()); + else + bs_setState(bs_getIdleState()); + +} + +void func_80295B04(void){ + f32 longleg_timer; + enum bs_e current_state = bs_getState(); + bool is_in_talon_trot; + + longleg_timer = (bslongleg_inSet(current_state)) ? stateTimer_get(STATE_TIMER_2_LONGLEG) : 0.0f; + bsStoredState_setLongLegTimer(longleg_timer); + longleg_timer = 0.0f; + is_in_talon_trot = false; + + if (bsbtrot_inSet(current_state)) { + longleg_timer = stateTimer_get(STATE_TIMER_3_TURBO_TALON); + is_in_talon_trot = true; + } + + bsStoredState_setTrot(is_in_talon_trot); + bsStoredState_setTurboTimer(longleg_timer); + bs_setState(BS_5A_LOADZONE); + baMarker_free(); + func_8029065C(); + stateTimer_free(); + eggShatter_free(); + baModel_free(); + baAnim_free(); + func_80293E88(); + bacarry_end(); + basfx_free(); + func_8029A54C(); + func_8029ADA8(); + freeHazardSfxId(); + D_80363820 = 0; +} + +void func_80295C08(void (* arg0)(void)){ + D_8037C3B0 = arg0; +} + +void func_80295C14(void){ + func_802964B8(); + balookat_update(); + stateTimer_update(); + modelAppendages_kazooiesUpperHalfVisibilityTimer(); + pfsManager_update();//controller_update + disableInput_set(); + bakey_update(); + bastick_update(); + bainput_update(); //dive_cooldown_update + bs_updateState(); + baphysics_update(); + playerPosition_applyOffset(); + bafalldamage_update(); + func_80293F0C(); + pitch_update(); + roll_update(); + func_802993C8();//yaw update + func_802906D8(); + baAnim_update(); + func_8029A554(); + climb_regrab_update(); + func_80290108(); + eggShatter_update(); + baeyes_update(); + baModel_update(); + playerPosition_func_8029842C(); + baMarker_update(); + bacarry_update(); + snackerctl_update(); + func_8028B71C(); + hazards_update(); + baiFrame_update(); + func_80294E60(); + cameraMode_update(); + func_802919A0(); + if(D_8037C3B0){ + D_8037C3B0(); + D_8037C3B0 = NULL; + } + basfx_update(); + babounds_update();//voidOut_update +} + +void func_80295D74(void){ + if(D_80363820){ + baAnim_defrag(); + baModel_defrag(); + eggShatter_defrag(); + func_80294750(); + func_8029AF1C(); + } +} diff --git a/src/core2/ba/ba_carriedobj.c b/src/core2/ba/carriedobj.c similarity index 93% rename from src/core2/ba/ba_carriedobj.c rename to src/core2/ba/carriedobj.c index 9d39a7c57..3d666a454 100644 --- a/src/core2/ba/ba_carriedobj.c +++ b/src/core2/ba/carriedobj.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/carriedobj.c #include #include "functions.h" #include "variables.h" @@ -9,7 +10,7 @@ bool player_setCarryObjectPose(enum actor_e actor_id, Actor **arg1){ Actor *actor; m1 = (*arg1)->marker; - m2 = bacarry_get_marker(); + m2 = bacarry_getMarker(); if(m2){ actor = marker_getActor(m2); } @@ -40,7 +41,7 @@ void bacarriedobj_spawn(enum actor_e actor_id){ ActorMarker *marker; Actor *actor; - marker = bacarry_get_marker(); + marker = bacarry_getMarker(); if(marker){ actor = marker_getActor(marker); } @@ -68,7 +69,7 @@ void bacarriedobj_dec(enum actor_e actor_id){ ActorMarker *marker; Actor* actor; - marker = bacarry_get_marker(); + marker = bacarry_getMarker(); if(marker) actor = marker_getActor(marker); diff --git a/src/core2/ba/ba_carry.c b/src/core2/ba/carry.c similarity index 95% rename from src/core2/ba/ba_carry.c rename to src/core2/ba/carry.c index 3f71a39a8..d15cff986 100644 --- a/src/core2/ba/ba_carry.c +++ b/src/core2/ba/carry.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/carry.c #include "functions.h" #include "core2/ba/carry.h" @@ -61,7 +62,7 @@ void bacarry_reset_marker(void){ baCarry_marker = NULL; } -ActorMarker *bacarry_get_marker(void){ +ActorMarker *bacarry_getMarker(void){ return baCarry_marker; } diff --git a/src/core2/ba/ba_scripted.c b/src/core2/ba/drone.c similarity index 98% rename from src/core2/ba/ba_scripted.c rename to src/core2/ba/drone.c index 403b48de5..9ebae29a8 100644 --- a/src/core2/ba/ba_scripted.c +++ b/src/core2/ba/drone.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/drone.c #include #include "functions.h" diff --git a/src/core2/ba/ba_falldamage.c b/src/core2/ba/falldamage.c similarity index 96% rename from src/core2/ba/ba_falldamage.c rename to src/core2/ba/falldamage.c index 0b17f17ab..a39d52212 100644 --- a/src/core2/ba/ba_falldamage.c +++ b/src/core2/ba/falldamage.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/falldamage.c #include #include "functions.h" #include "variables.h" @@ -114,7 +115,7 @@ void bafalldamage_set_start_position(f32 arg0[3]){ } void bafalldamage_init(void){ - _player_getPosition(bafalldamage_start_position); + playerPosition_get(bafalldamage_start_position); bafalldamage_state = 0; bafalldamage_set_state(1); D_8037C1C0.damage = 0; @@ -134,6 +135,6 @@ void bafalldamage_update(void){ void bafalldamage_start(void){ f32 player_position[3]; - _player_getPosition(player_position); + playerPosition_get(player_position); bafalldamage_set_start_position(player_position); } diff --git a/src/core2/ba/ba_flap.c b/src/core2/ba/flap.c similarity index 98% rename from src/core2/ba/ba_flap.c rename to src/core2/ba/flap.c index c35f93134..5647fae92 100644 --- a/src/core2/ba/ba_flap.c +++ b/src/core2/ba/flap.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/flap.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_groundsurface.c b/src/core2/ba/hazards.c similarity index 96% rename from src/core2/ba/ba_groundsurface.c rename to src/core2/ba/hazards.c index 506846ce4..8b70a882a 100644 --- a/src/core2/ba/ba_groundsurface.c +++ b/src/core2/ba/hazards.c @@ -1,6 +1,8 @@ +// BanjoDecomp: core2/hazards.c #include #include "functions.h" #include "variables.h" +#include "iFrame.h" #include "core2/ba/timer.h" #include "core2/statetimer.h" @@ -14,7 +16,7 @@ f32 D_8037D224; /*.code */ bool isOnFloor(void){ - return floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > player_getYPosition(); + return floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > playerPosition_getY(); } void freeHazardSfxId(void){ @@ -185,7 +187,10 @@ bool isPlayerInHazard(void){ case MAP_6E_GL_GV_LOBBY: case MAP_72_GL_BGS_LOBBY: case MAP_8E_GL_FURNACE_FUN://L8029D6FC - return func_80294610(0xE000) && player_isStable(); + // [port] Default is the vanilla hazard-collision-flag check; a romhack + // whose hazard-flagged collision was stripped on export can force it. + return EventSystem_Should(VB_GROUND_HAZARD_ACTIVE, func_80294610(0xE000) != 0, gsworld_getMap()) && + player_isStable(); case MAP_31_RBB_RUSTY_BUCKET_BAY: player_getPosition(sp2C); diff --git a/src/core2/ba/ba_eyeblink.c b/src/core2/ba/iFrame.c similarity index 92% rename from src/core2/ba/ba_eyeblink.c rename to src/core2/ba/iFrame.c index 33803e3ee..ed3bd4e9d 100644 --- a/src/core2/ba/ba_eyeblink.c +++ b/src/core2/ba/iFrame.c @@ -1,6 +1,8 @@ +// BanjoDecomp: core2/ba/iFrame.c #include #include "functions.h" #include "variables.h" +#include "iFrame.h" #include "core2/statetimer.h" /* .bss */ diff --git a/src/core2/ba/iFrame.h b/src/core2/ba/iFrame.h new file mode 100644 index 000000000..41798abb8 --- /dev/null +++ b/src/core2/ba/iFrame.h @@ -0,0 +1,10 @@ +// BanjoDecomp: core2/ba/iFrame.h +#ifndef BANJO_KAZOOIE_BA_IFRAME_H +#define BANJO_KAZOOIE_BA_IFRAME_H + +typedef enum { + IFRAME_NONE = 1, + IFRAME_INVICIBLE = 3 +} IFrameState; + +#endif // BANJO_KAZOOIE_BA_IFRAME_H diff --git a/src/core2/ba/ba_marker.c b/src/core2/ba/marker.c similarity index 95% rename from src/core2/ba/ba_marker.c rename to src/core2/ba/marker.c index 843b4a6a8..81c8e406b 100644 --- a/src/core2/ba/ba_marker.c +++ b/src/core2/ba/marker.c @@ -1,15 +1,16 @@ +// BanjoDecomp: core2/ba/marker.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "port/Romhack/RomhackConfig.h" +#include "port/Enhancements/Retention/Retention.h" #include "core2/ba/physics.h" #include "version.h" #include "prop.h" extern void func_803012F8(void); extern void __baMarker_8028BA00(s32); -extern Actor *spawnQueue_actor_s16(uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern void func_802A6388(f32); extern f32 chwadingboots_802D6E4C(Actor *); extern void set_turbo_duration(f32); @@ -156,16 +157,36 @@ void __baMarker_8028B904(s32 arg0, s32 arg1, s32 arg2, s32 arg3){ } +extern ActorArray *suBaddieActorArray; +extern enum honeycomb_e D_8037DDC0; // honeycomb.c: pending uid for the next spawned honeycomb + +static bool __baMarker_honeycombPresent(s32 uid){ + s32 i; + s32 actorUid; + Actor *actor; + + if(suBaddieActorArray == NULL) return false; + for(i = 0; i < suBaddieActorArray->cnt; i++){ + actor = &suBaddieActorArray->data[i]; + if(actor->marker == NULL || actor->marker->id != MARKER_53_EMPTY_HONEYCOMB) continue; + actorUid = func_802CA1C4(actor); + if(actorUid == uid || (actorUid == 0 && D_8037DDC0 == uid)) return true; + } + return false; +} + void __baMarker_8028B9A8(uintptr_t arg0){ NodeProp *tmp_v0; s32 ideal_yaw[3]; + if(__baMarker_honeycombPresent(arg0)) return; + tmp_v0 = cubeList_findNodePropByActorIdAndPosition_s32(0x1F6, NULL); nodeprop_getPosition_s32(tmp_v0, ideal_yaw); func_802CA1CC(arg0); actor_spawnWithYaw_s32(ACTOR_47_EMPTY_HONEYCOMB, &ideal_yaw, 0); coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - + } void __baMarker_8028BA00(s32 arg0){ @@ -555,11 +576,12 @@ void __baMarker_resolveCollision(Prop *other_prop){ || (player_isStable() && !(3600.0f < ml_distanceSquared_vec3f(actor->position, spA0))) ) { jiggyscore_setCollected(jiggy_id, true); + CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_JIGGY, jiggy_id); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, 1); if (jiggy_id == JIGGY_20_BGS_ELEVATED_WALKWAY || jiggy_id == JIGGY_25_BGS_MAZE) { func_802D6924(); } - if (jiggyscore_total() < 3) { + if (jiggyscore_total() < 3 && EventSystem_Should(VB_JIGGY_COLLECT_TUTORIAL, true)) { __baMarker_8028B848(); } @@ -578,9 +600,11 @@ void __baMarker_resolveCollision(Prop *other_prop){ if (__baMarker_8028BC20(marker)) return; sp98 = func_802CA1C4(marker_getActor(marker)); - if (sp98 != HONEYCOMB_12_MMM_FLOORBOARD || player_getTransformation() == TRANSFORM_3_PUMPKIN) + if (sp98 != HONEYCOMB_12_MMM_FLOORBOARD || player_getTransformation() == TRANSFORM_3_PUMPKIN + || !EventSystem_Should(VB_HONEYCOMB_PUMPKIN_REQUIREMENT, true)) { honeycombscore_set(sp98, 1); + CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_HONEYCOMB, sp98); coMusicPlayer_playMusic(COMUSIC_17_EMPTY_HONEYCOMB_COLLECTED, 28000); timedFunc_set_1(2.0f, (GenFunction_1)progressDialog_showDialogMaskZero, FILEPROG_B_EMPTY_HONEYCOMB_TEXT); item_inc(ITEM_13_EMPTY_HONEYCOMB); @@ -608,7 +632,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ && volatileFlag_get(VOLATILE_FLAG_0_IN_FURNACE_FUN_QUIZ) && !fileProgressFlag_get(FILEPROG_A6_FURNACE_FUN_COMPLETE) ) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB); func_8030E6D4(SFX_126_AUDIENCE_BOOING); } @@ -698,6 +722,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ return; __baMarker_resolveMusicNoteCollision(other_prop); + port_noteRetention_onLocalNoteCollected(marker); marker_despawn(marker); break; @@ -722,7 +747,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ && volatileFlag_get(VOLATILE_FLAG_0_IN_FURNACE_FUN_QUIZ) && !fileProgressFlag_get(FILEPROG_A6_FURNACE_FUN_COMPLETE) ) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE); func_8030E6D4(SFX_127_AUDIENCE_MIXED); } coMusicPlayer_playMusic(COMUSIC_15_EXTRA_LIFE_COLLECTED, 0x7FFF); @@ -762,7 +787,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ return; if (bsStoredState_getTransformation() != TRANSFORM_1_BANJO) return; - if (func_8028F170()) + if(player_isInFirstPersonView()) return; if (func_8028F25C()) return; @@ -787,7 +812,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ if (func_8028F25C()) return; - if (func_8028F170()) + if(player_isInFirstPersonView()) return; if (!chtrainers_canUse(actor)) @@ -818,6 +843,9 @@ void __baMarker_resolveCollision(Prop *other_prop){ if (plyr_hitbox_type == HITBOX_1_BEAK_BUSTER) obj_collision_type = MARKER_COLLISION_FUNC_1; break; + case MARKER_300_CUSTOM_COLLECTIBLE: + marker_callCollisionFunc(playerMarker, marker, plyr_collision_type); + break; }//L8028D034 if (baiFrame_getState() == 3) { plyr_collision_type = MARKER_COLLISION_FUNC_0; @@ -885,7 +913,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ void baMarker_init(void){ f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); playerMarker = func_8032FBE4(sp1C, baModel_80291AAC, 1, 0); playerMarker->unk2C_1 = 1; marker_setCollisionScripts(playerMarker, NULL, func_80291634, func_80291610); @@ -918,7 +946,7 @@ void baMarker_update(void){ if ((D_8037BF88 != 0)){ temp_s0 = func_8024FEEC(func_8025ADD4(COMUSIC_30_5TH_JINJO_COLLECTED) & 0xFF); - if((comusic_active_track_count() < 4 && temp_s0 >= 0xBB9) || !func_8025AD7C(COMUSIC_30_5TH_JINJO_COLLECTED)){ + if((coMusicPlayer_getTrackCount() < 4 && temp_s0 >= 0xBB9) || !func_8025AD7C(COMUSIC_30_5TH_JINJO_COLLECTED)){ func_8028F918(0); D_8037BF88 = 0; } @@ -928,7 +956,7 @@ void baMarker_update(void){ temp_s0_2 = __baMarker_8028B750(); baflag_clear(BA_FLAG_1_ON_FLIGHT_PAD); baflag_clear(BA_FLAG_2_ON_SPRING_PAD); - _player_getPosition(sp168); + playerPosition_get(sp168); func_8032F64C(sp168, playerMarker); for(D_8037BF8C = NULL, i = 0, temp_s2 = 0; i < 2;i++){//L8028D3DC D_8037BF90 = i; diff --git a/src/core2/ba/ba_model.c b/src/core2/ba/model.c similarity index 94% rename from src/core2/ba/ba_model.c rename to src/core2/ba/model.c index 4c2fc13d1..286240997 100644 --- a/src/core2/ba/ba_model.c +++ b/src/core2/ba/model.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/model.c #include #include "functions.h" #include "variables.h" @@ -6,6 +7,8 @@ #include "core2/ba/physics.h" #include "bk_math.h" +#include "port/Enhancements/Cosmetics/PlayerColors.h" + void assetcache_release(void *); //assetcache_free void modelRender_func_8033A280(f32); @@ -54,7 +57,7 @@ static void _baModel_updateModelYaw(void){ void baModel_80291A50(s32 arg0, f32 dst[3]){ vec3fArray_get_vec3f(D_80363780, arg0, dst); if(ml_isZero_vec3f(dst)){ - _player_getPosition(dst); + playerPosition_get(dst); } } @@ -78,7 +81,7 @@ void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ _baModel_updateModelYaw(); baModelRoll = roll_get(); baModelPitch = pitch_get(); - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); plyr_pos[1] += 2.0f; ml_vec3f_assign(rotation, baModelPitch, baModelYaw, baModelRoll); func_8029A47C(env_color); @@ -94,12 +97,14 @@ void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(baModelBin){ baanim_80289F30(); - func_8029DD6C(); + modelAppendages_loadAppendage(); modelRender_setEnvColor(env_color[0], env_color[1], env_color[2], baModelEnvAlpha); modelRender_func_8033A280(2.0f); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)_baModel_preDraw, 0); modelRender_setRefPoints(D_80363780); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); + // [port] Swap in this player's recoloured palettes/vertex colours for this draw. + PlayerColors_applyLocalForDraw(baModel_getModelId(), baModelBin); if(D_8037C150.unk0){ D_8037C150.unk0 = 0; modelRender_draw(gfx, mtx, D_8037C150.unk4, rotation, baModelScale, sp38, baModelBin); @@ -115,7 +120,7 @@ void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ } void baModel_updateModel(void){ - baModel_set(func_802985F0()); + baModel_set(playerModel_get()); } void baModel_reset(void){ @@ -304,7 +309,7 @@ void baModel_80292284(f32 arg0[3], s32 arg1){ case ASSET_374_MODEL_BANJO_CROC: vec3fArray_get_vec3f(D_80363780, arg1 + 1, arg0); if(ml_isZero_vec3f(arg0)){ - _player_getPosition(arg0); + playerPosition_get(arg0); } arg0[1] += D_8037C130[arg1][0]; @@ -320,12 +325,12 @@ void baModel_80292284(f32 arg0[3], s32 arg1){ arg0[2] = arg0[2] + sp38[2]; break; default: ////80292400 - _player_getPosition(arg0); + playerPosition_get(arg0); break; } } else{//L80292410 - _player_getPosition(arg0); + playerPosition_get(arg0); if(arg1){ arg0[1] += 33.0f; } diff --git a/src/core2/ba/modelappendages.c b/src/core2/ba/modelappendages.c new file mode 100644 index 000000000..b02da560a --- /dev/null +++ b/src/core2/ba/modelappendages.c @@ -0,0 +1,209 @@ +// BanjoDecomp: core2/modelappendages.c +#include +#include "functions.h" +#include "variables.h" + +void modelAppendages_setKazooiesUpperHalfVisibility(bool); +void modelAppendages_setKazooiesFeetAndShoesVisibility(bool); +void modelAppendages_setKazooiesAssVisibility(bool); +void modelAppendages_setBanjosLeftEyeVisibility(f32); +void modelAppendages_setBanjosRightEyeVisibility(f32); +void modelAppendages_setTurboTrainersVisibility(bool); +void modelAppendages_setWadingBootsVisibility(bool); +void modelAppendages_setSledVisibility(bool); + +/* .bss */ +f32 showKazooiesUpperHalfModelTimer; // Only used in bFlap +u8 showKazooiesUpperHalfModelNext; // Only used in bFlap +u8 showKazooieAssModel; +u8 showKazooieFeetAndShoesModel; +u8 hideTurboTrainersModel; +u8 showKazooiesUpperHalfModel; +u8 hideWadingBootsModel; +u8 showSledModel; +f32 showBanjosLeftEye; +f32 showBanjosRightEye; + +/* .code */ +// Kazooie & Bee do not blink +// Wishywashy's eyes blink together +void modelAppendages_loadBlinkingEyes(void){ + s32 is_model_visible; + switch(baModel_getModelId()){ + case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: //L8029DC24 + case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: //L8029DC24 + is_model_visible = (s32) ml_interpolate_f(showBanjosLeftEye, 1.0f, 8.0f); + modelRender_setAppendageVisibility(0x1B, is_model_visible); + modelRender_setAppendageVisibility(0x1D, is_model_visible); + modelRender_setAppendageVisibility(0x1F, is_model_visible); + modelRender_setAppendageVisibility(0x21, is_model_visible); + is_model_visible = (s32) ml_interpolate_f(showBanjosRightEye, 1.0f, 8.0f); + modelRender_setAppendageVisibility(0x1A, is_model_visible); + modelRender_setAppendageVisibility(0x1C, is_model_visible); + modelRender_setAppendageVisibility(0x1E, is_model_visible); + modelRender_setAppendageVisibility(0x20, is_model_visible); + break; + + case ASSET_34F_MODEL_BANJO_TERMITE: //L8029DCCC + case ASSET_359_MODEL_BANJO_WALRUS: //L8029DCCC + case ASSET_36F_MODEL_BANJO_PUMPKIN: //L8029DCCC + case ASSET_374_MODEL_BANJO_CROC: //L8029DCCC + modelRender_setAppendageVisibility(0x1B, (s32) ml_interpolate_f(showBanjosLeftEye, 1.0f, 6.0f)); + modelRender_setAppendageVisibility(0x1A, (s32) ml_interpolate_f(showBanjosRightEye, 1.0f, 6.0f)); + break; + + case ASSET_356_MODEL_BANJO_WISHYWASHY: //L8029DD2C + modelRender_setAppendageVisibility(1, (s32) ml_interpolate_f(showBanjosRightEye, 1.0f, 4.0f)); + break; + } +} + +// This includes Kazooie, the shoes, and the sled +void modelAppendages_loadAppendage(void) { + s32 is_model_visible; // [port] must hold values > 1 for geo selector branches + + modelRender_func_8033A1FC(); + switch (baModel_getModelId()) { + case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: + case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: + /* Kazooie's Upper Half */ + modelRender_setAppendageVisibility(0x1, showKazooiesUpperHalfModel); + modelRender_setAppendageVisibility(0x9, showKazooiesUpperHalfModel); + modelRender_setAppendageVisibility(0xC, showKazooiesUpperHalfModel); + modelRender_setAppendageVisibility(0xF, showKazooiesUpperHalfModel); + /* Kazooie's Legs & Shoes */ + modelRender_setAppendageVisibility(0x2, showKazooieFeetAndShoesModel); + modelRender_setAppendageVisibility(0xA, showKazooieFeetAndShoesModel); + modelRender_setAppendageVisibility(0xD, showKazooieFeetAndShoesModel); + modelRender_setAppendageVisibility(0x10, showKazooieFeetAndShoesModel); + /* Kazooie's Ass */ + modelRender_setAppendageVisibility(0x8, showKazooieAssModel); + modelRender_setAppendageVisibility(0xB, showKazooieAssModel); + modelRender_setAppendageVisibility(0xE, showKazooieAssModel); + modelRender_setAppendageVisibility(0x11, showKazooieAssModel); + /* Turbo Talon Trainer */ + is_model_visible = hideTurboTrainersModel + 1; + modelRender_setAppendageVisibility(0x12, is_model_visible); + modelRender_setAppendageVisibility(0x14, is_model_visible); + modelRender_setAppendageVisibility(0x16, is_model_visible); + modelRender_setAppendageVisibility(0x18, is_model_visible); + modelRender_setAppendageVisibility(0x13, is_model_visible); + modelRender_setAppendageVisibility(0x15, is_model_visible); + modelRender_setAppendageVisibility(0x17, is_model_visible); + modelRender_setAppendageVisibility(0x19, is_model_visible); + /* Wading Boots */ + is_model_visible = hideWadingBootsModel + 1; + modelRender_setAppendageVisibility(0x22, is_model_visible); + modelRender_setAppendageVisibility(0x24, is_model_visible); + modelRender_setAppendageVisibility(0x26, is_model_visible); + modelRender_setAppendageVisibility(0x28, is_model_visible); + modelRender_setAppendageVisibility(0x23, is_model_visible); + modelRender_setAppendageVisibility(0x25, is_model_visible); + modelRender_setAppendageVisibility(0x27, is_model_visible); + modelRender_setAppendageVisibility(0x29, is_model_visible); + break; + case ASSET_359_MODEL_BANJO_WALRUS: + /* Sled */ + modelRender_setAppendageVisibility(0x3, showSledModel); + break; + case ASSET_374_MODEL_BANJO_CROC: + /* Turbo Talon Trainer */ + is_model_visible = hideTurboTrainersModel + 1; + modelRender_setAppendageVisibility(0x4, is_model_visible); + modelRender_setAppendageVisibility(0x5, is_model_visible); + modelRender_setAppendageVisibility(0x6, is_model_visible); + modelRender_setAppendageVisibility(0x7, is_model_visible); + break; + } + modelAppendages_loadBlinkingEyes(); +} + +bool modelAppendages_showKazooiesAss(void){ + return showKazooieAssModel; +} + +bool modelAppendages_showKazooiesFeetAndShoes(void){ + return showKazooieFeetAndShoesModel; +} + +bool modelAppendages_showKazooiesUpperHalf(void){ + return showKazooiesUpperHalfModel; +} + +f32 modelAppendages_showBanjosLeftEye(void){ + return showBanjosLeftEye; +} + +f32 modelAppendages_showBanjosRightEye(void){ + return showBanjosRightEye; +} + +bool modelAppendages_hideTurboTrainers(void){ + return hideTurboTrainersModel; +} + +bool modelAppendages_hideWadingBoots(void){ + return hideWadingBootsModel; +} + +void modelAppendages_reset(void) { + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); + modelAppendages_setKazooiesAssVisibility(false); + modelAppendages_setBanjosLeftEyeVisibility(0.0f); + modelAppendages_setBanjosRightEyeVisibility(0.0f); + modelAppendages_setTurboTrainersVisibility(false); + modelAppendages_setWadingBootsVisibility(false); + modelAppendages_setSledVisibility(false); + CALL_EVENT(OnPlayerAnimReset); +} + +void modelAppendages_setKazooiesAssVisibility(bool show_model){ + showKazooieAssModel = show_model; +} + +void modelAppendages_setKazooiesFeetAndShoesVisibility(bool show_model){ + showKazooieFeetAndShoesModel = show_model; +} + +void modelAppendages_setKazooiesUpperHalfVisibility(bool show_model) { + modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(show_model, 0.0f); +} + +// Timer only set in bFlap +void modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(bool show_model, f32 timer) { + showKazooiesUpperHalfModelTimer = timer; + showKazooiesUpperHalfModelNext = show_model; + if (timer == 0.0f) { + showKazooiesUpperHalfModel = show_model; + } +} + +void modelAppendages_setBanjosLeftEyeVisibility(f32 show_model){ + showBanjosLeftEye = show_model; +} + +void modelAppendages_setBanjosRightEyeVisibility(f32 show_model){ + showBanjosRightEye = show_model; +} + +void modelAppendages_setTurboTrainersVisibility(bool hide_model){ + hideTurboTrainersModel = hide_model; +} + +void modelAppendages_setSledVisibility(bool show_model){ + showSledModel = show_model; +} + +void modelAppendages_setWadingBootsVisibility(bool hide_model){ + hideWadingBootsModel = hide_model; +} + +void modelAppendages_kazooiesUpperHalfVisibilityTimer(void) { + if (showKazooiesUpperHalfModelTimer != 0.0f) { + showKazooiesUpperHalfModelTimer -= time_getDelta(); + if (showKazooiesUpperHalfModelTimer <= 0.0f) { + showKazooiesUpperHalfModel = showKazooiesUpperHalfModelNext; + } + } +} diff --git a/src/core2/ba/ba_physics.c b/src/core2/ba/physics.c similarity index 96% rename from src/core2/ba/ba_physics.c rename to src/core2/ba/physics.c index b61b4c703..c5ff222b4 100644 --- a/src/core2/ba/ba_physics.c +++ b/src/core2/ba/physics.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ba/physics.c #include "core2/ba/physics.h" #include "functions.h" #include "variables.h" @@ -5,7 +6,7 @@ #include -extern f32 climbGetRadius(void); +extern f32 climb_getRadius(void); extern f32 func_8029CED0(void); /* .data */ @@ -153,10 +154,10 @@ void __baphysics_update_climb(void){ f32 sp34[3]; f32 sp28[3]; - climbGetBottom(sp28); + climb_getBottom(sp28); s_next_position[0] = sp28[0]; s_next_position[2] = sp28[2]; - func_80256E24(sp34, 0.0f, yaw_get(), 0.0f, 0.0f, -climbGetRadius()); + func_80256E24(sp34, 0.0f, yaw_get(), 0.0f, 0.0f, -climb_getRadius()); s_player_velocity[2] = 0.0f; s_next_position[0] += sp34[0];\ @@ -197,7 +198,7 @@ void __baphysics_update_goto(void){ break; case 1: //L802974E8 baphysics_goto.state = 2; - _player_getPosition(baphysics_goto.start_position); + playerPosition_get(baphysics_goto.start_position); baphysics_goto.elapsed_time = 0.0f; baphysics_set_velocity(0); break; @@ -225,8 +226,8 @@ void __baphysics_update_transform(void){ D_8037C500 += time_getDelta(); temp_f0 = func_80257A44(D_8037C500, 1.2f); - temp_f0 = ml_sin_deg(temp_f0*360.0f); - s_next_position[1] = 5.0*temp_f0 + D_8037C4FC; + temp_f0 = ml_sin_deg(temp_f0 * 360.0f); + s_next_position[1] = 5.0 * temp_f0 + D_8037C4FC; } void baphysics_get_position_change(f32 arg0[3]){ @@ -244,7 +245,7 @@ void baphysics_init(void){ } void baphysics_update(void){ - _player_getPosition(s_next_position); + playerPosition_get(s_next_position); switch(baphysics_type){ case BA_PHYSICS_GOTO: //L80297780 __baphysics_update_goto(); @@ -289,7 +290,7 @@ void baphysics_update(void){ default: break; } - player_setPosition(s_next_position); + playerPosition_set(s_next_position); } void baphysics_reset_horizontal_velocity(void){ diff --git a/src/core2/ba/ba_modelselect.c b/src/core2/ba/playermodel.c similarity index 87% rename from src/core2/ba/ba_modelselect.c rename to src/core2/ba/playermodel.c index eeedd3ccb..7c05e884c 100644 --- a/src/core2/ba/ba_modelselect.c +++ b/src/core2/ba/playermodel.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/playermodel.c #include #include "functions.h" #include "variables.h" @@ -5,10 +6,10 @@ #include "port/Patches/Patches.h" /* .bss */ -void *D_8037C5D0; +void *PlayerModelAssetId; /* .code */ -s32 func_802985F0(void){ +enum asset_e playerModel_get(void){ switch(bsStoredState_getTransformation()) { case TRANSFORM_2_TERMITE: //80298624 @@ -75,21 +76,22 @@ s32 func_802985F0(void){ } } -void func_802986D0(void){ - if(D_8037C5D0){ - assetcache_release(D_8037C5D0); +void playerModel_free(void){ + if(PlayerModelAssetId){ + assetcache_release(PlayerModelAssetId); } } -void func_80298700(void){ - s32 sp1C = func_802985F0(); +void playerModel_set(void){ + enum asset_e model_id = playerModel_get(); + if(func_8028ADB4()){ - D_8037C5D0 = 0; + PlayerModelAssetId = 0; } - else if(sp1C){ - D_8037C5D0 = assetcache_get(sp1C); + else if(model_id){ + PlayerModelAssetId = assetcache_get(model_id); } else{ - D_8037C5D0 = NULL; + PlayerModelAssetId = NULL; } } diff --git a/src/core2/ba/ba_position.c b/src/core2/ba/playerposition.c similarity index 87% rename from src/core2/ba/ba_position.c rename to src/core2/ba/playerposition.c index ff7109717..95c04692c 100644 --- a/src/core2/ba/ba_position.c +++ b/src/core2/ba/playerposition.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/playerposition.c #include #include "functions.h" #include "variables.h" @@ -24,19 +25,19 @@ void playerPosition_func_80298464(f32 arg0[3]){ ml_vec3f_copy(D_8037C5B0, arg0); } -void player_setPosition(f32 arg0[3]){ +void playerPosition_set(f32 arg0[3]){ ml_vec3f_copy(player_position, arg0); } -void player_setYPosition(f32 arg0){ +void playerPosition_setY(f32 arg0){ player_position[1] = arg0; } -void _player_getPosition(f32 arg0[3]){ +void playerPosition_get(f32 arg0[3]){ ml_vec3f_copy(arg0, player_position); } -f32 player_getYPosition(void){ +f32 playerPosition_getY(void){ return player_position[1]; } diff --git a/src/core2/bs/ant.c b/src/core2/bs/ant.c index 7ccf6ec65..f00639615 100644 --- a/src/core2/bs/ant.c +++ b/src/core2/bs/ant.c @@ -50,11 +50,11 @@ void func_8029E48C(void){ } } -void func_8029E4EC(void){ +void bsant_end(void){ if(!bsant_inSet(bs_getNextState())){ bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -69,8 +69,8 @@ void func_8029E554(void){ int bsant_inSet(s32 move_indx){ return (move_indx == BS_35_ANT_IDLE) - || (move_indx == BS_ANT_WALK) - || (move_indx == BS_ANT_JUMP) + || (move_indx == BS_36_ANT_WALK) + || (move_indx == BS_37_ANT_WALK) || (move_indx == BS_38_ANT_FALL) || (move_indx == BS_3E_ANT_OW) || (move_indx == BS_43_ANT_DIE) @@ -81,7 +81,7 @@ int bsant_inSet(s32 move_indx){ void bsant_idle_init(void){ func_8029E554(); baanim_playForDuration_loopSmooth(ASSET_5E_ANIM_BSANT_IDLE, 1.2f); - func_8029C7F4(1,YAW_STATE_1_DEFAULT,1,BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -101,23 +101,23 @@ void bsant_idle_update(void){ new_state = badrone_look(); if(bastick_getZone() > 0) - new_state = BS_ANT_WALK; + new_state = BS_36_ANT_WALK; if(bakey_pressed(BUTTON_A)) - new_state = BS_ANT_JUMP; + new_state = BS_37_ANT_WALK; bs_setState(new_state); } void bsant_idle_end(void){ func_802900FC(); - func_8029E4EC(); + bsant_end(); } void bsant_walk_init(void){ func_8029E554(); baanim_playForDuration_loopSmooth(ASSET_5F_ANIM_BSANT_WALK, 0.8f); - func_8029C7F4(2, YAW_STATE_1_DEFAULT,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364960, D_80364964, D_80364968, D_8036496C); func_802900B4(); } @@ -142,13 +142,13 @@ void bsant_walk_update(void){ sp1C = BS_38_ANT_FALL; if(bakey_pressed(BUTTON_A)) - sp1C = BS_ANT_JUMP; + sp1C = BS_37_ANT_WALK; bs_setState(sp1C); } void bsant_walk_end(void){ - func_8029E4EC(); + bsant_end(); func_802900FC(); } @@ -163,7 +163,7 @@ void bsant_jump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.4423f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsant.c", 0x17c); - func_8029C7F4(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -217,10 +217,10 @@ void bsant_jump_update(void){ if(player_isStable()){ baphysics_set_target_horizontal_velocity(0.0f); if(bastick_getZone() > 0) - sp2C = BS_ANT_WALK; + sp2C = BS_36_ANT_WALK; if(bakey_pressed(BUTTON_A)) - sp2C = BS_ANT_JUMP; + sp2C = BS_37_ANT_WALK; } bs_setState(sp2C); @@ -228,7 +228,7 @@ void bsant_jump_update(void){ void bsant_jump_end(void){ baphysics_reset_gravity(); - func_8029E4EC(); + bsant_end(); } void bsant_fall_init(void){ @@ -241,7 +241,7 @@ void bsant_fall_init(void){ anctrl_setStart(aCtrl, 0.4423f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bsant.c", 0x208); - func_8029C7F4(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); bsant_substate = 0; } @@ -276,7 +276,7 @@ void bsant_fall_update(void){ } void bsant_fall_end(void){ - func_8029E4EC(); + bsant_end(); } static void __bsant_recoil_init(int take_damage){ @@ -297,7 +297,7 @@ static void __bsant_recoil_init(int take_damage){ else func_8030E58C(SFX_56_BANJO_HUI, 1.8f); - _player_getPosition(sp2C); + playerPosition_get(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -305,7 +305,7 @@ static void __bsant_recoil_init(int take_damage){ baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -341,7 +341,7 @@ static void __bsant_recoil_end(void){ baphysics_reset_gravity(); baMarker_collisionOn(); baeyes_open(); - func_8029E4EC(); + bsant_end(); } void bsant_ow_init(void){ @@ -383,7 +383,7 @@ void bsant_die_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsant.c", 0x2f6); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); - _player_getPosition(sp2C); + playerPosition_get(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); D_8037D290 = 250.0f; @@ -392,12 +392,12 @@ void bsant_die_init(void){ baphysics_set_target_horizontal_velocity(D_8037D290); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); pitch_setAngVel(1000.0f, 12.0f); func_802914CC(0xd); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8029C984(); bsant_substate = 0; baMarker_collisionOff(); @@ -449,16 +449,16 @@ void bsant_die_end(void){ baeyes_open(); } -void func_8029F398(void){ +void bsant_locked_init(void){ func_8029E554(); baanim_playForDuration_loopSmooth(ASSET_5E_ANIM_BSANT_IDLE, 2.0f); - func_8029C7F4(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); } -void func_8029F3F4(void){ +void bsant_locked_update(void){ enum bs_e sp1C = 0; func_802B3A50(); func_80299628(0); @@ -469,9 +469,9 @@ void func_8029F3F4(void){ bs_setState(sp1C); } -void func_8029F440(void){ +void bsant_locked_end(void){ func_8029C748(); - func_8029E4EC(); + bsant_end(); } void bsant_drone_init(void){ @@ -485,5 +485,5 @@ void bsant_drone_update(void){ void bsant_drone_end(void){ bsdrone_end(); - func_8029E4EC(); + bsant_end(); } diff --git a/src/core2/bs/beak_barge.c b/src/core2/bs/bBarge.c similarity index 94% rename from src/core2/bs/beak_barge.c rename to src/core2/bs/bBarge.c index 21107b516..c3fc7ca5a 100644 --- a/src/core2/bs/beak_barge.c +++ b/src/core2/bs/bBarge.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/bBarge.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" void func_80292864(f32, f32); @@ -47,7 +49,7 @@ void func_8029F4F0(void){ void func_8029F60C(void){ f32 player_position[3]; - _player_getPosition(player_position); + playerPosition_get(player_position); func_8032728C(player_position, 50.0f, 2, func_8029F4E0); } @@ -68,11 +70,11 @@ void bsbarge_init(void){ anctrl_setPlaybackType(plyrMvmnt, ANIMCTRL_ONCE); anctrl_start(plyrMvmnt, "bsbbarge.c", 0x98); D_8037D2A4 = 0; - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_target_horizontal_velocity(baphysics_get_target_horizontal_velocity()*0.3); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); D_8037D2A6 = 0; D_8037D2A5 = 0; baflag_clear(BA_FLAG_A); @@ -174,6 +176,6 @@ void bsbarge_update(void){ void bsbarge_end(void){ ability_use(5); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); D_8037D2A6 = 0; } diff --git a/src/core2/bs/beak_egg_fire.c b/src/core2/bs/bEggAss.c similarity index 72% rename from src/core2/bs/beak_egg_fire.c rename to src/core2/bs/bEggAss.c index 6dac9bf1e..b4941a6b0 100644 --- a/src/core2/bs/beak_egg_fire.c +++ b/src/core2/bs/bEggAss.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/bEggAss.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .bss */ u8 D_8037D2E0; @@ -10,11 +12,11 @@ u8 D_8037D2E1; /* .code */ void bseggass_init(void){ - baanim_playForDuration_onceSmooth(ASSET_2B_ANIM_BSEGGASS, 1.0f); - func_8029C7F4(1,3,1, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_once(ASSET_2B_ANIM_BSEGGASS, 1.0f); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_LOCKED_ROTATION); yaw_setVelocityBounded(350.0f, 14.0f); baphysics_set_target_horizontal_velocity(0.0f); - func_8029E058(1); + modelAppendages_setKazooiesAssVisibility(true); D_8037D2E0 = (D_8037D2E1 = 1); bainput_enable(5,0); } @@ -38,7 +40,10 @@ void bseggass_update(void) { } if (has_eggs) { if (anctrl_isAt(plyr_mvmt, 0.3837f)) { - func_8030E760(SFX_3E_POOP_NOISE, 1.4f, 28000); + // [port] Romhack gate + s32 rate = 28000; + EventSystem_Should(VB_EGG_FIRE_SFX, true, 2, &rate); + func_8030E760(SFX_3E_POOP_NOISE, 1.4f, rate); commonParticle_new(COMMON_PARTICLE_4_EGG_ASS, 1); item_dec(ITEM_D_EGGS); ability_use(7); @@ -50,7 +55,7 @@ void bseggass_update(void) { } } if (anctrl_isStopped(plyr_mvmt)) { - next_state = (bakey_held(BUTTON_Z))? BS_CROUCH : BS_1_IDLE; + next_state = (bakey_held(BUTTON_Z))? BS_7_CROUCH : BS_1_IDLE; } else if (0.6 < (f64) anctrl_getAnimTimer(plyr_mvmt)) { next_state = func_802ADCD4(0); } @@ -63,5 +68,5 @@ void bseggass_update(void) { void bseggass_end(void){ bainput_enable(5, 1); baphysics_reset_gravity(); - func_8029E058(0); + modelAppendages_setKazooiesAssVisibility(false); } diff --git a/src/core2/bs/beak_egg_aim.c b/src/core2/bs/bEggHead.c similarity index 63% rename from src/core2/bs/beak_egg_aim.c rename to src/core2/bs/bEggHead.c index 5d6bd79f0..65dedeff8 100644 --- a/src/core2/bs/beak_egg_aim.c +++ b/src/core2/bs/bEggHead.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/bEggHead.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" void yaw_setVelocityBounded(f32, f32); //void anctrl_start(AnimCtrl *, char*, s32); @@ -13,11 +15,11 @@ u8 D_8037D2F1; /* .code */ void bsegghead_init(void){ - baanim_playForDuration_onceSmooth(ASSET_2A_ANIM_BSEGGHEAD, 1.0f); - func_8029C7F4(1,3,1, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_once(ASSET_2A_ANIM_BSEGGHEAD, 1.0f); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_LOCKED_ROTATION); yaw_setVelocityBounded(350.0f, 14.0f); baphysics_set_target_horizontal_velocity(0.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); D_8037D2F0 = (D_8037D2F1 = 1); bainput_enable(2,0); } @@ -40,11 +42,19 @@ void bsegghead_update(void) { func_80346C10((enum bs_e *)&sp28, -1, 0, ITEM_D_EGGS, 0); } if (has_eggs) { - if (anctrl_isAt(aCtrl, 0.1f)) - func_8030E760(SFX_46_KAZOOIE_CHOKING_UP, 1.0f, 0x7fff); + // [port] Romhack gate: listeners may retune the sample rate and hook the + // egg noise into a stealth meter. + if (anctrl_isAt(aCtrl, 0.1f)) { + s32 rate = 0x7fff; + EventSystem_Should(VB_EGG_FIRE_SFX, true, 0, &rate); + func_8030E760(SFX_46_KAZOOIE_CHOKING_UP, 1.0f, rate); + } - if (anctrl_isAt(aCtrl, 0.4f)) - func_8030E760(SFX_57_KAZOOIE_HEGH, 1.0f, 0x7fff); + if (anctrl_isAt(aCtrl, 0.4f)) { + s32 rate = 0x7fff; + EventSystem_Should(VB_EGG_FIRE_SFX, true, 1, &rate); + func_8030E760(SFX_57_KAZOOIE_HEGH, 1.0f, rate); + } if (anctrl_isAt(aCtrl, 0.4704f)){ commonParticle_new(COMMON_PARTICLE_1_EGG_HEAD, 1); @@ -58,7 +68,7 @@ void bsegghead_update(void) { } } if (anctrl_isStopped(aCtrl)) { - next_state = (bakey_held(BUTTON_Z))? BS_CROUCH : BS_1_IDLE; + next_state = (bakey_held(BUTTON_Z))? BS_7_CROUCH : BS_1_IDLE; } else if (0.65 < (f64) anctrl_getAnimTimer(aCtrl)) { next_state = func_802ADCD4(0); @@ -71,5 +81,5 @@ void bsegghead_update(void) { void bsegghead_end(void){ bainput_enable(2, 1); baphysics_reset_gravity(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); } diff --git a/src/core2/bs/flap_flip.c b/src/core2/bs/bFlap.c similarity index 94% rename from src/core2/bs/flap_flip.c rename to src/core2/bs/bFlap.c index 898da2356..bf2615a71 100644 --- a/src/core2/bs/flap_flip.c +++ b/src/core2/bs/bFlap.c @@ -1,9 +1,11 @@ +// BanjoDecomp: core2/bs/bFlap.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" f32 func_802A2858(void); @@ -20,8 +22,8 @@ f32 D_8037D308; u8 D_8037D30C; void bsbflap_init(void) { - baanim_playForDuration_onceSmooth(ASSET_18_ANIM_BSBFLAP_ENTER, 0.3f); - func_8029C7F4(1, 1, 1, BA_PHYSICS_NORMAL); + baanim_playForDuration_once(ASSET_18_ANIM_BSBFLAP_ENTER, 0.3f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); if (bastick_distance() != 0.0f) { yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -30,7 +32,7 @@ void bsbflap_init(void) { baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); baphysics_set_vertical_velocity(0.0f); baphysics_set_gravity(D_80364A14); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); baflag_set(BA_FLAG_12_HAS_FLAPPED); batimer_set(0, 2.5f); D_8037D30C = sfxsource_createSfxsourceAndReturnIndex(); @@ -197,6 +199,6 @@ void bsbflap_end(void) { ability_use(1); baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - func_8029E090(0, 0.2f); + modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(0, 0.2f); sfxsource_freeSfxsourceByIndex(D_8037D30C); } diff --git a/src/core2/bs/backflip.c b/src/core2/bs/bFlip.c similarity index 94% rename from src/core2/bs/backflip.c rename to src/core2/bs/bFlip.c index 128363f25..5f16813ee 100644 --- a/src/core2/bs/backflip.c +++ b/src/core2/bs/bFlip.c @@ -1,7 +1,9 @@ +// BanjoDecomp: core2/bs/bFlip.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .data */ const f32 D_80364A20 = 920.0f; @@ -51,10 +53,10 @@ void bsbflip_init(void){ anctrl_setStart(aCtrl, 0.0f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsbflip.c", 0x80); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); basfx_80299BD4(); D_8037D310 = 0; } @@ -137,7 +139,7 @@ void bsbflip_update(void){ if(player_isFallTumbling()) sp24 = BS_3D_FALL_TUMBLING; if(player_isStable()){ - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); _bsbflip_802A2DC0(); sp24 = func_8029C9C0(sp24); D_8037D310 = 4; @@ -163,6 +165,6 @@ void bsbflip_end(void){ ability_use(2); baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); bastick_resetZones(); } diff --git a/src/core2/bs/beak_bomb.c b/src/core2/bs/bFly.c similarity index 85% rename from src/core2/bs/beak_bomb.c rename to src/core2/bs/bFly.c index 265776934..539528063 100644 --- a/src/core2/bs/beak_bomb.c +++ b/src/core2/bs/bFly.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/bFly.c #include #include "core1/core1.h" #include "functions.h" @@ -5,10 +6,11 @@ #include "core2/ba/physics.h" #include "core2/ba/flap.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" extern void baModel_setYDisplacement(f32); extern f32 bastick_getX(void); -extern void ncDynamicCam4_func_802BFE50(f32, f32, f32); +extern void ncbafly_func_802BFE50(f32, f32, f32); extern void func_80354030(f32[3], f32); @@ -36,7 +38,7 @@ int func_802A3350(void){ } void func_802A339C(f32 arg0[3], f32 arg1[3], f32 arg2){ - viewport_getLookbk_vector(arg0); + viewport_getLookVector(arg0); ml_vec3f_scale(arg0, arg2); viewport_getRotation_vec3f(arg1); } @@ -65,7 +67,7 @@ void func_802A34C8(void){ if(!bsbfly_inSet(bs_getNextState())){ baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); baModel_setYDisplacement(0.0f); func_8029CB84(); yaw_setUpdateState(1); @@ -110,7 +112,7 @@ void func_802A3648(void){ void func_802A36D0(void){ f32 plyr_pos[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); plyr_pos[0] += randf2(-30.0f, 30.0f); plyr_pos[1] += 50.0f + randf2(0.0f, 30.0f); plyr_pos[2] += randf2(-30.0f, 30.0f); @@ -121,11 +123,11 @@ void func_802A36D0(void){ } int bsbfly_inSet(enum bs_e arg0){ - return arg0 == BS_BOMB + return arg0 == BS_2A_BOMB || arg0 == BS_57_BOMB_END || arg0 == BS_18_FLY_KNOCKBACK || arg0 == BS_59_BFLY_UNK59 - || arg0 == BS_FLY_OW + || arg0 == BS_91_FLY_OW || arg0 == BS_76_BFLY_LOCKED || arg0 == BS_24_FLY || arg0 == BS_99_BFLY_DRONE; @@ -136,8 +138,8 @@ int func_802A37F8(void){ } void bsbfly_enter_init(void){ - baanim_playForDuration_onceSmooth(ASSET_45_ANIM_BSBFLY_ENTER, 1.4f); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + baanim_playForDuration_once(ASSET_45_ANIM_BSBFLY_ENTER, 1.4f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -145,7 +147,7 @@ void bsbfly_enter_init(void){ baphysics_set_velocity(0); baphysics_set_target_horizontal_velocity(0.0f); baphysics_set_gravity(-1200.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); basfx_80299BD4(); D_8037D344 = 0; D_8037D346 = 0; @@ -176,12 +178,12 @@ void bsbfly_enter_update(void){ void bsbfly_enter_end(void){ ability_use(8); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); } void bsbfly_init(void){ baanim_playForDuration_loopSmooth(ASSET_38_ANIM_BSBFLY, 0.62f); - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); if(baflag_isTrue(BA_FLAG_9)){ baphysics_set_target_horizontal_velocity(0.0f); }else{ @@ -190,7 +192,7 @@ void bsbfly_init(void){ baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); baphysics_set_target_yaw(yaw_getIdeal()); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); baphysics_set_gravity(-300.0f); baphysics_set_terminal_velocity(-99.9f); func_802914CC(4); @@ -298,7 +300,7 @@ void bsbfly_update(void){ sp2C = 0; func_80346C10(&sp2C, 0, 1, ITEM_F_RED_FEATHER, 1); if(sp2C) - sp54 = BS_BOMB; + sp54 = BS_2A_BOMB; } if(player_inWater()) @@ -311,7 +313,7 @@ void bsbfly_update(void){ bs_setState(sp54); } -void func_802A3F70(void){ +void bsbfly_end(void){ func_802A34C8(); } @@ -321,23 +323,23 @@ int bsbfly_bombHitboxActive(void){ } //bsbfly_bomb_init -void func_802A3F9C(void){ +void bsbfly_bomb_init(void){ f32 sp1C[3]; - baanim_playForDuration_once(ASSET_43_ANIM_BSBFLY_BEAKBOMB_START, 1.0f); - func_8029C7F4(1,1,3,BA_PHYSICS_FREEZE); + baanim_playForDuration_onceSmooth(ASSET_43_ANIM_BSBFLY_BEAKBOMB_START, 1.0f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); func_802A339C(D_8037D338, sp1C, 4200.0f); yaw_setIdeal(sp1C[1] + 180.0f); pitch_setIdeal(sp1C[0]); roll_setIdeal(0.0f); baphysics_set_velocity(D_8037D338); pitch_setIdeal(sp1C[0]); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802914CC(4); - ncDynamicCam4_func_802BFE74(1); + ncbafly_func_802BFE74(1); func_802A3430(); FUNC_8030E624(SFX_52_BANJO_YAH_OH, 1.0f, 28000); D_8037D345 = 0; - _player_getPosition(D_8037D328); + playerPosition_get(D_8037D328); D_8037D344 = 0; func_802D8BE4(0); } @@ -345,7 +347,7 @@ void func_802A3F9C(void){ void func_802A4078(void){ f32 plyr_pos[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); plyr_pos[0] += D_8037D338[0]; plyr_pos[1] += D_8037D338[1]; plyr_pos[2] += D_8037D338[2]; @@ -362,7 +364,7 @@ s32 func_802A40E0(void){ return BS_41_DIE; } -void func_802A411C(void) { +void bsbfly_bomb_update(void) { s32 next_state; AnimCtrl *sp58; BKCollisionTriangle *phi_v0; @@ -424,7 +426,7 @@ void func_802A411C(void) { next_state = BS_58_BEAKBOMB_CRASH; } } - _player_getPosition(sp48); + playerPosition_get(sp48); ml_vec3f_diff(sp48, D_8037D328); if (sp48[0]*sp48[0] + sp48[1]*sp48[1] + sp48[2]*sp48[2] > 16000000.0f) { next_state = BS_57_BOMB_END; @@ -440,13 +442,13 @@ void func_802A411C(void) { bs_setState(next_state); } -void func_802A4404(void){ +void bsbfly_bomb_end(void){ basfx_80299E6C(); D_8037D345 = 0; func_802A34C8(); } -void func_802A4430(void){ +void bsbfly_beakbombend_init(void){ AnimCtrl *plyr_anctrl; plyr_anctrl = baanim_getAnimCtrlPtr(); @@ -456,8 +458,8 @@ void func_802A4430(void){ anctrl_setDuration(plyr_anctrl, 0.38f); anctrl_setPlaybackType(plyr_anctrl, ANIMCTRL_LOOP); anctrl_start(plyr_anctrl, "bsbfly.c", 0x38a); - func_8029C7F4(1, 1, 3, BA_PHYSICS_LOCKED_ROTATION); - func_8029E070(1); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802A3430(); func_80293D74(); func_80294378(1); @@ -472,14 +474,14 @@ void func_802A4430(void){ D_8037D344 = 0; } -void func_802A4548(void){ +void bsbfly_beakbombend_update(void){ s32 next_state = 0; f32 sp20[3]; baphysics_get_velocity(sp20); switch(D_8037D344){ case 0://L802A457C if(func_8028B254(0x5A)){ - baanim_playForDuration_onceStartingAt(ASSET_8_ANIM_BSJUMP, 2.0f, 0.6667f); + baanim_playForDuration_onceSmoothStartingAt(ASSET_8_ANIM_BSJUMP, 2.0f, 0.6667f); D_8037D344 = 1; } break; @@ -508,7 +510,7 @@ void func_802A4548(void){ bs_setState(next_state); } -void func_802A4664(void){ +void bsbfly_beakbombend_end(void){ s32 next_state; basfx_80299E6C(); basfx_80299E90(); @@ -517,7 +519,7 @@ void func_802A4664(void){ sfxsource_playHighPriority(SFX_3EA_BANJO_GUH_HUH); } func_802A34C8(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); } void func_802A46C8(void) { @@ -530,9 +532,9 @@ void func_802A46C8(void) { void bsbfly_beakbomb_crash_init(void) { - baanim_playForDuration_once(ASSET_3E_ANIM_BSBFLY_BEAKBOMB_CRASH, 1.4f); - func_8029C7F4(1, 1, 3, BA_PHYSICS_LOCKED_ROTATION); - func_8029E070(1); + baanim_playForDuration_onceSmooth(ASSET_3E_ANIM_BSBFLY_BEAKBOMB_CRASH, 1.4f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + modelAppendages_setKazooiesUpperHalfVisibility(true); FUNC_8030E624(SFX_1F_HITTING_AN_ENEMY_3, 0.8f, 32750); basfx_80299CF4(SFX_36_BANJO_DOH, 1.0f, 28000); baMotor_80250D94(1.0f, 0.5f, 0.5f); @@ -576,13 +578,13 @@ void func_802A48B4(void) { if (item_getCount(ITEM_14_HEALTH) == 0) { func_8029C984(); func_8029151C(0xD); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8029B930(); batimer_set(0, 2.5f); D_8037D344 = 2; } } else if (anctrl_isAt(sp18, 0.92f)) { - baanim_playForDuration_once(ASSET_D2_ANIM_BSSPLAT, 2.25f); + baanim_playForDuration_onceSmooth(ASSET_D2_ANIM_BSSPLAT, 2.25f); D_8037D344 = 1; } break; @@ -614,7 +616,7 @@ void func_802A48B4(void) { void func_802A4A40(void) { func_80291548(); func_8029CB84(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); baMarker_collisionOn(); } @@ -634,10 +636,10 @@ void func_802A4A78(s32 arg0) { sp20 = 400.0f; } func_802BB3DC(2, 100.0f, 0.85f); - baanim_playForDuration_onceSmooth(ASSET_D3_ANIM_BSBFLY_BEAKBOMB_REBOUND, 1.2f); + baanim_playForDuration_once(ASSET_D3_ANIM_BSBFLY_BEAKBOMB_REBOUND, 1.2f); basfx_playOwSfx(1.0f); baMotor_80250D94(1.0f, 0.5f, 0.5f); - _player_getPosition(sp3C); + playerPosition_get(sp3C); func_80294980(sp30); func_80257F18(sp30, sp3C, &sp28); yaw_setIdeal(mlNormalizeAngle(sp28 + 180.0f)); @@ -649,13 +651,13 @@ void func_802A4A78(s32 arg0) { yaw_setIdeal(mlNormalizeAngle(sp28)); yaw_applyIdeal(); } - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(800.0f); baphysics_set_gravity(sp2C); baphysics_set_terminal_velocity(-4000.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802914CC(4); - ncDynamicCam4_func_802BFE50(12.0f, 10000.0f, 800.0f); + ncbafly_func_802BFE50(12.0f, 10000.0f, 800.0f); baMarker_collisionOff(); func_802A3430(); } @@ -677,7 +679,7 @@ void func_802A4C88(s32 arg0) { baphysics_reset(); baMarker_collisionOn(); baiFrame_start(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); func_80291548(); func_802A34C8(); } @@ -694,27 +696,27 @@ void func_802A4D10(void){ func_802A4C88(0); } -void func_802A4D30(void){ +void bsbfly_ow_init(void){ func_802A4A78(1); } -void func_802A4D50(void){ +void bsbfly_ow_update(void){ func_802A4C34(1); } -void func_802A4D70(void){ +void bsbfly_ow_end(void){ func_802A4C88(1); } -void func_802A4D90(void) { +void bsbfly_knockback_init(void) { f32 sp34; f32 player_position[3]; f32 sp1C[3]; func_802BB3DC(2, 100.0f, 0.85f); - baanim_playForDuration_onceSmooth(0x10D, 1.0f); + baanim_playForDuration_once(0x10D, 1.0f); func_8030E58C(SFX_56_BANJO_HUI, 1.0f); - _player_getPosition(player_position); + playerPosition_get(player_position); func_80294980(sp1C); func_80257F18(sp1C, player_position, &sp34); yaw_setIdeal(mlNormalizeAngle(sp34 + 180.0f)); @@ -726,15 +728,15 @@ void func_802A4D90(void) { yaw_setIdeal(mlNormalizeAngle(sp34)); yaw_applyIdeal(); } - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(400.0f); baphysics_set_gravity(-1800.0f); baMarker_collisionOff(); func_802914CC(4); - ncDynamicCam4_func_802BFE50(12.0f, 10000.0f, 800.0f); + ncbafly_func_802BFE50(12.0f, 10000.0f, 800.0f); } -void func_802A4EC8(void) { +void bsbfly_knockback_update(void) { s32 next_state; AnimCtrl *sp18; @@ -750,21 +752,21 @@ void func_802A4EC8(void) { bs_setState(next_state); } -void func_802A4F44(void){ +void bsbfly_knockback_end(void){ baphysics_reset_gravity(); baMarker_collisionOn(); func_802A34C8(); } -void func_802A4F74(void) { +void bsbfly_locked_init(void) { baanim_playForDuration_loopSmooth(ASSET_38_ANIM_BSBFLY, 0.62f); - func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); - func_8029E070(1); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802914CC(4); func_802A3430(); } -void func_802A4FC8(void) { +void bsbfly_locked_update(void) { s32 next_state; next_state = 0; @@ -777,7 +779,7 @@ void func_802A4FC8(void) { bs_setState(next_state); } -void func_802A503C(void){ +void bsbfly_locked_end(void){ func_802A34C8(); } @@ -795,32 +797,32 @@ void func_802A505C(void){ extern void baanim_playForDuration_loop(s32, f32); /* .code */ -void func_802A50B0(void){ +void bsbfly_drone_init(void){ func_802A3430(); bsdrone_init(); } -void func_802A50D8(void){ +void bsbfly_drone_update(void){ bsdrone_update(); } -void func_802A50F8(void){ +void bsbfly_drone_end(void){ bsdrone_end(); func_802A34C8(); } -void func_802A5120(void){ +void bsfly_dingpotLaunch_init(void){ baanim_playForDuration_loop(ASSET_68_ANIM_BSJUMP_TUMBLE, 0.35f); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); baphysics_set_target_horizontal_velocity(0.0f); baphysics_set_velocity(0); baphysics_set_vertical_velocity(2000.0f); basfx_80299CF4(SFX_63_BANJO_UWAAAAOOH, 1.0f, 32000); } -void func_802A5190(void){ +void bsfly_dingpotLaunch_update(void){ baphysics_set_vertical_velocity(2000.0f); bs_setState(0); } -void func_802A51C0(void){} +void bsfly_dingpotLaunch_end(void){} diff --git a/src/core2/bs/stilt_stride.c b/src/core2/bs/bLongLeg.c similarity index 88% rename from src/core2/bs/stilt_stride.c rename to src/core2/bs/bLongLeg.c index 7972e2774..343d1d763 100644 --- a/src/core2/bs/stilt_stride.c +++ b/src/core2/bs/bLongLeg.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/bLongLeg.c #include #include "functions.h" #include "variables.h" @@ -6,6 +7,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" /* .data */ @@ -48,10 +50,10 @@ void func_802A524C(void){ int bslongleg_inSet(s32 move_indx){ return (move_indx == BS_26_LONGLEG_IDLE) - || (move_indx == BS_LONGLEG_WALK) - || (move_indx == BS_LONGLEG_JUMP) - || (move_indx == BS_LONGLEG_EXIT) - || (move_indx == BS_LONGLEG_SLIDE) + || (move_indx == BS_27_LONGLEG_WALK) + || (move_indx == BS_28_LONGLEG_JUMP) + || (move_indx == BS_29_LONGLEG_EXIT) + || (move_indx == BS_55_LONGLEG_SLIDE) || (move_indx == BS_9B_LONGLEG_DRONE) || (move_indx == BS_62_LONGLEG_LOCKED); } @@ -66,9 +68,9 @@ void func_802A5374(void){ baModel_80292078(1, -50.0f); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - func_8029E070(1); - func_8029E064(1); - func_8029E0F4(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); + modelAppendages_setKazooiesFeetAndShoesVisibility(true); + modelAppendages_setWadingBootsVisibility(true); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baflag_set(BA_FLAG_3); @@ -80,9 +82,9 @@ void func_802A5404(void){ baModel_80292078(1,0); bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); - func_8029E0F4(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); + modelAppendages_setWadingBootsVisibility(false); baModel_setDirection(PLAYER_MODEL_DIR_BANJO); pitch_setIdeal(0.0f); roll_setIdeal(0.0f); @@ -127,7 +129,7 @@ void bsblongleg_enter_init(void){ __bsblongleg_enterFromTrot(); else __bsblongleg_enter(); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A5374(); basfx_80299BD4(); @@ -158,7 +160,7 @@ void bsblongleg_enter_end(void){ void bsblongleg_stand_enter(void){ baanim_playForDuration_loopSmooth(ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); baModel_setDirection(PLAYER_MODEL_DIR_KAZOOIE); func_802A5374(); @@ -175,16 +177,16 @@ void bsblongleg_stand_update(void){ stateTimer_clear(STATE_TIMER_2_LONGLEG); if(bastick_getZone() > 0) - next_state = BS_LONGLEG_WALK; + next_state = BS_27_LONGLEG_WALK; if(player_shouldSlideTrot()) - next_state = BS_LONGLEG_SLIDE; + next_state = BS_55_LONGLEG_SLIDE; if(bakey_pressed(BUTTON_A) && player_isStable()) - next_state = BS_LONGLEG_JUMP; + next_state = BS_28_LONGLEG_JUMP; if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - next_state = BS_LONGLEG_EXIT; + next_state = BS_29_LONGLEG_EXIT; if(func_802A51D0()) next_state = BS_4C_LANDING_IN_WATER; @@ -204,7 +206,7 @@ void bsblongleg_walk_init(void){ anctrl_setIndex(aCtrl, ASSET_42_ANIM_BSLONGLEG_WALK); anctrl_setPlaybackType(aCtrl, ANIMCTRL_LOOP); anctrl_start(aCtrl, "bsblongleg.c", 0x1a1); - func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364A40, D_80364A44, D_80364A48, D_80364A4C); } @@ -229,13 +231,13 @@ void bsblongleg_walk_update(void){ next_state = BS_26_LONGLEG_IDLE; if(player_shouldSlideTrot()) - next_state = BS_LONGLEG_SLIDE; + next_state = BS_55_LONGLEG_SLIDE; if(bakey_pressed(BUTTON_A) && player_isStable()) - next_state = BS_LONGLEG_JUMP; + next_state = BS_28_LONGLEG_JUMP; if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - next_state = BS_LONGLEG_EXIT; + next_state = BS_29_LONGLEG_EXIT; if(func_802A51D0()) next_state = BS_4C_LANDING_IN_WATER; @@ -324,7 +326,7 @@ void bsblongleg_jump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.42f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsblongleg.c", 0x27F); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -348,7 +350,7 @@ void bsblongleg_jump_update(void){ if(bakey_released(BUTTON_A) && 0.0f < sp34[1]) baphysics_reset_gravity(); - sp30 = player_getYPosition() - func_80294438(); + sp30 = playerPosition_getY() - func_80294438(); switch(D_8037D360){ case 0://L802A5F24 if((sp34[1] < 100.0f) || sp30 < 10.0f) @@ -386,10 +388,10 @@ void bsblongleg_jump_update(void){ sp44 = BS_26_LONGLEG_IDLE; if(bakey_pressed(BUTTON_A)) - sp44 = BS_LONGLEG_JUMP; + sp44 = BS_28_LONGLEG_JUMP; if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - sp44 = BS_LONGLEG_EXIT; + sp44 = BS_29_LONGLEG_EXIT; break; }//L802A60F0 @@ -414,11 +416,11 @@ void bsblongleg_slide_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_setStart(aCtrl, 0.0865f); anctrl_start(aCtrl, "bsblongleg.c", 0x339); - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - func_8029E070(1); - func_8029E064(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); + modelAppendages_setKazooiesFeetAndShoesVisibility(true); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baphysics_set_target_horizontal_velocity(0.0f); @@ -447,7 +449,7 @@ void bsblongleg_slide_update(void){ } if(D_8037D358 == 0.0f && bakey_pressed(BUTTON_A)) - sp3C = BS_LONGLEG_JUMP; + sp3C = BS_28_LONGLEG_JUMP; if(func_802A51D0()) sp3C = BS_4C_LANDING_IN_WATER; @@ -463,16 +465,16 @@ void func_802A6388(f32 arg0){ D_8037D35C = arg0; } -void func_802A6394(void){ +void bsblongleg_locked_init(void){ baanim_playForDuration_loopSmooth(ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A5374(); baModel_setDirection(PLAYER_MODEL_DIR_KAZOOIE); func_8029C674(); } -void func_802A63F0(void){ +void bsblongleg_locked_update(void){ enum bs_e next_state = 0; func_802A531C(); func_8029C6D0(); @@ -487,7 +489,7 @@ void func_802A63F0(void){ bs_setState(next_state); } -void func_802A6450(void){ +void bsblongleg_locked_end(void){ func_8029C748(); func_802A5404(); } @@ -501,7 +503,7 @@ void bsblongleg_drone_update(void){ func_802A531C(); bsdrone_update(); if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - bs_setState(BS_LONGLEG_EXIT); + bs_setState(BS_29_LONGLEG_EXIT); } void bsblongleg_drone_end(void){ diff --git a/src/core2/bs/beak_peck.c b/src/core2/bs/bPeck.c similarity index 92% rename from src/core2/bs/beak_peck.c rename to src/core2/bs/bPeck.c index ea581151b..8f1bcc506 100644 --- a/src/core2/bs/beak_peck.c +++ b/src/core2/bs/bPeck.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/bPeck.c #include #include "functions.h" #include "variables.h" @@ -39,10 +40,10 @@ void bsbpeck_init(void){ if(bafalldamage_get_state() == 1) bafalldamage_set_state(2); - baanim_playForDuration_onceSmooth(ASSET_1A_ANIM_BSBPECK, 0.2f); - func_8029C7F4(1,YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_AIRBORN); + baanim_playForDuration_once(ASSET_1A_ANIM_BSBPECK, 0.2f); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_AIRBORN); yaw_setVelocityBounded(1200.0f, 10.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); baphysics_set_gravity(D_80364A60); baphysics_set_vertical_velocity(D_80364A64); baModel_80292048(1, -38.0f, 0.0f, 105.0f); @@ -135,6 +136,6 @@ void bsbpeck_end(void){ baModel_80292048(1, 0.0f, 0.0f, 0.0f); baModel_80292048(0, 0.0f, 0.0f, 0.0f); baMarker_8028D638(0, 0); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); baphysics_reset_gravity(); } diff --git a/src/core2/bs/shock_spring.c b/src/core2/bs/bShock.c similarity index 86% rename from src/core2/bs/shock_spring.c rename to src/core2/bs/bShock.c index 77046f033..ce8347a83 100644 --- a/src/core2/bs/shock_spring.c +++ b/src/core2/bs/bShock.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/bShock.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .data */ const f32 D_80364A70 = 1250.0f; @@ -23,7 +25,7 @@ void bsbshock_charge_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.1061f); anctrl_setPlaybackType(aCtrl,1); anctrl_start(aCtrl, "bsbshock.c", 0x61); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -31,8 +33,8 @@ void bsbshock_charge_init(void){ baphysics_set_target_yaw(yaw_getIdeal()); func_802B6FA8(); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - func_8029E064(1); - func_8029E070(1); + modelAppendages_setKazooiesFeetAndShoesVisibility(true); + modelAppendages_setKazooiesUpperHalfVisibility(true); basfx_80299BD4(); D_8037D382 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(D_8037D382, SFX_2C_PULLING_NOISE); @@ -96,13 +98,13 @@ void bsbshock_charge_update(void){ } else{//L802A6D18 if(bainput_should_feathery_flap()) - sp2C = BS_BFLAP; + sp2C = BS_10_BFLAP; if(bainput_should_beak_bust()) sp2C = BS_F_BBUSTER; }//L802A6D44 if(anctrl_isAt( aCtrl, 0.3637f) && D_8037D380) - sp2C = BS_BSHOCK_JUMP; + sp2C = BS_22_BSHOCK_JUMP; if(anctrl_isAt(aCtrl, 0.5551f)){ baphysics_set_vertical_velocity(180.0f); @@ -117,8 +119,8 @@ void bsbshock_charge_update(void){ void bsbshock_charge_end(void){ sfxsource_freeSfxsourceByIndex(D_8037D382); - func_8029E064(0); - func_8029E070(0); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); + modelAppendages_setKazooiesUpperHalfVisibility(false); if(baModel_80292230() != 0.0f){ baModel_80292158(0.0f); playerPosition_addY(50.0f); @@ -135,7 +137,7 @@ void bsbshock_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 1.0f); anctrl_setPlaybackType(aCtrl,1); anctrl_start(aCtrl, "bsbshock.c", 0x13a); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -146,8 +148,8 @@ void bsbshock_init(void){ baphysics_set_vertical_velocity(D_80364A70); baphysics_set_gravity(D_80364A74); sfxsource_playHighPriority(SFX_E_SHOCKSPRING_BOING); - func_8029E064(1); - func_8029E070(1); + modelAppendages_setKazooiesFeetAndShoesVisibility(true); + modelAppendages_setKazooiesUpperHalfVisibility(true); ability_use(9); baModel_80292158(-50.0f); playerPosition_addY(-50.0f); @@ -178,7 +180,7 @@ void bsbshock_update(void){ sp2C = BS_3D_FALL_TUMBLING; if(bainput_should_feathery_flap()) - sp2C = BS_BFLAP; + sp2C = BS_10_BFLAP; if(bainput_should_beak_bust()) sp2C =BS_F_BBUSTER; @@ -191,8 +193,8 @@ void bsbshock_end(void){ if(bs_getNextState() != BS_11_BPECK) baphysics_reset_gravity(); - func_8029E064(0); - func_8029E070(0); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); + modelAppendages_setKazooiesUpperHalfVisibility(false); baModel_80292158(0.0f); playerPosition_addY(50.0f); } diff --git a/src/core2/bs/beak_swim.c b/src/core2/bs/bSwim.c similarity index 89% rename from src/core2/bs/beak_swim.c rename to src/core2/bs/bSwim.c index f88395db2..15abe2080 100644 --- a/src/core2/bs/beak_swim.c +++ b/src/core2/bs/bSwim.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/bSwim.c #include #include "functions.h" #include "variables.h" @@ -5,6 +6,7 @@ #include "core2/ba/model.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" extern f32 func_8029494C(void); @@ -18,7 +20,7 @@ u8 D_8037D396; f32 D_8037D398; void func_802A7140() { - func_8029C7F4(1, 3, 3, BA_PHYSICS_NO_GRAVITY); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NO_GRAVITY); } f32 func_802A716C() { @@ -64,7 +66,7 @@ bool func_802A73BC(void) { f32 sp1C; sp1C = (gsworld_getMap() == MAP_46_CCW_WINTER) ? 90.0f : 130.0f; - return floor_isCurrentFloorunk59() && player_getYPosition() > (floor_getCurrentFloorYPosition() - sp1C); + return floor_isCurrentFloorunk59() && playerPosition_getY() > (floor_getCurrentFloorYPosition() - sp1C); } void func_802A744C(void) { @@ -76,7 +78,7 @@ void func_802A744C(void) { baphysics_set_terminal_velocity(-399.99f); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_80294378(3); baModel_setYDisplacement(60.0f); baphysics_set_acceleration(2.0f); @@ -106,13 +108,13 @@ void func_802A75B0(void) { baphysics_reset_terminal_velocity(); baphysics_reset_gravity(); bastick_resetZones(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); func_80294378(1); baModel_setYDisplacement(0.0f); } } -void func_802A762C() { +void bsbdive_idle_init() { baanim_playForDuration_loopSmooth(0x70, 2.0f); func_802A7140(); baphysics_set_target_velocity(0); @@ -120,7 +122,7 @@ void func_802A762C() { baphysics_set_acceleration(0.4f); } -void func_802A7674() { +void bsbdive_idle_update() { s32 state_id = 0; func_802A71D8(); @@ -145,11 +147,11 @@ void func_802A7674() { bs_setState(state_id); } -void func_802A7718() { +void bsbdive_idle_end() { func_802A75B0(); } -void func_802A7738(void) { +void bsbdiveb_init(void) { AnimCtrl* temp_s0; AnimCtrl* temp_v0; @@ -179,7 +181,7 @@ void func_802A77D8(void) { baphysics_set_velocity(sp24); } -void func_802A7838(void) { +void bsbdiveb_update(void) { s32 next_state; AnimCtrl *anim_ctrl; f64 temp_f2; @@ -229,12 +231,12 @@ void func_802A7838(void) { bs_setState(next_state); } -void func_802A7A2C() { +void bsbdiveb_end() { func_802906A4(1); func_802A75B0(); } -void func_802A7A54() { +void bsswim_divea_init() { baanim_playForDuration_loopSmooth(0x71, 0.75f); func_802A7140(); func_802A744C(); @@ -243,7 +245,7 @@ void func_802A7A54() { func_802906A4(2); } -void func_802A7AB0(void) { +void bsswim_divea_update(void) { s32 next_state; AnimCtrl *anim_ctl; @@ -275,20 +277,20 @@ void func_802A7AB0(void) { bs_setState(next_state); } -void func_802A7BA8(void) { +void bsswim_divea_end(void) { func_802906A4(1); func_802A75B0(); } -void func_802A7BD0(void) { +void bsbswim_ow_init(void) { f32 sp3C; f32 sp30[3]; f32 sp24[3]; barebound_set_active(func_80296560()); - baanim_playForDuration_onceSmooth(0x1A0, 1.4f); + baanim_playForDuration_once(0x1A0, 1.4f); basfx_playOwSfx(1.0f); - _player_getPosition(sp30); + playerPosition_get(sp30); func_80294980(sp24); func_80257F18(sp24, sp30, &sp3C); yaw_setIdeal(mlNormalizeAngle(sp3C)); @@ -296,19 +298,19 @@ void func_802A7BD0(void) { baphysics_set_target_horizontal_velocity(barebound_get_horizontal_velocity()); baphysics_set_target_yaw(sp3C); baphysics_set_horizontal_velocity(sp3C, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baMarker_collisionOff(); baeyes_close(); func_802A744C(); } -void func_802A7CA8(void) { +void bsbswim_ow_update(void) { s32 next_state; f32 plyr_pos[3]; ParticleEmitter *p_ctrl; next_state = 0; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); plyr_pos[1] += 60.0f; p_ctrl = func_8029B950(plyr_pos, 25.0f); particleEmitter_setParticleVelocityRange(p_ctrl, -60.0f, -50.0f, -60.0f, 60.0f, 100.0f, 60.0f); @@ -323,7 +325,7 @@ void func_802A7CA8(void) { } -void func_802A7D74(void) { +void bsbswim_ow_end(void) { baiFrame_start(); baMarker_collisionOn(); baeyes_open(); @@ -332,7 +334,7 @@ void func_802A7D74(void) { void bsSwim_dive_init(void) { ability_use(ABILITY_3_CAMERA_CONTROL); - baanim_playForDuration_once(ASSET_3C_ANIM_BSSWIM_DIVE_ENTER, 1.0f); + baanim_playForDuration_onceSmooth(ASSET_3C_ANIM_BSSWIM_DIVE_ENTER, 1.0f); func_802A7140(); yaw_setVelocityBounded(500.0f, 5.0f); baphysics_set_target_velocity(0); @@ -343,7 +345,7 @@ void bsSwim_dive_init(void) { } -void func_802A7E2C(void) { +void bsSwim_dive_update(void) { s32 next_state; AnimCtrl *sp38; f32 sp34; @@ -379,11 +381,11 @@ void func_802A7E2C(void) { bs_setState(next_state); } -void func_802A7F4C(void){ +void bsSwim_dive_end(void){ func_802A75B0(); } -void func_802A7F6C(void) { +void bsbswim_die_init(void) { D_8037D394 = BOOL(bs_getPrevState() == BS_41_DIE); if (D_8037D394 || level_get() == LEVEL_9_RUSTY_BUCKET_BAY || gsworld_getMap() == MAP_46_CCW_WINTER) { @@ -409,7 +411,7 @@ void func_802A7F6C(void) { basfx_80299CF4(SFX_CA_BANJO_DROWNING_1, 1.0f, 24000); } -void func_802A8098(void) { +void bsbswim_die_update(void) { s32 next_state; f32 sp40[3]; ParticleEmitter *p_ctrl; @@ -429,7 +431,7 @@ void func_802A8098(void) { switch (D_8037D396) { case 0: if (globalTimer_getTimeMasked(1) == 0) { - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); plyr_pos[1] += 60.0f; p_ctrl = func_8029B950(plyr_pos, 25.0f); particleEmitter_setParticleVelocityRange(p_ctrl, -60.0f, -50.0f, -60.0f, 60.0f, 100.0f, 60.0f); @@ -443,7 +445,7 @@ void func_802A8098(void) { } if (batimer_isAt(1, 1.9f)) { func_802914CC(0xD); - ncDynamicCamD_func_802BF2C0(80.0f); + ncbadie_func_802BF2C0(80.0f); if (D_8037D394) { batimer_set(0, 0.5f); } else { @@ -461,7 +463,7 @@ void func_802A8098(void) { bs_setState(next_state); } -void func_802A82D4(void) { +void bsbswim_die_end(void) { func_802906A4(1); func_80291548(); core1_ce60_incOrDecCounter(false); @@ -478,8 +480,8 @@ void __bsbswim_update_rotation(void) { f32 sp2C[3]; if (balookat_getState() && balookat_try_get_position(sp2C)) { - _player_getPosition(sp44); - func_8025727C(sp44[0], sp44[1], sp44[2], sp2C[0], sp2C[1], sp2C[2], &sp38[0], &sp38[1]); + playerPosition_get(sp44); + ml_horizontal_and_vertical_angles(sp44[0], sp44[1], sp44[2], sp2C[0], sp2C[1], sp2C[2], &sp38[0], &sp38[1]); pitch_setIdeal(sp38[0]); yaw_setIdeal(sp38[1]); roll_setIdeal(0.0f); @@ -511,7 +513,7 @@ void bsbswim_lookat_end(void){ func_802A75B0(); } -void func_802A846C(void) { +void bsbswim_landingInWater_init(void) { AnimCtrl *temp_s0; f32 sp28; @@ -538,18 +540,18 @@ void func_802A846C(void) { } D_8037D398 = ml_map_f(sp28, 40.0f, 1000.0f, -300.0f, -1200.0f); baphysics_set_vertical_velocity(D_8037D398); - func_8029C7F4(1, 3, 3, BA_PHYSICS_NO_GRAVITY); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NO_GRAVITY); func_802A744C(); baphysics_set_type(BA_PHYSICS_AIRBORN); } -void func_802A85EC(void) { +void bsbswim_landingInWater_update(void) { s32 next_state; f32 sp38[3]; ParticleEmitter *sp34; next_state = 0; - _player_getPosition(sp38); + playerPosition_get(sp38); sp38[1] += 60.0f; sp34 = func_8029B950(sp38, 20.0f); particleEmitter_setParticleVelocityRange(sp34, -30.0f, -30.0f, -30.0f, 30.0f, 30.0f, 30.0f); @@ -570,7 +572,7 @@ void func_802A85EC(void) { bs_setState(next_state); } -void func_802A872C(void){ +void bsbswim_landingInWater_end(void){ func_802A75B0(); } diff --git a/src/core2/bs/talon_trot.c b/src/core2/bs/bTrot.c similarity index 92% rename from src/core2/bs/talon_trot.c rename to src/core2/bs/bTrot.c index abfc22b86..59af518e6 100644 --- a/src/core2/bs/talon_trot.c +++ b/src/core2/bs/bTrot.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/bTrot.c #include #include "functions.h" #include "variables.h" @@ -6,6 +7,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/statetimer.h" +#include "core2/yaw.h" /* .data */ f32 D_80364A90 = 30.0f; @@ -102,8 +104,8 @@ void bsbtrot_walkUpdateTargetVelocity(void){ void func_802A8A40(void){ bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - func_8029E070(1); - func_8029E064(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); + modelAppendages_setKazooiesFeetAndShoesVisibility(true); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baflag_set(BA_FLAG_3); @@ -120,14 +122,14 @@ void func_802A8AD8(void){ } if(stateTimer_isDone(STATE_TIMER_3_TURBO_TALON)){ - if(func_8029DFE0()){ - func_8029E0DC(0); + if(modelAppendages_hideTurboTrainers()){ + modelAppendages_setTurboTrainersVisibility(false); if(baflag_isFalse(BA_FLAG_14_LOSE_BOGGY_RACE)) - sfxsource_playHighPriority(0x3eb); + sfxsource_playHighPriority(SFX_3EB_UNKNOWN); func_803219F4(1); } }else{ - func_8029E0DC(1); + modelAppendages_setTurboTrainersVisibility(true); } } @@ -139,8 +141,8 @@ void func_802A8BB0(void){ baModel_setDirection(PLAYER_MODEL_DIR_BANJO); bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); pitch_setIdeal(0.0f); roll_setIdeal(0.0f); baflag_clear(BA_FLAG_3); @@ -213,8 +215,8 @@ enum bs_e func_802A8D84(enum bs_e arg0){ void bsbtrot_enter_init(void){ func_802A8AD8(); - baanim_playForDuration_onceSmooth(ASSET_16_ANIM_BSBTROT_ENTER, 1.0f); - func_8029C7F4(1,1,2, BA_PHYSICS_NORMAL); + baanim_playForDuration_once(ASSET_16_ANIM_BSBTROT_ENTER, 1.0f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A8A40(); basfx_80299BD4(); @@ -243,7 +245,7 @@ void bsbtrot_enter_end(void){ void bsbtrot_stand_init(void){ baanim_playForDuration_loopSmooth(ASSET_26_ANIM_BSBTROT_IDLE, 1.2f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A8A40(); } @@ -283,7 +285,7 @@ void func_802A9054(void){ void bsbtrot_walk_init(void){ baanim_playForDuration_loopSmooth(func_802A9030(), 0.53f); - func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); func_802A8A40(); func_802A9054(); } @@ -480,7 +482,7 @@ void bsbtrot_jump_end(void){ } void bsbtrot_exit_init(void){ - baanim_playForDuration_onceSmooth(ASSET_7_ANIM_BSBTROT_EXIT, 0.6f); + baanim_playForDuration_once(ASSET_7_ANIM_BSBTROT_EXIT, 0.6f); baanim_setUpdateType(BAANIM_UPDATE_1_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); } @@ -505,11 +507,11 @@ void bsbtrot_slide_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bsbtrot.c", 0x382); func_802A8A40(); - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - func_8029E070(1); - func_8029E064(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); + modelAppendages_setKazooiesFeetAndShoesVisibility(true); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baphysics_set_target_horizontal_velocity(0.0f); @@ -559,7 +561,7 @@ int bsbtrot_inSet(s32 move_indx){ || (move_indx == BS_45_BTROT_SLIDE) || (move_indx == BS_14_BTROT_ENTER) || (move_indx == 0x79) - || (move_indx == BS_BTROT_OW) + || (move_indx == BS_7B_BTROT_OW) || (move_indx == BS_71_BTROT_FALL) || (move_indx == 0x9a); } @@ -573,7 +575,7 @@ void bsbtrot_fall_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bsbtrot.c", 0x400); func_802A8A40(); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); baphysics_set_target_yaw(yaw_getIdeal()); bsbtrot_walkUpdateTargetVelocity(); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); @@ -678,16 +680,16 @@ void bsbtrot_fall_end(void){ func_802A8BB0(); } -void bsbtrot_unk79_init(void){ +void bsbtrot_locked_init(void){ baanim_playForDuration_loopSmooth(ASSET_26_ANIM_BSBTROT_IDLE, 1.2f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A8A40(); baModel_setDirection(PLAYER_MODEL_DIR_KAZOOIE); func_8029C674(); } -void bsbtrot_unk79_update(void){ +void bsbtrot_locked_update(void){ enum bs_e sp1C = 0; func_8029C6D0(); func_802A8AD8(); @@ -697,7 +699,7 @@ void bsbtrot_unk79_update(void){ bs_setState(sp1C); } -void bsbtrot_unk79_end(void){ +void bsbtrot_locked_end(void){ func_8029C748(); func_802A8BB0(); } @@ -709,9 +711,9 @@ void bsbtrot_ow_init(void){ func_802A8A40(); barebound_set_active(func_80296560()); - baanim_playForDuration_onceSmooth(ASSET_66_ANIM_BSBTROT_OW, 1.1f); + baanim_playForDuration_once(ASSET_66_ANIM_BSBTROT_OW, 1.1f); basfx_playOwSfx(1.0f); - _player_getPosition(sp30); + playerPosition_get(sp30); func_80294980(sp24); func_80257F18(sp24, sp30, &sp3C); yaw_setIdeal(mlNormalizeAngle(sp3C + 180.0f));\ @@ -719,7 +721,7 @@ void bsbtrot_ow_init(void){ baphysics_set_target_horizontal_velocity(barebound_get_horizontal_velocity()); baphysics_set_target_yaw(sp3C); baphysics_set_horizontal_velocity(sp3C, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); if(barebound_802987B4() == 2) baphysics_set_type(BA_PHYSICS_AIRBORN); baphysics_set_vertical_velocity(barebound_get_vertical_velocity()); diff --git a/src/core2/bs/wonderwing.c b/src/core2/bs/bWhirl.c similarity index 90% rename from src/core2/bs/wonderwing.c rename to src/core2/bs/bWhirl.c index 48be4a02c..4db5bd97a 100644 --- a/src/core2/bs/wonderwing.c +++ b/src/core2/bs/bWhirl.c @@ -1,9 +1,11 @@ +// BanjoDecomp: core2/bs/bWhirl.c #include #include "functions.h" #include "variables.h" #include "core2/ba/anim.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" const f32 D_80364AD0 = 80.0f; const f32 D_80364AD4 = 425.0f; @@ -37,7 +39,7 @@ static void __bsbwhirl_end(void){ ) ){ bastick_resetZones(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); func_8025A55C(-1, 0xfa0, 0xd); core1_ce60_incOrDecCounter(true); func_8025A7DC(COMUSIC_25_USING_GOLD_FEATHERS); @@ -79,12 +81,12 @@ void func_802AA58C(enum bs_e *arg0){ } void bsbwhirl_enter_init(void){ - baanim_playForDuration_onceSmooth(ASSET_22_ANIM_BSWHIRL_EXIT, 0.5f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + baanim_playForDuration_once(ASSET_22_ANIM_BSWHIRL_EXIT, 0.5f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); D_8037D3B0 = 0.0f; core1_ce60_incOrDecCounter(false); func_8025A55C(0, 0xfa0, 0xd); @@ -108,7 +110,7 @@ void bsbwhirl_enter_end(void){ void bsbwhirl_stand_init(void){ baanim_playForDuration_loopSmooth(ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); } @@ -119,7 +121,7 @@ void bsbwhirl_stand_update(void){ func_802AA58C(&sp1C); if(player_isSliding()) - sp1C = BS_SLIDE; + sp1C = BS_32_SLIDE; if(player_inWater()) sp1C = BS_4C_LANDING_IN_WATER; @@ -135,7 +137,7 @@ void bsbwhirl_stand_end(void){ void bsbwhirl_walk_init(void){ baanim_playForDuration_loopSmooth(ASSET_11_ANIM_BSWHIRL_WALK, 0.53f); baanim_setVelocityMapRanges(D_80364AD0, D_80364AD4, D_80364AD8, D_80364ADC); - func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); } void bsbwhirl_walk_update(void){ @@ -160,7 +162,7 @@ void bsbwhirl_walk_update(void){ func_802AA58C(&sp1C); if(player_isSliding()) - sp1C = BS_SLIDE; + sp1C = BS_32_SLIDE; bs_setState(sp1C); } @@ -180,7 +182,7 @@ void bsbwhirl_jump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.4495f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsbwhirl.c", 0x181); - func_8029C7F4(1,1,3,BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -283,14 +285,14 @@ void bsbwhirl_drone_end(void){ __bsbwhirl_end(); } -void func_802AADBC(void){ +void bsbwhirl_bsA5unknown_init(void){ baanim_playForDuration_loopSmooth(ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); } -void func_802AAE08(void){ +void bsbwhirl_bsA5unknown_update(void){ enum bs_e sp1C =0; __bsbwhirl_spawnSparkle(); func_8029C6D0(); @@ -300,7 +302,7 @@ void func_802AAE08(void){ bs_setState(sp1C); } -void func_802AAE4C(void){ +void bsbwhirl_bsA5unknown_end(void){ func_8029C748(); __bsbwhirl_end(); } diff --git a/src/core2/bs/beak_buster.c b/src/core2/bs/bbuster.c similarity index 94% rename from src/core2/bs/beak_buster.c rename to src/core2/bs/bbuster.c index 3190548f2..049ffedc0 100644 --- a/src/core2/bs/beak_buster.c +++ b/src/core2/bs/bbuster.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/bbuster.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /*.data*/ const f32 D_80364990 = 400.0f; @@ -64,12 +66,12 @@ void bsbbuster_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.35f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsbbuster.c", 0x81); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); baphysics_set_gravity(0.0f); baphysics_set_target_horizontal_velocity(0.0f); ml_vec3f_clear(sp20); baphysics_set_velocity(sp20); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802A02B4(0); D_8037D2B9 = 0; D_8037D2B7 = 0; @@ -146,10 +148,10 @@ void bsbbuster_update(void){ D_8037D2B8 = 1; D_8037D2B0 = 0.09f; D_8037D2BA = 3; - _player_getPosition(player_position); + playerPosition_get(player_position); func_8032728C(player_position, 150.0f, 2, func_8029FB20); if(bafalldamage_get_damage(&sp3C)){ - sp44 = BS_SPLAT; + sp44 = BS_72_SPLAT; } } break; @@ -200,7 +202,7 @@ void bsbbuster_update(void){ void bsbbuster_end(void){ baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); D_8037D2B7 = 0; D_8037D2B8 = 0; } diff --git a/src/core2/bs/bee.c b/src/core2/bs/bee.c index bbc820bf8..ef32faa9c 100644 --- a/src/core2/bs/bee.c +++ b/src/core2/bs/bee.c @@ -17,8 +17,8 @@ void func_802A02C0(void){ pitch_setIdeal(0.0f); //pitch_setIdeal roll_setIdeal(0.0f); bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); diff --git a/src/core2/bs/bee_fly.c b/src/core2/bs/beeFly.c similarity index 91% rename from src/core2/bs/bee_fly.c rename to src/core2/bs/beeFly.c index 1f03de7e5..b837172ea 100644 --- a/src/core2/bs/bee_fly.c +++ b/src/core2/bs/beeFly.c @@ -1,9 +1,11 @@ +// BanjoDecomp: core2/bs/beeFly.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/flap.h" +#include "core2/yaw.h" void func_80354030(f32*, f32); @@ -11,7 +13,7 @@ f32 bastick_distance(void); f32 bastick_getAngleRelativeToBanjo(void); void baModel_setYDisplacement(f32); -void ncDynamicCam4_func_802BFE50(f32, f32, f32); +void ncbafly_func_802BFE50(f32, f32, f32); void yaw_setVelocityBounded(f32, f32); f32 bastick_getX(void); f32 bastick_getY(void); @@ -30,7 +32,7 @@ int bsBeeFly_inSet(s32); void func_802A04F0(void){ f32 player_position[3]; - _player_getPosition(player_position); + playerPosition_get(player_position); player_position[0] += randf2(-30.0f, 30.0f); player_position[1] += 30.0f + randf2(0.0f, 30.0f); player_position[2] += randf2(-30.0f, 30.0f); @@ -40,10 +42,10 @@ void func_802A04F0(void){ } -void func_802A0590(void){ +void bsbeefly_bs8Bunknown_init(void){ func_802A0340(); - baanim_playForDuration_onceSmooth(0x1df, 1.5f); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + baanim_playForDuration_once(0x1df, 1.5f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -53,7 +55,7 @@ void func_802A0590(void){ D_8037D2C0 = 0; } -void func_802A0630(void){ +void bsbeefly_bs8Bunknown_update(void){ s32 next_state = 0; AnimCtrl * mvmnt; //sp1C @@ -71,13 +73,13 @@ void func_802A0630(void){ if(anctrl_isStopped(mvmnt)) baanim_playForDuration_loopSmooth(ASSET_1DC_ANIM_BEE_FLY, 0.38f); if(baphysics_get_vertical_velocity() < 0.0f) - next_state = BS_BEE_FLY; + next_state = BS_8C_BEE_FLY; break; } bs_setState(next_state); } -void func_802A0704(void){ +void bsbeefly_bs8Bunknown_end(void){ func_802A02C0(); } @@ -121,7 +123,7 @@ void _bsBeeFly_updateYaw(void){ f32 sp30; f32 stickX; stickX = bastick_getX(); - ncDynamicCam4_func_802BFE50(2.0f, 2000.0f, 350.0f); + ncbafly_func_802BFE50(2.0f, 2000.0f, 350.0f); if(bakey_held(BUTTON_R)){ yaw_setVelocityBounded(500.0f, 30.0f); sp34 = 6.0f; @@ -151,7 +153,7 @@ void bsbeefly_enter(void){ mvmnt = bs_getPrevState(); baanim_playForDuration_loopSmooth(ASSET_1DC_ANIM_BEE_FLY, 0.38); - func_8029C7F4(1, 1, 3, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); if(baflag_isTrue(BA_FLAG_9)) baphysics_set_target_horizontal_velocity(0.0f); else @@ -185,7 +187,7 @@ void bsbeefly_update(void){ _bsBeeFly_updateYaw(); _bsBeeFly_updatePitch(); pitch_get(); //return value never used - if(bakey_pressed(BUTTON_A) && (player_getYPosition() < 7500.0)){ + if(bakey_pressed(BUTTON_A) && (playerPosition_getY() < 7500.0)){ baflap_add(1.0f); } if((baflap_getCount() == 0) && player_inWater()){ diff --git a/src/core2/bs/bee_main.c b/src/core2/bs/beeMain.c similarity index 85% rename from src/core2/bs/bee_main.c rename to src/core2/bs/beeMain.c index 754a135d3..ed51d441a 100644 --- a/src/core2/bs/bee_main.c +++ b/src/core2/bs/beeMain.c @@ -1,14 +1,16 @@ +// BanjoDecomp: core2/bs/beeMain.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" f32 func_8029B41C(void); void func_80299628(s32); void yaw_applyIdeal(void); -void ncDynamicCamD_func_802BF2C0(f32); +void ncbadie_func_802BF2C0(f32); f32 baanim_getTimer(void); void baanim_setEndAndDuration(f32, f32); @@ -56,15 +58,15 @@ void func_802A1020(void){ } } -void func_802A1080(void){ +void bsbeemain_idle_init(void){ func_802A0340(); baanim_playForDuration_loopSmooth(ASSET_1DE_ANIM_BEE_IDLE,3.0f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802900B4(); } -void func_802A10D4(void){ +void bsbeemain_idle_update(void){ s32 s0; s0 = 0; @@ -76,31 +78,31 @@ void func_802A10D4(void){ s0 = badrone_look(); if(bastick_getZone() > 0) - s0 = BS_BEE_WALK; + s0 = BS_86_BEE_WALK; if(bakey_pressed(BUTTON_A)) - s0 = BS_BEE_JUMP; + s0 = BS_87_BEE_JUMP; if(player_inWater()) - s0 = BS_BEE_FLY; + s0 = BS_8C_BEE_FLY; bs_setState(func_8029CA94(s0)); } -void func_802A117C(void){ +void bsbeemain_idle_end(void){ func_802900FC(); func_802A02C0(); } -void func_802A11A4(void){ +void bsbeemain_walk_init(void){ func_802A0340(); baanim_playForDuration_loopSmooth(ASSET_1DD_ANIM_BEE_WALK, 0.38f); - func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_803649E0, D_803649E4, D_803649E8, D_803649EC); func_802900B4(); } -void func_802A1214(void){ +void bsbeemain_walk_update(void){ s32 s0; s0 = 0; @@ -115,20 +117,20 @@ void func_802A1214(void){ s0 = BS_88_BEE_FALL; if(bakey_pressed(BUTTON_A)) - s0 = BS_BEE_JUMP; + s0 = BS_87_BEE_JUMP; if(player_inWater()) - s0 = BS_BEE_FLY; + s0 = BS_8C_BEE_FLY; bs_setState(s0); } -void func_802A12D4(void){ +void bsbeemain_walk_end(void){ func_802900FC(); func_802A02C0(); } -void func_802A12FC(void){ +void bsbeemain_jump_init(void){ AnimCtrl * s0; s0 = baanim_getAnimCtrlPtr(); @@ -141,7 +143,7 @@ void func_802A12FC(void){ anctrl_setDuration(s0, 1.2f); anctrl_setPlaybackType(s0, ANIMCTRL_ONCE); anctrl_start(s0, "bsbeemain.c", 0x15b); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -154,7 +156,7 @@ void func_802A12FC(void){ D_8037D2D4 = 0; } -void func_802A1438(void){ +void bsbeemain_jump_update(void){ s32 sp2c; AnimCtrl * sp28; f32 sp1c[3]; @@ -203,27 +205,27 @@ void func_802A1438(void){ } if(player_isStable()){ if(bastick_getZone() > 0) - sp2c = BS_BEE_WALK; + sp2c = BS_86_BEE_WALK; if(bakey_pressed(BUTTON_A)){ - sp2c = BS_BEE_JUMP; + sp2c = BS_87_BEE_JUMP; } } else{ if(bakey_pressed(BUTTON_A)){ - sp2c = BS_BEE_FLY; + sp2c = BS_8C_BEE_FLY; } } if(player_inWater()) - sp2c = BS_BEE_FLY; + sp2c = BS_8C_BEE_FLY; bs_setState(sp2c); } -void func_802A163C(void){ +void bsbeemain_jump_end(void){ func_802A02C0(); baphysics_reset_gravity(); } -void func_802A1664(void){ +void bsbeemain_fall_init(void){ AnimCtrl * s0; s0 = baanim_getAnimCtrlPtr(); @@ -235,11 +237,11 @@ void func_802A1664(void){ anctrl_setSubRange(s0, 0, 0.51f); anctrl_setPlaybackType(s0, ANIMCTRL_ONCE); anctrl_start(s0, "bsbeemain.c", 0x1e2); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); D_8037D2D4 = 0; } -void func_802A170C(void){ +void bsbeemain_fall_update(void){ s32 sp2c; //next state AnimCtrl * sp28; f32 sp1c[3]; @@ -278,22 +280,22 @@ void func_802A170C(void){ sp2c = badrone_transform(); }else{ if(bastick_getZone() > 0) - sp2c = BS_BEE_WALK; + sp2c = BS_86_BEE_WALK; if(bakey_pressed(BUTTON_A)) - sp2c = BS_BEE_JUMP; + sp2c = BS_87_BEE_JUMP; sp2c = func_8029CA94(sp2c); } } else{ if(baflag_isFalse(BA_FLAG_F) && bakey_pressed(BUTTON_A)) - sp2c = BS_BEE_FLY; + sp2c = BS_8C_BEE_FLY; }//L802A189C if(player_inWater()) - sp2c = BS_BEE_FLY; + sp2c = BS_8C_BEE_FLY; bs_setState(sp2c); } -void func_802A18C8(void){ +void bsbeemain_fall_end(void){ func_802A02C0(); } @@ -318,7 +320,7 @@ void func_802A18E8(s32 arg0){ }else{ func_8030E58C(SFX_56_BANJO_HUI, 1.8f); } - _player_getPosition(sp2C); + playerPosition_get(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -326,7 +328,7 @@ void func_802A18E8(s32 arg0){ baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -367,27 +369,27 @@ void func_802A1B28(void){ func_802A02C0(); } -void func_802A1B68(void){ +void bsbeemain_ow_init(void){ func_802A18E8(1); } -void func_802A1B88(void){ +void bsbeemain_ow_update(void){ func_802A1A50(); } -void func_802A1BA8(void){ +void bsbeemain_ow_end(void){ func_802A1B28(); } -void func_802A1BC8(void){ +void bsbeemain_bounce_init(void){ func_802A18E8(2); } -void func_802A1BE8(void){ +void bsbeemain_bounce_update(void){ func_802A1A50(); } -void func_802A1C08(void){ +void bsbeemain_bounce_end(void){ func_802A1B28(); } @@ -407,8 +409,8 @@ void bsbeemain_die_init(void){ anctrl_setDuration(sp3C, 1.7f); anctrl_setPlaybackType(sp3C, ANIMCTRL_ONCE); anctrl_start(sp3C, "bsbeemain.c", 0x2ef); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); - _player_getPosition(sp2C); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + playerPosition_get(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -423,14 +425,14 @@ void bsbeemain_die_init(void){ baMarker_collisionOff(); baeyes_close(); func_802914CC(0xd); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8029C984(); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); batimer_set(0, 2.9f); D_8037D2D4 = 0; } -void func_802A1DD8(void){ +void bsbeemain_die_update(void){ baphysics_set_target_horizontal_velocity(D_8037D2D0); func_80299628(0); switch(D_8037D2D4){ @@ -467,7 +469,7 @@ void func_802A1DD8(void){ } -void func_802A1F2C(void){ +void bsbeemain_die_end(void){ core1_ce60_incOrDecCounter(false); baphysics_reset_gravity(); func_80291548(); @@ -475,16 +477,16 @@ void func_802A1F2C(void){ func_802A02C0(); } -void func_802A1F6C(void){ +void bsbee_locked_init(void){ func_802A0340(); baanim_playForDuration_loopSmooth(ASSET_1DE_ANIM_BEE_IDLE, 3.0f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); } -void func_802A1FC8(void){ +void bsbee_locked_update(void){ s32 sp1C; sp1C = 0; @@ -497,7 +499,7 @@ void func_802A1FC8(void){ bs_setState(sp1C); } -void func_802A2014(void){ +void bsbee_locked_end(void){ pitch_setIdeal(0.0f); roll_setIdeal(0.0f); func_8029C748(); @@ -516,7 +518,7 @@ void func_802A2098(void){ baflag_clear(BA_FLAG_1A_OPEN_NOTEDOOR); baanim_playForDuration_loopSmooth(ASSET_1DE_ANIM_BEE_IDLE, 3.0f); yaw_setIdeal(func_8029B41C()); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); core1_ce60_incOrDecCounter(false); func_8025A2FC(0, 0xFA0); diff --git a/src/core2/bs/bs_list.c b/src/core2/bs/bsList.c similarity index 97% rename from src/core2/bs/bs_list.c rename to src/core2/bs/bsList.c index 94103f61e..4232c817e 100644 --- a/src/core2/bs/bs_list.c +++ b/src/core2/bs/bsList.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bsList.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/bs_storedstate.c b/src/core2/bs/bsStoredState.c similarity index 97% rename from src/core2/bs/bs_storedstate.c rename to src/core2/bs/bsStoredState.c index 4d7db9391..45badf5db 100644 --- a/src/core2/bs/bs_storedstate.c +++ b/src/core2/bs/bsStoredState.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bsStoredState.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/bs_statemachine.c b/src/core2/bs/bs_statemachine.c index dd1588f8d..5b18f4d99 100644 --- a/src/core2/bs/bs_statemachine.c +++ b/src/core2/bs/bs_statemachine.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_13780.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/carry.c b/src/core2/bs/carry.c index 3ecb6e2e6..a8b79b32e 100644 --- a/src/core2/bs/carry.c +++ b/src/core2/bs/carry.c @@ -6,6 +6,7 @@ #include "core2/ba/anim.h" #include "core2/ba/carry.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .data */ const f32 D_80364AF0 = 30.0f; @@ -36,7 +37,7 @@ void bscarry_idle_init(void){ anctrl_setIndex(aCtrl, ASSET_72_ANIM_BSCARRY_IDLE); anctrl_setDuration(aCtrl, 1.2f); anctrl_start(aCtrl, "bscarry.c", 0x6f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -48,7 +49,7 @@ void bscarry_idle_update(void){ if(bastick_getZone() > 0) sp1C = BS_3B_CARRY_WALK; - if(bacarry_get_marker() == NULL) + if(bacarry_getMarker() == NULL) sp1C = BS_1_IDLE; bs_setState(sp1C); @@ -65,7 +66,7 @@ void bscarry_walk_init(void){ anctrl_setDuration(aCtrl, 0.8f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_LOOP); anctrl_start(aCtrl, "bscarry.c", 0xac); - func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364AF0, D_80364AF4, D_80364AF8, D_80364AFC); } @@ -77,7 +78,7 @@ void bscarry_walk_update(void){ if(bastick_getZone() == 0 && baphysics_is_slower_than(1.0f)) sp1C = BS_3A_CARRY_IDLE; - if(bacarry_get_marker() == NULL) + if(bacarry_getMarker() == NULL) sp1C = BS_1_IDLE; bs_setState(sp1C); @@ -106,7 +107,7 @@ void bscarry_interrupt(void){ break; case BS_INTR_16_THROW_CARRIED_OBJ: if(stateTimer_isDone(STATE_TIMER_1_THROW)){ - bs_setState(BS_CARRY_THROW); + bs_setState(BS_5B_CARRY_THROW); bs_setInterruptResponse(2); } else{ diff --git a/src/core2/bs/claw.c b/src/core2/bs/claw.c index 0ee1324be..cd43bd2eb 100644 --- a/src/core2/bs/claw.c +++ b/src/core2/bs/claw.c @@ -3,6 +3,7 @@ #include "variables.h" #include "core2/abilityprogress.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" void func_802915CC(f32); @@ -17,8 +18,8 @@ int bsclaw_hitboxActive(void){ } void bsclaw_init(void){ - baanim_playForDuration_once(ASSET_5_ANIM_BSPUNCH, 1.3f); - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_onceSmooth(ASSET_5_ANIM_BSPUNCH, 1.3f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_target_horizontal_velocity(160.0f); func_802915CC(80.0f); diff --git a/src/core2/bs/climb.c b/src/core2/bs/climb.c index 8252ea420..38b9724af 100644 --- a/src/core2/bs/climb.c +++ b/src/core2/bs/climb.c @@ -72,7 +72,7 @@ void bsclimb_idle_init(void){ f32 pole_pos[3]; player_getPosition(plyr_pos); - climbGetBottom(pole_pos); + climb_getBottom(pole_pos); if(!bsclimb_inSet(bs_getPrevState())){ func_80257F18(plyr_pos, pole_pos, &angle_towards_pole); yaw_setIdeal(angle_towards_pole); @@ -96,7 +96,7 @@ void bsclimb_idle_update(void){ case 0: D_8037D3D4 -= time_getDelta(); if(D_8037D3D4 <= 0.0f){ - baanim_playForDuration_once(ASSET_B1_ANIM_BSCLIMB_IDLE_1, 2.96f); + baanim_playForDuration_onceSmooth(ASSET_B1_ANIM_BSCLIMB_IDLE_1, 2.96f); D_8037D3D0 = 1; } break; @@ -164,13 +164,13 @@ void bsclimb_move_update(void){ if(!func_802AB788() && baphysics_get_vertical_velocity() < 30.0f) next_state = BS_4F_CLIMB_IDLE; - _player_getPosition(plyr_pos); - if(baphysics_get_target_vertical_velocity() < 0.0f && climbGetBottomY() == plyr_pos[1]) + playerPosition_get(plyr_pos); + if(baphysics_get_target_vertical_velocity() < 0.0f && climb_getBottomY() == plyr_pos[1]) next_state = BS_1_IDLE; if( func_8029825C() == 2 && 0.0f < baphysics_get_target_vertical_velocity() - && climbGetTopY() == plyr_pos[1] + && climb_getTopY() == plyr_pos[1] ){ next_state = BS_51_CLIMB_EXIT; } @@ -191,7 +191,7 @@ void bsclimb_move_end(void){ } //bsclimb_unknown_9E_init -void func_802ABCCC(void){ +void bsclimb_locked_init(void){ baanim_playForDuration_loopSmooth(ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f); baanim_setUpdateType(BAANIM_UPDATE_1_NORMAL); func_802AB654(); @@ -199,7 +199,7 @@ void func_802ABCCC(void){ } //bsclimb_unknown_9E_update -void func_802ABD0C(void){ +void bsclimb_locked_update(void){ s32 next_state = 0; if(!balookat_getState()) next_state = BS_4F_CLIMB_IDLE; @@ -208,7 +208,7 @@ void func_802ABD0C(void){ } //bsclimb_unknown_9E_end -void func_802ABD40(void){ +void bsclimb_locked_end(void){ func_802AB6F0(); } diff --git a/src/core2/bs/croc.c b/src/core2/bs/croc.c index 383d34b64..c9671d38f 100644 --- a/src/core2/bs/croc.c +++ b/src/core2/bs/croc.c @@ -5,6 +5,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" int bscroc_inSet(enum bs_e state); @@ -54,7 +55,7 @@ void __bscroc_update_turbo_talon_trainers(void){ baflag_clear(BA_FLAG_10_TOUCHING_TURBO_TRAINERS); stateTimer_set(STATE_TIMER_3_TURBO_TALON, get_turbo_duration()); coMusicPlayer_playMusic(COMUSIC_8A_GETTING_TURBO_TRAINERS, -1); - func_8029E0DC(1); + modelAppendages_setTurboTrainersVisibility(true); } if(sp1C != 0.0f ){ @@ -62,7 +63,7 @@ void __bscroc_update_turbo_talon_trainers(void){ } if(stateTimer_isAt(STATE_TIMER_3_TURBO_TALON, 0.01f)){ - func_8029E0DC(0); + modelAppendages_setTurboTrainersVisibility(false); func_8030E58C(SFX_3EB_UNKNOWN, 1.35f); } } @@ -80,8 +81,8 @@ void __bscroc_update_velocity(void){ void __bscroc_end(void){ if(!bscroc_inSet(bs_getNextState())){ bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -91,13 +92,13 @@ void __bscroc_end(void){ int bscroc_inSet(enum bs_e state){ return state == BS_5E_CROC_IDLE - || state == BS_CROC_WALK - || state == BS_CROC_JUMP + || state == BS_5F_CROC_WALK + || state == BS_60_CROC_JUMP || state == BS_61_CROC_FALL - || state == BS_CROC_OW - || state == BS_CROC_OW + || state == BS_63_CROC_OW + || state == BS_63_CROC_OW || state == BS_6E_CROC_BITE - || state == BS_CROC_EAT_BAD + || state == BS_6F_CROC_EAT_BAD || state == BS_70_CROC_EAT_GOOD || state == BS_8D_CROC_LOCKED || state == BS_94_CROC_DRONE; @@ -105,7 +106,7 @@ int bscroc_inSet(enum bs_e state){ void bscroc_idle_init(void){ baanim_playForDuration_loopSmooth(ASSET_E1_ANIM_BSCROC_IDLE, 1.0f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -126,13 +127,13 @@ void bscroc_idle_update(void){ next_state = badrone_look(); if(bastick_getZone() > 0) - next_state = BS_CROC_WALK; + next_state = BS_5F_CROC_WALK; if(bakey_pressed(BUTTON_B)) next_state = BS_6E_CROC_BITE; if(bakey_pressed(BUTTON_A)) - next_state = BS_CROC_JUMP; + next_state = BS_60_CROC_JUMP; next_state = func_8029CA94(next_state); bs_setState(next_state); @@ -145,8 +146,8 @@ void bscroc_idle_end(void){ } void bscroc_walk_init(void){ - baanim_playForDuration_loopStartingAt(ASSET_E0_ANIM_BSCROC_WALK, 0.8f, 0.4f); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ, 1, 1, BA_PHYSICS_NORMAL); + baanim_playForDuration_loopSmoothStartingAt(ASSET_E0_ANIM_BSCROC_WALK, 0.8f, 0.4f); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(bsCrocMinWalkVelocity, bsCrocMaxWalkVelocity, bsCrocSlowestWalkDuration, bsCrocFastestWalkDuration); func_802900B4(); } @@ -170,7 +171,7 @@ void bscroc_walk_update(void){ next_state = BS_6E_CROC_BITE; if(bakey_pressed(BUTTON_A)) - next_state = BS_CROC_JUMP; + next_state = BS_60_CROC_JUMP; bs_setState(next_state); } @@ -191,7 +192,7 @@ void bscroc_jump_init(void){ anctrl_setStart(aCtrl, 0.1f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bscroc.c", 0x1ac); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -253,10 +254,10 @@ void bscroc_jump_update(void){ if(player_isStable()){ if(bastick_getZone() > 0) - sp2C = BS_CROC_WALK; + sp2C = BS_5F_CROC_WALK; if(bakey_pressed(BUTTON_A)) - sp2C = BS_CROC_JUMP; + sp2C = BS_60_CROC_JUMP; } if(bakey_pressed(BUTTON_B)) @@ -279,7 +280,7 @@ void bscroc_fall_init(void){ anctrl_setDuration(aCtrl, 0.7f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bscroc.c", 0x235); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); D_8037D3EC = 0; } @@ -345,7 +346,7 @@ static void __bscroc_recoil_init(s32 damage){ else func_8030E58C(SFX_56_BANJO_HUI, 1.8f); - _player_getPosition(player_position); + playerPosition_get(player_position); func_80294980(sp20); func_80257F18(sp20, player_position, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -353,7 +354,7 @@ static void __bscroc_recoil_init(s32 damage){ baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -429,8 +430,8 @@ void bscroc_die_init(void){ anctrl_setDuration(aCtrl, 1.7f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bscroc.c", 0x32b); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); - _player_getPosition(player_position); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + playerPosition_get(player_position); func_80294980(sp20); func_80257F18(sp20, player_position, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -445,7 +446,7 @@ void bscroc_die_init(void){ baMarker_collisionOff(); baeyes_close(); func_802914CC(0xd); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8029C984(); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); batimer_set(0, 2.9f); @@ -513,8 +514,8 @@ static void func_802ACF58(void){ } void bscroc_bite_init(void){ - baanim_playForDuration_loopStartingAt(ASSET_122_ANIM_BSCROC_BITE, 0.25f, 0.2f); - func_8029C7F4(1,1,1, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_loopSmoothStartingAt(ASSET_122_ANIM_BSCROC_BITE, 0.25f, 0.2f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_LOCKED_ROTATION); func_802ACF58(); D_8037D3F4 = 0; _bscrocHitboxActive = true; @@ -547,11 +548,11 @@ void bscroc_bite_update(void){ if(player_shouldFall()) next_state = BS_61_CROC_FALL; else - next_state = BS_CROC_WALK; + next_state = BS_5F_CROC_WALK; } if(player_isStable() && bakey_pressed(BUTTON_A)) - next_state = BS_CROC_JUMP; + next_state = BS_60_CROC_JUMP; bs_setState(next_state); } @@ -562,8 +563,8 @@ void bscroc_bite_end(void){ } void bscroc_eat_bad_init(void){ - baanim_playForDuration_once(ASSET_123_ANIM_BSCROC_EAT_BAD, 2.41f); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_onceSmooth(ASSET_123_ANIM_BSCROC_EAT_BAD, 2.41f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_horizontal_velocity(0.0f); } @@ -614,7 +615,7 @@ void bscroc_set_ate_wrong_thing(void){ void bscroc_eat_good_init(void){ baanim_playForDuration_loopSmooth(ASSET_122_ANIM_BSCROC_BITE, 0.25f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baModel_setPostDraw((void (*)(Gfx **, Mtx **, Vtx **))func_802AD2A8); D_8037D3E8 = assetcache_get(func_80294974()); D_8037D3F0 = 1.0f; @@ -645,7 +646,7 @@ void bscroc_eat_good_update(void){ break; case 3: if(s_ate_wrong) - next_state = BS_CROC_EAT_BAD; + next_state = BS_6F_CROC_EAT_BAD; else next_state = BS_5E_CROC_IDLE; break; @@ -670,7 +671,7 @@ void bscroc_eat_good_end(void){ void bscroc_locked_enter(void){ baanim_playForDuration_loopSmooth(ASSET_E1_ANIM_BSCROC_IDLE, 1.0f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); diff --git a/src/core2/bs/crouch.c b/src/core2/bs/crouch.c index c4e0d3a01..440744f60 100644 --- a/src/core2/bs/crouch.c +++ b/src/core2/bs/crouch.c @@ -18,12 +18,12 @@ void func_802AD6D0(void){ } void func_802AD6FC(void){ - baanim_playForDuration_once(ASSET_116_ANIM_BSCROUCH_NOINPUT, 2.0f); + baanim_playForDuration_onceSmooth(ASSET_116_ANIM_BSCROUCH_NOINPUT, 2.0f); D_8037D404 = 2; } void func_802AD728(void){ - baanim_playForDuration_onceStartingAt(ASSET_10C_ANIM_BSCROUCH_IDLE, 0.5f, 0.9999f); + baanim_playForDuration_onceSmoothStartingAt(ASSET_10C_ANIM_BSCROUCH_IDLE, 0.5f, 0.9999f); batimer_set(2, 2.0f); D_8037D404 = 1; } @@ -159,7 +159,7 @@ void bscrouch_update(void){ }//L802ADC50 if(player_isSliding()) - sp34 = BS_SLIDE; + sp34 = BS_32_SLIDE; if(player_shouldFall()) sp34 = BS_2F_FALL; @@ -181,7 +181,7 @@ enum bs_e func_802ADCD4(enum bs_e arg0){ arg0 = BS_1_IDLE; if(bakey_pressed(BUTTON_B) && can_claw()) - arg0 = BS_CLAW; + arg0 = BS_6_CLAW; if(bakey_pressed(BUTTON_A)) arg0 = bs_getTypeOfJump(); @@ -203,7 +203,7 @@ enum bs_e func_802ADCD4(enum bs_e arg0){ arg0 = BS_12_BFLIP; if(bainput_should_beak_barge()) - arg0 = BS_BBARGE; + arg0 = BS_13_BBARGE; } diff --git a/src/core2/bs/die.c b/src/core2/bs/die.c index 626983387..ae2b823f4 100644 --- a/src/core2/bs/die.c +++ b/src/core2/bs/die.c @@ -37,7 +37,7 @@ void bsdie_init(void){ anctrl_start(aCtrl, "bsdie.c", 0x7e); func_8029B930(); func_8030E58C(SFX_36_BANJO_DOH, 1.0f); - _player_getPosition(sp2C); + playerPosition_get(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); D_8037D410 = 250.0f; @@ -53,9 +53,9 @@ void bsdie_init(void){ baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1400.0f); pitch_setAngVel(1000.0f, 12.0f); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_8029151C(0xd); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8029C984(); batimer_set(0,2.9f); D_8037D414 = 0; @@ -112,7 +112,7 @@ void bsdie_update(void){ && floor_isCurrentFloorunk59() && ( D_8037D414 || ( anctrl_isStopped(aCtrl) - && ( player_getYPosition() < (floor_getCurrentFloorYPosition() - 150.0f)) + && ( playerPosition_getY() < (floor_getCurrentFloorYPosition() - 150.0f)) ) ) && player_inWater() @@ -127,7 +127,7 @@ void bsdie_update(void){ void bsdie_end(void){ core1_ce60_incOrDecCounter(false); baphysics_reset_gravity(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); pitch_setIdeal(0.0f); roll_setIdeal(0.0f); func_80291548(); diff --git a/src/core2/bs/scripted.c b/src/core2/bs/drone.c similarity index 97% rename from src/core2/bs/scripted.c rename to src/core2/bs/drone.c index 6a683962a..9e774c2cb 100644 --- a/src/core2/bs/scripted.c +++ b/src/core2/bs/drone.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/drone.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/scripted_enter.c b/src/core2/bs/droneenter.c similarity index 97% rename from src/core2/bs/scripted_enter.c rename to src/core2/bs/droneenter.c index e25767d92..f95220d91 100644 --- a/src/core2/bs/scripted_enter.c +++ b/src/core2/bs/droneenter.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/droneenter.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" enum bsdroneenter_state_e{ @@ -111,7 +113,7 @@ void bsDroneEnter_init(void) { func_8029BCF8(&anim_id, &anim_duration); baanim_playForDuration_loopSmooth(anim_id, anim_duration); - func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); func_80294378(6); __bsDroneEnter_init(); bsDroneEnterSubstate = BSDRONEENTER_SUBSTATE_0_UNINITIALIZED; diff --git a/src/core2/bs/scripted_goto.c b/src/core2/bs/dronegoto.c similarity index 94% rename from src/core2/bs/scripted_goto.c rename to src/core2/bs/dronegoto.c index 7d69723e7..2b2befb88 100644 --- a/src/core2/bs/scripted_goto.c +++ b/src/core2/bs/dronegoto.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/dronegoto.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .bss */ @@ -55,7 +57,7 @@ void func_802AEC78(void){ badrone_get_position_and_duration(target_position, &duration_s); baphysics_set_goto_position(target_position); baphysics_set_goto_duration(duration_s); - func_8029C7F4(1,1,3,BA_PHYSICS_GOTO); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_GOTO); func_8029436C(1); D_8037D441 = 0; } diff --git a/src/core2/bs/scripted_look.c b/src/core2/bs/dronelook.c similarity index 84% rename from src/core2/bs/scripted_look.c rename to src/core2/bs/dronelook.c index 799fb2671..61ca4e3d5 100644 --- a/src/core2/bs/scripted_look.c +++ b/src/core2/bs/dronelook.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/dronelook.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "port/Controller/ModernCamera.h" +#include "core2/yaw.h" extern f32 bastick_getX(void); @@ -20,17 +22,17 @@ void bsDroneLook_init(void) { basfx_80299D2C(SFX_12D_CAMERA_ZOOM_CLOSEST, 1.2f, 12000); func_8029BCF8(&anim_id, &anim_duration); baanim_playForDuration_loopSmooth(anim_id, anim_duration); - func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); baphysics_set_velocity(0); ncDynamicCamera_enterFirstPerson(); __bsDroneLook_getEyePos(eye_position); - ncFirstPersonCamera_setZoomedOutPosition(eye_position); + ncba1p_setZoomedOutPosition(eye_position); player_getRotation(eye_rotation); eye_rotation[0] = 0.0f; eye_rotation[1] += 180.0f; eye_rotation[2] = 0.0f; - ncFirstPersonCamera_setZoomedOutRotation(eye_rotation); + ncba1p_setZoomedOutRotation(eye_rotation); baflag_set(BA_FLAG_17_FIRST_PERSON_VIEW); } @@ -43,14 +45,14 @@ void bsDroneLook_update(void) { next_state = 0; dt = time_getDelta(); - if (ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_2_IDLE) { + if (ncba1p_getState() == FIRSTPERSON_STATE_2_IDLE) { //camera is in "idle" state - ncFirstPersonCamera_getZoomedInRotation(eye_rotation); + ncba1p_getZoomedInRotation(eye_rotation); eye_rotation[0] -= bastick_getY() * 90.0f * dt * port_cameraInvertYSign(); eye_rotation[1] -= bastick_getX() * 90.0f * dt * port_cameraInvertXSign(); eye_rotation[2] = 0.0f; eye_rotation[0] = (eye_rotation[0] > 180.0f) ? ml_max_f(305.0f, eye_rotation[0]) : ml_min_f(70.0f, eye_rotation[0]); - ncFirstPersonCamera_setZoomedOutRotation(eye_rotation); + ncba1p_setZoomedOutRotation(eye_rotation); yaw_setIdeal(eye_rotation[1] + 180.0f); exit_first_person = false; @@ -71,7 +73,7 @@ void bsDroneLook_update(void) { } } __bsDroneLook_getEyePos(eye_position); - ncFirstPersonCamera_setZoomedOutPosition(eye_position); + ncba1p_setZoomedOutPosition(eye_position); bs_setState(next_state); } diff --git a/src/core2/bs/scripted_vanish.c b/src/core2/bs/dronevanish.c similarity index 96% rename from src/core2/bs/scripted_vanish.c rename to src/core2/bs/dronevanish.c index db3ba567d..5647470e6 100644 --- a/src/core2/bs/scripted_vanish.c +++ b/src/core2/bs/dronevanish.c @@ -1,9 +1,11 @@ +// BanjoDecomp: core2/bs/dronevanish.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" /* .bss */ struct { @@ -97,7 +99,7 @@ void bsDroneVanish_init(void){ func_8029BCF8(&anim_id, &anim_duration); baanim_playForDuration_loopSmooth(anim_id, anim_duration); - func_8029C7F4(1,1,3, BA_PHYSICS_FREEZE); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); func_80294378(6); __bsDroneVanish_init(); D_8037D468 = 0; diff --git a/src/core2/bs/scripted_transform.c b/src/core2/bs/dronexform.c similarity index 91% rename from src/core2/bs/scripted_transform.c rename to src/core2/bs/dronexform.c index adc06db19..915cc28da 100644 --- a/src/core2/bs/scripted_transform.c +++ b/src/core2/bs/dronexform.c @@ -1,12 +1,14 @@ +// BanjoDecomp: core2/bs/dronexform.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" -extern void player_setYPosition(f32); +extern void playerPosition_setY(f32); extern void yaw_applyIdeal(void); extern f32 cosf(f32); @@ -56,28 +58,28 @@ void func_802AF900(void){ f32 sp44; f32 sp40; f32 sp3C; - f32 sp30[3]; + f32 player_position[3]; - player_getPosition(sp30); + player_getPosition(player_position); sp3C = D_8037D470.unk8; sp48 = func_80257A44(sp3C, 0.38f); sp4C = sp48 * 6.283185308; sp40 = sinf(sp4C); sp44 = cosf(sp4C); - sp30[0] += sp40 * D_8037D470.unk18; - sp30[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 0.0f, 130.0f); - sp30[2] += sp44 * D_8037D470.unk18; + player_position[0] += sp40 * D_8037D470.unk18; + player_position[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 0.0f, 130.0f); + player_position[2] += sp44 * D_8037D470.unk18; func_802AF88C(D_8037D470.unk4, sp40, sp44); - particleEmitter_setPosition(D_8037D470.unk4, sp30); + particleEmitter_setPosition(D_8037D470.unk4, player_position); particleEmitter_emitN(D_8037D470.unk4, 1); - player_getPosition(sp30); + player_getPosition(player_position); sp4C = (1.0 - ml_remainder_f(sp48 + 0.5, 1.0f))* 6.283185308; - sp30[0] -= sinf(sp4C) * D_8037D470.unk18; - sp30[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 130.0f, 0.0f); - sp30[2] -= cosf(sp4C) * D_8037D470.unk18; + player_position[0] -= sinf(sp4C) * D_8037D470.unk18; + player_position[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 130.0f, 0.0f); + player_position[2] -= cosf(sp4C) * D_8037D470.unk18; func_802AF88C(D_8037D470.unk0, sp40, sp44); - particleEmitter_setPosition(D_8037D470.unk0, sp30); + particleEmitter_setPosition(D_8037D470.unk0, player_position); particleEmitter_emitN(D_8037D470.unk0, 1); } @@ -249,13 +251,13 @@ void func_802B01C8(void){ static void __bsdronexform_setState(int next_state){ enum asset_e sp34; f32 sp30; - f32 sp24[3]; + f32 player_position[3]; D_8037D470.state = next_state; switch(next_state){ case 1:// 802B0230 D_8037D470.unk1C = 1; - D_8037D470.unk2C = player_getYPosition(); + D_8037D470.unk2C = playerPosition_getY(); func_802AFB94(0.28f); func_802AFBA0(180.0f); func_802AFBAC(0.04f); @@ -279,10 +281,10 @@ static void __bsdronexform_setState(int next_state){ break; case 5:// 802B02F4 - _player_getPosition(sp24); - sp24[1] += 30.0f; - viewport_adjustPointDistance(sp24, 80.0f); - func_802AFBB8(sp24); + playerPosition_get(player_position); + player_position[1] += 30.0f; + viewport_adjustPointDistance(player_position, 80.0f); + func_802AFBB8(player_position); batimer_set(0, 0.1f); break; @@ -324,7 +326,7 @@ void bsdronexform_init(void){ enum asset_e sp18; func_8029BCAC(&sp18, &sp1C); baanim_playForDuration_loopSmooth(sp18, sp1C); - func_8029C7F4(1,1,3, BA_PHYSICS_FREEZE); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); baphysics_set_velocity(0); baphysics_set_target_velocity(0); pitch_setIdeal(0.0f); @@ -352,7 +354,7 @@ void bsdronexform_update(void){ switch(D_8037D470.state){ case 1: sp24 = batimer_decrement(0); - player_setYPosition(func_802B051C(0, 2.8f, 0.0f, 90.0f) + D_8037D470.unk2C); + playerPosition_setY(func_802B051C(0, 2.8f, 0.0f, 90.0f) + D_8037D470.unk2C); func_802AFB94(func_802B051C(0, 2.8f, 0.28f, 1.0f)); func_802AFBA0(func_802B051C(0, 2.8f, 180.0f, 55.0f)); func_802AFBAC(func_802B051C(0, 2.8f, 0.04f, 0.35f)); @@ -428,7 +430,7 @@ void bsdronexform_update(void){ case 9: sp24 = batimer_decrement(0); - player_setYPosition(func_802B051C(0, 0.7f, 90.0f, 0.0f) + D_8037D470.unk2C); + playerPosition_setY(func_802B051C(0, 0.7f, 90.0f, 0.0f) + D_8037D470.unk2C); if(sp24) bs_setState(bs_getIdleState()); break; diff --git a/src/core2/bs/jiggy_dance.c b/src/core2/bs/jig.c similarity index 92% rename from src/core2/bs/jiggy_dance.c rename to src/core2/bs/jig.c index 6ad7325a9..136e613cd 100644 --- a/src/core2/bs/jiggy_dance.c +++ b/src/core2/bs/jig.c @@ -1,8 +1,10 @@ +// BanjoDecomp: core2/bs/jig.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .bss */ u8 D_8037D4B0; @@ -30,7 +32,7 @@ void bsjig_jiggy_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsjig.c", 0x7f); yaw_setIdeal(func_8029B41C()); //face camera - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); core1_ce60_incOrDecCounter(false); func_8025A2FC(0,0xfa0); @@ -40,7 +42,7 @@ void bsjig_jiggy_init(void){ D_8037D4B1 = tmp; coMusicPlayer_playMusic(COMUSIC_D_JINGLE_JIGGY_COLLECTED, -1); func_8029151C(0xC); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_8030E6D4(SFX_33_BANJO_AHOO); baflag_clear(BA_FLAG_7_TOUCHING_JIGGY); baflag_clear(BA_FLAG_F); @@ -101,7 +103,7 @@ void bsjig_jiggy_end(void){ item_inc(ITEM_E_JIGGY); func_802B0CD8(); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); func_80291548(); if(bs_getNextState() != BS_34_JIG_NOTEDOOR){ @@ -149,7 +151,7 @@ void bsjig_notedoor_end(void){ baMarker_collisionOn(); func_8025A2FC(-1, 0xfa0); core1_ce60_incOrDecCounter(true); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); func_80291548(); if( D_8037D4B2 && jiggyscore_total() == 100 @@ -171,7 +173,7 @@ void bsjig_notedoor_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsjig.c", 0x14d); yaw_setIdeal(func_8029B41C()); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); if(bs_getPrevState() != BS_44_JIG_JIGGY){ core1_ce60_incOrDecCounter(false); @@ -179,7 +181,7 @@ void bsjig_notedoor_init(void){ } coMusicPlayer_playMusic(COMUSIC_42_NOTEDOOR_OPENING_FANFARE,-1); func_8029151C(0xc); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_8030E6D4(SFX_33_BANJO_AHOO); baMarker_collisionOff(); } diff --git a/src/core2/bs/jump.c b/src/core2/bs/jump.c index 2506d8990..ea331a73a 100644 --- a/src/core2/bs/jump.c +++ b/src/core2/bs/jump.c @@ -7,6 +7,7 @@ #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" f32 func_80294438(void); void basfx_playJumpSfx(f32, f32); @@ -39,7 +40,7 @@ void bsjump_init(void){ D_8037D4C2 = baflag_isTrue(BA_FLAG_2_ON_SPRING_PAD); sp30 = bs_getPrevState(); if(bsclimb_inSet(sp30)){ - climbRelease(); + climb_release(); } if(sp30 == BS_11_BPECK){ @@ -59,7 +60,7 @@ void bsjump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.5042f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsjump.c", 0x95); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -117,12 +118,12 @@ void bsjump_update(void){ } break; case 1://L802B14B4 - if( 500.0f < (player_getYPosition() - func_80294438())){ + if( 500.0f < (playerPosition_getY() - func_80294438())){ sp34 = BS_2F_FALL; } if(D_8037D4C2){ D_8037D4C2 = 0; - sp34 = BS_BSHOCK_CHARGE; + sp34 = BS_21_BSHOCK_CHARGE; } if(func_8028B254(0x5A)){ anctrl_setSubRange(aCtrl, 0.0, 1.0f); @@ -142,7 +143,7 @@ void bsjump_update(void){ D_8037D4C2 = 0; if(bainput_should_feathery_flap()) - sp34 = BS_BFLAP; + sp34 = BS_10_BFLAP; if(bainput_should_peck()) sp34 = BS_11_BPECK; @@ -183,7 +184,7 @@ void bsjump_fall_init(void){ anctrl_setTransitionDuration(aCtrl, 0.3f); anctrl_setDuration(aCtrl, 0.38f); anctrl_start(aCtrl, "bsjump.c", 0x188); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); D_8037D4C0 = 0; } @@ -219,7 +220,7 @@ void bsjump_fall_update(void){ sp2C = BS_3D_FALL_TUMBLING; if(bainput_should_feathery_flap() && baflag_isFalse(BA_FLAG_5_HAS_PECKED)) - sp2C = BS_BFLAP; + sp2C = BS_10_BFLAP; if(bainput_should_peck()) sp2C = BS_11_BPECK; @@ -233,7 +234,7 @@ void bsjump_fall_update(void){ else if(player_inWater()){ func_8029CCC4(); if(baflag_isTrue(BA_FLAG_6) || baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)){ - sp2C = BS_D_TIMEOUT; + sp2C = BS_D_TIMEOUT_TRANSFORMATION; } }//L802B18E8 @@ -248,11 +249,11 @@ void bsjump_fall_update(void){ void bsjump_fall_end(void){} -void func_802B1928(void) { +void bsjump_climbExit_init(void) { AnimCtrl *anim_ctrl; anim_ctrl = baanim_getAnimCtrlPtr(); - climbRelease(); + climb_release(); anctrl_reset(anim_ctrl); anctrl_setIndex(anim_ctrl, ASSET_8_ANIM_BSJUMP); anctrl_setDuration(anim_ctrl, 1.9f); @@ -275,7 +276,7 @@ void func_802B1928(void) { func_802B1100(); } -void func_802B1A54(void) { +void bsjump_climbExit_update(void) { s32 next_state; AnimCtrl *anim_ctrl; f32 velocity[3]; @@ -319,7 +320,7 @@ void func_802B1A54(void) { bs_setState(next_state); } -void func_802B1BCC(void){ +void bsjump_climbExit_end(void){ func_80294378(1); baphysics_reset_gravity(); } @@ -388,7 +389,7 @@ bool bsjump_jumpingFromWater(void){ void bsjump_tumble_init(void){ baanim_playForDuration_loop(ASSET_68_ANIM_BSJUMP_TUMBLE, 0.35f); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); baModel_setYDisplacement(60.0f); if(bafalldamage_get_state() == 1){ batimer_set(0, 0.5f); @@ -413,7 +414,7 @@ void bsjump_tumble_update(void){ } if(batimer_isNonzero(0)){ if(bainput_should_feathery_flap()) - sp1C = BS_BFLAP; + sp1C = BS_10_BFLAP; if(bainput_should_peck()) sp1C = BS_11_BPECK; @@ -426,7 +427,7 @@ void bsjump_tumble_update(void){ sp1C = BS_4C_LANDING_IN_WATER; if(player_isStable()) - sp1C = BS_SPLAT; + sp1C = BS_72_SPLAT; bs_setState(sp1C); } @@ -434,7 +435,7 @@ void bsjump_tumble_update(void){ void bsjump_tumble_end(void){ enum bs_e next_state = bs_getNextState(); if( next_state == BS_F_BBUSTER - || next_state == BS_BFLAP + || next_state == BS_10_BFLAP || next_state == BS_11_BPECK ){ bafalldamage_set_state(3); diff --git a/src/core2/bs/hurt.c b/src/core2/bs/ow.c similarity index 98% rename from src/core2/bs/hurt.c rename to src/core2/bs/ow.c index 333f8c836..d627bd33a 100644 --- a/src/core2/bs/hurt.c +++ b/src/core2/bs/ow.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/bs/ow.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/player_spawn.c b/src/core2/bs/player_spawn.c index d69f06c9c..50c667bcc 100644 --- a/src/core2/bs/player_spawn.c +++ b/src/core2/bs/player_spawn.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_14420.c #include #include "core1/core1.h" #include "functions.h" @@ -59,123 +60,138 @@ s16 D_80364624[14] = { BS_1B_WONDERWING_IDLE }; -u8 D_80364640[14] = {1, 1, 1, 1, 0, 0, 1, 0 , 1, 1, 1, 1, 0, 1}; +u8 D_80364640[14] = { + true, + true, + true, + true, + false, + false, + true, + false, + true, + true, + true, + true, + false, + true +}; Struct_core2_13FC0 D_80364650[14] = { - {BS_92_ANT_DRONE, ASSET_5F_ANIM_BSANT_WALK, 0.4f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.4f}, - {BS_94_CROC_DRONE, ASSET_E0_ANIM_BSCROC_WALK, 0.6f}, - {BS_95_WALRUS_DRONE, ASSET_120_ANIM_BSWALRUS_WALK, 0.7f}, - {BS_96_SWIM_DRONE, ASSET_39_ANIM_BSSWIM_MOVE, 0.8f}, - {BS_97_DIVE_DRONE, ASSET_71_ANIM_BSSWIM_DIVE_SLOW, 0.75f}, - {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_15_ANIM_BSBTROT_WALK, 0.53f}, - {BS_9B_LONGLEG_DRONE, ASSET_42_ANIM_BSLONGLEG_WALK, 0.8f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DC_ANIM_BEE_FLY, 0.38f}, - {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, - {BS_A4_WONDERWING_DRONE, ASSET_11_ANIM_BSWHIRL_WALK, 0.53f} + {BS_92_ANT_DRONE, ASSET_5F_ANIM_BSANT_WALK, 0.4f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.4f}, + {BS_94_CROC_DRONE, ASSET_E0_ANIM_BSCROC_WALK, 0.6f}, + {BS_95_WALRUS_DRONE, ASSET_120_ANIM_BSWALRUS_WALK, 0.7f}, + {BS_96_SWIM_DRONE, ASSET_39_ANIM_BSSWIM_MOVE, 0.8f}, + {BS_97_DIVE_DRONE, ASSET_71_ANIM_BSSWIM_DIVE_SLOW, 0.75f}, + {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_15_ANIM_BSBTROT_WALK, 0.53f}, + {BS_9B_LONGLEG_DRONE, ASSET_42_ANIM_BSLONGLEG_WALK, 0.8f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DC_ANIM_BEE_FLY, 0.38f}, + {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, + {BS_A4_WONDERWING_DRONE, ASSET_11_ANIM_BSWHIRL_WALK, 0.53f} }; Struct_core2_13FC0 D_803646C0[14] = { - {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, - {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, - {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, - {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, - {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, - {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, - {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, - {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f}, + {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, + {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, + {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, + {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, + {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, + {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, + {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, + {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} }; Struct_core2_13FC0 D_80364730[14] = { - {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, - {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, - {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, - {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, - {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, - {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, - {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, - {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f}, + {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, + {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, + {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, + {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, + {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, + {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, + {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, + {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} }; Struct_core2_13FC0 D_803647A0[14] = { - {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, - {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, - {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, - {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, - {BS_98_WALK_DRONE, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, - {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, - {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, - {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} + {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, + {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, + {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, + {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, + {BS_98_WALK_DRONE, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, + {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, + {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, + {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} }; Struct_core2_13FC0 D_80364810[14] = { - {BS_8E_ANT_LOCKED, 0, 0.0f}, - {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, - {BS_8D_CROC_LOCKED, 0, 0.0f}, - {BS_73_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, - {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, - {BS_73_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, - {BS_76_BFLY_LOCKED, 0, 0.0f}, - {BS_79_BTROT_LOCKED, 0, 0.0f}, - {BS_62_LONGLEG_LOCKED, 0, 0.0f}, - {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, - {BS_6B_BEE_LOCKED, 0, 0.0f}, - {BS_9E_CLIMB_LOCKED, 0, 0.0f}, - {BS_A5_WONDERWING_UNKA5, 0, 0.0f}, + {BS_8E_ANT_LOCKED, 0, 0.0f}, + {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, + {BS_8D_CROC_LOCKED, 0, 0.0f}, + {BS_73_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, + {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, + {BS_73_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, + {BS_76_BFLY_LOCKED, 0, 0.0f}, + {BS_79_BTROT_LOCKED, 0, 0.0f}, + {BS_62_LONGLEG_LOCKED, 0, 0.0f}, + {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, + {BS_6B_BEE_LOCKED, 0, 0.0f}, + {BS_9E_CLIMB_LOCKED, 0, 0.0f}, + {BS_A5_WONDERWING_UNKA5, 0, 0.0f} }; Struct_core2_13FC0 D_80364880[14] = { - {BS_8E_ANT_LOCKED, 0, 0.0f}, - {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, - {BS_8D_CROC_LOCKED, 0, 0.0f}, - {BS_74_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, - {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, - {BS_74_UNKNOWN, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, - {BS_76_BFLY_LOCKED, 0, 0.0f}, - {BS_79_BTROT_LOCKED, 0, 0.0f}, - {BS_62_LONGLEG_LOCKED, 0, 0.0f}, - {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, - {BS_6B_BEE_LOCKED, 0, 0.0f}, - {BS_9E_CLIMB_LOCKED, 0, 0.0f}, - {BS_A5_WONDERWING_UNKA5, 0, 0.0f} + {BS_8E_ANT_LOCKED, 0, 0.0f}, + {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, + {BS_8D_CROC_LOCKED, 0, 0.0f}, + {BS_74_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, + {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, + {BS_74_UNKNOWN, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, + {BS_76_BFLY_LOCKED, 0, 0.0f}, + {BS_79_BTROT_LOCKED, 0, 0.0f}, + {BS_62_LONGLEG_LOCKED, 0, 0.0f}, + {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, + {BS_6B_BEE_LOCKED, 0, 0.0f}, + {BS_9E_CLIMB_LOCKED, 0, 0.0f}, + {BS_A5_WONDERWING_UNKA5, 0, 0.0f} }; Struct_core2_13FC0 D_803648F0[14] = { - {BS_8E_ANT_LOCKED, 0, 0.0f}, - {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, - {BS_8D_CROC_LOCKED, 0, 0.0f}, - {BS_75_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, - {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, - {BS_75_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, - {BS_76_BFLY_LOCKED, 0, 0.0f}, - {BS_79_BTROT_LOCKED, 0, 0.0f}, - {BS_62_LONGLEG_LOCKED, 0, 0.0f}, - {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, - {BS_6B_BEE_LOCKED, 0, 0.0f}, - {BS_9E_CLIMB_LOCKED, 0, 0.0f}, - {BS_A5_WONDERWING_UNKA5, 0, 0.0f} + {BS_8E_ANT_LOCKED, 0, 0.0f}, + {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, + {BS_8D_CROC_LOCKED, 0, 0.0f}, + {BS_75_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, + {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, + {BS_75_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, + {BS_76_BFLY_LOCKED, 0, 0.0f}, + {BS_79_BTROT_LOCKED, 0, 0.0f}, + {BS_62_LONGLEG_LOCKED, 0, 0.0f}, + {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, + {BS_6B_BEE_LOCKED, 0, 0.0f}, + {BS_9E_CLIMB_LOCKED, 0, 0.0f}, + {BS_A5_WONDERWING_UNKA5, 0, 0.0f} }; /* .bss */ @@ -281,6 +297,8 @@ void func_8029B62C(void){ func_802E4048(gVoidOutReturnLocation[0], gVoidOutReturnLocation[1], 1); return; } + // [port] Permadeath difficulty empties the reserve and erases the save here. + CALL_EVENT(OnPlayerDeath); if(item_empty(ITEM_16_LIFE)){ if(!fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE) || fileProgressFlag_get(FILEPROG_A6_FURNACE_FUN_COMPLETE)){ func_8025A430(-1, 0x7D0, 3); @@ -296,7 +314,12 @@ void func_8029B62C(void){ } } else{ - func_802E4048(gVoidOutReturnLocation[0], gVoidOutReturnLocation[1], 1); + // [port] Romhack gate: listeners can replace the void-out respawn with a + // full map transition. + if (EventSystem_Should(VB_VOID_OUT_RESPAWN_TRANSITION, true, gVoidOutReturnLocation[0], + gVoidOutReturnLocation[1])) { + func_802E4048(gVoidOutReturnLocation[0], gVoidOutReturnLocation[1], 1); + } } } @@ -376,7 +399,7 @@ void func_8029B984(f32 dst[3]){ f32 plyr_pos[3]; f32 sp18[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); viewport_getPosition_vec3f(sp18); ml_vec3f_diff_copy(dst, sp18, plyr_pos); } @@ -596,7 +619,7 @@ enum bs_e bs_getIdleState(void){ return BS_26_LONGLEG_IDLE; } if (player_inWater()) { - if (player_getYPosition() > (floor_getCurrentFloorYPosition() - 80.0f)) { + if (playerPosition_getY() > (floor_getCurrentFloorYPosition() - 80.0f)) { return BS_2D_SWIM_IDLE; } return BS_2B_DIVE_IDLE; @@ -615,7 +638,7 @@ void func_8029C0D0(void) { f32 sp34; if (floor_isCurrentFloorunk59()) { - _player_getPosition(sp3C); + playerPosition_get(sp3C); sp3C[1] = sp34 = floor_getCurrentFloorYPosition(); p_ctrl = func_802F4094(sp3C, 35.0f); fxRipple_802F3554(3, sp3C); @@ -635,7 +658,7 @@ void func_8029C0D0(void) { void func_8029C22C(void) { - if(floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > player_getYPosition()) + if(floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > playerPosition_getY()) return; D_80364620 = D_80364620 ? false : true; @@ -652,7 +675,7 @@ void func_8029C22C(void) { void func_8029C304(s32 arg0) { f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); sp1C[1] = floor_getCurrentFloorYPosition(); fxRipple_802F3584(arg0, sp1C, (uintptr_t)func_802946CC()); } @@ -660,7 +683,7 @@ void func_8029C304(s32 arg0) { void func_8029C348(void) { f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); sp1C[0] += randf2(-30.0f, 30.0f); sp1C[1] += randf2(60.0f, 70.0f); sp1C[2] += randf2(-30.0f, 30.0f); @@ -675,7 +698,7 @@ void func_8029C3E8(f32 arg0, f32 arg1) { f32 sp2C; f32 sp28; - _player_getPosition(sp30); + playerPosition_get(sp30); sp28 = ml_map_f(baphysics_get_horizontal_velocity(), 0.0f, 1000.0f, arg0, arg1); sp2C = player_getYaw(); func_802589E4(sp3C, sp2C, sp28); @@ -740,7 +763,7 @@ void func_8029C674(void) { baflag_set(BA_FLAG_17_FIRST_PERSON_VIEW); ncDynamicCamera_enterFirstPerson(); func_8028E9C4(5, sp1C); - ncFirstPersonCamera_setZoomedOutPosition(sp1C); + ncba1p_setZoomedOutPosition(sp1C); } } @@ -752,11 +775,11 @@ void func_8029C6D0(void) { if (balookat_getState() == 4 && D_8037D1E8) { func_8028E9C4(5, sp18); - ncFirstPersonCamera_setZoomedOutPosition(sp18); + ncba1p_setZoomedOutPosition(sp18); func_8028E9C4(5, sp30); balookat_try_get_position(sp24); func_802BC434(sp3C, sp24, sp30); - ncFirstPersonCamera_setZoomedOutRotation(sp3C); + ncba1p_setZoomedOutRotation(sp3C); } } @@ -780,7 +803,7 @@ enum bs_e bs_getTypeOfJump(void){ return BS_5_JUMP; } -void func_8029C7F4(s32 arg0, s32 yaw_state, s32 arg2, s32 arg3){ +void code_14420_setUpdateTypes(enum baanim_update_type_e arg0, enum yaw_state_e yaw_state, s32 arg2, BaPhysicsType arg3){ baanim_setUpdateType(arg0); yaw_setUpdateState(yaw_state); func_8029957C(arg2); @@ -850,16 +873,16 @@ s32 func_8029C9C0(s32 arg0){ // [port] v1.1 fix: check sliding first so claw swipe can't trigger during a slide if(bakey_pressed(BUTTON_B) && can_claw() && (EventSystem_Should(VB_CLAW_SWIPE_SLIDE, true) || !player_isSliding())) - arg0 = BS_CLAW; + arg0 = BS_6_CLAW; if(bakey_held(BUTTON_Z) && bainput_should_beak_barge()) - arg0 = BS_BBARGE; + arg0 = BS_13_BBARGE; if(bainput_should_look_first_person_camera()) arg0 = badrone_look(); if(player_isSliding()) - arg0 = BS_SLIDE; + arg0 = BS_32_SLIDE; return arg0; } @@ -878,14 +901,14 @@ s32 func_8029CA94(s32 arg0){ arg0 = BS_14_BTROT_ENTER; if(baflag_isTrue(BA_FLAG_6)) - arg0 = BS_53_TIMEOUT; + arg0 = BS_53_TIMEOUT_BANJO; if(baflag_isTrue(BA_FLAG_7_TOUCHING_JIGGY)) { arg0 = BS_44_JIG_JIGGY; } if(baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)) - arg0 = (player_getTransformation() == TRANSFORM_4_WALRUS) ? BS_80_WALRUS_SLED_LOSE : BS_53_TIMEOUT; + arg0 = (player_getTransformation() == TRANSFORM_4_WALRUS) ? BS_80_WALRUS_SLED_LOSE : BS_53_TIMEOUT_BANJO; baflag_clear(BA_FLAG_F); @@ -963,7 +986,7 @@ void func_8029CDC0(void) { f32 sp2C[3]; f32 sp20[3]; - _player_getPosition(sp20); + playerPosition_get(sp20); sp20[0] += (randf() * 90.0f) - 45.0f; sp20[2] += (randf() * 90.0f) - 45.0f; sp2C[0] = (randf() * 20.0f) - 10.0f; diff --git a/src/core2/bs/pumpkin.c b/src/core2/bs/pumpkin.c index 1f1b41ff9..c5f3d8b2e 100644 --- a/src/core2/bs/pumpkin.c +++ b/src/core2/bs/pumpkin.c @@ -5,6 +5,7 @@ #include "core2/ba/model.h" #include "core2/ba/anim.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" extern void baanim_playForDuration_loop(s32, f32); extern void func_8029AD68(f32, s32); @@ -53,8 +54,8 @@ void func_802B223C(void) { void func_802B229C(void) { if (!bspumpkin_inSet(bs_getNextState())) { bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -75,7 +76,7 @@ int bspumpkin_inSet(s32 move_indx){ void bspumpkin_idle_init(void) { baanim_playForDuration_loop(ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f); - func_8029C7F4(1, 1, 1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -119,7 +120,7 @@ void bspumpkin_walk_init(void) { anctrl_setDuration(anim_ctrl, 0.8f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bspumpkin.c", 0x11D); - func_8029C7F4(2, 1, 1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364CF0, D_80364CF4, D_80364CF8, D_80364CFC); func_802900B4(); } @@ -158,7 +159,7 @@ void bspumpkin_jump_init(void) { anctrl_setDuration(anim_ctrl, 1.2f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); anctrl_start(anim_ctrl, "bspumpkin.c", 0x16C); - func_8029C7F4(1, 1, 3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if (bastick_distance() != 0.0f) { yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -252,7 +253,7 @@ void bspumpkin_fall_init(void) { anctrl_setDuration(anim_ctrl, 0.7f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_STOPPED); anctrl_start(anim_ctrl, "bspumpkin.c", 0x1F1); - func_8029C7F4(1, 1, 3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); D_8037D4E0 = 0; } @@ -303,16 +304,16 @@ void bspumpkin_fall_end(void){ func_802B229C(); } -void func_802B2BF0(void) { +void bspumpkin_flush_init(void) { func_8029656C(D_8037D4E8); func_8028FAB0(D_8037D4E8); baanim_playForDuration_loop(ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f); - func_8029C7F4(1, 1, 2, BA_PHYSICS_FREEZE); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_FREEZE); func_80294378(6); batimer_set(0, 0.0f); } -void func_802B2C58(void) { +void bspumpkin_flush_update(void) { f32 sp3C; f32 sp38; f32 sp34; @@ -330,7 +331,7 @@ void func_802B2C58(void) { func_8028FAB0(sp28); } -void func_802B2D50(void) { +void bspumpkin_flush_end(void) { func_80294378(1); baModel_setScale(1.0f); } @@ -353,7 +354,7 @@ void __bspumpkin_bounce_init(s32 arg0) { } else { func_8030E58C(SFX_56_BANJO_HUI, 1.8f); } - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); func_80294980(sp20); func_80257F18(sp20, plyr_pos, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -361,7 +362,7 @@ void __bspumpkin_bounce_init(s32 arg0) { baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -441,7 +442,7 @@ void bspumpkin_die_init(void) { anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); anctrl_start(anim_ctrl, "bspumpkin.c", 0x32E); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); func_80294980(sp20); func_80257F18(sp20, plyr_pos, &sp38); D_8037D4F4 = 250.0f; @@ -450,12 +451,12 @@ void bspumpkin_die_init(void) { baphysics_set_target_horizontal_velocity(D_8037D4F4); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); pitch_setAngVel(1000.0f, 12.0f); func_802914CC(0xD); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8029C984(); baMarker_collisionOff(); baeyes_close(); @@ -532,15 +533,15 @@ void bspumpkin_die_end(void) { func_80291548(); } -void func_802B34A0(void) { +void bspumpkin_locked_init(void) { baanim_playForDuration_loopSmooth(0xA0, 0.8f); - func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); } -void func_802B34F8(void) { +void bspumpkin_locked_update(void) { s32 next_state; next_state = 0; @@ -552,7 +553,7 @@ void func_802B34F8(void) { bs_setState(next_state); } -void func_802B353C(void) { +void bspumpkin_locked_end(void) { func_8029C748(); func_802B229C(); } diff --git a/src/core2/bs/rebound.c b/src/core2/bs/rebound.c index 8c28825fe..a8f4b9f7a 100644 --- a/src/core2/bs/rebound.c +++ b/src/core2/bs/rebound.c @@ -4,6 +4,7 @@ #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" extern f32 func_80296548(void); extern f32 func_8029653C(void); @@ -27,7 +28,7 @@ void func_802B35DC(void) { void func_802B360C(void) { f32 sp44[3]; f32 sp38[3]; - f32 sp2C[3]; + f32 player_position[3]; f32 sp28; f32 sp24; f32 sp20; @@ -35,16 +36,16 @@ void func_802B360C(void) { sp1C = func_80296560(); func_80294980(sp38); - _player_getPosition(sp2C); - func_80257F18(sp38, sp2C, &sp28); + playerPosition_get(player_position); + func_80257F18(sp38, player_position, &sp28); if ((sp1C == 0xE) || (sp1C == 0x10)) { func_802B35D0(1); - func_8029C7F4(1, 1, 2, BA_PHYSICS_UNK1); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_UNK1); yaw_setIdeal(mlNormalizeAngle(sp28)); baphysics_set_gravity(func_80296548()); sp20 = func_8029653C(); - sp24 = func_8029B56C(sp2C[1], sp38[1], sp20, baphysics_get_gravity()); - ml_vec3f_diff_copy(sp44, sp38, sp2C); + sp24 = func_8029B56C(player_position[1], sp38[1], sp20, baphysics_get_gravity()); + ml_vec3f_diff_copy(sp44, sp38, player_position); D_8037D504 = sp24; sp44[0] /= sp24; sp44[1] /= sp24; @@ -61,7 +62,7 @@ void func_802B360C(void) { baphysics_set_horizontal_velocity(sp28, baphysics_get_target_horizontal_velocity()); baphysics_set_vertical_velocity(barebound_get_vertical_velocity()); baphysics_set_gravity(barebound_get_gravity()); - func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); if (barebound_802987B4() == 2) { baphysics_set_type(BA_PHYSICS_AIRBORN); } @@ -85,7 +86,7 @@ void func_802B37DC(void) { } } -void func_802B3868(void) { +void rebound_init(void) { AnimCtrl *anim_ctrl; f32 sp20; @@ -109,7 +110,7 @@ void func_802B3868(void) { } -void func_802B3954(void) { +void rebound_update(void) { s32 next_state; AnimCtrl *anim_ctrl; @@ -132,7 +133,7 @@ void func_802B3954(void) { } -void func_802B3A20(void) { +void rebound_end(void) { func_802B35DC(); baphysics_reset_gravity(); baMarker_collisionOn(); diff --git a/src/core2/bs/rest.c b/src/core2/bs/rest.c index 7d625bf87..b811abb7d 100644 --- a/src/core2/bs/rest.c +++ b/src/core2/bs/rest.c @@ -3,6 +3,7 @@ #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" void func_802B3A50(void) { f32 sp34; @@ -10,7 +11,7 @@ void func_802B3A50(void) { f32 sp1C[3]; if (balookat_getState()) { - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); if (balookat_try_get_position(sp1C) && func_80257F18(plyr_pos, sp1C, &sp34)) { yaw_setIdeal(sp34); } @@ -22,7 +23,7 @@ void func_802B3AAC(enum asset_e anim_id, f32 anim_duration) { anim_ctrl = baanim_getAnimCtrlPtr(); if (anim_id == ASSET_14A_ANIM_BSREST_LISTEN) { - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); switch (anctrl_getIndex(baanim_getAnimCtrlPtr())) { case ASSET_14A_ANIM_BSREST_LISTEN: baanim_playForDuration_loopSmooth(anim_id, anim_duration); @@ -34,14 +35,14 @@ void func_802B3AAC(enum asset_e anim_id, f32 anim_duration) { anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); break; default: - baanim_playForDuration_once(ASSET_167_ANIM_BSREST_MOVE, 0.5f); + baanim_playForDuration_onceSmooth(ASSET_167_ANIM_BSREST_MOVE, 0.5f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); break; } } else { baanim_playForDuration_loopSmooth(anim_id, anim_duration); } - func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802B3A50(); } @@ -85,10 +86,10 @@ bool func_802B3BB0(void) { } void func_802B3CCC(void){ - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); } -void func_802B3CEC(void){ +void bsrest_bs73unknown_init(void){ enum asset_e anim_id; f32 anim_duration; @@ -96,7 +97,7 @@ void func_802B3CEC(void){ func_802B3AAC(anim_id, anim_duration); } -void func_802B3D1C(void) { +void bsrest_bs73unknown_update(void) { enum bs_e next_state; next_state = 0; @@ -109,11 +110,11 @@ void func_802B3D1C(void) { bs_setState(next_state); } -void func_802B3D6C(void){ +void bsrest_bs73unknown_end(void){ func_802B3CCC(); } -void func_802B3D8C(void){ +void bsrest_bs75unknown_init(void){ enum asset_e anim_id; f32 anim_duration; @@ -122,7 +123,7 @@ void func_802B3D8C(void){ } -void func_802B3DBC(void) { +void bsrest_bs75unknown_update(void) { enum bs_e next_state; next_state = 0; @@ -136,11 +137,11 @@ void func_802B3DBC(void) { } -void func_802B3E0C(void){ +void bsrest_bs75unknown_end(void){ func_802B3CCC(); } -void func_802B3E2C(void){ +void bsrest_bs74unknown_init(void){ enum asset_e anim_id; f32 anim_duration; @@ -149,7 +150,7 @@ void func_802B3E2C(void){ func_8029C674(); } -void func_802B3E64(void) { +void bsrest_bs74unknown_update(void) { s32 next_state; next_state = 0; @@ -167,7 +168,7 @@ void func_802B3E64(void) { } -void func_802B3EF4(void){ +void bsrest_bs74unknown_end(void){ func_802B3CCC(); func_8029C748(); } diff --git a/src/core2/bs/sled.c b/src/core2/bs/sled.c index 9d8a8ac92..eaa653542 100644 --- a/src/core2/bs/sled.c +++ b/src/core2/bs/sled.c @@ -2,6 +2,7 @@ #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" extern ActorMarker *func_80296554(void); @@ -29,7 +30,7 @@ void __bssled_unlinkSledMarker(void){ void bssled_init(void){ __bssled_linkSledMarker(); baanim_playForDuration_loopSmooth(ASSET_228_ANIM_BANJO_SLED, 1.8f); - func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); baphysics_set_target_horizontal_velocity(0.0f); func_80294A8C(0); func_80294378(6); diff --git a/src/core2/bs/slide.c b/src/core2/bs/slide.c index 3c2a75be5..1cd561ef8 100644 --- a/src/core2/bs/slide.c +++ b/src/core2/bs/slide.c @@ -3,6 +3,7 @@ #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .bss */ s32 D_8037D520; @@ -15,7 +16,7 @@ void func_802B40D0(void){ f32 sp2C[3]; f32 sp28; - _player_getPosition(sp38); + playerPosition_get(sp38); sp38[1] += 20.0f; D_8037D524++; if(!(D_8037D524 < 3)) @@ -68,7 +69,7 @@ void bsslide_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_setDuration(aCtrl, 1.0f); anctrl_start(aCtrl, "bsslide.c", 0x7f); - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_horizontal_velocity(yaw_getIdeal() ,baphysics_get_target_horizontal_velocity()); pitch_setAngVel(800.0f, 8.0f); diff --git a/src/core2/bs/splat.c b/src/core2/bs/splat.c index eb3ec99ed..0ec89715c 100644 --- a/src/core2/bs/splat.c +++ b/src/core2/bs/splat.c @@ -4,6 +4,7 @@ #include "bsint.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" void func_80292900(f32, f32); void baMotor_80250D94(f32, f32, f32); @@ -22,8 +23,8 @@ void func_802B4570(void) { void bssplat_init(void){ s32 sp1C; - baanim_playForDuration_onceSmooth(ASSET_149_ANIM_BSSPLAT, 1.1f); - func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_once(ASSET_149_ANIM_BSSPLAT, 1.1f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); bafalldamage_get_damage(&sp1C); item_adjustByDiffWithHud(ITEM_14_HEALTH, -sp1C); if(func_8029CEB0() == 4){ @@ -59,7 +60,7 @@ void bssplat_update(void){ sp1C = BS_2F_FALL; if(anctrl_isStopped(aCtrl)){ - baanim_playForDuration_once(ASSET_D2_ANIM_BSSPLAT, 2.25f); + baanim_playForDuration_onceSmooth(ASSET_D2_ANIM_BSSPLAT, 2.25f); D_8037D530 = 1; } break; diff --git a/src/core2/bs/stand.c b/src/core2/bs/stand.c index 1626eb750..d049e10fa 100644 --- a/src/core2/bs/stand.c +++ b/src/core2/bs/stand.c @@ -4,6 +4,7 @@ #include "bsint.h" #include "core2/statetimer.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" extern f32 bastick_distance(void); void yaw_setVelocityBounded(f32, f32); @@ -52,23 +53,23 @@ s32 func_802B488C(s32 arg0){ s32 retVal = arg0; switch(bastick_getZone()){ case 1: //L802B48CC - retVal = BS_WALK_CREEP; + retVal = BS_1F_WALK_CREEP; break; case 2: //L802B48D4 retVal = BS_2_WALK_SLOW; break; case 3: //L802B48D4 - retVal = BS_WALK; + retVal = BS_3_WALK; break; case 4: //L802B48D4 retVal = BS_4_WALK_FAST; break; } if(bakey_held(BUTTON_Z)) - retVal = BS_CROUCH; + retVal = BS_7_CROUCH; if(bakey_pressed(BUTTON_B) && can_claw()) - retVal = BS_CLAW; + retVal = BS_6_CLAW; if(bakey_pressed(BUTTON_A)) retVal = bs_getTypeOfJump(); @@ -77,7 +78,7 @@ s32 func_802B488C(s32 arg0){ retVal = badrone_look(); if(player_isSliding()) - retVal = BS_SLIDE; + retVal = BS_32_SLIDE; retVal = func_8029CA94(retVal); @@ -89,10 +90,10 @@ s32 func_802B488C(s32 arg0){ void bsstand_init(void){ if(bsclimb_inSet(bs_getPrevState())) - climbRelease(); + climb_release(); - baanim_playForDuration_once(ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + baanim_playForDuration_onceSmooth(ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802900B4(); D_8037D540 = 0; @@ -205,12 +206,12 @@ void bsstand_update(void) { if (sp18 & 8) { if (sp18 & 4) { if (anctrl_isAt(anim_ctrl, 0.0909f)) basfx_80299BD4(); - if (anctrl_isAt(anim_ctrl, 0.0909f)) func_8029E070(1); - if (anctrl_isAt(anim_ctrl, 0.6818f)) func_8029E070(0); + if (anctrl_isAt(anim_ctrl, 0.0909f)) modelAppendages_setKazooiesUpperHalfVisibility(true); + if (anctrl_isAt(anim_ctrl, 0.6818f)) modelAppendages_setKazooiesUpperHalfVisibility(false); }//L802B4E70 if (sp18 & 2) { - if (anctrl_isAt(anim_ctrl, 0.7727f)) func_8029E070(1); - if (anctrl_isAt(anim_ctrl, 0.9999f)) func_8029E070(0); + if (anctrl_isAt(anim_ctrl, 0.7727f)) modelAppendages_setKazooiesUpperHalfVisibility(true); + if (anctrl_isAt(anim_ctrl, 0.9999f)) modelAppendages_setKazooiesUpperHalfVisibility(false); }//L802B50E4 } else if (sp18 & 0x20) { if (anctrl_getIndex(anim_ctrl) == ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK) { @@ -242,13 +243,13 @@ void bsstand_update(void) { D_8037D540 = func_802B4870(D_8037D540); sp18 = D_80364D20[D_8037D540]; if (sp18 & 0x10) { - baanim_playForDuration_once(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); + baanim_playForDuration_onceSmooth(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); anctrl_start(anim_ctrl, "bsstand.c", 0x1AB); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802900FC(); } else if (sp18 & 0x20) { - baanim_playForDuration_once(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); - func_8029E070(1); + baanim_playForDuration_onceSmooth(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); + modelAppendages_setKazooiesUpperHalfVisibility(true); func_802900FC(); } else if (sp18 & 8) { if (anctrl_getIndex(anim_ctrl) == ASSET_6F_ANIM_BSSTAND_IDLE) { @@ -263,7 +264,7 @@ void bsstand_update(void) { anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_setStart(anim_ctrl, sp1C); anctrl_start(anim_ctrl, "bsstand.c", 0x1C3); - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); } } if (player_shouldFall() != 0) { @@ -273,14 +274,14 @@ void bsstand_update(void) { } void bsstand_end(void){ - func_8029E070(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); func_802900FC(); baeyes_open(); } //bsStand_Land_init void bsstand_landing_init(void){ - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); } @@ -309,11 +310,11 @@ void bsstand_landing_update(void){ ///BREAK??? void func_802B5350(void){ - s32 sp1C = bs_getInterruptType(); - if(sp1C == BS_INTR_D_SURF){ + s32 interrupt_type = bs_getInterruptType(); + if(interrupt_type == BS_INTR_D_SURF){ bs_setState(0x52); } - if(sp1C == 0x7){ + if(interrupt_type == BS_INTR_7){ if(bsStoredState_getTransformation() != TRANSFORM_1_BANJO) bs_setInterruptResponse(1); else{ @@ -321,14 +322,14 @@ void func_802B5350(void){ bs_setState(BS_3A_CARRY_IDLE); } } - else if(sp1C == 0x12){//L802B53D0 + else if(interrupt_type == BS_INTR_12){//L802B53D0 bs_setInterruptResponse(1); if( bsStoredState_getTransformation() == TRANSFORM_1_BANJO && !baflag_isTrue(BA_FLAG_F) && stateTimer_isDone(STATE_TIMER_0_UNKNOWN)){ bacarriedobj_spawn(baMarker_getCarriedObjectActorId()); bs_setInterruptResponse(2); } } - else if(sp1C == 0x8){//L802B5438 + else if(interrupt_type == BS_INTR_8){//L802B5438 bs_setInterruptResponse(2); bs_setState(BS_3C_TALK); }else{ diff --git a/src/core2/bs/surf.c b/src/core2/bs/surf.c index 6ad84a30b..89d803f76 100644 --- a/src/core2/bs/surf.c +++ b/src/core2/bs/surf.c @@ -3,12 +3,13 @@ #include "variables.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" /* .bss */ s32 D_8037D560; /* .code */ -void func_802B5FD0(void) { +void bssurf_init(void) { AnimCtrl *anim_ctrl; anim_ctrl = baanim_getAnimCtrlPtr(); @@ -17,12 +18,12 @@ void func_802B5FD0(void) { anctrl_setDuration(anim_ctrl, 1.8f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bssurf.c", 0x33); - func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); D_8037D560 = 1; } -void func_802B6064(void) { +void bssurf_update(void) { enum bs_e next_state; next_state = 0; @@ -34,12 +35,12 @@ void func_802B6064(void) { } D_8037D560 = 0; if (baflag_isTrue(BA_FLAG_6)) { - next_state = BS_53_TIMEOUT; + next_state = BS_53_TIMEOUT_BANJO; } bs_setState(next_state); } -void func_802B60D0(void){} +void bssurf_end(void){} void func_802B60D8(void) { if (bs_getInterruptType() == BS_INTR_D_SURF) { diff --git a/src/core2/bs/swim.c b/src/core2/bs/swim.c index a96668f62..e6e4d77a7 100644 --- a/src/core2/bs/swim.c +++ b/src/core2/bs/swim.c @@ -4,6 +4,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" extern void bainput_setDiveCooldown(s32, f32); @@ -73,7 +74,7 @@ void __bsswim_updateVelocity(void) { baphysics_set_target_horizontal_velocity(ml_interpolate_f(sp1C, bsSwimHorzVelocityMin, bsSwimHorzVelocityMax)); } -void swim_enteredWater(void) { +void __bsswim_enteredWater(void) { if (level_get() == LEVEL_9_RUSTY_BUCKET_BAY) { progressDialog_showDialogMaskZero(FILEPROG_AB_SWIM_OILY_WATER); } else if (gsworld_getMap() == MAP_46_CCW_WINTER) { @@ -139,10 +140,10 @@ void bsswim_idle_init(void) { anctrl_setDuration(anim_ctrl, 1.2f); anctrl_start(anim_ctrl, "bsswim.c", 0xFD); } - func_8029C7F4(1, 3, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NORMAL); yaw_setVelocityBounded(500.0f, 5.0f); baphysics_set_target_horizontal_velocity(0.0f); - swim_enteredWater(); + __bsswim_enteredWater(); bsSwimCurrentAnimation = 0; } @@ -180,7 +181,7 @@ void bsswim_idle_update(void) { next_state = BS_5_JUMP; } if (baflag_isTrue(BA_FLAG_6) || baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)) { - next_state = BS_D_TIMEOUT; + next_state = BS_D_TIMEOUT_TRANSFORMATION; } bs_setState(next_state); } @@ -245,7 +246,7 @@ void bsswim_swim_update(void) { if ((func_80294530() != 0) && (can_dive() != 0)) { func_802944D0(sp1C); if (sp1C[1] < -0.7) { - if ((floor_getCurrentFloorYPosition() - player_getYPosition()) > 90.0f) { + if ((floor_getCurrentFloorYPosition() - playerPosition_getY()) > 90.0f) { next_state = BS_30_DIVE_ENTER; } } @@ -257,7 +258,7 @@ void bsswim_swim_update(void) { next_state = BS_5_JUMP; } if (baflag_isTrue(BA_FLAG_6) || baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)) { - next_state = BS_D_TIMEOUT; + next_state = BS_D_TIMEOUT_TRANSFORMATION; } bs_setState(next_state); } @@ -266,13 +267,13 @@ void bsswim_swim_end(void){ __bsswim_end(); } -void __bsswim_enteredWater(void) { +void __bsswim_update_rotation(void) { f32 sp34; f32 plyr_pos[3]; f32 sp1C[3]; if (balookat_getState() != 0) { - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); if (balookat_try_get_position(sp1C) && func_80257F18(plyr_pos, sp1C, &sp34)) { yaw_setIdeal(sp34); } @@ -281,11 +282,11 @@ void __bsswim_enteredWater(void) { void bsswim_lookat_init(void) { baanim_playForDuration_loopSmooth(0x57, 1.2f); - func_8029C7F4(1, 3, 3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NORMAL); yaw_setVelocityBounded(500.0f, 5.0f); baphysics_set_target_horizontal_velocity(0.0f); - swim_enteredWater(); __bsswim_enteredWater(); + __bsswim_update_rotation(); } void bsswim_lookat_update(void) { @@ -295,7 +296,7 @@ void bsswim_lookat_update(void) { if (balookat_getState() == 0) { next_state = BS_2D_SWIM_IDLE; } - __bsswim_enteredWater(); + __bsswim_update_rotation(); bs_setState(next_state); } @@ -304,7 +305,7 @@ void bsswim_lookat_end(void){ } void bsswim_drone_init(void){ - swim_enteredWater(); + __bsswim_enteredWater(); bsdrone_init(); } diff --git a/src/core2/bs/talk.c b/src/core2/bs/talk.c index da8ad965a..e2c8fb195 100644 --- a/src/core2/bs/talk.c +++ b/src/core2/bs/talk.c @@ -20,7 +20,7 @@ void bstalk_init(void){ func_8029C848(player_anim_ctrl); anctrl_setPlaybackType(player_anim_ctrl, ANIMCTRL_LOOP); anctrl_start(player_anim_ctrl, "bstalk.c", 0x38); - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); get_talk_target_position(target_pos); func_80257F18(plyr_pos, target_pos, &yaw); yaw_setIdeal(yaw); diff --git a/src/core2/bs/throw.c b/src/core2/bs/throw.c index 2e5e95de3..ee4a64da0 100644 --- a/src/core2/bs/throw.c +++ b/src/core2/bs/throw.c @@ -5,7 +5,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" -extern ActorMarker *bacarry_get_marker(void); +extern ActorMarker *bacarry_getMarker(void); /* .bss */ u8 D_8037D580; @@ -35,12 +35,12 @@ void bsthrow_update(void){ f32 sp34[3]; f32 player_position[3]; f32 sp24; - ActorMarker *sp20 = bacarry_get_marker(); + ActorMarker *sp20 = bacarry_getMarker(); if(D_8037D580 == 0 && sp20 != NULL) bacarry_set_marker(sp20); - _player_getPosition(player_position); + playerPosition_get(player_position); get_throw_target_position(sp34); func_80257F18(player_position, sp34, &sp24); yaw_setIdeal(sp24); diff --git a/src/core2/bs/timeout.c b/src/core2/bs/timeout.c index 0d01ed5cc..03b3fef09 100644 --- a/src/core2/bs/timeout.c +++ b/src/core2/bs/timeout.c @@ -3,27 +3,28 @@ #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" void baeyes_openSingleEye(s32, f32); f32 func_8029B41C(void); -void ncDynamicCamD_func_802BF2C0(f32); +void ncbadie_func_802BF2C0(f32); -void func_802B6270(void){ - baanim_playForDuration_once(ASSET_77_ANIM_BSTIMEOUT, 3.2f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); +void timeout_banjo_init(void){ + baanim_playForDuration_onceSmooth(ASSET_77_ANIM_BSTIMEOUT, 3.2f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); - func_802914CC(0xd); + func_802914CC(0xD); yaw_setIdeal(func_8029B41C() + 35.0f); - ncDynamicCamD_func_802BF2C0(80.0f); - func_8025A58C(0,0xfa0); + ncbadie_func_802BF2C0(80.0f); + func_8025A58C(0, 4000); comusic_playTrack(COMUSIC_3C_MINIGAME_LOSS); core1_ce60_incOrDecCounter(false); - func_8029E070(1); + modelAppendages_setKazooiesUpperHalfVisibility(true); baMarker_collisionOff(); } -void func_802B6314(void){ +void timeout_banjo_update(void){ AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); if(anctrl_isAt(aCtrl, 0.0625f)) baeyes_close(); @@ -40,37 +41,37 @@ void func_802B6314(void){ func_8029B6F0(); } -void func_802B63C8(void){ +void timeout_banjo_end(void){ baeyes_open(); func_80291548(); core1_ce60_incOrDecCounter(true); } -void func_802B63F8(void){ +void timeout_transformation_init(void){ AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); anctrl_reset(aCtrl); func_8029C848(aCtrl); anctrl_setPlaybackType(aCtrl, ANIMCTRL_LOOP); - anctrl_start(aCtrl, "bstimeout.c", 0x7e); - func_8029C7F4(1,1,3,BA_PHYSICS_FREEZE); + anctrl_start(aCtrl, "bstimeout.c", 0x7E); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); baphysics_set_target_horizontal_velocity(0.0f); - func_802914CC(0xd); + func_802914CC(0xD); yaw_setIdeal(func_8029B41C() + 35.0f); - ncDynamicCamD_func_802BF2C0(80.0f); - func_8025A58C(0,0xfa0); + ncbadie_func_802BF2C0(80.0f); + func_8025A58C(0, 4000); comusic_playTrack(COMUSIC_3C_MINIGAME_LOSS); core1_ce60_incOrDecCounter(false); baMarker_collisionOff(); batimer_set(0, 2.9f); } -void func_802B64D0(void){ +void timeout_transformation_update(void){ if(batimer_decrement(0)) func_8029B6F0(); } -void func_802B6500(void){ - func_8029E070(0); +void timeout_transformation_end(void){ + modelAppendages_setKazooiesUpperHalfVisibility(false); func_80291548(); core1_ce60_incOrDecCounter(true); func_8025A904(); diff --git a/src/core2/bs/turn.c b/src/core2/bs/turn.c index 2a0dfc397..58758d251 100644 --- a/src/core2/bs/turn.c +++ b/src/core2/bs/turn.c @@ -54,10 +54,10 @@ void bsturn_update(void){ sp2C = BS_4_WALK_FAST; if(bakey_held(BUTTON_Z)) - sp2C = BS_CROUCH; + sp2C = BS_7_CROUCH; if(bakey_pressed(BUTTON_B)) - sp2C = BS_CLAW; + sp2C = BS_6_CLAW; if(bakey_pressed(BUTTON_A)) sp2C = bs_getTypeOfJump(); diff --git a/src/core2/bs/walk.c b/src/core2/bs/walk.c index c55574ad3..e2540c5ee 100644 --- a/src/core2/bs/walk.c +++ b/src/core2/bs/walk.c @@ -4,6 +4,7 @@ #include "animation.h" #include "core2/ba/anim.h" #include "core2/ba/physics.h" +#include "core2/yaw.h" void baanim_setDurationRange(f32, f32); void func_802927E0(f32, f32); @@ -96,10 +97,10 @@ s32 func_802B6F20(s32 arg0){ if(bakey_pressed(BUTTON_B)){ if( bsWalkWalkFastWalkVelocityThreshold < baphysics_get_target_horizontal_velocity()){ if(can_roll()) - arg0 = BS_ROLL; + arg0 = BS_31_ROLL; }else{//L802B6F74 if(can_claw()) - arg0 = BS_CLAW; + arg0 = BS_6_CLAW; } } return arg0; @@ -128,7 +129,7 @@ void bswalk_creep_init(void){ anctrl_setStart(anim_ctrl, start_position); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0xe4); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkMinCreepVelocity, bsWalkCreepSlowWalkVelocityThreshold, bsWalkSlowestCreepDuration, bsWalkFastestCreepDuration); } @@ -152,14 +153,14 @@ void bswalk_creep_update(void){ next_state = BS_2_WALK_SLOW; break; case 3://L802B7188 - next_state = BS_WALK; + next_state = BS_3_WALK; break; case 4: next_state = BS_4_WALK_FAST; break; }//L802B7194 if(player_isOnDangerousGround()) - next_state = BS_WALK_MUD; + next_state = BS_7A_WALK_MUD; if(bainput_should_look_first_person_camera()) next_state = badrone_look(); @@ -168,7 +169,7 @@ void bswalk_creep_update(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_CROUCH; + next_state = BS_7_CROUCH; next_state = func_802B6F20(next_state); @@ -176,7 +177,7 @@ void bswalk_creep_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_SLIDE; + next_state = BS_32_SLIDE; next_state = func_8029CA94(next_state); @@ -201,7 +202,7 @@ void bswalk_slow_init(void){ anctrl_setStart(anim_ctrl, start_position); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0x168); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkCreepSlowWalkVelocityThreshold, bsWalkSlowWalkWalkVelocityThreshold, bsWalkSlowestSlowWalkDuration, bsWalkFastestSlowWalkDuration); } @@ -222,17 +223,17 @@ void bswalk_slow_upate(void){ next_state = BS_1_IDLE; break; case 1://L802B7180 - next_state = BS_WALK_CREEP; + next_state = BS_1F_WALK_CREEP; break; case 3://L802B7188 - next_state = BS_WALK; + next_state = BS_3_WALK; break; case 4: next_state = BS_4_WALK_FAST; break; }//L802B7194 if(player_isOnDangerousGround()) - next_state = BS_WALK_MUD; + next_state = BS_7A_WALK_MUD; if(bainput_should_look_first_person_camera()) next_state = badrone_look(); @@ -241,7 +242,7 @@ void bswalk_slow_upate(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_CROUCH; + next_state = BS_7_CROUCH; next_state = func_802B6F20(next_state); @@ -249,7 +250,7 @@ void bswalk_slow_upate(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_SLIDE; + next_state = BS_32_SLIDE; next_state = func_8029CA94(next_state); @@ -279,7 +280,7 @@ void bswalk_init(void){ anctrl_setStart(anim_ctrl, start_position); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0x1ed); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkSlowWalkWalkVelocityThreshold, bsWalkWalkFastWalkVelocityThreshold, bsWalkSlowestWalkDuration, bsWalkFastestWalkDuration); func_802B6EB0(0.3f); @@ -304,10 +305,10 @@ void bswalk_update(void){ break; }//L802B76B8 if(player_isOnDangerousGround()) - next_state = BS_WALK_MUD; + next_state = BS_7A_WALK_MUD; if(func_8028B4C4() && bsWalkSkidVelocity < baphysics_get_horizontal_velocity()){ - next_state = BS_SKID; + next_state = BS_C_SKID; } if(bainput_should_look_first_person_camera()) @@ -317,7 +318,7 @@ void bswalk_update(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_CROUCH; + next_state = BS_7_CROUCH; next_state = func_802B6F20(next_state); @@ -325,7 +326,7 @@ void bswalk_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_SLIDE; + next_state = BS_32_SLIDE; next_state = func_8029CA94(next_state); @@ -363,7 +364,7 @@ void bswalk_fast_init(void){ anctrl_setStart(anim_ctrl, sp28); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0x27d); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkWalkFastWalkVelocityThreshold, bsWalkMaxFastWalkVelocity, bsWalkSlowestFastWalkDuration, bsWalkFastestFastWalkDuration); pitch_setAngVel(1000.0f, 12.0f); @@ -400,24 +401,24 @@ void bswalk_fast_update(void){ break; case 3://L802B7A60 if(baphysics_is_slower_than(bsWalkWalkFastWalkVelocityThreshold) && func_802B6EF4()) - next_state = BS_WALK; + next_state = BS_3_WALK; if(bainput_should_look_first_person_camera()) next_state = badrone_look(); break; }//L802B7AA4 if(player_isOnDangerousGround()) - next_state = BS_WALK_MUD; + next_state = BS_7A_WALK_MUD; if(func_8028B4C4() && bsWalkSkidVelocity < baphysics_get_horizontal_velocity()){ - next_state = BS_SKID; + next_state = BS_C_SKID; } if(player_shouldFall()) next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_CROUCH; + next_state = BS_7_CROUCH; next_state = func_802B6F20(next_state); @@ -425,7 +426,7 @@ void bswalk_fast_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_SLIDE; + next_state = BS_32_SLIDE; next_state = func_8029CA94(next_state); @@ -442,7 +443,7 @@ void bswalk_fast_end(void){ void bswalk_mud_init(void){ baanim_playForDuration_loopSmooth(ASSET_B_ANIM_BSWALK_MUD, 0.43f); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkMinMudVelocity, bsWalkMaxMudVelocity, bsWalkSlowestMudDuration, bsWalkFastestMudDuration); } @@ -466,7 +467,7 @@ void bswalk_mud_update(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_CROUCH; + next_state = BS_7_CROUCH; next_state = func_802B6F20(next_state); @@ -474,7 +475,7 @@ void bswalk_mud_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_SLIDE; + next_state = BS_32_SLIDE; next_state = func_8029CA94(next_state); diff --git a/src/core2/bs/walrus.c b/src/core2/bs/walrus.c index 952203c40..9b45a6a76 100644 --- a/src/core2/bs/walrus.c +++ b/src/core2/bs/walrus.c @@ -4,6 +4,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" extern void func_8029AD68(f32, s32); @@ -93,8 +94,8 @@ void func_802B8048(void){ pitch_setIdeal(0.0f); roll_setIdeal(0.0f); bastick_resetZones(); - func_8029E070(0); - func_8029E064(0); + modelAppendages_setKazooiesUpperHalfVisibility(false); + modelAppendages_setKazooiesFeetAndShoesVisibility(false); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -105,7 +106,7 @@ void func_802B8048(void){ void func_802B80D0(void) { if (bswalrus_inSledSet(bs_getNextState()) == 0) { func_802B8048(); - func_8029E0E8(0); + modelAppendages_setSledVisibility(false); } } @@ -116,7 +117,7 @@ void func_802B8110(void){ void func_802B813C(void) { if (!bswalrus_inSledSet(bs_getPrevState())) { D_8037D5C0 = 0.0f; - func_8029E0E8(1); + modelAppendages_setSledVisibility(true); func_8029CF48(4, 1, 0.15f); } } @@ -132,18 +133,18 @@ int bswalrus_inSledSet(enum bs_e state){ int bswalrus_inSet(enum bs_e state){ return state == BS_67_WALRUS_IDLE - || state == BS_WALRUS_WALK - || state == BS_WALRUS_JUMP + || state == BS_68_WALRUS_WALK + || state == BS_69_WALRUS_JUMP || state == BS_6A_WALRUS_FALL - || state == BS_WALRUS_OW - || state == BS_WALRUS_DIE + || state == BS_6C_WALRUS_OW + || state == BS_6D_WALRUS_DIE || state == BS_95_WALRUS_DRONE || bswalrus_inSledSet(state); } void bswalrus_idle_init(void){ baanim_playForDuration_loopSmooth(ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f); - func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -166,10 +167,10 @@ void bswalrus_idle_update(void){ next_state = badrone_look(); if(bastick_getZone() > 0) - next_state = BS_WALRUS_WALK; + next_state = BS_68_WALRUS_WALK; if(bakey_pressed(BUTTON_A)) - next_state = BS_WALRUS_JUMP; + next_state = BS_69_WALRUS_JUMP; bs_setState(next_state); } @@ -181,7 +182,7 @@ void bswalrus_idle_end(void){ void bswalrus_walk_init(void){ baanim_playForDuration_loopSmooth(ASSET_120_ANIM_BSWALRUS_WALK, 0.8f); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364DC0, D_80364DC4, D_80364DC8, D_80364DCC); func_802900B4(); func_802B8110(); @@ -201,7 +202,7 @@ void bswalrus_walk_update(void){ next_state = BS_6A_WALRUS_FALL; if(bakey_pressed(BUTTON_A)) - next_state = BS_WALRUS_JUMP; + next_state = BS_69_WALRUS_JUMP; bs_setState(next_state); } @@ -222,7 +223,7 @@ void bswalrus_jump_init(void){ anctrl_setStart(aCtrl, 0.1); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bswalrus.c", 0x1f8); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -289,10 +290,10 @@ void bswalrus_jump_update(void){ if(player_isStable()){ if(bastick_getZone() > 0) - next_state = BS_WALRUS_WALK; + next_state = BS_68_WALRUS_WALK; if(bakey_pressed(BUTTON_A)) - next_state = BS_WALRUS_JUMP; + next_state = BS_69_WALRUS_JUMP; } bs_setState(next_state); @@ -311,7 +312,7 @@ void bswalrus_fall_init(void){ anctrl_setDuration(aCtrl, 0.7f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bswalrus.c", 0x284); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); func_802B8110(); D_8037D5C8 = 0; } @@ -372,13 +373,13 @@ static void __bswalrus_recoil_init(s32 damage){ f32 sp24[3]; barebound_set_active(func_80296560()); - baanim_playForDuration_onceSmooth(0x19c, 1.0f); + baanim_playForDuration_once(ASSET_19C_ANIM_BSWALRUS_BOUNCE, 1.0f); if(damage == 1) func_8030E58C(SFX_38_BANJO_AYE_1, 1.8f); else func_8030E58C(SFX_56_BANJO_HUI, 1.8f); - _player_getPosition(sp30); + playerPosition_get(sp30); func_80294980(sp24); func_80257F18(sp24, sp30, &sp3C); yaw_setIdeal(mlNormalizeAngle(sp3C + 180.0f)); @@ -386,7 +387,7 @@ static void __bswalrus_recoil_init(s32 damage){ baphysics_set_target_horizontal_velocity(barebound_get_horizontal_velocity()); baphysics_set_target_yaw(sp3C); baphysics_set_horizontal_velocity(sp3C, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(barebound_get_vertical_velocity()); baphysics_set_gravity(barebound_get_gravity()); baMarker_collisionOff(); @@ -451,7 +452,7 @@ void bswalrus_die_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bswalrus.c", 0x366); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); - _player_getPosition(sp2C); + playerPosition_get(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); D_8037D5C4 = 250.0f; @@ -460,12 +461,12 @@ void bswalrus_die_init(void){ baphysics_set_target_horizontal_velocity(D_8037D5C4); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(420.0f); //B) baphysics_set_gravity(-1200.0f); pitch_setAngVel(1000.0f, 12.0f); func_802914CC(0xd); - ncDynamicCamD_func_802BF2C0(30.0f); + ncbadie_func_802BF2C0(30.0f); func_8025AB00(); func_8025A2FC(0, 0xfa0); comusic_playTrack(0x1A); @@ -530,16 +531,16 @@ void bswalrus_drone_end(void){ func_802B8048(); } -void func_802B90D0(void){ +void bswalrus_sledlocked_init(void){ baanim_playForDuration_loopSmooth(ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f); - func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B813C(); func_802B3A50(); } -void func_802B9130(void){ +void bswalrus_sledlocked_update(void){ enum bs_e next_state = 0; func_802B3A50(); func_80299628(0); @@ -550,14 +551,14 @@ void func_802B9130(void){ bs_setState(next_state); } -void func_802B917C(void){ +void bswalrus_sledlocked_end(void){ func_8029C748(); func_802B80D0(); } void bswalrus_sled_init(void){ baanim_playForDuration_loopSmooth(ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f); - func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); + code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364DC0, D_80364DC4, D_80364DE0, D_80364DE4); func_802900B4(); func_802B813C(); @@ -603,7 +604,7 @@ void bswalrus_sled_jump_init(void){ anctrl_setStart(aCtrl, 0.14f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bswalrus.c", 0x477); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -663,7 +664,7 @@ void bswalrus_sled_jump_end(void){ func_802B80D0(); } -void func_802B95A0(void){ +void bswalrus_sledloseinair_init(void){ AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); anctrl_reset(aCtrl); anctrl_setIndex(aCtrl, ASSET_19F_ANIM_BSWALRUS_SLED_JUMP); @@ -671,12 +672,12 @@ void func_802B95A0(void){ anctrl_setDuration(aCtrl, 1.0f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bswalrus.c", 0x4e2); - func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); func_802B813C(); D_8037D5C8 = 0; } -void func_802B963C(void){ +void bswalrus_sledloseinair_update(void){ enum bs_e next_state = 0; AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); f32 sp1C[3]; @@ -720,16 +721,16 @@ void func_802B963C(void){ bs_setState(next_state); } -void func_802B976C(void){ +void bswalrus_sledloseinair_end(void){ func_802B8048(); } void bswalrus_timeout_init(void) { - baanim_playForDuration_once(ASSET_1A9_ANIM_BSWALRUS_LOSS, 3.2f); - func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); + baanim_playForDuration_onceSmooth(ASSET_1A9_ANIM_BSWALRUS_LOSS, 3.2f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); baphysics_set_target_horizontal_velocity(0.0f); func_802914CC(0xD); - ncDynamicCamD_func_802BF2C0(60.0f); + ncbadie_func_802BF2C0(60.0f); func_8025A58C(0, 4000); comusic_playTrack(COMUSIC_3C_MINIGAME_LOSS); core1_ce60_incOrDecCounter(false); @@ -739,7 +740,7 @@ void bswalrus_timeout_init(void) { baeyes_close(); } -void func_802B9830(void) { +void bswalrus_timeout_update(void) { yaw_setIdeal(func_8029B41C() + 35.0f); func_80299628(0); if (batimer_decrement(0) != 0) { @@ -747,7 +748,7 @@ void func_802B9830(void) { } } -void func_802B9880(void) { +void bswalrus_timeout_end(void) { func_80291548(); core1_ce60_incOrDecCounter(true); func_8025A904(); diff --git a/src/core2/bs/washing_machine.c b/src/core2/bs/washy.c similarity index 90% rename from src/core2/bs/washing_machine.c rename to src/core2/bs/washy.c index aa08904df..6494ece1b 100644 --- a/src/core2/bs/washing_machine.c +++ b/src/core2/bs/washy.c @@ -1,9 +1,11 @@ +// BanjoDecomp: core2/bs/washy.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" +#include "core2/yaw.h" /* .bss */ u8 D_8037D5D0; @@ -42,18 +44,18 @@ void func_802B9980(s32 arg0){ D_8037D5D0 = arg0; } -void func_802B9AAC(void){ +void bswashy_end(void){ func_802900FC(); } -void func_802B9ACC(void){ - baanim_playForDuration_once(ASSET_281_ANIM_WISHYWASHY_DOOOH, 40.0f); - func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); +void bswashy_init(void){ + baanim_playForDuration_onceSmooth(ASSET_281_ANIM_WISHYWASHY_DOOOH, 40.0f); + code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); func_802900B4(); func_802B9980(0); } -void func_802B9B14(void){ +void bswashy_update(void){ s32 next_state = 0; s32 sp18; diff --git a/src/core2/bundle.c b/src/core2/bundle.c index c162b7d1a..ce710eb32 100644 --- a/src/core2/bundle.c +++ b/src/core2/bundle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_41FB0.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/camera/dynamicCam1.c b/src/core2/camera/dynamicCam1.c deleted file mode 100644 index fd28a665b..000000000 --- a/src/core2/camera/dynamicCam1.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" - -extern f32 func_802BD51C(void); -extern f32 player_getYaw(void); -extern void func_802BD870(f32, f32, f32, f32); - -void ncDynamicCam1_init(void){ - func_802BD870(12.0f, 10.0f, 120.0f, 120.0f); -} - -void ncDynamicCam1_end(void){} - -void ncDynamicCam1_update(void) { - f32 sp8C[3]; - f32 sp80[3]; - f32 sp74[3]; - f32 sp68[3]; - f32 sp5C[3]; - f32 sp50[3]; - f32 sp4C; - f32 sp48; - f32 temp_f20; - f32 sp40; - f32 sp3C; - - ncDynamicCamera_getPosition(sp74); - func_802BD4C0(sp8C); - sp3C = func_802BD8D4(); - temp_f20 = time_getDelta(); - ml_vec3f_diff_copy(sp50, sp74, sp8C); - sp4C = gu_sqrtf((sp50[0] * sp50[0]) + (sp50[2] * sp50[2])); - sp4C += func_80259198((sp3C - sp4C) * temp_f20 * 2, temp_f20 * 120.0f); - func_8025801C(sp50, &sp48); - sp40 = func_80259198(mlDiffDegF(mlNormalizeAngle(180.0f + player_getYaw()), sp48) * (temp_f20 * 1), temp_f20 * 50.0f); - sp48 = mlNormalizeAngle(sp48 + sp40); - func_80256E24(sp68, 0.0f, sp48, 0.0f, 0.0f, sp4C); - ml_vec3f_add(sp80, sp8C, sp68); - sp80[1] = sp74[1] + ((func_802BD51C() - sp74[1]) * temp_f20 * 2); - ncDynamicCamera_setPosition(sp80); - func_8025727C(sp8C[0], sp8C[1], sp8C[2], sp80[0], sp80[1], sp80[2], &sp5C[0], &sp5C[1]); - sp5C[0] = -sp5C[0]; - sp5C[2] = 0.0f; - func_802BD720(sp5C); -} diff --git a/src/core2/ch/beehive.c b/src/core2/ch/beehive.c index c54111705..4f4037470 100644 --- a/src/core2/ch/beehive.c +++ b/src/core2/ch/beehive.c @@ -34,8 +34,8 @@ void chBeehive_die(ActorMarker *this, ActorMarker *other){ __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_4C_STEAM, reinterpret_cast(s32, actor->position[0]), reinterpret_cast(s32, actor->position[1]), reinterpret_cast(s32, actor->position[2])); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_4A_WOOD_EXPLOSION, reinterpret_cast(s32, actor->position[0]), reinterpret_cast(s32, actor->position[1]), reinterpret_cast(s32, actor->position[2])); actor->marker->propPtr->unk8_3 = 0; - func_803115C4(ASSET_D96_DIALOG_BEEHIVE_MEET); - func_803115C4(ASSET_DA6_DIALOG_BEEHIVE_WITH_BEES); + func_803115C4(VER_SELECT(ASSET_D96_DIALOG_BEEHIVE_MEET, 0x0A14, 0, 0)); + func_803115C4(VER_SELECT(ASSET_DA6_DIALOG_BEEHIVE_WITH_BEES, 0x0A24, 0, 0)); } void chBeehive_update(Actor *this){ @@ -62,7 +62,7 @@ void chBeehive_update(Actor *this){ ){ if(player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT){ if( player_getTransformation() == TRANSFORM_1_BANJO - && gcdialog_showDialog(ASSET_D96_DIALOG_BEEHIVE_MEET, 0, NULL, NULL, NULL, 0) + && gcdialog_showDialog(VER_SELECT(ASSET_D96_DIALOG_BEEHIVE_MEET, 0xA14, 0, 0), 0, NULL, NULL, NULL, 0) ){ fileProgressFlag_set(FILEPROG_D_BEEHIVE_TEXT, 1); } diff --git a/src/core2/ch/beeswarm.c b/src/core2/ch/beeswarm.c index 40ccdb12b..a45d072ca 100644 --- a/src/core2/ch/beeswarm.c +++ b/src/core2/ch/beeswarm.c @@ -1,8 +1,6 @@ #include #include "functions.h" #include "variables.h" - -#include "core2/quiz_storage.h" #include "port/Interpolation/FrameInterpolation.h" extern void func_8030DBFC(u32, f32, f32, f32); @@ -39,7 +37,7 @@ Actor *chBeeSwarm_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); /* .data */ -ActorInfo D_80367310 = { +ActorInfo chBeeSwarm = { MARKER_217_BEE_SWARM, ACTOR_34D_BEE_SWARM, ASSET_49E_SPRITE_BEE_SWARM, 1, NULL, chBeeSwarm_update, NULL, chBeeSwarm_draw, @@ -225,7 +223,7 @@ void chBeeSwarm_802CF1C8(f32 arg0[3], f32 arg1[3], f32 arg2[3], f32 arg3, f32 ar } if (arg5 != 0) { sp3C[0] = sp3C[1] = sp3C[2] = 0.0f; - func_8025727C(arg2[0], arg2[1], arg2[2], sp3C[0], sp3C[1], sp3C[2], arg5, arg5 + 1); + ml_horizontal_and_vertical_angles(arg2[0], arg2[1], arg2[2], sp3C[0], sp3C[1], sp3C[2], arg5, arg5 + 1); } } @@ -451,7 +449,7 @@ void chBeeSwarm_update(Actor *this) { if (!fileProgressFlag_get(FILEPROG_8F_MET_BEE_INFESTED_BEEHIVE) && subaddie_playerIsWithinCylinder(this, 250, 300) && ((player_movementGroup() == BSGROUP_0_NONE) || (player_movementGroup() == BSGROUP_8_TROT)) && (player_getTransformation() == TRANSFORM_1_BANJO) - && (gcdialog_showDialog(0xDA6, 0, NULL, NULL, NULL, NULL) != 0) + && (gcdialog_showDialog(VER_SELECT(0xDA6, 0xA24, 0, 0), 0, NULL, NULL, NULL, NULL) != 0) ) { fileProgressFlag_set(FILEPROG_8F_MET_BEE_INFESTED_BEEHIVE, true); } diff --git a/src/core2/ch/bottlesbonus.c b/src/core2/ch/bottlesbonus.c index be20b6560..f24b279ee 100644 --- a/src/core2/ch/bottlesbonus.c +++ b/src/core2/ch/bottlesbonus.c @@ -51,20 +51,21 @@ typedef struct{ extern void actor_postdrawMethod(ActorMarker *); extern void viewport_setNearAndFar(f32, f32); -extern s16 *func_8030C704(void); +extern s16 *picturebox_getColorBuffer(void); + Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chBottlesBonus_update(Actor *this); /* .data */ Struct_core2_560F0_0 D_803681A0[] = { { 0, 0x000, 0, 0x211}, - {99, 0xE27, 0, 0x2C1}, - {99, 0xE29, 0, 0x2C2}, - {99, 0xE2B, 0, 0x2C9}, - {99, 0xE2D, 0, 0x2C3}, - {99, 0xE2F, 0, 0x2C4}, - {99, 0xE31, 0, 0x2C5}, - {75, 0xE34, 0, 0x007} + {99, VER_SELECT(0xE27, 0xA69, 0, 0), 0, 0x2C1}, + {99, VER_SELECT(0xE29, 0xA6B, 0, 0), 0, 0x2C2}, + {99, VER_SELECT(0xE2B, 0xA6D, 0, 0), 0, 0x2C9}, + {99, VER_SELECT(0xE2D, 0xA6F, 0, 0), 0, 0x2C3}, + {99, VER_SELECT(0xE2F, 0xA71, 0, 0), 0, 0x2C4}, + {99, VER_SELECT(0xE31, 0xA73, 0, 0), 0, 0x2C5}, + {75, VER_SELECT(0xE34, 0xA76, 0, 0), 0, 0x007} }; ActorAnimationInfo chBottlesBonusAnimations[] ={ @@ -157,7 +158,7 @@ Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) void *sp50; sp6C = marker_getActor(marker); - sp50 = func_8030C704(); //grabs frame as texture? + sp50 = picturebox_getColorBuffer(); //grabs frame as texture? if ((sp50 == NULL) || (getGameMode() != GAME_MODE_8_BOTTLES_BONUS)) return sp6C; @@ -171,9 +172,9 @@ Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) gDPSetTextureFilter((*gfx)++, G_TF_BILERP); gDPSetColorDither((*gfx)++, G_CD_DISABLE); func_802DF160(gfx, mtx, vtx); - func_80253190(gfx); - - gDPSetTextureFilter((*gfx)++, G_TF_BILERP); + depthbuffer_clear(gfx); + + gDPSetTextureFilter((*gfx)++, G_TF_POINT); gSPSegment((*gfx)++, 0x04, osVirtualToPhysical(sp50)); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)sp6C); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); diff --git a/src/core2/ch/bottlesbonuscursor.c b/src/core2/ch/bottlesbonuscursor.c index 5e328b2c0..4b37d33a9 100644 --- a/src/core2/ch/bottlesbonuscursor.c +++ b/src/core2/ch/bottlesbonuscursor.c @@ -37,25 +37,25 @@ void chBottlesBonusCursor_func_802DF99C(void); void chBottlesBonusCursor_update(Actor *this); /* .data */ -ActorAnimationInfo D_803683B0[] = { +ActorAnimationInfo chBottlesBonusCursorAnimations[] = { {0x000, 0.0f}, - {0x2A2, 1.0f}, - {0x2A5, 1.0f}, - {0x2A4, 0.4f}, - {0x2A3, 0.4f}, - {0x2A1, 0.3f}, - {0x2A7, 0.4f}, - {0x2A1, 0.3f}, - {0x2A6, 2.6f}, - {0x2A8, 2.6f} + {ASSET_2A2_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 1.0f}, + {ASSET_2A5_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 1.0f}, + {ASSET_2A4_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.4f}, + {ASSET_2A3_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.4f}, + {ASSET_2A1_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.3f}, + {ASSET_2A7_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.4f}, + {ASSET_2A1_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.3f}, + {ASSET_2A6_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 2.6f}, + {ASSET_2A8_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 2.6f} }; f32 D_80368400[3] = {570.0f, 328.9f, -186.4f}; f32 D_8036840C[3] = {-11.28f, 3.92f, -52.96f}; -ActorInfo D_80368418 = { - 0x17A, 0x2B4, 0x565, - 0x1, D_803683B0, +ActorInfo chBottlesBonusCursor = { + MARKER_17A_BOTTLES_BONUS_BANJO_HAND, ACTOR_2B4_BOTTLES_BONUS_BANJO_HAND, ASSET_565_MODEL_BOTTLES_BONUS_BANJO_HAND, + 0x1, chBottlesBonusCursorAnimations, chBottlesBonusCursor_update, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 }; @@ -65,6 +65,7 @@ ActorMarker *chBottlesBonusCursorMarker; f32 D_8037E068[60][2]; Struct_core2_584D0_0 D_8037E248[20]; //puzzle pieces s32 D_8037E5B8; + struct { s32 unk0; u8 pad4[0xC]; @@ -76,6 +77,7 @@ struct { f32 unk28; f32 unk2C; } D_8037E5C0; + f32 D_8037E5F0; f32 D_8037E5F4; f32 D_8037E5F8[3]; @@ -152,7 +154,7 @@ void chBottlesBonusCursor_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { actor_setOpacity(this, 0xB9); viewport_func_8024E030(this->position, D_8037E5C0.unk18); sp3C = (this->scale * 650.0f); - func_80253208(gfx, + depthbuffer_clearRegion(gfx, (s32)(D_8037E5C0.unk18[0] - sp3C/2), (s32)(D_8037E5C0.unk18[1] - sp3C/2), (s32)sp3C, (s32)sp3C, gFramebuffers[getActiveFramebuffer()] diff --git a/src/core2/ch/climb_base.c b/src/core2/ch/climbBase.c similarity index 95% rename from src/core2/ch/climb_base.c rename to src/core2/ch/climbBase.c index 5b3f87c66..a3e561bac 100644 --- a/src/core2/ch/climb_base.c +++ b/src/core2/ch/climbBase.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/climbBase.c #include #include "functions.h" #include "variables.h" @@ -12,8 +13,8 @@ typedef struct { }ActorLocal_climbBase; /* .data */ -ActorInfo D_80367B20 = { - 0x35, 0x26, 0x0, +ActorInfo D_80367B20 = { + MARKER_35_CLIMB_BASE, ACTOR_26_CLIMB_BASE, 0x0, 0x1, NULL, func_802D77D4, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 diff --git a/src/core2/ch/clucker.c b/src/core2/ch/clucker.c index d3b77877a..3c3953bb7 100644 --- a/src/core2/ch/clucker.c +++ b/src/core2/ch/clucker.c @@ -2,7 +2,7 @@ #include "functions.h" #include "variables.h" -extern void func_8033A45C(s32, s32); +extern void modelRender_setAppendageVisibility(s32, s32); typedef struct{ u8 unk0; @@ -118,8 +118,8 @@ void chClucker_die(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *chClucker_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - func_8033A45C(3, (this->state == 5)? 1 : 0); - func_8033A45C(4, (this->state == 0 || this->state == 1 || this->state == 6)? 0 : 1); + modelRender_setAppendageVisibility(3, (this->state == 5)? 1 : 0); + modelRender_setAppendageVisibility(4, (this->state == 0 || this->state == 1 || this->state == 6)? 0 : 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/core2/ch/collectible.c b/src/core2/ch/collectible.c index 9d6aafa1f..f31cf7f09 100644 --- a/src/core2/ch/collectible.c +++ b/src/core2/ch/collectible.c @@ -10,21 +10,21 @@ Actor *chCollectible_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); void chCollectible_update(Actor *this); /* .data */ -extern ActorInfo D_80367D00 = { +extern ActorInfo chBlueEgg = { MARKER_60_BLUE_EGG_COLLECTIBLE, ACTOR_52_BLUE_EGG, ASSET_36D_SPRITE_BLUE_EGG, 0, NULL, chCollectible_update, actor_update_func_80326224, chCollectible_draw, 0, 0, 0.7f, 0 }; -extern ActorInfo D_80367D24 = { +extern ActorInfo chRedFeather = { MARKER_B5_RED_FEATHER_COLLECTIBLE, ACTOR_129_RED_FEATHER, ASSET_580_SPRITE_RED_FEATHER, 0, NULL, chCollectible_update, actor_update_func_80326224, chCollectible_draw, 0, 0, 0.5f, 0 }; -extern ActorInfo D_80367D48 = { +extern ActorInfo chGoldFeather = { MARKER_1E5_GOLD_FEATHER_COLLECTIBLE, ACTOR_370_GOLD_FEATHER, ASSET_6D1_SPRITE_GOLDFEATHER, 0, NULL, chCollectible_update, actor_update_func_80326224, chCollectible_draw, @@ -99,7 +99,7 @@ s32 chCollectible_collectEgg(ActorProp *arg0){ if(arg0->isActorProp) actPtr = marker_getActor(arg0->marker); } - return chCollectible_collectItem(actPtr, FILEPROG_5_BLUE_EGG_TEXT, 0xD9E, COMUSIC_C_EGG_COLLECTED, 0xD, 2.0f); + chCollectible_collectItem(actPtr, FILEPROG_5_BLUE_EGG_TEXT, VER_SELECT(0xD9E, 0xA1C, 0, 0), COMUSIC_C_EGG_COLLECTED, 0xD, 2.0f); } bool chCollectible_collectRedFeather(ActorProp *arg0){ @@ -107,7 +107,7 @@ bool chCollectible_collectRedFeather(ActorProp *arg0){ fxSparkle_redFeather(&arg0->x); if(arg0->isActorProp) actPtr = marker_getActor(arg0->marker); - return chCollectible_collectItem(actPtr, FILEPROG_6_RED_FEATHER_TEXT, 0xD9F, COMUSIC_B_RED_FEATHER_COLLECTED, 0xF, 4.0f); + chCollectible_collectItem(actPtr, FILEPROG_6_RED_FEATHER_TEXT, VER_SELECT(0xD9F, 0xA1D, 0, 0), COMUSIC_B_RED_FEATHER_COLLECTED, 0xF, 4.0f); } bool chCollectible_collectGoldFeather(ActorProp *arg0){ @@ -115,7 +115,7 @@ bool chCollectible_collectGoldFeather(ActorProp *arg0){ fxSparkle_goldFeather(&arg0->x); if(arg0->isActorProp) actPtr = marker_getActor(arg0->marker); - return chCollectible_collectItem(actPtr, FILEPROG_7_GOLD_FEATHER_TEXT, 0xDA0, COMUSIC_14_GOLD_FEATHER_COLLECTED, ITEM_10_GOLD_FEATHER, 6.0f); + chCollectible_collectItem(actPtr, FILEPROG_7_GOLD_FEATHER_TEXT, VER_SELECT(0xDA0, 0xA1E, 0, 0), COMUSIC_14_GOLD_FEATHER_COLLECTED, ITEM_10_GOLD_FEATHER, 6.0f); } Actor *chCollectible_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3){ diff --git a/src/core2/ch/crab.c b/src/core2/ch/crab.c index a2193fdfe..6e253cb25 100644 --- a/src/core2/ch/crab.c +++ b/src/core2/ch/crab.c @@ -1,32 +1,47 @@ +// BanjoDecomp: core2/ch/crab.c #include #include "functions.h" #include "variables.h" /* .data */ + +enum crab_states +{ + CRAB_STATE_1_IDLE_UNK = 1, + CRAB_STATE_2_IDLE_UNK, + CRAB_STATE_3_TURN_TO_PLAYER, + CRAB_STATE_4_CHASE_PLAYER, + CRAB_STATE_5_UPSIDE_DOWN, + CRAB_STATE_6_FLIP_UPSIDE_DOWN, + CRAB_STATE_7_FLIP_UPRIGHT, + CRAB_STATE_8_MUTIES_FIRST_DIALOG, + CRAB_STATE_9_MUTIES_REVISIT +}; + ActorAnimationInfo chCrabAnimations[] ={ { 0, 0.0f}, - { ASSET_1DA_ANIM_CRAB_IDLE, 0.8f}, - { ASSET_2C_ANIM_CRAB_WALK, 2.0f}, - { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, - { ASSET_2C_ANIM_CRAB_WALK, 0.7f}, - { ASSET_96_ANIM_CRAB_UPSIDEDOWN, 0.5f}, + { ASSET_1DA_ANIM_CRAB_IDLE, 0.8f}, + { ASSET_2C_ANIM_CRAB_WALK, 2.0f}, + { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, + { ASSET_2C_ANIM_CRAB_WALK, 0.7f}, + { ASSET_96_ANIM_CRAB_UPSIDEDOWN, 0.5f}, { ASSET_97_ANIM_CRAB_FLIP_UPSIDEDOWN, 0.8f}, - { ASSET_155_ANIM_CRAB_FLIP_UPRIGHT, 0.55f}, - { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, - { ASSET_2C_ANIM_CRAB_WALK, 4.0f} + { ASSET_155_ANIM_CRAB_FLIP_UPRIGHT, 0.55f}, + { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, + { ASSET_2C_ANIM_CRAB_WALK, 4.0f} }; ActorAnimationInfo chCrabMutantAnimations[] = { {0x000, 0.0f}, - {ASSET_1DB_ANIM_MUTANT_CRAB_IDLE, 0.8f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 0.7f}, - {ASSET_158_ANIM_MUTANT_CRAB_UPSIDEDOWN, 0.5f}, + {ASSET_1DB_ANIM_MUTANT_CRAB_IDLE, 0.8f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 0.7f}, + {ASSET_158_ANIM_MUTANT_CRAB_UPSIDEDOWN, 0.5f}, {ASSET_157_ANIM_MUTANT_CRAB_FLIP_UPSIDEDOWN, 0.8f}, - {ASSET_159_ANIM_MUTANT_CRAB_UPRIGHT, 0.55f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f} + {ASSET_159_ANIM_MUTANT_CRAB_UPRIGHT, 0.55f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f} }; /* .code */ @@ -44,18 +59,18 @@ void __chCrab_802CB078(Actor *this) { return; } else{ - if( subaddie_playerIsWithinSphereAndActive(this, 1500) + if( subaddie_playerIsWithinSphereAndActive(this, 1500) && ( (this->modelCacheIndex == ACTOR_F2_BLACK_SNIPPET) || func_803292E0(this)) ) { this->actor_specific_1_f = 0.0f; - subaddie_set_state(this, 3U); + subaddie_set_state(this, CRAB_STATE_3_TURN_TO_PLAYER); } } } } void __chCrab_802CB140(Actor *this) { - subaddie_set_state(this, 2U); + subaddie_set_state(this, CRAB_STATE_2_IDLE_UNK); __chCrab_802CB040(this); func_80328CEC(this, (s32) this->yaw_ideal, 135, 175); this->unk38_31 = 150; @@ -65,10 +80,10 @@ void __chCrab_touch(ActorMarker *marker, ActorMarker *other){ Actor *this; this = marker_getActor(marker); - if ((this->state == 4) && func_803294F0(this, 80, subaddie_getYawToPlayer(this))) { + if ((this->state == CRAB_STATE_4_CHASE_PLAYER) && func_803294F0(this, 80, subaddie_getYawToPlayer(this))) { sfx_playFadeShorthandDefault(SFX_1E_HITTING_AN_ENEMY_2, 1.0f, 28000, this->position, 950, 1900); __chCrab_802CB140(this); - subaddie_set_state(this, 1); + subaddie_set_state(this, CRAB_STATE_1_IDLE_UNK); } } @@ -77,7 +92,7 @@ void __chCrab_ow(ActorMarker *marker, ActorMarker *other) { this = marker_getActor(marker); this->lifetime_value = 3.0f; - subaddie_set_state(this, 6); + subaddie_set_state(this, CRAB_STATE_6_FLIP_UPSIDE_DOWN); actor_playAnimationOnce(this); if (marker->id == MARKER_13_SNIPPET) { sfx_playFadeShorthandDefault(SFX_6E_VILE_EGH, 2.0f, 26000, this->position, 950, 1900); @@ -142,7 +157,7 @@ void __chCrab_spawn_mutant_crab_jiggy(void) { } void __chCrab_mutantTextCallback(ActorMarker *caller, enum asset_e text_id, s32 model_id){ - if (text_id == ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT) { + if (text_id == VER_SELECT(ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT, 0xA06, 0, 0)) { func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.0f, 4); timedFunc_set_0(0.1f, __chCrab_spawn_mutant_crab_jiggy); @@ -150,17 +165,17 @@ void __chCrab_mutantTextCallback(ActorMarker *caller, enum asset_e text_id, s32 func_80324E38(3.0f, 0); return; } - levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, false); + levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, FALSE); } -s32 __chCrab_802CB76C(ActorMarker *marker, ActorMarker *other) { +bool __chCrab_802CB76C(ActorMarker *marker, ActorMarker *other) { Actor *this; this = marker_getActor(marker); if ((this->modelCacheIndex == ACTOR_F2_BLACK_SNIPPET) && !maCastle_hasBanjoKazooieCodeBeenEntered()) { - return false; + return FALSE; } - return true; + return TRUE; } void __chCrab_die(ActorMarker *marker, ActorMarker *other){ @@ -179,7 +194,7 @@ void __chCrab_die(ActorMarker *marker, ActorMarker *other){ sfx_playFadeShorthandDefault(SFX_79_TICKER_DEATH, 1.0f, 28000, this->position, 950, 1900); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_4C_STEAM, reinterpret_cast(s32, this->position[0]), reinterpret_cast(s32, this->position[1]), reinterpret_cast(s32, this->position[2])); this->lifetime_value = 5.0f; - marker->collidable = false; + marker->collidable = FALSE; this->unk138_27 = 1; marker_despawn(marker); if( gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN @@ -192,7 +207,7 @@ void __chCrab_die(ActorMarker *marker, ActorMarker *other){ jiggy_spawn_position[1] = 3812.0f; jiggy_spawn_position[2] = 0.0f; coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - func_80324DBC(2.25f, ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT, 0xF, jiggy_spawn_position, NULL, __chCrab_mutantTextCallback, NULL); + func_80324DBC(2.25f, VER_SELECT(ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT, 0xA06, 0, 0), 0xF, jiggy_spawn_position, NULL, __chCrab_mutantTextCallback, NULL); } } p_ctrl = partEmitMgr_newEmitter(2); @@ -235,10 +250,10 @@ void chCrab_update(Actor *this) { is_mutant_snippet = this->modelCacheIndex == ACTOR_F5_MUTIE_SNIPPET; if (!this->volatile_initialized) { marker_setCollisionScripts(this->marker, __chCrab_touch, __chCrab_ow, __chCrab_die); - func_803300C0(this->marker, &__chCrab_802CB76C); - this->unk124_0 = this->unk138_31 = false; - this->has_met_before = false; - this->volatile_initialized = true; + func_803300C0(this->marker, (s32 (*)(ActorMarker *, ActorMarker *)) &__chCrab_802CB76C); // [port] bool/s32 fn-ptr cast + this->unk124_0 = this->unk138_31 = FALSE; + this->has_met_before = FALSE; + this->volatile_initialized = TRUE; anctrl_setTransitionDuration(this->anctrl, 0.25f); if (gsworld_getMap() == MAP_A_TTC_SANDCASTLE) { if (!jiggyscore_isCollected(JIGGY_10_TTC_SANDCASTLE)) { @@ -267,11 +282,11 @@ void chCrab_update(Actor *this) { && subaddie_playerIsWithinSphereAndActive(this, 500) && !subaddie_playerIsWithinSphereAndActive(this, 200) && !player_movementGroup() ) { - if ((this->state != 6) && (this->state != 5)) { - gcdialog_showDialog(ASSET_D32_DIALOG_MUTANT_CRAB_MEET, 0xF, this->position, NULL, __chCrab_mutantTextCallback, NULL); - mapSpecificFlags_set(0, true); - levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, true); - this->has_met_before = true; + if ((this->state != CRAB_STATE_6_FLIP_UPSIDE_DOWN) && (this->state != CRAB_STATE_5_UPSIDE_DOWN)) { + gcdialog_showDialog(VER_SELECT(ASSET_D32_DIALOG_MUTANT_CRAB_MEET, 0xA05, 0, 0), 0xF, this->position, NULL, __chCrab_mutantTextCallback, NULL); + mapSpecificFlags_set(0, TRUE); + levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, TRUE); + this->has_met_before = TRUE; } } if (gsworld_getMap() == MAP_A_TTC_SANDCASTLE) { @@ -281,66 +296,66 @@ void chCrab_update(Actor *this) { && !jiggyscore_isCollected(JIGGY_10_TTC_SANDCASTLE) && subaddie_playerIsWithinSphereAndActive(this, 1600) ) { - gcdialog_showDialog(ASSET_A12_DIALOG_BLACK_SNIPPET_SPAWNED, 4, this->position, NULL, NULL, NULL); - mapSpecificFlags_set(0, true); + gcdialog_showDialog(VER_SELECT(ASSET_A12_DIALOG_BLACK_SNIPPET_SPAWNED, 0x912, 0, 0), 4, this->position, NULL, NULL, NULL); + mapSpecificFlags_set(0, TRUE); } else if (mapSpecificFlags_get(1)) { - gcdialog_showDialog(ASSET_A13_DIALOG_BLACK_SNIPPET_DEFEATED, 4, this->position, NULL, NULL, NULL); - mapSpecificFlags_set(1, false); + gcdialog_showDialog(VER_SELECT(ASSET_A13_DIALOG_BLACK_SNIPPET_DEFEATED, 0x913, 0, 0), 4, this->position, NULL, NULL, NULL); + mapSpecificFlags_set(1, FALSE); } } if (levelSpecificFlags_get(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS)) { - if ((this->state != 8) && (this->state != 9)) { - subaddie_set_state_with_direction(this, (this->has_met_before) ? 8 : 9, 0.0f, 1); - this->has_met_before = false; + if ((this->state != CRAB_STATE_8_MUTIES_FIRST_DIALOG) && (this->state != CRAB_STATE_9_MUTIES_REVISIT)) { + subaddie_set_state_with_direction(this, (this->has_met_before) ? CRAB_STATE_8_MUTIES_FIRST_DIALOG : CRAB_STATE_9_MUTIES_REVISIT, 0.0f, 1); + this->has_met_before = FALSE; } } switch(this->state){ - case 1: //L802CBE30 - if (subaddie_maybe_set_state(this, 2, 0.03f)) { + case CRAB_STATE_1_IDLE_UNK: //L802CBE30 + if (subaddie_maybe_set_state(this, CRAB_STATE_2_IDLE_UNK, 0.03f)) { __chCrab_802CB040(this); } __chCrab_802CB078(this); break; - case 9: //L802CBE6C + case CRAB_STATE_9_MUTIES_REVISIT: //L802CBE6C if (!levelSpecificFlags_get(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS)) { - subaddie_set_state_with_direction(this, 3, 0.0f, 1); + subaddie_set_state_with_direction(this, CRAB_STATE_3_TURN_TO_PLAYER, 0.0f, 1); } break; - case 2: //L802CBE9C + case CRAB_STATE_2_IDLE_UNK: //L802CBE9C subaddie_turnToYaw(this, 1.0f); if( func_8032CA80(this, (this->modelCacheIndex == ACTOR_F2_BLACK_SNIPPET)? 0xD: 0) && func_80329480(this) ) { func_80328CEC(this, (s32) this->yaw, 90, 150); } - subaddie_maybe_set_state_position_direction(this, 1, 0.0f, 1, 0.0075f); + subaddie_maybe_set_state_position_direction(this, CRAB_STATE_1_IDLE_UNK, 0.0f, 1, 0.0075f); __chCrab_802CB078(this); break; - case 3: //L802CBF44 + case CRAB_STATE_3_TURN_TO_PLAYER: //L802CBF44 this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); if (func_80329480(this)) { - subaddie_set_state(this, 4); + subaddie_set_state(this, CRAB_STATE_4_CHASE_PLAYER); this->actor_specific_1_f = 12.0f; } break; - case 8: //L802CBF9C + case CRAB_STATE_8_MUTIES_FIRST_DIALOG: //L802CBF9C this->yaw_ideal = subaddie_getYawToPlayer(this) + 90.0; subaddie_turnToYaw(this, 4.0f); if (func_80329480(this)) { - subaddie_set_state(this, 9); + subaddie_set_state(this, CRAB_STATE_9_MUTIES_REVISIT); this->actor_specific_1_f = 12.0f; } else if (!levelSpecificFlags_get(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS)) { - subaddie_set_state_with_direction(this, 3, 0.0f, 1); + subaddie_set_state_with_direction(this, CRAB_STATE_3_TURN_TO_PLAYER, 0.0f, 1); } break; - case 4: //L802CC024 + case CRAB_STATE_4_CHASE_PLAYER: //L802CC024 if ((globalTimer_getTime() & 0xF) == 9) { this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); } @@ -350,12 +365,12 @@ void chCrab_update(Actor *this) { } break; - case 5: //L802CC0AC + case CRAB_STATE_5_UPSIDE_DOWN: //L802CC0AC this->lifetime_value = MAX(0.0, this->lifetime_value - sp30); if (this->lifetime_value == 0.0f) { - subaddie_set_state(this, 7); + subaddie_set_state(this, CRAB_STATE_7_FLIP_UPRIGHT); actor_playAnimationOnce(this); - if (this->marker->id == 0x16B) { + if (this->marker->id == MARKER_16B_SNIPPET_UPSIDEDOWN) { this->marker->id = MARKER_13_SNIPPET; } if (this->marker->id == MARKER_DE_BLACK_SNIPPET_UPSIDEDOWN) { @@ -364,26 +379,26 @@ void chCrab_update(Actor *this) { } break; - case 6: //L802CC18C + case CRAB_STATE_6_FLIP_UPSIDE_DOWN: //L802CC18C if (anctrl_isStopped(this->anctrl)) { if (this->lifetime_value == 0.0f) { func_80326310(this); } else { - subaddie_set_state(this, 5); + subaddie_set_state(this, CRAB_STATE_5_UPSIDE_DOWN); actor_loopAnimation(this); } } break; - case 7: //L802CC1E8 + case CRAB_STATE_7_FLIP_UPRIGHT: //L802CC1E8 if (anctrl_isStopped(this->anctrl)) { - subaddie_set_state(this, 1); + subaddie_set_state(this, CRAB_STATE_1_IDLE_UNK); actor_loopAnimation(this); } break; } - if ((this->state == 2) || (this->state == 3) || (this->state == 4)) { + if ((this->state == CRAB_STATE_2_IDLE_UNK) || (this->state == CRAB_STATE_3_TURN_TO_PLAYER) || (this->state == CRAB_STATE_4_CHASE_PLAYER)) { if (sp34 != D_803670B0) { D_803670B0 = sp34; D_803670B4 = 1; @@ -397,6 +412,24 @@ void chCrab_update(Actor *this) { } /* .data */ -ActorInfo chSnippet = { MARKER_13_SNIPPET, ACTOR_67_SNIPPET, ASSET_358_SNIPPET, 0x1, chCrabAnimations, chCrab_update, actor_update_func_80326224, actor_draw, 1900, 0, 0.8f, 0}; -ActorInfo chBlackSnippet = { MARKER_DD_BLACK_SNIPPET, ACTOR_F2_BLACK_SNIPPET, ASSET_566_MODEL_BLACK_SNIPPET, 0x1, chCrabAnimations, chCrab_update, actor_update_func_80326224, actor_draw, 1900, 0, 0.8f, 0}; -ActorInfo chMutieSnippet = { MARKER_13_SNIPPET, ACTOR_F5_MUTIE_SNIPPET, ASSET_38F_MODEL_MUTIE_SNIPPET, 0x1, chCrabMutantAnimations, chCrab_update, actor_update_func_80326224, actor_draw, 1900, 0, 0.8f, 0}; + +ActorInfo chSnippet = { + MARKER_13_SNIPPET, ACTOR_67_SNIPPET, ASSET_358_SNIPPET, + 0x1, chCrabAnimations, + chCrab_update, actor_update_func_80326224, actor_draw, + 1900, 0, 0.8f, 0 +}; + +ActorInfo chBlackSnippet = { + MARKER_DD_BLACK_SNIPPET, ACTOR_F2_BLACK_SNIPPET, ASSET_566_MODEL_BLACK_SNIPPET, + 0x1, chCrabAnimations, + chCrab_update, actor_update_func_80326224, actor_draw, + 1900, 0, 0.8f, 0 +}; + +ActorInfo chMutieSnippet = { + MARKER_13_SNIPPET, ACTOR_F5_MUTIE_SNIPPET, ASSET_38F_MODEL_MUTIE_SNIPPET, + 0x1, chCrabMutantAnimations, + chCrab_update, actor_update_func_80326224, actor_draw, + 1900, 0, 0.8f, 0 +}; \ No newline at end of file diff --git a/src/core2/ch/extralife.c b/src/core2/ch/extralife.c index d0f8a2936..484842ec8 100644 --- a/src/core2/ch/extralife.c +++ b/src/core2/ch/extralife.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_41F30.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ch/feather.c b/src/core2/ch/feather.c index 363b00296..f4cd8ff77 100644 --- a/src/core2/ch/feather.c +++ b/src/core2/ch/feather.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_43800.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/ch/gameSelect.h b/src/core2/ch/gameSelect.h new file mode 100644 index 000000000..a7a3ec955 --- /dev/null +++ b/src/core2/ch/gameSelect.h @@ -0,0 +1,14 @@ +// BanjoDecomp: core2/ch/gameSelect.h +#ifndef BANJO_KAZOOIE_CH_GAMESELECT_H +#define BANJO_KAZOOIE_CH_GAMESELECT_H + +typedef enum { + GAME_SELECT_INITIALIZE = 1, + GAME_SELECT_IDLE = 2, + GAME_SELECT_STARTING = 3, + GAME_SELECT_STARTING_SILLY = 4, + GAME_SELECT_ERASE_CONFIRMATION = 5, + GAME_SELECT_DONE = 6 +} GameSelectState; + +#endif // BANJO_KAZOOIE_CH_GAMESELECT_H diff --git a/src/core2/ch/ghost.c b/src/core2/ch/ghost.c index 98c80714e..16dd4500f 100644 --- a/src/core2/ch/ghost.c +++ b/src/core2/ch/ghost.c @@ -9,11 +9,11 @@ typedef struct { f32 unk4; } ActorLocal_Core2_D4050; -void func_8035B900(Actor *this); -void func_8035BD48(Actor *this); +void chTeehee_update(Actor *this); +void chPurpleTeehee_update(Actor *this); /* .data */ -ActorAnimationInfo D_80372BE0[] ={ +ActorAnimationInfo chTeeheeAnimations[] ={ {0x00, 0.0f}, {ASSET_9E_ANIM_TEEHEE_IDLE, 2.0f}, {ASSET_9F_ANIM_TEEHEE_ALERTED, 1.5f}, @@ -23,17 +23,17 @@ ActorAnimationInfo D_80372BE0[] ={ {ASSET_2AB_ANIM_TEEHEE_DIE, 1.0f} }; -ActorInfo D_80372C18 = { //TEEHEE +ActorInfo chTeeHee = { //TEEHEE MARKER_99_TEEHEE, ACTOR_CA_TEEHEE, ASSET_3CB_MODEL_TEEHEE, - 0x1, D_80372BE0, - func_8035B900, actor_update_func_80326224, actor_draw, + 0x1, chTeeheeAnimations, + chTeehee_update, actor_update_func_80326224, actor_draw, 6500, 0, 0.9f, 0 }; -ActorInfo D_80372C3C = { //PURPLE_TEEHEE (inside tumblar) +ActorInfo chPurpleTeeHee = { //PURPLE_TEEHEE (inside tumblar) MARKER_296_TEEHEE_PURPLE, ACTOR_3C1_PURPLE_TEEHEE, ASSET_564_MODEL_PURPLE_TEEHEE, - 0x1, D_80372BE0, - func_8035B900, func_8035BD48, actor_draw, + 0x1, chTeeheeAnimations, + chTeehee_update, chPurpleTeehee_update, actor_draw, 6500, 0, 0.9f, 0 }; @@ -41,27 +41,48 @@ s32 D_80372C60[3] = {0x46, 0xFE, 0x46}; s32 D_80372C6C[3] = {0xFE, 0x46, 0xFE}; +enum chteehee_state_e { + CH_TEEHEE_STATE_0_NOT_INIT, + CH_TEEHEE_STATE_1_IDLE, + CH_TEEHEE_STATE_2_ALERT, + CH_TEEHEE_STATE_3_CHASE, + CH_TEEHEE_STATE_4_UNK, + CH_TEEHEE_STATE_5_UNK, + CH_TEEHEE_STATE_6_DIE +}; + +enum chpurpleteehee_state_e { + CH_PURPLE_TEEHEE_STATE_0_NOT_INIT, + CH_PURPLE_TEEHEE_STATE_1_UNK, + CH_PURPLE_TEEHEE_STATE_2_UNUSED, + CH_PURPLE_TEEHEE_STATE_3_ROAMING, + CH_PURPLE_TEEHEE_STATE_4_UNUSED, + CH_PURPLE_TEEHEE_STATE_5_UNUSED, + CH_PURPLE_TEEHEE_STATE_6_DIE +}; + /* .code */ -void func_8035AFE0(f32 scale, f32 pos[3], s32 cnt, enum asset_e sprite_id, s32 arg4[3]){ +void chTeehee_emitDust(f32 scale, f32 pos[3], s32 cnt, enum asset_e sprite_id, s32 arg4[3]) +{ ParticleEmitter *pCtrl = partEmitMgr_newEmitter(cnt); particleEmitter_setSprite(pCtrl, sprite_id); particleEmitter_setRGB(pCtrl, arg4); particleEmitter_setPosition(pCtrl, pos); particleEmitter_setSpawnPositionRange(pCtrl, - -100.0f*scale, 20.0f*scale, -100.0f*scale, - 100.0f*scale, 200.0f*scale, 100.0f*scale + -100.0f * scale, 20.0f * scale, -100.0f * scale, + 100.0f * scale, 200.0f * scale, 100.0f * scale ); particleEmitter_setAccelerationRange(pCtrl, - 0.0f, -10.0f*scale, 0.0f, - 0.0f, -10.0f*scale, 0.0f + 0.0f, -10.0f * scale, 0.0f, + 0.0f, -10.0f * scale, 0.0f ); particleEmitter_setParticleVelocityRange(pCtrl, - -100.0f*scale, -20.0f*scale, -100.0f*scale, - 100.0f*scale, 100.0f*scale, 100.0f*scale + -100.0f * scale, -20.0f * scale, -100.0f * scale, + 100.0f * scale, 100.0f * scale, 100.0f * scale ); - particleEmitter_setStartingScaleRange(pCtrl, scale*0.4, scale*0.6); - particleEmitter_setFinalScaleRange(pCtrl, scale*1.0, scale*1.4); + particleEmitter_setStartingScaleRange(pCtrl, scale * 0.4, scale * 0.6); + particleEmitter_setFinalScaleRange(pCtrl, scale * 1.0, scale * 1.4); particleEmitter_setSpawnIntervalRange(pCtrl, 0.0f, 0.01f); particleEmitter_setParticleLifeTimeRange(pCtrl, 1.0f, 1.4f); particleEmitter_setFade(pCtrl, 0.0f, 0.01f); @@ -69,49 +90,54 @@ void func_8035AFE0(f32 scale, f32 pos[3], s32 cnt, enum asset_e sprite_id, s32 a particleEmitter_emitN(pCtrl, cnt); } -void func_8035B1CC(ActorMarker *this_marker, ActorMarker *other_marker){ +void chTeehee_die(ActorMarker *this_marker, ActorMarker *other_marker) +{ Actor *this = marker_getActor(this_marker); - f32 sp30; + f32 scale; - sp30 = this->scale; - func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); - func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); - subaddie_set_state_with_direction(this, 6, 0.01f, 1); + scale = this->scale; + func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + subaddie_set_state_with_direction(this, CH_TEEHEE_STATE_6_DIE, 0.01f, 1); actor_playAnimationOnce(this); actor_collisionOff(this); func_80326310(this); - func_8035AFE0(sp30, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C60); + chTeehee_emitDust(scale, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C60); } -void func_8035B2C4(ActorMarker *this_marker, ActorMarker *other_marker){ +void chTeeheePurple_die(ActorMarker *this_marker, ActorMarker *other_marker) +{ Actor *this = marker_getActor(this_marker); - f32 sp30 = this->scale; - func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); - func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); - subaddie_set_state_with_direction(this, 6, 0.01f, 1); + f32 scale = this->scale; + func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_6_DIE, 0.01f, 1); actor_playAnimationOnce(this); actor_collisionOff(this); - func_8035AFE0(sp30, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C6C); + chTeehee_emitDust(scale, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C6C); } -void func_8035B3B4(ActorMarker *this_marker, ActorMarker *other_marker){ +void chTeehee_hitPlayer(ActorMarker *this_marker, ActorMarker *other_marker) +{ Actor *this = marker_getActor(this_marker); this->lifetime_value = 1.0f; } -int func_8035B3E4(Actor *this){ - if(subaddie_playerIsWithinSphereAndActive(this, (s32)(this->scale*600.0f)) && func_803292E0(this)) - return 1; - return 0; +bool func_8035B3E4(Actor *this) +{ + if(subaddie_playerIsWithinSphereAndActive(this, (s32)(this->scale * 600.0f)) && func_803292E0(this)) + return true; + return false; } -int func_8035B444(Actor *this, f32 arg1){ +bool func_8035B444(Actor *this, f32 arg1) +{ int out; - subaddie_turnToYaw(this, arg1); + subaddie_turnToYaw(this, arg1); if(!func_80329054(this, 2) && func_80329480(this)) - return 0; - return 1; + return false; + return true; } void func_8035B49C(Actor *this){ @@ -127,16 +153,16 @@ void func_8035B49C(Actor *this){ } void func_8035B56C(Actor *this){ - f32 sp2C; + f32 scale_doubled; f32 plyr_pos[3]; - sp2C = 2*(f64)this->scale; + scale_doubled = 2 * (f64)this->scale; player_getPosition(plyr_pos); if(this->position_y < plyr_pos[1]){ - if(this->position_y + sp2C < plyr_pos[1]){ - this->position_y = this->position_y + sp2C; - this->velocity_x += sp2C; + if(this->position_y + scale_doubled < plyr_pos[1]){ + this->position_y = this->position_y + scale_doubled; + this->velocity_x += scale_doubled; } else{ this->velocity_x += plyr_pos[1] - this->position_y; @@ -144,9 +170,9 @@ void func_8035B56C(Actor *this){ } } else if(plyr_pos[1] < this->position_y){ - if(plyr_pos[1] < this->position_y - sp2C){ - this->position_y = this->position_y - sp2C; - this->velocity_x -= sp2C; + if(plyr_pos[1] < this->position_y - scale_doubled){ + this->position_y = this->position_y - scale_doubled; + this->velocity_x -= scale_doubled; } else{ this->velocity_x -= (this->position_y - plyr_pos[1]); @@ -170,14 +196,14 @@ void func_8035B6CC(Actor *this){ subaddie_set_state_with_direction(this, 2, 0.01f, 1); actor_playAnimationOnce(this); this->actor_specific_1_f = 1.0f; - func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); } void func_8035B75C(Actor *this){ subaddie_set_state_with_direction(this, 3, 0.01f, 1); actor_loopAnimation(this); this->actor_specific_1_f = volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE) ? 0.0 : 12.0; - func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); } void func_8035B824(Actor *this){ @@ -196,78 +222,78 @@ void func_8035B8A8(Actor *this){ func_80328CEC(this, (s32)this->yaw_ideal, 0xE1, 0x87); } -void func_8035B900(Actor *this){ +void chTeehee_update(Actor *this){ ActorLocal_Core2_D4050 *local = (ActorLocal_Core2_D4050 *)&this->local; - s32 sp30 = globalTimer_getTime(); - f32 sp2C = time_getDelta(); + s32 global_time = globalTimer_getTime(); + f32 time_delta = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = true; - marker_setCollisionScripts(this->marker, NULL, func_8035B3B4, func_8035B1CC); + marker_setCollisionScripts(this->marker, NULL, chTeehee_hitPlayer, chTeehee_die); this->marker->propPtr->unk8_3 = false; actor_collisionOn(this); this->velocity_z = 0.0f; this->lifetime_value = 0.0f; - this->unk1C[0] = this->position_y + this->scale*100.0f; - this->velocity_y = this->scale*2.0; + this->unk1C[0] = this->position_y + this->scale * 100.0f; + this->velocity_y = this->scale * 2.0; this->velocity_x = this->unk1C[0]; local->unk0 = randf2(1.0f, 4.5f); anctrl_setTransitionDuration(this->anctrl, 0.8f); }//L8035B9D4 - if(0.0 < this->lifetime_value - sp2C){ - this->lifetime_value -= sp2C; + if(0.0 < this->lifetime_value - time_delta){ + this->lifetime_value -= time_delta; } else{//L8035BA08 switch(this->state){ - case 1: //L8035BA30 + case CH_TEEHEE_STATE_1_IDLE: //L8035BA30 func_8035B49C(this); if(func_8035B3E4(this)){ func_8035B6CC(this); } - else if(0.0 < local->unk0 - sp2C){ - local->unk0 = local->unk0 - sp2C; + else if(0.0 < local->unk0 - time_delta){ + local->unk0 = local->unk0 - time_delta; } else{ func_8035B824(this); } break; - case 2: //L8035BA98 + case CH_TEEHEE_STATE_2_ALERT: //L8035BA98 this->yaw_ideal = subaddie_getYawToPlayer(this); func_8035B444(this, 4.0f); if(actor_animationIsAt(this, 0.99f)){ func_8035B75C(this); } break; - case 3: //L8035BAE0 + case CH_TEEHEE_STATE_3_CHASE: //L8035BAE0 func_8035B56C(this); - if((sp30 & 0x3F) == 7 && randf() < 0.7){ - func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + if((global_time & 0x3F) == 7 && randf() < 0.7){ + func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); }//L8035BB6C this->yaw_ideal = subaddie_getYawToPlayer(this); if(!func_8035B3E4(this) || !func_8035B444(this, 5.0f)){ func_8035B674(this); } break; - case 4: //L8035BBB0 + case CH_TEEHEE_STATE_4_UNK: //L8035BBB0 func_8035B49C(this); if(!func_8035B444(this, 2.0f)){ func_8035B8A8(this); } - else if(local->unk4 - sp2C <= 0.0){ + else if(local->unk4 - time_delta <= 0.0){ func_8035B674(this); } else{ - local->unk4 = local->unk4 - sp2C; + local->unk4 = local->unk4 - time_delta; } break; - case 5: //L8035BC1C + case CH_TEEHEE_STATE_5_UNK: //L8035BC1C func_8035B49C(this); subaddie_turnToYaw(this, 3.0f); if(func_80329480(this)){ func_8035B674(this); } break; - case 6: //L8035BC48 + case CH_TEEHEE_STATE_6_DIE: //L8035BC48 break; } }//L8035BC48 @@ -297,12 +323,12 @@ int func_8035BC5C(Actor *this, s32 target, s32 delta){ return done; } -void func_8035BD48(Actor *this){ +void chPurpleTeehee_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; this->marker->propPtr->unk8_3 = false; actor_collisionOn(this); - marker_setCollisionScripts(this->marker, NULL, func_8035B3B4, func_8035B2C4); + marker_setCollisionScripts(this->marker, NULL, chTeehee_hitPlayer, chTeeheePurple_die); mapSpecificFlags_set(3, false); mapSpecificFlags_set(4, false); if(gsworld_getMap() == MAP_24_MMM_TUMBLARS_SHED){ @@ -312,32 +338,32 @@ void func_8035BD48(Actor *this){ marker_despawn(this->marker); } else{//L8035BE04 - subaddie_set_state_with_direction(this, 1, 0.01f, 1); + subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_1_UNK, 0.01f, 1); actor_setOpacity(this, 0); } } else{//L8035BE2C - subaddie_set_state_with_direction(this, 3, 0.01f, 1); + subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_3_ROAMING, 0.01f, 1); actor_setOpacity(this, 0xff); } }//L8035BE50 switch(this->state){ - case 1: //L8035BE78 + case CH_PURPLE_TEEHEE_STATE_1_UNK: //L8035BE78 actor_collisionOff(this); if(mapSpecificFlags_getClear(4)){ marker_despawn(this->marker); } else if(mapSpecificFlags_getClear(3)){ - subaddie_set_state_with_direction(this, 3, 0.01f, 1); + subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_3_ROAMING, 0.01f, 1); } break; - case 3: //L8035BECC + case CH_PURPLE_TEEHEE_STATE_3_ROAMING: //L8035BECC this->unk58_0 = true; actor_collisionOn(this); if(mapSpecificFlags_getClear(4)){ this->unk38_0 = true; - func_8035B2C4(this->marker, NULL); + chTeeheePurple_die(this->marker, NULL); } else{//L8035BF14 if(this->alpha_124_19 == 0xFF || func_8035BC5C(this, 0xff, 0xA)){ @@ -345,11 +371,11 @@ void func_8035BD48(Actor *this){ } if((globalTimer_getTime() &0x3F) == 7 && randf() < 0.7){ - func_8030E878(0x3f4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + func_8030E878(0x3f4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); } } break; - case 6: //L8035BFD4 + case CH_PURPLE_TEEHEE_STATE_6_DIE: //L8035BFD4 if(func_8035BC5C(this, 0, -7)){ this->unk58_0 = false; this->unk48 = 0.0f; @@ -358,7 +384,7 @@ void func_8035BD48(Actor *this){ marker_despawn(this->marker); } else{ - subaddie_set_state_with_direction(this, 1, 0.01f, 1); + subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_1_UNK, 0.01f, 1); timedFunc_set_2(randf2(5.0f, 10.0f), (GenFunction_2)mapSpecificFlags_set, 3, true); } } diff --git a/src/core2/ch/gloop.c b/src/core2/ch/gloop.c index 6a71d5c7d..2fee4d88e 100644 --- a/src/core2/ch/gloop.c +++ b/src/core2/ch/gloop.c @@ -60,7 +60,7 @@ void chgloop_update(Actor *this){ if( !mapSpecificFlags_get(2) && subaddie_playerIsWithinSphereAndActive(this, 350) - && gcdialog_showDialog(ASSET_D34_DIALOG_GLOOP_MEET, 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(VER_SELECT(ASSET_D34_DIALOG_GLOOP_MEET, 0xA07, 0, 0), 0, NULL, NULL, NULL, NULL) ){ mapSpecificFlags_set(2, true); } diff --git a/src/core2/ch/goldfeather.c b/src/core2/ch/goldfeather.c index ff39d1ff0..bc45e3e15 100644 --- a/src/core2/ch/goldfeather.c +++ b/src/core2/ch/goldfeather.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_51950.c #include #include "functions.h" #include "variables.h" @@ -7,14 +8,14 @@ extern f32 player_getYaw(void); void func_802D88E0(Actor *this); /* .data */ -ActorInfo D_80367C90 = { +ActorInfo fxSpentRedFeather = { 0x100, 0x1FF, 0x580, 0x0, NULL, func_802D88E0, actor_update_func_80326224, fxTouchSparkle_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80367CB4 = { +ActorInfo fxSpentGoldFeather = { 0x101, 0x200, 0x6D1, 0x0, NULL, func_802D88E0, actor_update_func_80326224, fxTouchSparkle_draw, diff --git a/src/core2/ch/gravestone.c b/src/core2/ch/gravestone.c index 97cf86660..4a17efff6 100644 --- a/src/core2/ch/gravestone.c +++ b/src/core2/ch/gravestone.c @@ -47,8 +47,8 @@ Actor *chgravestone_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { this = marker_getActorAndRotation(marker, rotation); local = (ActorLocal_core2_D7D10 *)&this->local; - func_8033A45C(3, (s32) this->velocity[1]); - func_8033A45C(4, local->unk0); + modelRender_setAppendageVisibility(3, (s32) this->velocity[1]); + modelRender_setAppendageVisibility(4, local->unk0); modelRender_setPreDrawCallback( (model_render_pre_draw_callback_f)actor_predrawMethod, (void *)this); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); modelRender_draw(gfx, mtx, this->position, rotation, this->scale, D_80373008, func_803257B4(marker)); diff --git a/src/core2/ch/grill_chompa.c b/src/core2/ch/grillechompa.c similarity index 97% rename from src/core2/ch/grill_chompa.c rename to src/core2/ch/grillechompa.c index cbb060d68..a6a74f62c 100644 --- a/src/core2/ch/grill_chompa.c +++ b/src/core2/ch/grillechompa.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/grillechompa.c #include #include "functions.h" #include "variables.h" @@ -72,7 +73,7 @@ Actor *chGrilleChompa_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) return actor; } else{ - func_8033A45C(3, (actor->state == 1 || actor->state == 6)? 0:1); + modelRender_setAppendageVisibility(3, (actor->state == 1 || actor->state == 6)? 0:1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/core2/ch/honeycomb.c b/src/core2/ch/honeycomb.c index fbdf64f24..dcf803337 100644 --- a/src/core2/ch/honeycomb.c +++ b/src/core2/ch/honeycomb.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_42CB0.c #include #include "functions.h" #include "variables.h" @@ -11,13 +12,15 @@ typedef struct{ void chHoneycomb_update(Actor *this); /* .data */ -ActorInfo D_80366C80 = { MARKER_53_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, ASSET_361_MODEL_EMPTY_HONEYCOMB, +ActorInfo chEmptyHoneycomb = { + MARKER_53_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, ASSET_361_MODEL_EMPTY_HONEYCOMB, 0, NULL, chHoneycomb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.8f, 0 }; -ActorInfo D_80366CA4 = { MARKER_55_HONEYCOMB, ACTOR_50_HONEYCOMB, ASSET_363_MODEL_HONEYCOMB, +ActorInfo chHoneycomb = { + MARKER_55_HONEYCOMB, ACTOR_50_HONEYCOMB, ASSET_363_MODEL_HONEYCOMB, 0, NULL, chHoneycomb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.8f, 0 @@ -165,3 +168,19 @@ enum honeycomb_e func_802CA1C4(Actor *this){ void func_802CA1CC(enum honeycomb_e id){ D_8037DDC0 = id; } + +// [port] Anchor: spawn a teammate's dropped empty honeycomb locally. Spawned through the +// same per-map bundle as the local drop so it gets the pickup drop physics. +static void __chHoneycomb_netSpawnDrop(uintptr_t uid, uintptr_t bundle, uintptr_t x, uintptr_t y, uintptr_t z){ + f32 pos[3]; + pos[0] = reinterpret_cast(f32, x); + pos[1] = reinterpret_cast(f32, y); + pos[2] = reinterpret_cast(f32, z); + func_802CA1CC((enum honeycomb_e)uid); + bundle_spawn_f32((enum bundle_e)bundle, pos); +} + +void chHoneycomb_netSpawnDropAt(s32 uid, s32 bundleId, f32 x, f32 y, f32 z){ + __spawnQueue_add_5((GenFunction_5)__chHoneycomb_netSpawnDrop, (uintptr_t)uid, (uintptr_t)bundleId, + reinterpret_cast(s32, x), reinterpret_cast(s32, y), reinterpret_cast(s32, z)); +} diff --git a/src/core2/ch/icecube.c b/src/core2/ch/icecube.c index 2582264c4..231756902 100644 --- a/src/core2/ch/icecube.c +++ b/src/core2/ch/icecube.c @@ -39,7 +39,7 @@ s32 D_80372BD4[3] = {200, 200, 255}; /*.code */ Actor *chicecube_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *actor = marker_getActor(marker); - func_8033A45C(3, actor->unk38_31); + modelRender_setAppendageVisibility(3, actor->unk38_31); actor = actor_draw(marker, gfx, mtx, vtx); return actor; } diff --git a/src/core2/ch/jiggy.c b/src/core2/ch/jiggy.c index fed32dbd7..02cb2178a 100644 --- a/src/core2/ch/jiggy.c +++ b/src/core2/ch/jiggy.c @@ -1,31 +1,21 @@ +// BanjoDecomp: core2/ch/jiggy.c #include #include "functions.h" #include "variables.h" #include "enums.h" +#include "jiggy.h" +#include "core2/commonParticle.h" +#include "port/Enhancements/Events/Hooks/Events.h" extern void func_802BE720(void); -extern f32 modelRender_func_8033A244(f32); -extern void modelRender_func_8033A280(f32); - -typedef struct chjiggy_s{ - u32 unk0; - u32 index; -} ActorLocal_Jiggy; - -Actor *spawnQueue_actor_s32(f32, f32, f32); -void spawnJiggyDestroyedEffects(u32 x, u32 y, u32 z, u32 arg3); -Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chjiggy_update_2(Actor * arg0); -void chjiggy_update(Actor *this); -enum jiggy_e chjiggy_getJiggyId(Actor *this); - +extern void modelRender_func_8033A280(f32); /* .data */ ActorAnimationInfo JIGGY_ANIMATIONS[] = { - {0, 0.0f}, - {0, 0.0f}, - {0, 0.0f} + { 0, 0.0f }, + { 0, 0.0f }, + { 0, 0.0f } }; ActorInfo chJiggy = { @@ -36,119 +26,137 @@ ActorInfo chJiggy = { }; /* .code */ -enum jiggy_e getJiggyId(Actor *this){ +enum jiggy_e getJiggyId(Actor *this) { s32 id; - s32 sp18[3]; + s32 position[3]; id = gsworld_getMap(); - sp18[0] = (s32)this->position[0]; - sp18[1] = (s32)this->position[1]; - sp18[2] = (s32)this->position[2]; - id = func_80307164(sp18); - if( id < 0){ + position[0] = (s32)this->position[0]; + position[1] = (s32)this->position[1]; + position[2] = (s32)this->position[2]; + + id = func_80307164(position); + + if (id < 0) { return 0; } - else{ - return func_80306DBC(id) + 1; - } + + return func_80306DBC(id) + 1; } -void playJiggyDestroyedSoundsAndReset(ActorMarker * arg0, u32 arg1){ +void playJiggyDestroyedSoundsAndReset(ActorMarker *marker, u32 resetSwitchFlag) { func_8030E6D4(SFX_30_MAGIC_POOF); coMusicPlayer_playMusic(COMUSIC_3C_MINIGAME_LOSS, 0x7FF8); - mapSpecificFlags_set(arg1, 1); - marker_despawn(arg0); + mapSpecificFlags_set(resetSwitchFlag, TRUE); + marker_despawn(marker); } -void spawnJiggyDestroyedEffects(u32 x, u32 y, u32 z, u32 arg3){ +void spawnJiggyDestroyedEffects(u32 x, u32 y, u32 z, u32 resetSwitchFlag) { __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_s32, ACTOR_4C_STEAM, x, y, z); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_s32, ACTOR_14F_DESTROYED_JIGGY, x, y, z); - mapSpecificFlags_set(arg3, 1); + mapSpecificFlags_set(resetSwitchFlag, TRUE); } -void resetFlag(u32 arg0){ - mapSpecificFlags_set(arg0, 0); +void resetFlag(enum bgs_specific_flags flag) { + mapSpecificFlags_set(flag, FALSE); } -void destroyJiggy(Actor *this, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, enum volatile_flags_e arg6){ - if( !mapSpecificFlags_get(arg1) - && mapSpecificFlags_get(arg2) - && item_getCount(ITEM_0_HOURGLASS_TIMER) == 0 - ){ - player_setModelVisible(1); - actor_collisionOff(this); - gcStaticCamera_activate(arg3); - volatileFlag_setAndTriggerDialog_0(arg6); - timedFunc_set_4(0.6f, (GenFunction_4)spawnJiggyDestroyedEffects, (s32)this->position[0], (s32)this->position[1], (s32)this->position[2], arg4); - timedFunc_set_2(0.6f, (GenFunction_2)playJiggyDestroyedSoundsAndReset, (uintptr_t)this->marker, arg5); - timedFunc_set_0(1.0f, (GenFunction_0)func_802BE720); - timedFunc_set_1(3.9f, (GenFunction_1)resetFlag, arg4); - mapSpecificFlags_set(arg1, 1); +void destroyJiggy(Actor *this, s32 jiggyFlag, s32 timerRunningFlag, s32 cameraId, s32 switchPressedFlag, s32 resetSwitchFlag, enum volatile_flags_e dialogFlag) { + + // Jiggy is still active + if (mapSpecificFlags_get(jiggyFlag) + || !mapSpecificFlags_get(timerRunningFlag) + || item_getCount(ITEM_0_HOURGLASS_TIMER) != 0) { + + return; } + + CALL_EVENT(OnTimedJiggyExpired, (s32)chjiggy_getJiggyId(this)); + player_setModelVisible(1); + actor_collisionOff(this); + + // Switch camera to a static one showing the newly destroyed jiggy + gcStaticCamera_activate(cameraId); + + progressDialog_setAndTriggerDialog_0(dialogFlag); + timedFunc_set_4(0.6f, (GenFunction_4)spawnJiggyDestroyedEffects, (s32)this->position[0], (s32)this->position[1], (s32)this->position[2], switchPressedFlag); + timedFunc_set_2(0.6f, (GenFunction_2)playJiggyDestroyedSoundsAndReset, reinterpret_cast(uintptr_t, this->marker), resetSwitchFlag); + timedFunc_set_0(1.0f, (GenFunction_0)func_802BE720); + timedFunc_set_1(3.9f, (GenFunction_1)resetFlag, switchPressedFlag); + mapSpecificFlags_set(jiggyFlag, TRUE); } -void chjiggy_updateRotation(Actor *this){ +void chjiggy_updateRotation(Actor *this) { f32 delta = time_getDelta(); + + // Controls the rotation speed this->yaw += delta * 230.0f; - if(360.0f <= this->yaw){ + + if (360.0f <= this->yaw) { this->yaw -= 360.0f; } + this->yaw_ideal = this->yaw; } -//chjiggy_draw -Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3){ - Actor * thisActor = marker_getActor(this); - ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&thisActor->local; +Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **vtx) { + Actor *jiggy_actor = marker_getActor(this); + ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&jiggy_actor->local; u32 jiggyId; - if(!local->unk0){ - jiggyId = chjiggy_getJiggyId(thisActor); - if((jiggyId == JIGGY_1C_CC_RINGS) || (jiggyId == JIGGY_1D_CC_SLOW_SAWBLADES)){ + if (!local->isHidden) { + jiggyId = chjiggy_getJiggyId(jiggy_actor); + + if ((jiggyId == JIGGY_1C_CC_RINGS) || (jiggyId == JIGGY_1D_CC_SLOW_SAWBLADES)) { modelRender_func_8033A280(10.0f); modelRender_func_8033A244(30000.0f); } - thisActor = actor_draw(this, gdl, mptr, arg3); + + jiggy_actor = actor_draw(this, gdl, mptr, vtx); } - return thisActor; + + return jiggy_actor; } -void chjiggy_update_2(Actor * arg0){ - func_80343DEC(arg0); - chjiggy_updateRotation(arg0); +void chjiggy_update_2(Actor *this) { + func_80343DEC(this); + chjiggy_updateRotation(this); } -//chjiggy_update -void chjiggy_update(Actor *this){ +void chjiggy_update(Actor *this) { ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; int i; - if(this->marker->unk14_21){ - for(i = 0; i < 4; i++){ - if(randf() < 0.015){ + // A small chance to show a jiggy shine effect. Up to four can be shown at once. + if (this->marker->unk14_21) { + for (i = 0; i < 4; i++) { + if (randf() < 0.015) { commonParticle_add(this->marker, i + 5, func_80329904); - commonParticle_new(8, 1); + commonParticle_new(COMMON_PARTICLE_8_JIGGY_SHINE, 1); } } - }//L802C7E44 - switch(this->state){ - case 1: //L802C7E68 - local->unk0 = 0; - if(local->index == 0) - local->index = getJiggyId(this); + } + + switch (this->state) { + case JIGGY_STATE_1_INIT: + local->isHidden = FALSE; + + if (local->id == 0) { + local->id = getJiggyId(this); + } - if(jiggyscore_isCollected(local->index)){ + if (jiggyscore_isCollected(local->id)) { marker_despawn(this->marker); - } - else{ - subaddie_set_state(this, 2); - switch(chjiggy_getJiggyId(this)){ - case JIGGY_17_CC_CLANKER_RAISED: //L802C7EF8 - case JIGGY_49_CCW_EYRIE:// L802C7EF8 + } else { + subaddie_set_state(this, JIGGY_STATE_2_IDLE); + switch (chjiggy_getJiggyId(this)) { + case JIGGY_17_CC_CLANKER_RAISED: + case JIGGY_49_CCW_EYRIE: this->marker->unk40_21 = 1; break; - case JIGGY_36_LAIR_TTC_WITCH_SWITCH:// L802C7F0C + + case JIGGY_36_LAIR_TTC_WITCH_SWITCH: this->unk44_14 = func_80341F2C(0x20A); this->unk48 = 0.0f; this->unk4C = 300.0f; @@ -157,53 +165,63 @@ void chjiggy_update(Actor *this){ func_80343DEC(this); chjiggy_updateRotation(this); break; - case JIGGY_3E_GV_GRABBA:// L802C7F6C - case JIGGY_4D_CCW_FLOWER:// L802C7F6C + + case JIGGY_3E_GV_GRABBA: + case JIGGY_4D_CCW_FLOWER: this->unk124_6 = 0; break; - case JIGGY_41_GV_MAZE:// L802C7F7C + + case JIGGY_41_GV_MAZE: this->marker->unk14_10 = 30; break; - case JIGGY_13_TTC_LOCKUP: //L802C7F94 + + case JIGGY_13_TTC_LOCKUP: this->marker->unk14_10 = 40; break; } } + break; - case 2: //L802C7FAC + + case JIGGY_STATE_2_IDLE: chjiggy_updateRotation(this); - switch(chjiggy_getJiggyId(this)){ - case JIGGY_20_BGS_ELEVATED_WALKWAY: //L802C7FE8 - destroyJiggy(this, 4, 3, 0xD, 5, 2, VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED); + + switch (chjiggy_getJiggyId(this)) { + case JIGGY_20_BGS_ELEVATED_WALKWAY: + destroyJiggy(this, BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY, BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING, STATIC_CAMERA_D_WALKWAY_JIGGY_DESTROY, + BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED, BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET, VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED); break; - case JIGGY_25_BGS_MAZE://L802C8018 - destroyJiggy(this, 0xd, 0xc, 0x1e, 9, 0xb, VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED); + + case JIGGY_25_BGS_MAZE: + destroyJiggy(this, BGS_SPECIFIC_FLAG_D_MAZE_JIGGY, BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING, STATIC_CAMERA_1E_MAZE_JIGGY_DESTROY, + BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED, BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET, VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED); break; - case JIGGY_2F_FP_XMAS_TREE://L802C8048 + + case JIGGY_2F_FP_XMAS_TREE: if (levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { actor_collisionOn(this); - } - else { + } else { actor_collisionOff(this); } break; } + break; - }//L802C8074 + } } -enum jiggy_e chjiggy_getJiggyId(Actor *this){ +enum jiggy_e chjiggy_getJiggyId(Actor *this) { ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; - return local->index; + return local->id; } -void chjiggy_hide(Actor * this){ +void chjiggy_hide(Actor *this) { ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; - local->unk0 = 1; + local->isHidden = TRUE; actor_collisionOff(this); } -void chjiggy_setJiggyId(Actor *this, u32 id){ +void chjiggy_setJiggyId(Actor *this, u32 id) { ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; - local->index = id; + local->id = id; } diff --git a/src/core2/ch/jiggy.h b/src/core2/ch/jiggy.h new file mode 100644 index 000000000..b66c45a28 --- /dev/null +++ b/src/core2/ch/jiggy.h @@ -0,0 +1,20 @@ +// BanjoDecomp: core2/ch/jiggy.h +#ifndef BANJO_KAZOOIE_CH_JIGGY_H +#define BANJO_KAZOOIE_CH_JIGGY_H + +typedef struct chjiggy_s { + bool isHidden; + u32 id; +} ActorLocal_Jiggy; + +Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chjiggy_update_2(Actor * arg0); +void chjiggy_update(Actor *this); +enum jiggy_e chjiggy_getJiggyId(Actor *this); + +enum jiggy_state_e { + JIGGY_STATE_1_INIT = 1, + JIGGY_STATE_2_IDLE = 2 +}; + +#endif // BANJO_KAZOOIE_CH_JIGGY_H diff --git a/src/core2/ch/jinjo.c b/src/core2/ch/jinjo.c index 45533fbff..09d57b993 100644 --- a/src/core2/ch/jinjo.c +++ b/src/core2/ch/jinjo.c @@ -1,6 +1,7 @@ #include #include "functions.h" #include "variables.h" +#include "port/Enhancements/Retention/Retention.h" extern void subaddie_set_state_with_direction(Actor *, s32, f32 , s32); extern f32 func_80309B24(f32*); @@ -28,30 +29,49 @@ ActorInfo chJinjoYellow = { MARKER_5E_JINJO_YELLOW, ACTOR_5E_JINJO_YELLOW, ASSET ActorInfo chJinjoPink = { MARKER_5D_JINJO_PINK, ACTOR_61_JINJO_PINK, ASSET_3C1_MODEL_JINJO_PINK, 0x1, chJinjoAnimations, chJinjo_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; ActorInfo chJinjoOrange = { MARKER_5C_JINJO_ORANGE, ACTOR_5F_JINJO_ORANGE, ASSET_3BC_MODEL_JINJO_ORANGE, 0x1, chJinjoAnimations, chJinjo_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +enum chjinjo_state_e { + CH_JINJO_STATE_0_NOT_INIT, + CH_JINJO_STATE_1_IDLE, + CH_JINJO_STATE_2_ONE_HAND_WAVE, + CH_JINJO_STATE_3_TWO_HAND_WAVE, + CH_JINJO_STATE_4_JUMPING_WAVE, + CH_JINJO_STATE_5_UNK, + CH_JINJO_STATE_6_COLLECTED, + CH_JINJO_STATE_7_FLY_START, + CH_JINJO_STATE_8_FLY_END, + CH_JINJO_STATE_9_UNK +}; + +/*.code */ enum asset_e __chJinjo_getMeetDialogId(enum marker_e marker_id){ switch(marker_id){ - case MARKER_5A_JINJO_BLUE: return ASSET_D98_DIALOG_JINJO_MEET_BLUE; - case MARKER_5B_JINJO_GREEN: return ASSET_D99_DIALOG_JINJO_MEET_GREEN; - case MARKER_5C_JINJO_ORANGE: return ASSET_D9B_DIALOG_JINJO_MEET_ORANGE; - case MARKER_5D_JINJO_PINK: return ASSET_D9A_DIALOG_JINJO_MEET_PINK; - case MARKER_5E_JINJO_YELLOW: return ASSET_D97_DIALOG_JINJO_MEET_YELLOW; + case MARKER_5A_JINJO_BLUE: return VER_SELECT(ASSET_D98_DIALOG_JINJO_MEET_BLUE, 0x0A16, 0, 0); + case MARKER_5B_JINJO_GREEN: return VER_SELECT(ASSET_D99_DIALOG_JINJO_MEET_GREEN, 0x0A17, 0, 0); + case MARKER_5C_JINJO_ORANGE: return VER_SELECT(ASSET_D9B_DIALOG_JINJO_MEET_ORANGE, 0x0A19, 0, 0); + case MARKER_5D_JINJO_PINK: return VER_SELECT(ASSET_D9A_DIALOG_JINJO_MEET_PINK, 0x0A18, 0, 0); + case MARKER_5E_JINJO_YELLOW: return VER_SELECT(ASSET_D97_DIALOG_JINJO_MEET_YELLOW, 0x0A15, 0, 0); } return 0; } -void __chJinjo_802CDBA8(ActorMarker *this, ActorMarker *other){ +void __chJinjo_collected(ActorMarker *this, ActorMarker *other){ Actor *actorPtr = marker_getActor(this); ActorLocal_Jinjo *localPtr = &actorPtr->jinjo; - if(actorPtr->state < 5){ + if(actorPtr->state < CH_JINJO_STATE_5_UNK){ if(!fileProgressFlag_get(FILEPROG_E_JINJO_TEXT)){ gcdialog_showDialog(__chJinjo_getMeetDialogId(actorPtr->marker->id), 4, 0, 0, 0, 0); fileProgressFlag_set(FILEPROG_E_JINJO_TEXT, 1); } - subaddie_set_state_with_direction(actorPtr, 6, 0.0f , -1); + subaddie_set_state_with_direction(actorPtr, CH_JINJO_STATE_6_COLLECTED, 0.0f , -1); + /* + If multiple Jinjos of a color are collected, it overflows into the next Jinjo. + Example, two Green Jinjos -> Orange Jinjo collected & no Green Jinjo collected + */ if (!EventSystem_Should(VB_UPDATE_JINJO_HUD, false, actorPtr->position)) { if (item_adjustByDiffWithHud(ITEM_12_JINJOS, 1 << ((this->id + 6) & 0x1F)) == 0x1f) // [port] MIPS SLL uses low 5 bits; mask to avoid UB localPtr->unk4 = 1; + port_jinjoRetention_onLocalJinjoCollected(this->id); } actor_loopAnimation(actorPtr); this->collidable = false; @@ -62,7 +82,7 @@ void __chJinjo_802CDC9C(Actor *this, s16 arg1){ f32 tmpf; tmpf = this->yaw; - tmpf -= time_getDelta()*arg1/45.0; + tmpf -= time_getDelta() * arg1 / 45.0; if(tmpf >= 360.0f) tmpf -= 360.0f; @@ -72,7 +92,7 @@ void __chJinjo_802CDC9C(Actor *this, s16 arg1){ this->yaw = tmpf; } -void __chJinjo_802CDD3C(Actor * this){ +void __chJinjo_free(Actor * this){ ActorLocal_Jinjo *localPtr = &this->jinjo; if(localPtr->unkC != 0){ func_802F9D38(localPtr->unkC); @@ -82,21 +102,21 @@ void __chJinjo_802CDD3C(Actor * this){ void chJinjo_update(Actor * this){ f32 sp7C[3]; - f32 sp70[3]; + f32 player_velocity[3]; f32 sp6C; f32 sp68; //unused?? s16 sp66; s16 sp64; - s32 sp60; + s32 is_within_jinjos_vision; // f32 sp5C; ActorLocal_Jinjo *local; //= &this->jinjo; //sp34 - f32 sp58 = time_getDelta(); + f32 time_delta = time_getDelta(); s32 i; - int sp50; - f32 *sp30; + int is_flying_start; + f32 *this_position; //f32 sp4C; //unused - f32 sp40[3]; + f32 jiggy_position[3]; //s32 sp3C; //s32 sp38; @@ -109,50 +129,50 @@ void chJinjo_update(Actor * this){ local->unk0 = 1; local->unk4 = 0; local->unk8 = (this->position_y < func_80309B24(this->position)); - this->marker->collisionFunc = __chJinjo_802CDBA8; - marker_setFreeMethod(this->marker, __chJinjo_802CDD3C); + this->marker->collisionFunc = __chJinjo_collected; + marker_setFreeMethod(this->marker, __chJinjo_free); if(volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)){ marker_despawn(this->marker); } }//L802CDE24 - sp30 = this->position; + this_position = this->position; func_8028E964(sp7C); - func_80257F18(sp30, sp7C, &sp6C); + func_80257F18(this_position, sp7C, &sp6C); sp64 = (this->yaw * 182.04444); // sp66 = sp64 - (s32)(sp6C*182.04444); sp66 = (s32) (sp6C * 182.04444); sp66 = sp64 - sp66; - sp60 = func_8028AED4(sp30, 55.0f); + is_within_jinjos_vision = func_8028AED4(this_position, 55.0f); switch(this->state){ - case 1: + case CH_JINJO_STATE_1_IDLE: if(randf() < 0.015){ - if(sp60){ - subaddie_set_state_with_direction(this, 3, 0.0f, -1); + if(is_within_jinjos_vision){ + subaddie_set_state_with_direction(this, CH_JINJO_STATE_3_TWO_HAND_WAVE, 0.0f, -1); }else{ - subaddie_set_state_with_direction(this, 2, 0.0f, -1); + subaddie_set_state_with_direction(this, CH_JINJO_STATE_2_ONE_HAND_WAVE, 0.0f, -1); } actor_playAnimationOnce(this); }//L802CDF24 break; - case 2: /* 46FA0 802CDF30 3C053F7D */ - case 3: + case CH_JINJO_STATE_2_ONE_HAND_WAVE: /* 46FA0 802CDF30 3C053F7D */ + case CH_JINJO_STATE_3_TWO_HAND_WAVE: if(actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, 1, 0.0f, -1); + subaddie_set_state_with_direction(this, CH_JINJO_STATE_1_IDLE, 0.0f, -1); } break; - case 4: /* 46FD8 802CDF68 3C053F7D */ + case CH_JINJO_STATE_4_JUMPING_WAVE: /* 46FD8 802CDF68 3C053F7D */ if(actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, 1, 0.0f, -1); + subaddie_set_state_with_direction(this, CH_JINJO_STATE_1_IDLE, 0.0f, -1); }else{//L802CDF9C tmp_f0 = this->yaw; if(sp66 >= 0){ - tmp_f0 -= 80.0f * sp58; + tmp_f0 -= 80.0f * time_delta; } else{//L802CDFBC - tmp_f0 += 80.0f * sp58; + tmp_f0 += 80.0f * time_delta; }//L802CDFD0 if(tmp_f0 >= 360.0f) tmp_f0 -= 360.0f; @@ -162,17 +182,17 @@ void chJinjo_update(Actor * this){ this->yaw = tmp_f0; }//L802CE018 break; - case 6:/* 47094 802CE024 02002025 */ + case CH_JINJO_STATE_6_COLLECTED:/* 47094 802CE024 02002025 */ __chJinjo_802CDC9C(this, sp66); if(actor_animationIsAt(this, 0.0f) && --(local->unk0) == 0){ - subaddie_set_state_with_direction(this, 7, 0.0f, -1); + subaddie_set_state_with_direction(this, CH_JINJO_STATE_7_FLY_START, 0.0f, -1); actor_playAnimationOnce(this); if(local->unk4){ - sp40[0] = this->position_x; - sp40[1] = this->position_y; - sp40[2] = this->position_z; - sp40[1] += 50.0f; - jiggy_spawn(10*level_get()-9, sp40); + jiggy_position[0] = this->position_x; + jiggy_position[1] = this->position_y; + jiggy_position[2] = this->position_z; + jiggy_position[1] += 50.0f; + jiggy_spawn(10 * level_get() - 9, jiggy_position); }//L802CE0CC core1_ce60_incOrDecCounter(false); func_8032BB88(this, 0, 4000); @@ -184,27 +204,27 @@ void chJinjo_update(Actor * this){ }//L802CE114 break; - case 7: - case 8: - sp50 = this->state == 7; - if(!sp50 || 0.1 < anctrl_getAnimTimer(this->anctrl)){//L802CE158 - player_getVelocity(sp70); - sp70[0] *= sp58*6.0f;\ - sp70[1] *= sp58*6.0f;\ - sp70[2] *= sp58*6.0f; - sp70[0] = sp70[0] + sp7C[0];\ - sp70[1] = sp70[1] + sp7C[1];\ - sp70[2] = sp70[2] + sp7C[2]; - sp70[0] -= this->position_x;\ - sp70[1] -= this->position_y;\ - sp70[2] -= this->position_z; - sp70[0] *= sp58*3.0f; - sp70[1] *= sp58*3.0f; - sp70[2] *= sp58*3.0f; - this->position_x = this->position_x + sp70[0]; - this->position_y = this->position_y + sp70[1]; - this->position_z = this->position_z + sp70[2]; - if(sp50 || anctrl_getAnimTimer(this->anctrl) < 0.8){ + case CH_JINJO_STATE_7_FLY_START: + case CH_JINJO_STATE_8_FLY_END: + is_flying_start = this->state == CH_JINJO_STATE_7_FLY_START; + if(!is_flying_start || 0.1 < anctrl_getAnimTimer(this->anctrl)){//L802CE158 + player_getVelocity(player_velocity); + player_velocity[0] *= time_delta * 6.0f;\ + player_velocity[1] *= time_delta * 6.0f;\ + player_velocity[2] *= time_delta * 6.0f; + player_velocity[0] = player_velocity[0] + sp7C[0];\ + player_velocity[1] = player_velocity[1] + sp7C[1];\ + player_velocity[2] = player_velocity[2] + sp7C[2]; + player_velocity[0] -= this->position_x;\ + player_velocity[1] -= this->position_y;\ + player_velocity[2] -= this->position_z; + player_velocity[0] *= time_delta * 3.0f; + player_velocity[1] *= time_delta * 3.0f; + player_velocity[2] *= time_delta * 3.0f; + this->position_x = this->position_x + player_velocity[0]; + this->position_y = this->position_y + player_velocity[1]; + this->position_z = this->position_z + player_velocity[2]; + if(is_flying_start || anctrl_getAnimTimer(this->anctrl) < 0.8){ for(i = 0; i < 4; i++){ if(randf() < 0.3){ commonParticle_add(this->marker, i + 5, func_80329904); @@ -214,38 +234,38 @@ void chJinjo_update(Actor * this){ }//L802CE2D0 } - if(sp50){ + if(is_flying_start){ if(anctrl_getAnimTimer(this->anctrl) < 0.2) __chJinjo_802CDC9C(this, sp66); if(actor_animationIsAt(this, 0.1f)){ local->unkC = func_802F9AA8(SFX_18_BIGBUTT_SLIDE); - func_802F9EC4(local->unkC, sp30, 500, 2000); + func_802F9EC4(local->unkC, this_position, 500, 2000); func_802F9F80(local->unkC, 0.0f, 9e+09, 0.0f); func_802FA0B0(local->unkC, 0); coMusicPlayer_playMusic(COMUSIC_43_ENTER_LEVEL_GLITTER, 0x7FFF); func_8025AABC(COMUSIC_43_ENTER_LEVEL_GLITTER); - func_8030E9C4(SFX_C7_SHWOOP, 0.8f, 0x7FFF, sp30, 300.0f, 2000.0f); + func_8030E9C4(SFX_C7_SHWOOP, 0.8f, 0x7FFF, this_position, 300.0f, 2000.0f); }//L802CE3C4 if(actor_animationIsAt(this, 0.434f)){ - func_8030E9C4(SFX_C7_SHWOOP, 0.9f, 0x7fff, sp30, 300.0f, 2000.0f); + func_8030E9C4(SFX_C7_SHWOOP, 0.9f, 0x7fff, this_position, 300.0f, 2000.0f); }//L802CE408 if(actor_animationIsAt(this, 0.811f)){ - func_8030E9C4(SFX_C7_SHWOOP, 1.0f, 0x7fff, sp30, 300.0f, 2000.0f); + func_8030E9C4(SFX_C7_SHWOOP, 1.0f, 0x7fff, this_position, 300.0f, 2000.0f); } }else{//L802CE450 - if(actor_animationIsAt(this,0.214f)){ - func_8030E9C4(SFX_C7_SHWOOP, 1.1f, 0x7fff, sp30, 300.0f, 2000.0f); + if(actor_animationIsAt(this, 0.214f)){ + func_8030E9C4(SFX_C7_SHWOOP, 1.1f, 0x7fff, this_position, 300.0f, 2000.0f); }//L802CE490 - if(actor_animationIsAt(this,0.55f)){ - func_8030E9C4(SFX_53_BANJO_HUIII, 1.5f, 0x7fff, sp30, 300.0f, 2000.0f); + if(actor_animationIsAt(this, 0.55f)){ + func_8030E9C4(SFX_53_BANJO_HUIII, 1.5f, 0x7fff, this_position, 300.0f, 2000.0f); }//L802CE4D0 - if(actor_animationIsAt(this,0.75f)){ + if(actor_animationIsAt(this, 0.75f)){ func_80326310(this); if(local->unk4 == 0){ func_8032BB88(this, -1, 4000); @@ -255,7 +275,7 @@ void chJinjo_update(Actor * this){ } }//L802CE518 - if(actor_animationIsAt(this,0.85f)){ + if(actor_animationIsAt(this, 0.85f)){ if(local->unkC){ func_802F9D38(local->unkC); local->unkC = 0; @@ -264,7 +284,7 @@ void chJinjo_update(Actor * this){ func_8025A7DC(COMUSIC_43_ENTER_LEVEL_GLITTER); }//L802CE558 - if(local->unk4 && actor_animationIsAt(this,0.95f)){ + if(local->unk4 && actor_animationIsAt(this, 0.95f)){ func_8032BB88(this, -1, 4000); if (EventSystem_Should(VB_SET_JINJO_COUNT, true)) { core1_ce60_incOrDecCounter(true); @@ -272,44 +292,47 @@ void chJinjo_update(Actor * this){ } }//L802CE598 - if(sp50){ + if(is_flying_start){ if(actor_animationIsAt(this, 0.96f) || actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, 8, 0.0f, -1); + subaddie_set_state_with_direction(this, CH_JINJO_STATE_8_FLY_END, 0.0f, -1); actor_playAnimationOnce(this); } } break; }//L802CE5F0 - if(this->state < 4 && !(((sp66 >= 0)? sp66: -sp66) <= 0x1000)){ - subaddie_set_state_with_direction(this, 4, 0.0f, -1); + if(this->state < CH_JINJO_STATE_4_JUMPING_WAVE + && !(((sp66 >= 0)? sp66: -sp66) <= 0x1000)) + { + subaddie_set_state_with_direction(this, CH_JINJO_STATE_4_JUMPING_WAVE, 0.0f, -1); actor_playAnimationOnce(this); }//L802CE630 + if(!gcdialog_hasCurrentTextId()){ switch(chJinjoAnimations[this->state].index){ case ASSET_31_ANIM_JINJO_JUMP: if(actor_animationIsAt(this, 0.6f)){ if(local->unk8){ - func_8030E988(SFX_8_BANJO_LANDING_04, 1.8f, 18000, sp30, 120.0f, 1200.0f); + func_8030E988(SFX_8_BANJO_LANDING_04, 1.8f, 18000, this_position, 120.0f, 1200.0f); }else{ - sfx_playFadeShorthandDefault(SFX_8_BANJO_LANDING_04, 1.8f, 18000, sp30, 120, 1200); + sfx_playFadeShorthandDefault(SFX_8_BANJO_LANDING_04, 1.8f, 18000, this_position, 120, 1200); } } break; case ASSET_2D_ANIM_JINJO_IDLE: //L802CE6F4 if(actor_animationIsAt(this, 0.2f)){ if(local->unk8){ - func_8030E988(SFX_17_JINJO_WHISTLE, 1.0f, 22000, sp30, 120.0f, 1200.0f); + func_8030E988(SFX_17_JINJO_WHISTLE, 1.0f, 22000, this_position, 120.0f, 1200.0f); }else{ - sfx_playFadeShorthandDefault(SFX_17_JINJO_WHISTLE, 1.0f, 22000, sp30, 120, 1200); + sfx_playFadeShorthandDefault(SFX_17_JINJO_WHISTLE, 1.0f, 22000, this_position, 120, 1200); } } break; case ASSET_2F_ANIM_JINJO_HELP: //L802CE760 if(actor_animationIsAt(this, 0.2f)){ if(local->unk8){ - func_8030E988(SFX_27_JINJO_HI, 1.0f, 22000, sp30, 120.0f, 1200.0f); + func_8030E988(SFX_27_JINJO_HI, 1.0f, 22000, this_position, 120.0f, 1200.0f); }else{ - sfx_playFadeShorthandDefault(SFX_27_JINJO_HI, 1.0f, 22000, sp30, 120, 1200); + sfx_playFadeShorthandDefault(SFX_27_JINJO_HI, 1.0f, 22000, this_position, 120, 1200); } } break; diff --git a/src/core2/ch/level_collectible.c b/src/core2/ch/level_collectible.c deleted file mode 100644 index 1d1fb4dcf..000000000 --- a/src/core2/ch/level_collectible.c +++ /dev/null @@ -1,378 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" - -extern void func_8028F7D4(f32, f32); -void chLevelCollectible_update(Actor *this); -extern ActorMarker *func_8028E86C(void); -extern void timed_mapSpecificFlags_setTrue(f32, s32); -extern void progressDialog_showDialogMaskFour(s32); - -ActorAnimationInfo D_80367B50[] = { - {0, 0.0f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f} -}; - -ActorInfo D_80367B80 = { - MARKER_36_ORANGE_COLLECTIBLE, ACTOR_29_ORANGE_COLLECTIBLE, ASSET_2D2_MODEL_ORANGE, - 0x5, NULL, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.6f,0 -}; - -ActorInfo D_80367BA4 = { - MARKER_37_GOLD_BULLION, ACTOR_2A_GOLD_BULLION, ASSET_3C7_MODEL_GOLD_BULLION, - 0x5, NULL, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.6f, 0 -}; - -ActorInfo D_80367BC8 = { - MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE, ASSET_47F_MODEL_XMAS_GIFT_BLUE, - 0x5, D_80367B50, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 1.8f, 0 -}; - -ActorInfo D_80367BEC = { - MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE, ASSET_480_MODEL_XMAS_GIFT_GREEN, - 0x5, D_80367B50, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 1.4f, 0 -}; - -ActorInfo D_80367C10 = { - MARKER_1FF_RED_PRESENT_COLLECTIBLE, ACTOR_1F1_RED_PRESENT_COLLECTIBLE, ASSET_481_MODEL_XMAS_GIFT_RED, - 0x5, D_80367B50, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 1.4f, 0 -}; - -/* .code */ -void __chLevelCollectible_presentReturnEmitSparkles(f32 position[3], enum asset_e sprite_id) { - static ParticleScaleAndLifetimeRanges D_80367C34 = {{0.2f, 0.4f}, {0.1f, 0.1f}, {0.0f, 0.01f}, {3.0f, 3.5f}, 0.1f, 0.1f}; - ParticleEmitter *p_emitter; - - p_emitter = partEmitMgr_newEmitter(1); - particleEmitter_setSprite(p_emitter, sprite_id); - particleEmitter_setStartingFrameRange(p_emitter, 0, 7); - particleEmitter_setPosition(p_emitter, position); - particleEmitter_setSpawnPositionRange(p_emitter, -40.0f, 0.0f, -40.0f, 40.0f, 60.0f, 40.0f); - particleEmitter_setAccelerationRange(p_emitter, 0.0f, -1000.0f, 0.0f, 0.0f, -1000.0f, 0.0f); - particleEmitter_setScaleAndLifetimeRanges(p_emitter, &D_80367C34); - particleEmitter_emitN(p_emitter, 1); -} - -void __chLevelCollectible_presentCollectEmitSparkles(f32 position[3], enum asset_e sprite_id) { - ParticleEmitter *p_emitter; - - p_emitter = partEmitMgr_newEmitter(8); - particleEmitter_setSprite(p_emitter, sprite_id); - particleEmitter_setPosition(p_emitter, position); - particleEmitter_setAccelerationRange(p_emitter, 0.0f, -250.0f, 0.0f, 0.0f, -250.0f, 0.0f); - particleEmitter_setParticleVelocityRange(p_emitter, -100.0f, 200.0f, -100.0f, 100.0f, 350.0f, 100.0f); - particleEmitter_setAngularVelocityRange(p_emitter, 0.0f, 0.0f, 200.0f, 0.0f, 0.0f, 240.0f); - particleEmitter_setStartingScaleRange(p_emitter, 0.47f, 0.47f); - particleEmitter_setFinalScaleRange(p_emitter, 0.03f, 0.03f); - particleEmitter_setFade(p_emitter, 0.4f, 0.8f); - particleEmitter_setParticleLifeTimeRange(p_emitter, 0.9f, 0.9f); - particleEmitter_emitN(p_emitter, 8); -} - -s32 __chLevelCollectible_dialogCallback(ActorMarker *marker, enum asset_e text_id, s32 arg2) { - return -(levelSpecificFlags_get(LEVEL_FLAG_2A_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2B_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2C_FP_UNKNOWN)); -} - - -void __chLevelCollectible_callDialog(enum asset_e text_id){ - gcdialog_showDialogConditional(text_id, 0, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker*,s32,s32))__chLevelCollectible_dialogCallback); -} - -void __chLevelCollectible_collide(ActorMarker *marker, ActorMarker *other_marker) { - Actor *this; - f32 pad28; - s32 dialog_id; - f32 sp18[3]; - - this = marker_getActor(marker); - dialog_id = 0; - if ((this->state == 1) || (this->state == 2)) { - sp18[0] = this->position[0]; - sp18[1] = this->position[1]; - sp18[2] = this->position[2]; - switch (marker->id) { - case MARKER_36_ORANGE_COLLECTIBLE: - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_1_ORANGE_HAS_BEEN_COLLECTED)) { - return; - } - - progressDialog_showDialogMaskFour(FILEPROG_8_ORANGE_TEXT); - func_8030E6D4(SFX_B3_ORANGE_TALKING); - dialog_id = 0; - break; - - case MARKER_37_GOLD_BULLION: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - timedFunc_set_1(0.5f, (GenFunction_1)progressDialog_showDialogMaskFour, FILEPROG_9_GOLD_BULLION_TEXT); - dialog_id = 0; - break; - - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - levelSpecificFlags_set(LEVEL_FLAG_2A_FP_UNKNOWN, true); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); - dialog_id = ASSET_C20_DIALOG_PRESENT_COLLECTIBLE_MEET_BLUE; - break; - - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - levelSpecificFlags_set(LEVEL_FLAG_2B_FP_UNKNOWN, true); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_712_SPRITE_SPARKLE_GREEN); - dialog_id = ASSET_C21_DIALOG_PRESENT_COLLECTIBLE_MEET_GREEN; - break; - - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - levelSpecificFlags_set(LEVEL_FLAG_2C_FP_UNKNOWN, true); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); - dialog_id = ASSET_C22_DIALOG_PRESENT_COLLECTIBLE_MEET_RED; - break; - - default: - break; - } - if (dialog_id != 0) { - timedFunc_set_1(0.5f, (GenFunction_1)__chLevelCollectible_callDialog, dialog_id); - } - func_8028F030(this->modelCacheIndex); - marker_despawn(marker); - } -} - -void func_802D7DE8(ActorMarker *marker, f32 arg1[3]) { - Actor *this; - s32 sp50[3]; - s32 sp4C; - f32 var_f12; - f32 var_f14; - f32 var_f18; - - sp4C = marker->id; - this = marker_getActor(marker); - ml_vec3f_to_vec3w(sp50, arg1); - if (sp4C == MARKER_37_GOLD_BULLION) { - if (mapSpecificFlags_get(0)) { - mapSpecificFlags_set(1, true); - } else { - mapSpecificFlags_set(0, true); - } - } - func_8028F010(this->modelCacheIndex); - subaddie_set_state(this, 4); - var_f12 = this->position[1]; - var_f14 = 28.0f; - var_f18 = 0.0f; - this->unk1C[0] = arg1[0]; - this->unk1C[1] = arg1[1]; - this->unk1C[2] = arg1[2]; - this->velocity[0] = (f32) sp50[0] - this->position[0]; - this->velocity[1] = 28.0f; - this->velocity[2] = (f32) sp50[2] - this->position[2]; - while (!(var_f12 < sp50[1]) || !(var_f14 < 0.0f)) { - var_f18 += 1.0f; - var_f12 += (var_f14 -= 5.0); - } - this->velocity[0] /= var_f18; - this->velocity[2] /= var_f18; - this->unk38_31 = (u32)var_f18; -} - -void func_802D8030(Actor *this){ - s32 *local; - - local = (s32*)&this->local; - *local = 1; - this->marker->collisionFunc = __chLevelCollectible_collide; - subaddie_set_state(this, 2); -} - -void __chLevelCollectible_returnObj(Actor *this) { - s32 *local; - f32 sp20; - - local = (s32*)&this->local; - if( (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) - || (this->secondaryId == 0) - ) { - this->position[0] += this->velocity[0]; - this->position[1] += (this->velocity[1] -= 5.0); - this->position[2] += this->velocity[2]; - } - if (--this->unk38_31 < 4) { - sp20 = this->unk1C[1]; - } else { - sp20 = this->position[1]; - } - if (this->position[1] < sp20) { - if (this->modelCacheIndex == ACTOR_2A_GOLD_BULLION) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - if (mapSpecificFlags_get(1)) { - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 32000); - } - } - this->position[1] = sp20; - if (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) { - sfx_playFadeShorthandDefault(SFX_21_EGG_BOUNCE_1, 0.76f, 25000, this->position, 1000, 2000); - } else { - sfx_playFadeShorthandDefault(SFX_B3_ORANGE_TALKING, 1.0f, 25000, this->position, 1000, 2000); - } - if (this->state == 4) { - switch (this->marker->id) { - case MARKER_37_GOLD_BULLION: - break; - case MARKER_36_ORANGE_COLLECTIBLE: - timed_mapSpecificFlags_setTrue(1.7f, MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED); - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - break; - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - levelSpecificFlags_set(LEVEL_FLAG_11_FP_UNKNOWN, true); - break; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - levelSpecificFlags_set(LEVEL_FLAG_12_FP_UNKNOWN, true); - break; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - levelSpecificFlags_set(LEVEL_FLAG_13_FP_UNKNOWN, true); - break; - } - } - this->unk138_22 = this->unk138_21 = 0; - subaddie_set_state(this, 2); - } - switch (this->marker->id) { - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); - break; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, 0x712); - break; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); - break; - } - - if (*local != 0) { - *local = 0; - } -} - -void func_802D8374(Actor *this){ - s32 pad2C; - f32 sp20[3]; - - if(func_8028E86C() != this->marker){ - func_8028F050(this->modelCacheIndex); - marker_despawn(this->marker); - } - else{ - if(this->unk138_21){ - func_8028EF28(sp20); - func_802D7DE8(this->marker, sp20); - } - } -} - -void func_802D83EC(Actor *this) { - s32 var_s0; - - // temp_f20 = D_80376D70; - for(var_s0 = 0; var_s0 < 10; var_s0++){ - if (randf() < 0.03) { - commonParticle_add(this->marker, var_s0 + 5, func_80329904); - commonParticle_new(8, this->marker->unk14_21); - } - } - this->yaw = this->yaw + time_getDelta() * 25.0f; - if (360.0 < this->yaw) { - this->yaw -= 360.0; - } - if (mapSpecificFlags_get(0x1F)) { - marker_despawn(this->marker); - } -} - -void func_802D84F4(Actor *this){ - this->marker->propPtr->unk8_3 = ( this->state == 2 ); -} - -void chLevelCollectible_update(Actor *this){ - s32 marker_id; - if(this->despawn_flag) return; - - if(!this->volatile_initialized){ - this->volatile_initialized = true; - if( this->marker->id == MARKER_1FD_BLUE_PRESENT_COLLECTIBLE - || this->marker->id == MARKER_1FE_GREEN_PRESENT_COLLECTIBLE - || this->marker->id == MARKER_1FF_RED_PRESENT_COLLECTIBLE - ){ - if(jiggyscore_isCollected(JIGGY_2E_FP_PRESENTS)){ - marker_despawn(this->marker); - return; - } - } - if(this->unk138_22){ - func_8028F7D4(0.0f, 0.0f); - subaddie_set_state(this, 3); - } - }//L802D85DC - - switch(this->state){ - case 5:// 802D8604 - func_802D8030(this); - break; - - case 1:// 802D8620 - __chLevelCollectible_returnObj(this); - break; - - case 2:// 802D863C - break; - - case 3:// 802D8650 - func_802D8374(this); - break; - - case 4:// 802D866C - __chLevelCollectible_returnObj(this); - break; - - default: - break; - } - - marker_id = this->marker->id; - - switch(this->marker->id){ - - case MARKER_37_GOLD_BULLION: //L802D86CC - func_802D83EC(this); - break; - case MARKER_36_ORANGE_COLLECTIBLE: //L802D86DC - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_3_CHIMPY_HAS_LEFT) && gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN) { - marker_despawn(this->marker); - } - break; - - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - func_802D84F4(this); - break; - } -} diff --git a/src/core2/ch/levelcollectible.c b/src/core2/ch/levelcollectible.c new file mode 100644 index 000000000..2591e199d --- /dev/null +++ b/src/core2/ch/levelcollectible.c @@ -0,0 +1,692 @@ +// BanjoDecomp: core2/levelcollectible.c +#include +#include "functions.h" +#include "variables.h" +#include "port/Enhancements/Retention/Retention.h" + +extern void func_8028F7D4(f32, f32); +void chLevelCollectible_update(Actor *this); +extern ActorMarker *bacarry_getMarkerWithExtraSteps(void); + +static s32 levelCollectible_syncKind(s32 markerId) { + switch (markerId) { + case MARKER_36_ORANGE_COLLECTIBLE: return ANCHOR_COLLECTIBLE_ORANGE; + case MARKER_37_GOLD_BULLION: return ANCHOR_COLLECTIBLE_GOLD; + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: return ANCHOR_COLLECTIBLE_PRESENT_BLUE; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: return ANCHOR_COLLECTIBLE_PRESENT_GREEN; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: return ANCHOR_COLLECTIBLE_PRESENT_RED; + default: return -1; + } +} + +extern s32 port_anchor_getDummyTransform(u32 clientId, f32 pos[3], f32* yaw); +extern void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]); + +void __chLevelCollectible_presentReturnEmitSparkles(f32 position[3], enum asset_e sprite_id); + +#define REMOTE_CARRY_MAX 16 +static struct { + u32 clientId; // 0 = free slot + ActorMarker *marker; // NULL while the spawn is still queued + s32 markerId; + u8 throwPending; + f32 throwStart[3]; + f32 throwTarget[3]; + f32 carryOff[3]; // held pose: object position relative to the owner + f32 carryYawOff; // held pose: object yaw relative to the owner's yaw +} sRemoteCarry[REMOTE_CARRY_MAX]; + +static s32 __remoteCarry_actorIdForMarker(s32 markerId) { + switch (markerId) { + case MARKER_36_ORANGE_COLLECTIBLE: return ACTOR_29_ORANGE_COLLECTIBLE; + case MARKER_37_GOLD_BULLION: return ACTOR_2A_GOLD_BULLION; + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: return ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: return ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: return ACTOR_1F1_RED_PRESENT_COLLECTIBLE; + case MARKER_1B5_CATERPILLAR: return ACTOR_2A2_CATERPILLAR; + case 0x1BC /* acorn marker (unnamed) */: return ACTOR_2A9_ACORN; + default: return 0; + } +} + +static s32 __remoteCarry_findByClient(u32 clientId) { + s32 i; + for (i = 0; i < REMOTE_CARRY_MAX; i++) { + if (sRemoteCarry[i].clientId == clientId) { + return i; + } + } + return -1; +} + +static s32 __remoteCarry_findByMarker(ActorMarker *marker) { + s32 i; + for (i = 0; i < REMOTE_CARRY_MAX; i++) { + if (sRemoteCarry[i].clientId != 0 && sRemoteCarry[i].marker == marker) { + return i; + } + } + return -1; +} + +static void __remoteCarry_clearSlot(s32 slot) { + sRemoteCarry[slot].clientId = 0; + sRemoteCarry[slot].marker = NULL; + sRemoteCarry[slot].markerId = 0; + sRemoteCarry[slot].throwPending = 0; + sRemoteCarry[slot].carryOff[0] = sRemoteCarry[slot].carryOff[1] = sRemoteCarry[slot].carryOff[2] = 0.0f; + sRemoteCarry[slot].carryYawOff = 0.0f; +} + +static void __remoteCarry_setPose(s32 slot, f32 offset[3], f32 yawOffset) { + sRemoteCarry[slot].carryOff[0] = offset[0]; + sRemoteCarry[slot].carryOff[1] = offset[1]; + sRemoteCarry[slot].carryOff[2] = offset[2]; + sRemoteCarry[slot].carryYawOff = yawOffset; +} + +// Mirror of func_802D7DE8's arc math without its side effects. State 7 = remote flight. +static void __remoteCarry_launch(Actor *actor, f32 start[3], f32 target[3]) { + s32 tgt[3]; + f32 var_f12; + f32 var_f14; + f32 var_f18; + + actor->position[0] = start[0]; + actor->position[1] = start[1]; + actor->position[2] = start[2]; + ml_vec3f_to_vec3w(tgt, target); + actor->unk1C[0] = target[0]; + actor->unk1C[1] = target[1]; + actor->unk1C[2] = target[2]; + actor->velocity[0] = (f32)tgt[0] - actor->position[0]; + actor->velocity[1] = 28.0f; + actor->velocity[2] = (f32)tgt[2] - actor->position[2]; + var_f12 = actor->position[1]; + var_f14 = 28.0f; + var_f18 = 0.0f; + while (!(var_f12 < tgt[1]) || !(var_f14 < 0.0f)) { + var_f18 += 1.0f; + var_f12 += (var_f14 -= 5.0); + } + actor->velocity[0] /= var_f18; + actor->velocity[2] /= var_f18; + actor->unk38_31 = (u32)var_f18; + subaddie_set_state(actor, 7); +} + +static void __remoteCarry_spawnMethod(s32 markerId, s32 clientId) { + f32 pos[3]; + f32 yaw = 0.0f; + Actor *actor; + s32 slot = __remoteCarry_findByClient((u32)clientId); + s32 actorId = __remoteCarry_actorIdForMarker(markerId); + + if (slot < 0 || sRemoteCarry[slot].markerId != markerId || actorId == 0) { + return; // stale queue entry + } + if (!port_anchor_getDummyTransform((u32)clientId, pos, &yaw)) { + __remoteCarry_clearSlot(slot); + return; + } + actor = actor_spawnWithYaw_f32(actorId, pos, (s32)yaw); + // Display copy: skip init, no collision with the local player. + actor->volatile_initialized = true; + actor->marker->propPtr->unk8_3 = false; + if (sRemoteCarry[slot].throwPending) { + __remoteCarry_launch(actor, sRemoteCarry[slot].throwStart, sRemoteCarry[slot].throwTarget); + __remoteCarry_clearSlot(slot); + } else { + sRemoteCarry[slot].marker = actor->marker; + subaddie_set_state(actor, 6); + } +} + +void port_remoteCarry_setCarried(u32 clientId, s32 markerId, f32 offset[3], f32 yawOffset) { + s32 slot; + if (clientId == 0) { + return; + } + if (markerId != 0 && __remoteCarry_actorIdForMarker(markerId) == 0) { + markerId = 0; // not a synced carryable + } + slot = __remoteCarry_findByClient(clientId); + if (markerId == 0) { + if (slot >= 0 && !sRemoteCarry[slot].throwPending) { + if (sRemoteCarry[slot].marker != NULL) { + marker_despawn(sRemoteCarry[slot].marker); + } + __remoteCarry_clearSlot(slot); + } + return; + } + if (slot >= 0) { + if (sRemoteCarry[slot].markerId == markerId) { + __remoteCarry_setPose(slot, offset, yawOffset); + return; + } + if (sRemoteCarry[slot].marker != NULL) { + marker_despawn(sRemoteCarry[slot].marker); + } + __remoteCarry_clearSlot(slot); + } + slot = __remoteCarry_findByClient(0); + if (slot < 0) { + return; // registry full + } + sRemoteCarry[slot].clientId = clientId; + sRemoteCarry[slot].markerId = markerId; + sRemoteCarry[slot].marker = NULL; + sRemoteCarry[slot].throwPending = 0; + __remoteCarry_setPose(slot, offset, yawOffset); + __spawnQueue_add_2((GenFunction_2)__remoteCarry_spawnMethod, markerId, clientId); +} + +void port_remoteCarry_throw(u32 clientId, s32 markerId, f32 start[3], f32 target[3]) { + s32 slot; + if (clientId == 0 || __remoteCarry_actorIdForMarker(markerId) == 0) { + return; + } + slot = __remoteCarry_findByClient(clientId); + if (slot >= 0 && sRemoteCarry[slot].marker != NULL) { + Actor *actor = marker_getActor(sRemoteCarry[slot].marker); + __remoteCarry_launch(actor, start, target); + __remoteCarry_clearSlot(slot); + return; + } + if (slot < 0) { + slot = __remoteCarry_findByClient(0); + if (slot < 0) { + return; + } + sRemoteCarry[slot].clientId = clientId; + __spawnQueue_add_2((GenFunction_2)__remoteCarry_spawnMethod, markerId, clientId); + } + sRemoteCarry[slot].markerId = markerId; + sRemoteCarry[slot].throwPending = 1; + sRemoteCarry[slot].throwStart[0] = start[0]; + sRemoteCarry[slot].throwStart[1] = start[1]; + sRemoteCarry[slot].throwStart[2] = start[2]; + sRemoteCarry[slot].throwTarget[0] = target[0]; + sRemoteCarry[slot].throwTarget[1] = target[1]; + sRemoteCarry[slot].throwTarget[2] = target[2]; +} + +void port_remoteCarry_reset(void) { + s32 i; + for (i = 0; i < REMOTE_CARRY_MAX; i++) { + __remoteCarry_clearSlot(i); + } +} + +s32 port_remoteCarry_displayUpdate(Actor *this) { + s32 slot = __remoteCarry_findByMarker(this->marker); + + if (this->state == 6 || slot >= 0) { // carried: glued to the owner's dummy + f32 pos[3]; + f32 yaw = 0.0f; + if (slot < 0 || !port_anchor_getDummyTransform(sRemoteCarry[slot].clientId, pos, &yaw)) { + if (slot >= 0) { + __remoteCarry_clearSlot(slot); + } + marker_despawn(this->marker); + return 1; + } + this->position[0] = pos[0] + sRemoteCarry[slot].carryOff[0]; + this->position[1] = pos[1] + sRemoteCarry[slot].carryOff[1]; + this->position[2] = pos[2] + sRemoteCarry[slot].carryOff[2]; + this->yaw = mlNormalizeAngle(yaw + sRemoteCarry[slot].carryYawOff); + return 1; + } + + if (this->state == 7) { // thrown: replay the arc, land with feedback only + f32 landY; + this->position[0] += this->velocity[0]; + this->position[1] += (this->velocity[1] -= 5.0); + this->position[2] += this->velocity[2]; + landY = (--this->unk38_31 < 4) ? this->unk1C[1] : this->position[1]; + if (this->position[1] < landY) { + if (this->modelCacheIndex == ACTOR_2A2_CATERPILLAR || this->modelCacheIndex == ACTOR_2A9_ACORN) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); + marker_despawn(this->marker); + return 1; + } + if (this->modelCacheIndex == ACTOR_2A_GOLD_BULLION) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + } + if (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) { + sfx_playFadeShorthandDefault(SFX_21_EGG_BOUNCE_1, 0.76f, 25000, this->position, 1000, 2000); + } else { + sfx_playFadeShorthandDefault(SFX_B3_ORANGE_TALKING, 1.0f, 25000, this->position, 1000, 2000); + } + // State 8: landed display copy. + this->position[1] = landY; + subaddie_set_state(this, 8); + return 1; + } + switch (this->marker->id) { + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); + break; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, 0x712); + break; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); + break; + } + return 1; + } + + // State 8 (landed display copy) falls through to the vanilla lifecycle below. + + return 0; +} +extern void timed_mapSpecificFlags_setTrue(f32, s32); +extern void progressDialog_showDialogMaskFour(s32); + +ActorAnimationInfo chPresentCollectibleAnimations[] = { + {0, 0.0f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f} +}; + +ActorInfo chOrangeCollectible = { + MARKER_36_ORANGE_COLLECTIBLE, ACTOR_29_ORANGE_COLLECTIBLE, ASSET_2D2_MODEL_ORANGE, + 0x5, NULL, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.6f,0 +}; + +ActorInfo chGoldBullion = { + MARKER_37_GOLD_BULLION, ACTOR_2A_GOLD_BULLION, ASSET_3C7_MODEL_GOLD_BULLION, + 0x5, NULL, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.6f, 0 +}; + +ActorInfo chBluePresentCollectible = { + MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE, ASSET_47F_MODEL_XMAS_GIFT_BLUE, + 0x5, chPresentCollectibleAnimations, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 1.8f, 0 +}; + +ActorInfo chGreenPresentCollectible = { + MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE, ASSET_480_MODEL_XMAS_GIFT_GREEN, + 0x5, chPresentCollectibleAnimations, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 1.4f, 0 +}; + +ActorInfo chRedPresentCollectible = { + MARKER_1FF_RED_PRESENT_COLLECTIBLE, ACTOR_1F1_RED_PRESENT_COLLECTIBLE, ASSET_481_MODEL_XMAS_GIFT_RED, + 0x5, chPresentCollectibleAnimations, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 1.4f, 0 +}; + +/* .code */ +void __chLevelCollectible_presentReturnEmitSparkles(f32 position[3], enum asset_e sprite_id) { + static ParticleScaleAndLifetimeRanges D_80367C34 = {{0.2f, 0.4f}, {0.1f, 0.1f}, {0.0f, 0.01f}, {3.0f, 3.5f}, 0.1f, 0.1f}; + ParticleEmitter *p_emitter; + + p_emitter = partEmitMgr_newEmitter(1); + particleEmitter_setSprite(p_emitter, sprite_id); + particleEmitter_setStartingFrameRange(p_emitter, 0, 7); + particleEmitter_setPosition(p_emitter, position); + particleEmitter_setSpawnPositionRange(p_emitter, -40.0f, 0.0f, -40.0f, 40.0f, 60.0f, 40.0f); + particleEmitter_setAccelerationRange(p_emitter, 0.0f, -1000.0f, 0.0f, 0.0f, -1000.0f, 0.0f); + particleEmitter_setScaleAndLifetimeRanges(p_emitter, &D_80367C34); + particleEmitter_emitN(p_emitter, 1); +} + +void __chLevelCollectible_presentCollectEmitSparkles(f32 position[3], enum asset_e sprite_id) { + ParticleEmitter *p_emitter; + + p_emitter = partEmitMgr_newEmitter(8); + particleEmitter_setSprite(p_emitter, sprite_id); + particleEmitter_setPosition(p_emitter, position); + particleEmitter_setAccelerationRange(p_emitter, 0.0f, -250.0f, 0.0f, 0.0f, -250.0f, 0.0f); + particleEmitter_setParticleVelocityRange(p_emitter, -100.0f, 200.0f, -100.0f, 100.0f, 350.0f, 100.0f); + particleEmitter_setAngularVelocityRange(p_emitter, 0.0f, 0.0f, 200.0f, 0.0f, 0.0f, 240.0f); + particleEmitter_setStartingScaleRange(p_emitter, 0.47f, 0.47f); + particleEmitter_setFinalScaleRange(p_emitter, 0.03f, 0.03f); + particleEmitter_setFade(p_emitter, 0.4f, 0.8f); + particleEmitter_setParticleLifeTimeRange(p_emitter, 0.9f, 0.9f); + particleEmitter_emitN(p_emitter, 8); +} + +s32 __chLevelCollectible_dialogCallback(ActorMarker *marker, enum asset_e text_id, s32 arg2) { + return -(levelSpecificFlags_get(LEVEL_FLAG_2A_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2B_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2C_FP_UNKNOWN)); +} + + +void __chLevelCollectible_callDialog(enum asset_e text_id){ + gcdialog_showDialogConditional(text_id, 0, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker*,s32,s32))__chLevelCollectible_dialogCallback); +} + +void __chLevelCollectible_collide(ActorMarker *marker, ActorMarker *other_marker) { + Actor *this; + f32 pad28; + s32 dialog_id; + f32 sp18[3]; + + this = marker_getActor(marker); + dialog_id = 0; + if ((this->state == 1) || (this->state == 2)) { + sp18[0] = this->position[0]; + sp18[1] = this->position[1]; + sp18[2] = this->position[2]; + switch (marker->id) { + case MARKER_36_ORANGE_COLLECTIBLE: + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_1_ORANGE_HAS_BEEN_COLLECTED)) { + return; + } + + progressDialog_showDialogMaskFour(FILEPROG_8_ORANGE_TEXT); + func_8030E6D4(SFX_B3_ORANGE_TALKING); + dialog_id = 0; + break; + + case MARKER_37_GOLD_BULLION: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + timedFunc_set_1(0.5f, (GenFunction_1)progressDialog_showDialogMaskFour, FILEPROG_9_GOLD_BULLION_TEXT); + dialog_id = 0; + break; + + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + levelSpecificFlags_set(LEVEL_FLAG_2A_FP_UNKNOWN, true); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); + dialog_id = VER_SELECT(ASSET_C20_DIALOG_PRESENT_COLLECTIBLE_MEET_BLUE, 0x99A, 0, 0); + break; + + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + levelSpecificFlags_set(LEVEL_FLAG_2B_FP_UNKNOWN, true); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_712_SPRITE_SPARKLE_GREEN); + dialog_id = VER_SELECT(ASSET_C21_DIALOG_PRESENT_COLLECTIBLE_MEET_GREEN, 0x99B, 0, 0); + break; + + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + levelSpecificFlags_set(LEVEL_FLAG_2C_FP_UNKNOWN, true); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); + dialog_id = VER_SELECT(ASSET_C22_DIALOG_PRESENT_COLLECTIBLE_MEET_RED, 0x99C, 0, 0); + break; + + default: + break; + } + if (dialog_id != 0) { + timedFunc_set_1(0.5f, (GenFunction_1)__chLevelCollectible_callDialog, dialog_id); + } + bacarriedobj_incWithExtraSteps(this->modelCacheIndex); + { + s32 kind = levelCollectible_syncKind(marker->id); + if (kind >= 0) { + port_carriedSync_onLocalCollect(kind, marker); + } + } + marker_despawn(marker); + } +} + +void func_802D7DE8(ActorMarker *marker, f32 arg1[3]) { + Actor *this; + s32 sp50[3]; + s32 sp4C; + f32 var_f12; + f32 var_f14; + f32 var_f18; + + sp4C = marker->id; + this = marker_getActor(marker); + ml_vec3f_to_vec3w(sp50, arg1); + if (sp4C == MARKER_37_GOLD_BULLION) { + if (mapSpecificFlags_get(0)) { + mapSpecificFlags_set(1, true); + } else { + mapSpecificFlags_set(0, true); + } + } + bacarriedobj_decWithExtraSteps(this->modelCacheIndex); + { + s32 kind = levelCollectible_syncKind(marker->id); + if (kind >= 0) { + port_carriedSync_onLocalSpend(kind); + } + } + subaddie_set_state(this, 4); + var_f12 = this->position[1]; + var_f14 = 28.0f; + var_f18 = 0.0f; + this->unk1C[0] = arg1[0]; + this->unk1C[1] = arg1[1]; + this->unk1C[2] = arg1[2]; + this->velocity[0] = (f32) sp50[0] - this->position[0]; + this->velocity[1] = 28.0f; + this->velocity[2] = (f32) sp50[2] - this->position[2]; + while (!(var_f12 < sp50[1]) || !(var_f14 < 0.0f)) { + var_f18 += 1.0f; + var_f12 += (var_f14 -= 5.0); + } + this->velocity[0] /= var_f18; + this->velocity[2] /= var_f18; + this->unk38_31 = (u32)var_f18; +} + +void func_802D8030(Actor *this){ + s32 *local; + + local = (s32*)&this->local; + *local = 1; + this->marker->collisionFunc = __chLevelCollectible_collide; + subaddie_set_state(this, 2); +} + +void __chLevelCollectible_returnObj(Actor *this) { + s32 *local; + f32 sp20; + + local = (s32*)&this->local; + if( (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) + || (this->secondaryId == 0) + ) { + this->position[0] += this->velocity[0]; + this->position[1] += (this->velocity[1] -= 5.0); + this->position[2] += this->velocity[2]; + } + if (--this->unk38_31 < 4) { + sp20 = this->unk1C[1]; + } else { + sp20 = this->position[1]; + } + if (this->position[1] < sp20) { + if (this->modelCacheIndex == ACTOR_2A_GOLD_BULLION) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + if (mapSpecificFlags_get(1)) { + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 32000); + } + } + this->position[1] = sp20; + if (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) { + sfx_playFadeShorthandDefault(SFX_21_EGG_BOUNCE_1, 0.76f, 25000, this->position, 1000, 2000); + } else { + sfx_playFadeShorthandDefault(SFX_B3_ORANGE_TALKING, 1.0f, 25000, this->position, 1000, 2000); + } + if (this->state == 4) { + switch (this->marker->id) { + case MARKER_37_GOLD_BULLION: + break; + case MARKER_36_ORANGE_COLLECTIBLE: + timed_mapSpecificFlags_setTrue(1.7f, MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); + break; + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + levelSpecificFlags_set(LEVEL_FLAG_11_FP_UNKNOWN, true); + break; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + levelSpecificFlags_set(LEVEL_FLAG_12_FP_UNKNOWN, true); + break; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + levelSpecificFlags_set(LEVEL_FLAG_13_FP_UNKNOWN, true); + break; + } + } + this->unk138_22 = this->unk138_21 = 0; + subaddie_set_state(this, 2); + } + switch (this->marker->id) { + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); + break; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, 0x712); + break; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); + break; + } + + if (*local != 0) { + *local = 0; + } +} + +void func_802D8374(Actor *this){ + s32 pad2C; + f32 sp20[3]; + + if(bacarry_getMarkerWithExtraSteps() != this->marker){ + bacarriedobj_displayOnHudWithExtraSteps(this->modelCacheIndex); + marker_despawn(this->marker); + } + else{ + if(this->unk138_21){ + func_8028EF28(sp20); + // [port] Anchor: replay this throw on teammates; sent before func_802D7DE8 moves the actor. + port_anchor_onCarryThrow(this->marker->id, this->position, sp20); + func_802D7DE8(this->marker, sp20); + } + } +} + +void func_802D83EC(Actor *this) { + s32 var_s0; + + // temp_f20 = D_80376D70; + for(var_s0 = 0; var_s0 < 10; var_s0++){ + if (randf() < 0.03) { + commonParticle_add(this->marker, var_s0 + 5, func_80329904); + commonParticle_new(8, this->marker->unk14_21); + } + } + this->yaw = this->yaw + time_getDelta() * 25.0f; + if (360.0 < this->yaw) { + this->yaw -= 360.0; + } + if (mapSpecificFlags_get(0x1F)) { + marker_despawn(this->marker); + } +} + +void func_802D84F4(Actor *this){ + this->marker->propPtr->unk8_3 = ( this->state == 2 ); +} + +void chLevelCollectible_update(Actor *this){ + s32 marker_id; + if(this->despawn_flag) return; + + if (port_remoteCarry_displayUpdate(this)) { + return; + } + + if(!this->volatile_initialized){ + this->volatile_initialized = true; + if( this->marker->id == MARKER_1FD_BLUE_PRESENT_COLLECTIBLE + || this->marker->id == MARKER_1FE_GREEN_PRESENT_COLLECTIBLE + || this->marker->id == MARKER_1FF_RED_PRESENT_COLLECTIBLE + ){ + if(jiggyscore_isCollected(JIGGY_2E_FP_PRESENTS)){ + marker_despawn(this->marker); + return; + } + } + if(this->unk138_22){ + func_8028F7D4(0.0f, 0.0f); + subaddie_set_state(this, 3); + } else { + s32 kind = levelCollectible_syncKind(this->marker->id); + if (kind >= 0) { + s32 suppress; + port_carriedSync_register(kind, this->marker, (s32)this->position[0], + (s32)this->position[1], (s32)this->position[2], &suppress); + if (suppress) { + marker_despawn(this->marker); + return; + } + } + } + }//L802D85DC + + if (!this->unk138_22) { + s32 kind = levelCollectible_syncKind(this->marker->id); + if (kind >= 0 && port_carriedSync_consumeRemoteDespawn(kind, this->marker)) { + marker_despawn(this->marker); + return; + } + } + + switch(this->state){ + case 5:// 802D8604 + func_802D8030(this); + break; + + case 1:// 802D8620 + __chLevelCollectible_returnObj(this); + break; + + case 2:// 802D863C + break; + + case 3:// 802D8650 + func_802D8374(this); + break; + + case 4:// 802D866C + __chLevelCollectible_returnObj(this); + break; + + default: + break; + } + + marker_id = this->marker->id; + + switch(this->marker->id){ + + case MARKER_37_GOLD_BULLION: //L802D86CC + func_802D83EC(this); + break; + case MARKER_36_ORANGE_COLLECTIBLE: //L802D86DC + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_3_CHIMPY_HAS_LEFT) && gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN) { + marker_despawn(this->marker); + } + break; + + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + func_802D84F4(this); + break; + } +} diff --git a/src/core2/ch/mole.c b/src/core2/ch/mole.c index fc2813357..ca9a701a5 100644 --- a/src/core2/ch/mole.c +++ b/src/core2/ch/mole.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/mole.c #include #include "functions.h" #include "variables.h" @@ -14,6 +15,29 @@ typedef struct{ } ChMoleDescription; /* .data */ + +enum mole_states +{ + MOLE_STATE_1_AWAITING_PLAYER = 1, + MOLE_STATE_2_POP_OUT_OF_MOLEHILL, + MOLE_STATE_3_EXPLAINING_ABILITY, + MOLE_STATE_4_REENTER_MOLEHILL, + MOLE_STATE_5_REFRESHER +}; + +enum mole_ability_learn_actions +{ + MOLE_ABILITY_LEARN_ACTION_1_STILT_STRIDE = 1, + MOLE_ABILITY_LEARN_ACTION_2_UNK, + MOLE_ABILITY_LEARN_ACTION_3_TURBO_TALON_TRAINER, + MOLE_ABILITY_LEARN_ACTION_4_UNK, + MOLE_ABILITY_LEARN_ACTION_5_EGG_FIRING, + MOLE_ABILITY_LEARN_ACTION_6_FLIGHT, + MOLE_ABILITY_LEARN_ACTION_7_WONDERWING, + MOLE_ABILITY_LEARN_ACTION_8_REFILL_HEALTH, + MOLE_ABILITY_LEARN_ACTION_FF_UNK = 0xFF +}; + ActorAnimationInfo moleAnimations[]= { {0, 0.0f}, {ASSET_13A_ANIM_BOTTLES_ENTER, 2000000000.0f}, @@ -30,22 +54,22 @@ ActorInfo gChMole = { 0, 0, 0.0f, 0 }; -// D_80367DC4 ChMoleDescription moleTable[] = { - {ASSET_C23_DIALOG_BEAKBOMB_LEARN, ASSET_C24_DIALOG_BEAKBOMB_REFRESHER, 0x0F, ABILITY_1_BEAK_BOMB}, - {ASSET_B47_DIALOG_EGGS_LEARN, ASSET_B4B_DIALOG_EGGS_REFRESHER, 0x16, ABILITY_6_EGGS}, - {ASSET_B48_DIALOG_BEAKBUSTER_LEARN, ASSET_B4C_DIALOG_BEAKBUSTER_REFRESHER, 0x17, ABILITY_2_BEAK_BUSTER}, - {ASSET_B49_DIALOG_TALON_TROT_LEARN, ASSET_B4A_DIALOG_TALON_TROT_REFRESHER, 0x18, ABILITY_10_TALON_TROT}, - {ASSET_A1F_DIALOG_SHOCKJUMP_LEARN, ASSET_A23_DIALOG_SHOCKJUMP_REFRESHER, 0x0C, ABILITY_D_SHOCK_JUMP}, - {ASSET_A20_DIALOG_FLY_LEARN, ASSET_A22_DIALOG_FLY_REFRESHER, 0x0D, ABILITY_9_FLIGHT}, - {ASSET_D35_DIALOG_WONDERWING_LEARN, ASSET_D36_DIALOG_WONDERWING_REFRESHER, 0x01, ABILITY_12_WONDERWING}, - {ASSET_C88_DIALOG_WADING_BOOTS_LEARN, ASSET_C89_DIALOG_WADING_BOOTS_REFRESHER, 0x10, ABILITY_E_WADING_BOOTS}, - {ASSET_A84_DIALOG_TURBOTRAINERS_LEARN, ASSET_A85_DIALOG_TURBOTRAINERS_REFRESHER, 0x19, ABILITY_11_TURBO_TALON}, - {ASSET_F64_DIALOG_NOTEDOORS_LEARN, ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, 0x0E, ABILITY_13_1ST_NOTEDOOR} + {VER_SELECT(ASSET_C23_DIALOG_BEAKBOMB_LEARN, 0x99D, 0, 0), VER_SELECT(ASSET_C24_DIALOG_BEAKBOMB_REFRESHER, 0x99E, 0, 0), 0x0F, ABILITY_1_BEAK_BOMB}, + {VER_SELECT(ASSET_B47_DIALOG_EGGS_LEARN, 0x965, 0, 0), VER_SELECT(ASSET_B4B_DIALOG_EGGS_REFRESHER, 0x969, 0, 0), 0x16, ABILITY_6_EGGS}, + {VER_SELECT(ASSET_B48_DIALOG_BEAKBUSTER_LEARN, 0x966, 0, 0), VER_SELECT(ASSET_B4C_DIALOG_BEAKBUSTER_REFRESHER, 0x96A, 0, 0), 0x17, ABILITY_2_BEAK_BUSTER}, + {VER_SELECT(ASSET_B49_DIALOG_TALON_TROT_LEARN, 0x967, 0, 0), VER_SELECT(ASSET_B4A_DIALOG_TALON_TROT_REFRESHER, 0x968, 0, 0), 0x18, ABILITY_10_TALON_TROT}, + {VER_SELECT(ASSET_A1F_DIALOG_SHOCKJUMP_LEARN, 0x91F, 0, 0), VER_SELECT(ASSET_A23_DIALOG_SHOCKJUMP_REFRESHER, 0x923, 0, 0), 0x0C, ABILITY_D_SHOCK_JUMP}, + {VER_SELECT(ASSET_A20_DIALOG_FLY_LEARN, 0x920, 0, 0), VER_SELECT(ASSET_A22_DIALOG_FLY_REFRESHER, 0x922, 0, 0), 0x0D, ABILITY_9_FLIGHT}, + {VER_SELECT(ASSET_D35_DIALOG_WONDERWING_LEARN, 0xA08, 0, 0), VER_SELECT(ASSET_D36_DIALOG_WONDERWING_REFRESHER, 0xA09, 0, 0), 0x01, ABILITY_12_WONDERWING}, + {VER_SELECT(ASSET_C88_DIALOG_WADING_BOOTS_LEARN, 0x9CB, 0, 0), VER_SELECT(ASSET_C89_DIALOG_WADING_BOOTS_REFRESHER, 0x9CC, 0, 0), 0x10, ABILITY_E_WADING_BOOTS}, + {VER_SELECT(ASSET_A84_DIALOG_TURBOTRAINERS_LEARN, 0x940, 0, 0), VER_SELECT(ASSET_A85_DIALOG_TURBOTRAINERS_REFRESHER, 0x941, 0, 0), 0x19, ABILITY_11_TURBO_TALON}, + {VER_SELECT(ASSET_F64_DIALOG_NOTEDOORS_LEARN, 0xACA, 0, 0), VER_SELECT(ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, 0xACB, 0, 0), 0x0E, ABILITY_13_1ST_NOTEDOOR} }; +#define MOLE_ID_TO_TABLE_SHIFT 9 + /* .code */ -// chmole_learnedAllLevelAbilities int chmole_learnedAllLevelAbilities(enum level_e level){ // Checks if all of the level's abilities are learned. switch (level){ @@ -65,7 +89,7 @@ int chmole_learnedAllLevelAbilities(enum level_e level){ case LEVEL_7_GOBIS_VALLEY: return ability_isUnlocked(ABILITY_11_TURBO_TALON); default: - return false; + return FALSE; } } @@ -76,19 +100,19 @@ enum asset_e chmole_learnedAllLevelAbilitiesDialog(void){ int learned_all_moves = chmole_learnedAllLevelAbilities(level_id); switch(level_id){ case LEVEL_1_MUMBOS_MOUNTAIN: - return learned_all_moves ? ASSET_B4E_DIALOG_BOTTLES_ALL_MM_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return learned_all_moves ? ASSET_B4E_DIALOG_BOTTLES_ALL_MM_MOVES_LEARNED : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); case LEVEL_2_TREASURE_TROVE_COVE: - return learned_all_moves ? ASSET_A27_DIALOG_BOTTLES_ALL_TTC_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return learned_all_moves ? ASSET_A27_DIALOG_BOTTLES_ALL_TTC_MOVES_LEARNED : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); case LEVEL_3_CLANKERS_CAVERN: - return learned_all_moves ? ASSET_D37_DIALOG_BOTTLES_ALL_CC_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return learned_all_moves ? VER_SELECT(ASSET_D37_DIALOG_BOTTLES_ALL_CC_MOVES_LEARNED, 0xA0A, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); case LEVEL_4_BUBBLEGLOOP_SWAMP: - return learned_all_moves ? ASSET_C8A_DIALOG_BOTTLES_ALL_BGS_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return learned_all_moves ? VER_SELECT(ASSET_C8A_DIALOG_BOTTLES_ALL_BGS_MOVES_LEARNED, 0x9CD, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); case LEVEL_5_FREEZEEZY_PEAK: - return learned_all_moves ? ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return learned_all_moves ? VER_SELECT(ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED, 0x9A4, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); case LEVEL_7_GOBIS_VALLEY: - return learned_all_moves ? ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return learned_all_moves ? VER_SELECT(ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED, 0x9A4, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); default: - return ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; + return VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); } } @@ -109,9 +133,9 @@ int chmole_learnedAllGameAbilities(void){ Actor *func_802D94B4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *actor = marker_getActor(marker); - if(actor->state != 1 && actor->state != 5){ - func_8033A45C(3, 0); - func_8033A45C(4, 0); + if(actor->state != MOLE_STATE_1_AWAITING_PLAYER && actor->state != MOLE_STATE_5_REFRESHER){ + modelRender_setAppendageVisibility(3, 0); + modelRender_setAppendageVisibility(4, 0); actor = actor_draw(marker, gfx, mtx, vtx); } @@ -122,9 +146,9 @@ void func_802D9530(Actor *this){ Actor *other = subaddie_getLinkedActor(this); if(this->partnerActor && other){ if(this->partnerActor->id == 0xB8) - subaddie_set_state_with_direction(other, 3, 0.0001f, 1); + subaddie_set_state_with_direction(other, MOLE_STATE_3_EXPLAINING_ABILITY, 0.0001f, 1); } - subaddie_set_state_with_direction(this, 4, 0.0001f, 1); + subaddie_set_state_with_direction(this, MOLE_STATE_4_REENTER_MOLEHILL, 0.0001f, 1); actor_playAnimationOnce(this); this->unk44_31 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(this->unk44_31, SFX_3F9_UNKNOWN); @@ -136,37 +160,35 @@ void func_802D9530(Actor *this){ void func_802D9600(Actor * this){ anctrl_setSmoothTransition(this->anctrl, 0); - subaddie_set_state_with_direction(this, 1, 0.0001f, 1); + subaddie_set_state_with_direction(this, MOLE_STATE_1_AWAITING_PLAYER, 0.0001f, 1); this->marker->propPtr->unk8_3 = 0; } -// chmole_setStaticCamera void chmole_setStaticCamera(Actor *this){ // Sets the camera to a static camera - timed_setStaticCameraToNode(0.0f, moleTable[this->actorTypeSpecificField-9].camera_node); + timed_setStaticCameraToNode(0.0f, moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].camera_node); } -// chmole_healthRefill void chmole_healthRefill(ActorMarker *marker, enum asset_e arg1, s32 arg2){ // Refills the player's health upon learning a new ability, if needed // Also releases the camera Actor *actor = marker_getActor(marker); - if( arg1 == moleTable[actor->actorTypeSpecificField-9].teach_text_id + if( arg1 == moleTable[actor->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].teach_text_id && item_getCount(ITEM_14_HEALTH) < item_getCount(ITEM_15_HEALTH_TOTAL) ){ - gcdialog_showDialog(ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH, 7, 0, actor->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); + gcdialog_showDialog(VER_SELECT(ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH, 0xA0C, 0, 0), 7, 0, actor->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); }//L802D9738 - else if(arg1 == moleTable[actor->actorTypeSpecificField-9].teach_text_id || arg1 == ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH){ - gcdialog_showDialog(chmole_learnedAllGameAbilities()? 0xa87 : chmole_learnedAllLevelAbilitiesDialog(), 7, 0, actor->marker, chmole_healthRefill, NULL); + else if(arg1 == moleTable[actor->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].teach_text_id || arg1 == VER_SELECT(ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH, 0xA0C, 0, 0)){ + gcdialog_showDialog(chmole_learnedAllGameAbilities()? VER_SELECT(ASSET_A87_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0x943, 0, 0) : chmole_learnedAllLevelAbilitiesDialog(), 7, 0, actor->marker, chmole_healthRefill, NULL); } else{//L802D97BC if(actor->has_met_before){ func_80347A14(1); - actor->has_met_before = false; + actor->has_met_before = FALSE; } timed_exitStaticCamera(0.0f); - if(actor->state == 5){ + if(actor->state == MOLE_STATE_5_REFRESHER){ func_8028F918(0); func_802D9600(actor); }//L802D9814 @@ -176,84 +198,83 @@ void chmole_healthRefill(ActorMarker *marker, enum asset_e arg1, s32 arg2){ }//L802D9820 } -// chmole_additionalAbilityLearnActions void chmole_additionalAbilityLearnActions(ActorMarker *marker, enum asset_e arg1, s32 arg2){ // Performs actions depending on what move is being learned Actor *actor = marker_getActor(marker); switch(arg2){ - case 1: // Stilt Stride + case MOLE_ABILITY_LEARN_ACTION_1_STILT_STRIDE: timed_setStaticCameraToNode(0.0f, 0x11); - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, true); + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, TRUE); break; - case 2: - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, false); + case MOLE_ABILITY_LEARN_ACTION_2_UNK: + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, FALSE); chmole_setStaticCamera(actor); break; - case 3: // Turbo Talon Trainer + case MOLE_ABILITY_LEARN_ACTION_3_TURBO_TALON_TRAINER: timed_setStaticCameraToNode(0.0f, 0x29); - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, true); + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, TRUE); break; - case 4: - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, false); + case MOLE_ABILITY_LEARN_ACTION_4_UNK: + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, FALSE); chmole_setStaticCamera(actor); break; - case 5: // Egg Firing + case MOLE_ABILITY_LEARN_ACTION_5_EGG_FIRING: item_adjustByDiffWithHud(ITEM_D_EGGS, 50); break; - case 6: // Flight + case MOLE_ABILITY_LEARN_ACTION_6_FLIGHT: item_adjustByDiffWithHud(ITEM_F_RED_FEATHER, 25); break; - case 7: // Wonderwing + case MOLE_ABILITY_LEARN_ACTION_7_WONDERWING: item_adjustByDiffWithHud(ITEM_10_GOLD_FEATHER, 5); break; - case 8: // Refill Health + case MOLE_ABILITY_LEARN_ACTION_8_REFILL_HEALTH: item_set(ITEM_14_HEALTH, item_getCount(ITEM_15_HEALTH_TOTAL)); break; - case 0xff: + case MOLE_ABILITY_LEARN_ACTION_FF_UNK: chmole_setStaticCamera(actor); break; } } -// chmole_learnAbility int chmole_learnAbility(Actor *this){ - s32 sp2C; + s32 teach_text_id; s32 sp28 = 0xe; - if (!EventSystem_Should(VB_OVERRIDE_MOLEHILL_ABILITY, false, this, &sp2C, &sp28)) { + // [port] Rando hands out its own item here, whether or not the vanilla move is known. + if (!EventSystem_Should(VB_OVERRIDE_MOLEHILL_ABILITY, false, this, &teach_text_id, &sp28)) { // Known Ability: Refresher Dialog - if (ability_isUnlocked(moleTable[this->actorTypeSpecificField - 9].ability)) { + if(ability_isUnlocked(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability)){ sp28 = 0xf; - sp2C = moleTable[this->actorTypeSpecificField - 9].refresher_text_id; + teach_text_id = moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].refresher_text_id; }//L802D99EC // New Ability: Learn Dialog & Misc Actions - else { + else{ func_80347A14(0); - this->has_met_before = true; - sp2C = moleTable[this->actorTypeSpecificField - 9].teach_text_id; - ability_unlock(moleTable[this->actorTypeSpecificField - 9].ability); - switch (moleTable[this->actorTypeSpecificField - 9].ability) { - case ABILITY_9_FLIGHT: - case ABILITY_D_SHOCK_JUMP: - gcsfx_playWithPitch(SFX_113_PAD_APPEARS, 0.9f, 32000); - break; - case ABILITY_13_1ST_NOTEDOOR: - func_802FAD64(ITEM_C_NOTE); - break; + this->has_met_before = TRUE; + teach_text_id = moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].teach_text_id; + ability_unlock(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability); + switch(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability){ + case ABILITY_9_FLIGHT: + case ABILITY_D_SHOCK_JUMP: + gcsfx_playWithPitch(SFX_113_PAD_APPEARS, 0.9f, 32000); + break; + case ABILITY_13_1ST_NOTEDOOR: + func_802FAD64(ITEM_C_NOTE); + break; } }//L802D9A9C } - gcdialog_showDialog(sp2C, sp28, this->position, this->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); - return true; + gcdialog_showDialog(teach_text_id, sp28, this->position, this->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); + return TRUE; } void func_802D9ADC(Actor *this){ Actor *other = subaddie_getLinkedActor(this); if(this->partnerActor && other && this->partnerActor->id == 0xB8){ - subaddie_set_state_with_direction(other, 2, 0.0001f, 1); + subaddie_set_state_with_direction(other, MOLE_STATE_2_POP_OUT_OF_MOLEHILL, 0.0001f, 1); } this->marker->propPtr->unk8_3 = 1; - anctrl_setSmoothTransition(this->anctrl, true); - subaddie_set_state_with_direction(this, 2, 0.0001f, 1); + anctrl_setSmoothTransition(this->anctrl, TRUE); + subaddie_set_state_with_direction(this, MOLE_STATE_2_POP_OUT_OF_MOLEHILL, 0.0001f, 1); actor_playAnimationOnce(this); this->unk44_31 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(this->unk44_31, SFX_3F9_UNKNOWN); @@ -266,16 +287,15 @@ void func_802D9ADC(Actor *this){ void chmole_Refresher(Actor *this){ // Plays the scene where Bottles gives the player a refresher on the ability. - subaddie_set_state(this, 5); + subaddie_set_state(this, MOLE_STATE_5_REFRESHER); chmole_setStaticCamera(this); func_8028F94C(2, this->position); chmole_learnAbility(this); } -// chmole_setFacingDirection void chmole_setFacingDirection(Actor *this){ // Sets the actor to always be facing the player - subaddie_set_state_with_direction(this, 3, 0.0001f, 1); + subaddie_set_state_with_direction(this, MOLE_STATE_3_EXPLAINING_ABILITY, 0.0001f, 1); actor_loopAnimation(this); } @@ -296,11 +316,10 @@ void func_802D9C90(Actor *this){ } } -// chmole_startingDialog void chmole_startingDialog(Actor *this){ // If the player knows the ability, use refresher function // Otherwise, set player's position and spawn mole - if(ability_isUnlocked(moleTable[this->actorTypeSpecificField - 9].ability)){ + if(ability_isUnlocked(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability)){ chmole_Refresher(this); } else{ @@ -314,7 +333,6 @@ void chmole_startingDialog(Actor *this){ } } -// chmole_update void chmole_update(Actor *this){ // Sets up the initial functions and state for the actor s32 sp50[6]; @@ -326,11 +344,11 @@ void chmole_update(Actor *this){ // Checks the actor's selector value is between 0x8 and 0x13 // Anything lower is a Spiral Mountain ability, and should use a different actor id - if(this->actorTypeSpecificField < 8 || this->actorTypeSpecificField >= 0x13) + if(this->actorTypeSpecificField < CH_SM_MOLE_ID_8_BRIDGE || this->actorTypeSpecificField >= CH_MOLE_ID_13_EMPTY) return; if(!this->volatile_initialized){ - this->volatile_initialized = true; + this->volatile_initialized = TRUE; marker_setFreeMethod(this->marker, func_802D9C90); if(this->initialized){ other = actorArray_findClosestActorFromActorId(this->position, ACTOR_12C_MOLEHILL, -1, &sp4C); @@ -338,7 +356,7 @@ void chmole_update(Actor *this){ if(this->partnerActor){ other = subaddie_getLinkedActor(this); if(other && this->partnerActor->id == MARKER_B8_MOLEHILL){ - subaddie_set_state(other, 1); + subaddie_set_state(other, MOLE_STATE_1_AWAITING_PLAYER); } } } @@ -349,17 +367,17 @@ void chmole_update(Actor *this){ // If actor exists and player is within radius, force trigger conversation node_prop = nodeprop_findByActorIdAndActorPosition(0x372, this); if(node_prop == NULL){ - this->unk38_0 = false; + this->unk38_0 = FALSE; } else{ - this->unk38_0 = true; + this->unk38_0 = TRUE; nodeprop_getPosition(node_prop, this->unk1C); } // Spawns molehill - __spawnQueue_add_1((GenFunction_1)chmole_spawnMolehill, (uintptr_t)this->marker); - this->marker->propPtr->unk8_3 = false; - this->marker->collidable = false; - this->initialized = true; + __spawnQueue_add_1((GenFunction_1)chmole_spawnMolehill, reinterpret_cast(uintptr_t, this->marker)); + this->marker->propPtr->unk8_3 = FALSE; + this->marker->collidable = FALSE; + this->initialized = TRUE; if(this->actorTypeSpecificField == CH_MOLE_ID_12_OPEN_NOTEDOORS){ node_prop = nodeprop_findByActorIdAndActorPosition(0x349, this); if(node_prop == NULL){ @@ -376,12 +394,12 @@ void chmole_update(Actor *this){ }//L802D9F34 controller_copyFaceButtons(0, sp50); // get face buttons press counters switch(this->state){ - case 1://L802D9F70 + case MOLE_STATE_1_AWAITING_PLAYER://L802D9F70 this->yaw_ideal = subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); - if(func_8028F20C() && func_8028F0D4() && !func_8028EC04()){ + if(player_isStableWithExtraSteps() && player_isBanjoOrWishywashy() && !func_8028EC04()){ if( this->actorTypeSpecificField == CH_MOLE_ID_12_OPEN_NOTEDOORS - && !ability_isUnlocked(moleTable[this->actorTypeSpecificField-9].ability) + && !ability_isUnlocked(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability) && (player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT) ){ player_getPosition(sp34); @@ -400,8 +418,8 @@ void chmole_update(Actor *this){ } } break; - case 2://L802DA0A0 - this->marker->propPtr->unk8_3 = true; + case MOLE_STATE_2_POP_OUT_OF_MOLEHILL://L802DA0A0 + this->marker->propPtr->unk8_3 = TRUE; this->yaw_ideal = subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); if( 0.0 < anctrl_getAnimTimer(this->anctrl) @@ -427,7 +445,7 @@ void chmole_update(Actor *this){ chmole_learnAbility(this); } break; - case 3://L802DA210 + case MOLE_STATE_3_EXPLAINING_ABILITY://L802DA210 this->yaw_ideal = subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); if( ( actor_animationIsAt(this, 0.37f) @@ -456,7 +474,7 @@ void chmole_update(Actor *this){ func_8030E878(SFX_6F_BANJO_HEADSCRATCH, randf2(1.35f, 1.5f), 6000, this->position, 1250.0f, 2500.0f); } break; - case 4://L802DA400 + case MOLE_STATE_4_REENTER_MOLEHILL://L802DA400 if( 0.35 < anctrl_getAnimTimer(this->anctrl) && anctrl_getAnimTimer(this->anctrl) < 0.9 ){ diff --git a/src/core2/ch/molehill.c b/src/core2/ch/molehill.c index 8a484c54c..83f010c1e 100644 --- a/src/core2/ch/molehill.c +++ b/src/core2/ch/molehill.c @@ -14,16 +14,16 @@ Actor *func_802DA560(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802DA740(Actor *this); /*.data */ -ActorAnimationInfo D_80367E00[] = { +ActorAnimationInfo chMolehillAnimations[] = { {0x000, 0.0f}, - {0x13D, 2000000000.0f}, - {0x13D, 4.5f}, - {0x13C, 1.7f} + {ASSET_13D_ANIM_MOLEHILL_UNKNOWN, 2000000000.0f}, + {ASSET_13D_ANIM_MOLEHILL_UNKNOWN, 4.5f}, + {ASSET_13C_ANIM_MOLEHILL_UNKNOWN, 1.7f} }; -ActorInfo D_80367E20= { +ActorInfo chMolehill = { MARKER_B8_MOLEHILL, ACTOR_12C_MOLEHILL, ASSET_388_MODEL_MOLEHILL, - 0, D_80367E00, + 0, chMolehillAnimations, func_802DA740, actor_update_func_80326224, func_802DA560, 0, 0, 0.0f, 0 }; diff --git a/src/core2/ch/mumbo_sign.c b/src/core2/ch/mumbo_sign.c deleted file mode 100644 index 1944b538d..000000000 --- a/src/core2/ch/mumbo_sign.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" - -void chMumboSign_update(Actor *this); - -/* .data */ -ActorInfo D_80367530 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_368_5_MUMBO_TOKEN_SIGN, ASSET_301_MODEL_5_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80367554 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36B_10_MUMBO_TOKEN_SIGN, ASSET_302_MODEL_10_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80367578 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36A_15_MUMBO_TOKEN_SIGN, ASSET_303_MODEL_15_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8036759C = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_369_20_MUMBO_TOKEN_SIGN, ASSET_304_MODEL_20_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_803675C0 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36C_25_MUMBO_TOKEN_SIGN, ASSET_305_MODEL_25_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; - -void chMumboSign_update(Actor *this) { - if (!this->volatile_initialized) { - if( fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST) - || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - ) { - marker_despawn(this->marker); - } - this->volatile_initialized = true; - } - if (fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST)) { - func_80326310(this); - } -} diff --git a/src/core2/ch/mumbosign.c b/src/core2/ch/mumbosign.c new file mode 100644 index 000000000..46ff261ba --- /dev/null +++ b/src/core2/ch/mumbosign.c @@ -0,0 +1,27 @@ +// BanjoDecomp: core2/mumbosign.c +#include +#include "functions.h" +#include "variables.h" + +void chMumboSign_update(Actor *this); + +/* .data */ +ActorInfo chMumboSign5 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_368_5_MUMBO_TOKEN_SIGN, ASSET_301_MODEL_5_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chMumboSign10 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36B_10_MUMBO_TOKEN_SIGN, ASSET_302_MODEL_10_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chMumboSign15 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36A_15_MUMBO_TOKEN_SIGN, ASSET_303_MODEL_15_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chMumboSign20 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_369_20_MUMBO_TOKEN_SIGN, ASSET_304_MODEL_20_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chMumboSign25 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36C_25_MUMBO_TOKEN_SIGN, ASSET_305_MODEL_25_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; + +void chMumboSign_update(Actor *this) { + if (!this->volatile_initialized) { + if( fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST) + || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) + ) { + marker_despawn(this->marker); + } + this->volatile_initialized = true; + } + if (fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST)) { + func_80326310(this); + } +} diff --git a/src/core2/ch/mumbotoken.c b/src/core2/ch/mumbotoken.c index c3623b286..ddcb1ba29 100644 --- a/src/core2/ch/mumbotoken.c +++ b/src/core2/ch/mumbotoken.c @@ -7,14 +7,14 @@ typedef struct { enum mumbotoken_e uid; }ActorLocal_MumboToken; -void func_802E0B10(Actor *this); +void chMumboToken_update(Actor *this); enum mumbotoken_e func_802E0CB0(Actor *this); /* .data */ - ActorInfo D_803685A0 = { + ActorInfo chMumboToken = { MARKER_39_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, ASSET_41A_SPRITE_MUMBO_TOKEN, - 0, NULL, - func_802E0B10, actor_update_func_80326224, fxTouchSparkle_draw, + 0, NULL, + chMumboToken_update, actor_update_func_80326224, fxTouchSparkle_draw, 2000, 0, 0.0f, 0 }; @@ -27,6 +27,7 @@ void chMumboToken_collect(ActorMarker *marker, ActorMarker *other_marker){ this = marker_getActor(marker); mumboscore_set(func_802E0CB0(this), true); + CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_MUMBO, func_802E0CB0(this)); func_8030E760(0x401, 1.0f, 0x7fff); timedFunc_set_1(0.75f, (GenFunction_1)progressDialog_showDialogMaskZero, FILEPROG_4_MUMBO_TOKEN_TEXT); fxSparkle_mumboToken(&marker->propPtr->x); @@ -56,7 +57,7 @@ enum mumbotoken_e func_802E0A90(Actor *this){ } } -void func_802E0B10(Actor *this){ +void chMumboToken_update(Actor *this){ ActorLocal_MumboToken *local; f32 sp28[3]; diff --git a/src/core2/ch/shock_jumppad.c b/src/core2/ch/shock_jumppad.c index 2b53f347a..cd127c9ae 100644 --- a/src/core2/ch/shock_jumppad.c +++ b/src/core2/ch/shock_jumppad.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_43A40.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ch/snacker.c b/src/core2/ch/snacker.c index 1191d59f6..63d518b95 100644 --- a/src/core2/ch/snacker.c +++ b/src/core2/ch/snacker.c @@ -80,7 +80,7 @@ static void __chsnacker_start_dialog(Actor *this) { text_index = mapSpecificFlags_getN(8, 3); if( !this->has_met_before ) { if(text_index < 4) { - if(gcdialog_showDialog(ASSET_A1B_DIALOG_SNACKER_SPAWNED_1 + text_index, 0, NULL, NULL, NULL, NULL)){ + if(gcdialog_showDialog(VER_SELECT(ASSET_A1B_DIALOG_SNACKER_SPAWNED_1, 0x91B, 0, 0) + text_index, 0, NULL, NULL, NULL, NULL)){ text_index++; mapSpecificFlags_setN(8, text_index, 3); this->has_met_before = true; @@ -195,7 +195,7 @@ void chsnacker_update(Actor *this) { this->unk154 = 0x085E0000; marker_setCollisionScripts(this->marker, __chsnacker_ow, func_802E1010, __chsnacker_die); } - _player_getPosition(player_position); + playerPosition_get(player_position); controller_state = snackerctl_get_state(); if(func_802E0DC0(this->position) || ((controller_state != SNACKER_CTL_STATE_1_RBB) && (controller_state != SNACKER_CTL_STATE_2_TTC))) { @@ -330,7 +330,7 @@ void chSnacker_spawn(void) { f32 sp20[3]; - _player_getPosition(spawn_position); + playerPosition_get(spawn_position); if (volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE) != 0) { nodeprop_getPosition(nodeprop_findByActorIdAndPosition_f32(ACTOR_3CB_UNKNOWN, spawn_position), spawn_position); } diff --git a/src/core2/ch/snowball.c b/src/core2/ch/snowball.c index fefe9928d..3d82557ef 100644 --- a/src/core2/ch/snowball.c +++ b/src/core2/ch/snowball.c @@ -160,7 +160,7 @@ void chSnowball_update(Actor *this) { } break; case 2: - this->marker->unk40_22 = NOT(func_8028F170()); + this->marker->unk40_22 = NOT(player_isInFirstPersonView()); this->velocity[0] *= 0.7; this->velocity[1] *= 0.7; this->velocity[2] *= 0.7; diff --git a/src/core2/ch/snowman.c b/src/core2/ch/snowman.c index dba509c54..9b152afc8 100644 --- a/src/core2/ch/snowman.c +++ b/src/core2/ch/snowman.c @@ -2,6 +2,8 @@ #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + extern void particleEmitter_func_802EFA20(ParticleEmitter *, f32, f32); extern void subaddie_set_state_with_direction(Actor *, s32, f32, s32); extern void subaddie_turnToYaw(Actor *, f32); @@ -47,8 +49,8 @@ Actor *chSnowman_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ actor = marker_getActor(marker); local = (ActorLocal_chSirSlush *)&actor->local; - func_8033A45C(1, local->unk9); - func_8033A45C(2, local->unkA); + modelRender_setAppendageVisibility(1, local->unk9); + modelRender_setAppendageVisibility(2, local->unkA); return actor_draw(marker, gfx, mtx, vtx); } @@ -185,8 +187,11 @@ void __chSnowman_deathCallback(ActorMarker *marker, ActorMarker *other_marker){ sfx_playFadeShorthandDefault(SFX_2F_ORANGE_SPLAT, 1.0f, 30000, actor->position, 1500, 4500); __spawnQueue_add_1((GenFunction_1)__chSnowman_spawnHat, (uintptr_t)actor->marker); - if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK) + if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ maSnowy_decRemaining(); + port_puzzlePos_mark(ANCHOR_PUZZLE_FP_SLUSHES, (s32)actor->position[0], (s32)actor->position[1], + (s32)actor->position[2]); + } __chSnowman_spawnSnowballParticles(actor->position, 0xC); marker_despawn(actor->marker); } @@ -224,8 +229,20 @@ void chSnowman_update(Actor *this){ if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ local->unk0 = actorArray_findActorFromActorId(0x336)->marker; maSnowy_incTotal(); + if(port_puzzlePos_isMarked(ANCHOR_PUZZLE_FP_SLUSHES, (s32)this->position[0], + (s32)this->position[1], (s32)this->position[2])){ + maSnowy_decRemaining(); + marker_despawn(this->marker); + return; + } } }//L802E21D8 + if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK && !this->despawn_flag + && port_puzzlePos_isMarked(ANCHOR_PUZZLE_FP_SLUSHES, (s32)this->position[0], + (s32)this->position[1], (s32)this->position[2])){ + __chSnowman_deathCallback(this->marker, NULL); + return; + } if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ if(maSlalom_isActive() || func_8038DD14()){ actor_collisionOff(this); diff --git a/src/core2/ch/trainers.c b/src/core2/ch/trainers.c index 29635e1bc..da9df47f8 100644 --- a/src/core2/ch/trainers.c +++ b/src/core2/ch/trainers.c @@ -82,8 +82,8 @@ void chtrainers_update(Actor *this){ && !volatileFlag_get(VOLATILE_FLAG_F_HAS_MEET_TURBO_SHOES) && player_getTransformation() == TRANSFORM_1_BANJO ){ - if(gcdialog_showDialog(0xda4, 0, NULL, NULL, NULL, NULL)){ - volatileFlag_set(VOLATILE_FLAG_F_HAS_MEET_TURBO_SHOES, true); + if(gcdialog_showDialog(VER_SELECT(0xda4, 0xA22, 0, 0), 0, NULL, NULL, NULL, NULL)){ + volatileFlag_set(VOLATILE_FLAG_F_HAS_MEET_TURBO_SHOES, TRUE); } }//L802CA620 _chtrainers_802CA378(this, sp2C); diff --git a/src/core2/ch/wadingboots.c b/src/core2/ch/wadingboots.c index 0499263ce..319620ba9 100644 --- a/src/core2/ch/wadingboots.c +++ b/src/core2/ch/wadingboots.c @@ -9,16 +9,16 @@ Actor *chwadingboots_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chwadingboots_update(Actor *this); /* .data */ -ActorAnimationInfo D_80367A00[] = { +ActorAnimationInfo chWadingBootsAnimations[] = { {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, }; -ActorInfo D_80367A20 = { +ActorInfo chWadingBoots = { MARKER_11_WADING_BOOTS, ACTOR_65_WADING_BOOTS, ASSET_366_MODEL_WADING_BOOTS, - 0x0, D_80367A00, + 0x0, chWadingBootsAnimations, chwadingboots_update, actor_update_func_80326224, chwadingboots_draw, 0, 0, 0.0f, 0 }; @@ -70,8 +70,8 @@ void chwadingboots_update(Actor *this){ if(!subaddie_playerIsWithinSphereAndActive(this, 250)) break; if(player_getTransformation() != TRANSFORM_1_BANJO) break; - if(gcdialog_showDialog(ASSET_DA5_DIALOG_WADINGBOOTS_MEET, 0, NULL, NULL, NULL, NULL)){ - volatileFlag_set(VOLATILE_FLAG_10_HAS_MEET_WADING_BOOTS, true); + if(gcdialog_showDialog(VER_SELECT(ASSET_DA5_DIALOG_WADINGBOOTS_MEET, 0xA23, 0, 0), 0, NULL, NULL, NULL, NULL)){ + volatileFlag_set(VOLATILE_FLAG_10_HAS_MEET_WADING_BOOTS, TRUE); } break; diff --git a/src/core2/checksums.c b/src/core2/checksums.c new file mode 100644 index 000000000..15652a8f4 --- /dev/null +++ b/src/core2/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: core2/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsCore2; diff --git a/src/core2/climb.c b/src/core2/climb.c index deda2e7c5..d1a6e3015 100644 --- a/src/core2/climb.c +++ b/src/core2/climb.c @@ -7,30 +7,29 @@ /* .bss */ f32 climbPoleBottom[3]; f32 climbPoleTop[3]; -f32 climbRadius;//climbRadius +f32 climbRadius; f32 D_8037C580[3]; -f32 D_8037C58C; -u8 D_8037C590; //bool climbing +f32 climbRegrabWaitTime; +u8 isClimbingBool; u8 D_8037C591; /* .code */ -void climbClear(void){ //climbClear +void climb_clear(void){ ml_vec3f_clear(climbPoleBottom); ml_vec3f_clear(climbPoleTop); - D_8037C590 = 0; - D_8037C58C = 0.0f; - + isClimbingBool = 0; + climbRegrabWaitTime = 0.0f; } -void climbGetBottom(f32 dst[3]){ //climbGetBottom +void climb_getBottom(f32 dst[3]){ ml_vec3f_copy(dst, climbPoleBottom); } -f32 climbGetBottomY(void){ //climbGetBottomY +f32 climb_getBottomY(void){ return climbPoleBottom[1]; } -f32 climbGetRadius(void){ //climbGetRadius +f32 climb_getRadius(void){ return climbRadius; } @@ -38,32 +37,32 @@ u8 func_8029825C(void){ //climb_2098250 return D_8037C591; } -f32 climbGetTopY(void){ //climbGetTopY +f32 climb_getTopY(void){ return climbPoleTop[1]; } -void climbSet(f32 bottom[3], f32 top[3], f32 radius, u32 arg3){ - if( !(D_8037C58C > 0.0f) || D_8037C580[0] != bottom[0] +void climb_set(f32 bottom[3], f32 top[3], f32 radius, u32 arg3){ + if( !(climbRegrabWaitTime > 0.0f) || D_8037C580[0] != bottom[0] || D_8037C580[1] != bottom[1] || D_8037C580[2] != bottom[2]) { ml_vec3f_copy(climbPoleBottom, bottom); ml_vec3f_copy(climbPoleTop, top); climbRadius = radius; D_8037C591 = arg3; - D_8037C590 = 1; + isClimbingBool = 1; } } -void func_80298344(void){ //climbUpdateRegrab - D_8037C58C = ml_max_f(D_8037C58C - time_getDelta(), 0.0f); - if(D_8037C590 && ability_hasLearned(ABILITY_5_CLIMB)){ +void climb_regrab_update(void){ + climbRegrabWaitTime = ml_max_f(climbRegrabWaitTime - time_getDelta(), 0.0f); + if(isClimbingBool && ability_hasLearned(ABILITY_5_CLIMB)){ bs_checkInterrupt(BS_INTR_C_CLIMB); } - D_8037C590 = 0; + isClimbingBool = 0; } -void climbRelease(void){ //climbRelease - D_8037C590 = 0; +void climb_release(void){ + isClimbingBool = 0; ml_vec3f_copy(D_8037C580, climbPoleBottom); - D_8037C58C = 0.6f; + climbRegrabWaitTime = 0.6f; } diff --git a/src/core2/collision/climbsurface.c b/src/core2/collision/climbsurface.c index 1175fa005..f820a626f 100644 --- a/src/core2/collision/climbsurface.c +++ b/src/core2/collision/climbsurface.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C4B0.c #include #include "core1/core1.h" #include "functions.h" @@ -61,8 +62,8 @@ s32 D_8037C284; /* .code */ void func_80293440(void){ f32 sp34[3]; - f32 bottomY = climbGetBottomY(); - f32 topY = climbGetTopY(); + f32 bottomY = climb_getBottomY(); + f32 topY = climb_getTopY(); f32 sp28; f32 diff; @@ -72,7 +73,7 @@ void func_80293440(void){ if(D_8037C218[1] < bottomY) D_8037C218[1] = bottomY; - climbGetBottom(sp34); + climb_getBottom(sp34); func_80257F18(D_8037C218, sp34, &sp28); diff = mlDiffDegF(sp28, yaw_get()); diff = mlAbsF(diff); @@ -297,7 +298,7 @@ void func_80293F0C(void){ f32 sp38[3]; f32 sp2C[3]; - _player_getPosition(sp44); + playerPosition_get(sp44); if(gsworld_getMap() == MAP_34_RBB_ENGINE_ROOM && ml_vec3f_inside_box_f(sp44, -900.0f, -940.0f, 200.0f, 900.0f, 940.0f, 800.0f)){ func_8031C5FC(D_8037C200, 150.0f); } else{ @@ -316,7 +317,7 @@ void func_80293F0C(void){ case 1: case 3: case 4: - _player_getPosition(D_8037C218); + playerPosition_get(D_8037C218); playerPosition_func_80298504(D_8037C228); ml_vec3f_diff_copy(D_8037C238, D_8037C218, D_8037C228); if ((D_8037C274 == 3) && func_8031C594(D_8037C200) && (D_8037C218[1] > (floor_getYPosition(D_8037C200) - 70.0f))) { @@ -325,15 +326,15 @@ void func_80293F0C(void){ baphysics_set_vertical_velocity(1.0f); } func_80293668(); - player_setPosition(D_8037C218); + playerPosition_set(D_8037C218); break; case 5: - _player_getPosition(D_8037C218); + playerPosition_get(D_8037C218); playerPosition_func_80298504(D_8037C228); func_80293668(); func_80293440(); - player_setPosition(D_8037C218); + playerPosition_set(D_8037C218); break; case 2: @@ -364,7 +365,7 @@ void func_80293F0C(void){ } if (D_8037C27F) { - player_setPosition(sp44); + playerPosition_set(sp44); } D_8037C27A = 0; @@ -375,7 +376,7 @@ void func_80293F0C(void){ D_8037C280 = 0; } playerPosition_func_80298504(sp2C); - _player_getPosition(sp38); + playerPosition_get(sp38); ml_vec3f_diff_copy(D_8037C268, sp38, sp2C); if (D_8037C204) { collisionTri_copy(&D_8037C208, D_8037C204); @@ -412,7 +413,7 @@ void func_80294390(void) { } f32 func_80294404(void){ - return player_getYPosition() - floor_getXPosition(D_8037C200); + return playerPosition_getY() - floor_getXPosition(D_8037C200); } f32 func_80294438(void){ diff --git a/src/core2/collision/dispatch.c b/src/core2/collision/dispatch.c index bf7c6ddc4..a2a5470ca 100644 --- a/src/core2/collision/dispatch.c +++ b/src/core2/collision/dispatch.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_999A0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/collision/enemy.c b/src/core2/collision/enemy.c index 1d275daca..7c022dcc1 100644 --- a/src/core2/collision/enemy.c +++ b/src/core2/collision/enemy.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_45310.c #include #include "core1/core1.h" #include "functions.h" @@ -28,7 +29,7 @@ Actor *func_802CCA7C(ActorMarker *, Gfx **, Mtx **, Vtx **); void func_802CCC5C(Actor *this); /* .data */ -ActorInfo D_80367130 = { +ActorInfo chBuzzbomb = { MARKER_C2_BUZZBOMB, ACTOR_134_BUZZBOMB, ASSET_3ED_MODEL_BUZZBOMB, 0, NULL, func_802CCC5C, NULL, func_802CCA7C, @@ -434,7 +435,7 @@ void func_802CCC5C(Actor *this) { if (this->state == 1) { player_getPosition(sp8C); viewport_getPosition_vec3f(sp80); - viewport_getLookbk_vector(sp74); + viewport_getLookVector(sp74); sp5C[0] = this->position[0] - sp80[0]; sp5C[1] = this->position[1] - sp80[1]; sp5C[2] = this->position[2] - sp80[2]; diff --git a/src/core2/collision/filter.c b/src/core2/collision/filter.c index ffa350843..b74354afa 100644 --- a/src/core2/collision/filter.c +++ b/src/core2/collision/filter.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C9F00.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/collision/geometrybounds.c b/src/core2/collision/geometrybounds.c index 979a927bb..31e68f968 100644 --- a/src/core2/collision/geometrybounds.c +++ b/src/core2/collision/geometrybounds.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B6640.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/collision/hitboxdata.c b/src/core2/collision/hitboxdata.c index c28adc8b6..8f2993899 100644 --- a/src/core2/collision/hitboxdata.c +++ b/src/core2/collision/hitboxdata.c @@ -1,14 +1,31 @@ +// BanjoDecomp: core2/code_B62B0.c #include #include "functions.h" #include "variables.h" +#include "version.h" -//Struct5Cs = u16 packed bitwise as (aaaa bbcc cdde eeff) +//CollisionParams = u16 packed bitwise as (aaaa bbcc cdde eeff) typedef struct{ - u16 unk0; - u16 unk2; //Struct5Cs - u16 unk4[11]; //Struct5Cs -} Struct_core2_B62B0_0; + u16 markerId; + u16 collisionUnion; + union{ + u16 collisionTypes[11]; + struct{ + u16 activeClawSwipe; + u16 activeRoll; + u16 jumpOnTop; + u16 activeRatATat; + u16 activeBeakBarge; + u16 activeBeakBuster; + u16 activeBeakBomb; + u16 activeEggFiring; + u16 activeWonderwing; + u16 activeCrocBite; + u16 otherContact; + }; + }; +} CollisionTable; typedef struct{ s32 (*unk0)(ActorMarker *, ActorMarker *); @@ -16,194 +33,202 @@ typedef struct{ } Struct_core2_B62B0_1; /* .data */ -Struct_core2_B62B0_0 D_80370AC0[0xBB] = { - {MARKER_12A_TOPPER_THE_CARROT_A, 0x0000, {0x0904, 0x8504, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, - {MARKER_129_BAWL_THE_ONION_A, 0x0000, {0x0504, 0x0984, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, - {MARKER_128_COLLYWOBBLE_THE_CAULIFLOWER_A, 0x0000, {0x0000, 0x0000, 0x8404, 0x0984, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404}}, - {MARKER_135_QUARRIE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_1E6_TOPPER_THE_CARROT_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_1E7_BAWL_THE_ONION_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_1EA_GRUNTLING_RED, 0x0001, {0x0A08, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0984, 0x2020}}, - {MARKER_295_GRUNTLING_BLUE, 0x0001, {0x0A0C, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_1F1_GRUNTLING_BLACK, 0x0001, {0x0A10, 0x898C, 0x8100, 0x8988, 0x8A08, 0x8A08, 0x0A84, 0x098C, 0x0A04, 0x0000, 0x2020}}, - {0x1E0, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0004, 0x8000, 0x0000, 0x7000}}, - {0x005, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {0x004, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1020}}, - {0x003, 0x0000, {0x0914, 0x990C, 0x2020, 0x8908, 0x8908, 0x8908, 0x0A04, 0x0914, 0x0904, 0x0000, 0x4020}}, - {0x29E, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xA000, 0x0004, 0x8000, 0x0000, 0x8000}}, - {MARKER_7_CONGA, 0x0000, {0x0000, 0x0000, 0x3020, 0x9000, 0x0000, 0x0000, 0x0000, 0x0804, 0x9000, 0x0000, 0x3020}}, - {MARKER_13_SNIPPET, 0x0002, {0x0504, 0x7584, 0x8100, 0x7584, 0x7604, 0x0A04, 0x0A84, 0x0504, 0x0A04, 0x0000, 0x1020}}, - {0x16B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0904, 0x0A04, 0x0000, 0x1020}}, - {MARKER_DD_BLACK_SNIPPET, 0x0002, {0x060C, 0x7588, 0x8100, 0x7588, 0x7608, 0x8604, 0x0A84, 0x050C, 0x0A04, 0x0000, 0x1020}}, - {0x0DE, 0x0001, {0x0908, 0x0988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x090C, 0x0A04, 0x0000, 0x1020}}, - {0x015, 0x0001, {0x0A88, 0x7988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1424}}, - {0x065, 0x0804, {0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x090E, 0x0804, 0x0000, 0x5844}}, - {0x014, 0x0003, {0x3020, 0x3020, 0x3020, 0x9080, 0x9080, 0x9080, 0x0A84, 0x0914, 0x0904, 0x0000, 0x3020}}, - {MARKER_A5_NIPPER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x5020}}, - {0x16C, 0x0000, {0x0000, 0x0000, 0x0000, 0xB804, 0x0000, 0x0000, 0x0000, 0x0404, 0xB804, 0x0000, 0x5020}}, - {MARKER_A4_LOCKUP_SLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {MARKER_F6_LOCKUP_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {MARKER_F7_LOCKUP_FAST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {0x0029, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x3444}}, - {0x01CF, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x1424}}, - {0x01A6, 0x0000, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x0000, 0x0000, 0x3020, 0x3020}}, - {MARKER_1A7_CLANKER_WHIPCRACK, 0x0804, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, - {MARKER_69_CHUMP_FISH, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_173_CHUMP_FISH_2, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x4020}}, - {MARKER_C1_FLIBBIT_RED, 0x0000, {0x0A09, 0x0985, 0x8100, 0x0985, 0x0A05, 0x0A05, 0x0000, 0x0989, 0x0A05, 0x0986, 0x2020}}, - {MARKER_C5_FLIBBIT_YELLOW, 0x0000, {0x0A0D, 0x8989, 0x8100, 0x8989, 0x7A09, 0x7A09, 0x0000, 0x098D, 0x0A05, 0x0986, 0x2020}}, - {MARKER_C2_BUZZBOMB, 0x0000, {0x0805, 0x0805, 0x8000, 0x0805, 0x0805, 0x0805, 0x0000, 0x0805, 0x0805, 0x0806, 0x3020}}, - {MARKER_B1_SIR_SLUSH, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x9000, 0x0004, 0x8000, 0x0000, 0x7000}}, - {0x0287, 0x0001, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x8804, 0x0004, 0x8000, 0x0000, 0x7000}}, - {MARKER_205_TWINKLY_MUNCHER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0404, 0x0404, 0x0404, 0x0000, 0x0408, 0x0404, 0x0000, 0x0000}}, - {MARKER_245_XMAS_TREE_EGG_TOLL, 0x0000, {0x3004, 0x3004, 0x3004, 0x3004, 0x3004, 0x2004, 0x3004, 0x0000, 0x0000, 0x3004, 0x3004}}, - {MARKER_250_ICECUBE_A, 0x0000, {0x0A90, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0910, 0x0A04, 0x0984, 0x3104}}, - {MARKER_25F_ICECUBE_B, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0908, 0x0A04, 0x0984, 0x3104}}, - {0x00AD, 0x0001, {0x0A10, 0x998C, 0x0020, 0x9988, 0x8A08, 0x0A04, 0x0A84, 0x0914, 0x0A04, 0x0000, 0x5124}}, - {MARKER_253_SCARAB_BEETLE, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x3020}}, - {MARKER_219_MUMMUM, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x0588, 0x0A04, 0x0000, 0x2020}}, - {MARKER_298_MUMMUM_BALL, 0x0000, {0x7000, 0x8000, 0x7000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0004, 0x0A04, 0x0000, 0x2020}}, - {MARKER_218_LIMBO, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x050C, 0x0A04, 0x0000, 0x2020}}, - {MARKER_99_TEEHEE, 0x0001, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, - {MARKER_296_TEEHEE_PURPLE, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, - {MARKER_96_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, - {MARKER_297_GIANT_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, - {MARKER_127_BAT, 0x0001, {0x0804, 0x0804, 0x8100, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x1424}}, - {MARKER_254_PORTRAIT_CHOMPA_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3444}}, - {MARKER_1D1_PORTRAIT_CHOMPA_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x1424}}, - {MARKER_21A_SEAMAN_GRUBLIN, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_C9_FLOTSAM, 0x0001, {0x0808, 0x8808, 0x8000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0808, 0x0804, 0x0000, 0x3424}}, - {MARKER_1B7_BOOM_BOX, 0x0000, {0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x098C, 0x0404, 0x0804, 0x5000}}, - {MARKER_2E_GRIMLET, 0x0004, {0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x8000, 0x3000, 0x3004}}, - {MARKER_1A1_BOSS_BOOM_BOX_LARGEST, 0x0000, {0x8020, 0x8884, 0x8020, 0x8884, 0x9884, 0x9884, 0x0804, 0x0904, 0x0884, 0x0000, 0x4020}}, - {MARKER_1A2_BOSS_BOOM_BOX_LARGE, 0x0000, {0x8020, 0x8904, 0x8020, 0x8904, 0x9904, 0x9904, 0x0804, 0x0984, 0x0904, 0x0000, 0x4020}}, - {MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, 0x0000, {0x9020, 0x9984, 0x9020, 0x9984, 0x9984, 0x9984, 0x0804, 0x0A04, 0x0984, 0x0000, 0x3020}}, - {MARKER_1A4_BOSS_BOOM_BOX_SMALL, 0x0000, {0x9020, 0x9A04, 0x9020, 0x9A04, 0x9A04, 0x9A04, 0x0804, 0x0A84, 0x0A04, 0x0000, 0x3020}}, - {MARKER_185_RBB_REAR_PROPELLER, 0x5060, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5060}}, - {MARKER_191_ENGINE_ROOM_PROPELLOR_1, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, - {MARKER_192_ENGINE_ROOM_PROPELLOR_2, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, - {MARKER_193_ENGINE_ROOM_PROPELLOR_3, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, - {MARKER_1E2_GRUBLIN_HOOD, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_1C5_WHIPCRACK, 0x0001, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x080C, 0x0804, 0x0000, 0x3020}}, - {MARKER_1F9_SNARE_BEAR, 0x0000, {0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x0000, 0x0000, 0x0000, 0x2040}}, - {MARKER_1B2_CLUCKER_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x3444}}, - {MARKER_1D0_CLUCKER_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x1424}}, - {MARKER_1B4_EEYRIE_BABY, 0x8000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000}}, - {0x000E, 0x0001, {0x3000, 0x7504, 0x7080, 0x7504, 0x7584, 0x0804, 0x0804, 0x0488, 0x0804, 0x0000, 0x1020}}, - {0x01AC, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_256_FIRE_FX, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x2020, 0x2020}}, - {MARKER_C_ORANGE_PROJECTILE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2424}}, - {MARKER_DB_BURIED_TREASURE, 0x0000, {0x7000, 0x7000, 0x7000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x7000}}, - {MARKER_28_CLANKER_SAWBLADE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x2020}}, - {MARKER_4A_CC_KEY, 0x0404, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, - {MARKER_6E_PINK_EGG_LARGEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D7_PINK_EGG_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D9_PINK_EGG_SMALLEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D6_PINK_EGG_LARGE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D8_PINK_EGG_SMALL, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x006D, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x019B, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x019C, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x019D, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x019E, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x019F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x01A0, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_B9_FP_SNOWMAN_BUTTON,0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_124_BOGGY_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0097, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, - {0x0125, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, - {0x0126, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, - {MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_1FF_RED_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_20B_WOZZA, 0x7000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x7000}}, - {MARKER_20F_WOZZA_IN_CAVE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, - {0x0204, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0207, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0404}}, - {0x0206, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, - {MARKER_BC_GOBI_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {0x00BE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x0000}}, - {MARKER_BF_GOBI_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_C3_GOBI_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_252_LOGGO, 0x0000, {0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0000, 0x0004, 0x0004, 0x0004}}, - {MARKER_48_NAPPER, 0x0004, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0000, 0x8000, 0x0000, 0x8004}}, - {0x0132, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0130, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x012E, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x012C, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x01BF, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x7404, 0x0000, 0x0414, 0x7404, 0x0000, 0x0000}}, - {0x01B3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x01B0, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0814, 0x0000, 0x0000, 0x0000}}, - {MARKER_1AE_ZUBBA, 0x0000, {0x3004, 0x3004, 0x3004, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3004}}, - {0x0050, 0x0003, {0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000}}, - {0x009A, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x009E, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x009D, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x00E7, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x009C, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_EA_LIGHTHOUSE_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x022D, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x022E, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0235, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0163, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0239, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0236, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0237, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0238, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0263, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x017D, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x009F, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x00A0, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x00FF, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x0107, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x0108, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0109, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x080C, 0x0804, 0x0000, 0x0000}}, - {0x0118, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x0119, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x011A, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x011E, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x8804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x011F, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x7804, 0x7804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {0x0121, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x8804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0123, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x01F2, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x01F3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {0x0224, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xA000, 0x080C, 0x0000, 0x0000, 0x0000}}, - {0x0225, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0xA000, 0x080C, 0x8000, 0x0000, 0x0000}}, - {0x00A2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x8804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x01A9, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x080C, 0x0000, 0x0000, 0x0000}}, - {0x0195, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0196, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0197, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x002F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0194, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0186, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0183, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0184, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0164, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x0165, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {0x00E4, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, - {0x00E5, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, - {0x00E6, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, - {0x00B2, 0x0001, {0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {0x01A5, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001}}, - {0x01A6, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, - {0x016D, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, - {0x016E, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, - {0x016F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, - {0x0170, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, - {0x0171, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, - {0x0172, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, - {0x025C, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, - {0x025D, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, - {0x027A, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, - {0x027F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, - {0x025E, 0x0000, {0x4000, 0x4000, 0x4000, 0xA604, 0x4000, 0x4000, 0x4000, 0x0584, 0xA000, 0x0000, 0x4000}}, - {0x0260, 0x0000, {0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x0000, 0xA000, 0x0000, 0x5000}}, - {0x0281, 0x0000, {0x4080, 0x4080, 0x4080, 0xA604, 0x4080, 0x4080, 0x4080, 0x0584, 0xA200, 0x0000, 0x4080}}, - {0x0282, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0xA604, 0xA604, 0x0000, 0xA200, 0x0000, 0x4080}}, - {0x0283, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x0000, 0xA200, 0x0000, 0x4080}}, - {0x0284, 0x0000, {0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x0000, 0xB404, 0x5404, 0x5404}}, + +#define COLLISION_TABLE_SIZE 187 + +CollisionTable collision_table[COLLISION_TABLE_SIZE] = { + {MARKER_12A_TOPPER_THE_CARROT_A, 0x0000, {0x0904, 0x8504, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, + {MARKER_129_BAWL_THE_ONION_A, 0x0000, {0x0504, 0x0984, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, + {MARKER_128_COLLYWOBBLE_THE_CAULIFLOWER_A, 0x0000, {0x0000, 0x0000, 0x8404, 0x0984, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404}}, + {MARKER_135_QUARRIE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_1E6_TOPPER_THE_CARROT_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_1E7_BAWL_THE_ONION_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_1EA_GRUNTLING_RED, 0x0001, {0x0A08, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0984, 0x2020}}, + {MARKER_295_GRUNTLING_BLUE, 0x0001, {0x0A0C, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_1F1_GRUNTLING_BLACK, 0x0001, {0x0A10, 0x898C, 0x8100, 0x8988, 0x8A08, 0x8A08, 0x0A84, 0x098C, 0x0A04, 0x0000, 0x2020}}, + {MARKER_1E0_BRENTILDA, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0004, 0x8000, 0x0000, 0x7000}}, + {MARKER_5_GRUBLIN, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_4_TERMITE, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1020}}, + {MARKER_3_BIGBUTT, 0x0000, {0x0914, 0x990C, 0x2020, 0x8908, 0x8908, 0x8908, 0x0A04, 0x0914, 0x0904, 0x0000, 0x4020}}, + {MARKER_29E_BIGBUTT_KNOCKED_DOWN, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xA000, 0x0004, 0x8000, 0x0000, 0x8000}}, + {MARKER_7_CONGA, 0x0000, {0x0000, 0x0000, 0x3020, 0x9000, 0x0000, 0x0000, 0x0000, 0x0804, 0x9000, 0x0000, 0x3020}}, + {MARKER_13_SNIPPET, 0x0002, {0x0504, 0x7584, 0x8100, 0x7584, 0x7604, 0x0A04, 0x0A84, 0x0504, 0x0A04, 0x0000, 0x1020}}, + {MARKER_16B_SNIPPET_UPSIDEDOWN, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0904, 0x0A04, 0x0000, 0x1020}}, + {MARKER_DD_BLACK_SNIPPET, 0x0002, {0x060C, 0x7588, 0x8100, 0x7588, 0x7608, 0x8604, 0x0A84, 0x050C, 0x0A04, 0x0000, 0x1020}}, + {MARKER_DE_BLACK_SNIPPET_UPSIDEDOWN, 0x0001, {0x0908, 0x0988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x090C, 0x0A04, 0x0000, 0x1020}}, + {MARKER_15_CLAM, 0x0001, {0x0A88, 0x7988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1424}}, + {MARKER_65_SHRAPNEL, 0x0804, {0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x090E, 0x0804, 0x0000, 0x5844}}, + {MARKER_14_SNACKER, 0x0003, {0x3020, 0x3020, 0x3020, 0x9080, 0x9080, 0x9080, 0x0A84, 0x0914, 0x0904, 0x0000, 0x3020}}, + {MARKER_A5_NIPPER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x5020}}, + {MARKER_16C_NIPPER, 0x0000, {0x0000, 0x0000, 0x0000, 0xB804, 0x0000, 0x0000, 0x0000, 0x0404, 0xB804, 0x0000, 0x5020}}, + {MARKER_A4_LOCKUP_SLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {MARKER_F6_LOCKUP_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {MARKER_F7_LOCKUP_FAST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {MARKER_29_GRILLE_CHOMPA, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x3444}}, + {MARKER_1CF_GRILLE_CHOMPA_ATTACKING, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x1424}}, + {MARKER_1A6_BETA_VENT, 0x0000, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x0000, 0x0000, 0x3020, 0x3020}}, + {MARKER_1A7_CLANKER_WHIPCRACK, 0x0804, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, + {MARKER_69_CHUMP_FISH, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_173_CHUMP_FISH_2, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x4020}}, + {MARKER_C1_FLIBBIT_RED, 0x0000, {0x0A09, 0x0985, 0x8100, 0x0985, 0x0A05, 0x0A05, 0x0000, 0x0989, 0x0A05, 0x0986, 0x2020}}, + {MARKER_C5_FLIBBIT_YELLOW, 0x0000, {0x0A0D, 0x8989, 0x8100, 0x8989, 0x7A09, 0x7A09, 0x0000, 0x098D, 0x0A05, 0x0986, 0x2020}}, + {MARKER_C2_BUZZBOMB, 0x0000, {0x0805, 0x0805, 0x8000, 0x0805, 0x0805, 0x0805, 0x0000, 0x0805, 0x0805, 0x0806, 0x3020}}, + {MARKER_B1_SIR_SLUSH, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x9000, 0x0004, 0x8000, 0x0000, 0x7000}}, + {0x0287, 0x0001, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x8804, 0x0004, 0x8000, 0x0000, 0x7000}}, // snowman.c + {MARKER_205_TWINKLY_MUNCHER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0404, 0x0404, 0x0404, 0x0000, 0x0408, 0x0404, 0x0000, 0x0000}}, + {MARKER_245_XMAS_TREE_EGG_TOLL, 0x0000, {0x3004, 0x3004, 0x3004, 0x3004, 0x3004, 0x2004, 0x3004, 0x0000, 0x0000, 0x3004, 0x3004}}, + {MARKER_250_ICECUBE_A, 0x0000, {0x0A90, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0910, 0x0A04, 0x0984, 0x3104}}, + {MARKER_25F_ICECUBE_B, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0908, 0x0A04, 0x0984, 0x3104}}, + {0x00AD, 0x0001, {0x0A10, 0x998C, 0x0020, 0x9988, 0x8A08, 0x0A04, 0x0A84, 0x0914, 0x0A04, 0x0000, 0x5124}}, + {MARKER_253_SCARAB_BEETLE, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x3020}}, + {MARKER_219_MUMMUM, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x0588, 0x0A04, 0x0000, 0x2020}}, + {MARKER_298_MUMMUM_BALL, 0x0000, {0x7000, 0x8000, 0x7000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0004, 0x0A04, 0x0000, 0x2020}}, + {MARKER_218_LIMBO, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x050C, 0x0A04, 0x0000, 0x2020}}, + {MARKER_99_TEEHEE, 0x0001, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, + {MARKER_296_TEEHEE_PURPLE, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, + {MARKER_96_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, + {MARKER_297_GIANT_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, + {MARKER_127_BAT, 0x0001, {0x0804, 0x0804, 0x8100, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x1424}}, + {MARKER_254_PORTRAIT_CHOMPA_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3444}}, + {MARKER_1D1_PORTRAIT_CHOMPA_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x1424}}, + {MARKER_21A_SEAMAN_GRUBLIN, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_C9_FLOTSAM, 0x0001, {0x0808, 0x8808, 0x8000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0808, 0x0804, 0x0000, 0x3424}}, + {MARKER_1B7_BOOM_BOX, 0x0000, {0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x098C, 0x0404, 0x0804, 0x5000}}, + {MARKER_2E_GRIMLET, 0x0004, {0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x8000, 0x3000, 0x3004}}, + {MARKER_1A1_BOSS_BOOM_BOX_LARGEST, 0x0000, {0x8020, 0x8884, 0x8020, 0x8884, 0x9884, 0x9884, 0x0804, 0x0904, 0x0884, 0x0000, 0x4020}}, + {MARKER_1A2_BOSS_BOOM_BOX_LARGE, 0x0000, {0x8020, 0x8904, 0x8020, 0x8904, 0x9904, 0x9904, 0x0804, 0x0984, 0x0904, 0x0000, 0x4020}}, + {MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, 0x0000, {0x9020, 0x9984, 0x9020, 0x9984, 0x9984, 0x9984, 0x0804, 0x0A04, 0x0984, 0x0000, 0x3020}}, + {MARKER_1A4_BOSS_BOOM_BOX_SMALL, 0x0000, {0x9020, 0x9A04, 0x9020, 0x9A04, 0x9A04, 0x9A04, 0x0804, 0x0A84, 0x0A04, 0x0000, 0x3020}}, + {MARKER_185_RBB_REAR_PROPELLER, 0x5060, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5060}}, + {MARKER_191_ENGINE_ROOM_PROPELLOR_1, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, + {MARKER_192_ENGINE_ROOM_PROPELLOR_2, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, + {MARKER_193_ENGINE_ROOM_PROPELLOR_3, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, + {MARKER_1E2_GRUBLIN_HOOD, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_1C5_WHIPCRACK, 0x0001, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x080C, 0x0804, 0x0000, 0x3020}}, + {MARKER_1F9_SNARE_BEAR, 0x0000, {0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x0000, 0x0000, 0x0000, 0x2040}}, + {MARKER_1B2_CLUCKER_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x3444}}, + {MARKER_1D0_CLUCKER_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x1424}}, + {MARKER_1B4_EEYRIE_BABY, 0x8000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000}}, + {0x000E, 0x0001, {0x3000, 0x7504, 0x7080, 0x7504, 0x7584, 0x0804, 0x0804, 0x0488, 0x0804, 0x0000, 0x1020}}, + {MARKER_1AC_ZUBBA_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_256_FIRE_FX, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x2020, 0x2020}}, + {MARKER_C_ORANGE_PROJECTILE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2424}}, + {MARKER_DB_BURIED_TREASURE, 0x0000, {0x7000, 0x7000, 0x7000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x7000}}, + {MARKER_28_CLANKER_SAWBLADE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x2020}}, + {MARKER_4A_CC_KEY, 0x0404, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, + {MARKER_6E_PINK_EGG_LARGEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D7_PINK_EGG_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D9_PINK_EGG_SMALLEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D6_PINK_EGG_LARGE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D8_PINK_EGG_SMALL, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_6D_TANKTUP_LEG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_19B_CHOIR_TURTLE_YELLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_19C_CHOIR_TURTLE_CYAN, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_19D_CHOIR_TURTLE_BLUE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_19E_CHOIR_TURTLE_RED, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_19F_CHOIR_TURTLE_PINK, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_1A0_CHOIR_TURTLE_PURPLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_B9_FP_SNOWMAN_BUTTON, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_124_BOGGY_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_97_BOGGY_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, + {MARKER_125_BOGGY_RACE_FLAG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, + {MARKER_126_BOGGY_RACE_FLAG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, + {MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_1FF_RED_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_20B_WOZZA, 0x7000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x7000}}, + {MARKER_20F_WOZZA_IN_CAVE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, + {MARKER_204_TWINKLY_BOX, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_207_XMAS_TREE_STAR, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0404}}, + {MARKER_206_XMAS_TREE_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, + {MARKER_BC_GOBI_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_BE_GOBI_ROCK, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x0000}}, + {MARKER_BF_GOBI_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_C3_GOBI_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_252_LOGGO, 0x0000, {0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0000, 0x0004, 0x0004, 0x0004}}, + {MARKER_48_NAPPER, 0x0004, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0000, 0x8000, 0x0000, 0x8004}}, + {MARKER_132_CCW_SPRING_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_130_CCW_SUMMER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_12E_CCW_AUTUMN_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_12C_CCW_WINTER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_1BF_GNAWTY_BOULDER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x7404, 0x0000, 0x0414, 0x7404, 0x0000, 0x0000}}, + {MARKER_1B3_EAGLE_EGG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_1B0_CCW_BEANSTALK, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0814, 0x0000, 0x0000, 0x0000}}, + {MARKER_1AE_ZUBBA, 0x0000, {0x3004, 0x3004, 0x3004, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3004}}, + {MARKER_50_BEEHIVE, 0x0003, {0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000}}, + {MARKER_9A_1881_BARREL_TOP, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_9E_CELLAR_HATCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_9D_MANSION_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_E7_DINING_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_9C_SHACK_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_EA_LIGHTHOUSE_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_22D_SHIP_SHADOW_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_22E_SHIP_SUNNY_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_235_CRACKED_SKYLIGHT, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_163_CRYPT_COFFIN_LID, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_239_CCW_UNKNOWN_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_236_CCW_UNKNOWN_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_237_CCW_AUTUMN_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_238_CCW_WINTER_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_263_CCW_WHIPCRACK_ROOM_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_17D_IRON_GATE_NO_LOCK, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_9F_CHURCH_GATE_LEFT_LOCK, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_107_ENGINE_ROOM_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_108_CABIN_CLOSET_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_109_BREAKABLE_BRICK_WALL, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x080C, 0x0804, 0x0000, 0x0000}}, + {MARKER_118_GRATE_TO_LEVEL_3_WATER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_119_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_11A_GRATE_TO_RBB_PUZZLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_11E_ICE_BALL_TO_CHEATO, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x8804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_11F_RAREWARE_BOX, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x7804, 0x7804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {MARKER_121_GLASS_EYE, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x8804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_123_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_1F2_WIDE_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_1F3_TALL_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_224_BREAKABLE_FLOOR_COBWEB, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xA000, 0x080C, 0x0000, 0x0000, 0x0000}}, + {MARKER_225_BREAKABLE_WALL_COBWEB, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0xA000, 0x080C, 0x8000, 0x0000, 0x0000}}, + {MARKER_A2_CHURCH_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x8804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_1A9_CC_BREAKABLE_GRATES, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x080C, 0x0000, 0x0000, 0x0000}}, + {MARKER_195_WHISTLE_SWITCH_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_196_WHISTLE_SWITCH_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_197_WHISTLE_SWITCH_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_2F_ANCHOR_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_194_RBB_GREY_PROPELLER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_186_RBB_GREEN_PROPELLER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_183_RBB_CAGE_UP_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_184_RBB_TNT_DOWN_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_164_GL_GRUNTY_FLOOR_PICTURE_EYE_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_165_GL_GRUNTY_FLOOR_PICTURE_EYE_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_E4_CS_BK_SLEEPING, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, + {MARKER_E5_CS_BK_GAMEBOY, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, + {MARKER_E6_CS_BK_COOKING, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, + {MARKER_B2_SNOWBALL, 0x0001, {0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {MARKER_1A5_SANDYBUTT_EGG_TOLL, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001}}, + {MARKER_1A6_BETA_VENT, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, + {MARKER_16D_CHEATO_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, + {MARKER_16E_CHEATO_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, + {MARKER_16F_CHEATO_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, + {MARKER_170_BLUE_EGG_REFILL_PILLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, + {MARKER_171_RED_FEATHER_REFILL_PILLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, + {MARKER_172_GOLD_FEATHER_REFILL_PILLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, + {MARKER_25C_GRUNTY_SPELL_FIREBALL, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, + {MARKER_25D_GREEN_BLAST, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, + {MARKER_27A_JINJO_STATUE_BASE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, + {MARKER_27F_JINJONATOR_STATUE_BASE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, + {MARKER_25E_GRUNTILDA_FINAL_BOSS_VULNERABLE, 0x0000, {0x4000, 0x4000, 0x4000, 0xA604, 0x4000, 0x4000, 0x4000, 0x0584, 0xA000, 0x0000, 0x4000}}, + {MARKER_260_GRUNTY_PHASE_1_2_MOVING, 0x0000, {0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x0000, 0xA000, 0x0000, 0x5000}}, + {MARKER_281_GRUNTY_PHASE_2_VULNERABLE, 0x0000, {0x4080, 0x4080, 0x4080, 0xA604, 0x4080, 0x4080, 0x4080, 0x0584, 0xA200, 0x0000, 0x4080}}, + {MARKER_282_GRUNTY_PHASE_3_FLIGHT, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0xA604, 0xA604, 0x0000, 0xA200, 0x0000, 0x4080}}, +#if VERSION == VERSION_USA_1_0 + {MARKER_283_GRUNTY_PHASE_4_5_INVULNERABLE, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x0000, 0xA200, 0x0000, 0x4080}}, + {MARKER_284_GRUNTY_SPELL_BARRIER, 0x0000, {0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x0000, 0xB404, 0x5404, 0x5404}}, +#elif VERSION == VERSION_PAL + {MARKER_283_GRUNTY_PHASE_4_5_INVULNERABLE, 0x0000, {0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x0004, 0xA000, 0x0000, 0x4000}}, + {MARKER_284_GRUNTY_SPELL_BARRIER, 0x0000, {0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x0004, 0xB404, 0x5404, 0x5404}}, +#endif }; s32 func_8033D240(ActorMarker *arg0, ActorMarker *arg1); @@ -217,10 +242,10 @@ Struct_core2_B62B0_1 D_80371DC0[11] = { {func_8033D2A8, HITBOX_2_BEAK_BARGE}, {func_8033D2A8, HITBOX_1_BEAK_BUSTER}, {func_8033D2A8, HITBOX_3_BEAK_BOMB}, - {func_8033D240, 1}, + {func_8033D240, 1}, // Egg Firing {func_8033D2A8, HITBOX_6_WONDERWING}, {func_8033D2A8, HITBOX_9_CROC_BITE}, - {func_8033D240, 0} + {func_8033D240, 0} // Other Contact }; /* .bss */ @@ -249,49 +274,53 @@ void func_8033D2F4(void) { s32 var_a0; bool var_a1; s32 var_v1; - s32 var_v0 = 0xBB; + s32 var_v0 = COLLISION_TABLE_SIZE; for(var_v1 = 0; var_v1 < 0x2A9; var_v1++) { - for(((var_a0 = 0), (var_a1 = false), (D_80383F10[var_v1] = -1)); (var_a0 < var_v0) && !var_a1; var_a0++){ - if (var_v1 == D_80370AC0[var_a0].unk0) { + for(((var_a0 = 0), (var_a1 = FALSE), (D_80383F10[var_v1] = -1)); (var_a0 < var_v0) && !var_a1; var_a0++){ + if (var_v1 == collision_table[var_a0].markerId) { D_80383F10[var_v1] = var_a0; - var_a1 = true; + var_a1 = TRUE; } } } for(var_a0 = 0; var_a0 < var_v0; var_a0++) { for(var_v1 = 0; var_v1 < 10; var_v1++){ - D_80370AC0[var_a0].unk4[var_v1] |= D_80370AC0[var_a0].unk2; + collision_table[var_a0].collisionTypes[var_v1] |= collision_table[var_a0].collisionUnion; } } } bool func_8033D410(ActorMarker *arg0, ActorMarker *arg1) { s32 var_s2; - s32 sp38; + s32 collision_index; s16 temp_t0; s32 temp_s0; - sp38 = D_80383F10[arg1->id]; - if (sp38 == -1) { - return false; + collision_index = D_80383F10[arg1->id]; + if (collision_index == -1) { + return FALSE; } for(var_s2 = 0; var_s2 < 11; var_s2++){ - if ((D_80370AC0[sp38].unk4[var_s2] != 0) && (D_80371DC0[var_s2].unk0(arg0, arg1) == D_80371DC0[var_s2].unk4)) { - func_80330078(arg1, arg0, D_80370AC0[sp38].unk4 + var_s2); - func_80330078(arg0, arg1, D_80370AC0[sp38].unk4 + var_s2); + if ((collision_table[collision_index].collisionTypes[var_s2] != 0) && (D_80371DC0[var_s2].unk0(arg0, arg1) == D_80371DC0[var_s2].unk4)) { + func_80330078(arg1, arg0, collision_table[collision_index].collisionTypes + var_s2); + func_80330078(arg0, arg1, collision_table[collision_index].collisionTypes + var_s2); break; } } - return true; + return TRUE; } s32 collision_getPlayerInteraction(CollisionParams *arg0){ + // Player Bounce vs Player Knockback + // Includes the distance the player is sent return arg0->playerInteraction; } enum marker_collision_func_type_e collision_getNextState(CollisionParams *arg0){ + // 01 -> Alternate State + // 10 -> Death return arg0->nextState; } @@ -304,9 +333,16 @@ s32 collision_getDamageToPlayer(CollisionParams *arg0){ } s32 collision_getHitsToTrigger(CollisionParams *arg0){ + // Enemies have health + // 1 divided by hits to trigger = % of health the enemy loses return arg0->hitsToTrigger; } s32 collision_getDropBundleNum(CollisionParams *arg0){ + // By default, + // 0 is nothing + // 1 is one honeycomb + // 2 is two honeycombs + // 3 is three honeycombs return arg0->dropBundleNum; } diff --git a/src/core2/collision/polydetect.c b/src/core2/collision/polydetect.c index 9d3869777..1903fd150 100644 --- a/src/core2/collision/polydetect.c +++ b/src/core2/collision/polydetect.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B9090.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/collision/raycast.c b/src/core2/collision/raycast.c index 3192cbe9a..c4422b518 100644 --- a/src/core2/collision/raycast.c +++ b/src/core2/collision/raycast.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_94A20.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/collision/raycastmap.c b/src/core2/collision/scarabbeetle.c similarity index 97% rename from src/core2/collision/raycastmap.c rename to src/core2/collision/scarabbeetle.c index d98f84bef..d0bfcebd6 100644 --- a/src/core2/collision/raycastmap.c +++ b/src/core2/collision/scarabbeetle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/scarabbeetle.c #include #include "functions.h" #include "variables.h" @@ -5,8 +6,8 @@ extern BKCollisionTriangle *func_80320DB0(f32[3], f32, f32[3], u32); /* .h */ -Actor *func_80358344(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_80358684(Actor *this); +Actor *chScarabBeetle_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chScarabBeetle_update(Actor *this); typedef struct { u8 sfxsourceIdx; @@ -24,14 +25,14 @@ typedef struct { }ActorLocal_core2_D0CA0; /* .data */ -ActorInfo D_803728A0 = { +// Scabby +ActorInfo chScarabBeetle = { MARKER_253_SCARAB_BEETLE, ACTOR_380_SCARAB_BEETLE, ASSET_51B_MODEL_SCARAB_BEETLE, 0, NULL, - func_80358684, NULL, func_80358344, + chScarabBeetle_update, NULL, chScarabBeetle_draw, 0, 0, 1.0f, 0 }; - /* .code */ bool func_80357C30(Actor *this) { ActorLocal_core2_D0CA0 *local; @@ -195,7 +196,7 @@ void func_80358304(ActorMarker *marker, ActorMarker *other_marker){ } } -Actor *func_80358344(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { +Actor *chScarabBeetle_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { Actor *this; ActorLocal_core2_D0CA0 *local; @@ -266,7 +267,7 @@ void func_80358610(Actor *this) { func_80358524(this->position, 4, 0x520); } -void func_80358684(Actor *this) { +void chScarabBeetle_update(Actor *this) { f32 sp94[3]; ActorLocal_core2_D0CA0 *local; //sp90 s32 next_state; //sp8C diff --git a/src/core2/collision/spherecast.c b/src/core2/collision/spherecast.c index 0522afcc4..6c9ce5982 100644 --- a/src/core2/collision/spherecast.c +++ b/src/core2/collision/spherecast.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_A4D00.c #include "functions.h" #include "structs.h" #include "variables.h" diff --git a/src/core2/collision/tricheck.c b/src/core2/collision/tricheck.c index 37f171478..51a539d4a 100644 --- a/src/core2/collision/tricheck.c +++ b/src/core2/collision/tricheck.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_BDCC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/crc_bootvalidation.c b/src/core2/crc_bootvalidation.c index 73c64a4ee..079c30546 100644 --- a/src/core2/crc_bootvalidation.c +++ b/src/core2/crc_bootvalidation.c @@ -1,92 +1,90 @@ +// BanjoDecomp: core2/code_CF5F0.c #include -#include "functions.h" -#include "variables.h" +#include "bool.h" +#include "checksums.h" +#include "enums.h" -//THIS VALUE -#ifndef CORE2_CODE_CRC2 - #define CORE2_CODE_CRC2 0x9E44C2DC -#endif - -// bk_boot segment start (skipping entry function) -extern u8 boot_bk_boot_ROM_START[]; -// bk_boot segment end -extern u8 boot_bk_boot_ROM_END[]; -extern u8 crc_ROM_START[]; +extern u8 boot_bk_boot_ROM_START[]; // bk_boot segment start (skipping entry function) +extern u8 boot_bk_boot_ROM_END[]; // bk_boot segment end -// bk_boot segment crc next word s32 D_803727F0 = 0; -s32 D_803727F4 = CORE2_CODE_CRC2; +s32 D_803727F4 = VER_SELECT(0x9E44C2DC, 0xC1A6FD58, 0, 0); // CORE2_TEXT_CRC2 s32 D_803727F8 = 0; -s32 D_803727FC = 0; -// bk_boot segment crc values -s32 D_80372800 = 0; -s32 D_80372804 = 0; +s32 sBootROMOffset = 0; +u32 sCalculatedChecksum1 = 0; +u32 sCalculatedChecksum2 = 0; +s32 sBootROMRemainingBytes = 0; -// bk_boot segment crc remaining words -s32 D_80372808 = 0; - -// init bk_boot crc -void codeCF5F0_initChecksumsVars(void) { +void codeCF5F0_reset(void) { #if ANTI_TAMPER - D_803727FC = (s32) boot_bk_boot_ROM_START; - D_80372800 = 0; - D_80372804 = -1; - D_80372808 = (s32) (boot_bk_boot_ROM_END - boot_bk_boot_ROM_START); + sBootROMOffset = (s32) boot_bk_boot_ROM_START; + sCalculatedChecksum1 = 0; + sCalculatedChecksum2 = -1; + sBootROMRemainingBytes = (s32) (boot_bk_boot_ROM_END - boot_bk_boot_ROM_START); #endif } -// advance bk_boot crc by one word -s32 codeCF5F0_areChecksumsValid(void) { - // Lighthouse TODO what should this actually return? +bool codeCF5F0_validate(void) { #if ANTI_TAMPER - u32 crc1; - u32 crc2; - u8 romBytes[4]; - u8 curByte; - - if (D_803727FC != 0) { - if (D_80372808 != 0) { - crc1 = D_80372800; - crc2 = D_80372804; - osPiReadIo(D_803727FC, (u32*)romBytes); - curByte = romBytes[0]; - crc1 += curByte; - crc2 ^= curByte << (crc1 & 0x17); - curByte = romBytes[1]; - crc1 += curByte; - crc2 ^= curByte << (crc1 & 0x17); - curByte = romBytes[2]; - crc1 += curByte; - crc2 ^= curByte << (crc1 & 0x17); - curByte = romBytes[3]; - crc1 += curByte; - crc2 ^= curByte << (crc1 & 0x17); - D_80372800 = crc1; - D_80372804 = crc2; - D_803727FC = D_803727FC + 4; - D_80372808 = D_80372808 - 4; + u32 checksum1, checksum2; + u8 rom_bytes[4]; + u8 cur_byte; + + if (sBootROMOffset != 0) { + if (sBootROMRemainingBytes != 0) { + checksum1 = sCalculatedChecksum1; + checksum2 = sCalculatedChecksum2; + + osPiReadIo(sBootROMOffset, (u32 *) rom_bytes); + + cur_byte = rom_bytes[0]; + checksum1 += cur_byte; + checksum2 ^= cur_byte << (checksum1 & 0x17); + + cur_byte = rom_bytes[1]; + checksum1 += cur_byte; + checksum2 ^= cur_byte << (checksum1 & 0x17); + + cur_byte = rom_bytes[2]; + checksum1 += cur_byte; + checksum2 ^= cur_byte << (checksum1 & 0x17); + + cur_byte = rom_bytes[3]; + checksum1 += cur_byte; + checksum2 ^= cur_byte << (checksum1 & 0x17); + + sCalculatedChecksum1 = checksum1; + sCalculatedChecksum2 = checksum2; + + sBootROMOffset += 4; + sBootROMRemainingBytes -= 4; } else { - D_803727FC = 0; - osPiReadIo((u32)crc_ROM_START + 0, &crc1); - if (crc1 != D_80372800) - return 0; - osPiReadIo((u32)crc_ROM_START + 4, &crc2); - if (crc2 != D_80372804) - return 0; + sBootROMOffset = 0; + + osPiReadIo((u32) crc_ROM_START + CRC_BOOT_TEXT_CHECKSUM1, &checksum1); + if (checksum1 != sCalculatedChecksum1) + return FALSE; + + osPiReadIo((u32) crc_ROM_START + CRC_BOOT_TEXT_CHECKSUM2, &checksum2); + if (checksum2 != sCalculatedChecksum2) + return FALSE; } } #endif - return 1; + + return TRUE; } -void func_80356714(void) { - codeCF5F0_initChecksumsVars(); +void codeCF5F0_init(void) { + codeCF5F0_reset(); } -void codeCF5F0_forgetAllAbilitiesExceptClawSwipeIfChecksumsFail(void) { - codeCF5F0_areChecksumsValid(); - if (codeCF5F0_areChecksumsValid() == 0) { - ability_setAllLearned(0x10); +void codeCF5F0_triggerAntiTamperMeasurement(void) { +#if ANTI_TAMPER + codeCF5F0_validate(); + if (!codeCF5F0_validate()) { + ability_setAllLearned(1 << ABILITY_4_CLAW_SWIPE); } +#endif } diff --git a/src/core2/demo_input.c b/src/core2/demo.c similarity index 91% rename from src/core2/demo_input.c rename to src/core2/demo.c index 9b089624d..c03c7dbd7 100644 --- a/src/core2/demo_input.c +++ b/src/core2/demo.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/demo.c #include #include "functions.h" #include "variables.h" @@ -41,8 +42,11 @@ s32 func_80349EC0(s32 arg0){ } int demo_readInput(OSContPad* arg0, s32* arg1){ - int not_eof = D_803860D8 < D_803860DC; - DemoInput *input_ptr = not_eof ? &D_803860D0[D_803860D8++] : &D_80371EF0; + s32 idx = D_803860D8; + int not_eof = (idx + 1) < D_803860DC; + DemoInput *input_ptr = not_eof ? &D_803860D0[idx] : &D_80371EF0; + if (idx < D_803860DC) + D_803860D8 = idx + 1; #if 0 DemoInput *input_ptr = &D_803860D0[D_803860D8++]; int not_eof = D_803860D8 < D_803860DC; diff --git a/src/core2/dialog/binload.c b/src/core2/dialog/binload.c index b5919ff20..192ee134b 100644 --- a/src/core2/dialog/binload.c +++ b/src/core2/dialog/binload.c @@ -1,10 +1,10 @@ +// BanjoDecomp: core2/code_94620.c #include #include "functions.h" #include "variables.h" #include "structs.h" #include "port/Patches/Patches.h" - -extern int ResourceMgr_GetDialogLanguageCount(void); +#include "port/ResourceHelpers.h" /* .bss */ s32 D_80383150; @@ -19,6 +19,7 @@ s32 code94620_func_8031B5B0(void) { return s_dialogBin.unk0; } +// s32 func_8031B5BC(void){ return VER_SELECT(1, 3, 0, 0); } s32 func_8031B5BC(void){ return ResourceMgr_GetDialogLanguageCount(); } void func_8031B5C4(s32 arg0) { diff --git a/src/core2/dialog/progressDialog.c b/src/core2/dialog/progressDialog.c new file mode 100644 index 000000000..e81c5cd4c --- /dev/null +++ b/src/core2/dialog/progressDialog.c @@ -0,0 +1,135 @@ +// BanjoDecomp: core2/progressDialog.c +#include +#include "functions.h" +#include "variables.h" + +typedef KEY_VALUE_PAIR(s16, s16) MapProgressFlagToDialogID; + +/* Mapping for file progess flags to Dialog IDs */ +MapProgressFlagToDialogID fileProgressDialogMap[] = { + { FILEPROG_AB_SWIM_OILY_WATER, VER_SELECT(ASSET_BA1_DIALOG_GRUNTY_TOUCH_OILY_WATER, 0x976, 0, 0)}, + { FILEPROG_AC_DIVE_OILY_WATER, VER_SELECT(ASSET_BA2_DIALOG_GRUNTY_DIVE_OILY_WATER, 0x977, 0, 0)}, + { FILEPROG_AA_HAS_TOUCHED_CCW_BRAMBLE_FIELD, VER_SELECT(ASSET_CE6_DIALOG_GRUNTY_TOUCH_BRAMBLE, 0x9FB, 0, 0)}, + { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, VER_SELECT(ASSET_C85_DIALOG_PIRANHA_TOUCH_SWAMP_WATER, 0x9C8, 0, 0)}, + { FILEPROG_A9_HAS_TOUCHED_RBB_OVEN, VER_SELECT(ASSET_BA0_DIALOG_GRUNTY_TOUCH_OVEN, 0x975, 0, 0)}, + { FILEPROG_10_HAS_TOUCHED_SAND_EEL_SAND, VER_SELECT(ASSET_A7E_DIALOG_SAND_EELS_MEET, 0x93A, 0, 0)}, + { FILEPROG_14_HAS_TOUCHED_FP_ICY_WATER, VER_SELECT(ASSET_C11_DIALOG_TOUCH_ICY_WATER, 0x98B, 0, 0)}, + { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, VER_SELECT(ASSET_C85_DIALOG_PIRANHA_TOUCH_SWAMP_WATER, 0x9C8, 0, 0)}, + { FILEPROG_86_HAS_TOUCHED_MMM_THORN_HEDGE, VER_SELECT(ASSET_AE1_DIALOG_GRUNTY_HEDGE_THORNS, 0x953, 0, 0)}, + { FILEPROG_DD_HAS_TOUCHED_CCW_ICY_WATER, VER_SELECT(ASSET_CE7_DIALOG_GRUNTY_TOUCH_ICY_WATER, 0x9FC, 0, 0)}, + { FILEPROG_3_MUSIC_NOTE_TEXT, VER_SELECT(ASSET_D9C_DIALOG_MUSIC_NOTE_MEET, 0xA1A, 0, 0)}, + { FILEPROG_4_MUMBO_TOKEN_TEXT, VER_SELECT(ASSET_D9D_DIALOG_MUMBO_TOKEN_MEET, 0xA1B, 0, 0)}, + { FILEPROG_5_BLUE_EGG_TEXT, VER_SELECT(ASSET_D9E_DIALOG_BLUE_EGG_MEET, 0xA1C, 0, 0)}, + { FILEPROG_6_RED_FEATHER_TEXT, VER_SELECT(ASSET_D9F_DIALOG_RED_FEATHER_MEET, 0xA1D, 0, 0)}, + { FILEPROG_7_GOLD_FEATHER_TEXT, VER_SELECT(ASSET_DA0_DIALOG_GOLD_FEATHER_MEET, 0xA1E, 0, 0)}, + { FILEPROG_8_ORANGE_TEXT, VER_SELECT(ASSET_B46_DIALOG_CONGA_COLLECT_ORANGE, 0x964, 0, 0)}, + { FILEPROG_9_GOLD_BULLION_TEXT, VER_SELECT(ASSET_A21_DIALOG_BLUBBER_MEET, 0x921, 0, 0)}, + { FILEPROG_A_HONEYCOMB_TEXT, VER_SELECT(ASSET_DA1_DIALOG_HONEYCOMB_MEET, 0xA1F, 0, 0)}, + { FILEPROG_B_EMPTY_HONEYCOMB_TEXT, VER_SELECT(ASSET_DA2_DIALOG_EMPTY_HONEYCOMB_MEET, 0xA20, 0, 0)}, + { FILEPROG_C_EXTRA_LIFE_TEXT, VER_SELECT(ASSET_DA3_DIALOG_EXTRA_LIFE_MEET, 0xA21, 0, 0)}, + { FILEPROG_BE_CHEATO_BLUEEGGS, VER_SELECT(ASSET_FA8_EGG_CHEAT_ACTIVATION, 0xB0E, 0, 0)}, + { FILEPROG_BF_CHEATO_REDFEATHERS, VER_SELECT(ASSET_FA9_RED_FEATHER_CHEAT_ACTIVATION, 0xB0F, 0, 0)}, + { FILEPROG_C0_CHEATO_GOLDFEATHERS, VER_SELECT(ASSET_FAA_GOLD_FEATHER_CHEAT_ACTIVATION, 0xB10, 0, 0)}, + { FILEPROG_95_UNUSED_UNKNOWN_ITEM_COLLECT, VER_SELECT(ASSET_B50_DIALOG_BOTTLES_BACKPACK_STORE, 0x96E, 0, 0)}, + { FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT, VER_SELECT(ASSET_F7B_DIALOG_BOTTLES_JIGSAW_PICTURE_MEET, 0xAE1, 0, 0)}, + { -1, -1 } +}; + +/* This progress IDs are not saved in the save file, like when Banjo goes near a Note door which requires more notes than the Banjo has. */ +/* Triggers a dialog every time after the game restarts. */ +MapProgressFlagToDialogID gVolatileFlagDialogMap[] = { + { VOLATILE_FLAG_9E_BETA_OILY_SCUM, VER_SELECT(ASSET_BA3_DIALOG_GRUNTY_TOUCH_OILY_WATER_2, 0x978, 0, 0)}, // (unused) + { VOLATILE_FLAG_9F_BETA_DIVE_IN_ICY_WATER, VER_SELECT(ASSET_CE8_DIALOG_GRUNTY_TOUCH_ICY_WATER_2, 0x9FD, 0, 0)}, // (unused) + { VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT, VER_SELECT(ASSET_1032_DIALOG_FF_FIRST_ANSWER_CORRECT, 0xB3A, 0, 0)}, + { VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT, VER_SELECT(ASSET_1033_DIALOG_FF_NEXT_ANSWER_CORRECT, 0xB3B, 0, 0)}, + { VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT, VER_SELECT(ASSET_1034_DIALOG_FF_GRUNTY_ANSWER_CORRECT, 0xB3C, 0, 0)}, + { VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG, VER_SELECT(ASSET_1035_DIALOG_FF_FIRST_ANSWER_WRONG, 0xB3D, 0, 0)}, + { VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG, VER_SELECT(ASSET_1036_DIALOG_FF_NEXT_ANSWER_WRONG, 0xB3E, 0, 0)}, + { VOLATILE_FLAG_A5_FF_UNUSED, VER_SELECT(ASSET_1037_DIALOG_FF_CHOICE_IS_YOURS_UNUSED, 0xB3F, 0, 0)}, + { VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB, VER_SELECT(ASSET_1038_DIALOG_FF_GET_HONEYCOMB, 0xB40, 0, 0)}, + { VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE, VER_SELECT(ASSET_1039_DIALOG_FF_GET_EXTRA_LIFE, 0xB41, 0, 0)}, + { VOLATILE_FLAG_A8_FF_GOT_JOKER, VER_SELECT(ASSET_103A_DIALOG_FF_GET_JOKER, 0xB42, 0, 0)}, + { VOLATILE_FLAG_A9_FF_USED_JOKER, VER_SELECT(ASSET_103B_DIALOG_FF_USE_JOKER, 0xB43, 0, 0)}, + { VOLATILE_FLAG_AA_FF_LOW_HEALTH, VER_SELECT(ASSET_103C_DIALOG_FF_LOW_HEALTH, 0xB44, 0, 0)}, + { VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL, VER_SELECT(ASSET_103D_DIALOG_FF_LOW_HEALTH_ON_SKULL, 0xB45, 0, 0)}, + { VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED, VER_SELECT(ASSET_A88_DIALOG_GRUNTY_WATER_PYRAMID_DOOR_MISS, 0x944, 0, 0)}, + { VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED, VER_SELECT(ASSET_AE2_DIALOG_GRUNTY_CHURCH_DOOR_MISS, 0x954, 0, 0)}, + { VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED, VER_SELECT(ASSET_C8B_DIALOG_GRUNTY_LONG_SWITCH_MISS, 0x9CE, 0, 0)}, + { VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED, VER_SELECT(ASSET_C8C_DIALOG_GRUNTY_SHORT_SWITCH_MISS, 0x9CF, 0, 0)}, + { VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES, VER_SELECT(ASSET_FBD_DIALOG_GRUNTY_NOT_ENOUGH_NOTES, 0xB23, 0, 0)}, + { VOLATILE_FLAG_C2_NOBONUS_TEXT, VER_SELECT(ASSET_E36_DIALOG_BOTTLES_NO_BONUS, 0xA78, 0, 0)}, + { VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT, VER_SELECT(ASSET_DB6_DIALOG_MUMBO_WISHYWASHY, 0xA34, 0, 0)}, + { -1, -1 } +}; + +static s32 __findIndex(MapProgressFlagToDialogID *map, s32 key) { + s32 i = 0; + + while (map[i].key >= 0) { + if (key == map[i].key) { + return i; + } + i++; + } + + return -1; +} + +/* Checks for a specific file progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ +s32 showProgressFlagDialog(enum file_progress_e progress_flag, s32 arg1) { + s32 index; + + if (fileProgressFlag_get(progress_flag) != 0) { + return 0; + } else { + index = __findIndex(fileProgressDialogMap, progress_flag); + if (index != -1) { + if (gcdialog_showDialog(fileProgressDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { + fileProgressFlag_set(progress_flag, 1); + } + return fileProgressFlag_get(progress_flag); + } + return 0; + } +} + +void progressDialog_showDialogMaskZero(enum file_progress_e progress_flag){ + showProgressFlagDialog(progress_flag, 0); +} + +void progressDialog_showDialogMaskFour(enum file_progress_e progress_flag) { + showProgressFlagDialog(progress_flag, 4); +} + +/* Checks for a specific "volatile" progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ +s32 progressDialog_setAndTriggerDialog(enum volatile_flags_e id, s32 arg1) { + s32 index; + + if (volatileFlag_get(id) != 0) { + return 0; + } else { + index = __findIndex(gVolatileFlagDialogMap, id); + if (index != -1) { + if (gcdialog_showDialog(gVolatileFlagDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { + volatileFlag_set(id, 1); + } + return volatileFlag_get(id); + } + return 0; + } +} + +// called for dialogs when banjo is not fast enough to reach a door or jiggy and for NOBONUS text +void progressDialog_setAndTriggerDialog_0(enum volatile_flags_e arg0) { + progressDialog_setAndTriggerDialog(arg0, 0); +} + +// called for FFQ dialogs +void progressDialog_setAndTriggerDialog_4(enum volatile_flags_e arg0) { + progressDialog_setAndTriggerDialog(arg0, 4); +} + +// called for WISHYWASHYBANJO dialog, mumbo jumbo speaking? +void progressDialog_setAndTriggerDialog_E(enum volatile_flags_e arg0) { + progressDialog_setAndTriggerDialog(arg0, 0xE); +} diff --git a/src/core2/dialog/progress_dialogs.c b/src/core2/dialog/progress_dialogs.c deleted file mode 100644 index 07089daf3..000000000 --- a/src/core2/dialog/progress_dialogs.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" - -typedef KEY_VALUE_PAIR(s16, s16) MapProgressFlagToDialogID; - -/* Mapping for file progess flags to Dialog IDs */ -MapProgressFlagToDialogID fileProgressDialogMap[] = { - { FILEPROG_AB_SWIM_OILY_WATER, 0xBA1}, - { FILEPROG_AC_DIVE_OILY_WATER, 0xBA2}, - { FILEPROG_AA_HAS_TOUCHED_CCW_BRAMBLE_FIELD, 0xCE6}, - { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, 0xC85}, - { FILEPROG_A9_HAS_TOUCHED_RBB_OVEN, 0xBA0}, - { FILEPROG_10_HAS_TOUCHED_SAND_EEL_SAND, 0xA7E}, - { FILEPROG_14_HAS_TOUCHED_FP_ICY_WATER, 0xC11}, - { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, 0xC85}, - { FILEPROG_86_HAS_TOUCHED_MMM_THORN_HEDGE, 0xAE1}, - { FILEPROG_DD_HAS_TOUCHED_CCW_ICY_WATER, 0xCE7}, - { FILEPROG_3_MUSIC_NOTE_TEXT, 0xD9C}, - { FILEPROG_4_MUMBO_TOKEN_TEXT, 0xD9D}, - { FILEPROG_5_BLUE_EGG_TEXT, 0xD9E}, - { FILEPROG_6_RED_FEATHER_TEXT, 0xD9F}, - { FILEPROG_7_GOLD_FEATHER_TEXT, 0xDA0}, - { FILEPROG_8_ORANGE_TEXT, 0xB46}, - { FILEPROG_9_GOLD_BULLION_TEXT, 0xA21}, - { FILEPROG_A_HONEYCOMB_TEXT, 0xDA1}, - { FILEPROG_B_EMPTY_HONEYCOMB_TEXT, 0xDA2}, - { FILEPROG_C_EXTRA_LIFE_TEXT, 0xDA3}, - { FILEPROG_BE_CHEATO_BLUEEGGS, 0xFA8}, - { FILEPROG_BF_CHEATO_REDFEATHERS, 0xFA9}, - { FILEPROG_C0_CHEATO_GOLDFEATHERS, 0xFAA}, - { FILEPROG_95_UNUSED_UNKNOWN_ITEM_COLLECT, 0xB50}, - { FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT, 0xF7B}, - { -1, -1} -}; - -/* This progress IDs are not saved in the save file, like when Banjo goes near a Note door which requires more notes than the Banjo has. */ -/* Triggers a dialog every time after the game restarts. */ -MapProgressFlagToDialogID gVolatileFlagDialogMap[] = { - {VOLATILE_FLAG_9E_BETA_OILY_SCUM, 0xBA3}, // Oily scum (unused) - {VOLATILE_FLAG_9F_BETA_DIVE_IN_ICY_WATER, 0xCE8}, // Dive in icy water (unused) - {VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT, 0x1032}, - {VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT, 0x1033}, - {VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT, 0x1034}, - {VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG, 0x1035}, - {VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG, 0x1036}, - {VOLATILE_FLAG_A5_FF_UNUSED, 0x1037}, // FF "the choice is yours" - {VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB, 0x1038}, - {VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE, 0x1039}, - {VOLATILE_FLAG_A8_FF_GOT_JOKER, 0x103A}, - {VOLATILE_FLAG_A9_FF_USED_JOKER, 0x103B}, - {VOLATILE_FLAG_AA_FF_LOW_HEALTH, 0x103C}, - {VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL, 0x103D}, - {VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED, 0xA88}, - {VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED, 0xAE2}, - {VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED, 0xC8B}, - {VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED, 0xC8C}, - {VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES, 0xFBD}, - {VOLATILE_FLAG_C2_NOBONUS_TEXT, 0xE36}, - {VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT, 0xDB6}, - { -1, -1} -}; - -static s32 __findIndex(MapProgressFlagToDialogID *map, s32 key) { - s32 i = 0; - - while (map[i].key >= 0) { - if (key == map[i].key) { - return i; - } - i++; - } - - return -1; -} - -/* Checks for a specific file progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ -s32 showProgressFlagDialog(enum file_progress_e progress_flag, s32 arg1) { - s32 index; - - if (fileProgressFlag_get(progress_flag) != 0) { - return 0; - } else { - index = __findIndex(fileProgressDialogMap, progress_flag); - if (index != -1) { - if (gcdialog_showDialog(fileProgressDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { - fileProgressFlag_set(progress_flag, 1); - } - return fileProgressFlag_get(progress_flag); - } - return 0; - } -} - -void progressDialog_showDialogMaskZero(enum file_progress_e progress_flag){ - showProgressFlagDialog(progress_flag, 0); -} - -void progressDialog_showDialogMaskFour(enum file_progress_e progress_flag) { - showProgressFlagDialog(progress_flag, 4); -} - -/* Checks for a specific "volatile" progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ -s32 volatileFlag_setAndTriggerDialog(enum volatile_flags_e id, s32 arg1) { - s32 index; - - if (volatileFlag_get(id) != 0) { - return 0; - } else { - index = __findIndex(gVolatileFlagDialogMap, id); - if (index != -1) { - if (gcdialog_showDialog(gVolatileFlagDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { - volatileFlag_set(id, 1); - } - return volatileFlag_get(id); - } - return 0; - } -} - -// called for dialogs when banjo is not fast enough to reach a door or jiggy and for NOBONUS text -void volatileFlag_setAndTriggerDialog_0(enum volatile_flags_e arg0) { - volatileFlag_setAndTriggerDialog(arg0, 0); -} - -// called for FFQ dialogs -void volatileFlag_setAndTriggerDialog_4(enum volatile_flags_e arg0) { - volatileFlag_setAndTriggerDialog(arg0, 4); -} - -// called for WISHYWASHYBANJO dialog, mumbo jumbo speaking? -void volatileFlag_setAndTriggerDialog_E(enum volatile_flags_e arg0) { - volatileFlag_setAndTriggerDialog(arg0, 0xE); -} diff --git a/src/core2/displaylist_init.c b/src/core2/displaylist_init.c index 7ecdb6c46..8ada226cd 100644 --- a/src/core2/displaylist_init.c +++ b/src/core2/displaylist_init.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_8DC20.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -41,7 +42,7 @@ s32 D_803830A0; void func_80314BB0(Gfx **gfx, Mtx **mtx, Vtx **vtx, void * frame_buffer_1, void *frame_buffer_2) { // [port] GPU-side pause snapshot s32 pauseFb = port_getPauseFramebufferId(); - bool isCapture = (frame_buffer_1 == zBuffer_get()); + bool isCapture = (frame_buffer_1 == depthbuffer_getDataPtr()); gSPDisplayList((*gfx)++, D_8036C630); @@ -79,7 +80,7 @@ void func_80314BB0(Gfx **gfx, Mtx **mtx, Vtx **vtx, void * frame_buffer_1, void void func_80315084(Gfx **gfx, Mtx **mtx, Vtx **vtx){ gsworld_setEnableDraw(0); D_803830A0 = 2; - func_80314BB0(gfx, mtx, vtx, zBuffer_get(), gFramebuffers[getActiveFramebuffer()]); + func_80314BB0(gfx, mtx, vtx, depthbuffer_getDataPtr(), gFramebuffers[getActiveFramebuffer()]); port_mirror_markCapture(); } @@ -93,7 +94,7 @@ void func_80315110(Gfx **gfx, Mtx **mtx, Vtx **vtx){ else{ D_803830A0--; } - func_80314BB0(gfx, mtx, vtx, gFramebuffers[getActiveFramebuffer()], zBuffer_get()); + func_80314BB0(gfx, mtx, vtx, gFramebuffers[getActiveFramebuffer()], depthbuffer_getDataPtr()); } void func_803151D0(Gfx **gfx, Mtx **mtx, Vtx **vtx){ diff --git a/src/core2/fileselect.c b/src/core2/fileselect.c index 5f7b9e42a..bd5b6f451 100644 --- a/src/core2/fileselect.c +++ b/src/core2/fileselect.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B5E00.c #include #include "functions.h" #include "variables.h" @@ -116,6 +117,7 @@ return 0; void gameFile_clear(s32 gamenum){ s32 filenum = gameFile_GameIdToFileIdMap[gamenum]; savedata_clear(&gameFile_saveData[filenum]); + CALL_EVENT(OnGameErase, gamenum); } void gameFile_load(s32 gamenum){ diff --git a/src/core2/freelist.c b/src/core2/fla.c similarity index 99% rename from src/core2/freelist.c rename to src/core2/fla.c index 2d50f492f..05c22d3fd 100644 --- a/src/core2/freelist.c +++ b/src/core2/fla.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fla.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/flags_bitfield.c b/src/core2/flags_bitfield.c index 7e215e899..055ddee55 100644 --- a/src/core2/flags_bitfield.c +++ b/src/core2/flags_bitfield.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_98CB0.c #include #include "functions.h" #include "variables.h" @@ -5,10 +6,10 @@ void func_8031FFAC(void); void fileProgressFlag_set(enum file_progress_e index, s32 set); -s32 bitfield_get_bit(u8 *array, s32 index); -s32 bitfield_get_n_bits(u8 *array, s32 offset, s32 numBits); -void bitfield_set_bit(u8 *array, s32 index, s32 set); -void bitfield_set_n_bits(u8 *array, s32 startIndex, s32 set, s32 length); +s32 bitfieldarray_getBit(u8 *array, s32 index); +s32 bitfieldarray_getNBits(u8 *array, s32 offset, s32 numBits); +void bitfieldarray_setBit(u8 *array, s32 index, s32 set); +void bitfieldarray_setNBits(u8 *array, s32 startIndex, s32 set, s32 length); void volatileFlag_clear(void); void volatileFlag_set(enum volatile_flags_e index, s32 set); s32 fileProgressFlag_getN(enum file_progress_e offset, s32 numBits); @@ -117,11 +118,11 @@ void func_8031FEC0(void) { } bool fileProgressFlag_get(enum file_progress_e index) { - return bitfield_get_bit(gFileProgressFlags.unk8, index); + return bitfieldarray_getBit(gFileProgressFlags.unk8, index); } s32 fileProgressFlag_getN(enum file_progress_e offset, s32 numBits) { - return bitfield_get_n_bits(gFileProgressFlags.unk8, offset, numBits); + return bitfieldarray_getNBits(gFileProgressFlags.unk8, offset, numBits); } s32 fileProgressFlag_getAndSet(enum file_progress_e index, s32 set) { @@ -142,16 +143,25 @@ void func_8031FFAC(void) { func_8031FEC0(); } -void fileProgressFlag_set(enum file_progress_e index, s32 set) { - bitfield_set_bit(gFileProgressFlags.unk8, index, set); +void fileProgressFlag_setEx(enum file_progress_e index, s32 set, s32 triggerEvent) { + s32 changed = bitfieldarray_getBit(gFileProgressFlags.unk8, index) != (set ? 1 : 0); + bitfieldarray_setBit(gFileProgressFlags.unk8, index, set); func_8031FC40(); func_8031FEC0(); + if (triggerEvent && changed) { + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_FILE_PROGRESS, index, set ? 1 : 0, 1); + } +} + +void fileProgressFlag_set(enum file_progress_e index, s32 set) { + fileProgressFlag_setEx(index, set, 1); } void fileProgressFlag_setN(enum file_progress_e startIndex, s32 set, s32 length) { - bitfield_set_n_bits(gFileProgressFlags.unk8, startIndex, set, length); + bitfieldarray_setNBits(gFileProgressFlags.unk8, startIndex, set, length); func_8031FC40(); func_8031FEC0(); + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_FILE_PROGRESS, startIndex, set, length); } void fileProgressFlag_getSizeAndPtr(s32 *size, u8 **addr) { @@ -160,7 +170,7 @@ void fileProgressFlag_getSizeAndPtr(s32 *size, u8 **addr) { } // Returns a single bit from a byte array -s32 bitfield_get_bit(u8 *array, s32 index) { +s32 bitfieldarray_getBit(u8 *array, s32 index) { s32 ret; if (array[index / 8] & (1 << (index & 7))) { ret = 1; @@ -171,18 +181,18 @@ s32 bitfield_get_bit(u8 *array, s32 index) { } // Extracts an integer of the given number of bits from a byte array at the starting bit offset -s32 bitfield_get_n_bits(u8 *array, s32 offset, s32 numBits) { +s32 bitfieldarray_getNBits(u8 *array, s32 offset, s32 numBits) { s32 ret = 0; s32 i; for (i = 0; i < numBits; i++) { - ret |= (bitfield_get_bit(array, offset + i) << i); + ret |= (bitfieldarray_getBit(array, offset + i) << i); } return ret; } // Sets or clears a single bit in a byte array -void bitfield_set_bit(u8 *array, s32 index, s32 set) { +void bitfieldarray_setBit(u8 *array, s32 index, s32 set) { if (set) { array[index / 8] |= (1 << (index & 7)); } else { @@ -191,11 +201,11 @@ void bitfield_set_bit(u8 *array, s32 index, s32 set) { } // Sets or clears a range of bits in a byte array -void bitfield_set_n_bits(u8 *array, s32 startIndex, s32 set, s32 length) { +void bitfieldarray_setNBits(u8 *array, s32 startIndex, s32 set, s32 length) { s32 i; for (i = 0; i < length; i++) { - bitfield_set_bit(array, startIndex + i, (1 << i) & set); + bitfieldarray_setBit(array, startIndex + i, (1 << i) & set); } } @@ -273,11 +283,11 @@ void func_803203A0(void) { } s32 volatileFlag_get(enum volatile_flags_e index) { - return bitfield_get_bit(gVolatileFlags.unk8, index); + return bitfieldarray_getBit(gVolatileFlags.unk8, index); } s32 volatileFlag_getN(enum volatile_flags_e index, s32 numBits) { - return bitfield_get_n_bits(gVolatileFlags.unk8, index, numBits); + return bitfieldarray_getNBits(gVolatileFlags.unk8, index, numBits); } s32 volatileFlag_getAndSet(enum volatile_flags_e index, s32 arg1) { @@ -297,16 +307,30 @@ void volatileFlag_clear(void) { func_803203A0(); } -void volatileFlag_set(enum volatile_flags_e index, s32 set) { - bitfield_set_bit(gVolatileFlags.unk8, index, set); +void volatileFlag_setEx(enum volatile_flags_e index, s32 set, s32 triggerEvent) { + s32 changed = bitfieldarray_getBit(gVolatileFlags.unk8, index) != (set ? 1 : 0); + bitfieldarray_setBit(gVolatileFlags.unk8, index, set); func_803202D0(); func_803203A0(); + if (triggerEvent && changed) { + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_VOLATILE, index, set ? 1 : 0, 1); + } +} + +void volatileFlag_set(enum volatile_flags_e index, s32 set) { + volatileFlag_setEx(index, set, 1); } void volatileFlag_setN(enum volatile_flags_e startIndex, s32 set, s32 length) { - bitfield_set_n_bits(gVolatileFlags.unk8, startIndex, set, length); + bitfieldarray_setNBits(gVolatileFlags.unk8, startIndex, set, length); func_803202D0(); func_803203A0(); + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_VOLATILE, startIndex, set, length); +} + +void volatileFlag_getSizeAndPtr(s32 *size, u8 **addr) { + *size = 0x19; + *addr = gVolatileFlags.unk8; } s32 func_8032056C(void) { diff --git a/src/core2/font/print.c b/src/core2/font/print.c index f551887a9..61bf3ce4f 100644 --- a/src/core2/font/print.c +++ b/src/core2/font/print.c @@ -1,18 +1,14 @@ +// BanjoDecomp: core2/print.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -extern int ResourceMgr_GetDialogLanguageCount(void); -extern int ResourceMgr_IsJapanese(void); -// [port] PAL font has 75 glyphs (0x21-0x6B), overlapping NTSC control codes b,d,e,f,h,j. -// When PAL, fmtStrings use shifted codes above the glyph range. -#define PRINT_PAL (ResourceMgr_GetDialogLanguageCount() > 1) -// [port] JP uses font index 2 (sprite 1770, 256 I4 glyphs) for dialog text. -// Dialog strings begin with "\xFD\x6A" (escape + 'j') which switches to font index 2. -#define PRINT_JP (ResourceMgr_IsJapanese()) - +#include "port/Patches/Patches.h" +#include "port/ResourceHelpers.h" +#include "port/Interpolation/FrameInterpolation.h" +#define PRINT_JP (ResourceMgr_IsJapanese()) typedef struct{ s8 pad0[0x20]; @@ -37,17 +33,17 @@ typedef struct font_letter{ typedef struct map_font_texture_map{ s16 mapID; s16 assetId; -} MapFontTextureMap; +} MapToBoldFontTextureMap; typedef struct{ u8 firstLetter; u8 secondLetter; s8 xOffset; s8 yOffset; -}Struct_6DA30_0_s; +}BoldFontKerningData; /* .data */ -extern Struct_6DA30_0_s boldFontKernings[] = { +extern BoldFontKerningData boldFontKernings[] = { {'A', 'V', -3, 0}, {'W', 'A', -3, 0}, {'V', 'A', -3, 0}, @@ -76,16 +72,16 @@ extern Struct_6DA30_0_s boldFontKernings[] = { 0 }; -s32 D_80369068[] = {8, 16, 16, 0}; //max letter width +s32 maxFontLetterWidths[] = {8, 16, 16, 0}; //max letter width struct { - u8 unk0; - u8 unk1; - u8 unk2; - u8 unk3; + u8 r; + u8 g; + u8 b; + u8 a; } normalTextColor = {0xFF, 0xFF, 0xFF, 0XFF}; -MapFontTextureMap mapToBoldFontTextureMap[] ={ +MapToBoldFontTextureMap mapToBoldFontTextureMap[] ={ {MAP_1_SM_SPIRAL_MOUNTAIN, SPRITE_BOLD_FONT_BLUE_SPHERE_TEXTURE}, {MAP_2_MM_MUMBOS_MOUNTAIN, 0x6EF}, {0x3, 0x6EE}, @@ -206,28 +202,28 @@ Gfx D_80369238[] = { }; /* .bss */ -char D_80380AB0; -BKSprite *D_80380AB8[0x5]; +char print_sPreviousBoldLetter; +BKSprite *print_sFontSpriteAssets[0x5]; FontLetter *print_sFonts[4]; PrintBuffer *print_sPrintBuffer; PrintBuffer *print_sCurrentPtr; -s32 D_80380AE8; -s32 D_80380AEC; -s32 D_80380AF0; //print_sMonospaced -s32 D_80380AF4; -s32 D_80380AF8; -s32 D_80380AFC; -s32 D_80380B00; -s32 D_80380B04; +s32 print_sCurrentFont; +s32 print_sPreviousFont; +s32 print_sMonospacedModeEnabled; //print_sMonospaced +s32 print_sGradientModeEnabled; +s32 print_sGradient2ModeEnabled; +s32 print_sBrokenFontModeEnabled; +s32 print_sBackgroundModeEnabled; +s32 print_sUnknownMode; bool print_sInFontFormatMode; s32 D_80380B0C; -s32 D_80380B10; -s32 D_80380B14; -s32 D_80380B18; -s32 D_80380B1C; +s32 print_sShakyModeEnabled; +s32 print_sBilinearFilterModeEnabled; +s32 print_sBoldLetterFontFreeTimer; +s32 print_sCurrentBoldFontTexture; s8 D_80380B20[0x400]; -s8 D_80380F20[0x80]; +s8 print_sBoldFontLetterToSpriteMap[0x80]; s32 print_sDialogFontGlyphCount; // [port] actual glyph count from loaded font sprite @@ -308,7 +304,7 @@ void print_applyTextureToBoldFontLetter(BKSpriteTextureBlock *alphaMask, BKSprit FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprite){ BKSpriteFrame * font = sprite_getFramePtr(alphaMask, 0); BKSpriteTextureBlock *chunkPtr; - FontLetter * sp2C = bk_malloc((font->chunkCnt + 1)*sizeof(FontLetter)); + FontLetter * letters = bk_malloc((font->chunkCnt + 1)*sizeof(FontLetter)); u8* palDataPtr; u8* chunkDataPtr; s32 chunkSize; @@ -332,8 +328,8 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit while((uintptr_t)chunkDataPtr % 8) chunkDataPtr++; - sp2C[i].sprite = chunkPtr; - sp2C[i].palette = palDataPtr; + letters[i].sprite = chunkPtr; + letters[i].palette = palDataPtr; chunkSize = chunkPtr->w*chunkPtr->h; chunkPtr = (BKSpriteTextureBlock *)(chunkDataPtr + chunkSize); } @@ -353,7 +349,7 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit BKSpriteTextureBlock *copy = bk_malloc(copySize); memcpy(copy, chunkPtr, copySize); print_applyTextureToBoldFontLetter(copy, (BKSpriteTextureBlock *)(sprite_getFramePtr(textureSprite, 0) + 1)); - sp2C[i].sprite = copy; + letters[i].sprite = copy; CALL_EVENT(OnBoldFontLetterBuilt, copy, chunkPtr, (BKSpriteTextureBlock *)(sprite_getFramePtr(textureSprite, 0) + 1)); } @@ -368,7 +364,7 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit { chunkPtr = (BKSpriteTextureBlock *) (font + 1); for( i = 0; i < font->chunkCnt; i++){ - sp2C[i].sprite = chunkPtr; + letters[i].sprite = chunkPtr; chunkDataPtr = (u8*)(chunkPtr + 1); chunkSize = chunkPtr->w*chunkPtr->h; while((uintptr_t)chunkDataPtr % 8) @@ -382,7 +378,7 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit chunkPtr = (BKSpriteTextureBlock *)(font + 1); for( i = 0; i < font->chunkCnt; i++){ chunkDataPtr = (u8*)(chunkPtr + 1); - sp2C[i].sprite = chunkPtr; + letters[i].sprite = chunkPtr; chunkSize = chunkPtr->w*chunkPtr->h; while((uintptr_t)chunkDataPtr % 8) chunkDataPtr++; @@ -391,14 +387,14 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit } break; }; - return sp2C; + return letters; } void print_free(void){ s32 i; for(i = 0; i< 5; i++){ - assetcache_release(D_80380AB8[i]); - D_80380AB8[i] = NULL; + assetcache_release(print_sFontSpriteAssets[i]); + print_sFontSpriteAssets[i] = NULL; if(i < 4){ bk_free(print_sFonts[i]); print_sFonts[i] = NULL; @@ -420,33 +416,33 @@ void print_setBoldFontTexture(s32 textureId){ CALL_EVENT(OnBoldFontReset); // [port] func_802546E4 reads bk_malloc HeapHeader, but assets now come from resource manager. // code_B3A80_func_8033BDAC is stubbed (returns 0), so always falls through to assetcache_get. - // tmp_a2 = func_802546E4(D_80380AB8[1]); + // tmp_a2 = func_802546E4(print_sFontSpriteAssets[1]); // if(tmp_a2 & 0xF) // tmp_a2 += 0x10 - (tmp_a2 & 0xF); - // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK, D_80380AB8[1],tmp_a2)){ - assetcache_release(D_80380AB8[1]); - D_80380AB8[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); + // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK, print_sFontSpriteAssets[1],tmp_a2)){ + assetcache_release(print_sFontSpriteAssets[1]); + print_sFontSpriteAssets[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); // } - if(D_80380AB8[3]){ + if(print_sFontSpriteAssets[3]){ // [port] Same as above — func_802546E4 unsafe on resource-manager pointers - // tmp_a2 = func_802546E4(D_80380AB8[3]); + // tmp_a2 = func_802546E4(print_sFontSpriteAssets[3]); // if(tmp_a2 & 0xF) // tmp_a2 += 0x10 - (tmp_a2 & 0xF); - // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK, D_80380AB8[3],tmp_a2)){ - assetcache_release(D_80380AB8[3]); - D_80380AB8[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); + // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK, print_sFontSpriteAssets[3],tmp_a2)){ + assetcache_release(print_sFontSpriteAssets[3]); + print_sFontSpriteAssets[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); // } }//L802F510C - D_80380AB8[4] = assetcache_get(textureId); + print_sFontSpriteAssets[4] = assetcache_get(textureId); bk_free(print_sFonts[1]); - print_sFonts[1] = print_getLettersFromFont(D_80380AB8[1], D_80380AB8[4]); - if(D_80380AB8[3]){ + print_sFonts[1] = print_getLettersFromFont(print_sFontSpriteAssets[1], print_sFontSpriteAssets[4]); + if(print_sFontSpriteAssets[3]){ bk_free(print_sFonts[3]); - print_sFonts[3] = print_getLettersFromFont(D_80380AB8[3], D_80380AB8[4]); + print_sFonts[3] = print_getLettersFromFont(print_sFontSpriteAssets[3], print_sFontSpriteAssets[4]); } - assetcache_release(D_80380AB8[4]); - D_80380AB8[4] = NULL; - D_80380B1C = textureId; + assetcache_release(print_sFontSpriteAssets[4]); + print_sFontSpriteAssets[4] = NULL; + print_sCurrentBoldFontTexture = textureId; } void print_resetBoldFontTexture(void){ @@ -460,29 +456,30 @@ void print_init(void){ int found; length = strlen(boldFontLetters); - D_80380AE8 = \ - D_80380AEC = \ - D_80380AF0 = \ - D_80380AF4 = \ - D_80380AF8 = \ - D_80380AFC = \ + print_sCurrentFont = \ + print_sPreviousFont = \ + print_sMonospacedModeEnabled = \ + print_sGradientModeEnabled = \ + print_sGradient2ModeEnabled = \ + print_sBrokenFontModeEnabled = \ print_sInFontFormatMode = \ - D_80380B04 = \ - D_80380B00 = \ - D_80380B10 = \ - D_80380B14 = 0; - D_80380AB0 = 0; + print_sUnknownMode = \ + print_sBackgroundModeEnabled = \ + print_sShakyModeEnabled = \ + print_sBilinearFilterModeEnabled = 0; + print_sPreviousBoldLetter = 0; func_802F7A2C(3); - D_80380AB8[0] = assetcache_get(SPRITE_DIALOG_FONT_ALPHAMASK); - D_80380AB8[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); - D_80380AB8[4] = assetcache_get(print_getCurrentMapBoldFontTexture()); - print_sFonts[0] = print_getLettersFromFont(D_80380AB8[0], D_80380AB8[4]); - print_sDialogFontGlyphCount = sprite_getFramePtr(D_80380AB8[0], 0)->chunkCnt; - print_sFonts[1] = print_getLettersFromFont(D_80380AB8[1], D_80380AB8[4]); + print_sFontSpriteAssets[0] = assetcache_get(SPRITE_DIALOG_FONT_ALPHAMASK); + print_sFontSpriteAssets[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); + print_sFontSpriteAssets[4] = assetcache_get(print_getCurrentMapBoldFontTexture()); + print_sFonts[0] = print_getLettersFromFont(print_sFontSpriteAssets[0], print_sFontSpriteAssets[4]); + print_sDialogFontGlyphCount = sprite_getFramePtr(print_sFontSpriteAssets[0], 0)->chunkCnt; + port_dialogFontHd_rebuild(); + print_sFonts[1] = print_getLettersFromFont(print_sFontSpriteAssets[1], print_sFontSpriteAssets[4]); if (PRINT_JP) { // [port] JP font index 2 = the Japanese dialog font (sprite 1770, 256 I4 glyphs). - D_80380AB8[2] = assetcache_get(SPRITE_JP_DIALOG_FONT_ALPHAMASK); - print_sFonts[2] = print_getLettersFromFont(D_80380AB8[2], D_80380AB8[4]); + print_sFontSpriteAssets[2] = assetcache_get(SPRITE_JP_DIALOG_FONT_ALPHAMASK); + print_sFonts[2] = print_getLettersFromFont(print_sFontSpriteAssets[2], print_sFontSpriteAssets[4]); } print_sPrintBuffer = bk_malloc(0x20*sizeof(PrintBuffer)); print_clearPrintBufferStrings(); @@ -491,37 +488,37 @@ void print_init(void){ found = 0; for(j = 0; j < length && !found; j++){//L802F5304 if(boldFontLetters[j] == i){ - D_80380F20[i] = j; + print_sBoldFontLetterToSpriteMap[i] = j; found = 1; }//L802F531C }//L802F5330 if(!found) - D_80380F20[i] = -1; + print_sBoldFontLetterToSpriteMap[i] = -1; } - assetcache_release(D_80380AB8[4]); - D_80380AB8[4] = NULL; - D_80380B1C = print_getCurrentMapBoldFontTexture(); + assetcache_release(print_sFontSpriteAssets[4]); + print_sFontSpriteAssets[4] = NULL; + print_sCurrentBoldFontTexture = print_getCurrentMapBoldFontTexture(); } void print_updateBoldLetterFontDelayedFreeing(void){ - if(D_80380B18 > 0 && --D_80380B18 == 0){ - assetcache_release(D_80380AB8[3]); - D_80380AB8[3] = 0; + if(print_sBoldLetterFontFreeTimer > 0 && --print_sBoldLetterFontFreeTimer == 0){ + assetcache_release(print_sFontSpriteAssets[3]); + print_sFontSpriteAssets[3] = 0; bk_free(print_sFonts[3]); print_sFonts[3] = NULL; } } void print_freeBoldLetterFont(void){ - if(D_80380AB8[3]){ - assetcache_release(D_80380AB8[3]); - D_80380AB8[3] = NULL; + if(print_sFontSpriteAssets[3]){ + assetcache_release(print_sFontSpriteAssets[3]); + print_sFontSpriteAssets[3] = NULL; } if(print_sFonts[3]){ bk_free(print_sFonts[3]); print_sFonts[3] = NULL; } - D_80380B18 = 0; + print_sBoldLetterFontFreeTimer = 0; } void printbuffer_defrag(void){ @@ -535,103 +532,103 @@ void printbuffer_defrag(void){ //returns the pixel data and type for a given letter BKSpriteTextureBlock *print_getBoldFontLetterSprite(s32 letterId, s32 *fontType){ - if(D_80380AE8 != 1 || (D_80380AE8 == 1 && letterId < 0xA)){ - s32 slot = D_80380AE8; + if(print_sCurrentFont != 1 || (print_sCurrentFont == 1 && letterId < 0xA)){ + s32 slot = print_sCurrentFont; // [port] Let the language system remap the slot/letter (e.g. fall back to // the base font if the JP font slot is momentarily unloaded mid-swap). CALL_EVENT(ResolveBoldFontSlot, &slot, &letterId); - *fontType = D_80380AB8[slot]->type; + *fontType = print_sFontSpriteAssets[slot]->type; return print_sFonts[slot][letterId].sprite; } else{//L802F5510 - if(!D_80380AB8[3]){ - D_80380AB8[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); - D_80380AB8[4] = assetcache_get(D_80380B1C); - print_sFonts[3] = print_getLettersFromFont(D_80380AB8[3], D_80380AB8[4]); - assetcache_release(D_80380AB8[4]); - D_80380AB8[4] = NULL; + if(!print_sFontSpriteAssets[3]){ + print_sFontSpriteAssets[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); + print_sFontSpriteAssets[4] = assetcache_get(print_sCurrentBoldFontTexture); + print_sFonts[3] = print_getLettersFromFont(print_sFontSpriteAssets[3], print_sFontSpriteAssets[4]); + assetcache_release(print_sFontSpriteAssets[4]); + print_sFontSpriteAssets[4] = NULL; }//L802F5568 - D_80380B18 = 5; - *fontType = D_80380AB8[3]->type; + print_sBoldLetterFontFreeTimer = 5; + *fontType = print_sFontSpriteAssets[3]->type; return print_sFonts[3][letterId-10].sprite; } } //returns the letter's palette void *print_getCurrentFontPalette(u8 arg0){ - return print_sFonts[D_80380AE8][arg0].palette; + return print_sFonts[print_sCurrentFont][arg0].palette; } void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx **gfx, Mtx **mtx, Vtx **vtx){ static f32 left_margin; // u8 letter = arg0; - BKSpriteTextureBlock *sp214; + BKSpriteTextureBlock *letter_sprite; uintptr_t sp210; - s32 sp20C; - s32 t0; - s8 t1; - f32 sp200; - f32 f28; - f32 sp1F8; - s32 sp1F4; //font_type; + s32 letter_id; + s32 valid_letter; + s8 y_offset; + f32 x; + f32 y; + f32 letter_width; + s32 font_type; //font_type; int i; - t0 = 0; - sp200 = *xPtr; - f28 = *yPtr; - t1 = 0; + valid_letter = 0; + x = *xPtr; + y = *yPtr; + y_offset = 0; - if(!D_80380B04 && !letter){ + if(!print_sUnknownMode && !letter){ left_margin = 0.0f; }//L802F563C - switch(D_80380AE8){ + switch(print_sCurrentFont){ case 0: //L802F5678 if(letter >= '\x21' && letter < ('\x21' + print_sDialogFontGlyphCount)){ - sp20C = letter - '\x21'; - t0 = 1; + letter_id = letter - '\x21'; + valid_letter = 1; } break; case 1: //L802F56A0 - if((u8)letter < 0x80 && D_80380F20[(u8)letter] >= 0){ // [port] char is signed on MSVC; MIPS char is unsigned + if((u8)letter < 0x80 && print_sBoldFontLetterToSpriteMap[(u8)letter] >= 0){ // [port] char is signed on MSVC; MIPS char is unsigned for(i = 0; boldFontKernings[i].firstLetter != 0; i++){ - if(letter == boldFontKernings[i].secondLetter && D_80380AB0 == boldFontKernings[i].firstLetter){ - t1 = boldFontKernings[i].yOffset; + if(letter == boldFontKernings[i].secondLetter && print_sPreviousBoldLetter == boldFontKernings[i].firstLetter){ + y_offset = boldFontKernings[i].yOffset; break; } }//L802F5710 - sp20C = D_80380F20[(u8)letter]; - t0 = 1; - D_80380AB0 = (u8)letter; - f28 += (f32)t1*arg3; + letter_id = print_sBoldFontLetterToSpriteMap[(u8)letter]; + valid_letter = 1; + print_sPreviousBoldLetter = (u8)letter; + y += (f32)y_offset*arg3; }//L802F5738 break; case 2: //L802F5740 - sp20C = (u8)letter; - if(D_80380B04){ - t0 = 1; - sp20C += (D_80380B04 << 8) - 0x100; - D_80380B04 = 0; + letter_id = (u8)letter; + if(print_sUnknownMode){ + valid_letter = 1; + letter_id += (print_sUnknownMode << 8) - 0x100; + print_sUnknownMode = 0; } else if(PRINT_JP){ - if(sp20C > 0 && sp20C != 0xFD && sp20C != 0x0F){ - t0 = 1; - if(sp20C == 0x36) - sp20C = 0xFD; + if(letter_id > 0 && letter_id != 0xFD && letter_id != 0x0F){ + valid_letter = 1; + if(letter_id == 0x36) + letter_id = 0xFD; } } else{//L802F5764 - if(sp20C > 0 && sp20C < 0xfD) - t0 = 1; + if(letter_id > 0 && letter_id < 0xfD) + valid_letter = 1; } break; }//L802F5778 - if(!t0 || print_sInFontFormatMode){ + if(!valid_letter || print_sInFontFormatMode){ print_sInFontFormatMode = false; switch((u8)letter){ case '\x0F': // [port] JP font-2 word space; no-op for US/PAL @@ -639,54 +636,54 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * break; // fallthrough case ' '://802F5818 - *xPtr += ((D_80380AF0) ? D_80369068[D_80380AE8]: D_80369068[D_80380AE8]*0.8) * arg3; + *xPtr += ((print_sMonospacedModeEnabled) ? maxFontLetterWidths[print_sCurrentFont]: maxFontLetterWidths[print_sCurrentFont]*0.8) * arg3; break; case 'b': //L802F5890 case '\x6D': // [port] PAL shifted b //toggle background - D_80380B00 = D_80380B00 ^ 1; + print_sBackgroundModeEnabled = print_sBackgroundModeEnabled ^ 1; break; case 'f': //L802F58A8 case '\x72': // [port] PAL shifted f - D_80380AEC = D_80380AE8 = D_80380AE8 ^ 1; + print_sPreviousFont = print_sCurrentFont = print_sCurrentFont ^ 1; break; case 'l': //L802F58BC - D_80380B10 = 0; + print_sShakyModeEnabled = 0; break; case 'h': //L802F58C8 case '\x73': // [port] PAL shifted h - D_80380B10 = 1; + print_sShakyModeEnabled = 1; break; case 'j': //L802F58D4 case '\x74': // [port] PAL shifted j - if(D_80380AFC == 0){ - D_80380AFC = 1; - D_80380AEC = D_80380AE8; - D_80380AE8 = 2; - // D_80380AE8 = 2; + if(print_sBrokenFontModeEnabled == 0){ + print_sBrokenFontModeEnabled = 1; + print_sPreviousFont = print_sCurrentFont; + print_sCurrentFont = 2; + // print_sCurrentFont = 2; } break; case 'e': //L802F58FC case '\x6F': // [port] PAL shifted e - if(D_80380AFC){ - D_80380AFC = 0; - D_80380AE8 = D_80380AEC; + if(print_sBrokenFontModeEnabled){ + print_sBrokenFontModeEnabled = 0; + print_sCurrentFont = print_sPreviousFont; } break; case 'p': //L802F5924 - D_80380AF0 = D_80380AF0 ^1; + print_sMonospacedModeEnabled = print_sMonospacedModeEnabled ^1; break; case 'q': //L802F593C - D_80380B14 = D_80380B14^1; - if(D_80380B14){ + print_sBilinearFilterModeEnabled = print_sBilinearFilterModeEnabled^1; + if(print_sBilinearFilterModeEnabled){ gDPSetTextureFilter((*gfx)++, G_TF_POINT); } else{//L802F5978 @@ -696,8 +693,8 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * case 'v': //L802F59A0 //toggle letter gradient - D_80380AF4 ^= 1; - if(D_80380AF4){ + print_sGradientModeEnabled ^= 1; + if(print_sGradientModeEnabled){ viewport_setRenderViewportAndOrthoMatrix(gfx, mtx); gDPPipeSync((*gfx)++); gDPSetTexturePersp((*gfx)++, G_TP_PERSP); @@ -712,8 +709,8 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * case 'd': //L802F5A8C case '\x6E': // [port] PAL shifted d - D_80380AF8 ^= 1; - if(D_80380AF8){ + print_sGradient2ModeEnabled ^= 1; + if(print_sGradient2ModeEnabled){ gDPPipeSync((*gfx)++); gDPSetCycleType((*gfx)++, G_CYC_2CYCLE); gDPSetRenderMode((*gfx)++, G_RM_PASS, G_RM_XLU_SURF2); @@ -734,81 +731,81 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * break; case 0xfe://L802F5BF4 - D_80380B04 = 1; + print_sUnknownMode = 1; break; case 0xff://L802F5BFC - D_80380B04 = 2; + print_sUnknownMode = 2; break; default: break; } } else{//L802F5C08 - sp214 = print_getBoldFontLetterSprite(sp20C, &sp1F4); - if (D_80380B10 != 0) { - sp200 += randf2(-2.0f, 2.0f); - f28 += randf2(-2.0f, 2.0f); + letter_sprite = print_getBoldFontLetterSprite(letter_id, &font_type); + if (print_sShakyModeEnabled != 0) { + x += randf2(-2.0f, 2.0f); + y += randf2(-2.0f, 2.0f); } - sp1F8 = (D_80380AF0 != 0) ? D_80369068[D_80380AE8] : sp214->x; + letter_width = (print_sMonospacedModeEnabled != 0) ? maxFontLetterWidths[print_sCurrentFont] : letter_sprite->x; // temp_f2 = left_margin; // phi_f2 = temp_f2; if (left_margin == 0.0f) { - left_margin = -sp1F8 * 0.5; + left_margin = -letter_width * 0.5; } - sp200 += (left_margin + (sp1F8 - sp214->x) * 0.5); - f28 -= sp214->h*0.5; - sp210 = (uintptr_t)(sp214 + 1); + x += (left_margin + (letter_width - letter_sprite->x) * 0.5); + y -= letter_sprite->h*0.5; + sp210 = (uintptr_t)(letter_sprite + 1); while(sp210 % 8){ sp210++; } // [port] Resolve alt bold fonts const char* hdPath = NULL; - CALL_EVENT(ResolveSpriteHdPath, sp214, &hdPath); + CALL_EVENT(ResolveSpriteHdPath, letter_sprite, &hdPath); if (hdPath != NULL) { sp210 = (uintptr_t)hdPath; } const char* boldHdPath = NULL; - CALL_EVENT(ResolveBoldFontHd, sp214, &boldHdPath); + CALL_EVENT(ResolveBoldFontHd, letter_sprite, &boldHdPath); if (boldHdPath != NULL) { sp210 = (uintptr_t)boldHdPath; } - if (sp1F4 == SPRITE_TYPE_RGBA32) { - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (sp1F4 == SPRITE_TYPE_IA8) { - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_IA, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (sp1F4 == SPRITE_TYPE_I8) { - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_I, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (sp1F4 == SPRITE_TYPE_I4) { - gDPLoadTextureTile_4b((*gfx)++, sp210, G_IM_FMT_I, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (sp1F4 == SPRITE_TYPE_CI8) { - void * pal = print_getCurrentFontPalette(sp20C); + if (font_type == SPRITE_TYPE_RGBA32) { + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (font_type == SPRITE_TYPE_IA8) { + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_IA, G_IM_SIZ_8b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (font_type == SPRITE_TYPE_I8) { + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_I, G_IM_SIZ_8b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (font_type == SPRITE_TYPE_I4) { + gDPLoadTextureTile_4b((*gfx)++, sp210, G_IM_FMT_I, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (font_type == SPRITE_TYPE_CI8) { + void * pal = print_getCurrentFontPalette(letter_id); gDPLoadTLUT_pal256((*gfx)++, pal); - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_CI, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_CI, G_IM_SIZ_8b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gDPSetTextureLUT((*gfx)++, G_TT_RGBA16); }//L802F6570 - if (D_80380AF8 != 0) { + if (print_sGradient2ModeEnabled != 0) { s32 temp_t1; s32 phi_a0; temp_t1 = ((print_sCurrentPtr->topVertexAlpha - print_sCurrentPtr->y) - D_80380B0C) + 1; phi_a0 = - MAX(1 - D_80380B0C, MIN(0, temp_t1)); gDPSetTextureImage((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, 32, &D_80380B20); - gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, (sp214->x + 8) >> 3, 0x0100, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); + gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, (letter_sprite->x + 8) >> 3, 0x0100, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); gDPLoadSync((*gfx)++); - gDPLoadTile((*gfx)++, G_TX_LOADTILE, 0 << G_TEXTURE_IMAGE_FRAC, (phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (D_80380B0C - 1) << G_TEXTURE_IMAGE_FRAC); + gDPLoadTile((*gfx)++, G_TX_LOADTILE, 0 << G_TEXTURE_IMAGE_FRAC, (phi_a0) << G_TEXTURE_IMAGE_FRAC, (letter_sprite->x) << G_TEXTURE_IMAGE_FRAC, (D_80380B0C - 1) << G_TEXTURE_IMAGE_FRAC); gDPPipeSync((*gfx)++); - gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, ((sp214->x - 0 + 1)*G_IM_SIZ_8b_LINE_BYTES + 7) >> 3, 0x0100, 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); - gDPSetTileSize((*gfx)++, 1, 0 << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) + phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) - (1 - D_80380B0C))<x - 0 + 1)*G_IM_SIZ_8b_LINE_BYTES + 7) >> 3, 0x0100, 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); + gDPSetTileSize((*gfx)++, 1, 0 << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) + phi_a0) << G_TEXTURE_IMAGE_FRAC, (letter_sprite->x) << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) - (1 - D_80380B0C))<x - 1.0); - spD0 = sp214->y - 1.0; - temp_f26 = (f64) sp200 - (f32) gFramebufferWidth * 0.5; - spC0 = (f64)f28 - (f32)gFramebufferHeight*0.5 -0.5f; + temp_f24 = (letter_sprite->x - 1.0); + spD0 = letter_sprite->y - 1.0; + temp_f26 = (f64) x - (f32) gFramebufferWidth * 0.5; + spC0 = (f64)y - (f32)gFramebufferHeight*0.5 -0.5f; gSPVertex((*gfx)++, (uintptr_t)*vtx, 4, 0); for(iy = 0.0f; iy < 2.0; iy+= 1.0){ for(ix = 0.0f; ix < 2.0; ix += 1.0){ @@ -843,9 +840,9 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * else{ // [port] Wide variant: widescreen-anchored HUD text can start left of x=0; the Scis // macro would CPU-clamp it to the 4:3 edge and crop the glyph. - gSPWideTextureRectangle((*gfx)++, (s32)(sp200*4.0f), (s32)(f28*4.0f), (s32)((sp200 + sp214->x*arg3)*4.0f), (s32)((f28 + sp214->y*arg3)*4.0f), 0, 0, 0, (s32)(1024.0f / arg3), (s32)(1024.0f / arg3)); + gSPWideTextureRectangle((*gfx)++, (s32)(x*4.0f), (s32)(y*4.0f), (s32)((x + letter_sprite->x*arg3)*4.0f), (s32)((y + letter_sprite->y*arg3)*4.0f), 0, 0, 0, (s32)(1024.0f / arg3), (s32)(1024.0f / arg3)); } - *xPtr += sp1F8 * arg3; + *xPtr += letter_width * arg3; } } @@ -861,17 +858,17 @@ f32 print_calculateLetterXPos(u8 letter, f32* xPtr, f32 *yPtr, f32 arg3){ sp38 = *xPtr; var_v0 = false; sp34 = 0; - if (D_80380AE8 == 1) { + if (print_sCurrentFont == 1) { if (letter < 0x80) { - if (D_80380F20[letter] >= 0) { + if (print_sBoldFontLetterToSpriteMap[letter] >= 0) { for(i = 0; boldFontKernings[i].firstLetter != 0; i++) { - if ((boldFontKernings[i].secondLetter == letter) && (boldFontKernings[i].firstLetter == D_80380AB0)) { + if ((boldFontKernings[i].secondLetter == letter) && (boldFontKernings[i].firstLetter == print_sPreviousBoldLetter)) { sp34 = boldFontKernings[i].xOffset; break; } } - D_80380AB0 = letter; - sp44 = D_80380F20[letter]; + print_sPreviousBoldLetter = letter; + sp44 = print_sBoldFontLetterToSpriteMap[letter]; var_v0 = true; sp38 += sp34 * arg3; } @@ -882,15 +879,15 @@ f32 print_calculateLetterXPos(u8 letter, f32* xPtr, f32 *yPtr, f32 arg3){ } if (!var_v0 || print_sInFontFormatMode) { if (letter == ' ') { - var_f2 = (D_80380AF0) ? D_80369068[D_80380AE8] : 0.8*D_80369068[D_80380AE8]; + var_f2 = (print_sMonospacedModeEnabled) ? maxFontLetterWidths[print_sCurrentFont] : 0.8*maxFontLetterWidths[print_sCurrentFont]; } else{ return *xPtr; } } else { - if(D_80380AF0){ - var_f2 = D_80369068[D_80380AE8]; + if(print_sMonospacedModeEnabled){ + var_f2 = maxFontLetterWidths[print_sCurrentFont]; } else{ var_f2 = print_getBoldFontLetterSprite(sp44, &sp2C)->x; @@ -910,6 +907,7 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { f32 _y; f32 width; + FrameInterpolation_RecordOpenChild("printbuffer", 0); gSPDisplayList((*gfx)++, D_80369238); for(print_sCurrentPtr = print_sPrintBuffer; print_sCurrentPtr < print_sPrintBuffer + 0x20; print_sCurrentPtr++){ if (print_sCurrentPtr->string != 0) { @@ -920,17 +918,17 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { _printbuffer_draw_letter(0xFD, &_x, &_y, 1.0f, gfx, mtx, vtx); _printbuffer_draw_letter(print_sCurrentPtr->fmtString[j], &_x, &_y, 1.0f, gfx, mtx, vtx); } - if (D_80380B00 != 0) { - width = (strlen(print_sCurrentPtr->string) -1)*D_80369068[D_80380AE8]; + if (print_sBackgroundModeEnabled != 0) { + width = (strlen(print_sCurrentPtr->string) -1)*maxFontLetterWidths[print_sCurrentFont]; gDPPipeSync((*gfx)++); gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0x64); gDPSetCombineMode((*gfx)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); - gDPScisFillRectangle((*gfx)++, _x - D_80369068[D_80380AE8]/2 - 1.0f, _y - D_80369068[D_80380AE8]/2 - 1.0f, _x + width + D_80369068[D_80380AE8]/2, _y + D_80369068[D_80380AE8]/2 + 1.0f); + gDPScisFillRectangle((*gfx)++, _x - maxFontLetterWidths[print_sCurrentFont]/2 - 1.0f, _y - maxFontLetterWidths[print_sCurrentFont]/2 - 1.0f, _x + width + maxFontLetterWidths[print_sCurrentFont]/2, _y + maxFontLetterWidths[print_sCurrentFont]/2 + 1.0f); gDPPipeSync((*gfx)++); }//L802F73E8 - if ((D_80380AF8 == 0) && (D_80380AF4 == 0)) { - if (D_80380AE8 != 0) { + if ((print_sGradient2ModeEnabled == 0) && (print_sGradientModeEnabled == 0)) { + if (print_sCurrentFont != 0) { gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA); gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF); } else { @@ -938,7 +936,7 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { gDPSetPrimColor((*gfx)++, 0, 0, print_sCurrentPtr->rgba[0], print_sCurrentPtr->rgba[1], print_sCurrentPtr->rgba[2], print_sCurrentPtr->rgba[3]); } } - if ((D_80380AE8 == 1) && ((f64) print_sCurrentPtr->scale < 0.0)) { + if ((print_sCurrentFont == 1) && ((f64) print_sCurrentPtr->scale < 0.0)) { for(j = 0; print_sCurrentPtr->string[j]; j++){ letter_x_coords[j] = print_calculateLetterXPos(print_sCurrentPtr->string[j], &_x, &_y, -print_sCurrentPtr->scale); } @@ -948,7 +946,7 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { j--; } } else { - for(j = 0; (print_sCurrentPtr->string[j] != 0) || (D_80380B04 != 0); j++){ + for(j = 0; (print_sCurrentPtr->string[j] != 0) || (print_sUnknownMode != 0); j++){ _printbuffer_draw_letter(print_sCurrentPtr->string[j], &_x, &_y, print_sCurrentPtr->scale, gfx, mtx, vtx); } } @@ -965,6 +963,7 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { gDPSetTexturePersp((*gfx)++, G_TP_PERSP); gDPSetTextureFilter((*gfx)++, G_TF_BILERP); viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); + FrameInterpolation_RecordCloseChild(); }//*/ //adds a new string to the print buffer and updates string buffer end ptr @@ -980,16 +979,16 @@ void _printbuffer_push_new(s32 x, s32 y, u8 * string) { print_sCurrentPtr->fmtString[0] = (u8)0; print_sCurrentPtr->string = string; print_sCurrentPtr->scale = 1.0f; - print_sCurrentPtr->rgba[0] = (u8) normalTextColor.unk0; - print_sCurrentPtr->rgba[1] = (u8) normalTextColor.unk1; - print_sCurrentPtr->rgba[2] = (u8) normalTextColor.unk2; - print_sCurrentPtr->rgba[3] = (u8) normalTextColor.unk3; + print_sCurrentPtr->rgba[0] = (u8) normalTextColor.r; + print_sCurrentPtr->rgba[1] = (u8) normalTextColor.g; + print_sCurrentPtr->rgba[2] = (u8) normalTextColor.b; + print_sCurrentPtr->rgba[3] = (u8) normalTextColor.a; } void print_bold_overlapping(s32 x, s32 y, f32 arg2, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x72l" : "fl"); + strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x72l" : "fl"); print_sCurrentPtr->scale = arg2; } } @@ -997,21 +996,21 @@ void print_bold_overlapping(s32 x, s32 y, f32 arg2, u8* string){ void print_bold_spaced(s32 x, s32 y, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x72" : "f"); + strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x72" : "f"); } } void print_dialog(s32 x, s32 y, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x6Flq" : "elq"); + strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x6Flq" : "elq"); } } void print_dialog_w_bg(s32 x, s32 y, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "p\x6D" : "pb"); + strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "p\x6D" : "pb"); } } @@ -1029,7 +1028,7 @@ void print_dialog_gradient2(s32 x, s32 y, u8* string, s32 arg3, s32 arg4){ if(print_sCurrentPtr){ print_sCurrentPtr->topVertexAlpha = arg3; print_sCurrentPtr->bottomVertexAlpha = arg4; - strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x6E\x6Flq" : "delq"); + strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x6E\x6Flq" : "delq"); } } @@ -1056,11 +1055,11 @@ void func_802F7A2C(s32 arg0) { } void text_setNormalTextColor(s32 arg0, s32 arg1, s32 arg2){ - normalTextColor.unk0 = arg0; - normalTextColor.unk1 = arg1; - normalTextColor.unk2 = arg2; + normalTextColor.r = arg0; + normalTextColor.g = arg1; + normalTextColor.b = arg2; } void text_setNormalTextAlpha(s32 arg0){ - normalTextColor.unk3 = arg0; + normalTextColor.a = arg0; } diff --git a/src/core2/font/render.c b/src/core2/font/render.c index 300f58e76..763994506 100644 --- a/src/core2/font/render.c +++ b/src/core2/font/render.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_5DBC0.c #include #include "functions.h" #include "variables.h" @@ -313,33 +314,33 @@ void func_802E57E0(struct5DBC0_1s *arg0, Gfx **gfx) { } } -void func_802E5C98(Gfx **gdl){ +void func_802E5C98(Gfx **gfx) { int i; - gDPPipeSync((*gdl)++); - gSPClearGeometryMode((*gdl)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); - gSPTexture((*gdl)++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); - gSPSetGeometryMode((*gdl)++, G_TEXTURE_GEN_LINEAR); - gDPSetCycleType((*gdl)++, G_CYC_1CYCLE); - gDPPipelineMode((*gdl)++, G_PM_NPRIMITIVE); - gDPSetTextureLOD((*gdl)++, G_TL_TILE); - gDPSetTextureLUT((*gdl)++, G_TT_NONE); - gDPSetTextureDetail((*gdl)++, G_TD_CLAMP); - gDPSetTexturePersp((*gdl)++, G_TP_NONE); - gDPSetTextureFilter((*gdl)++, G_TF_BILERP); - gDPSetTextureConvert((*gdl)++, G_TC_FILT); - gDPSetAlphaCompare((*gdl)++, G_AC_NONE); - gDPSetRenderMode((*gdl)++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPPipeSync((*gfx)++); + gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); + gSPTexture((*gfx)++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); + gSPSetGeometryMode((*gfx)++, G_TEXTURE_GEN_LINEAR); + gDPSetCycleType((*gfx)++, G_CYC_1CYCLE); + gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE); + gDPSetTextureLOD((*gfx)++, G_TL_TILE); + gDPSetTextureLUT((*gfx)++, G_TT_NONE); + gDPSetTextureDetail((*gfx)++, G_TD_CLAMP); + gDPSetTexturePersp((*gfx)++, G_TP_NONE); + gDPSetTextureFilter((*gfx)++, G_TF_BILERP); + gDPSetTextureConvert((*gfx)++, G_TC_FILT); + gDPSetAlphaCompare((*gfx)++, G_AC_NONE); + gDPSetRenderMode((*gfx)++, G_RM_XLU_SURF, G_RM_XLU_SURF2); for(i = 0; i < D_8037E900->unkC; i++){ D_8037E900->unk0[i].unk4 -= 0x10; - func_802E57E0(D_8037E900->unk0 + i, gdl); + func_802E57E0(D_8037E900->unk0 + i, gfx); D_8037E900->unk0[i].unk4 += 0x10; } - gDPSetTexturePersp((*gdl)++, G_TP_PERSP); + gDPSetTexturePersp((*gfx)++, G_TP_PERSP); } -void func_802E5F10(Gfx **gdl){ - func_802E5C98(gdl); +void func_802E5F10(Gfx **gfx) { + func_802E5C98(gfx); func_802E5188(); } diff --git a/src/core2/frame/auxbuffer.c b/src/core2/frame/auxbuffer.c index 28b1ca355..2578da188 100644 --- a/src/core2/frame/auxbuffer.c +++ b/src/core2/frame/auxbuffer.c @@ -1,13 +1,9 @@ +// BanjoDecomp: core2/code_851D0.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -int gfx_create_framebuffer(unsigned int width, unsigned int height, unsigned int native_width, - unsigned int native_height, unsigned char resize, unsigned char force_fixed_aspect); - -s32 sAuxGpuFbId = -1; - #define TILE_SIZE 32 #define TILE_COUNT_X 5 #define TILE_COUNT_Y 4 @@ -18,8 +14,7 @@ s32 sAuxGpuFbId = -1; #define HORIZONTAL_MARGIN (((SCREEN_WIDTH) - IMAGE_WIDTH) / 2) #define VERTICAL_MARGIN (((SCREEN_HEIGHT) - IMAGE_HEIGHT) / 2) -/* .data */ -Gfx D_8036C450[] = { +Gfx sPictureBoxInitDL[] = { gsDPPipeSync(), gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH), gsSPSetGeometryMode(G_SHADE | G_TEXTURE_GEN_LINEAR | G_SHADING_SMOOTH), @@ -29,87 +24,86 @@ Gfx D_8036C450[] = { gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE_ALPHA, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE_ALPHA, 0, 0, 0, 0, TEXEL0), gsDPSetTextureFilter(G_TF_POINT), gsDPSetTexturePersp(G_TP_NONE), - gsDPSetPrimColor(0, 0, 0x00, 0x00, 0x00, 0x78), + gsDPSetPrimColor(0, 0, 0, 0, 0, 120), gsSPEndDisplayList() }; -Gfx D_8036C4A8[] = { +Gfx sPictureBoxFinishDL[] = { gsDPPipeSync(), gsDPSetTextureFilter(G_TF_BILERP), gsDPSetTexturePersp(G_TP_PERSP), gsSPEndDisplayList() }; -/* .bss */ -s16 *D_80382450; -void *D_80382454; +s16 *sPictureBoxColorBuffer; +void *sPictureBoxColorBufferBase; -/* .code */ -void func_8030C160(void){ +void picturebox_func_8030C160(void) { func_8024F150(); } -void func_8030C180(void){ +void picturebox_func_8030C180(void) { func_8024F180(); } -void func_8030C1A0(void){ - if(D_80382454 == NULL){ - D_80382454 = D_80382450 = bk_malloc(IMAGE_WIDTH * IMAGE_HEIGHT * sizeof(u16) + 64); - while((uintptr_t)D_80382450 & 0x3F){ - D_80382450++; +void picturebox_init(void) { + if (sPictureBoxColorBufferBase == NULL) { + sPictureBoxColorBuffer = malloc(IMAGE_WIDTH * IMAGE_HEIGHT * sizeof(u16) + 64); + sPictureBoxColorBufferBase = sPictureBoxColorBuffer; + + // Make sure that the color buffer is aligned on a 64-byte boundary + while ((uintptr_t)sPictureBoxColorBuffer & 0x3F) { // [port] pointer-width + sPictureBoxColorBuffer++; } } - if (sAuxGpuFbId < 0) { - sAuxGpuFbId = gfx_create_framebuffer(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0); - } } -void func_8030C204(void){ - if(D_80382454){ - bk_free(D_80382454); - D_80382454 = NULL; +void picturebox_free(void) { + if (sPictureBoxColorBufferBase) { + free(sPictureBoxColorBufferBase); + sPictureBoxColorBufferBase = NULL; } - switch(getGameMode()){ + switch (getGameMode()) { case GAME_MODE_8_BOTTLES_BONUS: chBottlesBonus_func_802DEA8C(0, 0); break; + case GAME_MODE_A_SNS_PICTURE: func_802DF11C(0, 0); break; } } -void func_8030C27C(void){ - switch(getGameMode()){ +void picturebox_spawn(void) { + switch (getGameMode()) { case GAME_MODE_8_BOTTLES_BONUS: chBottlesBonus_spawn(0, 0); break; + case GAME_MODE_A_SNS_PICTURE: func_802DF090(0, 0); break; - } } -void func_8030C2D4(Gfx **gdl, Mtx **mptr, Vtx **vptr){ +void picturebox_resetScissorBoxAndFramebuffer(Gfx **gfx, Mtx **mtx, Vtx **vtx) { scissorBox_setDefault(); - func_80253640(gdl, gFramebuffers[getActiveFramebuffer()]); + setupFramebuffer(gfx, gFramebuffers[getActiveFramebuffer()]); } // [port] This function is not called anywhere // Draws a 160x128 image pointed to by D_80382450 into the center of the screen -void func_8030C33C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void picturebox_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 x, y; // Set up the rendering state to draw the image - gSPDisplayList((*gfx)++, D_8036C450); + gSPDisplayList((*gfx)++, sPictureBoxInitDL); // Iterate over every tile in the image for (y = 0; y < TILE_COUNT_Y; y++) { for(x = 0; x < TILE_COUNT_X; x++){ // Load the current tile from the image - gDPLoadTextureTile((*gfx)++, osVirtualToPhysical(D_80382450), G_IM_FMT_IA, G_IM_SIZ_16b, IMAGE_WIDTH, IMAGE_HEIGHT, + gDPLoadTextureTile((*gfx)++, osVirtualToPhysical(sPictureBoxColorBuffer), G_IM_FMT_IA, G_IM_SIZ_16b, IMAGE_WIDTH, IMAGE_HEIGHT, TILE_SIZE * x, TILE_SIZE * y, TILE_SIZE * (x + 1) - 1, TILE_SIZE * (y + 1) - 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, @@ -125,13 +119,14 @@ void func_8030C33C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { } } // Reset the rendering state - gSPDisplayList((*gfx)++, D_8036C4A8); + gSPDisplayList((*gfx)++, sPictureBoxFinishDL); } -s16 *func_8030C704(void){ - return D_80382450; + +s16 *picturebox_getColorBuffer(void) { + return sPictureBoxColorBuffer; } -void scissorBox_setSmall(void){ - scissorBox_set(0, 160, 0, 128); +void picturebox_setScissorBox(void) { + scissorBox_set(0, IMAGE_WIDTH, 0, IMAGE_HEIGHT); } diff --git a/src/core2/frame/rendermem.c b/src/core2/frame/rendermem.c index b69c54ce6..865009e91 100644 --- a/src/core2/frame/rendermem.c +++ b/src/core2/frame/rendermem.c @@ -1,12 +1,14 @@ +// BanjoDecomp: core2/code_5C240.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "bk_time.h" +#include "port/Interpolation/FrameInterpolation.h" extern void func_8023DFF0(s32); -extern void comusicPlayer_update(void); +extern void coMusicPlayer_update(void); extern void func_802F1A10(void *, f32); extern void func_8033DC10(void); extern void func_8033DC18(void); @@ -44,22 +46,26 @@ void func_802E329C(s32 arg0, Gfx **gfx_begin, Gfx **gfx_end) { Vtx *vtx; Vtx *vtx_start; - getGraphicsStacks(&gfx, &mtx, &vtx); + graphicscache_swapAndGetStacks(&gfx, &mtx, &vtx); gfx_start = gfx; mtx_start = mtx; vtx_start = vtx; - scissorBox_SetForGameMode(&gfx, arg0); + setupFramebufferForGamemode(&gfx, arg0); if (D_8037E8C0.unk14 == 2) { drawRectangle2D(&gfx, 0, 0, (s32) (f32) gFramebufferWidth, (s32) (f32) gFramebufferHeight, 0, 0, 0); } if ((D_8037E8C0.unk14 == 0) || (D_8037E8C0.unk14 == 3)) { + FrameInterpolation_RecordOpenChild("rendermem_bound", 0); viewport_setRenderViewportAndPerspectiveMatrix(&gfx, &mtx); gcbound_draw(&gfx); + FrameInterpolation_RecordCloseChild(); } if (D_8037E8C0.unk14 == 1) { + FrameInterpolation_RecordOpenChild("rendermem_pause", 0); drawRectangle2D(&gfx, 0, 0, (s32) (f32) gFramebufferWidth, (s32) (f32) gFramebufferHeight, 0, 0, 0); viewport_setRenderViewportAndPerspectiveMatrix(&gfx, &mtx); func_802F1858(D_8037E8C0.unk10, &gfx, &mtx, &vtx); + FrameInterpolation_RecordCloseChild(); } core1_15B30_finishDList(&gfx); graphicsCache_checkFrame(gfx_start, gfx, mtx_start, mtx, vtx_start, vtx); @@ -112,8 +118,8 @@ void func_802E3580(void) { assetcache_release((void *)(intptr_t)D_8037E8C0.unkC); func_802F1884(D_8037E8C0.unk10); func_802E5F68(); - comusicPlayer_free(); - depthBuffer_stub(); + coMusicPlayer_free(); + depthbuffer_stub(); viMgr_func_8024BF94(2); } @@ -167,7 +173,7 @@ void func_802E35D8(void ) { return; } } - comusicPlayer_update(); + coMusicPlayer_update(); if (D_8037E8C0.unk14 == 0) { gcbound_alpha(D_8037E8C0.unk8); } diff --git a/src/core2/frame/texture_capture.c b/src/core2/frame/texture_capture.c index d3798e782..51b7c1070 100644 --- a/src/core2/frame/texture_capture.c +++ b/src/core2/frame/texture_capture.c @@ -1,10 +1,19 @@ +// BanjoDecomp: core2/code_77E50.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "port/Patches/Patches.h" + extern void gfx_texture_cache_clear(void); +// [port] The texture cache belongs to the renderer; marshal the clear. +static void __textureCacheClearFn(void* arg) { + (void)arg; + gfx_texture_cache_clear(); +} + u8 *textureList_getDataPtr(BKTextureList *texture_list); void model_copyFramebufferBlockToTexture(BKTextureList *texture_list, s32 indx, s32 x_offset, s32 y_offset){ @@ -34,6 +43,10 @@ void model_copyFramebufferToTextures(BKModelBin *model_bin){ s32 x, y; texture_list = modelbin_getTextureList(model_bin); + // [port] The blocks below read the rendered frame from the CPU-side + // buffer, so the frame this tick submitted has to be drawn first. One + // sync covers the whole capture. + port_pipelineSyncPoint(); osInvalDCache((void *)gFramebuffers[getActiveFramebuffer()], gFramebufferWidth * gFramebufferHeight*2); for(y = 0; y < 8; y++){ @@ -46,5 +59,5 @@ void model_copyFramebufferToTextures(BKModelBin *model_bin){ // [port] The CPU just modified texture data that LUS may have cached on the GPU. // Clear the texture cache so the next draw re-uploads from CPU memory. - gfx_texture_cache_clear(); + port_runOnRenderThread(__textureCacheClearFn, NULL); } diff --git a/src/core2/fx/enemy_shadow.c b/src/core2/fx/badShad.c similarity index 93% rename from src/core2/fx/enemy_shadow.c rename to src/core2/fx/badShad.c index 971b2e88c..6804b9564 100644 --- a/src/core2/fx/enemy_shadow.c +++ b/src/core2/fx/badShad.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/badShad.c #include #include "core1/core1.h" #include "functions.h" @@ -13,8 +14,8 @@ void func_802D729C(Actor *actor, f32 arg1); /* .data */ ActorInfo chBadShad = { - 0x9B, 0x108, 0x3BF, - 0x1, NULL, + MARKER_9B_MODEL_PLAYER_SHADOW, ACTOR_108_MODEL_PLAYER_SHADOW, ASSET_3BF_MODEL_PLAYER_SHADOW, + 0x1, NULL, chBadShad_update, actor_update_func_80326224, chBadShad_draw, 0, 0, 0.0f, 0 }; @@ -55,9 +56,9 @@ Actor *chBadShad_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ modelRender_setAlpha(other->alpha_124_19); sp40 = ml_map_f(this->actor_specific_1_f, 0.0f , 800.0f, 0.53f, 0.18f)*this->unk1C[1]; modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); - FrameInterpolation_NoInterpolatePush(); + FrameInterpolation_CameraRelativePush(); modelRender_draw(gfx, mtx, this->position, sp44, sp40, NULL, marker_loadModelBin(marker)); - FrameInterpolation_NoInterpolatePop(); + FrameInterpolation_CameraRelativePop(); return this; } @@ -143,7 +144,7 @@ void func_802D729C(Actor *actor, f32 arg1){ return; } if(!actor->unk104){ - __spawnQueue_add_2((void (*)(void))func_802D71A0, (uintptr_t)actor->marker, reinterpret_cast(s32, arg1)); + __spawnQueue_add_2((GenFunction_2)func_802D71A0, (uintptr_t)actor->marker, reinterpret_cast(s32, arg1)); return; } diff --git a/src/core2/fx/effect_spriteanim.c b/src/core2/fx/banjokazooiesign.c similarity index 61% rename from src/core2/fx/effect_spriteanim.c rename to src/core2/fx/banjokazooiesign.c index f1075c066..10398096e 100644 --- a/src/core2/fx/effect_spriteanim.c +++ b/src/core2/fx/banjokazooiesign.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/banjokazooiesign.c #include #include "core1/core1.h" #include "functions.h" @@ -6,19 +7,20 @@ extern void actor_postdrawMethod(ActorMarker *); Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_802DC900(Actor *this); +void gcBanjoKazooieSign_update(Actor *this); /* .data */ -f32 D_803680A0[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_803680AC = { - 0x175, 0x1DC, 0x54D, +f32 gcBanjoKazooieSignPosition[3] = {0.0f, 0.0f, 0.0f}; + +ActorInfo gcBanjoKazooieSign = { + MARKER_175_BANJO_KAZOOIE_SIGN, ACTOR_1DC_BANJO_KAZOOIE_SIGN, ASSET_54D_MODEL_BANJO_KAZOOIE_SIGN, 0x1, NULL, - func_802DC900, actor_update_func_80326224, func_802DC7E0, + gcBanjoKazooieSign_update, actor_update_func_80326224, func_802DC7E0, 0, 0, 0.0f, 0 }; /* .bss */ -ActorMarker *D_8037DE60; +ActorMarker *gcBanjoKazooieSignMarker; /* .code */ Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ @@ -54,35 +56,35 @@ Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ return this; } -void func_802DC8F0(Actor *this){ - D_8037DE60 = NULL; +void gcBanjoKazooieSign_free(Actor *this){ + gcBanjoKazooieSignMarker = NULL; } -void func_802DC900(Actor *this){ +void gcBanjoKazooieSign_update(Actor *this){ if(!this->initialized){ this->initialized = true; this->depth_mode = MODEL_RENDER_DEPTH_NONE; actor_collisionOff(this); - marker_setFreeMethod(this->marker, func_802DC8F0); + marker_setFreeMethod(this->marker, gcBanjoKazooieSign_free); } } -void func_802DC960(void) { +void gcBanjoKazooieSign_spawn(void) { Actor *actor; - if (D_8037DE60 == 0) { - actor = actor_spawnWithYaw_f32(0x1DC, D_803680A0, 0); - D_8037DE60 = actor->marker; + if (gcBanjoKazooieSignMarker == NULL) { + actor = actor_spawnWithYaw_f32(ACTOR_1DC_BANJO_KAZOOIE_SIGN, gcBanjoKazooieSignPosition, 0); + gcBanjoKazooieSignMarker = actor->marker; } } void func_802DC9A4(s32 arg0, s32 arg1){ - if(D_8037DE60 == NULL){ - __spawnQueue_add_0(func_802DC960); + if(gcBanjoKazooieSignMarker == NULL){ + __spawnQueue_add_0(gcBanjoKazooieSign_spawn); } } void func_802DC9DC(s32 arg0, s32 arg1){ - if(D_8037DE60 != NULL){ - func_80326310(marker_getActor(D_8037DE60)); + if(gcBanjoKazooieSignMarker != NULL){ + func_80326310(marker_getActor(gcBanjoKazooieSignMarker)); } } diff --git a/src/core2/fx/projectile_manager.c b/src/core2/fx/commonParticle.c similarity index 96% rename from src/core2/fx/projectile_manager.c rename to src/core2/fx/commonParticle.c index 7cc4979b3..9f93abca2 100644 --- a/src/core2/fx/projectile_manager.c +++ b/src/core2/fx/commonParticle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/commonParticle.c #include "core2/commonParticle.h" #include #include "functions.h" @@ -182,14 +183,18 @@ s32 commonParticle_findFree(void){ int commonParticle_new(enum common_particle_e particle_id, int arg1){ f32 sp34[3]; uintptr_t a0; + s32 slot; if(arg1 == 0) return -1; ml_vec3f_clear(sp34); - D_80384FD0 = commonParticle_findFree(); - if(D_80384FD0 < 0) + // [port] Don't publish -1 to the global; every D_80384490[D_80384FD0] access + // downstream (accessors, commonParticle_update) would read out of bounds. + slot = commonParticle_findFree(); + if(slot < 0) return -1; + D_80384FD0 = slot; D_80384490[D_80384FD0].projectileIndex = func_8033FA84(); @@ -248,6 +253,10 @@ void freeParticleByIndex(s32 arg0){ void commonParticle_add(ActorMarker *arg0, s32 arg1, FuncUnk40 arg2){ s32 tmp_v0 = commonParticle_findFree(); + // [port] Pool full returns -1; writing D_80384490[-1] corrupts whatever precedes it. + if(tmp_v0 < 0){ + return; + } D_80384490[tmp_v0].isInUse--; D_80384490[tmp_v0].unk38 = arg0; D_80384490[tmp_v0].unk3C = arg1; diff --git a/src/core2/fx/background_decor.c b/src/core2/fx/cutscene_actors.c similarity index 69% rename from src/core2/fx/background_decor.c rename to src/core2/fx/cutscene_actors.c index 2d3a70e33..850a98751 100644 --- a/src/core2/fx/background_decor.c +++ b/src/core2/fx/cutscene_actors.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_59780.c #include #include "core1/core1.h" #include "functions.h" @@ -8,44 +9,44 @@ extern void actor_postdrawMethod(ActorMarker *); Actor *func_802E0738(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802E07E0(Actor *this); -void func_802E08F0(Actor *this); +void chFireSparkle_update(Actor *this); /* .data */ -ActorAnimationInfo D_80368440[] = { +ActorAnimationInfo chFireSparkleAnimations[] = { {0, 0.0f}, {ASSET_98_ANIM_FIRE_SPARKLE, 1.2f} }; -ActorInfo D_80368450 = { +ActorInfo chFireSparkle = { MARKER_72_FIRE_SPARKLE, ACTOR_A2_FIRE_SPARKLE, ASSET_3AD_FIRE_SPARKLE, - 0x1, D_80368440, - func_802E08F0, actor_update_func_80326224, actor_draw, + 0x1, chFireSparkleAnimations, + chFireSparkle_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80368474 = { - 0x8C, 0xBC, 0x45C, +ActorInfo chBanjoCurtains = { + MARKER_8C_BANJOS_CURTAINS, ACTOR_BC_BANJOS_CURTAINS, ASSET_45C_MODEL_BANJOS_CURTAINS, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 }; -ActorInfo D_80368498 = { - 0x8D, 0xBD, 0x45E, +ActorInfo chBanjoHouseDoor = { + MARKER_8D_BANJOS_HOUSE_DOOR, ACTOR_BD_BANJOS_HOUSE_DOOR, ASSET_45E_MODEL_BANJOS_HOUSE_DOOR, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 }; -ActorInfo D_803684BC = { - 0x13D, 0x2F4, 0x46E, +ActorInfo chFishbowl = { + MARKER_13D_FISHBOWL, ACTOR_2F4_FISHBOWL, ASSET_46E_MODEL_FISHBOWL, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 }; -ActorInfo D_803684E0 = { - 0x13E, 0x2F5, 0x46F, +ActorInfo chCuckooClock = { + MARKER_13E_CUCKOO_CLOCK, ACTOR_2F5_CUCKOO_CLOCK, ASSET_46F_MODEL_CUCKOO_CLOCK, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 @@ -86,13 +87,13 @@ void func_802E0710(Actor *this){ } Actor *func_802E0738(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - f32 sp34[3]; + f32 rotation[3]; Actor *this; - this = marker_getActorAndRotation(marker, sp34); + this = marker_getActorAndRotation(marker, rotation); modelRender_setPreDrawCallback( (model_render_pre_draw_callback_f)func_802E0710, (void *)this); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); - modelRender_draw(gfx, mtx, this->position, sp34, this->scale, NULL, marker_loadModelBin(marker)); + modelRender_draw(gfx, mtx, this->position, rotation, this->scale, NULL, marker_loadModelBin(marker)); return this; } @@ -109,9 +110,9 @@ void func_802E07E0(Actor *this) { sp24 = 0; break; - case 0x451: - case 0x458: - case 0x532: + case ASSET_451_MODEL_GRUNTILDA: + case ASSET_458_MODEL_BANJO_TOP_SLEEPING: + case ASSET_532_MODEL_BANJO_KAZOOIE_CUTSCENES: sp24 = 1; break; } @@ -137,8 +138,8 @@ void func_802E07E0(Actor *this) { func_80361EE0(this); } -void func_802E08F0(Actor *this) { - f32 sp24[3]; +void chFireSparkle_update(Actor *this) { + f32 rotation[3]; this->marker->collidable = false; anctrl_setDuration(this->anctrl, this->unk5C); @@ -146,6 +147,6 @@ void func_802E08F0(Actor *this) { if (actor_animationIsAt(this, 0.99f) != 0) { marker_despawn(this->marker); } - viewport_getRotation_vec3f(sp24); - this->yaw = sp24[1]; + viewport_getRotation_vec3f(rotation); + this->yaw = rotation[1]; } diff --git a/src/core2/fx/drips.c b/src/core2/fx/drips.c index 580e85501..fa6ec221d 100644 --- a/src/core2/fx/drips.c +++ b/src/core2/fx/drips.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/drips.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_colordata.c b/src/core2/fx/effect_colordata.c index b0b7b64f2..05ec9e930 100644 --- a/src/core2/fx/effect_colordata.c +++ b/src/core2/fx/effect_colordata.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_BE2C0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/fx/effect_debris.c b/src/core2/fx/effect_debris.c index 13f7acf9c..bf9f8c40e 100644 --- a/src/core2/fx/effect_debris.c +++ b/src/core2/fx/effect_debris.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_41460.c #include "functions.h" #include "variables.h" #include @@ -34,12 +35,49 @@ f32 D_80366330 = 0.5f; f32 D_80366334 = 30.0f; f32 D_80366338 = 150.0f; f32 D_8036633C = 25.0f; -ActorInfo D_80366340 = { 0x56, 0x4A, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; -ActorInfo D_80366364 = { 0x56, 0x4B, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; -ActorInfo D_80366388 = { 0x56, 0xD, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; -ActorInfo D_803663AC = { 0x56, 0x11F, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; -ActorInfo D_803663D0 = { 0x56, 0x14F, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; -ActorInfo D_803663F4 = { 0x56, 0x3AD, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; + +ActorInfo D_80366340 = { + MARKER_56_UNKNOWN, 0x4A, 0x0, + 0x2, NULL, + func_802C8C5C, actor_update_func_80326224, func_802C8484, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80366364 = { + MARKER_56_UNKNOWN, 0x4B, 0x0, + 0x2, NULL, + func_802C8C5C, actor_update_func_80326224, func_802C8484, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80366388 = { + MARKER_56_UNKNOWN, 0xD, 0x0, + 0x2, NULL, + func_802C8C5C, actor_update_func_80326224, func_802C8484, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803663AC = { + MARKER_56_UNKNOWN, 0x11F, 0x0, + 0x2, NULL, + func_802C8C5C, actor_update_func_80326224, func_802C8484, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803663D0 = { + MARKER_56_UNKNOWN, 0x14F, 0x0, + 0x2, NULL, + func_802C8C5C, actor_update_func_80326224, func_802C8484, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803663F4 = { + MARKER_56_UNKNOWN, 0x3AD, 0x0, + 0x2, NULL, + func_802C8C5C, actor_update_func_80326224, func_802C8484, + 0, 0, 0.0f, 0 +}; + s32 D_80366418[3] = {0,0,0}; /* .bss */ @@ -71,14 +109,14 @@ void func_802C83F0(Actor *actor) { Actor *func_802C8484(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { Struct25s *temp_s1; Struct24s *phi_s0; - f32 sp5C[3]; - Actor *sp58; + f32 rotation[3]; + Actor *this; u32 phi_v1; s32 phi_s4; - sp58 = marker_getActorAndRotation(marker, sp5C); - temp_s1 = sp58->unk40; - phi_s4 = false; + this = marker_getActorAndRotation(marker, rotation); + temp_s1 = (Struct25s*)this->unk40; + phi_s4 = FALSE; for(phi_s0 = temp_s1->begin; phi_s0 < temp_s1->current; phi_s0++){ if ((phi_s0->unk0 != 0) && (phi_s0->model_bin != NULL)) { // [port] Stable scope per piece. Expiry shrinks the range @@ -93,7 +131,7 @@ Actor *func_802C8484(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { if (phi_s4 == false) { marker_despawn(marker); } - return sp58; + return this; } Actor *func_802C8580(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ @@ -127,44 +165,44 @@ Actor *func_802C8580(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ s0->unk8[1] = 0.0f; s0->unk8[2] = 0.0f; switch(D_8037DD94){ - case 1: // 802C8740 - s0->unk30[0] = randf2(125.0f, 175.0f); - s0->unk30[1] = randf2(400.0f, 600.0f); - s0->unk30[2] = randf2(125.0f, 175.0f); - s0->model_bin = (BKModelBin *) assetcache_get(0x2e7); - s0->unk2C = 18.0f; - break; - case 2: // 802C87A8 - s0->model_bin = (BKModelBin *) assetcache_get(0x344); - s0->unk2C = 2.0f; - break; - case 4: // 802C87C4 - s0->model_bin = (BKModelBin *) assetcache_get(0x345); - s0->unk2C = 1.0f; - s0->unk30[0] = randf2(20.0f, 100.0f); - s0->unk30[1] = randf2(400.0f, 740.0f); - s0->unk30[2] = randf2(20.0f, 100.0f); - - s0->unk8[0] = randf2(0.0f, 30.0f); - s0->unk8[1] = 0.0f; - s0->unk8[2] = 0.0f; - break; - case 0: // 802C883C - if(0.5 < randf()) - s0->model_bin = (BKModelBin *) assetcache_get(0x2d1); - else - s0->model_bin = (BKModelBin *) assetcache_get(0x2e5); - - s0->unk2C = randf2(5.0f, 12.0f); - break; - case 3: // 802C88A0 - s0->model_bin = (BKModelBin *) assetcache_get(0x30e); - s0->unk2C = randf2(9.0f, 15.0f); - break; - case 5: // 802C88C8 - s0->model_bin = (BKModelBin *) assetcache_get(0x8a2); - s0->unk2C = 2.0f; - break; + case 1: // 802C8740 + s0->unk30[0] = randf2(125.0f, 175.0f); + s0->unk30[1] = randf2(400.0f, 600.0f); + s0->unk30[2] = randf2(125.0f, 175.0f); + s0->model_bin = (BKModelBin *) assetcache_get(0x2e7); + s0->unk2C = 18.0f; + break; + case 2: // 802C87A8 + s0->model_bin = (BKModelBin *) assetcache_get(0x344); + s0->unk2C = 2.0f; + break; + case 4: // 802C87C4 + s0->model_bin = (BKModelBin *) assetcache_get(0x345); + s0->unk2C = 1.0f; + s0->unk30[0] = randf2(20.0f, 100.0f); + s0->unk30[1] = randf2(400.0f, 740.0f); + s0->unk30[2] = randf2(20.0f, 100.0f); + + s0->unk8[0] = randf2(0.0f, 30.0f); + s0->unk8[1] = 0.0f; + s0->unk8[2] = 0.0f; + break; + case 0: // 802C883C + if(0.5 < randf()) + s0->model_bin = (BKModelBin *) assetcache_get(MODEL_ASSET_OFFSET); + else + s0->model_bin = (BKModelBin *) assetcache_get(0x2e5); + + s0->unk2C = randf2(5.0f, 12.0f); + break; + case 3: // 802C88A0 + s0->model_bin = (BKModelBin *) assetcache_get(0x30e); + s0->unk2C = randf2(9.0f, 15.0f); + break; + case 5: // 802C88C8 + s0->model_bin = (BKModelBin *) assetcache_get(0x8a2); + s0->unk2C = 2.0f; + break; }//L802C88E0 s0->unk3C = NULL; sp68[0] = (f32)position[0]; diff --git a/src/core2/fx/effect_ice.c b/src/core2/fx/effect_ice.c index ed50f683e..1b4378276 100644 --- a/src/core2/fx/effect_ice.c +++ b/src/core2/fx/effect_ice.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_54D50.c #include #include "functions.h" #include "variables.h" @@ -16,13 +17,14 @@ void func_802DC018(Actor *this); /* .data */ ActorInfo D_80367F30= { - 0x1F5, 0x1E5, 0, + MARKER_1F5_UNKNOWN, ACTOR_1E5_UNKNOWN, 0, 0, NULL, func_802DC018, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 }; s32 D_80367F54[3] = {0xff, 0xff, 0xff}; + ParticleSettingsScaleAndLifetimeDrawModeEmitCount D_80367F60 = { { {0.1f, 0.5f}, {1.0f, 1.5f}, {0.0f, 0.01f}, {0.5f, 1.4f}, 0.0f, 0.01f diff --git a/src/core2/fx/effect_jiggy.c b/src/core2/fx/effect_jiggy.c index db3d1fd68..711b94de1 100644 --- a/src/core2/fx/effect_jiggy.c +++ b/src/core2/fx/effect_jiggy.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C0CF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_jiggy_list.c b/src/core2/fx/effect_jiggy_list.c index efc1edcd6..6f0ef34d5 100644 --- a/src/core2/fx/effect_jiggy_list.c +++ b/src/core2/fx/effect_jiggy_list.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_ABC00.c #include #include "functions.h" #include "variables.h" @@ -253,6 +254,7 @@ void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]) { temp_v0->unk10.position[2] = pos[2]; temp_v0->init(&temp_v0->unk10); jiggyscore_setSpawned(jiggy_id, true); + CALL_EVENT(OnJiggySpawned, jiggy_id, pos[0], pos[1], pos[2]); if (!jiggyscore_isCollected(jiggy_id) && (jiggy_id != JIGGY_3E_GV_GRABBA) && (jiggy_id != JIGGY_0B_TTC_JINJO)) { core1_ce60_incOrDecCounter(false); func_8025A55C(0, 4000, 5); @@ -263,7 +265,15 @@ void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]) { } } -void codeABC00_spawnJiggyAtLocation(enum jiggy_e jiggy_id, f32 location[3]) { +// [port] Anchor: true once the jiggylist slot's marker is linked (covers bundle-pop, unlike jiggyscore_isSpawned). +s32 jiggylist_hasSpawnedObject(enum jiggy_e jiggy_id) { + if ((jiggy_id <= 0) || (jiggy_id >= (s_jiggyList_level_jiggy_count * 10))) { + return 0; + } + return jiggylist_list[jiggy_id - 1].unk10.marker != NULL; +} + +void codeABC00_spawnJiggyAtLocationEx(enum jiggy_e jiggy_id, f32 location[3], s32 triggerEvent) { jiggy_id = ((jiggy_id <= 0) || (jiggy_id >= (s_jiggyList_level_jiggy_count * 10))) ? JIGGY_A_MM_CONGA : jiggy_id; jiggylist_list[jiggy_id - 1].unk10.position[0] = location[0]; @@ -271,6 +281,13 @@ void codeABC00_spawnJiggyAtLocation(enum jiggy_e jiggy_id, f32 location[3]) { jiggylist_list[jiggy_id - 1].unk10.position[2] = location[2]; jiggylist_list[jiggy_id - 1].init(&jiggylist_list[jiggy_id - 1].unk10); jiggyscore_setSpawned(jiggy_id, true); + if (triggerEvent) { + CALL_EVENT(OnJiggySpawned, jiggy_id, location[0], location[1], location[2]); + } +} + +void codeABC00_spawnJiggyAtLocation(enum jiggy_e jiggy_id, f32 location[3]) { + codeABC00_spawnJiggyAtLocationEx(jiggy_id, location, 1); } void func_80333270(enum jiggy_e jiggy_id, f32 position[3], void (*method)(Actor *, ActorMarker *), ActorMarker *other_marker) { diff --git a/src/core2/fx/effect_jiggy_spawn.c b/src/core2/fx/effect_jiggy_spawn.c index d94f7f52d..f50f5fa4f 100644 --- a/src/core2/fx/effect_jiggy_spawn.c +++ b/src/core2/fx/effect_jiggy_spawn.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C0B80.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_modelparticle.c b/src/core2/fx/effect_modelparticle.c index 6247ae4d4..31e9bbbdb 100644 --- a/src/core2/fx/effect_modelparticle.c +++ b/src/core2/fx/effect_modelparticle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_53C10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_playerspray.c b/src/core2/fx/effect_playerspray.c index 2c71deae2..44d5f3f04 100644 --- a/src/core2/fx/effect_playerspray.c +++ b/src/core2/fx/effect_playerspray.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B850.c #include #include "functions.h" #include "variables.h" @@ -14,7 +15,7 @@ void func_802927E0(f32 arg0, f32 arg1){ f32 sp18[3]; arg1 *= 0.51; - _player_getPosition(sp18); + playerPosition_get(sp18); sp18[1] += 10.0f; func_802589E4(sp24, arg0, arg1); sp24[1] = 40.0f; @@ -27,7 +28,7 @@ void func_80292864(f32 arg0, f32 arg1){ f32 sp1C[3]; ml_vec3f_assign(sp1C, 0.0f, 40.0f, 0.0f); - _player_getPosition(sp28); + playerPosition_get(sp28); func_802589E4(sp34, arg0, arg1); sp34[1] = 10.0f; sp28[0] += sp34[0]; sp28[1] += sp34[1]; sp28[2] += sp34[2]; @@ -39,7 +40,7 @@ void func_80292900(f32 arg0, f32 arg1){ f32 sp18[3]; arg1 *= 0.51; - _player_getPosition(sp18); + playerPosition_get(sp18); func_802589E4(sp24, arg0, arg1); sp24[1] = 40.0f; func_80352CF4(sp18, sp24, 10.0f, 150.0f); @@ -49,7 +50,7 @@ void func_80292974(f32 arg0, f32 arg1, f32 arg2){ f32 sp24[3]; f32 sp18[3]; arg1 *= 0.51; - _player_getPosition(sp18); + playerPosition_get(sp18); sp18[1] += 10.0f; func_802589E4(sp24, arg0, arg1); sp24[1] = arg2; diff --git a/src/core2/fx/effect_ripple.c b/src/core2/fx/effect_ripple.c index 34eb0566c..8348a55e4 100644 --- a/src/core2/fx/effect_ripple.c +++ b/src/core2/fx/effect_ripple.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_DB010.c #include #include "core1/core1.h" #include "functions.h" @@ -587,7 +588,7 @@ void func_80363330(Actor *this){ void func_80363388(struct_core2_DB010 *arg0, s32 arg1){ f32 sp2C[3]; s32 sp20[3]; - s32 tmp_v0 = codeA5BC0_getPositionAndReturnRadius(arg0, sp20); + s32 tmp_v0 = codeA5BC0_getPositionAndSelectorOrRadius(arg0, sp20); sp2C[0] = (f32)sp20[0]; sp2C[1] = (f32)sp20[1]; sp2C[2] = (f32)sp20[2]; diff --git a/src/core2/fx/effect_simplesprite.c b/src/core2/fx/effect_simplesprite.c index 1f317d764..f1d14fdef 100644 --- a/src/core2/fx/effect_simplesprite.c +++ b/src/core2/fx/effect_simplesprite.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_55180.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/fx/effect_soundemit.c b/src/core2/fx/effect_soundemit.c deleted file mode 100644 index 7044b384a..000000000 --- a/src/core2/fx/effect_soundemit.c +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include "functions.h" -#include "variables.h" - -extern void func_802F82F4(struct3s *, f32, f32, f32, f32); - -typedef struct { - s16 unk0; - //u8 pad[0x2]; - int (*unk4)(Actor *); -} Struct_Core2_D2180_0; - -typedef struct { - Struct_Core2_D2180_0 *unk0; -} ActorLocal_core2_D2180; - -int func_80359110(Actor *); -int func_8035911C(Actor *); -int func_80359110(Actor *); -int func_80359160(Actor *); -int func_80359110(Actor *); -int func_803591A4(Actor *); -void func_8035933C(Actor *this); -void func_80359424(Actor *this); -void func_80359454(Actor *this); - -/* .data */ -Struct_Core2_D2180_0 D_80372940[] ={ - {2, func_80359110}, - {2, func_8035911C}, - {3, func_80359110}, - {3, func_80359160}, - {4, func_80359110}, - {4, func_803591A4} -}; - -ActorInfo D_80372970 = { 0x1C1, 0x2AE, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_80372994 = { 0x1C1, 0x2AF, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_803729B8 = { 0x1C1, 0x2B0, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_803729DC = { 0x1C1, 0x2B1, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_80372A00 = { 0x1C1, 0x2B2, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_80372A24 = { 0x1C1, 0x2B3, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_80372A48 = { 0x1C1, 0x316, 0x0, 0, NULL, func_80359424, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_80372A6C = { 0x1C1, 0x317, 0x0, 0, NULL, func_80359454, NULL, func_80325340, 0, 0, 0.0f, 0}; - -/* .code */ -int func_80359110(Actor *this){ - return true; -} - -int func_8035911C(Actor *this){ - f32 plyr_pos[3]; - - player_getPosition(plyr_pos); - return (plyr_pos[2] < -1700.0f); -} - -int func_80359160(Actor *this){ - f32 plyr_pos[3]; - - player_getPosition(plyr_pos); - return (1700.0f < plyr_pos[2]); -} - -int func_803591A4(Actor *this){ - f32 plyr_pos[3]; - - player_getPosition(plyr_pos); - return (1700.0f < plyr_pos[0]); -} - -void func_803591E8(Actor *this, s32 next_state){ - ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; - - if(next_state == 2) - func_802F8C90(func_802F7C38()); - - if(this->state == 2) - func_802F8CB0(func_802F7C38()); - - if(next_state == 3){ - struct3s *rain = func_802F7C7C(); - func_802F8338(rain); - if(local->unk0->unk4 == func_80359110) { - func_802F82F4(rain, 5.0f, 30.0f, 5.0f, 30.0f); - } - } - - if(this->state == 3) - func_802F8358(func_802F7C7C()); - - if(next_state == 4){ - func_802F7CC0(); - func_802F90F4(); - } - if(this->state == 4){ - func_802F7CC0(); - func_802F9114(); - } - - - this->state = next_state; -} - -void func_8035933C(Actor *this){ - ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; - if(!this->volatile_initialized){ - this->volatile_initialized = true; - local->unk0 = D_80372940 + (this->modelCacheIndex - 0x2AE); - func_803591E8(this, 1); - } - if(this->state == 1){ - if(local->unk0->unk4(this)){ - func_803591E8(this, local->unk0->unk0); - } - } - if(this->state != 1){ - if(!local->unk0->unk4(this)){ - func_803591E8(this, 1); - } - } -} - -void func_80359424(Actor *this){ - if(func_803292E0(this)) - func_802F7D44(); -} - -void func_80359454(Actor *this){ - if(func_803292E0(this)) - func_802F7DE4(); -} diff --git a/src/core2/fx/effect_sparkleemit.c b/src/core2/fx/effect_sparkleemit.c index 3cdf83c99..e3127d1b4 100644 --- a/src/core2/fx/effect_sparkleemit.c +++ b/src/core2/fx/effect_sparkleemit.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_50490.c #include #include "functions.h" #include "variables.h" @@ -16,7 +17,9 @@ f32 D_80367A84 = 30.0f; f32 D_80367A88 = 150.0f; f32 D_80367A8C = 25.0f; s32 D_80367A90[4] = {250, 250, 250, 120}; -s32 D_80367AA0 = 0; + +enum dust_emitter_type_e D_80367AA0 = DUST_EMITTER_TYPE_DUST; + f32 D_80367AA4[3] = {0.0f, 0.0f, 0.0f}; ActorInfo D_80367AB0 = { diff --git a/src/core2/fx/effect_eggshatter.c b/src/core2/fx/eggshatter.c similarity index 98% rename from src/core2/fx/effect_eggshatter.c rename to src/core2/fx/eggshatter.c index 19dfb5f76..88b7db8e4 100644 --- a/src/core2/fx/effect_eggshatter.c +++ b/src/core2/fx/eggshatter.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/eggshatter.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_generic.c b/src/core2/fx/explosionripple.c similarity index 94% rename from src/core2/fx/effect_generic.c rename to src/core2/fx/explosionripple.c index a52c26a49..73edc1542 100644 --- a/src/core2/fx/effect_generic.c +++ b/src/core2/fx/explosionripple.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/explosionripple.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/firefx.c b/src/core2/fx/firefx.c index 3e60f8000..8942b86e1 100644 --- a/src/core2/fx/firefx.c +++ b/src/core2/fx/firefx.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/firefx.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/fx/droplet.c b/src/core2/fx/piranhaWaterParticles.c similarity index 94% rename from src/core2/fx/droplet.c rename to src/core2/fx/piranhaWaterParticles.c index 67a61fb79..d26d8c98f 100644 --- a/src/core2/fx/droplet.c +++ b/src/core2/fx/piranhaWaterParticles.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/piranhaWaterParticles.c #include #include "core1/core1.h" #include "functions.h" @@ -8,7 +9,7 @@ extern ParticleEmitter *func_802F4094(f32 pos[3], f32 arg1); void chPiranhaWaterParticles_update(Actor *this); /* .data */ -ActorInfo D_80367C60 = { +ActorInfo chPiranhaWaterParticles = { 0x15E, 0x188, 0x0, 0, NULL, chPiranhaWaterParticles_update, actor_update_func_80326224, func_80325340, diff --git a/src/core2/fx/projectile_anim.c b/src/core2/fx/projectile_anim.c index 3e74868fa..92137d625 100644 --- a/src/core2/fx/projectile_anim.c +++ b/src/core2/fx/projectile_anim.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CBD10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_blueegg.c b/src/core2/fx/projectile_blueegg.c index 3c5323449..20abf395c 100644 --- a/src/core2/fx/projectile_blueegg.c +++ b/src/core2/fx/projectile_blueegg.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CC1E0.c #include #include "functions.h" #include "variables.h" @@ -106,7 +107,7 @@ s32 func_803531C8(u8 projectile_indx, s32 arg1){ func_8038685C(other_marker); break; - case MARKER_BB_UNKNOWN: //L803533E4 //"BIG_JINXYHEAD" + case MARKER_BB_JINXY_HEAD_SANDYBUTT: //L803533E4 other_actor = marker_getActor(other_marker); *(s32 *)&other_actor->local = 1; commonParticle_setCurrentInUseFalse(); @@ -119,9 +120,9 @@ s32 func_803531C8(u8 projectile_indx, s32 arg1){ break; case MARKER_AB_RUBEES_EGG_POT: //L80353434 - if (collisionTri_isHitFromAbove_marker(egg_position, other_marker, 0x1E) && (func_8038E178() < func_8038E184())) { + if (collisionTri_isHitFromAbove_marker(egg_position, other_marker, 0x1E) && (func_8038E178() < rubeeEggPot_getEggGoal())) { commonParticle_setCurrentInUseFalse(); - func_8038E140(); + rubeeEggPot_addedEggToPot(); } break; @@ -180,7 +181,7 @@ void fxegg_head_spawn(void){ func_8033EA40(0, 20.0f); func_8033EA40(1, 0.0f); func_8033EA40(2, 0.0f); - _player_getPosition(sp50); + playerPosition_get(sp50); sp50[1] += spawnHeight; ml_vec3f_copy(sp68, sp50); player_getRotation(sp44); @@ -290,7 +291,7 @@ void fxegg_ass_spawn(void) { func_8033EA40(1, 0); func_8033EA40(0, 20.0f); func_8033EA40(2, 0); - _player_getPosition(marker); + playerPosition_get(marker); player_getRotation(sp30); sp30[1] = mlNormalizeAngle(sp30[1] + 180.0f); func_80256E24(sp48, 0.0f, sp30[1], 0.0f, 0.0f, -18.0f); diff --git a/src/core2/fx/projectile_render.c b/src/core2/fx/projectile_render.c index 54d8ccfce..cb562833c 100644 --- a/src/core2/fx/projectile_render.c +++ b/src/core2/fx/projectile_render.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CD6E0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_smoke.c b/src/core2/fx/projectile_smoke.c index 4dd750152..2e2a78cb6 100644 --- a/src/core2/fx/projectile_smoke.c +++ b/src/core2/fx/projectile_smoke.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CF090.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_sparkle.c b/src/core2/fx/projectile_sparkle.c index 4bc192573..8157fcd69 100644 --- a/src/core2/fx/projectile_sparkle.c +++ b/src/core2/fx/projectile_sparkle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CECD0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_spawnfx.c b/src/core2/fx/projectile_spawnfx.c index 5f943c7b3..c7b154631 100644 --- a/src/core2/fx/projectile_spawnfx.c +++ b/src/core2/fx/projectile_spawnfx.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CD3F0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_system.c b/src/core2/fx/projectile_system.c index ef858ca10..509b6321f 100644 --- a/src/core2/fx/projectile_system.c +++ b/src/core2/fx/projectile_system.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B8860.c #include "core1/core1.h" #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_ripple_spawn.c b/src/core2/fx/ripple.c similarity index 99% rename from src/core2/fx/effect_ripple_spawn.c rename to src/core2/fx/ripple.c index f30debf76..32677ab4f 100644 --- a/src/core2/fx/effect_ripple_spawn.c +++ b/src/core2/fx/ripple.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/ripple.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_sparkle.c b/src/core2/fx/shoesparkle.c similarity index 50% rename from src/core2/fx/effect_sparkle.c rename to src/core2/fx/shoesparkle.c index 84150fdad..b48ee8009 100644 --- a/src/core2/fx/effect_sparkle.c +++ b/src/core2/fx/shoesparkle.c @@ -1,53 +1,57 @@ +// BanjoDecomp: core2/fx/shoesparkle.c #include #include "functions.h" #include "variables.h" typedef struct{ - s32 unk0; + s32 frameCount; } ActorLocal_Core2_3EAD0; -void func_802C5A60(Actor *this); +void fxShoeSparkle_update(Actor *this); /* .data */ -s32 D_80365F30[] = { +s32 fxShoeSparkleFrames[] = { 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 8 }; -ActorInfo D_80365F60 = { - 0x58, 0x4E, ASSET_7DE_SPRITE_SHOE_SPARKLES, + +#define MAX_FRAME_COUNT 12 + +ActorInfo fxWadingBootsTouchSparkle = { + MARKER_58_WADING_BOOTS_TOUCH_SPARKLE, ACTOR_4E_WADING_BOOTS_TOUCH_SPARKLE, ASSET_7DE_SPRITE_SHOE_SPARKLES, 0, NULL, - func_802C5A60, actor_update_func_80326224, fxTouchSparkle_draw, + fxShoeSparkle_update, actor_update_func_80326224, fxTouchSparkle_draw, 0, 0, 0.0f, 0 }; -ActorInfo D_80365F84 = { +ActorInfo fxTurboTrainersTouchSparkle = { 0x59, 0x4F, ASSET_7DE_SPRITE_SHOE_SPARKLES, 0, NULL, - func_802C5A60, actor_update_func_80326224, fxTouchSparkle_draw, + fxShoeSparkle_update, actor_update_func_80326224, fxTouchSparkle_draw, 0, 0, 0.0f, 0 }; /* .code */ -void func_802C5A60(Actor *this){ +void fxShoeSparkle_update(Actor *this){ // Spawns a sparkle sprite when touching turbo trainers or wading boots ActorLocal_Core2_3EAD0 *local = (ActorLocal_Core2_3EAD0*)&this->local; if(!this->initialized){ switch(this->marker->id){ - case 0x58: + case MARKER_58_WADING_BOOTS_TOUCH_SPARKLE: suSetSpriteScale(this, 0.35f); break; - case 0x59: + case MARKER_59_TURBO_TRAINERS_TOUCH_SPARKLE: suSetSpriteScale(this, 0.4f); break; } this->marker->propPtr->isMirrored = 0.5 < randf(); - this->position_y += 100.0*this->scale; + this->position_y += 100.0 * this->scale; actor_collisionOff(this); this->initialized = true; }//L802C5B60 - this->marker->propPtr->frame = D_80365F30[local->unk0]; - local->unk0++; - if(local->unk0 >= 0xC) + this->marker->propPtr->frame = fxShoeSparkleFrames[local->frameCount]; + local->frameCount++; + if(local->frameCount >= MAX_FRAME_COUNT) marker_despawn(this->marker); } diff --git a/src/core2/fx/shrapnel.c b/src/core2/fx/shrapnel.c index b112945c6..225f2a28d 100644 --- a/src/core2/fx/shrapnel.c +++ b/src/core2/fx/shrapnel.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/shrapnel.c #include #include "functions.h" #include "variables.h" @@ -156,7 +157,7 @@ void chshrapnel_update(Actor *this) { this->unk1C[2] = this->position[2]; this->unk1C[1] = func_80309B24(this->position) - 15.0f; this->position[1] = this->unk1C[1] - (sinf(this->lifetime_value * 4.0f) * 10.0f); - _player_getPosition(player_position); + playerPosition_get(player_position); switch (this->state) { case 1: chShrapnel_func_802D0A38(this); diff --git a/src/core2/fx/effect_sparkle_spawn.c b/src/core2/fx/sparkle.c similarity index 99% rename from src/core2/fx/effect_sparkle_spawn.c rename to src/core2/fx/sparkle.c index 5d0d0d4f3..dfd8fe4da 100644 --- a/src/core2/fx/effect_sparkle_spawn.c +++ b/src/core2/fx/sparkle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/sparkle.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/init.c b/src/core2/fx/weather.c similarity index 98% rename from src/core2/sfx/init.c rename to src/core2/fx/weather.c index 65b251fa2..c59dc5f8a 100644 --- a/src/core2/sfx/init.c +++ b/src/core2/fx/weather.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_70C30.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/weather_emitter.c b/src/core2/fx/weather_emitter.c new file mode 100644 index 000000000..118eb4db3 --- /dev/null +++ b/src/core2/fx/weather_emitter.c @@ -0,0 +1,188 @@ +// BanjoDecomp: core2/code_D2180.c +#include +#include "functions.h" +#include "variables.h" + +extern void func_802F82F4(struct3s *, f32, f32, f32, f32); + +typedef struct { + s16 startState; + //u8 pad[0x2]; + bool (*shouldStartFunc)(Actor *); +} Struct_Core2_D2180_0; + +typedef struct { + Struct_Core2_D2180_0 *unk0; +} ActorLocal_core2_D2180; + +bool weatherParticle_isAlwaysActive(Actor *); +bool weatherParticle_shouldStartCCWHubLeafFalling(Actor *); +bool weatherParticle_isAlwaysActive(Actor *); +bool weatherParticle_shouldStartCCWHubRainFalling(Actor *); +bool weatherParticle_isAlwaysActive(Actor *); +bool weatherParticle_shouldStartCCWHubSnowFalling(Actor *); +void weatherParticle_update(Actor *this); +void func_80359424(Actor *this); +void func_80359454(Actor *this); + +/* .data */ +enum weatherParticle_state_enum { + WEATHERPARTICLE_STATE_0_NOT_INIT, + WEATHERPARTICLE_STATE_1_IDLE, + WEATHERPARTICLE_STATE_2_LEAF_FALLING, + WEATHERPARTICLE_STATE_3_RAINING, + WEATHERPARTICLE_STATE_4_SNOWING +}; + +Struct_Core2_D2180_0 D_80372940[] = { + {WEATHERPARTICLE_STATE_2_LEAF_FALLING, weatherParticle_isAlwaysActive}, + {WEATHERPARTICLE_STATE_2_LEAF_FALLING, weatherParticle_shouldStartCCWHubLeafFalling}, + {WEATHERPARTICLE_STATE_3_RAINING, weatherParticle_isAlwaysActive}, + {WEATHERPARTICLE_STATE_3_RAINING, weatherParticle_shouldStartCCWHubRainFalling}, + {WEATHERPARTICLE_STATE_4_SNOWING, weatherParticle_isAlwaysActive}, + {WEATHERPARTICLE_STATE_4_SNOWING, weatherParticle_shouldStartCCWHubSnowFalling} +}; + +ActorInfo leafEmitterCCWAutumn = { + 0x1C1, ACTOR_2AE_LEAF_EMITTER_CCW_AUTUMN, 0x0, + 0, NULL, + weatherParticle_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo leafEmitterCCWHub = { + 0x1C1, ACTOR_2AF_LEAF_EMITTER_CCW_HUB, 0x0, + 0, NULL, + weatherParticle_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo rainEmitterCCWSpring = { + 0x1C1, ACTOR_2B0_RAIN_EMITTER_CCW_SPRING, 0x0, + 0, NULL, + weatherParticle_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo rainEmitterCCWHub = { + 0x1C1, ACTOR_2B1_RAIN_EMITTER_CCW_HUB, 0x0, + 0, NULL, + weatherParticle_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo snowEmitterCCWWinter = { + 0x1C1, ACTOR_2B2_SNOW_EMITTER_CCW_WINTER, 0x0, + 0, NULL, + weatherParticle_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo snowEmitterCCWHub = { + 0x1C1, ACTOR_2B3_SNOW_EMITTER_CCW_HUB, 0x0, + 0, NULL, + weatherParticle_update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80372A48 = { + 0x1C1, ACTOR_316_UNKNOWN, 0x0, + 0, NULL, + func_80359424, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80372A6C = { + 0x1C1, ACTOR_317_UNKNOWN, 0x0, + 0, NULL, + func_80359454, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +/* .code */ +bool weatherParticle_isAlwaysActive(Actor *this){ + return TRUE; +} + +// Player's Z Position +bool weatherParticle_shouldStartCCWHubLeafFalling(Actor *this){ + f32 plyr_pos[3]; + + player_getPosition(plyr_pos); + return (plyr_pos[2] < -1700.0f); +} + +bool weatherParticle_shouldStartCCWHubRainFalling(Actor *this){ + f32 plyr_pos[3]; + + player_getPosition(plyr_pos); + return (1700.0f < plyr_pos[2]); +} + +bool weatherParticle_shouldStartCCWHubSnowFalling(Actor *this){ + f32 plyr_pos[3]; + + player_getPosition(plyr_pos); + return (1700.0f < plyr_pos[0]); +} + +void weatherParticle_setState(Actor *this, s32 next_state){ + ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; + struct3s *sp20; // [port] pointer-width + + if(next_state == WEATHERPARTICLE_STATE_2_LEAF_FALLING) + func_802F8C90(func_802F7C38()); + + if(this->state == WEATHERPARTICLE_STATE_2_LEAF_FALLING) + func_802F8CB0(func_802F7C38()); + + if(next_state == WEATHERPARTICLE_STATE_3_RAINING){ + sp20 = func_802F7C7C(); + func_802F8338(sp20); + if(local->unk0->shouldStartFunc == weatherParticle_isAlwaysActive) + func_802F82F4(sp20, 5.0f, 30.0f, 5.0f, 30.0f); + } + + if(this->state == WEATHERPARTICLE_STATE_3_RAINING) + func_802F8358(func_802F7C7C()); + + if(next_state == WEATHERPARTICLE_STATE_4_SNOWING){ + func_802F7CC0(); + func_802F90F4(); + } + if(this->state == WEATHERPARTICLE_STATE_4_SNOWING){ + func_802F7CC0(); + func_802F9114(); + } + + this->state = next_state; +} + +void weatherParticle_update(Actor *this){ + ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; + if(!this->volatile_initialized){ + this->volatile_initialized = TRUE; + local->unk0 = D_80372940 + (this->modelCacheIndex - ACTOR_2AE_LEAF_EMITTER_CCW_AUTUMN); + weatherParticle_setState(this, WEATHERPARTICLE_STATE_1_IDLE); + } + if(this->state == WEATHERPARTICLE_STATE_1_IDLE){ + if(local->unk0->shouldStartFunc(this)){ + weatherParticle_setState(this, local->unk0->startState); + } + } + if(this->state != WEATHERPARTICLE_STATE_1_IDLE){ + if(!local->unk0->shouldStartFunc(this)){ + weatherParticle_setState(this, WEATHERPARTICLE_STATE_1_IDLE); + } + } +} + +void func_80359424(Actor *this){ + if(func_803292E0(this)) + func_802F7D44(); +} + +void func_80359454(Actor *this){ + if(func_803292E0(this)) + func_802F7DE4(); +} diff --git a/src/core2/sfx/playstate.c b/src/core2/fx/weather_leaves.c similarity index 97% rename from src/core2/sfx/playstate.c rename to src/core2/fx/weather_leaves.c index a3d5020d8..557496177 100644 --- a/src/core2/sfx/playstate.c +++ b/src/core2/fx/weather_leaves.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_71820.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -22,7 +23,7 @@ void func_802F87B0(struct6s *this){ return; player_getPosition(plyrPos); - viewport_getLookbk_vector(camNorm); + viewport_getLookVector(camNorm); viewport_getRotation_vec3f(camRot); ptr = bk_vector_pushBackNew(&this->unk1C); f20 = randf2(50.0f, 1200.0f); @@ -79,7 +80,7 @@ void func_802F8A90(struct6s *this, Gfx **gdl, Mtx **mptr, Vtx **vptr){ struct5s * endPtr = bk_vector_getEnd(this->unk1C); for(iPtr = startPtr; iPtr < endPtr; iPtr++){ // [port] Stable scope per entry; vector count fluctuates. - FrameInterpolation_RecordOpenChild("playstate", (uintptr_t)(iPtr - startPtr)); + FrameInterpolation_RecordOpenChild("weather_leaf", (uintptr_t)(iPtr - startPtr)); modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); modelRender_draw(gdl, mptr, iPtr->unk4, iPtr->unk1C, 1.0f, NULL, iPtr->unk0); iPtr->unk34 = modelRender_func_8033A170(); diff --git a/src/core2/sfx/streamctrl.c b/src/core2/fx/weather_rain.c similarity index 97% rename from src/core2/sfx/streamctrl.c rename to src/core2/fx/weather_rain.c index af3324508..b43602f00 100644 --- a/src/core2/sfx/streamctrl.c +++ b/src/core2/fx/weather_rain.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_70F20.c #include #include "core1/core1.h" #include "functions.h" @@ -20,7 +21,7 @@ void func_802F7EB0(struct3s *this){ return; player_getPosition(plyrPos); - viewport_getLookbk_vector(camNorm); + viewport_getLookVector(camNorm); viewport_getRotation_vec3f(camRot); sp50 = bk_vector_pushBackNew(&this->unk20); tmpf = randf2(50.0f, 1100.0f); @@ -68,7 +69,7 @@ void func_802F8110(struct3s *this, Gfx **gdl, Mtx **mptr, u32 arg3){ endPtr = bk_vector_getEnd(this->unk20); for(iPtr = startPtr; iPtr < endPtr; iPtr++){ // [port] Per-entry stable scope — vector count varies, indices shift. - FrameInterpolation_RecordOpenChild("streamctrl", (uintptr_t)(iPtr - startPtr)); + FrameInterpolation_RecordOpenChild("weather_rain", (uintptr_t)(iPtr - startPtr)); modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); modelRender_draw(gdl, mptr, iPtr->unk0, 0, 1.0f, 0, this->unk2C); iPtr->unk18 = modelRender_func_8033A170(); diff --git a/src/core2/sfx/filedata.c b/src/core2/fx/weather_snow.c similarity index 78% rename from src/core2/sfx/filedata.c rename to src/core2/fx/weather_snow.c index b338eb09a..894ecfe53 100644 --- a/src/core2/sfx/filedata.c +++ b/src/core2/fx/weather_snow.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_72060.c #include #include "core1/core1.h" #include "functions.h" @@ -28,22 +29,22 @@ Gfx D_80369290[] = gsSPEndDisplayList(), }; -Gfx D_803692B0[] = +// [port] The flake model reaches these render modes through segment 3 at fixed byte +// offsets; one 2D array guarantees the contiguity three separate globals did not. +Gfx D_803692B0[][2] = { - gsDPSetRenderMode(Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1)), - gsSPEndDisplayList(), -}; - -Gfx D_803692C0[] = -{ - gsDPSetRenderMode(AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | G_RM_PASS, AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)), - gsSPEndDisplayList(), -}; - -Gfx D_803692D0[] = -{ - gsDPSetRenderMode(Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)), - gsSPEndDisplayList(), + { + gsDPSetRenderMode(Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1)), + gsSPEndDisplayList(), + }, + { + gsDPSetRenderMode(AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | G_RM_PASS, AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)), + gsSPEndDisplayList(), + }, + { + gsDPSetRenderMode(Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)), + gsSPEndDisplayList(), + }, }; /* .bss */ @@ -56,6 +57,7 @@ f32 D_80381080[3]; f32 D_8038108C; Gfx *D_80381090; Struct_core2_72060_0 *D_80381094; +static u32 sSnowNextId = 0; // [port] Monotonic spawn id bool func_802F989C(Gfx **gfx, Mtx **mtx, f32 arg2[3]); @@ -178,6 +180,7 @@ void func_802F919C(void) { sp40->unkC[0] = 0.0f; sp40->unkC[1] = randf2(-150.0f, -50.0f); sp40->unkC[2] = 0.0f; + sp40->id = ++sSnowNextId; } } } @@ -205,20 +208,19 @@ void func_802F962C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { func_80349AD0(); gSPSegment((*gfx)++, 1, osVirtualToPhysical(temp_s3 + 1)); gSPSegment((*gfx)++, 0x02, osVirtualToPhysical((void*)((uintptr_t)D_80369288 + D_80369288->texture_list_offset + sizeof(BKTextureList) + sizeof(BKTextureInfo)))); - gSPSetGeometryMode((*gfx)++, G_ZBUFFER); + // [port] Vanilla only sets G_ZBUFFER here, inheriting the rest of the RSP/RDP state + // from whatever drew last. GraphicsPatches.cpp substitutes a self-contained preamble. + if (EventSystem_Should(VB_SNOW_RENDER_STATE, true, gfx)) { + gSPSetGeometryMode((*gfx)++, G_ZBUFFER); + } gSPDisplayList((*gfx)++, D_80369290); - gSPSegment((*gfx)++, 0x03, osVirtualToPhysical(&D_803692B0)); + gSPSegment((*gfx)++, 0x03, osVirtualToPhysical(D_803692B0)); D_80381094 = (Struct_core2_72060_0 *)((uintptr_t)D_80369288 + D_80369288->geo_list_offset); for(phi_s0 = D_80369280->unk1C; phi_s0 < D_80369280->unk1C + D_80369284; phi_s0++) { - // [port] Scope keyed on position — array shrinks below the - // height threshold and frustum culls inside func_802F989C, so - // index-based pairing would mismatch surviving items. - FrameInterpolation_RecordOpenChildHash3("grass_item", - FrameInterpolation_FloatBits(phi_s0->unk0[0]), - FrameInterpolation_FloatBits(phi_s0->unk0[1]), - FrameInterpolation_FloatBits(phi_s0->unk0[2])); + // [port] Scope keyed on spawn id + FrameInterpolation_RecordOpenChild("weather_snow", phi_s0->id); if ((func_802F989C(gfx, mtx, phi_s0->unk0) == 0) && (phi_s0->unk0[1] < D_8038104C)) { func_802F9134(phi_s0 - D_80369280->unk1C); phi_s0--; @@ -242,8 +244,12 @@ bool func_802F989C(Gfx **gfx, Mtx **mtx, f32 arg2[3]) { mlMtxApply(*mtx); mlMtx_apply_vec3f_restricted(D_80381080, D_80381094->unkC); func_80251B5C(D_80381080[0], D_80381080[1], D_80381080[2]); - mlMtx_rotate_yaw_deg(D_80381060[1]); - mlMtx_rotate_pitch_deg(D_80381060[0]); + // [port] Cancelled by PerfPatches.cpp, which applies the same rotations + // with the trig cached across flakes. + if (EventSystem_Should(VB_SNOW_CAMERA_ROTATION, true, D_80381060)) { + mlMtx_rotate_yaw_deg(D_80381060[1]); + mlMtx_rotate_pitch_deg(D_80381060[0]); + } func_80252A38(-(D_80381094->unkC[0]), -(D_80381094->unkC[1]), -(D_80381094->unkC[2])); mlMtxApply(*mtx); gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW); diff --git a/src/core2/fx/whipcrack.c b/src/core2/fx/whipcrack.c index 92b8d56f0..72cddba8b 100644 --- a/src/core2/fx/whipcrack.c +++ b/src/core2/fx/whipcrack.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/whipcrack.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gameSelect.c b/src/core2/gameSelect.c index 22c1322a7..8238aae99 100644 --- a/src/core2/gameSelect.c +++ b/src/core2/gameSelect.c @@ -1,11 +1,13 @@ +// BanjoDecomp: core2/ch/gameSelect.c #include #include "functions.h" #include "variables.h" +#include "ch/gameSelect.h" #include "core2/modelRender.h" #include "core2/gc/zoombox.h" -#include "core2/quiz_storage.h" +#include "core2/quiz/storage.h" #include "port/Romhack/RomhackConfig.h" #include "port/Patches/Patches.h" @@ -71,7 +73,7 @@ ActorAnimationInfo banjoGameboyAnimations[] = { {0x24F, 0.6f}, {0x24D, 2.0f} }; -ActorInfo D_80365E58 = { 0xE4, 0x195, 0x532, 0x1, banjoGameboyAnimations, gameSelect_initAndUpdate, actor_update_func_80326224, gameSelect_zoomboxDraw, 0, 0, 0.0f, 0}; +ActorInfo gameSelect_banjoSleeping = { 0xE4, 0x195, 0x532, 0x1, banjoGameboyAnimations, gameSelect_initAndUpdate, actor_update_func_80326224, gameSelect_zoomboxDraw, 0, 0, 0.0f, 0}; ActorAnimationInfo D_80365E7C[] = { {0x000, 0.0f}, @@ -81,7 +83,7 @@ ActorAnimationInfo D_80365E7C[] = { {0x252, 0.67f}, {0x250, 4.5f}, }; -ActorInfo D_80365EAC = { 0xE5, 0x196, 0x532, 0x1, D_80365E7C, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; +ActorInfo gameSelect_banjoGameboy = { 0xE5, 0x196, 0x532, 0x1, D_80365E7C, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; ActorAnimationInfo D_80365ED0[] = { {0x000, 0.0f}, @@ -91,12 +93,19 @@ ActorAnimationInfo D_80365ED0[] = { {0x24C, 1.0f}, {0x24A, 1.0f} }; -ActorInfo D_80365F00 = { 0xE6, 0x197, 0x532, 0x1, D_80365ED0, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; +ActorInfo gameSelect_banjoCooking = { 0xE6, 0x197, 0x532, 0x1, D_80365ED0, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; +// Yes, Gaming Chair is before Kitchen +enum chgameselect_savefile_e { + CH_GAME_SELECT_SAVEFILE_0_BED, + CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR, + CH_GAME_SELECT_SAVEFILE_2_KITCHEN +}; + /* .bss */ s32 mm_hut_smash_count; -u32 CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; +u32 chtreasureHunt_puzzleCurrentStep; struct FF_StorageStruct* ffStorage; s32 mmhut_smashCount; u8 gCompletedBottlesBonusGames[7]; // bottle bonus puzzle? @@ -131,16 +140,16 @@ f32 D_8037DD34; /* .code */ Actor *gameSelect_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ s32 sp1C = marker->id - 0xe4; - func_8033A45C(3, sp1C); - func_8033A45C(1, 1); - func_8033A45C(4, 1); - func_8033A45C(9, 1); - func_8033A45C(5, 0); - func_8033A45C(8, 0); - func_8033A45C(6, 0); - func_8033A45C(7, 0); - func_8033A45C(0xC, 1); - func_8033A45C(0xF, 1); + modelRender_setAppendageVisibility(3, sp1C); + modelRender_setAppendageVisibility(1, 1); + modelRender_setAppendageVisibility(4, 1); + modelRender_setAppendageVisibility(9, 1); + modelRender_setAppendageVisibility(5, 0); + modelRender_setAppendageVisibility(8, 0); + modelRender_setAppendageVisibility(6, 0); + modelRender_setAppendageVisibility(7, 0); + modelRender_setAppendageVisibility(0xC, 1); + modelRender_setAppendageVisibility(0xF, 1); if(sp1C == D_80365E00){ modelRender_setEnvColor(0xFF, 0xFF, 0xFF, 0xFF); } @@ -215,13 +224,13 @@ void setGameInformationZoombox(s32 gamenum){ strcpy(upperTextLine, ""); strcat(upperTextLine, sGamePrefix[lang]); switch(gamenum){ - case 0: //L802C4820 + case CH_GAME_SELECT_SAVEFILE_0_BED: //L802C4820 strIToA(upperTextLine, 1); break; - case 1: //L802C4838 + case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: //L802C4838 strIToA(upperTextLine, 3); break; - case 2: //L802C484C + case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: //L802C484C strIToA(upperTextLine, 2); break; }//L802C4858 @@ -250,13 +259,13 @@ void setGameInformationZoombox(s32 gamenum){ strcpy(upperTextLine, ""); strcat(upperTextLine, sGamePrefix[lang]); switch (gamenum){ - case 0: + case CH_GAME_SELECT_SAVEFILE_0_BED: strIToA(upperTextLine, 1); break; - case 1: + case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: strIToA(upperTextLine, 3); break; - case 2: + case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: strIToA(upperTextLine, 2); break; }//L802C4A40 @@ -276,6 +285,8 @@ void setGameInformationZoombox(s32 gamenum){ void eraseGame(s32 arg0){ gameFile_clear(arg0); + // [port] The clear only zeroes the slot in RAM; also delete the file. + CALL_EVENT(OnGameFileErase, arg0); setGameInformationZoombox(arg0); } @@ -349,7 +360,7 @@ void gameSelect_update(Actor *this){ __spawnQueue_add_1((GenFunction_1)spawnGameSelectProps, (uintptr_t)this->marker); func_802C7318(this); this->unk130 = func_802C71F0; - if(sp84 == 0){ + if(sp84 == CH_GAME_SELECT_SAVEFILE_0_BED){ func_802C75A0(this, 1); func_802C74F4(this, 0, 1.0f); func_802C74F4(this, 1, 1.0f); @@ -370,20 +381,20 @@ void gameSelect_update(Actor *this){ case 2: case 5: switch(sp84){ - case 0://L802C4D8C + case CH_GAME_SELECT_SAVEFILE_0_BED://L802C4D8C if(actor_animationIsAt(this, 0.1f)) sfxsource_play(SFX_5D_BANJO_RAAOWW, 8000); if(actor_animationIsAt(this, 0.7f)) sfxsource_play(SFX_5E_BANJO_PHEWWW, 8000); break; - case 1://L802C4DD0 + case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR://L802C4DD0 if(randf() < 0.1){ // if(randf() < D_80376118){ gcsfx_playWithPitch(MIN(2.0f, randf() *3.0f) + 311.0f, 1.0f, 12000); } break; - case 2://L802C4E74 + case CH_GAME_SELECT_SAVEFILE_2_KITCHEN://L802C4E74 if(randf() < 0.03){ gcsfx_playWithPitch(0x3ed, randf()*0.3 + 0.7, 15000); } @@ -394,7 +405,7 @@ void gameSelect_update(Actor *this){ if(!func_8038AAB0()){ switch(this->state){ case 1://L802C4F10 - if(sp84 == 1){ + if(sp84 == CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR){ sfxsource_play(SFX_136_GAMEBOY_STARTUP, 15000); timedFunc_set_3(0.25f, (GenFunction_3)comusic_8025AB44, COMUSIC_73_GAMEBOY, -1, 2000); func_8025A58C(0, 2000); @@ -404,7 +415,7 @@ void gameSelect_update(Actor *this){ func_8025A58C(-1, 2000); } - if(sp84 == 2){ + if(sp84 == CH_GAME_SELECT_SAVEFILE_2_KITCHEN){ D_8037DD28 = func_802F9AA8(SFX_12B_BOILING_AND_BUBBLING); func_802F9F80(D_8037DD28, 0.5f, 9000000000.0f, 0.5f); func_802F9DB8(D_8037DD28, 0.9f, 0.9f, 0.0f); @@ -441,14 +452,15 @@ void gameSelect_update(Actor *this){ chBottlesBonus_resetCompleted(); gameFile_load(gSelectedGameNum); port_syncBottlesBonusIndex(); - if(!gameFile_isNotEmpty(sp84)){ + CALL_EVENT(OnGameStart); + if(EventSystem_Should(VB_GAMESELECT_START_NEW_GAME, !gameFile_isNotEmpty(sp84), sp84)){ s32 skipIntro = 0; CALL_EVENT(OnNewGame, &skipIntro); if (skipIntro) { timedFunc_set_2(0.0f, (GenFunction_2)warp_lairEnterLairFromSMLevel, 0, 0); timedFunc_set_1(0.0f, (GenFunction_1)gsworld_setEnableUpdate, 1); } else { - // [port] BB romhacks can override the new-game boot map + // [port] Romhacks can override the new-game boot map s32 newGameMap = port_getRomhackNewGameMap(); if (newGameMap < 0) { newGameMap = MAP_85_CS_SPIRAL_MOUNTAIN_3; @@ -456,15 +468,18 @@ void gameSelect_update(Actor *this){ timedFunc_set_3(0.0f, (GenFunction_3)transitionToMap, newGameMap, 0, 1); if (port_getRomhackKnowAllMoves() >= 0) { ability_setAllLearned(-1); - ability_setAllUsed(-1); } } } else{//L802C511C sp44 = 0.0f; - if(this->state == 4 && (sp84 == 0 || sp84 == 1)) + if(this->state == 4 && (sp84 == CH_GAME_SELECT_SAVEFILE_0_BED || sp84 == CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR)) sp44 = 0.25f; - if(chmole_learnedAllSpiralMountainAbilities() && fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE)){ + // [port] Romhacks can replace the resume transition outright + if(port_getRomhackResumeWarpFunc() != NULL){ + timedFunc_set_2(sp44, (GenFunction_2)port_getRomhackResumeWarpFunc(), 0, 0); + } + else if(chmole_learnedAllSpiralMountainAbilities() && fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE)){ timedFunc_set_2(sp44, (GenFunction_2)warp_lairEnterLairFromSMLevel, 0, 0); } else{//L802C5188 @@ -493,22 +508,22 @@ void gameSelect_update(Actor *this){ if(gameFile_isNotEmpty(sp84)){ if(randf() < 0.1){ switch(sp84){ - case 0://L802C52B8 + case CH_GAME_SELECT_SAVEFILE_0_BED://L802C52B8 sfxsource_play(SFX_31_BANJO_OHHWAAOOO, 28000); - gcsfx_playAtSampleRate(SFX_135_CARTOONY_SPRING); + gcsfx_play(SFX_135_CARTOONY_SPRING); timedFunc_set_2(0.4f, (GenFunction_2)sfxsource_play, SFX_13A_GLASS_BREAKING_7, 0x7fff); timedFunc_set_2(0.9f, (GenFunction_2)sfxsource_play, SFX_150_PORCELAIN_CRASH, 0x7fff); timedFunc_set_2(1.0f, (GenFunction_2)sfxsource_play, SFX_151_CAT_MEOW, 0x7fff); break; - case 1://L802C5320 + case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR://L802C5320 timedFunc_set_2(0.4f, (GenFunction_2)sfxsource_play, SFX_31_BANJO_OHHWAAOOO, 28000); timedFunc_set_2(0.2f, (GenFunction_2)sfxsource_play, SFX_E_SHOCKSPRING_BOING, 28000); - gcsfx_playAtSampleRate(SFX_2D_KABOING); + gcsfx_play(SFX_2D_KABOING); break; - case 2://L802C5364 + case CH_GAME_SELECT_SAVEFILE_2_KITCHEN://L802C5364 timedFunc_set_2(0.15f, (GenFunction_2)sfxsource_play, SFX_32_BANJO_EGHEE, 28000); sfxsource_play(SFX_3F6_RUBBING, 28000); - gcsfx_playAtSampleRate(SFX_8F_SNOWBALL_FLYING); + gcsfx_play(SFX_8F_SNOWBALL_FLYING); break; }//L802C5394 subaddie_set_state(this, 4); @@ -522,10 +537,10 @@ void gameSelect_update(Actor *this){ sfxsource_play(SFX_4F_BANJO_WAHOO, 28000); subaddie_set_state(this, 3); }//L802C53E8 - if(sp84 == 0) + if(sp84 == CH_GAME_SELECT_SAVEFILE_0_BED) func_802C75A0(this, 2); - if(sp84 == 1) + if(sp84 == CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR) comusic_8025AB44(COMUSIC_73_GAMEBOY, 0, 4000); func_8025A58C(0, 0x1f4); @@ -538,28 +553,28 @@ void gameSelect_update(Actor *this){ if(sp54[0] < 0.0f){ D_8037DCEC = 1; switch(D_80365E00){ - case 0: + case CH_GAME_SELECT_SAVEFILE_0_BED: D_8037DCEC = 0; break; - case 1: - D_80365E00 = 2; + case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: + D_80365E00 = CH_GAME_SELECT_SAVEFILE_2_KITCHEN; break; - case 2: - D_80365E00 = 0; + case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: + D_80365E00 = CH_GAME_SELECT_SAVEFILE_0_BED; break; } } else{//L802C54D4 D_8037DCEC = 1; switch(D_80365E00){ - case 0: - D_80365E00 = 2; + case CH_GAME_SELECT_SAVEFILE_0_BED: + D_80365E00 = CH_GAME_SELECT_SAVEFILE_2_KITCHEN; break; - case 1: + case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: D_8037DCEC = 0; break; - case 2: - D_80365E00 = 1; + case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: + D_80365E00 = CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR; break; } }//L802C550C @@ -602,7 +617,6 @@ void gameSelect_update(Actor *this){ ); if(this->marker->unk14_21) { osViBlack(0); - port_setViBlack(0); } }//L802C5734 } @@ -633,8 +647,8 @@ void gameSelect_initAndUpdate(Actor * this){ D_8037DCEC = 0; debugScoreStates(); clearScoreStates(); - D_8037DCE8 = 0; - D_80365E00 = 0; + D_8037DCE8 = CH_GAME_SELECT_SAVEFILE_0_BED; + D_80365E00 = CH_GAME_SELECT_SAVEFILE_0_BED; cameraPositions[1][0] = D_80365DD0[0][0]; cameraPositions[1][1] = D_80365DD0[0][1]; cameraPositions[1][2] = D_80365DD0[0][2]; @@ -660,6 +674,11 @@ void gameSelect_saveAndExit(void){ s32 sp1C = level_get(); s32 t6 = gsworld_getMap() == MAP_83_CS_GAME_OVER_MACHINE_ROOM; s32 a1 = (0 < sp1C && sp1C < 0xd); + // [port] Permadeath erases the save on death; the game over path routes back through + // here, and saving would write the still-live game state over the erased slot. + if(!EventSystem_Should(VB_SAVE_AND_EXIT, true)){ + return; + } if( a1 || t6) { if(D_80365E00 != -1 && !func_802E4A08() && gsworld_getMap() != MAP_91_FILE_SELECT){ diff --git a/src/core2/gameloop.c b/src/core2/gameloop.c index 8ce87f1ca..c48c00169 100644 --- a/src/core2/gameloop.c +++ b/src/core2/gameloop.c @@ -1,8 +1,12 @@ +// BanjoDecomp: core2/code_5C870.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +extern void Graphics_PushFrame(Gfx* data); +extern void Framebuffer_ReadbackGPU(int bufferIndex); + #include "gc/gctransition.h" #include "bk_time.h" #include "port/Patches/Patches.h" @@ -15,10 +19,10 @@ extern void func_8025A2B0(void); extern void func_8025A430(s32, s32, s32); extern void gsworld_setEnableUpdate(s32); extern void func_8034BB90(void); -extern void func_8030C27C(void); +extern void picturebox_spawn(void); extern void func_80321C34(void); extern void func_8030ED0C(void); -extern void comusicPlayer_update(void); +extern void coMusicPlayer_update(void); enum transition_e { TRANSITION_0_NONE @@ -111,50 +115,46 @@ void func_802E38E8(enum map_e map, s32 exit, s32 reset_on_load){ void func_802E398C(s32 arg0) { gsworld_free(); func_8030ED0C(); - comusicPlayer_update(); + coMusicPlayer_update(); if (arg0 != 0) { func_802E3854(); } } -void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4){ - Mtx* m_start = *mptr; - Vtx* v_start = *vptr; +void func_802E39D0(Gfx **gfx, Mtx **mtx, Vtx **vtx, s32 framebuffer_idx, bool arg4) { + Mtx* mtx_start = *mtx; + Vtx* vtx_start = *vtx; - scissorBox_SetForGameMode(gdl, framebuffer_idx); + setupFramebufferForGamemode(gfx, framebuffer_idx); D_8037E8E0.unkC = false; port_mirror_beginScene(); - gsworld_draw(gdl, mptr, vptr); - CALL_EVENT(OnWorldDraw, gdl, mptr, vptr); + gsworld_draw(gfx, mtx, vtx); + CALL_EVENT(OnWorldDraw, gfx, mtx, vtx); port_mirror_endScene(); - port_mirror_undoProjection(gdl, mptr); - if (port_shouldCaptureTransition()) { - port_captureTransitionFb(gdl); - } + port_mirror_undoProjection(gfx, mtx); if(!arg4){ func_802E67AC(); func_802E3BD0(getActiveFramebuffer()); func_802E67C4(); - func_802E5F10(gdl); + func_802E5F10(gfx); } - if( D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE - && D_8037E8E0.unk19 != 6 - && D_8037E8E0.unk19 != 5 - ){ - gctransition_draw(gdl, mptr, vptr); + + if ((D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE) && (D_8037E8E0.unk19 != 6) && (D_8037E8E0.unk19 != 5)) { + if (port_shouldCaptureTransition()) { + port_captureTransitionFb(gfx); + } + gctransition_draw(gfx, mtx, vtx); } // [port] Return rendering to main FB after scene draw + transitions for // SNS/Bottles modes. Must come AFTER gctransition_draw so the transition // fade renders into the aux FB (visible on the picture), not the main FB. if (D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS || D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE) { - gsSPResetFB((*gdl)++); + gsSPResetFB((*gfx)++); } - if( D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS - || D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE - ){ - func_8030C2D4(gdl, mptr, vptr); + if ((D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS) || (D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE)) { + picturebox_resetScissorBoxAndFramebuffer(gfx, mtx, vtx); } // [port] Skip all HUD/overlay draws while pause menu is capturing the @@ -163,42 +163,44 @@ void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 a bool capturing = gcpausemenu_isCapturing(); if(!game_is_frozen() && gsworld_getEnableDraw() && !capturing){ - func_8032D474(gdl, mptr, vptr); + core2_A5BC0_drawScreenOverlayMarkers(gfx, mtx, vtx); } - gcpausemenu_draw(gdl, mptr, vptr); + gcpausemenu_draw(gfx, mtx, vtx); if(!game_is_frozen() && !capturing){ - dummy_func_8025AFC0(gdl, mptr, vptr); + // dummy_func_8025AFC0(gfx, mtx, vtx); } if (!capturing) { - gcdialog_draw(gdl, mptr, vptr); + gcdialog_draw(gfx, mtx, vtx); } if(!game_is_frozen() && !capturing){ - itemPrint_draw(gdl, mptr, vptr); + itemPrint_draw(gfx, mtx, vtx); } if (!capturing) { - printbuffer_draw(gdl, mptr, vptr); + CALL_EVENT(OnHudDraw, gfx, mtx, vtx); + printbuffer_draw(gfx, mtx, vtx); } - if( D_8037E8E0.game_mode != GAME_MODE_A_SNS_PICTURE - || D_8037E8E0.unk19 == 6 - || D_8037E8E0.unk19 == 5 - ){ - gctransition_draw(gdl, mptr, vptr); + if ((D_8037E8E0.game_mode != GAME_MODE_A_SNS_PICTURE) || (D_8037E8E0.unk19 == 6) || (D_8037E8E0.unk19 == 5)) { + // [port] Snapshot the composed frame for the falling-jiggy piece textures. + if (port_shouldCaptureTransition()) { + port_captureTransitionFb(gfx); + } + gctransition_draw(gfx, mtx, vtx); } // [port] Populate gFramebuffers from the GPU via gDPReadFB at native resolution. // Transitions and particles read from gFramebuffers during game logic. // On N64, gFramebuffers was the render target directly; on PC the GPU renders // to its own buffer, so we read it back here when requested. if (port_consumeReadbackRequest()) { - gDPReadFB((*gdl)++, 0, (u16 *)gFramebuffers[getActiveFramebuffer()], + gDPReadFB((*gfx)++, 0, (u16 *)gFramebuffers[getActiveFramebuffer()], 0, 0, gFramebufferWidth, gFramebufferHeight, 1); } - core1_15B30_finishDList(gdl); - osWritebackDCache(m_start, sizeof(Mtx)*( *mptr - m_start)); - osWritebackDCache(v_start, sizeof(Vtx)*( *vptr - v_start)); + core1_15B30_finishDList(gfx); + osWritebackDCache(mtx_start, sizeof(Mtx)*( *mtx - mtx_start)); + osWritebackDCache(vtx_start, sizeof(Vtx)*( *vtx - vtx_start)); } void func_802E3BD0(s32 frame_buffer_indx){ @@ -229,10 +231,10 @@ void game_setMode(enum game_mode_e next_mode, s32 arg1){ //L802E3C84 if(next_mode == GAME_MODE_8_BOTTLES_BONUS || next_mode == GAME_MODE_A_SNS_PICTURE){ - func_8030C1A0(); + picturebox_init(); } else{ - func_8030C204(); + picturebox_free(); }//L802E3CB4 D_8037E8E0.game_mode = next_mode; @@ -291,6 +293,7 @@ void func_802E3E7C(enum game_mode_e mode){ s32 sp28; s32 prev_mode; s32 prev_map; + s32 outgoing_mode = D_8037E8E0.game_mode; // [port] game_setMode below overwrites it core1_15B30_sendMesg3ToRenderThread(); sp34 = D_8037E8E0.unk18; @@ -300,13 +303,16 @@ void func_802E3E7C(enum game_mode_e mode){ prev_mode = D_8037E8E0.unk0; game_setMode(GAME_MODE_2_UNKNOWN, 0); if(!volatileFlag_getAndSet(VOLATILE_FLAG_21, 0) || map_getLevel(gsworld_getMap()) == map_getLevel(D_8037E8E0.map)){ - if(!volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE)) + if(!volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) + && EventSystem_Should(VB_MAP_SAVESTATE_USE, true, outgoing_mode)) mapSavestate_save(gsworld_getMap()); } func_802E398C(1); prev_map = gsworld_getMap(); func_802E38E8(map, sp28, sp34); - mapSavestate_apply(map); + if(EventSystem_Should(VB_MAP_SAVESTATE_USE, true, mode)){ + mapSavestate_apply(map); + } D_8037E8E0.unk0 = prev_mode; game_setMode(mode, sp30); jiggylist_map_actors(); @@ -318,26 +324,21 @@ s32 func_802E3F80(void){ return D_8037E8E0.unk0; } -extern void Graphics_PushFrame(Gfx* data); -extern void Framebuffer_ReadbackGPU(int bufferIndex); - -void game_draw(s32 arg0){ - Gfx *gfx; - Gfx *gfx_start; - Gfx *sp2C; +void game_draw(bool arg0) { + Gfx *gfx, *gfx_start, *gfx_end; Mtx *mtx; Mtx *mtx_start; Vtx *vtx; Vtx *vtx_start; - if(arg0) { + if (arg0) { scissorBox_setDefault(); } - getGraphicsStacks(&gfx, &mtx, &vtx); + graphicscache_swapAndGetStacks(&gfx, &mtx, &vtx); - if(D_8037E8E0.unkC == 1){ - getGraphicsStacks(&gfx, &mtx, &vtx); + if (D_8037E8E0.unkC == TRUE) { // BUG: Compares explicit for integral value of TRUE, instead for true-ness + graphicscache_swapAndGetStacks(&gfx, &mtx, &vtx); } gfx_start = gfx; @@ -346,6 +347,11 @@ void game_draw(s32 arg0){ func_802E39D0(&gfx, &mtx, &vtx, getActiveFramebuffer(), arg0); + // [port] Frame submission gate + if (!EventSystem_Should(VB_PICTUREBOX_SUBMIT_FRAME, true, (s32)(gfx - gfx_start))) { + return; + } + graphicsCache_checkFrame(gfx_start, gfx, mtx_start, mtx, vtx_start, vtx); // Lighthouse [Port] not sure if this should be here or after the following block @@ -355,11 +361,11 @@ void game_draw(s32 arg0){ Framebuffer_ReadbackGPU(getActiveFramebuffer()); if(D_8037E8E0.unkC == 0){ - sp2C = gfx; + gfx_end = gfx; viMgr_func_8024C1DC(); - core1_15B30_addF3DEXTaskData_40000000(gfx_start, sp2C); + core1_15B30_addF3DEXTaskData_40000000(gfx_start, gfx_end); - if(arg0) { + if (arg0) { scissorBox_setDefault(); } } @@ -379,6 +385,8 @@ void transitionToMap(enum map_e map, s32 exit, s32 transition){ } void func_802E40A8(s32 map, s32 exit){ + // [port] Romhack gate: listeners may rewrite the requested destination. + EventSystem_Should(VB_MAP_CHANGE_REQUEST, true, &map, &exit); D_8037E8E0.unk18 = 1; D_8037E8E0.map = map; D_8037E8E0.exit = exit; @@ -389,6 +397,8 @@ void func_802E40C4( s32 arg0){ } void func_802E40D0(s32 map, s32 exit){ + // [port] Romhack gate: listeners may rewrite the requested destination. + EventSystem_Should(VB_MAP_CHANGE_REQUEST, true, &map, &exit); D_8037E8E0.unk18 = 0; D_8037E8E0.map = map; D_8037E8E0.exit = exit; @@ -420,13 +430,13 @@ void func_802E4170(void){ timedFuncQueue_free(); func_802F9C48(); modelRender_free(); - depthBuffer_stub(); + depthbuffer_stub(); func_802E398C(0); func_8030AFD8(0); func_80321854(); debugScoreStates(); animCache_free(); - comusicPlayer_free(); + coMusicPlayer_free(); func_8030D8DC(); } @@ -435,12 +445,12 @@ void func_802E4214(enum map_e map_id){ D_8037E8E0.unk19 = D_8037E8E0.unk18 = 0; D_8037E8E0.map = D_8037E8E0.exit = D_8037E8E0.unk17 = 0; D_8037E8E0.unk1B = D_8037E8E0.unk1A = 0; - D_8037E8E0.unkC = 0; + D_8037E8E0.unkC = FALSE; D_8037E8E0.unk1C = 0; savedata_init(); sns_save_and_update_global_data(); func_8030D86C(); - comusicPlayer_init(); + coMusicPlayer_init(); func_80322764(); timedFuncQueue_init(); func_802F9CD8(); @@ -452,7 +462,7 @@ void func_802E4214(enum map_e map_id){ func_802E5F38(); defragManager_init(); modelRender_init(); - func_80253428(1); + depthbuffer_enable(TRUE); animCache_init(); viewport_reset(); viewport_setNearAndFar(1.0f, 10000.0f); @@ -480,6 +490,9 @@ void func_802E4384(void){ } else{ func_8033DC18(); + // [port] Latch this cutscene frame's stutter before anything reads it, so the + // time delta below and the renderer's frame budget agree for the whole tick. + port_tickCutsceneStutter(); // [port] Use a fixed 2-VI timestep for normal gameplay. s32 viDivisor = viMgr_func_8024BFA0(); func_8033DC20(); // always consume wall-clock to keep last_ticks fresh @@ -561,6 +574,7 @@ bool func_802E4424(void) { return false; case 7: /* switch 1 */ + port_beginDemoAudioHold(); func_8034B8C0(D_8037E8E0.map, D_8037E8E0.exit); func_802E3E7C(GAME_MODE_8_BOTTLES_BONUS); return false; @@ -592,11 +606,11 @@ bool func_802E4424(void) { sp1C = gsworld_update(); func_80321C34(); func_8030ED0C(); - comusicPlayer_update(); + coMusicPlayer_update(); switch (D_8037E8E0.game_mode) { case GAME_MODE_8_BOTTLES_BONUS: case GAME_MODE_A_SNS_PICTURE: - func_8030C27C(); + picturebox_spawn(); /* fallthrough */ case GAME_MODE_7_ATTRACT_DEMO: /* fallthrough */ @@ -685,7 +699,7 @@ s32 game_defrag(void){ gcpausemenu_defrag(); switch(overlayManager_getLoadedID()){ case OVERLAY_2_WHALE: - func_803894A0(); + maClanker_defrag(); break; case OVERLAY_D_WITCH: code_C9E70_defrag(); diff --git a/src/core2/gamestate.c b/src/core2/gamestate.c index 0ea5ed961..b8534231b 100644 --- a/src/core2/gamestate.c +++ b/src/core2/gamestate.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_BEF20.c #include #include "core1/core1.h" #include "functions.h" @@ -29,7 +30,12 @@ bool func_80347A4C(void); /* .code */ void func_80345EB0(enum item_e item){ if(func_802FAFE8(item)){ - item_adjustByDiffWithHud(item, (s32)(-time_getDelta()*60.0f * 1.1)); + // [port] Pin the Bottles Bonus hourglass for timer consistency + f32 dt = time_getDelta(); + if(item == ITEM_0_HOURGLASS_TIMER && getGameMode() == GAME_MODE_8_BOTTLES_BONUS){ + dt = 1.0f / 30.0f; + } + item_adjustByDiffWithHud(item, (s32)(-dt*(float)(FRAMERATE) * 1.1)); }else{ code_73640_printItemCount(item); } @@ -53,7 +59,7 @@ s32 item_getCount(enum item_e item){ } // func_80345FB4 -s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud){ +s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent){ // Modifies the count of an item by the diff // no_hud determines whether the HUD pops up during the adjustment s32 oldVal; @@ -93,7 +99,7 @@ s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud){ sp34 = ((fileProgressFlag_get(FILEPROG_B9_DOUBLE_HEALTH))? 2 : 1); D_80385F30[ITEM_15_HEALTH_TOTAL] = MIN(sp34*8, D_80385F30[ITEM_15_HEALTH_TOTAL]); D_80385F30[ITEM_14_HEALTH]= MIN(D_80385F30[ITEM_15_HEALTH_TOTAL], D_80385F30[ITEM_14_HEALTH]); - D_80385F30[ITEM_17_AIR] = MIN(3600, D_80385F30[ITEM_17_AIR]); + D_80385F30[ITEM_17_AIR] = MIN(VER_SELECT(3600, 3000, 0, 0), D_80385F30[ITEM_17_AIR]); D_80385F30[ITEM_25_MUMBO_TOKEN_TOTAL] = D_80385F30[ITEM_1C_MUMBO_TOKEN]; D_80385F30[ITEM_16_LIFE] = MIN(0xFF, D_80385F30[ITEM_16_LIFE]); @@ -175,6 +181,9 @@ s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud){ D_80385F30[ITEM_2B_UNKNOWN] += diff; break; } + if (triggerEvent) { + CALL_EVENT(OnItemCountChanged, item, D_80385F30[item]); + } return D_80385F30[item]; } @@ -182,18 +191,22 @@ s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud){ s32 item_adjustByDiffWithHud(enum item_e item, s32 diff){ // Modifies the count of an item by the diff // Displays the HUD during the adjustment - return item_adjustByDiff(item, diff, 0); + return item_adjustByDiff(item, diff, 0, 1); } // item_adjustByDiffWithoutHud void item_adjustByDiffWithoutHud(enum item_e item, s32 diff){ // Modifies the count of an item by the diff // Does not display the HUD during the adjustment - item_adjustByDiff(item, diff, 1); + item_adjustByDiff(item, diff, 1, 1); +} + +void item_setEx(s32 item, s32 val, s32 triggerEvent){ + item_adjustByDiff(item, val - item_getCount(item), 0, triggerEvent); } void item_set(s32 item, s32 val){ - item_adjustByDiffWithHud(item, val - item_getCount(item)); + item_setEx(item, val, 1); } // item_setMaxCount @@ -215,7 +228,7 @@ void item_setItemsStartCounts(void){ D_80385F30[ITEM_10_GOLD_FEATHER] = 0; D_80385F30[ITEM_14_HEALTH] = D_80385F30[ITEM_15_HEALTH_TOTAL] = 5; D_80385F30[ITEM_16_LIFE] = 3; - D_80385F30[ITEM_17_AIR] = 3600; + D_80385F30[ITEM_17_AIR] = VER_SELECT(3600, 3000, 0, 0); D_80385F30[ITEM_1C_MUMBO_TOKEN] = 0; D_80385F30[0x2B] = 0; D_80385F30[ITEM_26_JIGGY_TOTAL] = 0; @@ -235,7 +248,7 @@ void itemscore_levelReset(enum level_e level){ D_80385F30[ITEM_C_NOTE] = 0; D_80385F30[ITEM_E_JIGGY] = jiggyscore_leveltotal(level); D_80385F30[ITEM_12_JINJOS] = 0; - D_80385F30[ITEM_17_AIR] = 3600; + D_80385F30[ITEM_17_AIR] = VER_SELECT(3600, 3000, 0, 0); D_80385F30[ITEM_18_GOLD_BULLIONS] = 0; D_80385F30[ITEM_19_ORANGE] = 0; D_80385F30[ITEM_23_ACORNS] = 0; @@ -318,16 +331,16 @@ void func_803465E4(void){ D_80385FEC = MAX(0.0, D_80385FEC - time_getDelta()); }//L80346870 if( (!is_in_polluted_or_winter_water && is_underwater) || (is_in_polluted_or_winter_water && is_on_water_surface) ){//L80346894 - item_adjustByDiffWithHud(ITEM_17_AIR, (s32)((f64)((-time_getDelta())*60.0f)*1.1)); + item_adjustByDiffWithHud(ITEM_17_AIR, (s32)((f64)((-time_getDelta())*(float)(FRAMERATE))*1.1)); } else{ if(is_in_polluted_or_winter_water && is_underwater){//L803468D8 - item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(f64)((-time_getDelta()*60.0f)*2.1)); + item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(f64)((-time_getDelta()*(float)(FRAMERATE))*2.1)); }//L80346930 if(!is_in_polluted_or_winter_water || D_80385FEC == 0.0f){ - if(!D_80385FE4 && D_80385F30[ITEM_17_AIR] < 3600){ - item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(((time_getDelta()*60.0f)*100.0)*1.1)); - D_80385F30[ITEM_17_AIR] = MIN(D_80385F30[ITEM_17_AIR], 3600); + if(!D_80385FE4 && D_80385F30[ITEM_17_AIR] < VER_SELECT(3600, 3000, 0, 0)){ + item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(((time_getDelta()*(float)(FRAMERATE))*100.0)*1.1)); + D_80385F30[ITEM_17_AIR] = MIN(D_80385F30[ITEM_17_AIR], VER_SELECT(3600, 3000, 0, 0)); } } } @@ -383,7 +396,7 @@ void func_80346CA8(void) { if (D_80385FE4) { D_80385FE0 = true; D_80385F30[ITEM_14_HEALTH] = D_80385F30[ITEM_15_HEALTH_TOTAL]; - D_80385F30[ITEM_17_AIR] = 60*60; + D_80385F30[ITEM_17_AIR] = VER_SELECT(3600, 3000, 0, 0); } } @@ -425,16 +438,16 @@ void func_80346DB4(s32 note_count) { if (D_80385FF0[level_id] < note_count) { D_80385FF0[level_id] = note_count; if ((level_get() == LEVEL_1_MUMBOS_MOUNTAIN) && (note_count == 50)) { - gcdialog_showDialog(0xF74, 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(VER_SELECT(0xF74, 0xADA, 0, 0), 4, NULL, NULL, NULL, NULL); } - if (note_count == notesMax) { - gcdialog_showDialog(0xF78, 4, NULL, NULL, NULL, NULL); + if (note_count == 100) { + gcdialog_showDialog(VER_SELECT(0xF78, 0xADE, 0, 0), 4, NULL, NULL, NULL, NULL); } if (note_count == 1) { levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, true); } - if (!levelSpecificFlags_get(LEVEL_FLAG_34_UNKNOWN) && (gcdialog_showDialog(0xF76, 0, NULL, NULL, NULL, NULL))) { - levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, true); + if (!levelSpecificFlags_get(LEVEL_FLAG_34_UNKNOWN) && (gcdialog_showDialog(VER_SELECT(0xF76, 0xADC, 0, 0), 0, NULL, NULL, NULL, NULL))) { + levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, TRUE); } if (volatileFlag_get(VOLATILE_FLAG_17) == 0) { volatileFlag_set(VOLATILE_FLAG_17, 1); @@ -472,6 +485,19 @@ void notescore_getSizeAndPtr(s32 *size, void **ptr) { } } +// Raw per-level note-score array (vs. the packed u64 above). +void itemscore_noteScores_getSizeAndPtr(s32 *size, u8 **addr) { + *size = 0xE; + *addr = D_80385FF0; +} + +// Max-merge a level's note high score. +void itemscore_noteScores_setLevel(enum level_e level, s32 score) { + if (level >= 0 && level < 0xE && score > D_80385FF0[level]) { + D_80385FF0[level] = score; + } +} + void itemscore_noteScoress_maxAll(void) { s32 i; diff --git a/src/core2/context/bound.c b/src/core2/gc/bound.c similarity index 98% rename from src/core2/context/bound.c rename to src/core2/gc/bound.c index e179bf95a..54bd56587 100644 --- a/src/core2/context/bound.c +++ b/src/core2/gc/bound.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/bound.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/context/dialog.c b/src/core2/gc/dialog.c similarity index 97% rename from src/core2/context/dialog.c rename to src/core2/gc/dialog.c index 548508dfd..ad2493486 100644 --- a/src/core2/context/dialog.c +++ b/src/core2/gc/dialog.c @@ -1,7 +1,9 @@ +// BanjoDecomp: core2/gc/dialog.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "dialog.h" #include "core2/gc/zoombox.h" @@ -136,7 +138,7 @@ void gcdialog_init(void) { g_Dialog.unk128_3 = true; } -static void _gcdialog_freeZoomboxes(void){ +static void freeZoomboxes(void){ s32 i; for(i =0; i < 2; i++){ gczoombox_free(g_Dialog.zoombox[i]); @@ -167,7 +169,7 @@ void clearDialog(void){ func_80347A14(1); } if(!g_Dialog.unk11A[0].unk0_7 && !g_Dialog.unk11A[1].unk0_7){ - _gcdialog_freeZoomboxes(); + freeZoomboxes(); } g_Dialog.unk130 = -1; g_Dialog.unk128_15 = 0; @@ -244,7 +246,7 @@ void gcdialog_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ } } -void gcdialog_setState(s32 next_state){ +void dialog_setState(s32 next_state){ s32 i; s32 j; s32 v0 = 6; @@ -322,7 +324,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ break; case 3: //L8030F7BC - gcdialog_setState(2); + dialog_setState(2); break; case 4: //L8030F7CC @@ -331,7 +333,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ if(g_Dialog.unk12C_25 == 0){ temp_a0 = ((g_Dialog.unk11A[0].unk0_7) ? 1 : 0); temp_v0 = ((g_Dialog.unk11A[1].unk0_7) ? 1 : 0); - gcdialog_setState((temp_v0 + temp_a0) ? 8 : 5); + dialog_setState((temp_v0 + temp_a0) ? 8 : 5); }//L8030F980 break; } @@ -340,7 +342,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ if(temp_v0 > (s32)g_Dialog.unk12C_29){ g_Dialog.unk12C_29++; if(g_Dialog.unk128_15 == g_Dialog.unk12C_29 + g_Dialog.unk12C_27){ - gcdialog_setState(8); + dialog_setState(8); } } break; @@ -348,11 +350,11 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ case 6: //L8030F8FC g_Dialog.unk12C_27++; if(g_Dialog.unk12C_27 == g_Dialog.unk128_15){ - gcdialog_setState(7); + dialog_setState(7); }//L8030F964 if(g_Dialog.unk128_15 == g_Dialog.unk12C_29 + g_Dialog.unk12C_27){ - gcdialog_setState(8); + dialog_setState(8); } break; }//L8030F984 @@ -361,7 +363,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ #define CMD(i) (g_Dialog.string_list[g_Dialog.u8_s.active_zoombox] + i) #define CMD2(i) (&g_Dialog.string_list[g_Dialog.u8_s.active_zoombox][i]) -void gcdialog_update(void) { +void dialog_update(void) { s32 i; s32 spA8; s32 controller_face_buttons[6]; @@ -389,10 +391,10 @@ void gcdialog_update(void) { } } if (spA8 == 2) { - gcdialog_setState(7); + dialog_setState(7); } else if (g_Dialog.u8_s.unk12C_31 == g_Dialog.u8_s.unk128_15) { g_Dialog.u8_s.unk12C_31 = 0; - gcdialog_setState(2); + dialog_setState(2); } break; @@ -417,7 +419,7 @@ void gcdialog_update(void) { case -1: // Choice g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 = 2; - gcdialog_setState(4); + dialog_setState(4); break; case -4: // Close @@ -476,7 +478,7 @@ void gcdialog_update(void) { case -3: g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 = 0; - gcdialog_setState(4); + dialog_setState(4); break; default: @@ -564,7 +566,7 @@ void gcdialog_update(void) { g_Dialog.string_index[g_Dialog.u8_s.active_zoombox]++; } - gcdialog_setState(3); + dialog_setState(3); } break; } @@ -573,7 +575,7 @@ void gcdialog_update(void) { case 3: if ((g_Dialog.u8_s.unk128_31 & 1) && controller_face_buttons[FACE_BUTTON(BUTTON_B)] == 1u) { - gcdialog_setState(6); + dialog_setState(6); break; } @@ -585,7 +587,7 @@ void gcdialog_update(void) { break; } - gcdialog_setState(6); + dialog_setState(6); break; case 4: // Waiting for player to make choice @@ -596,13 +598,13 @@ void gcdialog_update(void) { } if (g_Dialog.u8_s.unk12C_23 != -1) { - gcdialog_setState(g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 ? 8 : 5); + dialog_setState(g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 ? 8 : 5); } break; case 7: case 8: - gcdialog_setState(0); + dialog_setState(0); break; } @@ -717,7 +719,7 @@ void loadAndCreateDialogs(s32 text_id, s32 arg1, ActorMarker *marker, void(*call g_Dialog.unk140 = arg4; g_Dialog.unk144 = arg5; g_Dialog.unk138 = (marker != NULL )? ((marker->unk5C)? marker->unk5C : -1) : 0; - gcdialog_setState(((func_802E4A08() || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE)) && g_Dialog.unk128_3) ? 6 : 1); + dialog_setState(((func_802E4A08() || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE)) && g_Dialog.unk128_3) ? 6 : 1); //L803109EC } @@ -816,7 +818,7 @@ void func_80310D2C(void){ g_Dialog.unk12C_15--; }else{//L80310F88 - gcdialog_update(); + dialog_update(); }//L80310F98 if( ( g_Dialog.state != 0 && g_Dialog.state != 5 && g_Dialog.state != 7) || ((!g_Dialog.state && (g_Dialog.unk11A[0].unk0_7 || g_Dialog.unk11A[1].unk0_7))) @@ -861,7 +863,7 @@ void func_80310D2C(void){ } } -int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, void (*arg4)(ActorMarker *, enum asset_e, s32)){ +int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, s32 (*arg4)(ActorMarker *, enum asset_e, s32)){ func_8025A55C(15000, 300, 2); gcdialog_showDialogConditional(next_state + 0xe57, 0x84, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker *, s32, s32))arg4); func_80310A5C(arg2, arg3, arg1, 0, 0); @@ -962,7 +964,7 @@ void func_803114D0(void){ s32 i; if(gcdialog_hasCurrentTextId()){ - gcdialog_setState(6); + dialog_setState(6); }else{ if(g_Dialog.state != 6){ g_Dialog.unk12C_25 = 0; @@ -986,7 +988,7 @@ int func_803115C4(s32 next_state){ if(gcdialog_getCurrentTextId() != next_state){ return 0; }else{ - gcdialog_setState(6); + dialog_setState(6); return 1; } } diff --git a/src/core2/gc/dialog.h b/src/core2/gc/dialog.h new file mode 100644 index 000000000..191a0fea6 --- /dev/null +++ b/src/core2/gc/dialog.h @@ -0,0 +1,22 @@ +// BanjoDecomp: core2/gc/dialog.h +#ifndef BANJO_KAZOOIE_GC_DIALOG_H +#define BANJO_KAZOOIE_GC_DIALOG_H + +enum { + DIALOG_BOTTOM = 0, + DIALOG_TOP = 1 +}; + +typedef enum { + DIALOG_STATE_0 = 0, + DIALOG_STATE_1 = 1, + DIALOG_STATE_2 = 2, + DIALOG_STATE_3 = 3, + DIALOG_WAITING_FOR_PLAYER_CHOICE = 4, + DIALOG_STATE_5 = 5, + DIALOG_STATE_6 = 6, + DIALOG_STATE_7 = 7, + DIALOG_STATE_8 = 8 +} DialogState; + +#endif // BANJO_KAZOOIE_GC_DIALOG_H diff --git a/src/core2/context/enter_text_trigger.c b/src/core2/gc/enter_text_trigger.c similarity index 78% rename from src/core2/context/enter_text_trigger.c rename to src/core2/gc/enter_text_trigger.c index 3c83c50c9..c089e8337 100644 --- a/src/core2/context/enter_text_trigger.c +++ b/src/core2/gc/enter_text_trigger.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_53A10.c #include #include "functions.h" #include "variables.h" @@ -5,8 +6,9 @@ void func_802DAA14(Actor *this); /* .data */ //000E0EE0 -ActorInfo D_80367E70= { - 0x21B, 0x351, 0, +// lair dialog object? +ActorInfo D_80367E70 = { + MARKER_21B_UNKNOWN, ACTOR_351_UNKNOWN, 0, 0, NULL, func_802DAA14, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 @@ -16,16 +18,17 @@ ActorInfo D_80367E70= { /* .code */ void func_802DA9A0(ActorMarker *caller, enum asset_e text_id, s32 arg2){ enum file_progress_e flag; - enum file_progress_e tmp; + enum file_progress_e flag_tmp; + if(level_get() == LEVEL_A_MAD_MONSTER_MANSION){ flag = FILEPROG_15_ENTER_MMM_TEXT; } else{ if(gsworld_getMap() == MAP_69_GL_MM_LOBBY) - tmp = FILEPROG_97_ENTERED_LAIR_TEXT; + flag_tmp = FILEPROG_97_ENTERED_LAIR_TEXT; else - tmp = FILEPROG_98_EXITED_LEVEL_TEXT; - flag = tmp; + flag_tmp = FILEPROG_98_EXITED_LEVEL_TEXT; + flag = flag_tmp; } fileProgressFlag_set(flag, 1); FUNC_8030E624(SFX_EA_GRUNTY_LAUGH_1, 1.0f, 30000); @@ -69,13 +72,13 @@ void func_802DAA14(Actor *this){ if(!this->has_met_before){ if(level_get() == LEVEL_A_MAD_MONSTER_MANSION){ - text_id = ASSET_ADC_DIALOG_GRUNTY_ENTER_SHED; + text_id = VER_SELECT(ASSET_ADC_DIALOG_GRUNTY_ENTER_SHED, 0x94E, 0, 0); } else{ if(gsworld_getMap() == MAP_69_GL_MM_LOBBY) - tmp = ASSET_F66_DIALOG_UNKNOWN; + tmp = VER_SELECT(ASSET_F66_DIALOG_UNKNOWN, 0xACC, 0, 0); else - tmp = ASSET_F67_DIALOG_UNKNOWN; + tmp = VER_SELECT(ASSET_F67_DIALOG_UNKNOWN, 0xACD, 0, 0); text_id = tmp; } gcdialog_showDialog(text_id, 4, NULL, this->marker, func_802DA9A0, NULL); diff --git a/src/core2/context/gameover.c b/src/core2/gc/gameoversign.c similarity index 85% rename from src/core2/context/gameover.c rename to src/core2/gc/gameoversign.c index 3ace29792..9e63caa9e 100644 --- a/src/core2/context/gameover.c +++ b/src/core2/gc/gameoversign.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/gameoversign.c #include #include "core1/core1.h" #include "functions.h" @@ -7,14 +8,15 @@ extern void actor_postdrawMethod(ActorMarker *); Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_802DC45C(Actor *this); +void gcGameOverSign_update(Actor *this); /* .data */ f32 D_80368040[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_8036804C = { + +ActorInfo gcGameOverSign = { MARKER_174_GAME_OVER, ACTOR_1DB_GAME_OVER, ASSET_54C_MODEL_GAME_OVER, 0x1, NULL, - func_802DC45C, actor_update_func_80326224, func_802DC320, + gcGameOverSign_update, actor_update_func_80326224, func_802DC320, 0, 0, 0.0f, 0 }; @@ -56,23 +58,23 @@ Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ } -void func_802DC430(Actor * this){ +void gcGameOverSign_free(Actor * this){ D_8037DE40 = NULL; func_8025A7DC(COMUSIC_31_GAME_OVER); } -void func_802DC45C(Actor *this){ +void gcGameOverSign_update(Actor *this){ if(!this->initialized){ this->initialized = true; this->depth_mode = MODEL_RENDER_DEPTH_NONE; func_803262E4(this); actor_collisionOff(this); - marker_setFreeMethod(this->marker, func_802DC430); + marker_setFreeMethod(this->marker, gcGameOverSign_free); } } -void func_802DC4C4(void) { +void gcGameOverSign_spawn(void) { Actor *actor; if (D_8037DE40 == 0) { actor = actor_spawnWithYaw_f32(ACTOR_1DB_GAME_OVER, D_80368040, 0); @@ -85,7 +87,7 @@ void func_802DC4C4(void) { void func_802DC528(NodeProp *arg0, ActorMarker *arg1){ if(D_8037DE40 == NULL){ - __spawnQueue_add_0(func_802DC4C4); + __spawnQueue_add_0(gcGameOverSign_spawn); } } @@ -99,7 +101,7 @@ void func_802DC560(NodeProp *arg0, ActorMarker *arg1){ void func_802DC5B8(void){ if(D_8037DE40 != NULL){ - func_802DC45C(marker_getActor(D_8037DE40)); + gcGameOverSign_update(marker_getActor(D_8037DE40)); func_80326894(marker_getActor(D_8037DE40)); } } diff --git a/src/core2/context/overlay_copyright.c b/src/core2/gc/overlaycopyright.c similarity index 97% rename from src/core2/context/overlay_copyright.c rename to src/core2/gc/overlaycopyright.c index d0b34563c..132d5f048 100644 --- a/src/core2/context/overlay_copyright.c +++ b/src/core2/gc/overlaycopyright.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/overlaycopyright.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/context/overlay_nocontroller.c b/src/core2/gc/overlaynocontroller.c similarity index 97% rename from src/core2/context/overlay_nocontroller.c rename to src/core2/gc/overlaynocontroller.c index 95a51d662..b0f1e3d26 100644 --- a/src/core2/context/overlay_nocontroller.c +++ b/src/core2/gc/overlaynocontroller.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/overlaynocontroller.c #include #include "core1/core1.h" #include "functions.h" @@ -17,8 +18,10 @@ ActorAnimationInfo D_80368150[] ={ {0x286, 1.1f}, {0x287, 1.6f} }; + f32 D_80368168[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_80368174 = { + +ActorInfo chOverlayNoController = { MARKER_178_NO_CONTROLLER_OVERLAY, ACTOR_1DF_NO_CONTROLLER_OVERLAY, ASSET_55D_MODEL_NO_CONTROLLER_OVERLAY, 0x0, D_80368150, chOverlayNoController_update, actor_update_func_80326224, chOverlayNoController_draw, diff --git a/src/core2/context/overlay_pressstart.c b/src/core2/gc/overlaypressstart.c similarity index 94% rename from src/core2/context/overlay_pressstart.c rename to src/core2/gc/overlaypressstart.c index ebba0e6cc..8ac99b3ab 100644 --- a/src/core2/context/overlay_pressstart.c +++ b/src/core2/gc/overlaypressstart.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/overlaypressstart.c #include #include "core1/core1.h" #include "functions.h" @@ -16,7 +17,7 @@ void chOverlayPressStart_update(Actor *this); /* .data */ -ActorAnimationInfo D_80368100[] = { +ActorAnimationInfo chOverlayPressStartAnimations[] = { {0, 0.0f}, {0x284, 1.6f}, {0x285, 1.6f} @@ -24,9 +25,9 @@ ActorAnimationInfo D_80368100[] = { f32 D_80368118[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_80368124 = { +ActorInfo chOverlayPressStart = { MARKER_177_PRESS_START_OVERLAY, ACTOR_1DE_PRESS_START_OVERLAY, ASSET_55C_MODEL_PRESS_START_OVERLAY, - 0x0, D_80368100, + 0x0, chOverlayPressStartAnimations, chOverlayPressStart_update, actor_update_func_80326224, chOverlayPressStart_draw, 0, 0, 0.0f, 0 }; diff --git a/src/core2/context/parade.c b/src/core2/gc/parade.c similarity index 99% rename from src/core2/context/parade.c rename to src/core2/gc/parade.c index c2dc549cb..87d83a3ac 100644 --- a/src/core2/context/parade.c +++ b/src/core2/gc/parade.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/parade.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/context/pause_menu.c b/src/core2/gc/pauseMenu.c similarity index 95% rename from src/core2/context/pause_menu.c rename to src/core2/gc/pauseMenu.c index 3180bf448..53aec1773 100644 --- a/src/core2/context/pause_menu.c +++ b/src/core2/gc/pauseMenu.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/pauseMenu.c #include #include "core1/core1.h" #include "functions.h" @@ -427,6 +428,11 @@ void gcpausemenu_printTotals(void) { } s32 gcpausemenu_levelToMenuPage(enum level_e level) { + // [port] Romhack gate: listeners can pin every level to one menu page. + s32 override_page = 0; + if (!EventSystem_Should(VB_PAUSEMENU_LEVEL_TO_PAGE, true, level, &override_page)) { + return override_page; + } switch (level) { case LEVEL_1_MUMBOS_MOUNTAIN: case LEVEL_2_TREASURE_TROVE_COVE: @@ -530,7 +536,10 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { gcpausemenu_zoomboxes_initTotalsMenu(); if (D_80383010.selection == gcpausemenu_levelToMenuPage(level_get())) { - print_setBoldFontTexture(0x6e7); + // [port] Romhack gate: listeners can swap the highlight bold-font texture. + s32 boldFontId = 0x6e7; + EventSystem_Should(VB_PAUSEMENU_BOLD_FONT_TEXTURE, true, &boldFontId); + print_setBoldFontTexture(boldFontId); } if (D_80383010.selection) { @@ -546,13 +555,17 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { if (hideCollLvl < 0) { hideCollLvl = LEVEL_6_LAIR; } if (hideJigLvl < 0) { hideJigLvl = LEVEL_B_SPIRAL_MOUNTAIN; } for (i = 0; i < 4; i++) { + s32 rowVisible; if (selLvl == hideCollLvl) { - gczoombox_highlight(D_80383010.zoombox[i], (!(i == 0) && !(i == 2))); + rowVisible = (!(i == 0) && !(i == 2)); } else if (selLvl == hideJigLvl) { - gczoombox_highlight(D_80383010.zoombox[i], (!(i == 0) && !(i == 1))); + rowVisible = (!(i == 0) && !(i == 1)); } else { - gczoombox_highlight(D_80383010.zoombox[i], 1); + rowVisible = 1; } + // [port] Romhack gate: level-merging hacks can hide extra rows per page. + rowVisible = EventSystem_Should(VB_PAUSEMENU_ROW_VISIBLE, rowVisible, selLvl, i); + gczoombox_highlight(D_80383010.zoombox[i], rowVisible); } break; @@ -609,7 +622,10 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { D_80383010.selection = D_80383010.page; if (D_80383010.selection && D_80383010.selection == gcpausemenu_levelToMenuPage(level_get())) { - print_setBoldFontTexture(0x6e7); + // [port] Romhack gate: listeners can swap the highlight bold-font texture. + s32 boldFontId = 0x6e7; + EventSystem_Should(VB_PAUSEMENU_BOLD_FONT_TEXTURE, true, &boldFontId); + print_setBoldFontTexture(boldFontId); } if (D_80383010.selection) { @@ -625,13 +641,17 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { if (hideCollLvl < 0) { hideCollLvl = LEVEL_6_LAIR; } if (hideJigLvl < 0) { hideJigLvl = LEVEL_B_SPIRAL_MOUNTAIN; } for (i = 0; i < 4; i++) { + s32 rowVisible; if (selLvl == hideCollLvl) { - gczoombox_highlight(D_80383010.zoombox[i], !((i == 0) || (i == 2))); + rowVisible = !((i == 0) || (i == 2)); } else if (selLvl == hideJigLvl) { - gczoombox_highlight(D_80383010.zoombox[i], (!(i == 0) && !(i == 1))); + rowVisible = (!(i == 0) && !(i == 1)); } else { - gczoombox_highlight(D_80383010.zoombox[i], 1); + rowVisible = 1; } + // [port] Romhack gate: level-merging hacks can hide extra rows per page. + rowVisible = EventSystem_Should(VB_PAUSEMENU_ROW_VISIBLE, rowVisible, selLvl, i); + gczoombox_highlight(D_80383010.zoombox[i], rowVisible); if (gczoombox_is_highlighted(D_80383010.zoombox[i])) { gczoombox_maximize(D_80383010.zoombox[i]); @@ -867,7 +887,11 @@ void gcpausemenu_printTotalsHeader(s32 page_id) { if (port_pauseBannerUpdate(page_id)) { return; } - print_bold_overlapping(v0->x, D_80383010.unk8, -1.05f, name ? (u8*)name : v0->string); + // [port] A custom romhack name inherits the vanilla name's hand-tuned x; let a + // listener recenter it for its own width. + s32 nameX = v0->x; + EventSystem_Should(VB_PAUSEMENU_LEVEL_NAME_X, true, &nameX, page_id, (const char*)v0->string, name); + print_bold_overlapping(nameX, D_80383010.unk8, -1.05f, name ? (u8*)name : v0->string); } void gcpausemenu_80312FD0(s32 arg0) { @@ -897,6 +921,10 @@ s32 gcpausemenu_getMaxPage(void) { } void gcpausemenu_setNextPage(s32 increment) { + // [port] Romhack gate: listeners can pin the page and skip paging entirely. + if (!EventSystem_Should(VB_PAUSEMENU_SET_NEXT_PAGE, true, &D_80383010.page)) { + return; + } D_80383010.page = D_80383010.selection; do { D_80383010.page += increment; @@ -1468,8 +1496,10 @@ void gcpausemenu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { } } - gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, 30.0f, 196.0f, 1, (s32) D_80383010.left_joystick_alpha); - gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, (f32)(gFramebufferWidth - 0x1E), 196.0f, 0, (s32) D_80383010.right_joystick_alpha); + if (EventSystem_Should(VB_PAUSEMENU_DRAW_JOYSTICKS, true, NULL)) { + gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, 30.0f, 196.0f, 1, (s32) D_80383010.left_joystick_alpha); + gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, (f32)(gFramebufferWidth - 0x1E), 196.0f, 0, (s32) D_80383010.right_joystick_alpha); + } // [port] Original decomp used raw u32 bit extraction: ((*((u32*)&D_80383010.state) << N) >> 0x1f) // This depends on big-endian byte order (byte 3 of the u32 is the bitfield byte on MIPS). // On little-endian, byte 0 of the u32 is 'state', so the shifts extract wrong bits. @@ -1548,9 +1578,9 @@ void gcpausemenu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { sp80[2] = 0.0f; for (var_s0_2 = 0; var_s0_2 < 7; var_s0_2++) { - func_8033A45C(var_s0_2 + 1, 0); + modelRender_setAppendageVisibility(var_s0_2 + 1, 0); } - func_8033A45C(i, 1); + modelRender_setAppendageVisibility(i, 1); modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE); modelRender_setAlpha(D_80383010.sns_alpha); modelRender_draw(gfx, mtx, sp98, sp8C, 0.8f, sp80, D_80383010.sns_egg_model); diff --git a/src/core2/context/pictureframe.c b/src/core2/gc/pictureframe.c similarity index 89% rename from src/core2/context/pictureframe.c rename to src/core2/gc/pictureframe.c index 483d22a7b..4697b14a5 100644 --- a/src/core2/context/pictureframe.c +++ b/src/core2/gc/pictureframe.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_581D0.c #include #include "functions.h" #include "variables.h" @@ -11,8 +12,11 @@ void func_802DF2C4(Actor *this); f32 D_80368360[3] = {0.0f, 0.0f, 0.0f}; s32 D_8036836C[4] = {0x60, 0x60, 0x60, 0xFF}; s32 D_8036837C[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + +// Asset is blank white rectangle +// Appears during Bottles Bonus ActorInfo D_8036838C = { - 0x17B, 0x2B5, 0x472, + MARKER_17B_UNKNOWN, ACTOR_2B5_UNKNOWN, ASSET_472_UNKNOWN, 0, NULL, func_802DF2C4, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 @@ -28,10 +32,9 @@ Actor *func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx) { void *sp38; this = marker_getActor(D_8037E000); - sp38 = func_8030C704(); + sp38 = picturebox_getColorBuffer(); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); gDPSetTextureFilter((*gfx)++, G_TF_BILERP); - port_readAuxFbToCpu(gfx); gSPSegment((*gfx)++, 0x04, osVirtualToPhysical(sp38)); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)this); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)D_8037E000); @@ -45,15 +48,17 @@ Actor *func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx) { void func_802DF270(void){ Actor *this; if(D_8037E000 == NULL){ - this = actor_spawnWithYaw_f32(0x2B5, D_80368360, 0); + this = actor_spawnWithYaw_f32(ACTOR_2B5_UNKNOWN, D_80368360, 0); D_8037E000 = this->marker; } } +// free void func_802DF2B4(Actor *this){ D_8037E000 = NULL; } +// update void func_802DF2C4(Actor *this) { s32 temp_fp; s32 i; @@ -61,7 +66,6 @@ void func_802DF2C4(Actor *this) { Struct70s *temp_v0; s32 val; - temp_fp = chBottlesBonusCursor_func_802E06B4() - 0x15; if (!this->initialized) { this->initialized = true; diff --git a/src/core2/context/map_info.c b/src/core2/gc/section.c similarity index 99% rename from src/core2/context/map_info.c rename to src/core2/gc/section.c index fb2d95f52..cc38fb812 100644 --- a/src/core2/context/map_info.c +++ b/src/core2/gc/section.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/section.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/context/sky.c b/src/core2/gc/sky.c similarity index 88% rename from src/core2/context/sky.c rename to src/core2/gc/sky.c index 021c6205e..fe157f99e 100644 --- a/src/core2/context/sky.c +++ b/src/core2/gc/sky.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/sky.c #include #include "core1/core1.h" #include "functions.h" @@ -64,7 +65,7 @@ static MapSkyInfo sSkyOverride; MapSkyInfo * sky_getMapSkyInfo(enum map_e map_id){ int models[3]; float scales[3], rotations[3]; - if (port_getRomhackSkyboxFull(map_getLevel(map_id), models, scales, rotations)) { + if (port_getRomhackSkyboxFull(map_id, models, scales, rotations)) { sSkyOverride.map = map_id; for (int i = 0; i < 3; i++) { sSkyOverride.sky_list[i].model_id = (s16)models[i]; @@ -84,30 +85,32 @@ MapSkyInfo * sky_getMapSkyInfo(enum map_e map_id){ return v1; } -void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ +void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { int i; f32 position[3]; f32 rotation[3]; - BKModelBin *iAsset; + BKModelBin *sky_model_bin; viewport_setNearAndFar(5.0f, 15000.0f); - if(gcSky.model_bins[0]){ - drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight, 0, 0, 0); + + if (gcSky.model_bins[0]) { + if (EventSystem_Should(VB_SKY_DRAW_BACKDROP_RECT, true)) { + drawRectangle2D(gfx, 0, 0, (f32) gFramebufferWidth, (f32) gFramebufferHeight, 0, 0, 0); + } viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); viewport_getPosition_vec3f(position); - for(i = 0; i < 3; i++){ - iAsset = gcSky.model_bins[i]; - if(iAsset){ + for (i = 0; i < 3; i++) { + sky_model_bin = gcSky.model_bins[i]; + if (sky_model_bin) { rotation[0] = 0.0f; rotation[1] = gcSky.sky_info->sky_list[i].rotation_speed * gcSky.timer; rotation[2] = 0.0f; - modelRender_draw(gfx, mtx, position, rotation, gcSky.sky_info->sky_list[i].scale, NULL, iAsset); + modelRender_draw(gfx, mtx, position, rotation, gcSky.sky_info->sky_list[i].scale, NULL, sky_model_bin); } } + } else { + drawRectangle2D(gfx, 0, 0, (f32) gFramebufferWidth, (f32) gFramebufferHeight, 0, 0, 0); } - else{//L8030B200 - drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight, 0, 0, 0); - }//L8030B254 } void sky_free(void){ diff --git a/src/core2/context/transition.c b/src/core2/gc/transition.c similarity index 94% rename from src/core2/context/transition.c rename to src/core2/gc/transition.c index ea1ea1248..01408d48a 100644 --- a/src/core2/context/transition.c +++ b/src/core2/gc/transition.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/transition.c #include #include "core1/core1.h" #include "functions.h" @@ -5,6 +6,7 @@ #include "gc/gctransition.h" #include "port/Patches/Patches.h" #include "port/Engine.h" +#include "port/Interpolation/FrameInterpolation.h" void anctrl_setAnimTimer(AnimCtrl*, f32); void func_8025AC20(s32, s32, s32, f32, char*, s32); @@ -241,7 +243,7 @@ void gctransition_defrag(void){ s_current_transition.model_ptr = defrag_asset(s_current_transition.model_ptr); } -void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ +void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { f32 vp_position[3]; f32 vp_rotation[3]; f32 percentage; @@ -252,6 +254,7 @@ void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ if(s_current_transition.state == 0) return; + FrameInterpolation_RecordOpenChild("transition", 0); viewport_backupState(); if(s_current_transition.anctrl != NULL){ vp_position[0] = 0.0f; @@ -270,31 +273,31 @@ void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ viewport_setPosition_vec3f(vp_position); //viewport_getPosition_vec3f viewport_setRotation_vec3f(vp_rotation); //viewport_getRotation_vec3f viewport_update(); //camera_updateNormal - viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); + viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); sp58[0] = 0.0f; sp58[1] = 0.0f; sp58[2] = 0.0f; if(s_current_transition.anctrl != NULL){ - gDPSetTextureFilter((*gdl)++, G_TF_POINT); - gDPSetColorDither((*gdl)++, G_CD_DISABLE); + gDPSetTextureFilter((*gfx)++, G_TF_POINT); + gDPSetColorDither((*gfx)++, G_CD_DISABLE); anctrl_drawSetup(s_current_transition.anctrl, sp58, 1); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); } // [port] Widescreen transition scaling is applied by the port listener f32 transitionScale = 1.0f; - CALL_EVENT(OnTransitionModelScale, gdl, mptr, + CALL_EVENT(OnTransitionModelScale, gfx, mtx, s_current_transition.transistion_info != NULL ? s_current_transition.transistion_info->uid : 0, &transitionScale); //complex animation (from animation bin file) if(s_current_transition.state == 1 || s_current_transition.state == 6){ - modelRender_draw(gdl, mptr, sp58, vp_rotation, transitionScale, 0, s_current_transition.model_ptr); + modelRender_draw(gfx, mtx, sp58, vp_rotation, 1.0f, 0, s_current_transition.model_ptr); if(s_current_transition.anctrl != NULL){ - gDPSetTextureFilter((*gdl)++, G_TF_BILERP); - gDPSetColorDither((*gdl)++, G_CD_MAGICSQ); + gDPSetTextureFilter((*gfx)++, G_TF_BILERP); + gDPSetColorDither((*gfx)++, G_CD_MAGICSQ); } return; } @@ -311,7 +314,7 @@ void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ vp_rotation[2] = s_current_transition.rotation - 90.0f*percentage; scale = percentage*s_current_transition.transistion_info->scale + 0.1; } - modelRender_draw(gdl, mptr, sp58, vp_rotation, scale * transitionScale, 0, s_current_transition.model_ptr); + modelRender_draw(gfx, mtx, sp58, vp_rotation, scale, 0, s_current_transition.model_ptr); } else if(s_current_transition.state == TRANSITION_STATE_5_FADE_OUT){//L8030B9EC switch (s_current_transition.transistion_info->uid) @@ -332,7 +335,7 @@ void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ break; } if(!(s_current_transition.substate < 3) || s_current_transition.transistion_info->uid != 0x11){ - modelRender_draw(gdl, mptr, sp58, vp_rotation, scale * transitionScale, 0, s_current_transition.model_ptr); + modelRender_draw(gfx, mtx, sp58, vp_rotation, scale, 0, s_current_transition.model_ptr); } else{ modelRender_reset(); @@ -344,14 +347,14 @@ void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ gcbound_reset(); gcbound_alpha((1.0f - percentage)*255.0f + 0.5); gcbound_color(0,0,0); - gcbound_draw(gdl); + gcbound_draw(gfx); } else if(s_current_transition.state == TRANSITION_STATE_3_BLACK_OUT){//L8030BB6C //fade out black (i.e. get more black) gcbound_reset(); gcbound_alpha(percentage*255.0f + 0.5); gcbound_color(0,0,0); - gcbound_draw(gdl); + gcbound_draw(gfx); } else if(s_current_transition.state == TRANSITION_STATE_7_WHITE_IN){//L8030BBD8 //fade in white (i.e. get less white) @@ -359,31 +362,35 @@ void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ gcbound_reset(); gcbound_alpha(percentage*255.0f + 0.5); gcbound_color(0xff,0xff,0xff); - gcbound_draw(gdl); + gcbound_draw(gfx); } else if(s_current_transition.state == TRANSITION_STATE_8_WHITE_OUT){//L8030BC8C //fade out white (i.e. get more white) gcbound_reset(); gcbound_alpha(percentage*255.0f + 0.5); gcbound_color(0xff,0xff,0xff); - gcbound_draw(gdl); + gcbound_draw(gfx); }//L8030BD00 else{ } if(s_current_transition.anctrl != NULL){ - gDPSetTextureFilter((*gdl)++, G_TF_BILERP); + gDPSetTextureFilter((*gfx)++, G_TF_BILERP); } viewport_restoreState(); - viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); - + viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); + FrameInterpolation_RecordCloseChild(); } void gctransition_8030BD4C(void){ MapTransitionInfo *tmp_10s; TransitionInfo *tmp_a1; + s32 in_index; tmp_10s = _gctranstion_get_map_transition_info(gsworld_getMap()); - tmp_a1 = _gctranstion_8030B400(tmp_10s->in_index); + in_index = tmp_10s->in_index; + // [port] Romhack gate: listeners may override the incoming transition style. + EventSystem_Should(VB_MAP_TRANSITION_IN_INDEX, true, gsworld_getMap(), &in_index); + tmp_a1 = _gctranstion_8030B400(in_index); _gctranstion_changeState(tmp_a1->state, tmp_a1); } @@ -414,7 +421,7 @@ void gctransition_8030BE3C(void){ void gctransition_8030BE60(void){ TransitionInfo *tmp_a1; tmp_a1 = _gctranstion_8030B400(_gctranstion_get_map_transition_info(gsworld_getMap())->out_index); - func_8030C180(); + picturebox_func_8030C180(); _gctranstion_changeState(tmp_a1->state, tmp_a1); } @@ -503,7 +510,7 @@ void gctransition_update(void){ }//L8030C104 _gctranstion_changeState(s_current_transition.transistion_info->next_state, 0); if(s_current_transition.state == TRANSITION_STATE_4_FADE_IN) - func_8030C180(); + picturebox_func_8030C180(); if(s_current_transition.anctrl != NULL) gsworld_update(); diff --git a/src/core2/context/zoombox.c b/src/core2/gc/zoombox.c similarity index 98% rename from src/core2/context/zoombox.c rename to src/core2/gc/zoombox.c index 40b629804..6a59d9769 100644 --- a/src/core2/context/zoombox.c +++ b/src/core2/gc/zoombox.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gc/zoombox.c #include #include "core1/core1.h" #include "core1/core1.h" @@ -418,9 +419,9 @@ gczoomboxPortraitInfo D_8036C6C0[] = { {SFX_FA_GRUNTLING_NOISE_2, 20000, 1.3f}, {SFX_FB_GRUNTLING_NOISE_3, 20000, 1.3f} }}, - {0x084A, 0xF2, 0x0A, {{SFX_6E_VILE_EGH, 20000, 1.0f}}}, - {0x084B, 0xF2, 0x0A, {{SFX_6E_VILE_EGH, 20000, 1.0f}}}, - {0x084C, 0xF2, 0x0A, {{SFX_6E_VILE_EGH, 20000, 1.0f}}}, + {0x084A, VER_SELECT(0xF2, 0xF0, 0, 0), VER_SELECT(0x0A, 0x05, 0, 0), {{VER_SELECT(SFX_6E_VILE_EGH, SFX_C3_HEGH, 0, 0), 20000, 1.0f}}}, + {0x084B, VER_SELECT(0xF2, 0xF0, 0, 0), VER_SELECT(0x0A, 0x05, 0, 0), {{VER_SELECT(SFX_6E_VILE_EGH, SFX_C3_HEGH, 0, 0), 20000, VER_SELECT(1.0f, 1.1f, 0.0f, 0.0f)}}}, + {0x084C, VER_SELECT(0xF2, 0xF0, 0, 0), VER_SELECT(0x0A, 0x05, 0, 0), {{VER_SELECT(SFX_6E_VILE_EGH, SFX_C3_HEGH, 0, 0), 20000, VER_SELECT(1.0f, 0.9f, 0.0f, 0.0f)}}}, }; s32 D_8036D924[] = { 70, 35, 18, 9, 4, 2, 1}; @@ -613,7 +614,9 @@ void func_8031594C(GcZoombox * this, u8 *str, s32 arg2, s32 arg3){ s1 = 0; f22 = (this->portrait_id == ZOOMBOX_SPRITE_5F_TOOTY_4) ? 0.4 : 0.8; - if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ + // [port] The zoombox draws from the shared gameplay RNG, and these two calls are a + // save/restore of the whole state around that. + if(func_802E4A08()){ sfx_rand_sync_to_rand(); } for(s2 = arg2; s2 <= arg3; s2++){ @@ -666,7 +669,7 @@ void func_8031594C(GcZoombox * this, u8 *str, s32 arg2, s32 arg3){ }//L80315B6C this->unk189 = s1; this->unk187 = 0; - if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ + if(func_802E4A08()){ rand_sync_to_sfx_rand(); } } @@ -994,7 +997,7 @@ void gczoombox_draw(GcZoombox *this, Gfx **gdl, Mtx ** mptr, void *vptr){ if(!this) return; - if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE) + if(func_802E4A08()) sfx_rand_sync_to_rand(); //L80316BCC // [port] Stable scope. The crossfade branch below toggles 1↔2 sprite @@ -1045,7 +1048,7 @@ void gczoombox_draw(GcZoombox *this, Gfx **gdl, Mtx ** mptr, void *vptr){ } }//L80316DD8 FrameInterpolation_RecordCloseChild(); - if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ + if(func_802E4A08()){ rand_sync_to_sfx_rand(); } @@ -1400,9 +1403,14 @@ void __gczoombox_load_sfx(GcZoombox *this, GcZoomboxSprite portrait_id){ } //L80317E48 } + // [port] Balanced bracket. Vanilla restores below without a matching save, + // which rewinds the shared stream to whenever the last snapshot was taken; + // taking one here means the restore only undoes this randi2. + if(func_802E4A08()){ + sfx_rand_sync_to_rand(); + } this->prev_sfx = randi2(0,this->sfx_count); - // [port] This mode needs a rand sync like many other places - if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ + if(func_802E4A08()){ rand_sync_to_sfx_rand(); } } diff --git a/src/core2/actor_cubebounds.c b/src/core2/gccube.c similarity index 99% rename from src/core2/actor_cubebounds.c rename to src/core2/gccube.c index 24f96b19f..d67d989a6 100644 --- a/src/core2/actor_cubebounds.c +++ b/src/core2/gccube.c @@ -1,10 +1,12 @@ +// BanjoDecomp: core2/gccube.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "bk_math.h" // [port] TUPLE macros #include -#include "bk_math.h" +#include "math.h" #include "prop.h" #include "port/Patches/Patches.h" @@ -50,7 +52,7 @@ void func_80308EC8(void); bool func_80308F54(s32 cube_index); extern ActorInfo D_803675F0; -extern ActorInfo D_80367838; +extern ActorInfo gWorldExitPad; /* .data */ s32 sSpawnableActorSize = 0; //0x8036A9B0 @@ -388,19 +390,19 @@ void func_80302C94(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 sp38[3]; f32 temp_f18; +#if ANTI_TAMPER if (!mapSpecificFlags_validateCRC1()) return; +#endif func_8032D3A8(); viewport_getPosition_vec3f(vp_position); viewport_getRotation_vec3f(vp_rotation); - func_80256664(vp_rotation); + ml_vec3f_clamp_deg360(vp_rotation); cube_positionToIndices(vp_cube_indices, vp_position); - vp_cube_indices[0] -= sCubeList.min[0];\ - vp_cube_indices[1] -= sCubeList.min[1];\ - vp_cube_indices[2] -= sCubeList.min[2]; + TUPLE_DIFF(vp_cube_indices, sCubeList.min) func_80308EC8(); - sp44[0] = sp44[1] = sp44[2] = 0; + TUPLE_SET(sp44, 0) sp38[0] = sCubeList.width[0] - 1;\ sp38[1] = sCubeList.width[1] - 1;\ sp38[2] = sCubeList.width[2] - 1; @@ -539,7 +541,7 @@ static Cube *__code7AF80_getCubeAtPosition(s32 position[3]) { (position[2] - sCubeList.min[2]) * sCubeList.stride[1]; } -Cube *cube_atPosition_s32(s32 position[3]) { +Cube *cubeList_GetCubeAtPosition_s32(s32 position[3]) { s32 sp1C[3]; s32 i; // Cube *out; @@ -563,13 +565,13 @@ Cube *cube_atPosition_s32(s32 position[3]) { + diff[2]*sCubeList.stride[1]; } -Cube *cube_atPosition_f32(f32 position[3]){ +Cube *cubeList_GetCubeAtPosition_f32(f32 position[3]){ s32 pos_s32[3]; pos_s32[0] = (s32)position[0]; pos_s32[1] = (s32)position[1]; pos_s32[2] = (s32)position[2]; - return cube_atPosition_s32(pos_s32); + return cubeList_GetCubeAtPosition_s32(pos_s32); } Cube *func_8030364C(void){ @@ -1082,7 +1084,7 @@ void nodeprop_getPosition(NodeProp *nodeProp, f32 dst[3]) { TUPLE_ASSIGN(dst, nodeProp->x, nodeProp->y, nodeProp->z) } -u32 nodeprop_getYaw(NodeProp *nodeProp) { +u32 nodeProp_getYaw(NodeProp *nodeProp) { return nodeProp->yaw; } @@ -1329,7 +1331,7 @@ void func_8030578C(void){ && (sSpawnableActorList != NULL) ){ for(i = 0; i < sSpawnableActorSize - 1; i++){ - if(sSpawnableActorList[i].infoPtr == &D_80367838){ + if(sSpawnableActorList[i].infoPtr == &gWorldExitPad){ sSpawnableActorList[i].infoPtr = &D_803675F0; sSpawnableActorList[i].spawnFunc = actor_new; sSpawnableActorList[i].unk8 = 0; @@ -2062,8 +2064,8 @@ void func_80307CA0(ActorMarker *marker) { for(i = 0; cubePtrList[i] != NULL; i++) { for(node_idx = 0; node_idx < cubePtrList[i]->unk0_4; node_idx++){ node = codeA5BC0_getPropNodeAtIndex(cubePtrList[i], node_idx); - if (codeA5BC0_getNodePropUnkA(node) == marker_bitfield) { - node_radius = codeA5BC0_getPositionAndReturnRadius(node, node_position); + if (codeA5BC0_getNodePropMarkerId(node) == marker_bitfield) { + node_radius = codeA5BC0_getPositionAndSelectorOrRadius(node, node_position); if( ((node_position[0] - node_radius) < marker_position[0]) && (marker_position[0] < (node_position[0] + node_radius)) && ((node_position[1] - node_radius) < marker_position[1]) && (marker_position[1] < (node_position[1] + node_radius)) && ((node_position[2] - node_radius) < marker_position[2]) && (marker_position[2] < (node_position[2] + node_radius)) @@ -2478,7 +2480,7 @@ void func_80308D2C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { cube = &sCubeList.cubes[D_80382150[phi_s4]]; if (viewport_cube_isInFrustum(cube)) { viewport_getPosition_vec3w(vp_pos); - vp_cube_index = cube_atPosition_s32(vp_pos) - sCubeList.cubes; + vp_cube_index = cubeList_GetCubeAtPosition_s32(vp_pos) - sCubeList.cubes; for(phi_s0 = 0; (phi_s0 < D_80382150[phi_s4 + 1]) && (vp_cube_index != D_80382150[phi_s0 + 2]); phi_s0++) { } if (phi_s0 < D_80382150[phi_s4 + 1]) { diff --git a/src/core2/score_honeycomb.c b/src/core2/honeycombscore.c similarity index 97% rename from src/core2/score_honeycomb.c rename to src/core2/honeycombscore.c index 420d64983..6667b3310 100644 --- a/src/core2/score_honeycomb.c +++ b/src/core2/honeycombscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/honeycombscore.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/inventory_slots.c b/src/core2/inventory_slots.c index 7feea4b74..f2cdc3383 100644 --- a/src/core2/inventory_slots.c +++ b/src/core2/inventory_slots.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9D760.c #include #include "functions.h" #include "variables.h" @@ -11,7 +12,7 @@ void func_80324700(u8* self){ for(i_ptr = self; i_ptr < self + 0x10; i_ptr++){ if(*i_ptr != 0xFF){ - func_8033A45C((i_ptr - self) + 1, *i_ptr); + modelRender_setAppendageVisibility((i_ptr - self) + 1, *i_ptr); } } } diff --git a/src/core2/score_jiggy.c b/src/core2/jiggyscore.c similarity index 90% rename from src/core2/score_jiggy.c rename to src/core2/jiggyscore.c index 32bfbc41b..6d7d9c46f 100644 --- a/src/core2/score_jiggy.c +++ b/src/core2/jiggyscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/jiggyscore.c #include #include "functions.h" #include "variables.h" @@ -83,6 +84,12 @@ s32 jiggyscore_leveltotal(s32 lvl) { s32 start; s32 end; s32 cnt; + s32 override_total = 0; + + // [port] Romhack gate: listeners can supply the whole per-level tally. + if (!EventSystem_Should(VB_JIGGYSCORE_LEVEL_TOTAL, true, lvl, &override_total)) { + return override_total; + } if (lvl <= 0 || lvl == 0xB || lvl >= 0xB) return 0; diff --git a/src/core2/level/specificflags.c b/src/core2/level/levelspecificflags.c similarity index 82% rename from src/core2/level/specificflags.c rename to src/core2/level/levelspecificflags.c index f055d5c97..69a066baf 100644 --- a/src/core2/level/specificflags.c +++ b/src/core2/level/levelspecificflags.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/levelspecificflags.c #include #include "functions.h" #include "variables.h" @@ -78,12 +79,12 @@ void _levelSpecificFlags_updateCRC2(void) { s32 levelSpecificFlags_get(s32 i){ CALL_CANCELLABLE_RETURN_EVENT(OnGetLevelSpecificFlag, i) { - return bitfield_get_bit(D_80383320.unk8, i); + return bitfieldarray_getBit(D_80383320.unk8, i); } } s32 levelSpecificFlags_getN(s32 i, s32 n){ - return bitfield_get_n_bits(D_80383320.unk8, i, n); + return bitfieldarray_getNBits(D_80383320.unk8, i, n); } s32 levelSpecificFlags_getSet(s32 arg0, s32 arg1){ @@ -101,16 +102,30 @@ void levelSpecificFlags_clear(void){ _levelSpecificFlags_updateCRC2(); } -void levelSpecificFlags_set(s32 index, s32 val){ - bitfield_set_bit(D_80383320.unk8, index, val); +void levelSpecificFlags_setEx(s32 index, s32 val, s32 triggerEvent){ + s32 changed = bitfieldarray_getBit(D_80383320.unk8, index) != (val ? 1 : 0); + bitfieldarray_setBit(D_80383320.unk8, index, val); _levelSpecificFlags_updateCRC1(); _levelSpecificFlags_updateCRC2(); + if (triggerEvent && changed) { + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_LEVEL_SPECIFIC, index, val ? 1 : 0, 1); + } +} + +void levelSpecificFlags_set(s32 index, s32 val){ + levelSpecificFlags_setEx(index, val, 1); } void levelSpecificFlags_setN(s32 index, s32 val, s32 n){ - bitfield_set_n_bits(D_80383320.unk8, index, val, n); + bitfieldarray_setNBits(D_80383320.unk8, index, val, n); _levelSpecificFlags_updateCRC1(); _levelSpecificFlags_updateCRC2(); + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_LEVEL_SPECIFIC, index, val, n); +} + +void levelSpecificFlags_getSizeAndPtr(s32 *size, u8 **addr){ + *size = 8; + *addr = D_80383320.unk8; } s32 levelSpecificFlags_validateCRC1(void) { diff --git a/src/core2/level/lightconfig.c b/src/core2/level/lightconfig.c index 84fbe73ec..3ccea6f57 100644 --- a/src/core2/level/lightconfig.c +++ b/src/core2/level/lightconfig.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_35520.c -> lightconfig.c +// BanjoDecomp: core2/code_35520.c // This file defines the distances for type-4 camera nodes (the normal 3rd person view camera?) for each map #include #include "functions.h" diff --git a/src/core2/level/metadata.c b/src/core2/level/metadata.c index 83b8e9b7d..553039d23 100644 --- a/src/core2/level/metadata.c +++ b/src/core2/level/metadata.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_117D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/audioconfig.c b/src/core2/map/audioconfig.c index ac373dd69..b32268d2d 100644 --- a/src/core2/map/audioconfig.c +++ b/src/core2/map/audioconfig.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9D640.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/cutscene_skip.c b/src/core2/map/cutscene_skip.c index 79c3e1bdd..32cf24111 100644 --- a/src/core2/map/cutscene_skip.c +++ b/src/core2/map/cutscene_skip.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_956B0.c #include #include "functions.h" #include "variables.h" @@ -7,7 +8,6 @@ extern void player_walkToPosition(f32 *, f32, void(*)(ActorMarker *), ActorMark extern void func_8028F760(s32, f32, f32); extern void func_8031CE70(f32 *arg0, enum map_e arg1, s32 arg2); extern void func_8031FFAC(void); -extern void fileProgressFlag_set(enum file_progress_e index, s32 set); extern NodeProp *func_80304ED0(void*, f32 *); extern void func_8031CD44(enum map_e, s32, f32, f32, s32); extern void mapSpecificFlags_set(s32, s32); @@ -135,6 +135,9 @@ void func_8031CB50(enum map_e map_id, s32 exit_id, s32 arg2) { s32 sp1C; if ((D_80383190 == 0) && (getGameMode() != GAME_MODE_8_BOTTLES_BONUS) && (getGameMode() != GAME_MODE_7_ATTRACT_DEMO)) { + // [port] Romhack gate: a listener may call musicKeepsPlaying() here to + // carry a special-music state across this warp. + EventSystem_Should(VB_WARP_KEEPS_MUSIC, true, map_id); sp1C = func_803226E8(gsworld_getMap()); if ((func_803226E8(map_id) != sp1C) && (func_80322914() == 0)) { func_8025A388(0, 0x4E2); @@ -1374,18 +1377,8 @@ void warp_smExitBanjosHouse(NodeProp *arg0, ActorMarker *arg1) { } void warp_lairEnterMMLobbyFromSMLevel(NodeProp *arg0, ActorMarker *arg1) { - // [port] BB romhacks can override this warp destination via BKCF; port - // listeners can refine further by responding to OnWarpResolveDest. s32 dest = 0x6912; - s32 bkcf = port_getRomhackWarpEnterLair(); - if (bkcf >= 0) { - dest = bkcf; - } - s32 mapOverride = port_getRomhackStartLevel2(); - if (mapOverride >= 0) { - dest = (mapOverride << 8) | (dest & 0xFF); - } - CALL_EVENT(OnWarpResolveDest, WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL, 0x6912, bkcf, &dest); + CALL_EVENT(OnWarpResolveDest, WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL, 0x6912, -1, &dest); func_8031CC8C(arg0, dest); } @@ -1522,9 +1515,15 @@ void func_8031FAB4(NodeProp *arg0, ActorMarker *arg1) { void warp_lairEnterLairFromSMLevel(NodeProp *arg0, ActorMarker *arg1) { if (fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE) != 0) { // MM Lobby - // [port] BB romhacks can override this warp destination - s32 override = port_getRomhackWarpEnterLair(); - func_8031CC8C(arg0, override >= 0 ? override : 0x6912); + // [port] BB romhacks can override this warp destination via BKCF; port + // listeners can refine further by responding to OnWarpResolveDest. + s32 dest = 0x6912; + s32 bkcf = port_getRomhackWarpEnterLair(); + if (bkcf >= 0) { + dest = bkcf; + } + CALL_EVENT(OnWarpResolveDest, WARP_ID_LAIR_ENTER_LAIR_FROM_SM_LEVEL, 0x6912, bkcf, &dest); + func_8031CC8C(arg0, dest); } else { fileProgressFlag_set(FILEPROG_BD_ENTER_LAIR_CUTSCENE, 1); // Enter Lair Cutscene diff --git a/src/core2/map/cutscene_triggers.c b/src/core2/map/cutscene_triggers.c index 2520d1d60..b734f1179 100644 --- a/src/core2/map/cutscene_triggers.c +++ b/src/core2/map/cutscene_triggers.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9B180.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/envcolor.c b/src/core2/map/envcolor.c index 595d620b8..b4f62ae65 100644 --- a/src/core2/map/envcolor.c +++ b/src/core2/map/envcolor.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_94780.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/exit.c b/src/core2/map/exit.c index d90dfa235..ef01e5a22 100644 --- a/src/core2/map/exit.c +++ b/src/core2/map/exit.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C4320.c #include #include "functions.h" #include "variables.h" @@ -44,9 +45,9 @@ extern Struct_core2_C4320_0 D_80371F44[] = { extern Struct_core2_C4320_0 D_80371F70 = {MAP_41_FP_BOGGYS_IGLOO, 6, 0x5D, 7, 8, 3}; extern Struct_core2_C4320_0 D_80371F78[] ={ - {MAP_7_TTC_TREASURE_TROVE_COVE, 0, 0x5F, 6, 9, 9}, - {MAP_27_FP_FREEZEEZY_PEAK, 0, 0x5F, 9, 9, 9}, - {MAP_12_GV_GOBIS_VALLEY, 0, 0x5F, 9, 5, 9} + {MAP_7_TTC_TREASURE_TROVE_COVE, 0, VER_SELECT(0x5F, 0x5E, 0, 0), 6, 9, 9}, + {MAP_27_FP_FREEZEEZY_PEAK, 0, VER_SELECT(0x5F, 0x5E, 0, 0), 9, 9, 9}, + {MAP_12_GV_GOBIS_VALLEY, 0, VER_SELECT(0x5F, 0x5E, 0, 0), 9, 5, 9} }; extern s32 D_80371F8C = 0xA; //attract demo count @@ -221,7 +222,9 @@ void func_8034B8C0(enum map_e map_id, s32 demo_id) { volatileFlag_set(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE, 1); func_802E4A70(); } - if ((demo_id == 0x5B) || (demo_id == 0x5F)) { + // [port] 0x5E: SNS picture demo slot on non-v1.0 bases (table retargeted in + // ResourceHelpers); unused leftover slot on v1.0, so always safe to accept. + if ((demo_id == 0x5B) || (demo_id == 0x5E) || (demo_id == 0x5F)) { sns_backup_items_and_unlock_all(); } } diff --git a/src/core2/map/gsworld.c b/src/core2/map/gsworld.c index 154af5ad4..8426ecdcf 100644 --- a/src/core2/map/gsworld.c +++ b/src/core2/map/gsworld.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gsworld.c #include #include "core1/core1.h" #include "functions.h" @@ -7,17 +8,18 @@ #include #include "core2/particle.h" #include "port/Interpolation/FrameInterpolation.h" -#include "port/Enhancements/NoteRetention/NoteRetention.h" +#include "port/Enhancements/Retention/Retention.h" /* .data */ extern u8 D_80370250 = 0; /* .bss */ -struct { - s32 unk0; - s32 map_4; - s32 unk8; -}sGsWorldData; +struct gsworld_data_s { + s32 unk0; // probably game_mode_e + enum map_e map; + s32 exit; +}; +struct gsworld_data_s sGsWorldData; s32 D_803835DC; u32 sEnableDraw; @@ -38,15 +40,15 @@ extern Struct64s *func_8032994C(void); extern void func_802F2ED0(Struct64s *, Gfx **, Mtx **, Vtx **); /* .code */ -void gsworld_draw(Gfx** gdl, Mtx **mptr, Vtx **vptr) { +void gsworld_draw(Gfx** gfx, Mtx **mtx, Vtx **vtx) { f32 sp44; f32 sp40; if (sEnableDraw == 0) { - drawRectangle2D(gdl, 0, 0, gFramebufferWidth, gFramebufferHeight, 0, 0, 0); - func_802BBD2C(&sp44, &sp40); + drawRectangle2D(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, 0, 0, 0); + core2_34790_getClipDistances(&sp44, &sp40); viewport_setNearAndFar(sp44, sp40); - viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); + viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); return; } // Lighthouse [port] Crashing here, not sure what this is. @@ -55,87 +57,87 @@ void gsworld_draw(Gfx** gdl, Mtx **mptr, Vtx **vptr) { // } spawnQueue_unlock(); FrameInterpolation_RecordOpenChild("sky", 0); - sky_draw(gdl, mptr, vptr); + sky_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); - func_802BBD2C(&sp44, &sp40); + core2_34790_getClipDistances(&sp44, &sp40); viewport_setNearAndFar(sp44, sp40); - viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); + viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); if (mapModel_has_xlu_bin() != 0) { FrameInterpolation_RecordOpenChild("map_opa", 0); - mapModel_opa_draw(gdl, mptr, vptr); + mapModel_opa_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); if (game_is_frozen() == 0) { - leveloverlay_drawCallback(gdl, mptr, vptr); + leveloverlay_drawCallback(gfx, mtx, vtx); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("player", 0); - player_draw(gdl, mptr, vptr); + player_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); - CALL_EVENT(OnPlayerDraw, gdl, mptr, vptr); + CALL_EVENT(OnPlayerDraw, gfx, mtx, vtx); } if (game_is_frozen() == 0) { - func_80302C94(gdl, mptr, vptr); + func_80302C94(gfx, mtx, vtx); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("jiggylist", 0); - jiggylist_draw(gdl, mptr, vptr); + jiggylist_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { - func_803500D8(gdl, mptr, vptr); + func_803500D8(gfx, mtx, vtx); } if (game_is_frozen() == 0) { - func_802F2ED0(func_8032994C(), gdl, mptr, vptr); + func_802F2ED0(func_8032994C(), gfx, mtx, vtx); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("part_pass0", 0); - partEmitMgr_drawPass0(gdl, mptr, vptr); + partEmitMgr_drawPass0(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("map_xlu", 0); - mapModel_xlu_draw(gdl, mptr, vptr); + mapModel_xlu_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); } - if (game_is_frozen() == 0) { - func_8032D3D8(gdl, mptr, vptr); + if (!game_is_frozen()) { + core2_A5BC0_drawUnknownMarkers(gfx, mtx, vtx); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("part_pass1", 0); - partEmitMgr_drawPass1(gdl, mptr, vptr); + partEmitMgr_drawPass1(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { - func_8034F6F0(gdl, mptr, (s32)(intptr_t)vptr); + func_8034F6F0(gfx, mtx, (s32)(intptr_t)vtx); } - func_802D520C(gdl, mptr, vptr); + func_802D520C(gfx, mtx, vtx); } else { FrameInterpolation_RecordOpenChild("map_opa", 0); - mapModel_opa_draw(gdl, mptr, vptr); + mapModel_opa_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); - leveloverlay_drawCallback(gdl, mptr, vptr); - func_8034F6F0(gdl, mptr, (s32)(intptr_t)vptr); + leveloverlay_drawCallback(gfx, mtx, vtx); + func_8034F6F0(gfx, mtx, (s32)(intptr_t)vtx); FrameInterpolation_RecordOpenChild("player", 0); - player_draw(gdl, mptr, vptr); + player_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); - CALL_EVENT(OnPlayerDraw, gdl, mptr, vptr); - func_80302C94(gdl, mptr, vptr); - func_8032D3D8(gdl, mptr, vptr); + CALL_EVENT(OnPlayerDraw, gfx, mtx, vtx); + func_80302C94(gfx, mtx, vtx); + core2_A5BC0_drawUnknownMarkers(gfx, mtx, vtx); FrameInterpolation_RecordOpenChild("jiggylist", 0); - jiggylist_draw(gdl, mptr, vptr); + jiggylist_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); - func_803500D8(gdl, mptr, vptr); - func_802F2ED0(func_8032994C(), gdl, mptr, vptr); - func_802D520C(gdl, mptr, vptr); + func_803500D8(gfx, mtx, vtx); + func_802F2ED0(func_8032994C(), gfx, mtx, vtx); + func_802D520C(gfx, mtx, vtx); FrameInterpolation_RecordOpenChild("part_draw", 0); - partEmitMgr_draw(gdl, mptr, vptr); + partEmitMgr_draw(gfx, mtx, vtx); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { - func_80350818(gdl, mptr, vptr); + func_80350818(gfx, mtx, vtx); } if (game_is_frozen() == 0) { - func_802BBD0C(gdl, mptr, vptr); + func_802BBD0C(gfx, mtx, vtx); } spawnQueue_lock(); } @@ -144,15 +146,15 @@ void gsworld_stub1(s32 arg0, s32 arg1, s32 arg2){ } enum map_e gsworld_getMap(void){ - return sGsWorldData.map_4; + return sGsWorldData.map; } s32 gsworld_getExit(){ - return sGsWorldData.unk8; + return sGsWorldData.exit; } void gsworld_transitionToExit(s32 arg0) { - transitionToMap(sGsWorldData.map_4, arg0, 1); + transitionToMap(sGsWorldData.map, arg0, 1); } s32 gsworld_getUnk0(){ @@ -214,9 +216,9 @@ void gsworld_free(void) { itemPrint_free(); } dialogBin_terminate(); - func_802986D0(); - if (func_80322914() == 0) { - func_8024F7C4(func_803226E8(sGsWorldData.map_4)); + playerModel_free(); + if (!func_80322914()) { + func_8024F7C4(func_803226E8(sGsWorldData.map)); } core1_7090_release(); AnimTextureListCache_free(); @@ -228,12 +230,12 @@ void gsworld_free(void) { void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { sGsWorldData.unk0 = 3; - CALL_EVENT(OnMapLoad, sGsWorldData.map_4, arg0, arg1); - sGsWorldData.map_4 = arg0; + CALL_EVENT(OnMapLoad, sGsWorldData.map, arg0, arg1); + sGsWorldData.map = arg0; // [port] Drop the prev tree; the next sub-frame would otherwise lerp // the old map's geometry against the new one's. FrameInterpolation_DontInterpolateCamera(); - sGsWorldData.unk8 = arg1; + sGsWorldData.exit = arg1; leveloverlay_init(); gsworld_setEnableUpdate(1); gsworld_setEnableDraw(1); @@ -243,15 +245,15 @@ void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { func_8038E7C4(); } if (func_80322914() == 0) { - func_8024F764(func_803226E8(sGsWorldData.map_4)); + func_8024F764(func_803226E8(sGsWorldData.map)); } func_80320B84(); AnimTextureListCache_init(); func_8034C97C(); func_8030A078(); func_8031B718(); - func_80298700(); - if (func_802E4A08() == 0) { + playerModel_set(); + if (!func_802E4A08()) { itemPrint_init(); } dialogBin_initialize(); @@ -300,7 +302,7 @@ void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { func_80350174(); gcparade_init(); func_80351998(); - func_802BC2CC(sGsWorldData.unk8); + func_802BC2CC(sGsWorldData.exit); func_802D63D4(); func_80255A04(); func_802D6948(); @@ -314,11 +316,11 @@ void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { void gsworld_reload(void) { gsworld_free(); - gsworld_set(sGsWorldData.map_4, sGsWorldData.unk8, 1); + gsworld_set(sGsWorldData.map, sGsWorldData.exit, 1); } void gsworld_stub2(void) { - gsworld_stub3(sGsWorldData.map_4); + gsworld_stub3(sGsWorldData.map); } void gsworld_setUnk0(s32 arg0) { @@ -340,7 +342,7 @@ s32 gsworld_update(void) { s32 phi_v1; s32 phi_v0; - codeCF5F0_forgetAllAbilitiesExceptClawSwipeIfChecksumsFail(); + codeCF5F0_triggerAntiTamperMeasurement(); func_802D5628(); itemPrint_update(); if (getGameMode() != GAME_MODE_4_PAUSED) { @@ -383,7 +385,9 @@ s32 gsworld_update(void) { func_8031B790(); func_8034C9D4(); propModelList_flush(1); - sky_update(); + if (EventSystem_Should(VB_SKY_UPDATE, true)) { + sky_update(); + } partEmitMgr_update(); func_8034F918(); func_80350250(); @@ -403,7 +407,7 @@ s32 gsworld_update(void) { func_803306C8(1); func_8032AD7C(1); func_80322490(); - if (map_getLevel(sGsWorldData.map_4) == LEVEL_D_CUTSCENE) { + if (map_getLevel(sGsWorldData.map) == LEVEL_D_CUTSCENE) { func_802C79C4(); } func_8032AABC(); @@ -432,6 +436,7 @@ void gsworld_load(enum map_e map_id) { File *fp; port_noteRetention_beginMapLoad((int32_t)map_id); + port_carriedSync_beginMapLoad((int32_t)map_id); core1_15B30_sendMesg3ToRenderThread(); fp = file_openMap(map_id); //LevelSetupFile_Open diff --git a/src/core2/map/list.c b/src/core2/map/list.c index 7ee10a629..c2e0b0487 100644 --- a/src/core2/map/list.c +++ b/src/core2/map/list.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_12F30.c #include #include "functions.h" #include "variables.h" @@ -125,7 +126,7 @@ void func_80299EC0(f32 arg0[3]) { } else { sp78 = 250; } - _player_getPosition(spEC); + playerPosition_get(spEC); sp6C = func_8029463C(); spC8 = func_802946A8(); if (spC8 == NULL) { diff --git a/src/core2/map/loadzone.c b/src/core2/map/loadzone.c index 1ab7baf3c..c26f81e0e 100644 --- a/src/core2/map/loadzone.c +++ b/src/core2/map/loadzone.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_A960.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/model.c b/src/core2/map/mapModel.c similarity index 93% rename from src/core2/map/model.c rename to src/core2/map/mapModel.c index 8cb5f4c68..09517ffb5 100644 --- a/src/core2/map/model.c +++ b/src/core2/map/mapModel.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/mapModel.c #include #include "functions.h" #include "variables.h" @@ -11,7 +12,7 @@ extern BKCollisionTriangle *func_802E92AC(BKCollisionList *, BKVertexList *, f32 extern s32 bkmodelunk14list_func_802EC394(BKModelUnk14List *arg0, f32 position[3], f32 rotation[3], f32 scale, f32 arg4[3], f32 arg5[3], s32 arg6); extern void vtxList_getBounds_s32(BKVertexList *, s32[3], s32[3]); extern void func_802F7BC0(Gfx **, Mtx **, Vtx **); -extern void func_8033A45C(s32, s32); +extern void modelRender_setAppendageVisibility(s32, s32); extern Vec3fArray *vec3fArray_defrag(Vec3fArray *this); extern Vec3fArray *vec3fArray_new(void); extern void func_8034C6DC(BKModel *arg0); @@ -260,101 +261,101 @@ f32 func_80308FDC(f32 arg0[3], u32 arg1) { void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 temp_a0; if (func_80320708() && levelSpecificFlags_validateCRC2() && dummy_func_80320248()) { - if (mapModel_getOpaModelId() == ASSET_14CF_MODEL_SM_SPIRAL_MOUNTAIN_OPA) { - func_8033A45C(1, 0); - func_8033A45C(2, 1); + if (mapModel_getOpaModelId() == VER_SELECT(ASSET_14CF_MODEL_SM_SPIRAL_MOUNTAIN_OPA, 0xD2D, 0, 0)) { + modelRender_setAppendageVisibility(1, 0); + modelRender_setAppendageVisibility(2, 1); } switch (gsworld_getMap()) { /* irregular */ case MAP_88_CS_SPIRAL_MOUNTAIN_6: if (mapSpecificFlags_get(0) != 0) { - func_8033A45C(1, 1); - func_8033A45C(2, 0); + modelRender_setAppendageVisibility(1, 1); + modelRender_setAppendageVisibility(2, 0); } break; case MAP_12_GV_GOBIS_VALLEY: - func_8033A45C(1, levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN) ? 1 : 0); - func_8033A45C(2, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 0 : 1); - func_8033A45C(5, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 1 : 0); + modelRender_setAppendageVisibility(1, levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN) ? 1 : 0); + modelRender_setAppendageVisibility(2, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 0 : 1); + modelRender_setAppendageVisibility(5, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 1 : 0); break; case MAP_14_GV_SANDYBUTTS_MAZE: - func_8033A45C(5, (player_movementGroup() == BSGROUP_4_LOOK) ? 1 : 0); + modelRender_setAppendageVisibility(5, (player_movementGroup() == BSGROUP_4_LOOK) ? 1 : 0); break; case MAP_E_MM_MUMBOS_SKULL: - func_8033A45C(1, 1); - func_8033A45C(5, 1); + modelRender_setAppendageVisibility(1, 1); + modelRender_setAppendageVisibility(5, 1); break; case MAP_47_BGS_MUMBOS_SKULL: - func_8033A45C(1, 2); - func_8033A45C(5, 2); + modelRender_setAppendageVisibility(1, 2); + modelRender_setAppendageVisibility(5, 2); break; case MAP_48_FP_MUMBOS_SKULL: - func_8033A45C(1, 3); - func_8033A45C(5, 3); + modelRender_setAppendageVisibility(1, 3); + modelRender_setAppendageVisibility(5, 3); break; case MAP_30_MMM_MUMBOS_SKULL: - func_8033A45C(1, 4); - func_8033A45C(5, 4); + modelRender_setAppendageVisibility(1, 4); + modelRender_setAppendageVisibility(5, 4); break; case MAP_4A_CCW_SPRING_MUMBOS_SKULL: - func_8033A45C(1, 5); - func_8033A45C(5, 5); + modelRender_setAppendageVisibility(1, 5); + modelRender_setAppendageVisibility(5, 5); break; case MAP_4B_CCW_SUMMER_MUMBOS_SKULL: - func_8033A45C(1, 6); - func_8033A45C(5, 6); + modelRender_setAppendageVisibility(1, 6); + modelRender_setAppendageVisibility(5, 6); break; case MAP_4C_CCW_AUTUMN_MUMBOS_SKULL: - func_8033A45C(1, 7); - func_8033A45C(5, 7); + modelRender_setAppendageVisibility(1, 7); + modelRender_setAppendageVisibility(5, 7); break; case MAP_4D_CCW_WINTER_MUMBOS_SKULL: - func_8033A45C(1, 8); - func_8033A45C(5, 8); + modelRender_setAppendageVisibility(1, 8); + modelRender_setAppendageVisibility(5, 8); break; case MAP_5E_CCW_SPRING_NABNUTS_HOUSE: case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE: case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE: - func_8033A45C(1, 1); - func_8033A45C(2, 0); + modelRender_setAppendageVisibility(1, 1); + modelRender_setAppendageVisibility(2, 0); break; case MAP_61_CCW_WINTER_NABNUTS_HOUSE: - func_8033A45C(1, 0); - func_8033A45C(2, 1); + modelRender_setAppendageVisibility(1, 0); + modelRender_setAppendageVisibility(2, 1); break; case MAP_1D_MMM_CELLAR: - func_8033A45C(1, actorArray_findActorFromActorId(0x191) ? 0 : 1); + modelRender_setAppendageVisibility(1, actorArray_findActorFromActorId(0x191) ? 0 : 1); break; case MAP_7C_CS_INTRO_BANJOS_HOUSE_1: case MAP_89_CS_INTRO_BANJOS_HOUSE_2: case MAP_8A_CS_INTRO_BANJOS_HOUSE_3: case MAP_8C_SM_BANJOS_HOUSE: case MAP_91_FILE_SELECT: - func_8033A45C(5, 1); + modelRender_setAppendageVisibility(5, 1); break; case MAP_7B_CS_INTRO_GL_DINGPOT_1: case MAP_81_CS_INTRO_GL_DINGPOT_2: - func_8033A45C(4, 0); - func_8033A45C(5, 0); - func_8033A45C(6, 0); + modelRender_setAppendageVisibility(4, 0); + modelRender_setAppendageVisibility(5, 0); + modelRender_setAppendageVisibility(6, 0); break; case MAP_82_CS_ENTERING_GL_MACHINE_ROOM: case MAP_83_CS_GAME_OVER_MACHINE_ROOM: case MAP_84_CS_UNUSED_MACHINE_ROOM: - func_8033A45C(4, 1); - func_8033A45C(5, 1); - func_8033A45C(6, 1); + modelRender_setAppendageVisibility(4, 1); + modelRender_setAppendageVisibility(5, 1); + modelRender_setAppendageVisibility(6, 1); break; case MAP_93_GL_DINGPOT: - func_8033A45C(4, 1); - func_8033A45C(5, 1); - func_8033A45C(6, (jigsawPicture_isJigsawPictureComplete(0xA) || fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE))); + modelRender_setAppendageVisibility(4, 1); + modelRender_setAppendageVisibility(5, 1); + modelRender_setAppendageVisibility(6, (jigsawPicture_isJigsawPictureComplete(0xA) || fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE))); break; } modelRender_setRefPoints(mapModel.unk24); @@ -376,7 +377,7 @@ void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { if (mapModel.model_bin_xlu != NULL) { if (gsworld_getMap() == MAP_1D_MMM_CELLAR) { - func_8033A45C(1, (actorArray_findActorFromActorId(0x191) != NULL) ? 0 : 1); + modelRender_setAppendageVisibility(1, (actorArray_findActorFromActorId(0x191) != NULL) ? 0 : 1); } modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); temp_a0 = mapModel.unk4; diff --git a/src/core2/map/savestate.c b/src/core2/map/mapsavestate.c similarity index 99% rename from src/core2/map/savestate.c rename to src/core2/map/mapsavestate.c index 9e1aa4cce..a84578949 100644 --- a/src/core2/map/savestate.c +++ b/src/core2/map/mapsavestate.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/mapsavestate.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/specificflags.c b/src/core2/map/mapspecificflags.c similarity index 85% rename from src/core2/map/specificflags.c rename to src/core2/map/mapspecificflags.c index dfaac4ad8..e6df70f0d 100644 --- a/src/core2/map/specificflags.c +++ b/src/core2/map/mapspecificflags.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/mapspecificflags.c #include #include "functions.h" #include "variables.h" @@ -43,16 +44,24 @@ u32 mapSpecificFlags_getN(s32 idx, s32 n){ u32 mapSpecificFlags_getClear(s32 i){ u32 ret_val = mapSpecificFlags_get(i); - mapSpecificFlags_set(i, 0); + mapSpecificFlags_setEx(i, 0, 0); return ret_val; } -void mapSpecificFlags_set(s32 i, s32 val){ +void mapSpecificFlags_setEx(s32 i, s32 val, s32 triggerEvent){ + s32 changed = ((D_80367000 >> i) & 1) != (val ? 1 : 0); if(val) D_80367000 |= 1 << i; else D_80367000 &= ~(1 << i); _mapSpecificFlags_updateCRCs(); + if (triggerEvent && changed) { + CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_MAP_SPECIFIC, i, val ? 1 : 0, 1); + } +} + +void mapSpecificFlags_set(s32 i, s32 val){ + mapSpecificFlags_setEx(i, val, 1); } void mapSpecificFlags_setN(s32 idx, s32 val, s32 n){ diff --git a/src/core2/map/overlay.c b/src/core2/map/overlay.c index c37d3e3bf..9146ee351 100644 --- a/src/core2/map/overlay.c +++ b/src/core2/map/overlay.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_9B990.c -> overlay.c (level overlay callbacks) +// BanjoDecomp: core2/code_9B990.c #include #include "functions.h" #include "variables.h" @@ -164,22 +164,22 @@ static void leveloverlay_MMM_unk14(s32 arg0, s32 arg1) { } static void leveloverlay_CC_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { - CC_func_80388760(gfx, mtx, vtx); + maClanker_draw(gfx, mtx, vtx); } static void leveloverlay_CC_release(void) { - func_80388CB4(); - func_803880D4(); + maClanker_release(); + maClankerRings_release(); } static void leveloverlay_CC_init(void) { - func_80388D54(); - func_80388104(); + maClanker_init(); + maClankerRings_init(); } static void leveloverlay_CC_update(void) { - CC_func_80388F4C(); - func_8038817C(); + maClanker_update(); + maClankerRings_update(); } static void leveloverlay_CC_unk14(s32 arg0, s32 arg1) {} @@ -372,7 +372,8 @@ void leveloverlay_debug(void) {} void leveloverlay_init(void) { int i; enum overlay_e overlay_id; - func_80356714(); + + codeCF5F0_init(); overlay_id = overlayManager_getLoadedID(); sActiveCallbacks.init = NULL; sActiveCallbacks.update = NULL; diff --git a/src/core2/map/warp_dispatch.c b/src/core2/map/warp_dispatch.c index 98c6c7e0b..839b4a8b1 100644 --- a/src/core2/map/warp_dispatch.c +++ b/src/core2/map/warp_dispatch.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_AD110.c #include #include "functions.h" #include "variables.h" @@ -554,25 +555,28 @@ void func_80334448(NodeProp *arg0, ActorMarker *arg1) { s32 warpIdx; s32 warpDest; - switch(codeA5BC0_getNodePropBit6(arg0)) { + switch(codeA5BC0_getNodePropCategory(arg0)) { case 3: // warp (L80334480) global_timer_time = globalTimer_getTime(); if ((codeA5BC0_getNodePropUnkC(arg0) + 1) != global_timer_time) { - // [port] BB romhacks remap warp destinations via BKCF config - warpIdx = codeA5BC0_getNodePropUnk8(arg0); + // [port] Romhacks remap warp destinations via BKCF config + warpIdx = codeA5BC0_getNodePropActorId(arg0); warpDest = port_getRomhackWarpDest(warpIdx); CALL_EVENT(OnWarpDispatch, warpIdx, warpDest); - if (warpDest >= 0) { - func_8031CC8C(arg0, warpDest); - } else { - sWarpFunctions[warpIdx](arg0, arg1); + // [port] Romhacks can hold a warp shut behind progress + if (EventSystem_Should(VB_WARP_DISPATCH, true, warpIdx)) { + if (warpDest >= 0) { + func_8031CC8C(arg0, warpDest); + } else { + sWarpFunctions[warpIdx](arg0, arg1); + } } } codeA5BC0_setNodePropUnkC(arg0, global_timer_time); break; case 4: // radius trigger like camera (L803344E0) - sRadiusTriggers[codeA5BC0_getNodePropUnk8(arg0)](arg0, arg1); + sRadiusTriggers[codeA5BC0_getNodePropActorId(arg0)](arg0, arg1); break; case 0: //L80334508 diff --git a/src/core2/map/world_reset.c b/src/core2/map/world_reset.c index 93cfd6f83..5859154cb 100644 --- a/src/core2/map/world_reset.c +++ b/src/core2/map/world_reset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9A740.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/matrix_interp.c b/src/core2/matrix_interp.c index fe09ea19b..812af806c 100644 --- a/src/core2/matrix_interp.c +++ b/src/core2/matrix_interp.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C3A40.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/lighting.c b/src/core2/model/lighting.c index f5d86ff0f..0ed2de3c2 100644 --- a/src/core2/model/lighting.c +++ b/src/core2/model/lighting.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_66490.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/mesh_dataaccess.c b/src/core2/model/mesh_dataaccess.c index 27c9a16ca..58253b248 100644 --- a/src/core2/model/mesh_dataaccess.c +++ b/src/core2/model/mesh_dataaccess.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_63410.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/meshbounds.c b/src/core2/model/meshbounds.c index 2575ffe6d..cfe91eb90 100644 --- a/src/core2/model/meshbounds.c +++ b/src/core2/model/meshbounds.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B8080.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/render.c b/src/core2/model/modelRender.c similarity index 97% rename from src/core2/model/render.c rename to src/core2/model/modelRender.c index 87cbd446a..d701fb000 100644 --- a/src/core2/model/render.c +++ b/src/core2/model/modelRender.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/modelRender.c #include #include "core1/core1.h" #include "functions.h" @@ -154,7 +155,7 @@ void modelRender_geoCmd_DRAWDIST(Gfx **, Mtx **, struct bk_geo_cmd_s *); void modelRender_geoCmd_UnkE(Gfx **, Mtx **, struct bk_geo_cmd_s *); void modelRender_geoCmd_CAMERA(Gfx **, Mtx **, struct bk_geo_cmd_s *); void modelRender_executeGeoCmds(Gfx **, Mtx **, BKGeoCmd *); -void func_8033A45C(s32 arg0, s32 arg1); +void modelRender_setAppendageVisibility(s32 arg0, s32 arg1); // Sets up 2 cycle mode Gfx setup2CycleDL[] = @@ -690,8 +691,8 @@ void modelRender_reset(void){ D_803837B0.unk0 = 0; sSecondaryModelData.model_id = 0; modelRenderDepthMode = MODEL_RENDER_DEPTH_NONE; - func_8033A45C(1,1); - func_8033A45C(2,0); + modelRender_setAppendageVisibility(1,1); + modelRender_setAppendageVisibility(2,0); if(D_80383758.unk18){ viewport_setPosition_vec3f(D_80383758.unk1C); viewport_setRotation_vec3f(D_80383758.unk28); @@ -710,6 +711,7 @@ void modelRender_geoCmd_Unk0(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2){ f32 sp30[3]; if(cmd->unk8){ + FrameInterpolation_RecordOpenChildHash3("billboard", (uintptr_t)cmd, 0, 0); mlMtx_apply_vec3f(sp30, cmd->unkC); mlMtx_push_translation(sp30[0], sp30[1], sp30[2]); mlMtxRotYaw(modelRenderCameraRotation[1]); @@ -723,6 +725,7 @@ void modelRender_geoCmd_Unk0(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2){ modelRender_executeGeoCmds(gfx, mtx, (BKGeoCmd*)((u8*)cmd + cmd->unk8)); mlMtxPop(); gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW); + FrameInterpolation_RecordCloseChild(); } } @@ -791,11 +794,8 @@ void modelRender_geoCmd_TEXWRAP(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2) void modelRender_geoCmd_BONE(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2){ GeoCmd2 *cmd = (GeoCmd2 *)arg2; - // [port] Stable per-bone scope. Without it, any op-count shift in the - // geo walk mis-pairs every subsequent bone — Banjo ends up half in - // one pose and half in another on the affected sub-frame. Nested - // bones nest their scopes via the recursive walk below. - FrameInterpolation_RecordOpenChild("bone", (uintptr_t)(u8)cmd->unk9); + // [port] Stable per-bone scope. + FrameInterpolation_RecordOpenChildHash3("bone", (uintptr_t)(u8)cmd->unk9, (uintptr_t)cmd, 0); if(D_8038371C){ mlMtx_push_multiplied_2(&D_80383BF8, animMtxList_get(D_8038371C, cmd->unk9)); if(D_80370990){ @@ -958,8 +958,10 @@ void modelRender_geoCmd_DRAWDIST(Gfx ** gfx, Mtx ** mtx, struct bk_geo_cmd_s *ar sp20[2] = (f32)cmd->unkE[2] * modelRenderScale; // [port] The N64 bounding boxes in CmdD_DRAW_DISTANCE are too conservative // for the port's viewport (292x216 -> 320x240 at 4:3). Extend to all aspect - //ratios since the port always renders at a higher effective resolution. - modelRender_executeGeoCmds(gfx, mtx, (BKGeoCmd*)((u8*)cmd + cmd->unk14)); + // ratios since the port always renders at a higher effective resolution. + if (EventSystem_Should(VB_DRAWDIST_BOX_CULL, true, sp2C, sp20)) { + modelRender_executeGeoCmds(gfx, mtx, (BKGeoCmd*)((u8*)cmd + cmd->unk14)); + } } } @@ -1157,6 +1159,7 @@ BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation tmp_f0 = D_80383708 - 500.0f; if(tmp_f0 < camera_focus_distance){ alpha = (s32)((1.0f - (camera_focus_distance - tmp_f0)/500.0f)*255.0f); + EventSystem_Should(VB_MODEL_DRAWDIST_FADE_ALPHA, true, &alpha); if(modelRenderColorMode == COLOR_MODE_DYNAMIC_PRIM_AND_ENV){ modelRenderDynColors.prim[3] = (modelRenderDynColors.prim[3] * alpha) / 0xff; } @@ -1289,6 +1292,8 @@ BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation if(model_bin->anim_vertices_list_offset != 0 && D_8038371C != NULL){ animVerticesList_transform((BKAnimVerticesList *)((uintptr_t)modelRenderModelBin + (uintptr_t)(u32)modelRenderModelBin->anim_vertices_list_offset), modelRendervertexList, D_8038371C); + // [port] The transform just posed the model's shared vertex array. Hand this draw a private copy. + port_modelRender_snapshotAnimVertices(gfx, vtxList_getVertices(modelRendervertexList), vtxList_getVtxCount(modelRendervertexList)); } mlMtxIdent(); @@ -1327,6 +1332,9 @@ BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation // [port] Mirror mode: restore culling inversion if (_mirror_excluded) gSPSetExtraGeometryMode((*gfx)++, G_EX_INVERT_CULLING); gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW); + // [port] Romhack model DLs can leave a palette (TLUT) mode enabled and leak it + // into the next model's draw; reset it after every model for romhacks. + port_modelRenderResetTLUT(gfx); if(modelRenderCallback.post_draw != NULL){ modelRenderCallback.post_draw(modelRenderCallback.post_draw_arg); @@ -1538,8 +1546,8 @@ void modelRender_setRefPoints(Vec3fArray *arg0){ modelRenderRefPoints = arg0; } -void func_8033A45C(s32 arg0, s32 arg1){ - D_80383658[arg0] = arg1; +void modelRender_setAppendageVisibility(s32 appendage_id, s32 appendage_visibility){ + D_80383658[appendage_id] = appendage_visibility; } void modelRender_func_8033A470(s32 arg0, s32 arg1){ diff --git a/src/core2/model/rendernormal.c b/src/core2/model/rendernormal.c index 5f3355085..f3502200e 100644 --- a/src/core2/model/rendernormal.c +++ b/src/core2/model/rendernormal.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_5FB00.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/skinning.c b/src/core2/model/skinning.c index 2d08038a8..e924e029f 100644 --- a/src/core2/model/skinning.c +++ b/src/core2/model/skinning.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_637D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/vertex_brightness.c b/src/core2/model/vertex_brightness.c index 908d1260e..056e99524 100644 --- a/src/core2/model/vertex_brightness.c +++ b/src/core2/model/vertex_brightness.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C8360.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/mumbo_transforms.c b/src/core2/mumbo.c similarity index 74% rename from src/core2/mumbo_transforms.c rename to src/core2/mumbo.c index a495a1ef9..4b3031d82 100644 --- a/src/core2/mumbo_transforms.c +++ b/src/core2/mumbo.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/mumbo.c #include #include "functions.h" #include "variables.h" @@ -25,7 +26,7 @@ ActorAnimationInfo D_80367490[] = { {ASSET_180_ANIM_MUMBO_ROTATE, 0.7f}, }; -ActorInfo D_803674E0 = { +ActorInfo chMumbo = { MARKER_6_MUMBO, ACTOR_7_MUMBO, ASSET_3C6_MODEL_MUMBO, 0x1, D_80367490, chMumbo_update, actor_update_func_80326224, chMumbo_draw, @@ -54,17 +55,17 @@ static bool __chMumbo_actorExists(enum actor_e actorId) { enum transformation_e func_802D16AC(void) { s32 ret = TRANSFORM_2_TERMITE; - __chMumbo_actorExists(0x1F); - if (__chMumbo_actorExists(0x20)) { + __chMumbo_actorExists(ACTOR_1F_UNUSED); + if (__chMumbo_actorExists(ACTOR_20_TRANSFORM_PUMPKIN)) { ret = TRANSFORM_3_PUMPKIN; } - if (__chMumbo_actorExists(0x21)) { + if (__chMumbo_actorExists(ACTOR_21_TRANSFORM_CROC)) { ret = TRANSFORM_5_CROC; } - if (__chMumbo_actorExists(0x22)) { + if (__chMumbo_actorExists(ACTOR_22_TRANSFORM_WALRUS)) { ret = TRANSFORM_4_WALRUS; } - if (__chMumbo_actorExists(0x23)) { + if (__chMumbo_actorExists(ACTOR_23_TRANSFORM_BEE)) { ret = TRANSFORM_6_BEE; } return ret; @@ -149,24 +150,24 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 this = marker_getActor(caller); switch(text_id){ - case ASSET_D8F_DIALOG_MUMBO_MEET: //L802D1A04 - gcdialog_showDialog((this->unk38_0) ? ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS : ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS, 0xe, this->position, this->marker, __chMumbo_textCallback, NULL); + case VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0): //L802D1A04 + gcdialog_showDialog((this->unk38_0) ? VER_SELECT(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xA28, 0, 0) : VER_SELECT(ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS, 0xA29, 0, 0), 0xe, this->position, this->marker, __chMumbo_textCallback, NULL); return; - case ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR: //L802D1A40 - fileProgressFlag_set(FILEPROG_12_HAS_TRANSFORMED_BEFORE, true); - gcdialog_showDialog(ASSET_D8F_DIALOG_MUMBO_MEET + D_8037DDF0, 4, NULL, NULL, NULL, NULL); + case VER_SELECT(ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR, 0xA0E, 0, 0): //L802D1A40 + fileProgressFlag_set(FILEPROG_12_HAS_TRANSFORMED_BEFORE, TRUE); + gcdialog_showDialog(VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0) + D_8037DDF0, 4, NULL, NULL, NULL, NULL); gcpausemenu_80314AC8(1); break; - case ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS: //L802D1A7C /* fall-through */ - fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, true); - case ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS: //L802D1A88 + case VER_SELECT(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xA28, 0, 0): //L802D1A7C /* fall-through */ + fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, TRUE); + case VER_SELECT(ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS, 0xA29, 0, 0): //L802D1A88 func_8028F918(0); break; - case ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE: //L802D1A98 - this->has_met_before = false; + case VER_SELECT(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xA2D, 0, 0): //L802D1A98 + this->has_met_before = FALSE; if(this->unk38_31 != 0){ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); item_adjustByDiffWithHud(ITEM_1C_MUMBO_TOKEN, -this->unk38_31); @@ -175,9 +176,9 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 subaddie_set_state_with_direction(this, 5, 0.0f, 1); return; - case ASSET_DB0_DIALOG_MUMBO_MISTAKE_0: //L802D1AF8 - case ASSET_DB1_DIALOG_MUMBO_MISTAKE_1: //L802D1AF8 - case ASSET_DB2_DIALOG_MUMBO_MISTAKE_2: //L802D1AF8 + case VER_SELECT(ASSET_DB0_DIALOG_MUMBO_MISTAKE_0, 0xA2E, 0, 0): //L802D1AF8 + case VER_SELECT(ASSET_DB1_DIALOG_MUMBO_MISTAKE_1, 0xA2F, 0, 0): //L802D1AF8 + case VER_SELECT(ASSET_DB2_DIALOG_MUMBO_MISTAKE_2, 0xA30, 0, 0): //L802D1AF8 D_8037DDF0 = this->unk10_12; this->unk10_12 = 1; if(this->unk38_31){ @@ -185,7 +186,7 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 item_adjustByDiffWithHud(ITEM_1C_MUMBO_TOKEN, -this->unk38_31); } - case ASSET_DAE_DIALOG_MUMBO_TREX_START: //L802D1B48 + case VER_SELECT(ASSET_DAE_DIALOG_MUMBO_TREX_START, 0xA2C, 0, 0): //L802D1B48 subaddie_set_state_with_direction(this, 5, 0.0f, 1); return; @@ -198,24 +199,24 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 void chMumbo_func_802D1B8C(Actor *this, enum transformation_e transform_id) { if (this->unk10_12 != 0) { - gcdialog_showDialog(fileProgressFlag_getN(FILEPROG_BB_MUMBO_MISTAKE_INDEX, 2) + ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(fileProgressFlag_getN(FILEPROG_BB_MUMBO_MISTAKE_INDEX, 2) + VER_SELECT(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xA2D, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); return; } if (fileProgressFlag_get(FILEPROG_12_HAS_TRANSFORMED_BEFORE)) { if (this->velocity[0] == 0.0f) { - gcdialog_showDialog(transform_id + ASSET_D8F_DIALOG_MUMBO_MEET, 6, this->position, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(transform_id + VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0), 6, this->position, this->marker, __chMumbo_textCallback, NULL); return; } if (gsworld_getMap() == MAP_7A_GL_CRYPT && transform_id == TRANSFORM_3_PUMPKIN && !fileProgressFlag_get(FILEPROG_F7_HAS_TRANSFORMED_IN_CRYPT)) { - gcdialog_showDialog(ASSET_DAD_DIALOG_MUMBO_XFORM_IN_CRYPT, 6, this->position, this->marker, __chMumbo_textCallback, NULL); - fileProgressFlag_set(FILEPROG_F7_HAS_TRANSFORMED_IN_CRYPT, true); + gcdialog_showDialog(VER_SELECT(ASSET_DAD_DIALOG_MUMBO_XFORM_IN_CRYPT, 0xA2B, 0, 0), 6, this->position, this->marker, __chMumbo_textCallback, NULL); + fileProgressFlag_set(FILEPROG_F7_HAS_TRANSFORMED_IN_CRYPT, TRUE); return; } gcpausemenu_80314AC8(1); subaddie_set_state(this, 4U); return; } - gcdialog_showDialog(ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR, 0xA0E, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); } void chMumbo_update(Actor *this) { @@ -288,8 +289,8 @@ void chMumbo_update(Actor *this) { && !volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) ) { subaddie_set_state(this, 3); - gcdialog_showDialog(ASSET_D8F_DIALOG_MUMBO_MEET, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); - fileProgressFlag_set(FILEPROG_11_HAS_MET_MUMBO, true); + gcdialog_showDialog(VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + fileProgressFlag_set(FILEPROG_11_HAS_MET_MUMBO, TRUE); break; } @@ -299,8 +300,8 @@ void chMumbo_update(Actor *this) { && this->unk38_0 ){ subaddie_set_state(this, 3); - gcdialog_showDialog(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); - fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, true); + gcdialog_showDialog(VER_SELECT(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xA28, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, TRUE); break; } @@ -317,7 +318,7 @@ void chMumbo_update(Actor *this) { sp48 = (gsworld_getMap() == MAP_7A_GL_CRYPT) ? chMumbo_withinHorzDistToPlayer(0x442, 0, 0x3C) : chMumbo_withinHorzDistToPlayer(0, -0x5A, 0x3C); if( sp48 && player_movementGroup() == BSGROUP_0_NONE - && func_8028F20C() + && player_isStableWithExtraSteps() && func_8028EFC8() ){ controller_copyFaceButtons(0, face_buttons); @@ -334,10 +335,10 @@ void chMumbo_update(Actor *this) { func_8028F94C(2, this->position); if ( sp44 && gsworld_getMap() != MAP_7A_GL_CRYPT && !fileProgressFlag_get(FILEPROG_BA_HAS_SEEN_TREX_TEXT) - && randf() < 0.01 + && romhack_mumboRandomEventsAllowed() && randf() < 0.01 && sp48 ) { - gcdialog_showDialog(ASSET_DAE_DIALOG_MUMBO_TREX_START, 6, NULL, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_DAE_DIALOG_MUMBO_TREX_START, 0xA2C, 0, 0), 6, NULL, this->marker, __chMumbo_textCallback, NULL); fileProgressFlag_set(FILEPROG_BA_HAS_SEEN_TREX_TEXT, 1); this->has_met_before = true; subaddie_set_state(this, 3); @@ -346,7 +347,7 @@ void chMumbo_update(Actor *this) { && gsworld_getMap() != MAP_7A_GL_CRYPT && !this->unk138_23 && (sp40 = fileProgressFlag_getN(FILEPROG_BB_MUMBO_MISTAKE_INDEX, 2), sp40 < 3) - && randf() < 0.05 + && romhack_mumboRandomEventsAllowed() && randf() < 0.05 && sp48 ){ this->unk138_23 = true; @@ -366,7 +367,7 @@ void chMumbo_update(Actor *this) { break; } coMusicPlayer_playMusic(COMUSIC_2C_BUZZER, 22000); - if ((levelSpecificFlags_get(LEVEL_FLAG_3E_UNKNOWN) == false) && (gcdialog_showDialog(ASSET_DAC_DIALOG_MUMBO_FAIL_TO_BUY, 0, NULL, NULL, NULL, NULL) != 0)) { + if ((levelSpecificFlags_get(LEVEL_FLAG_3E_UNKNOWN) == FALSE) && (gcdialog_showDialog(VER_SELECT(ASSET_DAC_DIALOG_MUMBO_FAIL_TO_BUY, 0xA2A, 0, 0), 0, NULL, NULL, NULL, NULL) != 0)) { levelSpecificFlags_set(LEVEL_FLAG_3E_UNKNOWN, 1); } } @@ -374,6 +375,10 @@ void chMumbo_update(Actor *this) { break; case 5: //L802D2488 + // [port] Fast Transformation drives this state from Cheats.cpp instead. + if (!EventSystem_Should(VB_MUMBO_HUT_TRANSFORM_CUTSCENE, true, this)) { + break; + } actor_playAnimationOnce(this); if (actor_animationIsAt(this, 0.35f)){ sfxSource_func_8030E2C4(this->unk44_31); @@ -394,11 +399,11 @@ void chMumbo_update(Actor *this) { if ( this->has_met_before || (this->unk10_12 == 0 && (player_getTransformation() != TRANSFORM_1_BANJO) - && (player_getTransformation() != TRANSFORM_7_WISHWASHY)) + && (player_getTransformation() != romhack_mumboWishwashyId())) ) { - func_8028FB88(TRANSFORM_1_BANJO); - } else if (func_8028FB88(D_8037DDF0)) { - if (D_8037DDF0 != TRANSFORM_7_WISHWASHY) { + romhack_mumboTransform(TRANSFORM_1_BANJO); + } else if (romhack_mumboTransform(D_8037DDF0)) { + if (D_8037DDF0 != romhack_mumboWishwashyId()) { if (fileProgressFlag_getAndSet(__bkProgId_from_transformationId(D_8037DDF0), true)) { this->velocity[0] = 1.0f; } @@ -424,7 +429,7 @@ void chMumbo_update(Actor *this) { } if (this->has_met_before) { subaddie_set_state(this, 3); - gcdialog_showDialog(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 6, NULL, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(VER_SELECT(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xA2D, 0, 0), 6, NULL, this->marker, __chMumbo_textCallback, NULL); break; } gcpausemenu_80314AC8(1); @@ -441,8 +446,8 @@ void chMumbo_update(Actor *this) { sp48 = chMumbo_withinHorzDistToPlayer(0, -0x6B, 0xBC); } if (sp48 != 0) { - gcdialog_showDialog(ASSET_DA7_DIALOG_MUMBO_CCW_SUMMER, 7, NULL, NULL, NULL, NULL); - volatileFlag_set(VOLATILE_FLAG_11, true); + gcdialog_showDialog(VER_SELECT(ASSET_DA7_DIALOG_MUMBO_CCW_SUMMER, 0xA25, 0, 0), 7, NULL, NULL, NULL, NULL); + volatileFlag_set(VOLATILE_FLAG_11, TRUE); } } actor_loopAnimation(this); @@ -457,8 +462,8 @@ void chMumbo_update(Actor *this) { sp48 = chMumbo_withinHorzDistToPlayer(0, -0x6B, 0xBC); } if (sp48 != 0) { - gcdialog_showDialog(ASSET_DA8_DIALOG_MUMBO_CCW_AUTUMN, 7, NULL, NULL, NULL, NULL); - volatileFlag_set(VOLATILE_FLAG_12, true); + gcdialog_showDialog(VER_SELECT(ASSET_DA8_DIALOG_MUMBO_CCW_AUTUMN, 0xA26, 0, 0), 7, NULL, NULL, NULL, NULL); + volatileFlag_set(VOLATILE_FLAG_12, TRUE); } } actor_loopAnimation(this); @@ -489,12 +494,12 @@ Actor *chMumbo_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { f32 sp44[3]; f32* sp38 = D_80367510; - func_8033A45C(4, (this->lifetime_value == 0.0f)); - func_8033A45C(5, (this->lifetime_value == 1.0f)); - func_8033A45C(6, (this->lifetime_value == 0.0f)); - func_8033A45C(7, (this->lifetime_value == 1.0f)); - func_8033A45C(8, (this->lifetime_value == 2.0f)); - func_8033A45C(9, 0); + modelRender_setAppendageVisibility(4, (this->lifetime_value == 0.0f)); + modelRender_setAppendageVisibility(5, (this->lifetime_value == 1.0f)); + modelRender_setAppendageVisibility(6, (this->lifetime_value == 0.0f)); + modelRender_setAppendageVisibility(7, (this->lifetime_value == 1.0f)); + modelRender_setAppendageVisibility(8, (this->lifetime_value == 2.0f)); + modelRender_setAppendageVisibility(9, 0); out = actor_draw(marker, gfx, mtx, vtx); if( marker->unk14_21 && out->state == 8){ if( actor_animationIsAt(out, 0.2f) @@ -509,26 +514,30 @@ Actor *chMumbo_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { } void chMumbo_detransformWarn(NodeProp *arg0, ActorMarker *arg1){ - s32 xform; - xform = player_getTransformation(); - if(xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || sHasWarnedBanjoAboutDetransform) - return; - - sHasWarnedBanjoAboutDetransform++; - if(D_8037DDF3) - return; - - gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_83_MAGIC_GET_WEAK_TEXT, true) ? ASSET_F5C_DIALOG_MUMBO_MAGIC_GET_WEAK_ABREV : ASSET_F5B_DIALOG_MUMBO_MAGIC_GET_WEAK_FULL, 0xe, NULL, NULL, NULL, NULL); + if (EventSystem_Should(VB_MUMBO_DETRANSFORM, true)) { + s32 xform; + xform = player_getTransformation(); + if (xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || sHasWarnedBanjoAboutDetransform) + return; + + sHasWarnedBanjoAboutDetransform++; + if (D_8037DDF3) + return; + + gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_83_MAGIC_GET_WEAK_TEXT, TRUE) ? VER_SELECT(ASSET_F5C_DIALOG_MUMBO_MAGIC_GET_WEAK_ABREV, 0xAC2, 0, 0) : VER_SELECT(ASSET_F5B_DIALOG_MUMBO_MAGIC_GET_WEAK_FULL, 0xAC1, 0, 0), 0xe, NULL, NULL, NULL, NULL); + } } void chMumbo_detransformTrigger(NodeProp *arg0, ActorMarker *arg1){ - s32 xform; - xform = player_getTransformation(); - if(xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || D_8037DDF1) - return; - gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_84_MAGIC_ALL_GONE_TEXT, true) ? ASSET_F5E_DIALOG_MUMBO_MAGIC_RUN_OUT_ABREV: ASSET_F5D_DIALOG_MUMBO_MAGIC_RUN_OUT_FULL, 0xe, NULL, NULL, NULL, NULL); - D_8037DDF1++; - func_8028FB88(TRANSFORM_1_BANJO); + if (EventSystem_Should(VB_MUMBO_DETRANSFORM, true)) { + s32 xform; + xform = player_getTransformation(); + if (xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || D_8037DDF1) + return; + gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_84_MAGIC_ALL_GONE_TEXT, TRUE) ? VER_SELECT(ASSET_F5E_DIALOG_MUMBO_MAGIC_RUN_OUT_ABREV, 0xAC4, 0, 0) : VER_SELECT(ASSET_F5D_DIALOG_MUMBO_MAGIC_RUN_OUT_FULL, 0xAC3, 0, 0), 0xe, NULL, NULL, NULL, NULL); + D_8037DDF1++; + player_transform(TRANSFORM_1_BANJO); + } } void func_802D2CB8(void){ diff --git a/src/core2/score_mumbo.c b/src/core2/mumboscore.c similarity index 97% rename from src/core2/score_mumbo.c rename to src/core2/mumboscore.c index e0d6a820e..d0a0b8248 100644 --- a/src/core2/score_mumbo.c +++ b/src/core2/mumboscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/mumboscore.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/demo_ctrl.c b/src/core2/mumboshandwithpicture.c similarity index 68% rename from src/core2/demo_ctrl.c rename to src/core2/mumboshandwithpicture.c index d7f4f15cb..5c4b044fe 100644 --- a/src/core2/demo_ctrl.c +++ b/src/core2/mumboshandwithpicture.c @@ -1,31 +1,31 @@ +// BanjoDecomp: core2/ch/mumboshandwithpicture.c #include #include "functions.h" #include "variables.h" extern void actor_postdrawMethod(ActorMarker *); extern void chBottlesBonus_func_802DD080(Gfx **, Mtx **); -extern void func_80311714(s32); #include "port/Patches/Patches.h" -Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_802DEE1C(Actor *this); +Actor *chMumbosHandWithPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chMumbosHandWithPicture_update(Actor *this); /* .data */ -ActorAnimationInfo D_80368300[] ={ +ActorAnimationInfo chMumbosHandWithPictureAnimations[] ={ {0x000, 0.0f}, - {0x2C7, 0.6f}, - {0x2C6, 3.0f}, - {0x2C8, 0.6f}, - {0x2C8, 0.6f}, - {0x2C6, 9e+09}, + {ASSET_2C7_ANIM_MUMBOS_HAND_WITH_PICTURE, 0.6f}, + {ASSET_2C6_ANIM_MUMBOS_HAND_WITH_PICTURE, 3.0f}, + {ASSET_2C8_ANIM_MUMBOS_HAND_WITH_PICTURE, 0.6f}, + {ASSET_2C8_ANIM_MUMBOS_HAND_WITH_PICTURE, 0.6f}, + {ASSET_2C6_ANIM_MUMBOS_HAND_WITH_PICTURE, 9e+09}, }; f32 D_80368330[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_8036833C = { - 0x294, 0x19B, ASSET_56D_MUMBOS_HAND_WITH_PICTURE, - 0x1, D_80368300, - func_802DEE1C, actor_update_func_80326224, func_802DEC00, +ActorInfo chMumbosHandWithPicture = { + MARKER_294_MUMBOS_HAND_WITH_PICTURE, ACTOR_19B_MUMBOS_HAND_WITH_PICTURE, ASSET_56D_MUMBOS_HAND_WITH_PICTURE, + 0x1, chMumbosHandWithPictureAnimations, + chMumbosHandWithPicture_update, actor_update_func_80326224, chMumbosHandWithPicture_draw, 0, 0, 0.0f, 0 }; @@ -36,7 +36,7 @@ BKModelBin *D_8037DFE8; f32 D_8037DFF0[3]; /* .code */ -Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *chMumbosHandWithPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this; f32 sp58[3]; f32 sp4C[3]; @@ -44,7 +44,7 @@ Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ this = marker_getActor(marker); - sp48 = func_8030C704(); + sp48 = picturebox_getColorBuffer(); if ((sp48 == 0) || (getGameMode() != GAME_MODE_A_SNS_PICTURE)) return this; @@ -62,14 +62,13 @@ Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ D_8037DFF0[1] = 270.0f; D_8037DFF0[2] = 0.0f; // [port] Draw the background picture and Mumbo's hand without depth testing. - // On N64, func_80253190 cleared the hardware depth buffer between the two draws + // On N64, depthbuffer_clear cleared the hardware depth buffer between the two draws // via CPU-accessible memory. On PC, the GBI depth fill may not translate to a // GPU depth clear, causing the hand to fail depth tests against the 3D scene. modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE); modelRender_draw(gfx, mtx, sp58, NULL, 1.0f, sp4C, D_8037DFE8); gDPSetColorDither((*gfx)++, G_CD_DISABLE); - func_80253190(gfx); - port_readAuxFbToCpu(gfx); + depthbuffer_clear(gfx); gDPSetTextureFilter((*gfx)++, G_TF_BILERP); gSPSegment((*gfx)++, 0x04, osVirtualToPhysical(sp48)); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)this); @@ -95,11 +94,11 @@ void func_802DEDDC(Actor *this){ } -void func_802DEE1C(Actor *this) { - s32 sp4C; - s32 sp48; - s32 sp44; - f32 sp38; +void chMumbosHandWithPicture_update(Actor *this) { + enum level_e level_id_1; + enum asset_e text_id; + enum level_e level_id_2; + f32 time; if (!this->initialized) { this->initialized = true; @@ -107,33 +106,33 @@ void func_802DEE1C(Actor *this) { marker_setFreeMethod(this->marker, func_802DEDDC); actor_playAnimationOnce(this); if (D_8037DFE8 == NULL) { - D_8037DFE8 = assetcache_get(0x56E); + D_8037DFE8 = assetcache_get(ASSET_56E_HAMMERHEAD_BEACH_SCENERY); } - sp4C = map_getLevel(gsworld_getMap()); - sp44 = sp4C == D_8037DFE4; - if (sp44) { + level_id_1 = map_getLevel(gsworld_getMap()); + level_id_2 = level_id_1 == D_8037DFE4; + if (level_id_2) { subaddie_set_state_with_direction(this, 2, 0.0f, 1); actor_loopAnimation(this); } - switch(sp4C){ + switch(level_id_1){ case LEVEL_2_TREASURE_TROVE_COVE: - sp48 = sp44 + 0xE39; + text_id = level_id_2 + 0xE39; // 0xE3B break; case LEVEL_5_FREEZEEZY_PEAK: - sp48 = sp44 + 0xE3B; + text_id = level_id_2 + 0xE3B; // 0xE40 break; case LEVEL_7_GOBIS_VALLEY: default: - sp48 = sp44 + 0xE3D; + text_id = level_id_2 + 0xE3D; // 0xE44 break; } - sp38 = (f32) ((f64) (sp44 + 1) * 0.75); - timedFunc_set_1(sp38, (GenFunction_1)func_80311714, 0); - func_80324DBC(sp38, sp48, 0x80, NULL, NULL, NULL, NULL); - timedFunc_set_1(sp38, (GenFunction_1)func_80311714, 1); - D_8037DFE4 = sp4C; + time = (f32) ((f64) (level_id_2 + 1) * 0.75); + timedFunc_set_1(time, (GenFunction_1)func_80311714, 0); + func_80324DBC(time, text_id, 0x80, NULL, NULL, NULL, NULL); + timedFunc_set_1(time, (GenFunction_1)func_80311714, 1); + D_8037DFE4 = level_id_1; } switch(this->state){ case 1: diff --git a/src/core2/camera/firstpersoncamera.c b/src/core2/nc/1p.c similarity index 74% rename from src/core2/camera/firstpersoncamera.c rename to src/core2/nc/1p.c index 1c1af0010..89539d0cc 100644 --- a/src/core2/camera/firstpersoncamera.c +++ b/src/core2/nc/1p.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/ba/1p.c #include #include "functions.h" #include "variables.h" @@ -5,7 +6,7 @@ extern void func_802BD780(f32[3], f32[3], f32, f32, f32, f32); -void ncFirstPersonCamera_setState(enum nc_first_person_state state); +void ncba1p_setState(enum nc_first_person_state state); /* .bss */ struct{ @@ -20,11 +21,11 @@ struct{ } D_8037DC60; /* .code */ -bool __ncFirstPersonCamera_fullyZoomedIn(void) { +bool __ncba1p_fullyZoomedIn(void) { return (ml_vec3f_distance(D_8037DC60.position, D_8037DC60.zoomed_in_position) < 40.0f); } -void __ncFirstPersonCamera_getPositionAndRotation_entering(f32 arg0[3], f32 arg1[3]) { +void __ncba1p_getPositionAndRotation_entering(f32 arg0[3], f32 arg1[3]) { s32 i; ml_sub_delta_time(&D_8037DC60.transistion_timer); @@ -33,9 +34,9 @@ void __ncFirstPersonCamera_getPositionAndRotation_entering(f32 arg0[3], f32 arg1 D_8037DC60.rotation[i] = mlNormalizeAngle(D_8037DC60.zoomed_out_rotation[i] + func_80257CF8(D_8037DC60.transistion_timer, 0.5f, 0.0f, 0.0f, mlDiffDegF(D_8037DC60.zoomed_in_rotation[i], D_8037DC60.zoomed_out_rotation[i]))); } if (D_8037DC60.transistion_timer == 0.0f) { - ncFirstPersonCamera_setState(FIRSTPERSON_STATE_2_IDLE); + ncba1p_setState(FIRSTPERSON_STATE_2_IDLE); } - if (__ncFirstPersonCamera_fullyZoomedIn() && func_8028F150()) { + if (__ncba1p_fullyZoomedIn() && func_8028F150()) { player_setModelVisible(0); } ml_vec3f_copy(arg0, D_8037DC60.position); @@ -43,7 +44,7 @@ void __ncFirstPersonCamera_getPositionAndRotation_entering(f32 arg0[3], f32 arg1 } -void __ncFirstPersonCamera_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[3]) { +void __ncba1p_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[3]) { s32 i; ml_sub_delta_time(&D_8037DC60.transistion_timer); @@ -52,9 +53,9 @@ void __ncFirstPersonCamera_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[ D_8037DC60.rotation[i] = mlNormalizeAngle(D_8037DC60.zoomed_in_rotation[i] + func_80257CF8(D_8037DC60.transistion_timer, 1.0f, 0.5f, 0.0f, mlDiffDegF(arg1[i], D_8037DC60.zoomed_in_rotation[i]))); } if (D_8037DC60.transistion_timer == 0.0f) { - ncFirstPersonCamera_setState(FIRSTPERSON_STATE_4_DONE); + ncba1p_setState(FIRSTPERSON_STATE_4_DONE); } - if (!__ncFirstPersonCamera_fullyZoomedIn() && !func_8028F150()) { + if (!__ncba1p_fullyZoomedIn() && !func_8028F150()) { player_setModelVisible(1); } ml_vec3f_copy(arg0, D_8037DC60.position); @@ -62,7 +63,7 @@ void __ncFirstPersonCamera_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[ } -void __ncFirstPersonCamera_getPositionAndRotation_idle(f32 arg0[3], f32 arg1[3]) { +void __ncba1p_getPositionAndRotation_idle(f32 arg0[3], f32 arg1[3]) { ml_vec3f_copy(D_8037DC60.position, D_8037DC60.zoomed_in_position); func_802BD780(D_8037DC60.zoomed_in_rotation, D_8037DC60.rotation, 10.0f, 20.0f, 120.0f, 200.0f); D_8037DC60.rotation[2] = 0.0f; @@ -70,7 +71,7 @@ void __ncFirstPersonCamera_getPositionAndRotation_idle(f32 arg0[3], f32 arg1[3]) ml_vec3f_copy(arg1, D_8037DC60.rotation); } -void ncFirstPersonCamera_reset(void){ +void ncba1p_reset(void){ ml_vec3f_clear(D_8037DC60.position); ml_vec3f_clear(D_8037DC60.rotation); ml_vec3f_clear(D_8037DC60.zoomed_in_position); @@ -80,23 +81,23 @@ void ncFirstPersonCamera_reset(void){ D_8037DC60.state = 0; } -void ncFirstPersonCamera_getPositionAndRotation(f32 position[3], f32 rotation[3]) { +void ncba1p_getPositionAndRotation(f32 position[3], f32 rotation[3]) { switch (D_8037DC60.state) { case FIRSTPERSON_STATE_1_ENTER: - __ncFirstPersonCamera_getPositionAndRotation_entering(position, rotation); + __ncba1p_getPositionAndRotation_entering(position, rotation); break; case FIRSTPERSON_STATE_2_IDLE: - __ncFirstPersonCamera_getPositionAndRotation_idle(position, rotation); + __ncba1p_getPositionAndRotation_idle(position, rotation); break; case FIRSTPERSON_STATE_3_EXIT: - __ncFirstPersonCamera_getPositionAndRotation_exiting(position, rotation); + __ncba1p_getPositionAndRotation_exiting(position, rotation); /* fallthrough */ case FIRSTPERSON_STATE_4_DONE: break; } } -void ncFirstPersonCamera_setState(enum nc_first_person_state next_state) { +void ncba1p_setState(enum nc_first_person_state next_state) { if (next_state == FIRSTPERSON_STATE_1_ENTER) { if (D_8037DC60.state == FIRSTPERSON_STATE_3_EXIT) { ml_vec3f_copy(D_8037DC60.zoomed_out_position, D_8037DC60.position); @@ -115,20 +116,20 @@ void ncFirstPersonCamera_setState(enum nc_first_person_state next_state) { D_8037DC60.state = next_state; } -void ncFirstPersonCamera_setZoomedOutPosition(f32 src[3]){ +void ncba1p_setZoomedOutPosition(f32 src[3]){ ml_vec3f_copy(D_8037DC60.zoomed_in_position, src); } -void ncFirstPersonCamera_setZoomedOutRotation(f32 src[3]){ +void ncba1p_setZoomedOutRotation(f32 src[3]){ D_8037DC60.zoomed_in_rotation[0] = mlNormalizeAngle(src[0]); D_8037DC60.zoomed_in_rotation[1] = mlNormalizeAngle(src[1]); D_8037DC60.zoomed_in_rotation[2] = mlNormalizeAngle(src[2]); } -void ncFirstPersonCamera_getZoomedInRotation(f32 dst[3]){ +void ncba1p_getZoomedInRotation(f32 dst[3]){ ml_vec3f_copy(dst, D_8037DC60.zoomed_in_rotation); } -s32 ncFirstPersonCamera_getState(void){ +s32 ncba1p_getState(void){ return D_8037DC60.state; } diff --git a/src/core2/camera/camera_debug_freecam.c b/src/core2/nc/camera_debug_freecam.c similarity index 98% rename from src/core2/camera/camera_debug_freecam.c rename to src/core2/nc/camera_debug_freecam.c index bf8b1e8a1..cc4a1fa1b 100644 --- a/src/core2/camera/camera_debug_freecam.c +++ b/src/core2/nc/camera_debug_freecam.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core1/stub_2FA0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/camera/camera_ease.c b/src/core2/nc/camera_ease.c similarity index 96% rename from src/core2/camera/camera_ease.c rename to src/core2/nc/camera_ease.c index c76d52edd..b343b3edd 100644 --- a/src/core2/camera/camera_ease.c +++ b/src/core2/nc/camera_ease.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_3B2C0.c #include #include "functions.h" #include "variables.h" @@ -29,7 +30,7 @@ void func_802C22B4(void){ s_state = 0; } - +// something for dynamic camera void func_802C22C0(f32 target_position[3], f32 target_rotation[3]){ f32 tmpf_1[3]; f32 tmpf_2[3]; diff --git a/src/core2/camera/camera_focus.c b/src/core2/nc/camera_focus.c similarity index 96% rename from src/core2/camera/camera_focus.c rename to src/core2/nc/camera_focus.c index 519e2266f..70624ae3f 100644 --- a/src/core2/camera/camera_focus.c +++ b/src/core2/nc/camera_focus.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_33C30.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/camera/camera_focustarget.c b/src/core2/nc/camera_focustarget.c similarity index 97% rename from src/core2/camera/camera_focustarget.c rename to src/core2/nc/camera_focustarget.c index 45911191c..c708c734e 100644 --- a/src/core2/camera/camera_focustarget.c +++ b/src/core2/nc/camera_focustarget.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_F8EAF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/camera_fog.c b/src/core2/nc/camera_fog.c similarity index 98% rename from src/core2/camera/camera_fog.c rename to src/core2/nc/camera_fog.c index fa2bc7f4e..b20ee5d5f 100644 --- a/src/core2/camera/camera_fog.c +++ b/src/core2/nc/camera_fog.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_37E50.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/camera/camera_motor1.c b/src/core2/nc/camera_motor1.c similarity index 94% rename from src/core2/camera/camera_motor1.c rename to src/core2/nc/camera_motor1.c index cb37c274d..ea43f777a 100644 --- a/src/core2/camera/camera_motor1.c +++ b/src/core2/nc/camera_motor1.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_33F90.c #include #include "functions.h" #include "variables.h" @@ -73,6 +74,7 @@ s16 D_8036502C[] = { 0, -1, 0, 4, 0x12, 5, s16 D_8036503C[] = { 0, -1, 0, 0, -4, 0x1E}; s16 D_80365048[] = { 0, -1, 0, 2, 0x23, 1, 0x46, -6, -1, 0x46}; s16 D_8036505C[] = { 0, -1, 0, 1, 0x1A, -6, -1, 0x1A}; +#if VERSION == VERSION_USA_1_0 s16 D_8036506C[] = { 0, -1, 0, 0xC, 0xD, 0xD, 0x20, 0x3, 0x34, -6, -1, 0x39}; s16 D_80365084[] = { 0, -1, 0, 0, 0x13, 1, 0x30, 0xD, -4, 0x53}; s16 D_80365098[] = { 0, -1, 0, 6, 0xD, 7, 0x20, 0x14, -4, 0x39}; @@ -82,6 +84,17 @@ s16 D_803650D4[] = { 0, -1, 0, 3, 0xD, 4, 0x20, 0x13, s16 D_803650E8[] = { 0, -1, 0, 0, 0xD, 1, 0x20, 0x4, -4, 0x39}; s16 D_803650FC[] = { 0, -1, 0, 0, 0xD, 1, 0x20, 0xD, -4, 0x41}; s16 D_80365110[] = { 0, -1, 0, 3, 0xD, 4, 0x20, 0x20, -4, 0x39}; +#elif VERSION == VERSION_PAL +s16 D_8036506C[] = { 0, -1, 0, 0xC, 0xD, 0xD, 0x28, 0x3, 0x46, -6, -1, 0x4B}; +s16 D_80365084[] = { 0, -1, 0, 0, 0x13, 1, 0x38, 0xD, -4, 0x65}; +s16 D_80365098[] = { 0, -1, 0, 6, 0xD, 7, 0x28, 0x14, -4, 0x49}; +s16 D_803650AC[] = { 0, -1, 0, 2, 0xD, 3, 0x28, 0xB, -4, 0x49}; +s16 D_803650C0[] = { 0, -1, 0, 0, 0xD, 1, 0x26, 0xC, -4, 0x48}; +s16 D_803650D4[] = { 0, -1, 0, 3, 0xD, 4, 0x26, 0x13, -4, 0x48}; +s16 D_803650E8[] = { 0, -1, 0, 0, 0xD, 1, 0x26, 0x4, -4, 0x48}; +s16 D_803650FC[] = { 0, -1, 0, 0, 0xD, 1, 0x26, 0xD, -4, 0x50}; +s16 D_80365110[] = { 0, -1, 0, 3, 0xD, 4, 0x26, 0x20, -4, 0x48}; +#endif s16 D_80365124[] = { 0, -1, 0, 2, 0xF, 3, -4, 0x28}; s16 D_80365134[] = { 0, -1, 0, 5, 0xC, 6, -4, 0x21}; s16 D_80365144[] = { 0, -1, 0, 0, 0xC, 1, -4, 0x21}; diff --git a/src/core2/camera/camera_motor2.c b/src/core2/nc/camera_motor2.c similarity index 99% rename from src/core2/camera/camera_motor2.c rename to src/core2/nc/camera_motor2.c index 0675f3b4d..0be2a6be9 100644 --- a/src/core2/camera/camera_motor2.c +++ b/src/core2/nc/camera_motor2.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_34310.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/camera_nodemanager.c b/src/core2/nc/camera_nodemanager.c similarity index 94% rename from src/core2/camera/camera_nodemanager.c rename to src/core2/nc/camera_nodemanager.c index 20063fcc1..de7e2b158 100644 --- a/src/core2/camera/camera_nodemanager.c +++ b/src/core2/nc/camera_nodemanager.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_34790.c #include #include "core1/core1.h" #include "functions.h" @@ -64,7 +65,7 @@ bool func_802BB720(s32 arg0, f32 arg1[3], f32 arg2[3], s32 *arg3) { if (temp_v0 != NULL) { nodeprop_getPosition(temp_v0, arg1); *arg3 = nodeprop_getScale(temp_v0); - temp_f6 = (f32) nodeprop_getYaw(temp_v0) - 180.0f; + temp_f6 = (f32) nodeProp_getYaw(temp_v0) - 180.0f; arg2[0] = 0.0f;\ arg2[1] = mlNormalizeAngle(temp_f6);\ arg2[2] = 0.0f; @@ -124,7 +125,7 @@ void func_802BBA84(void) { mapModel_getBounds((s32 *)min, (s32 *)max); viewport_getPosition_vec3f(vp_position); viewport_getRotation_vec3f(vp_rotation); - viewport_getLookbk_vector(sp48); + viewport_getLookVector(sp48); D_8037D8CC = (f32) coords_func_8033EAF8((s32*)min, (s32*)max, vp_position, sp48); D_8037D8CC += 100.0f; if (D_8037D8CC < 1000.0f) { @@ -186,9 +187,9 @@ void func_802BBD0C(Gfx **gdl, Mtx **mptr, Vtx **vptr){ func_802BEE2C(gdl, mptr, vptr); } -void func_802BBD2C(f32 *arg0, f32 *arg1){ - *arg0 = D_8037D8C8; - *arg1 = D_8037D8CC; +void core2_34790_getClipDistances(f32 *near, f32 *far) { + *near = D_8037D8C8; + *far = D_8037D8CC; } f32 func_802BBD48(void) { @@ -306,6 +307,9 @@ void ncCamera_update(void){ viewport_getPosition_vec3f(sp2C); viewport_getRotation_vec3f(sp20); func_802BB4D8(sp2C, sp20); + if (EventSystem_Should(VB_CAMERA_APPLY_SHAKE, true)) { + viewport_setPosition_vec3f(sp2C); + } viewport_update(); func_802BEFB0(); func_802BBA84(); @@ -361,7 +365,7 @@ void func_802BC2CC(s32 arg0) { viewport_setPosition_vec3f(D_8037D908); viewport_setRotation_vec3f(D_8037D918); viewport_update(); - __spawnQueue_add_2((void (*)(void))func_802BC2A0, (uintptr_t)sp24, (uintptr_t)sp20); + __spawnQueue_add_2((GenFunction_2)func_802BC2A0, (uintptr_t)sp24, (uintptr_t)sp20); if (ncCameraType == CAMERA_TYPE_2_DYNAMIC) { func_802BE720(); if (sp1C != 0x63) { @@ -376,7 +380,7 @@ bool func_802BC428(void){ } void func_802BC434(f32 arg0[3], f32 arg1[3], f32 arg2[3]) { - func_8025727C(arg1[0], arg1[1], arg1[2], arg2[0], arg2[1], arg2[2], &arg0[0], &arg0[1]); + ml_horizontal_and_vertical_angles(arg1[0], arg1[1], arg1[2], arg2[0], arg2[1], arg2[2], &arg0[0], &arg0[1]); arg0[0] = mlNormalizeAngle(-arg0[0]); arg0[2] = 0.0f; } diff --git a/src/core2/camera/camera_position.c b/src/core2/nc/camera_position.c similarity index 98% rename from src/core2/camera/camera_position.c rename to src/core2/nc/camera_position.c index 1c51a3142..e35048052 100644 --- a/src/core2/camera/camera_position.c +++ b/src/core2/nc/camera_position.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_379B0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/camera_set.c b/src/core2/nc/camera_set.c similarity index 98% rename from src/core2/camera/camera_set.c rename to src/core2/nc/camera_set.c index 93253ea10..123270faf 100644 --- a/src/core2/camera/camera_set.c +++ b/src/core2/nc/camera_set.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CB610.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/cameranode_type1.c b/src/core2/nc/cameranode_type1.c similarity index 99% rename from src/core2/camera/cameranode_type1.c rename to src/core2/nc/cameranode_type1.c index b80596118..5b70fcaa1 100644 --- a/src/core2/camera/cameranode_type1.c +++ b/src/core2/nc/cameranode_type1.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_336F0.c #include #include diff --git a/src/core2/camera/cameranode_type2.c b/src/core2/nc/cameranode_type2.c similarity index 98% rename from src/core2/camera/cameranode_type2.c rename to src/core2/nc/cameranode_type2.c index 06905a8ba..43df38fbf 100644 --- a/src/core2/camera/cameranode_type2.c +++ b/src/core2/nc/cameranode_type2.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_33AB0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/cameranode_type3.c b/src/core2/nc/cameranode_type3.c similarity index 99% rename from src/core2/camera/cameranode_type3.c rename to src/core2/nc/cameranode_type3.c index fcdd6a99f..9c2cf231b 100644 --- a/src/core2/camera/cameranode_type3.c +++ b/src/core2/nc/cameranode_type3.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_33310.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/cameranode_type4.c b/src/core2/nc/cameranode_type4.c similarity index 96% rename from src/core2/camera/cameranode_type4.c rename to src/core2/nc/cameranode_type4.c index 0fb4df6c7..36763a654 100644 --- a/src/core2/camera/cameranode_type4.c +++ b/src/core2/nc/cameranode_type4.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_33250.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/cameranodelist.c b/src/core2/nc/cameranodelist.c similarity index 99% rename from src/core2/camera/cameranodelist.c rename to src/core2/nc/cameranodelist.c index ce809a9e8..0e7d7d472 100644 --- a/src/core2/camera/cameranodelist.c +++ b/src/core2/nc/cameranodelist.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/cameranodelist.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCamD.c b/src/core2/nc/die.c similarity index 73% rename from src/core2/camera/dynamicCamD.c rename to src/core2/nc/die.c index 61f3413c3..c0d636a87 100644 --- a/src/core2/camera/dynamicCamD.c +++ b/src/core2/nc/die.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/ba/die.c #include #include "functions.h" #include "variables.h" @@ -6,18 +7,18 @@ f32 D_80365D90 = 30.0f; /* .code */ -void ncDynamicCamD_init(void){ +void ncbadie_init(void){ func_802BE244(4.0f, 16.0f); func_802BE230(1.4f, 14.0f); } -void ncDynamicCamD_end(void){} +void ncbadie_end(void){} -void ncDynamicCamD_func_802BF2C0(f32 arg0){ +void ncbadie_func_802BF2C0(f32 arg0){ D_80365D90 = arg0; } -void ncDynamicCamD_update(void) { +void ncbadie_update(void) { f32 sp54[3]; f32 sp48[3]; f32 sp3C[3]; @@ -36,7 +37,7 @@ void ncDynamicCamD_update(void) { ncDynamicCamera_getPosition(sp54); player_getPosition(sp3C); sp3C[1] += D_80365D90; - func_8025727C(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); + ml_horizontal_and_vertical_angles(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); sp48[0] = mlNormalizeAngle(-sp48[0]); func_802BD904(sp48); } diff --git a/src/core2/nc/dynamicCam1.c b/src/core2/nc/dynamicCam1.c new file mode 100644 index 000000000..eab3d2703 --- /dev/null +++ b/src/core2/nc/dynamicCam1.c @@ -0,0 +1,50 @@ +// BanjoDecomp: core2/nc/dynamicCam1.c +#include +#include "functions.h" +#include "variables.h" + +extern f32 func_802BD51C(void); +extern f32 player_getYaw(void); +extern void func_802BD870(f32, f32, f32, f32); + +void ncDynamicCam1_init(void){ + func_802BD870(12.0f, 10.0f, 120.0f, 120.0f); +} + +void ncDynamicCam1_end(void){} + +void ncDynamicCam1_update(void) { + f32 sp8C[3]; + f32 new_camera_position[3]; + f32 current_camera_position[3]; + f32 dst[3]; + f32 angles[3]; + f32 sp50[3]; + f32 position_z; + f32 phi; + f32 time_delta; + f32 sp40; + f32 sp3C; + + ncDynamicCamera_getPosition(current_camera_position); + func_802BD4C0(sp8C); + sp3C = func_802BD8D4(); + time_delta = time_getDelta(); + ml_vec3f_diff_copy(sp50, current_camera_position, sp8C); + position_z = sqrtf((sp50[0] * sp50[0]) + (sp50[2] * sp50[2])); + position_z += ml_clamp_abs_f((sp3C - position_z) * time_delta * 2, time_delta * 120.0f); + func_8025801C(sp50, &phi); + sp40 = ml_clamp_abs_f(mlDiffDegF(mlNormalizeAngle(180.0f + player_getYaw()), phi) * (time_delta * 1), time_delta * 50.0f); + phi = mlNormalizeAngle(phi + sp40); + func_80256E24(dst, 0.0f, phi, 0.0f, 0.0f, position_z); + ml_vec3f_add(new_camera_position, sp8C, dst); + new_camera_position[1] = current_camera_position[1] + ((func_802BD51C() - current_camera_position[1]) * time_delta * 2); + ncDynamicCamera_setPosition(new_camera_position); + ml_horizontal_and_vertical_angles( + sp8C[0], sp8C[1], sp8C[2], + new_camera_position[0], new_camera_position[1], new_camera_position[2], + &angles[0], &angles[1]); + angles[0] = -angles[0]; + angles[2] = 0.0f; + func_802BD720(angles); +} diff --git a/src/core2/camera/dynamicCam10.c b/src/core2/nc/dynamicCam10.c similarity index 96% rename from src/core2/camera/dynamicCam10.c rename to src/core2/nc/dynamicCam10.c index 8382589b0..745b7bb67 100644 --- a/src/core2/camera/dynamicCam10.c +++ b/src/core2/nc/dynamicCam10.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCam11.c b/src/core2/nc/dynamicCam11.c similarity index 98% rename from src/core2/camera/dynamicCam11.c rename to src/core2/nc/dynamicCam11.c index 1861a0905..755caf4cb 100644 --- a/src/core2/camera/dynamicCam11.c +++ b/src/core2/nc/dynamicCam11.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam11.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCam12.c b/src/core2/nc/dynamicCam12.c similarity index 99% rename from src/core2/camera/dynamicCam12.c rename to src/core2/nc/dynamicCam12.c index 4d788f602..fddad612a 100644 --- a/src/core2/camera/dynamicCam12.c +++ b/src/core2/nc/dynamicCam12.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam12.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCam13.c b/src/core2/nc/dynamicCam13.c similarity index 98% rename from src/core2/camera/dynamicCam13.c rename to src/core2/nc/dynamicCam13.c index 0798d448b..854c54545 100644 --- a/src/core2/camera/dynamicCam13.c +++ b/src/core2/nc/dynamicCam13.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam13.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCam3.c b/src/core2/nc/dynamicCam3.c similarity index 81% rename from src/core2/camera/dynamicCam3.c rename to src/core2/nc/dynamicCam3.c index 6d0cbc1a4..6c81bdf20 100644 --- a/src/core2/camera/dynamicCam3.c +++ b/src/core2/nc/dynamicCam3.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam3.c #include #include "functions.h" #include "variables.h" @@ -38,11 +39,11 @@ void ncDynamicCam3_update(void) { sp30 = time_getDelta(); if (sp30); ml_vec3f_diff_copy(sp40, sp64, sp7C); - sp3C = gu_sqrtf(sp40[0]*sp40[0] + sp40[2]*sp40[2]); - sp3C += func_80259198(sp30*(sp34 - sp3C)*2 , sp30 * 800.0f); - func_8025727C(sp7C[0], sp7C[1], sp7C[2], sp64[0], sp64[1], sp64[2], &sp4C[0], &sp4C[1]); + sp3C = sqrtf(sp40[0]*sp40[0] + sp40[2]*sp40[2]); + sp3C += ml_clamp_abs_f(sp30*(sp34 - sp3C)*2 , sp30 * 800.0f); + ml_horizontal_and_vertical_angles(sp7C[0], sp7C[1], sp7C[2], sp64[0], sp64[1], sp64[2], &sp4C[0], &sp4C[1]); sp40[1] = sp30 * 0.77 * mlDiffDegF(mlNormalizeAngle(player_getYaw() + 180.0f), sp4C[1]); - sp40[1] = func_80259198(sp40[1], sp30 * 300.0f); + sp40[1] = ml_clamp_abs_f(sp40[1], sp30 * 300.0f); sp4C[1] = mlNormalizeAngle(sp4C[1] + sp40[1]); func_80256E24(sp58, 0.0f, sp4C[1], 0.0f, 0.0f, sp3C); sp70[0] = sp7C[0] + sp58[0]; diff --git a/src/core2/camera/dynamicCam5.c b/src/core2/nc/dynamicCam5.c similarity index 87% rename from src/core2/camera/dynamicCam5.c rename to src/core2/nc/dynamicCam5.c index 8e9875cc9..668b3f58d 100644 --- a/src/core2/camera/dynamicCam5.c +++ b/src/core2/nc/dynamicCam5.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam5.c #include #include "functions.h" #include "variables.h" @@ -36,7 +37,7 @@ void ncDynamicCam5_update(void) { ml_vec3f_diff_copy(sp68, sp74, sp50); func_802BE190(sp68); ncDynamicCamera_getPosition(sp68); - func_8025727C(sp74[0], sp74[1], sp74[2], sp68[0], sp68[1], sp68[2], &sp38[0], &sp38[1]); + ml_horizontal_and_vertical_angles(sp74[0], sp74[1], sp74[2], sp68[0], sp68[1], sp68[2], &sp38[0], &sp38[1]); sp38[0] = -sp38[0]; sp38[2] = 0.0f; func_802BD904(sp38); diff --git a/src/core2/camera/dynamicCam8.c b/src/core2/nc/dynamicCam8.c similarity index 97% rename from src/core2/camera/dynamicCam8.c rename to src/core2/nc/dynamicCam8.c index b39d0d3ec..81df36cbc 100644 --- a/src/core2/camera/dynamicCam8.c +++ b/src/core2/nc/dynamicCam8.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam8.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCam9.c b/src/core2/nc/dynamicCam9.c similarity index 86% rename from src/core2/camera/dynamicCam9.c rename to src/core2/nc/dynamicCam9.c index 99de86932..947415fa3 100644 --- a/src/core2/camera/dynamicCam9.c +++ b/src/core2/nc/dynamicCam9.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCam9.c #include #include "functions.h" #include "variables.h" @@ -36,7 +37,7 @@ void ncDynamicCam9_func_802C0A60(f32 arg0[3]) { f32 sp30[3]; func_802BD4C0(sp54); - func_8025727C(sp54[0], sp54[1], sp54[2], D_8037DBB0[0], D_8037DBB0[1], D_8037DBB0[2], &sp30[0], &sp30[1]); + ml_horizontal_and_vertical_angles(sp54[0], sp54[1], sp54[2], D_8037DBB0[0], D_8037DBB0[1], D_8037DBB0[2], &sp30[0], &sp30[1]); sp30[1] = mlNormalizeAngle(sp30[1] - 60.0f); func_80256E24(sp48, 0.0f, sp30[1], 0.0f, 0.0f, D_8037DBC0); ml_vec3f_add(arg0, D_8037DBB0, sp48); @@ -58,9 +59,9 @@ void ncDynamicCam9_func_802C0B70(f32 arg0[3], f32 arg1[3]) { sp3C[0] *= dt * 1.5; sp3C[1] *= dt * 1.0; sp3C[2] *= dt * 1.5; - sp3C[0] = func_80259198(sp3C[0], dt * 1000.0); - sp3C[1] = func_80259198(sp3C[1], dt * 1000.0); - sp3C[2] = func_80259198(sp3C[2], dt * 1000.0); + sp3C[0] = ml_clamp_abs_f(sp3C[0], dt * 1000.0); + sp3C[1] = ml_clamp_abs_f(sp3C[1], dt * 1000.0); + sp3C[2] = ml_clamp_abs_f(sp3C[2], dt * 1000.0); ml_vec3f_add(arg0, sp30, sp3C); ncDynamicCamera_setPosition(arg0); } @@ -78,7 +79,7 @@ void ncDynamicCam9_func_802C0C5C(f32 arg0[3], f32 arg1[3]) { ml_vec3f_scale(sp3C, ml_map_f(sp38, 0.4f, 0.75f, 0.5f, 1.0f)); ml_vec3f_add(sp54, D_8037DBB0, sp3C); sp54[1] = sp48[1] + (sp54[1] - sp48[1]) * 0.4; - func_8025727C(sp54[0], sp54[1], sp54[2], arg1[0], arg1[1], arg1[2], &arg0[0], &arg0[1]); + ml_horizontal_and_vertical_angles(sp54[0], sp54[1], sp54[2], arg1[0], arg1[1], arg1[2], &arg0[0], &arg0[1]); arg0[0] = mlNormalizeAngle(-arg0[0]); arg0[2] = 0.0f; } diff --git a/src/core2/camera/dynamicCamA.c b/src/core2/nc/dynamicCamA.c similarity index 98% rename from src/core2/camera/dynamicCamA.c rename to src/core2/nc/dynamicCamA.c index 08006c4c9..c4cc76801 100644 --- a/src/core2/camera/dynamicCamA.c +++ b/src/core2/nc/dynamicCamA.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCamA.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCamB.c b/src/core2/nc/dynamicCamB.c similarity index 98% rename from src/core2/camera/dynamicCamB.c rename to src/core2/nc/dynamicCamB.c index 83bc5f4bc..e7a70b6a6 100644 --- a/src/core2/camera/dynamicCamB.c +++ b/src/core2/nc/dynamicCamB.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCamB.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCamC.c b/src/core2/nc/dynamicCamC.c similarity index 91% rename from src/core2/camera/dynamicCamC.c rename to src/core2/nc/dynamicCamC.c index f31d482b1..338dae9ac 100644 --- a/src/core2/camera/dynamicCamC.c +++ b/src/core2/nc/dynamicCamC.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCamC.c #include #include "functions.h" #include "variables.h" @@ -69,7 +70,7 @@ void ncDynamicCamC_update(void) { ncDynamicCamera_getPosition(sp54); player_getPosition(sp3C); sp3C[1] += 100.0f; - func_8025727C(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); + ml_horizontal_and_vertical_angles(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); sp48[0] = mlNormalizeAngle(-sp48[0]); func_802BD904(sp48); } diff --git a/src/core2/camera/dynamicCamF.c b/src/core2/nc/dynamicCamF.c similarity index 95% rename from src/core2/camera/dynamicCamF.c rename to src/core2/nc/dynamicCamF.c index 4656ce03c..0ec2ec401 100644 --- a/src/core2/camera/dynamicCamF.c +++ b/src/core2/nc/dynamicCamF.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCamF.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/camera/dynamicCamera.c b/src/core2/nc/dynamicCamera.c similarity index 85% rename from src/core2/camera/dynamicCamera.c rename to src/core2/nc/dynamicCamera.c index 76e27e4f5..e35337ede 100644 --- a/src/core2/camera/dynamicCamera.c +++ b/src/core2/nc/dynamicCamera.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/dynamicCamera.c #include #include "core1/core1.h" #include "functions.h" @@ -31,10 +32,33 @@ void func_802BD8EC(f32 arg0); f32 D_80365CD0[] = {0.0f}; f32 D_80365CD4[] = {0.0f, -25.0f, 25.0f, -50.0f, 50.0f, -80.0f, 80.0f, -120.0f, 120.0f, -140.0f, 140.0f}; f32 D_80365D00[] = {0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 120.0f, 140.0f, 160.0f, 180.0f, 200.0f, 220.0f, 240.0f, 260.0f, 280.0f, 300.0f, 320.0f, 340.0f}; + Struct_core2_356B0_0 D_80365D48 = {D_80365CD0, 1}; Struct_core2_356B0_0 D_80365D50 = {D_80365CD4, 11}; Struct_core2_356B0_0 D_80365D58 = {D_80365D00, 18}; +enum ncdynamiccamera_state_e { + NCDYNAMICCAMERA_STATE_0_NOT_INIT, + NCDYNAMICCAMERA_STATE_1_UNK, + NCDYNAMICCAMERA_STATE_2_UNK, + NCDYNAMICCAMERA_STATE_3_UNK, + NCDYNAMICCAMERA_STATE_4_UNK, + NCDYNAMICCAMERA_STATE_5_UNK, + NCDYNAMICCAMERA_STATE_6_UNK, + NCDYNAMICCAMERA_STATE_7_UNK, + NCDYNAMICCAMERA_STATE_8_UNK, + NCDYNAMICCAMERA_STATE_9_UNK, + NCDYNAMICCAMERA_STATE_A_UNK, + NCDYNAMICCAMERA_STATE_B_UNK, + NCDYNAMICCAMERA_STATE_C_UNK, + NCDYNAMICCAMERA_STATE_D_UNK, + NCDYNAMICCAMERA_STATE_E_UNK, + NCDYNAMICCAMERA_STATE_F_UNK, + NCDYNAMICCAMERA_STATE_10_UNK, + NCDYNAMICCAMERA_STATE_11_UNK, + NCDYNAMICCAMERA_STATE_12_UNK, + NCDYNAMICCAMERA_STATE_13_UNK +}; /* .bss */ s32 D_8037D940; @@ -207,7 +231,7 @@ void func_802BCBD4(void) { func_802BD870(10.0f, 10.0f, 120.0f, 120.0f); func_802BE230(1.4f, 14.0f); func_802BD840(); - ncFirstPersonCamera_reset(); + ncba1p_reset(); func_802C0120(); func_802C2258(); func_802C0F4C(); @@ -275,8 +299,9 @@ void func_802BCE94(void){ } void ncDynamicCamera_update(void){ - f32 sp24[3]; - f32 sp18[3]; + f32 position[3]; + f32 rotation[3]; + if(!cameraUpdateEnabled) return; @@ -287,73 +312,73 @@ void ncDynamicCamera_update(void){ func_802BCA58(); switch(dynamicCameraState){ - case 1:// L802BCF3C + case NCDYNAMICCAMERA_STATE_1_UNK:// L802BCF3C ncDynamicCam1_update(); func_802BCE94(); break; - case 3:// L802BCF54 + case NCDYNAMICCAMERA_STATE_3_UNK:// L802BCF54 ncDynamicCam3_update(); break; - case 4:// L802BCF64 - ncDynamicCam4_update(); + case NCDYNAMICCAMERA_STATE_4_UNK:// L802BCF64 + ncbafly_update(); func_802BCE94(); break; - case 5:// L802BCF7C + case NCDYNAMICCAMERA_STATE_5_UNK:// L802BCF7C ncDynamicCam5_update(); func_802BCE94(); break; - case 6:// L802BCF94 + case NCDYNAMICCAMERA_STATE_6_UNK:// L802BCF94 func_802BCE94(); break; - case 8:// L802BCFA4 + case NCDYNAMICCAMERA_STATE_8_UNK:// L802BCFA4 ncDynamicCam8_update(); break; - case 9:// L802BCFB4 + case NCDYNAMICCAMERA_STATE_9_UNK:// L802BCFB4 ncDynamicCam9_update(); func_802BCE94(); break; - case 0xA:// L802BCFCC + case NCDYNAMICCAMERA_STATE_A_UNK:// L802BCFCC ncDynamicCamA_update(); break; - case 0xB:// L802BCFDC + case NCDYNAMICCAMERA_STATE_B_UNK:// L802BCFDC ncDynamicCamB_update(); break; - case 0xC:// L802BCFEC + case NCDYNAMICCAMERA_STATE_C_UNK:// L802BCFEC ncDynamicCamC_update(); func_802BCE94(); break; - case 0xD:// L802BD004 - ncDynamicCamD_update(); + case NCDYNAMICCAMERA_STATE_D_UNK:// L802BD004 + ncbadie_update(); func_802BCE94(); break; - case 0xF:// L802BD01C + case NCDYNAMICCAMERA_STATE_F_UNK:// L802BD01C ncDynamicCamF_update(); break; - case 0x10:// L802BD02C + case NCDYNAMICCAMERA_STATE_10_UNK:// L802BD02C ncDynamicCam10_update(); break; - case 0x11:// L802BD03C + case NCDYNAMICCAMERA_STATE_11_UNK:// L802BD03C ncDynamicCam11_update(); break; - case 0x12:// L802BD04C + case NCDYNAMICCAMERA_STATE_12_UNK:// L802BD04C ncDynamicCam12_update(); break; - case 0x13:// L802BD05C + case NCDYNAMICCAMERA_STATE_13_UNK:// L802BD05C ncDynamicCam13_update(); break; @@ -365,14 +390,14 @@ void ncDynamicCamera_update(void){ port_modernCamera_update(); break; }//// L802BD064 - ml_vec3f_copy(sp24, cameraPosition); - ml_vec3f_copy(sp18, cameraRotation); - func_802C22C0(sp24, sp18); + ml_vec3f_copy(position, cameraPosition); + ml_vec3f_copy(rotation, cameraRotation); + func_802C22C0(position, rotation); if(dynamicCameraInFirstPerson){ - ncFirstPersonCamera_getPositionAndRotation(sp24, sp18); + ncba1p_getPositionAndRotation(position, rotation); } - viewport_setPosition_vec3f(sp24); - viewport_setRotation_vec3f(sp18); + viewport_setPosition_vec3f(position); + viewport_setRotation_vec3f(rotation); } int ncDynamicCamera_getState(void){ @@ -384,126 +409,126 @@ void ncDynamicCamera_setState(s32 state){ return; switch(dynamicCameraState){ - case 0x1://L802BD114 + case NCDYNAMICCAMERA_STATE_1_UNK://L802BD114 ncDynamicCam1_end(); break; - case 0x3://L802BD124 + case NCDYNAMICCAMERA_STATE_3_UNK://L802BD124 ncDynamicCam3_end(); break; - case 0x4://L802BD134 - ncDynamicCam4_end(); + case NCDYNAMICCAMERA_STATE_4_UNK://L802BD134 + ncbafly_end(); break; - case 0x5://L802BD144 + case NCDYNAMICCAMERA_STATE_5_UNK://L802BD144 ncDynamicCam5_end(); break; - case 0x8://L802BD154 + case NCDYNAMICCAMERA_STATE_8_UNK://L802BD154 ncDynamicCam8_end(); break; - case 0x9://L802BD164 + case NCDYNAMICCAMERA_STATE_9_UNK://L802BD164 ncDynamicCam9_end(); break; - case 0xa://L802BD174 + case NCDYNAMICCAMERA_STATE_A_UNK://L802BD174 ncDynamicCamA_end(); break; - case 0xb://L802BD184 + case NCDYNAMICCAMERA_STATE_B_UNK://L802BD184 ncDynamicCamB_end(); break; - case 0xc://L802BD194 + case NCDYNAMICCAMERA_STATE_C_UNK://L802BD194 ncDynamicCamC_end(); break; - case 0xd://L802BD1A4 - ncDynamicCamD_end(); + case NCDYNAMICCAMERA_STATE_D_UNK://L802BD1A4 + ncbadie_end(); break; - case 0xf://L802BD1B4 + case NCDYNAMICCAMERA_STATE_F_UNK://L802BD1B4 ncDynamicCamF_end(); break; - case 0x10://L802BD1C4 + case NCDYNAMICCAMERA_STATE_10_UNK://L802BD1C4 ncDynamicCam10_end(); break; - case 0x11://L802BD1D4 + case NCDYNAMICCAMERA_STATE_11_UNK://L802BD1D4 ncDynamicCam11_end(); break; - case 0x12://L802BD1E4 + case NCDYNAMICCAMERA_STATE_12_UNK://L802BD1E4 ncDynamicCam12_end(); break; - case 0x13://L802BD1F4 + case NCDYNAMICCAMERA_STATE_13_UNK://L802BD1F4 ncDynamicCam13_end(); break; }//L802BD1FC switch (state) { - case 0x1: //L802BD224 + case NCDYNAMICCAMERA_STATE_1_UNK: //L802BD224 ncDynamicCam1_init(); break; - case 0x3: //L802BD234 + case NCDYNAMICCAMERA_STATE_3_UNK: //L802BD234 ncDynamicCam3_init(); break; - case 0x4: //L802BD244 - ncDynamicCam4_init(); + case NCDYNAMICCAMERA_STATE_4_UNK: //L802BD244 + ncbafly_init(); break; - case 0x5: //L802BD254 + case NCDYNAMICCAMERA_STATE_5_UNK: //L802BD254 ncDynamicCam5_init(); break; - case 0x8: //L802BD264 + case NCDYNAMICCAMERA_STATE_8_UNK: //L802BD264 ncDynamicCam8_init(); break; - case 0x9: //L802BD274 + case NCDYNAMICCAMERA_STATE_9_UNK: //L802BD274 ncDynamicCam9_init(); break; - case 0xa: //L802BD284 + case NCDYNAMICCAMERA_STATE_A_UNK: //L802BD284 ncDynamicCamA_init(); break; - case 0xb: //L802BD294 + case NCDYNAMICCAMERA_STATE_B_UNK: //L802BD294 ncDynamicCamB_init(); break; - case 0xc: //L802BD2A4 + case NCDYNAMICCAMERA_STATE_C_UNK: //L802BD2A4 ncDynamicCamC_init(); break; - case 0xd: //L802BD2B4 - ncDynamicCamD_init(); + case NCDYNAMICCAMERA_STATE_D_UNK: //L802BD2B4 + ncbadie_init(); break; - case 0xf: //L802BD2C4 + case NCDYNAMICCAMERA_STATE_F_UNK: //L802BD2C4 ncDynamicCamF_init(); break; - case 0x10: //L802BD2D4 + case NCDYNAMICCAMERA_STATE_10_UNK: //L802BD2D4 ncDynamicCam10_init(); break; - case 0x11: //L802BD2E4 + case NCDYNAMICCAMERA_STATE_11_UNK: //L802BD2E4 ncDynamicCam11_init(); break; - case 0x12: //L802BD2F4 + case NCDYNAMICCAMERA_STATE_12_UNK: //L802BD2F4 dynamicCam12_init(); break; - case 0x13: //L802BD304 + case NCDYNAMICCAMERA_STATE_13_UNK: //L802BD304 ncDynamicCam13_init(); break; } @@ -586,8 +611,8 @@ void func_802BD610(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3, f32 arg4, f32 a sp24[1] = mlDiffDegF(arg0[1], arg1[1]); sp24[0] *= 0.003333 * D_8037D984; sp24[1] *= 0.003333 * D_8037D988; - sp24[0] = func_80259198(sp24[0], D_8037D98C * 0.003333); - sp24[1] = func_80259198(sp24[1], D_8037D990 * 0.003333); + sp24[0] = ml_clamp_abs_f(sp24[0], D_8037D98C * 0.003333); + sp24[1] = ml_clamp_abs_f(sp24[1], D_8037D990 * 0.003333); sp24[2] = 0.0f; arg1[0] = mlNormalizeAngle(arg1[0] + sp24[0]); arg1[1] = mlNormalizeAngle(arg1[1] + sp24[1]); @@ -955,7 +980,7 @@ void func_802BE720(void){ ncDynamicCamera_setState(sp34); ml_vec3f_clear(D_8037D9C8); ml_vec3f_clear(D_8037D9E0); - ncFirstPersonCamera_reset(); + ncba1p_reset(); } void func_802BE794(void){ @@ -997,11 +1022,11 @@ void func_802BE894(f32 position[3], f32 rotation[3]){ void ncDynamicCamera_enterFirstPerson(void){ dynamicCameraInFirstPerson = true; - ncFirstPersonCamera_setState(FIRSTPERSON_STATE_1_ENTER); - ncFirstPersonCamera_setZoomedOutPosition(cameraPosition); - ncFirstPersonCamera_setZoomedOutRotation(cameraRotation); + ncba1p_setState(FIRSTPERSON_STATE_1_ENTER); + ncba1p_setZoomedOutPosition(cameraPosition); + ncba1p_setZoomedOutRotation(cameraRotation); } void ncDynamicCamera_exitFirstPerson(void){ - ncFirstPersonCamera_setState(FIRSTPERSON_STATE_3_EXIT); + ncba1p_setState(FIRSTPERSON_STATE_3_EXIT); } diff --git a/src/core2/camera/dynamicCam4.c b/src/core2/nc/fly.c similarity index 70% rename from src/core2/camera/dynamicCam4.c rename to src/core2/nc/fly.c index 8fca9dc40..8ea98dafd 100644 --- a/src/core2/camera/dynamicCam4.c +++ b/src/core2/nc/fly.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/ba/fly.c #include #include "functions.h" #include "variables.h" @@ -6,8 +7,8 @@ extern f32 player_getYaw(void); extern f32 player_getPitch(void); extern void func_802BD870(f32, f32, f32, f32); -void ncDynamicCam4_func_802BFE50(f32 arg0, f32 arg1, f32 arg2); -void ncDynamicCam4_func_802BFE74(bool); +void ncbafly_func_802BFE50(f32 arg0, f32 arg1, f32 arg2); +void ncbafly_func_802BFE74(bool); /* .bss */ f32 D_8037DB10; @@ -17,19 +18,19 @@ f32 D_8037DB1C; f32 D_8037DB20; /* .code */ -void ncDynamicCam4_init(void) { +void ncbafly_init(void) { func_802BD870(10.0f, 20.0f, 120.0f, 200.0f); if (gsworld_getMap() == MAP_90_GL_BATTLEMENTS) { - ncDynamicCam4_func_802BFE50(10.0f, 800.0f, 1350.0f); + ncbafly_func_802BFE50(10.0f, 800.0f, 1350.0f); } else { - ncDynamicCam4_func_802BFE50(2.0f, 800.0f, 350.0f); + ncbafly_func_802BFE50(2.0f, 800.0f, 350.0f); } - ncDynamicCam4_func_802BFE74(0); + ncbafly_func_802BFE74(0); } -void ncDynamicCam4_end(void){} +void ncbafly_end(void){} -void ncDynamicCam4_update(void) { +void ncbafly_update(void) { f32 sp84[3]; f32 sp78[3]; f32 sp6C[3]; @@ -57,8 +58,8 @@ void ncDynamicCam4_update(void) { ml_vec3f_diff_copy(sp48, sp6C, sp84); sp44 = gu_sqrtf(sp48[0]*sp48[0] + sp48[1]*sp48[1] + sp48[2]*sp48[2]); temp_f10 = (sp3C - sp44) * sp38; - sp44 += func_80259198(temp_f10 * D_8037DB10, sp38 * D_8037DB14); - func_8025727C(sp84[0], sp84[1], sp84[2], sp6C[0], sp6C[1], sp6C[2], &sp54[0], &sp54[1]); + sp44 += ml_clamp_abs_f(temp_f10 * D_8037DB10, sp38 * D_8037DB14); + ml_horizontal_and_vertical_angles(sp84[0], sp84[1], sp84[2], sp6C[0], sp6C[1], sp6C[2], &sp54[0], &sp54[1]); if ((sp34 > 180.0f) && (sp34 < 360.0f)) { sp34 = ml_min_f(100.0f, (f32) ((f64) (360.0f - sp34) * 1.4)); } @@ -67,27 +68,27 @@ void ncDynamicCam4_update(void) { sp48[2] = 0.0f; sp48[0] = (f32) ((f64) sp48[0] * ((f64) sp38 * 0.8)); sp48[1] = sp48[1] * (sp38 * D_8037DB1C); - sp48[0] = func_80259198(sp48[0], sp38 * 40.0f); - sp48[1] = func_80259198(sp48[1], sp38 * D_8037DB20); + sp48[0] = ml_clamp_abs_f(sp48[0], sp38 * 40.0f); + sp48[1] = ml_clamp_abs_f(sp48[1], sp38 * D_8037DB20); sp54[0] = mlNormalizeAngle(sp54[0] + sp48[0]); sp54[1] = mlNormalizeAngle(sp54[1] + sp48[1]); func_80256E24(sp60, -sp54[0], sp54[1], 0.0f, 0.0f, sp44); ml_vec3f_add(sp78, sp84, sp60); ncDynamicCamera_setPosition(sp78); - func_8025727C(sp84[0], sp84[1], sp84[2], sp78[0], sp78[1], sp78[2], &sp54[0], &sp54[1]); + ml_horizontal_and_vertical_angles(sp84[0], sp84[1], sp84[2], sp78[0], sp78[1], sp78[2], &sp54[0], &sp54[1]); sp54[0] = -sp54[0]; sp54[2] = 0.0f; func_802BD720(sp54); } -void ncDynamicCam4_func_802BFE50(f32 arg0, f32 arg1, f32 arg2){ +void ncbafly_func_802BFE50(f32 arg0, f32 arg1, f32 arg2){ D_8037DB10 = arg0; D_8037DB14 = arg1; D_8037DB18 = arg2; } -void ncDynamicCam4_func_802BFE74(bool arg0) { +void ncbafly_func_802BFE74(bool arg0) { if (arg0) { D_8037DB1C = 6.0f; D_8037DB20 = 270.0f; diff --git a/src/core2/camera/randomCamera.c b/src/core2/nc/randomCamera.c similarity index 97% rename from src/core2/camera/randomCamera.c rename to src/core2/nc/randomCamera.c index 36ddf5871..7916a5c10 100644 --- a/src/core2/camera/randomCamera.c +++ b/src/core2/nc/randomCamera.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/randomCamera.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/camera/staticCamera.c b/src/core2/nc/staticCamera.c similarity index 96% rename from src/core2/camera/staticCamera.c rename to src/core2/nc/staticCamera.c index f62fb0147..58e88e284 100644 --- a/src/core2/camera/staticCamera.c +++ b/src/core2/nc/staticCamera.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/nc/staticCamera.c #include #include "core1/core1.h" #include "functions.h" @@ -19,7 +20,7 @@ void ncStaticCamera_init(void){ void ncStaticCamera_end(void){} void ncStaticCamera_rotateToTarget(f32 target[3]){ - func_8025727C( + ml_horizontal_and_vertical_angles( target[0], target[1], target[2], ncStaticCameraPosition[0], ncStaticCameraPosition[1], ncStaticCameraPosition[2], &ncStaticCameraRotation[0], &ncStaticCameraRotation[1] diff --git a/src/core2/particle/factory.c b/src/core2/particle/commonParticleTypeMap.c similarity index 98% rename from src/core2/particle/factory.c rename to src/core2/particle/commonParticleTypeMap.c index 592db456e..d187c709b 100644 --- a/src/core2/particle/factory.c +++ b/src/core2/particle/commonParticleTypeMap.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/commonParticleTypeMap.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/colordefault.c b/src/core2/particle/dustemitter.c similarity index 98% rename from src/core2/particle/colordefault.c rename to src/core2/particle/dustemitter.c index 524dfd6aa..2dc63ae76 100644 --- a/src/core2/particle/colordefault.c +++ b/src/core2/particle/dustemitter.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/dustemitter.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/emitter1.c b/src/core2/particle/emitter1.c index b3edf8f32..ea01aca00 100644 --- a/src/core2/particle/emitter1.c +++ b/src/core2/particle/emitter1.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6CD20.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/emitter2.c b/src/core2/particle/emitter2.c index 28df752af..6be9fcee8 100644 --- a/src/core2/particle/emitter2.c +++ b/src/core2/particle/emitter2.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6CEC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/emitterstruct.c b/src/core2/particle/emitterstruct.c index f0e136c48..06c8cffb9 100644 --- a/src/core2/particle/emitterstruct.c +++ b/src/core2/particle/emitterstruct.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CB050.c #include #include "functions.h" #include "variables.h" @@ -64,7 +65,7 @@ void func_80352114(Struct_core2_CB050_0 *arg0, Struct68s *arg1, f32 arg2) { arg0->unk64 = (f32) (arg0->unk64 + arg2); player_getPosition(player_position); if( (func_80294660() == 0x100) - && func_8028F20C() + && player_isStableWithExtraSteps() && (ml_vec3f_length_sq(player_position, arg0->unk4C) < 50000.0f) ) { sp58 = arg0->unk4C[0] - player_position[0]; diff --git a/src/core2/particle/initcallback.c b/src/core2/particle/initcallback.c index 7afb94169..e00fb760e 100644 --- a/src/core2/particle/initcallback.c +++ b/src/core2/particle/initcallback.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CBBF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/lifescale.c b/src/core2/particle/lifescale.c index a2ca784cb..d08fd8ee2 100644 --- a/src/core2/particle/lifescale.c +++ b/src/core2/particle/lifescale.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6A4B0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/particle/particle.c b/src/core2/particle/particle.c index 025830472..27b0c0c04 100644 --- a/src/core2/particle/particle.c +++ b/src/core2/particle/particle.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/particle.c #include #include "core1/core1.h" #include "functions.h" @@ -51,12 +52,17 @@ typedef struct particle{ f32 velocity_50[3]; u8 unk5C; //u8 pad5D[3]; + // [port] Spawn serial; see the identity comment in __particleEmitter_drawOnPass. + u32 portSerial; } Particle; /* .bss */ f32 particleSfxTimer; u8 partEmitMgrEnable; +// [port] Monotonic source for Particle::portSerial. +static u32 sPortParticleSerial = 0; + /* .code */ void func_802EE930(ParticleEmitter *this){ func_8033B388(&this->sprite_1C, &this->unk34); @@ -120,6 +126,7 @@ void __particleEmitter_initParticle(ParticleEmitter *this, Particle *particle){ particle->angluar_velocity[1] = randf2(this->unkBC[1], this->unkC8[1]); particle->angluar_velocity[2] = randf2(this->unkBC[2], this->unkC8[2]); + particle->portSerial = ++sPortParticleSerial; // [port] interpolation identity particle->age_48 = 0.0f; particle->lifetime_4C = randf2(this->particleLifeTimeRange[0], this->particleLifeTimeRange[1]) + 0.001; if(!this->sphericalParticleVelocity_48){ @@ -164,19 +171,10 @@ void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, V return; if(this->model_20 != NULL){ - // [port] Stable scope per emitter + per particle. Slot index plus - // a coarse age bucket: two consecutive frames of the same particle - // land in the same bucket, so they pair. When expiry swaps a new - // particle into the slot its age resets to ~0 — different bucket, - // no false pair with the dead particle. Spawn-field hashing alone - // failed for sparkles (shared emitter, zero-width scale/lifetime - // ranges → every particle had the same hash → visible flashing). + // [port] Stable scope per emitter + per particle, keyed on a spawn serial. FrameInterpolation_RecordOpenChild("part_emit", FrameInterpolation_GetId(this)); for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){ - FrameInterpolation_RecordOpenChildHash3("part", - (uint64_t)(uintptr_t)(iPtr - this->pList_start_124), - (uint64_t)(iPtr->age_48 * 2.0f), - 0); + FrameInterpolation_RecordOpenChildHash3("part", (uint64_t)iPtr->portSerial, 0, 0); position[0] = iPtr->position[0] + this->unk4[0]; position[1] = iPtr->position[1] + this->unk4[1]; position[2] = iPtr->position[2] + this->unk4[2]; @@ -217,13 +215,10 @@ void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, V flat_rotation[0] = 90.0f; flat_rotation[1] = 0.0f; flat_rotation[2] = 0.0f; - // [port] Same slot+age-bucket identity as the model branch above. + // [port] Same spawn-serial identity as the model branch above. FrameInterpolation_RecordOpenChild("part_emit", FrameInterpolation_GetId(this)); for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){ - FrameInterpolation_RecordOpenChildHash3("part", - (uint64_t)(uintptr_t)(iPtr - this->pList_start_124), - (uint64_t)(iPtr->age_48 * 2.0f), - 0); + FrameInterpolation_RecordOpenChildHash3("part", (uint64_t)iPtr->portSerial, 0, 0); gDPSetPrimColor((*gfx)++, 0, 0, this->rgb[0], this->rgb[1], this->rgb[2], iPtr->fade*this->alpha); position[0] = iPtr->position[0] + this->unk4[0]; position[1] = iPtr->position[1] + this->unk4[1]; diff --git a/src/core2/particle/accel.c b/src/core2/particle/particleemittermanager.c similarity index 98% rename from src/core2/particle/accel.c rename to src/core2/particle/particleemittermanager.c index 47aac78e1..e501e9c7b 100644 --- a/src/core2/particle/accel.c +++ b/src/core2/particle/particleemittermanager.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/particleemittermanager.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/positionset.c b/src/core2/particle/positionset.c index 1d493cc40..5bd1eecd4 100644 --- a/src/core2/particle/positionset.c +++ b/src/core2/particle/positionset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_CD0A0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/samplerate.c b/src/core2/particle/samplerate.c index ee9ebdf7a..4774b0c0c 100644 --- a/src/core2/particle/samplerate.c +++ b/src/core2/particle/samplerate.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6D490.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/scale1.c b/src/core2/particle/scale1.c index 79802f1d3..13e9c8f2b 100644 --- a/src/core2/particle/scale1.c +++ b/src/core2/particle/scale1.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_66D90.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/scale2.c b/src/core2/particle/scale2.c index 7fded4f8c..d6bac730b 100644 --- a/src/core2/particle/scale2.c +++ b/src/core2/particle/scale2.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_66FB0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/spawn.c b/src/core2/particle/spawn.c index 8b467a3ca..a2c1eb9fa 100644 --- a/src/core2/particle/spawn.c +++ b/src/core2/particle/spawn.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6D030.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/typeindex.c b/src/core2/particle/typeindex.c index 88a45f0b9..5feded98f 100644 --- a/src/core2/particle/typeindex.c +++ b/src/core2/particle/typeindex.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6AEF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/velocityrange.c b/src/core2/particle/velocityrange.c index e810851a5..45bbcbf13 100644 --- a/src/core2/particle/velocityrange.c +++ b/src/core2/particle/velocityrange.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6B030.c #include "core1/core1.h" #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/velocityset.c b/src/core2/particle/velocityset.c index 83d883c84..5728381ee 100644 --- a/src/core2/particle/velocityset.c +++ b/src/core2/particle/velocityset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_6D270.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/playerutils.c b/src/core2/playerutils.c index 524aa9a47..6fc927ff6 100644 --- a/src/core2/playerutils.c +++ b/src/core2/playerutils.c @@ -40,7 +40,7 @@ s32 can_climb(void){ return ability_hasLearned(ABILITY_5_CLIMB); } -int can_dive(void){ +bool can_dive(void){ return ability_hasLearned(ABILITY_F_DIVE) && !isPlayerInHazard() && 100.0f < floor_getCurrentFloorYPosition() - func_80294438(); @@ -50,7 +50,7 @@ s32 can_egg(void){ return ability_hasLearned(ABILITY_6_EGGS); } -int can_feathery_flap(void){ +bool can_feathery_flap(void){ return baflag_isFalse(BA_FLAG_12_HAS_FLAPPED) && baflag_isFalse(BA_FLAG_5_HAS_PECKED) && ability_hasLearned(ABILITY_7_FEATHERY_FLAP); @@ -68,18 +68,18 @@ s32 can_control_jump_height(void){ return ability_hasLearned(ABILITY_A_HOLD_A_JUMP_HIGHER); } -int can_peck(void){ +bool can_peck(void){ return baflag_isFalse(BA_FLAG_5_HAS_PECKED) && baflag_isFalse(BA_FLAG_12_HAS_FLAPPED) && ability_hasLearned(ABILITY_B_RATATAT_RAP); } -int func_8028ABB8(void){ +bool func_8028ABB8(void){ if(baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE) || baflag_isTrue(BA_FLAG_19_SHOULD_TRANSFORM)) - return 0; + return false; if(bs_getState() == BS_56_RECOIL) - return 0; - return 1; + return false; + return true; } s32 can_roll(void){ @@ -106,32 +106,32 @@ s32 can_wonderwing(void){ return ability_hasLearned(ABILITY_12_WONDERWING); } -int can_view_first_person(void){ +bool can_view_first_person(void){ if( gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK && mapSpecificFlags_get(0xd)){ - return 0; + return false; } - if(ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_3_EXIT) - return 0; + if(ncba1p_getState() == FIRSTPERSON_STATE_3_EXIT) + return false; if(!player_isStable() && !player_inWater()) - return 0; - return 1; + return false; + return true; } -int dummy_player_is_ant(void){ +bool dummy_player_is_ant(void){ return bsant_inSet(bs_getState()); } -int dummy_player_is_pumpkin(void){ +bool dummy_player_is_pumpkin(void){ return bspumpkin_inSet(bs_getState()); } -int func_8028ADB4(void){ +bool func_8028ADB4(void){ return func_8032190C() && gsworld_getMap() != MAP_1_SM_SPIRAL_MOUNTAIN; } -int wishyWashyFlag_get(void){ +bool wishyWashyFlag_get(void){ return volatileFlag_get(VOLATILE_FLAG_9D_SANDCASTLE_WISHY_WASHY); } @@ -141,7 +141,7 @@ bool dummy_player_withinIdealYaw(void) { f32 position[3]; f32 ideal_yaw; - _player_getPosition(position); + playerPosition_get(position); ideal_yaw = yaw_getIdeal(); right_angle = viewport_adjustAngleToRight(position, 90.0f); left_angle = viewport_adjustAngleToRight(position, 270.0f); @@ -153,37 +153,37 @@ bool dummy_player_withinIdealYaw(void) { } } -bool func_8028AED4(f32 arg0[3], f32 arg1) { - f32 position[3]; - f32 sp28; +bool func_8028AED4(f32 src_position[3], f32 arg1) { + f32 player_position[3]; + f32 yaw; u16 sp26; u16 sp24; s32 temp_v1; s32 phi_a0; - _player_getPosition(position); - func_80257F18(arg0, position, &sp28); - sp26 = (u16) (sp28 * 182.044444); + playerPosition_get(player_position); + func_80257F18(src_position, player_position, &yaw); + sp26 = (u16) (yaw * 182.044444); sp24 = (u16) (player_getYaw() * 182.044444); sp26 = (u16)((sp26 - sp24)); - temp_v1 = 0x8000 - sp26; + temp_v1 = 0x8000 - sp26; // Flip sign? phi_a0 = (temp_v1 >= 0) ? temp_v1 : -temp_v1; return (phi_a0 < arg1 * 182.044444); } -int player_shouldFall(void){ - return (60.0f < player_getYPosition() - func_80294438()); +bool player_shouldFall(void){ + return (60.0f < playerPosition_getY() - func_80294438()); } -int player_isInHorizontalRadius(f32 arg0[3], f32 arg1){ +bool player_isInHorizontalRadius(f32 arg0[3], f32 arg1){ f32 sp1C[3]; - _player_getPosition(sp1C); + playerPosition_get(sp1C); return ml_vec3f_point_within_horizontal_distance(sp1C, arg0[0], arg0[2], arg1); } s32 func_8028B120(void){return 0;} -int player_isOnDangerousGround(void){ +bool player_isOnDangerousGround(void){ return baflag_isTrue(BA_FLAG_13_TOUCHING_DANGEROUS_GROUND); } @@ -194,29 +194,29 @@ bool player_isInRBB(void){ bool player_isInVerticalRange(f32 position[3], f32 range) { f32 plyr_pos[3]; - _player_getPosition(plyr_pos); + playerPosition_get(plyr_pos); return (((position[1] - range) <= plyr_pos[1]) && (plyr_pos[1] <= (position[1] + range))); } -int player_shouldSlideTrot(void){ +bool player_shouldSlideTrot(void){ return stateTimer_isActive(STATE_TIMER_6_UNKNOWN) || (1.0 == get_slope_timer() && func_80294610(0x40)); } bool func_8028B254(s32 arg0) { - return (player_isStable() || (baphysics_get_vertical_velocity() < 0.0f && (player_getYPosition() - func_80294438()) < (f32) arg0)); + return (player_isStable() || (baphysics_get_vertical_velocity() < 0.0f && (playerPosition_getY() - func_80294438()) < (f32) arg0)); } -int player_isStable(void){ +bool player_isStable(void){ return D_8037BF60 && baphysics_get_vertical_velocity() < 0.0f; } -int player_isSliding(void){ +bool player_isSliding(void){ return stateTimer_isActive(STATE_TIMER_5_UNKNOWN) || 1.0 == get_slope_timer(); } -int func_8028B394(void){ +bool func_8028B394(void){ return func_8029CF20(4); } @@ -261,15 +261,15 @@ bool player_isSwimming(void){ return out; } -int func_8028B4C4(void){ +bool func_8028B4C4(void){ return 135.0f < mlAbsF(mlDiffDegF(yaw_getIdeal(), yaw_get())); } -int player_inWater(void){ +bool player_inWater(void){ return D_8037BF61; } -int func_8028B528(void){ +bool func_8028B528(void){ return D_8037BF62; } @@ -290,9 +290,9 @@ void func_8028B59C(void) { sp24 = D_8037BF61; if (D_8037BF61) { - D_8037BF61 = (func_80294554() && player_getYPosition() < ((floor_getCurrentFloorYPosition() - 50.0f) + 2.0f)); + D_8037BF61 = (func_80294554() && playerPosition_getY() < ((floor_getCurrentFloorYPosition() - 50.0f) + 2.0f)); } else { - D_8037BF61 = (func_80294554() && player_getYPosition() < ((floor_getCurrentFloorYPosition() - 50.0f) - 2.0f)); + D_8037BF61 = (func_80294554() && playerPosition_getY() < ((floor_getCurrentFloorYPosition() - 50.0f) - 2.0f)); } if (gsworld_getMap() == MAP_6_TTC_NIPPERS_SHELL) { D_8037BF61 = false; diff --git a/src/core2/prop_assetcache.c b/src/core2/propModelList.c similarity index 99% rename from src/core2/prop_assetcache.c rename to src/core2/propModelList.c index 9db6a69a2..7dd8feb07 100644 --- a/src/core2/prop_assetcache.c +++ b/src/core2/propModelList.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/propModelList.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/quiz/game.c b/src/core2/quiz/game.c index fc740563c..a058abd6e 100644 --- a/src/core2/quiz/game.c +++ b/src/core2/quiz/game.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_4C020.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -12,25 +13,28 @@ extern void func_802F9D38(s32); extern void func_802EE2E8(Actor *arg0, s32 arg1, s32 cnt, s32 arg3, f32 arg4, f32 arg5, f32 arg6); extern void gcquiz_func_80319EA4(void); -void func_802D3D54(Actor *this); -void func_802D3DA4(Actor *this); -Actor *func_802D3F48(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void func_802D3FD4(Actor *this); -Actor *func_802D41C4(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void func_802D4250(Actor *this); -void func_802D4388(Actor *this); -Actor *func_802D4588(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void func_802D4680(Actor *this); -void func_802D4B94(Actor *this); -void func_802D4BBC(Actor *this); -void func_802D4BE4(Actor *this); -void func_802D4C0C(Actor *this); -void func_802D4C34(Actor *this); -void func_802D4C5C(Actor *this); -void func_802D4C84(Actor *this); -void func_802D4CAC(Actor *this); -void func_802D4CD4(Actor *this); -void func_802D68F0(s32 seconds); +extern void port_lairWater_onRiseTrigger(int32_t waterMap, int32_t levelFlag); +extern int32_t port_lairWater_targetLevel(int32_t map, int32_t flagLevel); + +void chMMMBreakableWooden_update(Actor *this); +void gWorldExitPad_update(Actor *this); +Actor *gWorldExitPad_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chSnsEgg_update(Actor *this); +Actor *chSnsEgg_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chIceKey_update(Actor *this); +void chMumboSwitch_update(Actor *this); +Actor *chMumboSwitch_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chFFTeleportPad_Update(Actor *this); +void chMMWitchSwitch_update(Actor *this); +void chCCWitchSwitch_update(Actor *this); +void chBGSWitchSwitch_update(Actor *this); +void chGVWitchSwitch_update(Actor *this); +void chMMMWitchSwitch_update(Actor *this); +void chTTCWitchSwitch_update(Actor *this); +void chRBBWitchSwitch_update(Actor *this); +void chCCWWitchSwitch_update(Actor *this); +void chFPWitchSwitch_update(Actor *this); +void code_4C020_setHourglassTimer(s32 seconds); typedef struct { s16 unk0; @@ -53,7 +57,7 @@ f32 D_803676A4 = 0.0f; s32 D_803676A8 = 0; u8 D_803676AC = 0; -ActorAnimationInfo D_803676B0[] = { +ActorAnimationInfo gSwitchAnimations[] = { {0x000, 0.0f}, {0x000, 0.0f}, {ASSET_D4_ANIM_SWITCH_DOWN, 0.15f}, @@ -78,24 +82,67 @@ ActorAnimationInfo D_803676B0[] = { {ASSET_217_ANIM_UNKNOWN, 0.3f} }; -ActorInfo D_80367760 = { 0x26E, 0x2D9, 0x3B4, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80367784 = { 0x26F, 0x2DA, 0x3B5, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_803677A8 = { MARKER_168_ICE_KEY, ACTOR_25D_ICE_KEY, ASSET_50C_MODEL_ICE_KEY, 0x1, NULL, func_802D4250, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_803677CC = { 0x233, 0x23D, 0x4DD, 0x12, D_803676B0, func_802D4388, actor_update_func_80326224, func_802D4588, 0, 0, 0.0f, 0}; -ActorInfo D_803677F0 = { 0x16A, 0x242, 0x0, 0x0, NULL, func_802D4680, NULL, func_80325340, 0, 0, 0.0f, 0}; -ActorInfo D_80367814 = { MARKER_169_SNS_EGG, ACTOR_25E_SNS_EGG, ASSET_50D_MODEL_SNS_EGG, 0x1, NULL, func_802D3FD4, NULL, func_802D41C4, 0, 0, 0.0f, 0}; -ActorInfo D_80367838 = { 0x265, 0x2E4, 0x55A, 0x1, NULL, func_802D3DA4, NULL, func_802D3F48, 0, 0, 0.0f, 0}; -ActorInfo D_8036785C = { MARKER_103_MM_WITCH_SWITCH, ACTOR_204_MM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4B94, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80367880 = { MARKER_104_MMM_WITCH_SWITCH, ACTOR_206_MMM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C34, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_803678A4 = { MARKER_105_TTC_WITCH_SWITCH, ACTOR_208_TTC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C5C, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_803678C8 = { MARKER_106_RBB_WITCH_SWITCH, ACTOR_20B_RBB_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C84, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_803678EC = { MARKER_22A_CCW_WITCH_SWITCH, ACTOR_237_CCW_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4CAC, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80367910 = { MARKER_22B_FP_WITCH_SWITCH, ACTOR_239_FP_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4CD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80367934 = { MARKER_166_CC_WITCH_SWITCH, ACTOR_25B_CC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4BBC, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80367958 = { MARKER_162_BGS_WITCH_SWITCH, ACTOR_257_BGS_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4BE4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_8036797C = { MARKER_161_GV_WITCH_SWITCH, ACTOR_256_GV_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C0C, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367760 = { + MARKER_26E_UNKNOWN, ACTOR_2D9_UNKNOWN, ASSET_3B4_MODEL_UNUSED, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80367784 = { + MARKER_26F_UNKNOWN, ACTOR_2DA_UNKNOWN, ASSET_3B5_MODEL_UNUSED, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chIceKey = { + MARKER_168_ICE_KEY, ACTOR_25D_ICE_KEY, ASSET_50C_MODEL_ICE_KEY, + 0x1, NULL, + chIceKey_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo chMumboSwitch = { + MARKER_233_MUMBO_SWITCH, ACTOR_23D_MUMBO_SWITCH, ASSET_4DD_MODEL_MUMBO_SWITCH, + 0x12, gSwitchAnimations, + chMumboSwitch_update, actor_update_func_80326224, chMumboSwitch_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chFFTeleportPad = { + MARKER_16A_FF_TELEPORT_PAD, ACTOR_242_FF_TELEPORT_PAD, 0x0, + 0x0, NULL, + chFFTeleportPad_Update, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +ActorInfo chSnsEgg = { + MARKER_169_SNS_EGG, ACTOR_25E_SNS_EGG, ASSET_50D_MODEL_SNS_EGG, + 0x1, NULL, + chSnsEgg_update, NULL, chSnsEgg_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo gWorldExitPad = { + MARKER_265_WORLD_EXIT_PAD, ACTOR_2E4_WORLD_EXIT_PAD, ASSET_55A_MODEL_WORLD_EXIT_PAD, + 0x1, NULL, + gWorldExitPad_update, NULL, gWorldExitPad_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo chMMWitchSwitch = { MARKER_103_MM_WITCH_SWITCH, ACTOR_204_MM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chMMWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chMMMWitchSwitch = { MARKER_104_MMM_WITCH_SWITCH, ACTOR_206_MMM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chMMMWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chTTCWitchSwitch = { MARKER_105_TTC_WITCH_SWITCH, ACTOR_208_TTC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chTTCWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chRBBWitchSwitch = { MARKER_106_RBB_WITCH_SWITCH, ACTOR_20B_RBB_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chRBBWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chCCWWitchSwitch = { MARKER_22A_CCW_WITCH_SWITCH, ACTOR_237_CCW_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chCCWWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chFPWitchSwitch = { MARKER_22B_FP_WITCH_SWITCH, ACTOR_239_FP_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chFPWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chCCWitchSwitch = { MARKER_166_CC_WITCH_SWITCH, ACTOR_25B_CC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chCCWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chBGSWitchSwitch = { MARKER_162_BGS_WITCH_SWITCH, ACTOR_257_BGS_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chBGSWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo chGVWitchSwitch = { MARKER_161_GV_WITCH_SWITCH, ACTOR_256_GV_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chGVWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; s32 D_803679A0[4] = {0x87, 0x87, 0x87, 0xA0}; + s16 D_803679B0[] = { FILEPROG_5_BLUE_EGG_TEXT, FILEPROG_90_PAID_TERMITE_COST, @@ -115,6 +162,7 @@ Struct_core2_4C020_0 D_803679C8[] = { {-580, 0, 1550, 2200}, {150, 460, 1625, 2100}, }; + s16 D_803679E0[] = {-50, -100, 200}; /* .bss */ @@ -148,226 +196,349 @@ void func_802D2FB0(Actor *this, s32 arg1, s32 arg2, s32 arg3, f32 arg4, s32 arg5 // collision function if player shoots egg at spider webs void func_802D3138(ActorMarker *marker, ActorMarker *other_marker) { - if(marker->id == MARKER_224_BREAKABLE_FLOOR_COBWEB || marker->id == MARKER_225_BREAKABLE_WALL_COBWEB) { + if(marker->id == MARKER_224_BREAKABLE_FLOOR_COBWEB + || marker->id == MARKER_225_BREAKABLE_WALL_COBWEB) + { comusic_playTrack(COMUSIC_2B_DING_B); } } // called from collision die function below, set according file flag and despawns object -void func_802D317C(ActorMarker *marker, enum file_progress_e prog_flag_id) { - fileProgressFlag_set(prog_flag_id, true); +void code_4C020_breakableObjectSetFlag(ActorMarker *marker, enum file_progress_e prog_flag_id) { + fileProgressFlag_set(prog_flag_id, TRUE); marker_despawn(marker); } +extern void port_breakable_broadcastBreak(s32 markerId, s32 x, s32 y, s32 z); +extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); + // collision die function for several objects in Lair -void func_802D31AC(ActorMarker *arg0, ActorMarker * arg1) { - Actor *sp2C; - - sp2C = marker_getActor(arg0); - arg0->collidable = false; - switch (arg0->id) { - case 0x9F: - case 0xA0: - case 0xFF: - gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); - subaddie_set_state(sp2C, 4); +void code_4C020_breakableObjectSfx(ActorMarker *marker, ActorMarker *other_marker) { + Actor *actor; + + actor = marker_getActor(marker); + marker->collidable = FALSE; + switch (marker->id) { + case MARKER_9F_CHURCH_GATE_LEFT_LOCK: + case MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1: + case MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2: + gcsfx_play(SFX_82_METAL_BREAK); + subaddie_set_state(actor, 4); + port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); break; - case 0x17D: + case MARKER_17D_IRON_GATE_NO_LOCK: FUNC_8030E624(SFX_82_METAL_BREAK, 0.7f, 32736); FUNC_8030E624(SFX_82_METAL_BREAK, 0.6f, 32736); - func_802D2FB0(sp2C, 0x14, -0x1E, 0x190, 3.0f, 0x15E, 0x50, 0x96); - sp2C->lifetime_value = 1.0f; + func_802D2FB0(actor, 0x14, -0x1E, 0x190, 3.0f, 0x15E, 0x50, 0x96); + actor->lifetime_value = 1.0f; fileProgressFlag_set(FILEPROG_A5_LAIR_CRYPT_GATE_OPEN, 1); break; case MARKER_109_BREAKABLE_BRICK_WALL: func_8030E6D4(SFX_114_BRICKWALL_BREAKING); - sfxsource_play(SFX_11_WOOD_BREAKING_1, 28000); - subaddie_set_state_looped(sp2C, 9); - fileProgressFlag_set((sp2C->actorTypeSpecificField == 1) ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN, true); + gcsfx_playAtSampleRate(SFX_11_WOOD_BREAKING_1, 28000); + subaddie_set_state_looped(actor, 9); + fileProgressFlag_set((actor->actorTypeSpecificField == 1) ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN, TRUE); break; - case 0x107: - gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); - func_802EE278(sp2C, 0xE, 0xF, 0x46, 0.8f, 0.7f); - marker_despawn(arg0); + case MARKER_107_ENGINE_ROOM_DOOR: + gcsfx_play(SFX_82_METAL_BREAK); + func_802EE278(actor, 0xE, 0xF, 0x46, 0.8f, 0.7f); + port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); + marker_despawn(marker); break; case MARKER_224_BREAKABLE_FLOOR_COBWEB: comusic_playTrack(COMUSIC_2B_DING_B); - gcsfx_playWithPitch(SFX_129_SWOOSH, (sp2C->scale < 0.45) ? 1.0 : 0.8, 0x7FF8); - subaddie_set_state_looped(sp2C, 0xC); - func_802D2FB0(sp2C, 8, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); - fileProgressFlag_set((sp2C->actorTypeSpecificField== 1) ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN, 1); + gcsfx_playWithPitch(SFX_129_SWOOSH, (actor->scale < 0.45) ? 1.0 : 0.8, 0x7FF8); + subaddie_set_state_looped(actor, 0xC); + func_802D2FB0(actor, 8, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); + fileProgressFlag_set((actor->actorTypeSpecificField== 1) ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN, 1); break; case MARKER_225_BREAKABLE_WALL_COBWEB: comusic_playTrack(COMUSIC_2B_DING_B); - gcsfx_playAtSampleRate(SFX_129_SWOOSH); - subaddie_set_state_looped(sp2C, 0xF); - func_802D2FB0(sp2C, 0xE, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); + gcsfx_play(SFX_129_SWOOSH); + subaddie_set_state_looped(actor, 0xF); + func_802D2FB0(actor, 0xE, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); fileProgressFlag_set(FILEPROG_CA_COBWEB_BLOCKING_PURPLE_CAULDRON_BROKEN, 1); break; - case 0x163: - if (sp2C->unk10_12 == 0) { - sp2C->unk10_12 = true; + case MARKER_163_CRYPT_COFFIN_LID: + if (actor->unk10_12 == 0) { + actor->unk10_12 = TRUE; timed_playSfx(0.5f, SFX_3F9_UNKNOWN, 1.0f, 32000); FUNC_8030E624(SFX_114_BRICKWALL_BREAKING, 0.8f, 32000); } break; - case 0x9A: - case 0x9C: - case 0x9D: - case 0x9E: - case 0xA1: - case 0xE7: - case 0xEA: - case 0x108: - case 0x263: - if ((arg0->id == 0x9D) || (arg0->id == 0xE7)) { + case MARKER_9A_1881_BARREL_TOP: + case MARKER_9C_SHACK_DOOR: + case MARKER_9D_MANSION_DOOR: + case MARKER_9E_CELLAR_HATCH: + case MARKER_A1_BLUBBER_SHIP_TOP_HATCH: + case MARKER_E7_DINING_DOOR: + case MARKER_EA_LIGHTHOUSE_DOOR: + case MARKER_108_CABIN_CLOSET_DOOR: + case MARKER_263_CCW_WHIPCRACK_ROOM_DOOR: + if ((marker->id == MARKER_9D_MANSION_DOOR) || (marker->id == MARKER_E7_DINING_DOOR)) { levelSpecificFlags_set(LEVEL_FLAG_2E_MMM_UNKNOWN, 1); } - if (arg0->id == 0x263) { + if (marker->id == MARKER_263_CCW_WHIPCRACK_ROOM_DOOR) { levelSpecificFlags_set(LEVEL_FLAG_38_CCW_UNKNOWN, 1); } - func_802D2FB0(sp2C, 5, -0x28, 0xC8, 0.85f, 0xDC, 0x3C, 0x64); - gcsfx_playAtSampleRate(SFX_D_EGGSHELL_BREAKING); - gcsfx_playAtSampleRate(SFX_11_WOOD_BREAKING_1); - switch (arg0->id) { - case 0x9E: - func_802EE278(sp2C, 0xD, 9, 0x82, 0.34f, 1.0f); + func_802D2FB0(actor, 5, -0x28, 0xC8, 0.85f, 0xDC, 0x3C, 0x64); + gcsfx_play(SFX_D_EGGSHELL_BREAKING); + gcsfx_play(SFX_11_WOOD_BREAKING_1); + switch (marker->id) { + case MARKER_9E_CELLAR_HATCH: + func_802EE278(actor, 0xD, 9, 0x82, 0.34f, 1.0f); break; - case 0x9D: - case 0xE7: - case 0x108: - func_802EE278(sp2C, 7, 6, 0x32, 0.4f, 1.1f); - func_802EE278(sp2C, 7, 6, 0xB4, 0.4f, 1.1f); + case MARKER_9D_MANSION_DOOR: + case MARKER_E7_DINING_DOOR: + case MARKER_108_CABIN_CLOSET_DOOR: + func_802EE278(actor, 7, 6, 0x32, 0.4f, 1.1f); + func_802EE278(actor, 7, 6, 0xB4, 0.4f, 1.1f); break; - case 0x9A: - case 0x9C: - case 0x263: - func_802EE278(sp2C, 7, 0xA, 0x82, 0.3f, 0.8f); + case MARKER_9A_1881_BARREL_TOP: + case MARKER_9C_SHACK_DOOR: + case MARKER_263_CCW_WHIPCRACK_ROOM_DOOR: + func_802EE278(actor, 7, 0xA, 0x82, 0.3f, 0.8f); break; - case 0xA1: - func_802EE278(sp2C, 7, 9, 0x82, 0.3f, 0.6f); + case MARKER_A1_BLUBBER_SHIP_TOP_HATCH: + func_802EE278(actor, 7, 9, 0x82, 0.3f, 0.6f); break; - case 0xEA: - func_802EE278(sp2C, 3, 9, 0x82, 0.21f, 0.8f); + case MARKER_EA_LIGHTHOUSE_DOOR: + func_802EE278(actor, 3, 9, 0x82, 0.21f, 0.8f); break; default: - func_802EE278(sp2C, 7, 0x19, 0x82, 0.17f, 0.8f); + func_802EE278(actor, 7, 0x19, 0x82, 0.17f, 0.8f); break; } - marker_despawn(arg0); + port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); + marker_despawn(marker); break; - case 0x11F: - gcsfx_playAtSampleRate(SFX_D9_WOODEN_CRATE_BREAKING_1); - func_802EE2E8(sp2C, 7, 9, 0x78, 0.43f, 1.3f, 3.0f); - func_802EE2E8(sp2C, 3, 6, 0x78, 0.43f, 1.3f, 3.0f); - func_802D317C(arg0, FILEPROG_C5_RAREWARE_BOX_BROKEN); + case MARKER_11F_RAREWARE_BOX: + gcsfx_play(SFX_D9_WOODEN_CRATE_BREAKING_1); + func_802EE2E8(actor, 7, 9, 0x78, 0.43f, 1.3f, 3.0f); + func_802EE2E8(actor, 3, 6, 0x78, 0.43f, 1.3f, 3.0f); + code_4C020_breakableObjectSetFlag(marker, FILEPROG_C5_RAREWARE_BOX_BROKEN); break; - case 0x11A: - gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); - func_802EE278(sp2C, 0xE, 0xD, 0x32, 0.8f, 0.9f); - func_802EE278(sp2C, 0xE, 0xD, 0xAA, 0.8f, 0.9f); - func_802D317C(arg0, FILEPROG_C2_GRATE_TO_RBB_PUZZLE_OPEN); + case MARKER_11A_GRATE_TO_RBB_PUZZLE: + gcsfx_play(SFX_82_METAL_BREAK); + func_802EE278(actor, 0xE, 0xD, 0x32, 0.8f, 0.9f); + func_802EE278(actor, 0xE, 0xD, 0xAA, 0.8f, 0.9f); + code_4C020_breakableObjectSetFlag(marker, FILEPROG_C2_GRATE_TO_RBB_PUZZLE_OPEN); break; - case 0x118: - gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); - func_802EE278(sp2C, 0xE, 0xD, 0x50, 1.2f, 0.9f); - func_802EE278(sp2C, 0xE, 0xD, 0xB4, 1.2f, 0.9f); - func_802D317C(arg0, FILEPROG_CD_GRATE_TO_WATER_SWITCH_3_OPEN); + case MARKER_118_GRATE_TO_LEVEL_3_WATER_SWITCH: + gcsfx_play(SFX_82_METAL_BREAK); + func_802EE278(actor, 0xE, 0xD, 0x50, 1.2f, 0.9f); + func_802EE278(actor, 0xE, 0xD, 0xB4, 1.2f, 0.9f); + code_4C020_breakableObjectSetFlag(marker, FILEPROG_CD_GRATE_TO_WATER_SWITCH_3_OPEN); break; - case 0x119: - gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); - func_802EE278(sp2C, 0xE, 9, 0x50, 1.2f, 0.9f); - func_802EE278(sp2C, 0xE, 9, 0xAA, 1.2f, 0.9f); - func_802EE278(sp2C, 0xE, 9, 0x104, 1.2f, 0.9f); - func_802D317C(arg0, FILEPROG_CE_GRATE_TO_MMM_PUZZLE_OPEN); + case MARKER_119_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES: + gcsfx_play(SFX_82_METAL_BREAK); + func_802EE278(actor, 0xE, 9, 0x50, 1.2f, 0.9f); + func_802EE278(actor, 0xE, 9, 0xAA, 1.2f, 0.9f); + func_802EE278(actor, 0xE, 9, 0x104, 1.2f, 0.9f); + code_4C020_breakableObjectSetFlag(marker, FILEPROG_CE_GRATE_TO_MMM_PUZZLE_OPEN); break; - case 0x22D: - case 0x22E: - gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); - gcsfx_playAtSampleRate(SFX_B6_GLASS_BREAKING_1); - func_802EE278(sp2C, 4, 0x23, 0x1E, 0.7f, 0.6f); - marker_despawn(arg0); + case MARKER_22D_SHIP_SHADOW_WINDOW: + case MARKER_22E_SHIP_SUNNY_WINDOW: + gcsfx_play(SFX_82_METAL_BREAK); + gcsfx_play(SFX_B6_GLASS_BREAKING_1); + func_802EE278(actor, 4, 0x23, 0x1E, 0.7f, 0.6f); + port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); + marker_despawn(marker); break; - case 0x123: - case 0x1F2: - case 0x1F3: - case 0x235: - case 0x236: - case 0x237: - case 0x238: - case 0x239: - gcsfx_playAtSampleRate(SFX_13A_GLASS_BREAKING_7); - func_802EE278(sp2C, 4, 0x2D, 0x82, 1.0f, 1.0f); - if (arg0->id == 0x1F3) { - func_802EE278(sp2C, 4, 0x2D, 0x104, 1.0f, 1.0f); + case MARKER_123_WINDOW: + case MARKER_1F2_WIDE_WINDOW: + case MARKER_1F3_TALL_WINDOW: + case MARKER_235_CRACKED_SKYLIGHT: + case MARKER_236_CCW_UNKNOWN_NABNUT_WINDOW: + case MARKER_237_CCW_AUTUMN_NABNUT_WINDOW: + case MARKER_238_CCW_WINTER_NABNUT_WINDOW: + case MARKER_239_CCW_UNKNOWN_NABNUT_WINDOW: + gcsfx_play(SFX_13A_GLASS_BREAKING_7); + func_802EE278(actor, 4, 0x2D, 0x82, 1.0f, 1.0f); + if (marker->id == MARKER_1F3_TALL_WINDOW) { + func_802EE278(actor, 4, 0x2D, 0x104, 1.0f, 1.0f); } - marker_despawn(arg0); + port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); + marker_despawn(marker); break; - case 0x11E: - gcsfx_playAtSampleRate(SFX_B6_GLASS_BREAKING_1); - func_802EE278(sp2C, 4, 0x32, 0x50, 1.0f, 1.4f); - func_802EE278(sp2C, 4, 0x32, 0xA0, 1.0f, 1.4f); - func_802EE278(sp2C, 4, 0x1E, 0xF0, 0.8f, 1.1f); - func_802D317C(arg0, FILEPROG_C3_ICE_BALL_TO_CHEATO_BROKEN); + case MARKER_11E_ICE_BALL_TO_CHEATO: + gcsfx_play(SFX_B6_GLASS_BREAKING_1); + func_802EE278(actor, 4, 0x32, 0x50, 1.0f, 1.4f); + func_802EE278(actor, 4, 0x32, 0xA0, 1.0f, 1.4f); + func_802EE278(actor, 4, 0x1E, 0xF0, 0.8f, 1.1f); + code_4C020_breakableObjectSetFlag(marker, FILEPROG_C3_ICE_BALL_TO_CHEATO_BROKEN); break; case MARKER_121_GLASS_EYE: - gcsfx_playAtSampleRate(SFX_B6_GLASS_BREAKING_1); - func_802EE2E8(sp2C, 1, 0x32, 0x14, 1.2f, 1.4f, 2.2f); - func_802EE2E8(sp2C, 1, 0x3C, 0x64, 1.6f, 1.8f, 2.2f); - func_802EE2E8(sp2C, 1, 0x32, 0xB4, 1.2f, 1.4f, 2.2f); - func_802D317C(arg0, FILEPROG_C4_STATUE_EYE_BROKEN); + gcsfx_play(SFX_B6_GLASS_BREAKING_1); + func_802EE2E8(actor, 1, 0x32, 0x14, 1.2f, 1.4f, 2.2f); + func_802EE2E8(actor, 1, 0x3C, 0x64, 1.6f, 1.8f, 2.2f); + func_802EE2E8(actor, 1, 0x32, 0xB4, 1.2f, 1.4f, 2.2f); + code_4C020_breakableObjectSetFlag(marker, FILEPROG_C4_STATUE_EYE_BROKEN); break; - case 0x164: - case 0x165: - if (sp2C->unk1C[1] == sp2C->position[1]) { - sfxsource_play(SFX_9B_BOULDER_BREAKING_1, 25000); - sp2C->unk1C[0] = 1.0f; + case MARKER_164_GL_GRUNTY_FLOOR_PICTURE_EYE_1: + case MARKER_165_GL_GRUNTY_FLOOR_PICTURE_EYE_2: + if (actor->unk1C[1] == actor->position[1]) { + gcsfx_playAtSampleRate(SFX_9B_BOULDER_BREAKING_1, 25000); + actor->unk1C[0] = 1.0f; } break; default: - gcsfx_playAtSampleRate(SFX_D_EGGSHELL_BREAKING); - gcsfx_playAtSampleRate(SFX_11_WOOD_BREAKING_1); - marker_despawn(arg0); + gcsfx_play(SFX_D_EGGSHELL_BREAKING); + gcsfx_play(SFX_11_WOOD_BREAKING_1); + marker_despawn(marker); break; } } -void func_802D3CC8(ActorMarker *marker){ - func_802D31AC(marker, NULL); +// unused +void code_4C020_unusedBreakableObjectSfx(ActorMarker *marker){ + code_4C020_breakableObjectSfx(marker, NULL); } // used as init function void func_802D3CE8(Actor *this){ if(!this->initialized){ - marker_setCollisionScripts(this->marker, NULL, func_802D3138, func_802D31AC); - this->marker->propPtr->unk8_3 = true; - this->initialized = true; + marker_setCollisionScripts(this->marker, NULL, func_802D3138, code_4C020_breakableObjectSfx); + this->marker->propPtr->unk8_3 = TRUE; + this->initialized = TRUE; + if (port_breakable_isBroken((s32)gsworld_getMap(), this->marker->id, (s32)this->position[0], + (s32)this->position[1], (s32)this->position[2])) { + marker_despawn(this->marker); + } + } +} + +extern ActorArray *suBaddieActorArray; + +// fieldSel picks between two markers sharing an id: 0 = any, 1 = actorTypeSpecificField==1, 2 = !=1. +typedef struct { + s16 flag; + s16 markerId; + s8 fieldSel; +} LairBreakable; + +static const LairBreakable D_lairBreakables[] = { + { FILEPROG_A5_LAIR_CRYPT_GATE_OPEN, 0x17D, 0 }, + { FILEPROG_C2_GRATE_TO_RBB_PUZZLE_OPEN, 0x11A, 0 }, + { FILEPROG_C3_ICE_BALL_TO_CHEATO_BROKEN, 0x11E, 0 }, + { FILEPROG_C4_STATUE_EYE_BROKEN, MARKER_121_GLASS_EYE, 0 }, + { FILEPROG_C5_RAREWARE_BOX_BROKEN, 0x11F, 0 }, + { FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN, MARKER_109_BREAKABLE_BRICK_WALL, 1 }, + { FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN, MARKER_109_BREAKABLE_BRICK_WALL, 2 }, + { FILEPROG_CA_COBWEB_BLOCKING_PURPLE_CAULDRON_BROKEN, MARKER_225_BREAKABLE_WALL_COBWEB, 0 }, + { FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN, MARKER_224_BREAKABLE_FLOOR_COBWEB, 1 }, + { FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN, MARKER_224_BREAKABLE_FLOOR_COBWEB, 2 }, + { FILEPROG_CD_GRATE_TO_WATER_SWITCH_3_OPEN, 0x118, 0 }, + { FILEPROG_CE_GRATE_TO_MMM_PUZZLE_OPEN, 0x119, 0 }, +}; + +void port_breakable_remoteBreak(s32 progressFlag) { + s32 i; + s16 markerId = -1; + s8 fieldSel = 0; + + for (i = 0; i < (s32) (sizeof(D_lairBreakables) / sizeof(D_lairBreakables[0])); i++) { + if (D_lairBreakables[i].flag == progressFlag) { + markerId = D_lairBreakables[i].markerId; + fieldSel = D_lairBreakables[i].fieldSel; + break; + } + } + if (markerId < 0 || suBaddieActorArray == NULL) { + return; + } + for (i = 0; i < suBaddieActorArray->cnt; i++) { + Actor *actor = &suBaddieActorArray->data[i]; + if (actor->marker == NULL || actor->marker->id != markerId) { + continue; + } + if ((fieldSel == 1 && actor->actorTypeSpecificField != 1) || + (fieldSel == 2 && actor->actorTypeSpecificField == 1)) { + continue; + } + code_4C020_breakableObjectSfx(actor->marker, NULL); + return; + } +} + +void port_breakable_remoteBreakAt(s32 markerId, s32 x, s32 y, s32 z) { + s32 i; + + if (suBaddieActorArray == NULL) { + return; + } + for (i = 0; i < suBaddieActorArray->cnt; i++) { + Actor *actor = &suBaddieActorArray->data[i]; + if (actor->marker == NULL || actor->marker->id != markerId) { + continue; + } + if ((s32)actor->position[0] != x || (s32)actor->position[1] != y || (s32)actor->position[2] != z) { + continue; + } + code_4C020_breakableObjectSfx(actor->marker, NULL); + return; } } -void func_802D3D54(Actor *this){ +static bool port_breakable_survivesBreak(s32 markerId) { + switch (markerId) { + case MARKER_34_CEMETARY_POT: // flowers + case MARKER_66_ORANGE_PAD: // stays, marked hit + return TRUE; + default: + return FALSE; + } +} + +// [port] Iterates backward: despawn swap-removes from the end. +void port_breakable_despawnBrokenRestores(s32 map) { + s32 i; + + if (suBaddieActorArray == NULL) { + return; + } + for (i = suBaddieActorArray->cnt - 1; i >= 0; i--) { + Actor *actor = &suBaddieActorArray->data[i]; + if (actor->marker == NULL || actor->despawn_flag) { + continue; + } + if (port_breakable_survivesBreak(actor->marker->id)) { + continue; + } + if (port_breakable_isBroken(map, actor->marker->id, (s32)actor->position[0], (s32)actor->position[1], + (s32)actor->position[2])) { + marker_despawn(actor->marker); + } + } +} + +s32 port_cutsceneWarp_getReturnMap(void) { + return D_80367694; +} + +void chMMMBreakableWooden_update(Actor *this){ func_802D3CE8(this); } @@ -377,8 +548,8 @@ void func_802D3D74(Actor *this){ actor_collisionOff(this); } -void func_802D3DA4(Actor *this) { - f32 sp24[3]; +void gWorldExitPad_update(Actor *this) { + f32 player_position[3]; s32 phi_v0; // [port] anti-tamper: dereferences raw N64 physical address 0x22C — crashes on PC @@ -394,20 +565,29 @@ void func_802D3DA4(Actor *this) { this->marker->propPtr->unk8_3 = true; this->unk38_31 = 0; } - player_getPosition(sp24); - phi_v0 = ((this->position[1] - 5.0f) <= sp24[1]) && (sp24[1] <= (this->position[1] + 30.0f)) - && (((sp24[0] - this->position[0])*(sp24[0] - this->position[0]) + (sp24[2] - this->position[2])*(sp24[2] - this->position[2])) < 3025.0f); + player_getPosition(player_position); + phi_v0 = + ( + (this->position[1] - 5.0f) <= player_position[1]) + && (player_position[1] <= (this->position[1] + 30.0f) + ) + && (( + (player_position[0] - this->position[0]) + * (player_position[0] - this->position[0]) + + (player_position[2] - this->position[2]) + * (player_position[2] - this->position[2]) + ) < 3025.0f); if ((this->unk38_31 == 0) && (phi_v0 == 0)) { this->unk38_31 = 1; } if ((this->unk38_31 == 1) && (phi_v0 == 1) - && func_8028F20C() && (func_8028F66C(BS_INTR_37) == 2)) { + && player_isStableWithExtraSteps() && (func_8028F66C(BS_INTR_37) == 2)) { this->unk38_31 = 2; } } -Actor *func_802D3F48(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *gWorldExitPad_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ s32 phi_s2; Actor *this; s32 i; @@ -415,12 +595,12 @@ Actor *func_802D3F48(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ this = marker_getActor(marker); phi_s2 = this->actorTypeSpecificField; for(i = 0; i < 9; i++){ - func_8033A45C(i + 1, i+1 == phi_s2); + modelRender_setAppendageVisibility(i + 1, i + 1 == phi_s2); } return actor_drawFullDepth(marker, gfx, mtx, vtx); } -void func_802D3FD4(Actor *this){ +void chSnsEgg_update(Actor *this){ if(!this->initialized){ this->initialized = true; func_802D3CE8(this); @@ -474,21 +654,21 @@ void func_802D3FD4(Actor *this){ } } -Actor *func_802D41C4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - s32 sp2C; +Actor *chSnsEgg_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + s32 actor_type_specific_field; Actor *this; s32 i; this = marker_getActor(marker); - sp2C = this->actorTypeSpecificField; + actor_type_specific_field = this->actorTypeSpecificField; for(i = 0; i < 6; i++){ - func_8033A45C(i+1, false); + modelRender_setAppendageVisibility(i + 1, FALSE); } - func_8033A45C(sp2C, true); + modelRender_setAppendageVisibility(actor_type_specific_field, TRUE); return actor_drawFullDepth(marker, gfx, mtx, vtx); } -void func_802D4250(Actor *this){ +void chIceKey_update(Actor *this){ if(!this->initialized){ this->initialized = true; func_802D3CE8(this); @@ -508,8 +688,7 @@ void func_802D4250(Actor *this){ bool func_802D42F8(Actor *this) { s32 i; - for(i = 0; D_803679B0[i] != -1 && this->actorTypeSpecificField != D_803679B0[i]; i+=2){ - } + for(i = 0; D_803679B0[i] != -1 && this->actorTypeSpecificField != D_803679B0[i]; i+=2){} if (D_803679B0[i] == -1) { return false; @@ -520,10 +699,10 @@ bool func_802D42F8(Actor *this) { } -void func_802D4388(Actor *this){ +void chMumboSwitch_update(Actor *this){ func_802D3CE8(this); this->unk38_0 = BOOL(gsworld_getMap() == MAP_7A_GL_CRYPT || item_getCount(ITEM_1C_MUMBO_TOKEN) >= this->actorTypeSpecificField || func_802D42F8(this)); - mapSpecificFlags_set(0x1F, (func_8028F20C() && func_8028FB48(0x78000000)) || player_movementGroup() == BSGROUP_D_TRANSFORMING); + mapSpecificFlags_set(0x1F, (player_isStableWithExtraSteps() && func_8028FB48(0x78000000)) || player_movementGroup() == BSGROUP_D_TRANSFORMING); switch(this->state){ case 0x12: //L802D4468 if(this->unk38_0 && mapSpecificFlags_get(0x1F)){ @@ -555,11 +734,11 @@ void func_802D4388(Actor *this){ mapSpecificFlags_set(0x1F, false); } -Actor *func_802D4588(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { +Actor *chMumboSwitch_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 phi_a1; phi_a1 = (marker_getActor(marker)->unk38_0) ? ((globalTimer_getTime() & 4) != 0) ? 1 : 2 : 2; - func_8033A45C(1, phi_a1); + modelRender_setAppendageVisibility(1, phi_a1); return actor_draw(marker, gfx, mtx, vtx); } @@ -576,7 +755,7 @@ void func_802D4614(enum map_e map_id){ timedFunc_set_2(1.0f, (GenFunction_2) func_8031CC40, map_id, 2); } -void func_802D4680(Actor *this){ +void chFFTeleportPad_Update(Actor *this){ f32 sp1C[3]; player_getPosition(sp1C); @@ -588,7 +767,7 @@ void func_802D4680(Actor *this){ } break; case 1: - if(ml_vec3f_horizontal_distance_zero_likely(this->position, sp1C) < 150.0f && func_8028F20C()){ + if(ml_vec3f_horizontal_distance_zero_likely(this->position, sp1C) < 150.0f && player_isStableWithExtraSteps()){ if(player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT){ if(gsworld_getMap() == MAP_8E_GL_FURNACE_FUN){ volatileFlag_set(VOLATILE_FLAG_0_IN_FURNACE_FUN_QUIZ, 0); @@ -684,39 +863,39 @@ void func_802D4AC0(Actor *this, s32 arg1, enum file_progress_e arg2) { } -void func_802D4B94(Actor *this){ +void chMMWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000b6, FILEPROG_18_MM_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4BBC(Actor *this){ +void chCCWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000bc, FILEPROG_9A_CC_WITCH_SWITCH_PRESSED); } -void func_802D4BE4(Actor *this){ +void chBGSWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000bd, FILEPROG_9F_BGS_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4C0C(Actor *this){ +void chGVWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000be, FILEPROG_A0_GV_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4C34(Actor *this){ +void chMMMWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000b7, FILEPROG_19_MMM_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4C5C(Actor *this){ +void chTTCWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000b8, FILEPROG_1A_TTC_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4C84(Actor *this){ +void chRBBWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000b9, FILEPROG_1C_RBB_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4CAC(Actor *this){ +void chCCWWitchSwitch_update(Actor *this){ func_802D4AC0(this, 0x4000ba, FILEPROG_46_CCW_WITCH_SWITCH_JIGGY_PRESSED); } -void func_802D4CD4(Actor *this){ +void chFPWitchSwitch_update(Actor *this){ if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ if(maSlalom_isActive()){ this->unk58_0 = false; @@ -803,8 +982,8 @@ void func_getCameraViewFromLevel(enum map_e map_id, s32 arg1, bool arg2) { } -void func_802D5140(ActorMarker *caller, enum asset_e text_id, s32 arg2){ - itemscore_noteScores_get(volatileFlag_getN(VOLATILE_FLAG_19_CURRENT_LEVEL_ID, 4)); +s32 func_802D5140(ActorMarker *caller, enum asset_e text_id, s32 arg2){ + return itemscore_noteScores_get(volatileFlag_getN(VOLATILE_FLAG_19_CURRENT_LEVEL_ID, 4)); } void func_802D5178(s32 arg0, enum file_progress_e arg1, s32 arg2, enum map_e arg3, s32 arg4, s32 arg5, enum actor_e arg6, s32 arg7){ @@ -823,6 +1002,9 @@ void func_802D520C(Gfx **gfx, Mtx **mtx, Vtx **vtx){ } } +// [port] Map the lair water was last levelled for, so re-entry snaps instead of ramping. +static s32 sLairWaterMap = -1; + void func_802D5260(void) { s32 sp3C; Struct70s *sp38; @@ -835,6 +1017,7 @@ void func_802D5260(void) { : -1; if (sp3C == -1) { + sLairWaterMap = -1; // [port] see above levelSpecificFlags_set(LEVEL_FLAG_3C_LAIR_UNKNOWN, false); fileProgressFlag_set(FILEPROG_26_WATER_SWITCH_3_PRESSED, false); fileProgressFlag_set(FILEPROG_27_LAIR_WATER_LEVEL_3, false); @@ -846,7 +1029,7 @@ void func_802D5260(void) { && !levelSpecificFlags_get(LEVEL_FLAG_3D_LAIR_UNKNOWN) && !levelSpecificFlags_get(LEVEL_FLAG_3C_LAIR_UNKNOWN) ) { - func_802D68F0(30); + code_4C020_setHourglassTimer(30); item_set(ITEM_6_HOURGLASS, true); levelSpecificFlags_set(LEVEL_FLAG_3D_LAIR_UNKNOWN, true); } @@ -881,14 +1064,27 @@ void func_802D5260(void) { if (levelSpecificFlags_get(LEVEL_FLAG_3C_LAIR_UNKNOWN) != false) { sp34 = D_803679C8[sp3C].unk6 + D_803676A4; } else { - sp34 = ((s16 *)&D_803679C8[sp3C])[(fileProgressFlag_get(FILEPROG_27_LAIR_WATER_LEVEL_3)) ? 3 - : (fileProgressFlag_get(FILEPROG_25_LAIR_WATER_LEVEL_2)) ? 2 - : (fileProgressFlag_get(FILEPROG_23_LAIR_WATER_LEVEL_1)) ? 1 - : 0]; + s32 lvl = (fileProgressFlag_get(FILEPROG_27_LAIR_WATER_LEVEL_3)) ? 3 + : (fileProgressFlag_get(FILEPROG_25_LAIR_WATER_LEVEL_2)) ? 2 + : (fileProgressFlag_get(FILEPROG_23_LAIR_WATER_LEVEL_1)) ? 1 + : 0; + lvl = port_lairWater_targetLevel(gsworld_getMap(), lvl); + sp34 = ((s16 *)&D_803679C8[sp3C])[lvl]; + } + s32 curMap = gsworld_getMap(); + if (sLairWaterMap != curMap || levelSpecificFlags_get(LEVEL_FLAG_3C_LAIR_UNKNOWN)) { + sLairWaterMap = curMap; + } else { + f32 curY = sp38->type_6D.unk8; + f32 step = 240.0f * time_getDelta(); + f32 diff = sp34 - curY; + if (diff > step) sp34 = curY + step; + else if (diff < -step) sp34 = curY - step; + // within a step of the target: let sp34 stand. } func_8034DEB4(&sp38->type_6D, sp34); player_getPosition(sp28); - + fxRipple_802F363C(sp34 + ((sp3C != -1) ? (D_803679E0[sp3C] + ((sp3C == 2) ? (6600.0f < sp28[0]) ? -200 : 0 : 0)) : 0)); } } @@ -1043,7 +1239,7 @@ void func_802D5628(void){ func_802D5178(LEVEL_FLAG_22_MMM_OPEN, 0x2E, 0x36, MAP_75_GL_MMM_LOBBY, 0xC, 0x6, ACTOR_228_MMM_ENTRANCE_DOOR, 0xA); func_802D5178(LEVEL_FLAG_24_CCW_OPEN, 0x30, 0x37, MAP_79_GL_CCW_LOBBY, 0xF, 0xB, ACTOR_234_CCW_ENTRANCE_DOOR, 0xA); func_802D5178(LEVEL_FLAG_20_FP_OPEN, 0x2C, 0x38, MAP_6F_GL_FP_LOBBY, 0x11, 0xA, ACTOR_235_FP_ENTRANCE_DOOR_LEFT, 0xA); - func_802D5178(LEVEL_FLAG_3F_LAIR_GRUNTY_DOOR_OPEN, 0xE2, 0x40, MAP_93_GL_DINGPOT, 0x10, 0xA, ACTOR_2E5_DOOR_OF_GRUNTY, 0x28); + func_802D5178(LEVEL_FLAG_3F_LAIR_GRUNTY_DOOR_OPEN, 0xE2, 0x40, MAP_93_GL_DINGPOT, 0x10, 0xA, ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE, 0x28); if(volatileFlag_get(VOLATILE_FLAG_18)){ if(!fileProgressFlag_get(FILEPROG_99_PAST_50_NOTE_DOOR_TEXT)){ gcdialog_showDialogConditional(0xF75, 0xE, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker*,s32,s32))func_802D5140); @@ -1121,11 +1317,13 @@ int func_802D60C4(void){ } void func_802D6114(void){ - s32 sp24; + s32 sp24; s32 sp20; + s32 camScript; sp24 = D_80367694;\ sp20 = D_80367698; + camScript = D_80367688; if(D_8036769C) fileProgressFlag_set(D_8036769C, true); func_802D6344(); @@ -1142,6 +1340,10 @@ void func_802D6114(void){ else{//L802D61DC func_80347A14(1); gcpausemenu_80314AC8(1); + // [port] Anchor: exit the camera manually; 0x30 (MM) and 0x40 (Door of Grunty) schedule their own exit. + if (camScript != 0x30 && camScript != 0x40) { + ncStaticCamera_exit(); + } } } @@ -1164,6 +1366,8 @@ void func_802D6264(f32 delay, enum map_e map_id, s32 arg2, s32 arg3, s32 arg4, e D_8036769C = arg5; D_803676A0 = 0; + port_lairWater_onRiseTrigger(map_id, arg5); + if(map_id != D_80367694){ timedFunc_set_1(delay, (GenFunction_1) func_802D61FC, map_id); } @@ -1229,7 +1433,7 @@ void func_802D6494(void){ if( (!D_80367684 || (D_80367684 && (gsworld_getMap() == D_80367684))) ){ switch(D_803676A0){ - case ACTOR_2E5_DOOR_OF_GRUNTY: + case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE: break; case ACTOR_20E_MM_ENTRANCE_DOOR:// L802D6510 FUNC_8030E624(SFX_6B_LOCKUP_OPENING, 0.6f, 32000); @@ -1348,7 +1552,7 @@ int func_802D68B4(void){ //BREAK???? //set_hourglass_timer_seconds -void func_802D68F0(s32 seconds){ +void code_4C020_setHourglassTimer(s32 seconds){ item_set(ITEM_0_HOURGLASS_TIMER, seconds*60 - 1); } diff --git a/src/core2/quiz/minigamemanager.c b/src/core2/quiz/minigame.c similarity index 98% rename from src/core2/quiz/minigamemanager.c rename to src/core2/quiz/minigame.c index 64bac6e59..f757868dc 100644 --- a/src/core2/quiz/minigamemanager.c +++ b/src/core2/quiz/minigame.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/minigame.c #include #include "functions.h" #include "variables.h" @@ -109,7 +110,7 @@ void __chMinigame_textCallback1(ActorMarker *marker, enum asset_e text_id, s32 a void __chMinigame_transformToCroc(ActorMarker *marker, enum asset_e text_id, s32 arg2){ if(arg2 == 1){ - func_8028FB88(TRANSFORM_5_CROC); + player_transform(TRANSFORM_5_CROC); } } diff --git a/src/core2/quiz/questionmanager.c b/src/core2/quiz/questionmanager.c index 98c01add9..1fcac24dc 100644 --- a/src/core2/quiz/questionmanager.c +++ b/src/core2/quiz/questionmanager.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_91E10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/quiz/bitfield.c b/src/core2/quiz/quizquestionaskedbitfield.c similarity index 81% rename from src/core2/quiz/bitfield.c rename to src/core2/quiz/quizquestionaskedbitfield.c index cd7d27584..466c4a9d7 100644 --- a/src/core2/quiz/bitfield.c +++ b/src/core2/quiz/quizquestionaskedbitfield.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/quizquestionaskedbitfield.c #include #include "functions.h" #include "variables.h" @@ -9,7 +10,7 @@ u8* quizQuestionAskedBitfield; /* .code */ bool quizQuestionAskedBitfield_get(s32 index){ - return bitfield_get_bit(quizQuestionAskedBitfield, index); + return bitfieldarray_getBit(quizQuestionAskedBitfield, index); } void quizQuestionAskedBitfield_free(void){ @@ -26,7 +27,7 @@ void quizQuestionAskedBitfield_init(void){ } void quizQuestionAskedBitfield_set(s32 index, bool value){ - bitfield_set_bit(quizQuestionAskedBitfield, index, value); + bitfieldarray_setBit(quizQuestionAskedBitfield, index, value); } void quizQuestionAskedBitfield_defrag(void){ diff --git a/src/core2/quiz/storage.c b/src/core2/quiz/storage.c index 1bface1cc..34b7d3cc4 100644 --- a/src/core2/quiz/storage.c +++ b/src/core2/quiz/storage.c @@ -1,8 +1,9 @@ +// BanjoDecomp: core2/code_C9E70.c #include #include "functions.h" #include "variables.h" -#include "core2/quiz_storage.h" +#include "core2/quiz/storage.h" extern struct FF_StorageStruct *ffStorage; diff --git a/include/core2/quiz_storage.h b/src/core2/quiz/storage.h similarity index 85% rename from include/core2/quiz_storage.h rename to src/core2/quiz/storage.h index 039ff0c82..300fe5e03 100644 --- a/include/core2/quiz_storage.h +++ b/src/core2/quiz/storage.h @@ -1,5 +1,9 @@ -#ifndef __CORE2_QUIZ_STORAGE_H__ -#define __CORE2_QUIZ_STORAGE_H__ +// BanjoDecomp: core2/code_C9E70.h +#ifndef BANJO_KAZOOIE_CODE_C9E70_H +#define BANJO_KAZOOIE_CODE_C9E70_H + +#ifndef __CORE2_C9E70_H__ +#define __CORE2_C9E70_H__ #include #include "structs.h" @@ -59,8 +63,8 @@ struct FF_StorageStruct { /* 08 */ s16 currentTileId; /* 0A */ u8 currFfMode; /* 0B */ u8 ffQuestionType; - /* 0C */ u8 questionTypeTableIndex; - /* 0D */ u8 questionAssetIndex; + /* 0C */ u8 questionTypeTableIndex; // Question Type Index + /* 0D */ u8 questionAssetIndex; // Question Asset Id /* 0E */ s8 unkE; /* 0F */ s8 unkF; @@ -90,3 +94,5 @@ struct FF_StorageStruct { /* 48 */ struct FF_StorageStruct_48 *unk48; }; // 0x4C #endif + +#endif // BANJO_KAZOOIE_CODE_C9E70_H diff --git a/src/core2/savedata.c b/src/core2/savedata.c index e5c89ed91..f35e6d712 100644 --- a/src/core2/savedata.c +++ b/src/core2/savedata.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B5040.c #include #include "core1/core1.h" #include "functions.h" @@ -386,7 +387,7 @@ void saveData_load(void *savedata_){ func_8033C4E4((u8*)savedata); __savedata_load_abilities((u8*)savedata); for(i = 0; D_80370A20[i].unk0 != -1; i++){ - volatileFlag_set(D_80370A20[i].unk0, fileProgressFlag_get(D_80370A20[i].unk2)); + volatileFlag_setEx(D_80370A20[i].unk0, fileProgressFlag_get(D_80370A20[i].unk2), 0); } CALL_EVENT(OnSaveLoad, savedata); } @@ -395,7 +396,7 @@ void saveData_create(void *savedata_){ SaveData *savedata = (SaveData *)savedata_; int i; for(i = 0; D_80370A20[i].unk0 != -1; i++){ - fileProgressFlag_set(D_80370A20[i].unk2, volatileFlag_get(D_80370A20[i].unk0)); + fileProgressFlag_setEx(D_80370A20[i].unk2, volatileFlag_get(D_80370A20[i].unk0), 0); } savedata_clear((u8*)savedata); __savedata_save_magic((u8*)savedata); diff --git a/src/core2/scorequeue/drawui_air.c b/src/core2/scorequeue/airscore.c similarity index 99% rename from src/core2/scorequeue/drawui_air.c rename to src/core2/scorequeue/airscore.c index b45bde3c4..9c37b1e4c 100644 --- a/src/core2/scorequeue/drawui_air.c +++ b/src/core2/scorequeue/airscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/airscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/drawui_stub.c b/src/core2/scorequeue/common1score.c similarity index 91% rename from src/core2/scorequeue/drawui_stub.c rename to src/core2/scorequeue/common1score.c index bdee37f9a..677f4b307 100644 --- a/src/core2/scorequeue/drawui_stub.c +++ b/src/core2/scorequeue/common1score.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/common1score.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/drawui_sprites.c b/src/core2/scorequeue/common2score.c similarity index 97% rename from src/core2/scorequeue/drawui_sprites.c rename to src/core2/scorequeue/common2score.c index ba439e554..53d02db77 100644 --- a/src/core2/scorequeue/drawui_sprites.c +++ b/src/core2/scorequeue/common2score.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/common2score.c #include #include "core1/core1.h" #include "functions.h" @@ -225,7 +226,7 @@ void fxcommon2score_update(s32 arg0, struct8s * arg1){ phi_f16 = 0.333f; } if(arg0 < 6){ - if(item_getCount(arg0) < 30){ + if(item_getCount(arg0) < VER_SELECT(30, 25, 0, 0)){ arg1->unk28 |= 8; } else{ @@ -234,11 +235,11 @@ void fxcommon2score_update(s32 arg0, struct8s * arg1){ } if((arg1->unk28 & 4) == 0){ tmpf = arg1->unk2C; - arg1->unk60 = time_getDelta() * (arg1->unk34 * arg1->unk30) * 60.0f * phi_f16 + arg1->unk60; + arg1->unk60 = time_getDelta() * (arg1->unk34 * arg1->unk30) * VER_SELECT(60.0f, 50.0f, 0, 0) * phi_f16 + arg1->unk60; if(arg1->unk2C <= arg1->unk60){ if(arg1->unk28 & 1){ arg1->unk34 *= -1.0f; - arg1->unk60 -= two* arg1->unk30 * time_getDelta() * 60.0f; + arg1->unk60 -= two* arg1->unk30 * time_getDelta() * VER_SELECT(60.0f, 50.0f, 0, 0); } else{ arg1->unk60 -= arg1->unk2C; @@ -252,7 +253,7 @@ void fxcommon2score_update(s32 arg0, struct8s * arg1){ if(arg1->unk60 < 0.0){ if(arg1->unk28 & 1){ arg1->unk34 *= -1.0f; - arg1->unk60 += two * arg1->unk30 * time_getDelta() * 60.0f; + arg1->unk60 += two * arg1->unk30 * time_getDelta() * VER_SELECT(60.0f, 50.0f, 0, 0); } else{ arg1->unk60 += arg1->unk2C; @@ -281,7 +282,7 @@ void fxcommon2score_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **m } } if(item_id < 6){ - sp38 = ((sp38)? 1: 0) + sp38/60; + sp38 = ((sp38)? 1: 0) + sp38/FRAMERATE; }//L802FDBA8 if(item_id == ITEM_1B_VILE_VILE_SCORE && 9 < sp38){ sp34 = -16.0f; diff --git a/src/core2/scorequeue/drawui_models.c b/src/core2/scorequeue/common3score.c similarity index 89% rename from src/core2/scorequeue/drawui_models.c rename to src/core2/scorequeue/common3score.c index df0f941ad..e63b6e40b 100644 --- a/src/core2/scorequeue/drawui_models.c +++ b/src/core2/scorequeue/common3score.c @@ -1,13 +1,15 @@ +// BanjoDecomp: core2/fx/common3score.c #include #include "core1/core1.h" #include "functions.h" #include "port/Patches/Patches.h" #include "variables.h" #include "port/Engine.h" +#include "port/Interpolation/FrameInterpolation.h" -extern f32 vtxList_getGlobalNorm(BKVertexList *); -extern void func_80253208(Gfx **gdl, s32 x, s32 y, s32 w, s32 h, void *color_buffer); + +extern void depthbuffer_clearRegion(Gfx **gdl, s32 x, s32 y, s32 w, s32 h, void *color_buffer); extern f32 func_802FB0E4(struct8s*); @@ -192,6 +194,7 @@ void fxcommon3score_draw(enum item_e item_id, void *arg1, Gfx **gfx, Mtx **mtx, sp40 = func_802FB0E4(arg1)*a1->unk54 + a1->unk34; if(a1->model != NULL && func_802FB0D4(arg1)){ + FrameInterpolation_RecordOpenChild("score_model", (uintptr_t)item_id); draw_x = a1->unk30 + port_hudOrthoShift(a1->unk30); a1->value_string[0] = '\0'; strIToA(a1->value_string, itemPrint_getValue(item_id)); @@ -211,11 +214,15 @@ void fxcommon3score_draw(enum item_e item_id, void *arg1, Gfx **gfx, Mtx **mtx, if(a1->unk6C == 0.0f){ a1->unk6C = 1.1*(vtxList_getGlobalNorm(modelbin_getVtxList(a1->model)) * a1->unk3C); } - func_80253208(gfx, draw_x - a1->unk6C, sp40 - a1->unk6C, 2*a1->unk6C, 2*a1->unk6C, gFramebuffers[getActiveFramebuffer()]); + // [port] Clear against draw_x, not unk30: the model is drawn at the widescreen-anchored + // position, so the depth hole has to move with it or the icon gets z-clipped by the world. + // depthbuffer_clearRegion(gfx, a1->unk30 - a1->unk6C, sp40 - a1->unk6C, 2*a1->unk6C, 2*a1->unk6C, gFramebuffers[getActiveFramebuffer()]); + depthbuffer_clearRegion(gfx, draw_x - a1->unk6C, sp40 - a1->unk6C, 2*a1->unk6C, 2*a1->unk6C, gFramebuffers[getActiveFramebuffer()]); if(a1->anim_ctrl != NULL){ anctrl_drawSetup(a1->anim_ctrl, sp5C, 1); } modelRender_draw(gfx, mtx, sp5C, sp68, a1->unk3C*sp3C, sp44, a1->model); + FrameInterpolation_RecordCloseChild(); }//L80300BA4 } diff --git a/src/core2/scorequeue/dispatch.c b/src/core2/scorequeue/dispatch.c index fc9d41a8d..83d83a796 100644 --- a/src/core2/scorequeue/dispatch.c +++ b/src/core2/scorequeue/dispatch.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_74090.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/drawui_health.c b/src/core2/scorequeue/healthscore.c similarity index 99% rename from src/core2/scorequeue/drawui_health.c rename to src/core2/scorequeue/healthscore.c index 3673b3feb..5796e717e 100644 --- a/src/core2/scorequeue/drawui_health.c +++ b/src/core2/scorequeue/healthscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/healthscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/drawui_honeycarrier.c b/src/core2/scorequeue/honeycarrierscore.c similarity index 99% rename from src/core2/scorequeue/drawui_honeycarrier.c rename to src/core2/scorequeue/honeycarrierscore.c index 8ce9e90d4..e68b39820 100644 --- a/src/core2/scorequeue/drawui_honeycarrier.c +++ b/src/core2/scorequeue/honeycarrierscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/honeycarrierscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/drawui_jinjo.c b/src/core2/scorequeue/jinjoscore.c similarity index 99% rename from src/core2/scorequeue/drawui_jinjo.c rename to src/core2/scorequeue/jinjoscore.c index 3a613a4f6..f2c8486b6 100644 --- a/src/core2/scorequeue/drawui_jinjo.c +++ b/src/core2/scorequeue/jinjoscore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/jinjoscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/drawui_lives.c b/src/core2/scorequeue/lifescore.c similarity index 99% rename from src/core2/scorequeue/drawui_lives.c rename to src/core2/scorequeue/lifescore.c index b59a2139f..0dbf6df22 100644 --- a/src/core2/scorequeue/drawui_lives.c +++ b/src/core2/scorequeue/lifescore.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/fx/lifescore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/manager.c b/src/core2/scorequeue/manager.c index 6b6dfd362..2e62963f9 100644 --- a/src/core2/scorequeue/manager.c +++ b/src/core2/scorequeue/manager.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_73640.c #include #include "functions.h" #include "variables.h" @@ -190,13 +191,13 @@ void itemPrint_update(void) { } -void itemPrint_draw(Gfx **gdl, Mtx ** mptr, Vtx **vptr){ +void itemPrint_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 i; if(D_803810B0 && level_get() != LEVEL_D_CUTSCENE){ for(i = 0; i < 0x2C; i++){ if(!func_802E4A08() || i < 6){ if(func_802FB0D4(D_803692F8[i].unk14)){ - D_803692F8[i].unk8(i, D_803692F8[i].unk14, gdl, mptr, vptr); + D_803692F8[i].unk8(i, D_803692F8[i].unk14, gfx, mtx, vtx); } } } diff --git a/src/core2/scorequeue/queue_collectibles.c b/src/core2/scorequeue/queue_collectibles.c index 3089b0774..8c3f38467 100644 --- a/src/core2/scorequeue/queue_collectibles.c +++ b/src/core2/scorequeue/queue_collectibles.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_74910.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_honeycombs.c b/src/core2/scorequeue/queue_honeycombs.c index a4387833c..731c31de5 100644 --- a/src/core2/scorequeue/queue_honeycombs.c +++ b/src/core2/scorequeue/queue_honeycombs.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_74420.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_lives.c b/src/core2/scorequeue/queue_lives.c index f208e68bc..6422a6de6 100644 --- a/src/core2/scorequeue/queue_lives.c +++ b/src/core2/scorequeue/queue_lives.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_75E90.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_major_items.c b/src/core2/scorequeue/queue_major_items.c index 1d9ebc511..8a8ac6010 100644 --- a/src/core2/scorequeue/queue_major_items.c +++ b/src/core2/scorequeue/queue_major_items.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_74ED0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_notes.c b/src/core2/scorequeue/queue_notes.c index d16a25e5d..c6237e4e0 100644 --- a/src/core2/scorequeue/queue_notes.c +++ b/src/core2/scorequeue/queue_notes.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_74290.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_timers.c b/src/core2/scorequeue/queue_timers.c index 00ed40b63..af1211b4a 100644 --- a/src/core2/scorequeue/queue_timers.c +++ b/src/core2/scorequeue/queue_timers.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_75930.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_totals.c b/src/core2/scorequeue/queue_totals.c index 74f538ea2..7ee54a8c9 100644 --- a/src/core2/scorequeue/queue_totals.c +++ b/src/core2/scorequeue/queue_totals.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_75480.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/instruments.c b/src/core2/sfx/instruments.c index 4566c01bd..410004a40 100644 --- a/src/core2/sfx/instruments.c +++ b/src/core2/sfx/instruments.c @@ -1,12 +1,10 @@ +// BanjoDecomp: core2/code_AE290.c #include #include "functions.h" #include "variables.h" #include extern ALBank *music_get_sound_bank(void); -extern OSIoMesg *func_802405D0(void); -extern OSMesgQueue *func_802405C4(void); -extern ALHeap *func_802405B8(void); extern void func_80243070(void *arg0); extern u8 *soundfont1ctl_ROM_START; @@ -40,7 +38,7 @@ void sfxInstruments_init(void){ D_803835F0.unk4 = 0x100; D_803835F0.unk10 = 0x40; D_803835F0.unk8 = 0x18; - D_803835F0.unkC = func_802405B8(); + D_803835F0.unkC = audioManager_getALHeapInfo(); func_80243070(&D_803835F0); sfx_sound_bank = bnk; } diff --git a/src/core2/sfx/pitched.c b/src/core2/sfx/pitched.c index c70bb9b87..613667518 100644 --- a/src/core2/sfx/pitched.c +++ b/src/core2/sfx/pitched.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_599E0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/randompitch.c b/src/core2/sfx/randompitch.c index 2ed9a5317..333e5423a 100644 --- a/src/core2/sfx/randompitch.c +++ b/src/core2/sfx/randompitch.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_72B10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/sequenceindex.c b/src/core2/sfx/sequenceindex.c index 7f4298e94..b888aff1c 100644 --- a/src/core2/sfx/sequenceindex.c +++ b/src/core2/sfx/sequenceindex.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_857B0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/soundsource.c b/src/core2/sfx/soundsource.c index 088874b78..06f8c5e02 100644 --- a/src/core2/sfx/soundsource.c +++ b/src/core2/sfx/soundsource.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/ch/soundsource.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/source.c b/src/core2/sfx/source.c index 2b46b5988..3cd50ef42 100644 --- a/src/core2/sfx/source.c +++ b/src/core2/sfx/source.c @@ -1,7 +1,9 @@ +// BanjoDecomp: core2/code_85800.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +#include "port/ShipUtils.h" // gPortResetPending #include extern void func_80335394(intptr_t, f32); @@ -220,7 +222,7 @@ s32 func_8030CDE4(SfxSource *arg0){ f32 pad; viewport_getPosition_vec3f(sp44); - viewport_getLookbk_vector(sp38); + viewport_getLookVector(sp38); sp2C[0] = arg0->position[0] - sp44[0]; sp2C[1] = arg0->position[1] - sp44[1]; sp2C[2] = arg0->position[2] - sp44[2]; @@ -859,8 +861,12 @@ void sfxsource_play(enum sfx_e uid, s32 sampleRate){ func_8030D6C4(uid, 1.0f, sampleRate, 0, 2); } -void gcsfx_playAtSampleRate(enum sfx_e uid){ - sfxsource_play(uid, 0x7ff8); +void gcsfx_playAtSampleRate(enum sfx_e uid, s32 sampleRate){ + sfxsource_play(uid, sampleRate); +} + +void gcsfx_play(enum sfx_e uid){ + gcsfx_playAtSampleRate(uid, 0x7FF8); } void func_8030E560(enum sfx_e uid, s32 arg1){ diff --git a/src/core2/sfx/trackmanager.c b/src/core2/sfx/trackmanager.c index 155ddf472..e65939774 100644 --- a/src/core2/sfx/trackmanager.c +++ b/src/core2/sfx/trackmanager.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_9B650.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/sfx/volume.c b/src/core2/sfx/volume.c index 6fa3d6690..f775cf9c8 100644 --- a/src/core2/sfx/volume.c +++ b/src/core2/sfx/volume.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C8760.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/snacker_ctl.c b/src/core2/snackerctl.c similarity index 95% rename from src/core2/snacker_ctl.c rename to src/core2/snackerctl.c index 1f8b5bdb7..e016ff6bc 100644 --- a/src/core2/snacker_ctl.c +++ b/src/core2/snackerctl.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/snackerctl.c #include "core2/snackerctl.h" #include @@ -11,7 +12,7 @@ #define SNACKER_BB_DIALOG_0 VER_SELECT(0xe26, 0xa68, 0xa68, 0xa68) #define SNACKER_BB_DIALOG_1 VER_SELECT(0xe33, 0xa75, 0xa75, 0xa75) -void ncFirstPersonCamera_getZoomedInRotation(f32 *); +void ncba1p_getZoomedInRotation(f32 *); extern u8 D_8037DCCA; extern u8 D_8037DCCB; @@ -32,7 +33,7 @@ void snackerctl_reset(void){ static s32 __snackerctl_player_within_distance(f32 x, f32 z, f32 dist){ f32 player_position[3]; - _player_getPosition(player_position); + playerPosition_get(player_position); return ml_vec3f_point_within_horizontal_distance(player_position, x, z, dist); } @@ -40,7 +41,7 @@ static SnackerCtlState __snackerctl_update_ttc(void){ SnackerCtlState nextState = 0; f32 player_position[3]; - _player_getPosition(player_position); + playerPosition_get(player_position); if(player_isSwimming() || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)){ //(swimming || ???) if(player_position[1] < 600.0f && !__snackerctl_player_within_distance(2478.0f, 4586.0f, 1750.0f) //within 1750 of sandcastle center @@ -101,7 +102,7 @@ static SnackerCtlState _snackerctl_update_bottles_bonus(void){ chBottleBonusPuzzleIndex = 1; }//L8028A764 else if(jiggyscore_isCollected(0x10)){ - ncFirstPersonCamera_getZoomedInRotation(sp30); + ncba1p_getZoomedInRotation(sp30); if( (((D_8036361C[0] <= sp30[0])? (sp30[0] - D_8036361C[0]) : -(sp30[0] - D_8036361C[0])) < 4.0f) && (((D_8036361C[1] <= sp30[1])? (sp30[1] - D_8036361C[1]) : -(sp30[1] - D_8036361C[1])) < 20.0f) ){ diff --git a/src/core2/spawn_queue.c b/src/core2/spawnqueue.c similarity index 61% rename from src/core2/spawn_queue.c rename to src/core2/spawnqueue.c index d7a7aed28..2e039a1c8 100644 --- a/src/core2/spawn_queue.c +++ b/src/core2/spawnqueue.c @@ -1,11 +1,14 @@ +// BanjoDecomp: core2/spawnqueue.c #include #include "core1/core1.h" #include "functions.h" +#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "actor.h" #include "prop.h" #include "functions.h" #include "core2/ch/snacker.h" +#include "port/Patches/Patches.h" // port_getDrawDistanceLevel #include "port/Romhack/RomhackConfig.h" void spawnQueue_unlock(void); @@ -16,11 +19,11 @@ Actor *func_802D75B4(s32 *, s32, ActorInfo*, u32); Actor *func_802D7610(s32 *, s32, ActorInfo*, u32); Actor *chBottlesBonus_new(s32 *, s32, ActorInfo*, u32); -extern ActorInfo D_80365E58; //banjo.without_right_hand -extern ActorInfo D_80365EAC; //banjo.playing_gameboy -extern ActorInfo D_80365F00; //banjo.cooking -extern ActorInfo D_80365F60; -extern ActorInfo D_80365F84; //turbotrainers +extern ActorInfo gameSelect_banjoSleeping; //banjo.without_right_hand +extern ActorInfo gameSelect_banjoGameboy; //banjo.playing_gameboy +extern ActorInfo gameSelect_banjoCooking; //banjo.cooking +extern ActorInfo fxWadingBootsTouchSparkle; +extern ActorInfo fxTurboTrainersTouchSparkle; //turbotrainers extern ActorInfo D_80365FB0; //shrapnel extern ActorInfo chBubble; extern ActorInfo chBigbutt; //bigbutt @@ -35,8 +38,8 @@ extern ActorInfo D_803663D0; extern ActorInfo D_803663F4; extern ActorInfo chExtraLife; //extralife extern ActorInfo sumusicNote; //music_note -extern ActorInfo D_80366C80; //chhoneycarrier -extern ActorInfo D_80366CA4; //chhoney +extern ActorInfo chEmptyHoneycomb; //chhoneycarrier +extern ActorInfo chHoneycomb; //chhoney extern ActorInfo chTrainers; extern ActorInfo D_80366EF0; //large_shadow extern ActorInfo chShockJump; //chshockjump @@ -44,7 +47,7 @@ extern ActorInfo chFlightPad; //flight_pad extern ActorInfo chSnippet; //snippet extern ActorInfo chBlackSnippet; //black_snippet extern ActorInfo chMutieSnippet; //mutie_snippet -extern ActorInfo D_80367130; //buzzbomb +extern ActorInfo chBuzzbomb; //buzzbomb extern ActorInfo D_80367160; extern ActorInfo D_80367184; extern ActorInfo chJinjoBlue; //jingo_blue @@ -53,109 +56,109 @@ extern ActorInfo chJinjoYellow; //jingo_yellow extern ActorInfo chJinjoPink; //jingo_pink extern ActorInfo chJinjoOrange; //jingo_orange extern ActorInfo chBeehive; //chbeehive -extern ActorInfo D_80367310; //chswarm +extern ActorInfo chBeeSwarm; //chswarm extern ActorInfo D_80367390; //chwaterfallfx extern ActorInfo chShrapnelDescription; //scrapnel extern ActorInfo chGloop; //gloop -extern ActorInfo D_803674E0; //mumbo -extern ActorInfo D_80367530; //mumbo_token_sign.5 -extern ActorInfo D_80367554; //mumbo_toke_sign.10 -extern ActorInfo D_80367578; //mumbo_toke_sign.15 -extern ActorInfo D_8036759C; //mumbo_toke_sign.20 -extern ActorInfo D_803675C0; //mumbo_toke_sign.25 +extern ActorInfo chMumbo; //mumbo +extern ActorInfo chMumboSign5; //mumbo_token_sign.5 +extern ActorInfo chMumboSign10; //mumbo_toke_sign.10 +extern ActorInfo chMumboSign15; //mumbo_toke_sign.15 +extern ActorInfo chMumboSign20; //mumbo_toke_sign.20 +extern ActorInfo chMumboSign25; //mumbo_toke_sign.25 extern ActorInfo D_803675F0; extern ActorInfo D_80367760; extern ActorInfo D_80367784; -extern ActorInfo D_803677A8; //ice_key -extern ActorInfo D_803677CC; //mumbo_transform_pad -extern ActorInfo D_803677F0; -extern ActorInfo D_80367814; //SnS_egg -extern ActorInfo D_80367838; //level_entry_disk -extern ActorInfo D_8036785C; //witch_switch.mm; -extern ActorInfo D_80367880; //witch_switch.mmm -extern ActorInfo D_803678A4; //witch_switch.ttc -extern ActorInfo D_803678C8; //witch_switch.rbb -extern ActorInfo D_803678EC; //witch_switch.ccw -extern ActorInfo D_80367910; //witch_switch.fp -extern ActorInfo D_80367934; //witch_switch.cc -extern ActorInfo D_80367958; //witch_switch.bgs -extern ActorInfo D_8036797C; //witch_switch.gv -extern ActorInfo D_80367A20; //wading boots +extern ActorInfo chIceKey; //ice_key +extern ActorInfo chMumboSwitch; //mumbo_transform_pad +extern ActorInfo chFFTeleportPad; +extern ActorInfo chSnsEgg; //SnS_egg +extern ActorInfo gWorldExitPad; //level_entry_disk +extern ActorInfo chMMWitchSwitch; //witch_switch.mm; +extern ActorInfo chMMMWitchSwitch; //witch_switch.mmm +extern ActorInfo chTTCWitchSwitch; //witch_switch.ttc +extern ActorInfo chRBBWitchSwitch; //witch_switch.rbb +extern ActorInfo chCCWWitchSwitch; //witch_switch.ccw +extern ActorInfo chFPWitchSwitch; //witch_switch.fp +extern ActorInfo chCCWitchSwitch; //witch_switch.cc +extern ActorInfo chBGSWitchSwitch; //witch_switch.bgs +extern ActorInfo chGVWitchSwitch; //witch_switch.gv +extern ActorInfo chWadingBoots; //wading boots extern ActorInfo chBadShad; //chbadshad extern ActorInfo gDummyPlayerAnchorInfo; //dummy player anchor (port) extern ActorInfo D_80367AB0; extern ActorInfo D_80367AD4; extern ActorInfo D_80367AF8; extern ActorInfo D_80367B20; //chclimbbase -extern ActorInfo D_80367B80; //orange -extern ActorInfo D_80367BA4; //gold_bullion -extern ActorInfo D_80367BC8; -extern ActorInfo D_80367BEC; -extern ActorInfo D_80367C10; -extern ActorInfo D_80367C60; -extern ActorInfo D_80367C90; //spent_redfeather -extern ActorInfo D_80367CB4; //spent_goldfeather -extern ActorInfo D_80367D00; //egg -extern ActorInfo D_80367D24; //redfeather -extern ActorInfo D_80367D48; //goldfeather +extern ActorInfo chOrangeCollectible; //orange +extern ActorInfo chGoldBullion; //gold_bullion +extern ActorInfo chBluePresentCollectible; +extern ActorInfo chGreenPresentCollectible; +extern ActorInfo chRedPresentCollectible; +extern ActorInfo chPiranhaWaterParticles; +extern ActorInfo fxSpentRedFeather; //spent_redfeather +extern ActorInfo fxSpentGoldFeather; //spent_goldfeather +extern ActorInfo chBlueEgg; //egg +extern ActorInfo chRedFeather; //redfeather +extern ActorInfo chGoldFeather; //goldfeather extern ActorInfo gChMole; //bottles -extern ActorInfo D_80367E20; //chmolehill +extern ActorInfo chMolehill; //chmolehill extern ActorInfo D_80367E70; extern ActorInfo D_80367F30; -extern ActorInfo D_8036804C;//GAME_OVER -extern ActorInfo D_8036807C;//THE_END -extern ActorInfo D_803680AC;//player_KAZOOIE +extern ActorInfo gcGameOverSign;//GAME_OVER +extern ActorInfo gcTheEndSign;//THE_END +extern ActorInfo gcBanjoKazooieSign;//player_KAZOOIE extern ActorInfo chOverlayCopyrightDescription;//copyright_info -extern ActorInfo D_80368124;//PRESS_START -extern ActorInfo D_80368174;//NO_CONTROLLER) +extern ActorInfo chOverlayPressStart;//PRESS_START +extern ActorInfo chOverlayNoController;//NO_CONTROLLER) extern ActorInfo chBottlesBonusDescription; //jiggy_picture -extern ActorInfo D_8036833C; +extern ActorInfo chMumbosHandWithPicture; extern ActorInfo D_8036838C; -extern ActorInfo D_80368418; //banjos_hand_BB -extern ActorInfo D_80368450; //fire_sparkle -extern ActorInfo D_80368474; -extern ActorInfo D_80368498; -extern ActorInfo D_803684BC; //roysten -extern ActorInfo D_803684E0; //cuckoo_clock +extern ActorInfo chBottlesBonusCursor; //banjos_hand_BB +extern ActorInfo chFireSparkle; //fire_sparkle +extern ActorInfo chBanjoCurtains; +extern ActorInfo chBanjoHouseDoor; +extern ActorInfo chFishbowl; //roysten +extern ActorInfo chCuckooClock; //cuckoo_clock extern ActorInfo D_80368504; extern ActorInfo D_80368528; extern ActorInfo D_8036854C; extern ActorInfo D_80368570; -extern ActorInfo D_803685A0; //mumbotoken +extern ActorInfo chMumboToken; //mumbotoken extern ActorInfo chSnowman; //sirslush extern ActorInfo chSnowball; //snowball extern ActorInfo chSnowmanHat; //sir_slush_hat extern ActorInfo D_80372810; extern ActorInfo D_80372840; //grillchompa extern ActorInfo chClucker; //clucker -extern ActorInfo D_803728A0; //scarab +extern ActorInfo chScarabBeetle; //scarab extern ActorInfo chMinigame; //boombox -extern ActorInfo D_80372970; //leaf_particle -extern ActorInfo D_80372994; -extern ActorInfo D_803729B8; //rain -extern ActorInfo D_803729DC; -extern ActorInfo D_80372A00; //snow -extern ActorInfo D_80372A24; +extern ActorInfo leafEmitterCCWAutumn; //leaf_particle +extern ActorInfo leafEmitterCCWHub; +extern ActorInfo rainEmitterCCWSpring; //rain +extern ActorInfo rainEmitterCCWHub; +extern ActorInfo snowEmitterCCWWinter; //snow +extern ActorInfo snowEmitterCCWHub; extern ActorInfo D_80372A48; extern ActorInfo D_80372A6C; extern ActorInfo gChFireFxInfo; //fire extern ActorInfo gChDripsInfo;//water_drops extern ActorInfo chIcecubeA; extern ActorInfo chIcecubeB;//ice_cube -extern ActorInfo D_80372C18; //teehee +extern ActorInfo chTeeHee; //teehee extern ActorInfo chFlotsam; //floatsam extern ActorInfo D_80372D78; //limbo extern ActorInfo D_80372DF8; //grublin_hood extern ActorInfo chMumMum; //mummum -extern ActorInfo D_80372EE0; +extern ActorInfo chChumpFish; extern ActorInfo chTermite; //ticker extern ActorInfo D_80372FC0; extern ActorInfo D_80372FE4; extern ActorInfo gChBat; //nibbly extern ActorInfo chWhipcrack; -extern ActorInfo D_80373134; -extern ActorInfo D_80373158; -extern ActorInfo D_803731B0; +extern ActorInfo chBetaVent1; +extern ActorInfo chBetaVent2; +extern ActorInfo lairBottlesDialog; extern ActorInfo D_803732E0; extern ActorInfo D_80373DC0; @@ -179,18 +182,32 @@ u8 spawnQueueLength = 0; FunctionQueue *spawnQueue = NULL; /* .code */ -// [port] N64 used 15 entries. If this overflows, find the root cause — -// something is adding entries faster than they're being flushed. +// [port] N64 used 15 entries, sized for the N64's draw distance. +// Scales with the Draw Distance enhancement. #define SPAWN_QUEUE_DEFAULT_SIZE 15 #define SPAWN_QUEUE_GL_SIZE 50 +// [port] Capacity of the live allocation. +static u32 sSpawnQueueMax = 0; + static u32 __spawnQueue_getMax(void) { +#if 0 return (gsworld_getMap() == MAP_90_GL_BATTLEMENTS) ? SPAWN_QUEUE_GL_SIZE : SPAWN_QUEUE_DEFAULT_SIZE; +#endif + return sSpawnQueueMax; } void spawnQueue_malloc(void){ +#if 0 u32 tmp = __spawnQueue_getMax(); spawnQueue = (FunctionQueue *) bk_malloc(tmp * sizeof(FunctionQueue)); +#endif + u32 base = (gsworld_getMap() == MAP_90_GL_BATTLEMENTS) ? SPAWN_QUEUE_GL_SIZE : SPAWN_QUEUE_DEFAULT_SIZE; + // [port] The setting, not the render-time level: this runs during a map load, where + // port_getDrawDistanceLevel() clamps to 1x and would under-size the queue for the + // gameplay that follows. + sSpawnQueueMax = base * (u32) port_getDrawDistanceSetting(); + spawnQueue = (FunctionQueue *) bk_malloc(sSpawnQueueMax * sizeof(FunctionQueue)); } void spawnQueue_reset(void){ @@ -223,9 +240,9 @@ void spawnQueue_reset(void){ spawnableActorList_add(&D_803675F0, actor_new, ACTOR_FLAG_UNKNOWN_6); spawnableActorList_add(&chBigbutt, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25); spawnableActorList_add(&chSmallBull, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_8); - spawnableActorList_add(&D_803674E0, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); + spawnableActorList_add(&chMumbo, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chBeehive, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&D_80367310, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_17); + spawnableActorList_add(&chBeeSwarm, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_17); spawnableActorList_add(&D_80367390, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_19); spawnableActorList_add(&chJinjoYellow, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chJinjoOrange, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); @@ -234,12 +251,12 @@ void spawnQueue_reset(void){ spawnableActorList_add(&chJinjoGreen, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chJiggy, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21); spawnableActorList_add(&chJigsawDance, actor_new, ACTOR_FLAG_UNKNOWN_2); - spawnableActorList_add(&D_80367C60, actor_new, ACTOR_FLAG_UNKNOWN_2); - spawnableActorList_add(&D_80367A20, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_80366C80, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoneycarrier - spawnableActorList_add(&D_80366CA4, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoney + spawnableActorList_add(&chPiranhaWaterParticles, actor_new, ACTOR_FLAG_UNKNOWN_2); + spawnableActorList_add(&chWadingBoots, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chEmptyHoneycomb, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoneycarrier + spawnableActorList_add(&chHoneycomb, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoney spawnableActorList_add(&sumusicNote, actor_new, ACTOR_FLAG_UNKNOWN_21); //music_note - spawnableActorList_add(&D_80367D00, actor_new, ACTOR_FLAG_UNKNOWN_21); //egg + spawnableActorList_add(&chBlueEgg, actor_new, ACTOR_FLAG_UNKNOWN_21); //egg spawnableActorList_add(&D_80366340, func_802C8A54, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&D_80366364, func_802C8AA8, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&D_80366388, func_802C8AF8, ACTOR_FLAG_UNKNOWN_2); @@ -250,103 +267,102 @@ void spawnQueue_reset(void){ spawnableActorList_add(&D_80367AD4, func_802D75B4, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&D_80367AF8, func_802D7610, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&chTrainers, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_80365F60, actor_new, ACTOR_FLAG_UNKNOWN_2); - spawnableActorList_add(&D_80365F84, actor_new, ACTOR_FLAG_UNKNOWN_2); //turbotrainers + spawnableActorList_add(&fxWadingBootsTouchSparkle, actor_new, ACTOR_FLAG_UNKNOWN_2); + spawnableActorList_add(&fxTurboTrainersTouchSparkle, actor_new, ACTOR_FLAG_UNKNOWN_2); //turbotrainers spawnableActorList_add(&D_80367184, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&chExtraLife, actor_new, ACTOR_FLAG_UNKNOWN_21); //extralife spawnableActorList_add(&D_80365FB0, actor_new, ACTOR_FLAG_UNKNOWN_2); //shrapnel spawnableActorList_add(&chBadShad, actor_new, ACTOR_FLAG_UNKNOWN_2); //chbadshad - spawnableActorList_add(&gDummyPlayerAnchorInfo, actor_new, ACTOR_FLAG_UNKNOWN_2); //dummy player anchor - spawnableActorList_add(&D_803685A0, actor_new, ACTOR_FLAG_UNKNOWN_6); //mumbotoken + spawnableActorList_add(&chMumboToken, actor_new, ACTOR_FLAG_UNKNOWN_6); //mumbotoken spawnableActorList_add(&D_80367F30, actor_new, ACTOR_FLAG_UNKNOWN_10); spawnableActorList_add(&chBubble, actor_new, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&chGloop, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7); //gloop spawnableActorList_add(&chShockJump, actor_new, ACTOR_FLAG_NONE); //chshockjump spawnableActorList_add(&chFlightPad, actor_new, ACTOR_FLAG_NONE); //flight_pad - spawnableActorList_add(&D_80367D24, actor_new, ACTOR_FLAG_UNKNOWN_21); //redfeather - spawnableActorList_add(&D_80367D48, actor_new, ACTOR_FLAG_UNKNOWN_21); //goldfeather - spawnableActorList_add(&D_80367C90, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_redfeather - spawnableActorList_add(&D_80367CB4, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_goldfeather + spawnableActorList_add(&chRedFeather, actor_new, ACTOR_FLAG_UNKNOWN_21); //redfeather + spawnableActorList_add(&chGoldFeather, actor_new, ACTOR_FLAG_UNKNOWN_21); //goldfeather + spawnableActorList_add(&fxSpentRedFeather, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_redfeather + spawnableActorList_add(&fxSpentGoldFeather, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_goldfeather spawnableActorList_add(&gChMole, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); //bottles - spawnableActorList_add(&D_80367E20, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6); //chmolehill + spawnableActorList_add(&chMolehill, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6); //chmolehill spawnableActorList_add(&D_80373DC0, actor_new, ACTOR_FLAG_UNKNOWN_19); spawnableActorList_add(&D_80367E70, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&gChSnacker, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_16); //snacker spawnableActorList_add(&D_80366EF0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_17); //large_shadow spawnableActorList_add(&D_80367B20, actor_new, ACTOR_FLAG_UNKNOWN_7); //chclimbbase - spawnableActorList_add(&D_80367BA4, actor_new, ACTOR_FLAG_UNKNOWN_6); //gold_bullion - spawnableActorList_add(&D_80367B80, actor_new, ACTOR_FLAG_UNKNOWN_1); //orange - spawnableActorList_add(&D_80372970, actor_new, ACTOR_FLAG_UNKNOWN_7); //leaf_particle - spawnableActorList_add(&D_80372994, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_803729B8, actor_new, ACTOR_FLAG_UNKNOWN_7); //rain - spawnableActorList_add(&D_803729DC, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80372A00, actor_new, ACTOR_FLAG_UNKNOWN_7); //snow - spawnableActorList_add(&D_80372A24, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chGoldBullion, actor_new, ACTOR_FLAG_UNKNOWN_6); //gold_bullion + spawnableActorList_add(&chOrangeCollectible, actor_new, ACTOR_FLAG_UNKNOWN_1); //orange + spawnableActorList_add(&leafEmitterCCWAutumn, actor_new, ACTOR_FLAG_UNKNOWN_7); //leaf_particle + spawnableActorList_add(&leafEmitterCCWHub, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&rainEmitterCCWSpring, actor_new, ACTOR_FLAG_UNKNOWN_7); //rain + spawnableActorList_add(&rainEmitterCCWHub, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&snowEmitterCCWWinter, actor_new, ACTOR_FLAG_UNKNOWN_7); //snow + spawnableActorList_add(&snowEmitterCCWHub, actor_new, ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&D_80372A48, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&D_80372A6C, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&chMinigame, actor_new, ACTOR_FLAG_UNKNOWN_7); //boombox - spawnableActorList_add(&D_803677A8, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //ice_key - spawnableActorList_add(&D_80367814, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //SnS_egg + spawnableActorList_add(&chIceKey, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //ice_key + spawnableActorList_add(&chSnsEgg, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //SnS_egg spawnableActorList_add(&gChFireFxInfo, actor_new, ACTOR_FLAG_NONE); //fire - spawnableActorList_add(&D_80367838, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //level_entry_disk + spawnableActorList_add(&gWorldExitPad, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //level_entry_disk spawnableActorList_add(&D_80367760, actor_new, ACTOR_FLAG_UNKNOWN_12); spawnableActorList_add(&D_80367784, actor_new, ACTOR_FLAG_UNKNOWN_12); - spawnableActorList_add(&D_80365E58, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.without_right_hand - spawnableActorList_add(&D_80365EAC, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.playing_gameboy - spawnableActorList_add(&D_80365F00, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.cooking - spawnableActorList_add(&D_803677CC, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15);//mumbo_transform_pad - spawnableActorList_add(&D_803677F0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&D_803731B0, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&gameSelect_banjoSleeping, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.without_right_hand + spawnableActorList_add(&gameSelect_banjoGameboy, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.playing_gameboy + spawnableActorList_add(&gameSelect_banjoCooking, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.cooking + spawnableActorList_add(&chMumboSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15);//mumbo_transform_pad + spawnableActorList_add(&chFFTeleportPad, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&lairBottlesDialog, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&chSnowball, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_20);//snowball spawnableActorList_add(&chSnowmanHat, actor_new, ACTOR_FLAG_UNKNOWN_2);//sir_slush_hat spawnableActorList_add(&gChDripsInfo, actor_new, ACTOR_FLAG_UNKNOWN_10);//water_drops spawnableActorList_add(&chIcecubeB, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_25);//ice_cube - spawnableActorList_add(&D_8036804C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//GAME_OVER - spawnableActorList_add(&D_8036807C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//THE_END - spawnableActorList_add(&D_803680AC, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//player_KAZOOIE + spawnableActorList_add(&gcGameOverSign, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//GAME_OVER + spawnableActorList_add(&gcTheEndSign, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//THE_END + spawnableActorList_add(&gcBanjoKazooieSign, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//player_KAZOOIE spawnableActorList_add(&chOverlayCopyrightDescription, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//copyright_info - spawnableActorList_add(&D_80368124, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//PRESS_START + spawnableActorList_add(&chOverlayPressStart, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//PRESS_START spawnableActorList_add(&chBottlesBonusDescription, chBottlesBonus_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//jiggy_picture - spawnableActorList_add(&D_8036833C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22); + spawnableActorList_add(&chMumbosHandWithPicture, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22); spawnableActorList_add(&D_8036838C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22); - spawnableActorList_add(&D_80368418, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//banjos_hand_BB - spawnableActorList_add(&D_80368174, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//NO_CONTROLLER); - spawnableActorList_add(&D_80367530, actor_new, ACTOR_FLAG_NONE);//mumbo_token_sign.5 - spawnableActorList_add(&D_80367554, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.10 - spawnableActorList_add(&D_80367578, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.15 - spawnableActorList_add(&D_8036759C, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.20 - spawnableActorList_add(&D_803675C0, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.25 - spawnableActorList_add(&D_8036785C, actor_new, ACTOR_FLAG_NONE);//witch_switch.mm; - spawnableActorList_add(&D_80367880, actor_new, ACTOR_FLAG_NONE);//witch_switch.mmm - spawnableActorList_add(&D_803678A4, actor_new, ACTOR_FLAG_NONE);//witch_switch.ttc - spawnableActorList_add(&D_803678C8, actor_new, ACTOR_FLAG_NONE);//witch_switch.rbb - spawnableActorList_add(&D_803678EC, actor_new, ACTOR_FLAG_NONE);//witch_switch.ccw - spawnableActorList_add(&D_80367910, actor_new, ACTOR_FLAG_NONE);//witch_switch.fp - spawnableActorList_add(&D_80367934, actor_new, ACTOR_FLAG_NONE);//witch_switch.cc - spawnableActorList_add(&D_80367958, actor_new, ACTOR_FLAG_NONE);//witch_switch.bgs - spawnableActorList_add(&D_8036797C, actor_new, ACTOR_FLAG_UNKNOWN_10);//witch_switch.gv - spawnableActorList_add(&D_80368450, actor_new, ACTOR_FLAG_UNKNOWN_17);//fire_sparkle - spawnableActorList_add(&D_803684BC, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8);//roysten - spawnableActorList_add(&D_803684E0, actor_new, ACTOR_FLAG_NONE);//cuckoo_clock + spawnableActorList_add(&chBottlesBonusCursor, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//banjos_hand_BB + spawnableActorList_add(&chOverlayNoController, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//NO_CONTROLLER); + spawnableActorList_add(&chMumboSign5, actor_new, ACTOR_FLAG_NONE);//mumbo_token_sign.5 + spawnableActorList_add(&chMumboSign10, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.10 + spawnableActorList_add(&chMumboSign15, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.15 + spawnableActorList_add(&chMumboSign20, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.20 + spawnableActorList_add(&chMumboSign25, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.25 + spawnableActorList_add(&chMMWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.mm; + spawnableActorList_add(&chMMMWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.mmm + spawnableActorList_add(&chTTCWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.ttc + spawnableActorList_add(&chRBBWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.rbb + spawnableActorList_add(&chCCWWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.ccw + spawnableActorList_add(&chFPWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.fp + spawnableActorList_add(&chCCWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.cc + spawnableActorList_add(&chBGSWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.bgs + spawnableActorList_add(&chGVWitchSwitch, actor_new, ACTOR_FLAG_UNKNOWN_10);//witch_switch.gv + spawnableActorList_add(&chFireSparkle, actor_new, ACTOR_FLAG_UNKNOWN_17);//fire_sparkle + spawnableActorList_add(&chFishbowl, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8);//roysten + spawnableActorList_add(&chCuckooClock, actor_new, ACTOR_FLAG_NONE);//cuckoo_clock spawnableActorList_add(&D_80368504, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_80368528, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_8036854C, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_80368570, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&D_80368474, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&D_80368498, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chBanjoCurtains, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&chBanjoHouseDoor, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_803732E0, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_80372810, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_23); spawnableActorList_add(&chWhipcrack, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_23 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&D_80373134, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_80373158, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&D_80372EE0, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&chBetaVent1, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chBetaVent2, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chChumpFish, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25); spawnableActorList_addIfMapVisited(&chTermite, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_2_MM_MUMBOS_MOUNTAIN); //ticker spawnableActorList_addIfMapVisited(&chFlotsam, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_31_RBB_RUSTY_BUCKET_BAY); //floatsam - spawnableActorList_addIfMapVisited(&D_80372C18, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17, MAP_1B_MMM_MAD_MONSTER_MANSION); //teehee + spawnableActorList_addIfMapVisited(&chTeeHee, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17, MAP_1B_MMM_MAD_MONSTER_MANSION); //teehee spawnableActorList_addIfMapVisited(&D_80372FC0, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); spawnableActorList_addIfMapVisited(&D_80372FE4, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); spawnableActorList_addIfMapVisited(&gChBat, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_21 |ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); //nibbly - spawnableActorList_addIfMapVisited(&D_80367130, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_D_BGS_BUBBLEGLOOP_SWAMP); //buzzbomb + spawnableActorList_addIfMapVisited(&chBuzzbomb, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_D_BGS_BUBBLEGLOOP_SWAMP); //buzzbomb spawnableActorList_addIfMapVisited(&chIcecubeA, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_25, MAP_27_FP_FREEZEEZY_PEAK); spawnableActorList_addIfMapVisited(&chShrapnelDescription, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25, MAP_7_TTC_TREASURE_TROVE_COVE); //scrapnel spawnableActorList_addIfMapVisited(&D_80372D78, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_24 | ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); //limbo @@ -357,7 +373,7 @@ void spawnQueue_reset(void){ spawnableActorList_addIfMapVisited(&chBlackSnippet, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_24 | ACTOR_FLAG_UNKNOWN_25, MAP_7_TTC_TREASURE_TROVE_COVE); //black_snippet spawnableActorList_addIfMapVisited(&chMutieSnippet, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_24 | ACTOR_FLAG_UNKNOWN_25, MAP_7_TTC_TREASURE_TROVE_COVE); //mutie_snippet spawnableActorList_addIfMapVisited(&chClucker, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_23 |ACTOR_FLAG_UNKNOWN_25, MAP_40_CCW_HUB); //clucker - spawnableActorList_addIfMapVisited(&D_803728A0, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_12_GV_GOBIS_VALLEY); //scarab + spawnableActorList_addIfMapVisited(&chScarabBeetle, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_12_GV_GOBIS_VALLEY); //scarab spawnableActorList_addIfMapVisited(&chSnowman, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_25, MAP_27_FP_FREEZEEZY_PEAK); //sirslush switch(loaded_asm_file){ default: @@ -390,23 +406,23 @@ void spawnQueue_reset(void){ MM_func_803888B0(); break; case OVERLAY_7_SWAMP: - BGS_func_8038F1E0(); + bgs_updateSpawnableActors(); break; case OVERLAY_8_SHIP: RBB_func_80386C48(); break; case OVERLAY_9_SNOW: FP_func_80391324(); - spawnableActorList_add(&D_80367BC8, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&D_80367BEC, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&D_80367C10, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chBluePresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chGreenPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chRedPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); break; case OVERLAY_A_TREE: CCW_func_8038DB6C(); break; } - // BB romhacks globalize all overlays so any actor can spawn on any map. + // Romhacks globalize all overlays so any actor can spawn on any map. // Register actors from every overlay that wasn't already handled above. if (port_isRomhack()) { if (loaded_asm_file != OVERLAY_D_WITCH) { lair_func_8038A0C4(); } @@ -418,9 +434,14 @@ void spawnQueue_reset(void){ if (loaded_asm_file != OVERLAY_4_DESERT) { GV_func_8038F154(); } if (loaded_asm_file != OVERLAY_5_BEACH) { code26D0_resetSpawnableActorsForTTC(); } if (loaded_asm_file != OVERLAY_6_JUNGLE) { MM_func_803888B0(); } - if (loaded_asm_file != OVERLAY_7_SWAMP) { BGS_func_8038F1E0(); } + if (loaded_asm_file != OVERLAY_7_SWAMP) { bgs_updateSpawnableActors(); } if (loaded_asm_file != OVERLAY_8_SHIP) { RBB_func_80386C48(); } - if (loaded_asm_file != OVERLAY_9_SNOW) { FP_func_80391324(); } + if (loaded_asm_file != OVERLAY_9_SNOW) { + FP_func_80391324(); + spawnableActorList_add(&chBluePresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chGreenPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&chRedPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); + } if (loaded_asm_file != OVERLAY_A_TREE) { CCW_func_8038DB6C(); } } @@ -439,13 +460,14 @@ void spawnQueue_free(void){ bk_free(spawnQueue); spawnQueue = NULL; spawnQueueLength = 0; + sSpawnQueueMax = 0; // [port] no capacity without an allocation } void spawnQueue_func_802C39D4(void){ func_803268B4(); if(!levelSpecificFlags_validateCRC2()){ - eeprom_writeBlocks(0, 0, (void *)(uintptr_t)0x80749530, EEPROM_MAXBLOCKS); + eeprom_writeBlocks(0, 0, (void *)(uintptr_t) PHYS_TO_K0(0x00749530), EEPROM_MAXBLOCKS); } } @@ -485,68 +507,68 @@ void spawnQueue_flush(void){ func_803283D4(); } -void spawnQueue_unlock(void){ - spawnQueueLock = 0; +void spawnQueue_unlock(void) { + spawnQueueLock = FALSE; } -void spawnQueue_lock(void){ - spawnQueueLock = 1; +void spawnQueue_lock(void) { + spawnQueueLock = TRUE; } -void __spawnQueue_add_0(void (* arg0)(void)){ +void __spawnQueue_add_0(GenFunction_0 arg0){ u32 tmp = __spawnQueue_getMax(); - if(tmp != spawnQueueLength){ + if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp spawnQueue[spawnQueueLength].func0 = arg0; spawnQueue[spawnQueueLength].arg_cnt = 0; spawnQueueLength++; } else { - BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_0 entry", tmp); + BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_0 entry", tmp); } } void __spawnQueue_add_1(GenFunction_1 arg0, uintptr_t arg1){ u32 tmp = __spawnQueue_getMax(); - if(tmp != spawnQueueLength){ - spawnQueue[spawnQueueLength].func0 = (void (*)(void))arg0; + if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp + spawnQueue[spawnQueueLength].func1 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg_cnt = 1; spawnQueueLength++; } else { - BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_1 entry", tmp); + BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_1 entry", tmp); } } -void __spawnQueue_add_2(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2){ +void __spawnQueue_add_2(GenFunction_2 arg0, uintptr_t arg1, uintptr_t arg2){ u32 tmp = __spawnQueue_getMax(); - if(tmp != spawnQueueLength){ - spawnQueue[spawnQueueLength].func0 = arg0; + if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp + spawnQueue[spawnQueueLength].func2 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg_cnt = 2; spawnQueueLength++; } else { - BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_2 entry", tmp); + BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_2 entry", tmp); } } -void __spawnQueue_add_3(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2, uintptr_t arg3){ +void __spawnQueue_add_3(GenFunction_3 arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3){ u32 tmp = __spawnQueue_getMax(); - if(tmp != spawnQueueLength){ - spawnQueue[spawnQueueLength].func0 = arg0; + if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp + spawnQueue[spawnQueueLength].func3 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg[2] = arg3; spawnQueue[spawnQueueLength].arg_cnt = 3; spawnQueueLength++; } else { - BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_3 entry", tmp); + BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_3 entry", tmp); } } void __spawnQueue_add_4(GenFunction_4 arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4){ u32 tmp = __spawnQueue_getMax(); - if(tmp != spawnQueueLength){ - spawnQueue[spawnQueueLength].func0 = (void (*)(void))arg0; + if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp + spawnQueue[spawnQueueLength].func4 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg[2] = arg3; @@ -554,14 +576,14 @@ void __spawnQueue_add_4(GenFunction_4 arg0, uintptr_t arg1, uintptr_t arg2, uint spawnQueue[spawnQueueLength].arg_cnt = 4; spawnQueueLength++; } else { - BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_4 entry", tmp); + BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_4 entry", tmp); } } -void __spawnQueue_add_5(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5){ +void __spawnQueue_add_5(GenFunction_5 arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5){ u32 tmp = __spawnQueue_getMax(); - if(tmp != spawnQueueLength){ - spawnQueue[spawnQueueLength].func0 = arg0; + if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp + spawnQueue[spawnQueueLength].func5 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg[2] = arg3; @@ -570,7 +592,7 @@ void __spawnQueue_add_5(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2, uin spawnQueue[spawnQueueLength].arg_cnt = 5; spawnQueueLength++; } else { - BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_5 entry", tmp); + BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_5 entry", tmp); } } diff --git a/src/core2/spline_bezier.c b/src/core2/spline_bezier.c index 60b98db21..bdc4a40d1 100644 --- a/src/core2/spline_bezier.c +++ b/src/core2/spline_bezier.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C31A0.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/spline_pathfollow.c b/src/core2/spline_pathfollow.c index f9a7dc596..271422d9c 100644 --- a/src/core2/spline_pathfollow.c +++ b/src/core2/spline_pathfollow.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B9770.c #include #include "functions.h" #include "variables.h" @@ -925,8 +926,8 @@ f32 func_80342260(s32 arg0, f32 arg1, s32 arg2){ return func_803234FC(func_80342038(arg0), arg1, 1.0f) / ((f32)arg2 /4); } -void func_803422AC(ActorMarker *caller, enum asset_e text_id, s32 arg2){ - jiggyscore_total(); +s32 func_803422AC(ActorMarker *caller, enum asset_e text_id, s32 arg2){ + return jiggyscore_total(); } s32 func_803422D4(Actor *arg0, Union_glspline *arg1, SplineList *arg2){ @@ -961,6 +962,11 @@ s32 func_803422D4(Actor *arg0, Union_glspline *arg1, SplineList *arg2){ break; case 3: + // [port] Path sfx nodes fire for whichever actor is walking the spline; listeners + // get the actor so a single actor's path sounds can be muted. + if (!EventSystem_Should(VB_SPLINE_PATH_SFX, true, arg0)) { + break; + } sp78 = arg1->t0.unk4.common.bit31; sp7C = arg1->t0.unk8.bit31 / 8.388608e6f; sp74 = arg1->t0.unk4.common.bit15 * 8; diff --git a/src/core2/sprite/render.c b/src/core2/sprite/render.c index 7424da231..688853f8c 100644 --- a/src/core2/sprite/render.c +++ b/src/core2/sprite/render.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_BD100.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -55,7 +56,7 @@ void func_80344138(BKSpriteDisplayData *self, s32 frame, s32 mirrored, f32 posit FrameInterpolation_RecordOpenChild("sprite_viewport", (uintptr_t)self); viewport_getPosition_vec3f(sp6C); - viewport_getLookbk_vector(sp60); + viewport_getLookVector(sp60); sp50[0] = position[0] - sp6C[0]; sp50[1] = position[1] - sp6C[1]; sp50[2] = position[2] - sp6C[2]; @@ -129,7 +130,7 @@ void func_80344424(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 posi FrameInterpolation_RecordOpenChild("sprite_viewport_rot", (uintptr_t)arg0); viewport_getPosition_vec3f(sp6C); - viewport_getLookbk_vector(sp60); + viewport_getLookVector(sp60); sp50[0] = position[0] - sp6C[0]; sp50[1] = position[1] - sp6C[1]; sp50[2] = position[2] - sp6C[2]; @@ -204,7 +205,7 @@ void func_80344720(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 posi // the caller rather than billboarded against the camera. FrameInterpolation_RecordOpenChild("sprite_3d", (uintptr_t)arg0); viewport_getPosition_vec3f(sp5C); - viewport_getLookbk_vector(sp50); + viewport_getLookVector(sp50); sp40[0] = position[0] - sp5C[0]; sp40[1] = position[1] - sp5C[1]; sp40[2] = position[2] - sp5C[2]; diff --git a/src/core2/sprite/rendertex.c b/src/core2/sprite/rendertex.c index 7933db4f3..29e33f5bf 100644 --- a/src/core2/sprite/rendertex.c +++ b/src/core2/sprite/rendertex.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C0E60.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sprite/screenoverlay.c b/src/core2/sprite/screenoverlay.c index 81e63673d..55a166e8e 100644 --- a/src/core2/sprite/screenoverlay.c +++ b/src/core2/sprite/screenoverlay.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_AEDA0.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -205,7 +206,9 @@ void codeAEDA0_drawSprite( Gfx **gfx ) D_80370338[0] = 1; } - if(D_80383634 == 0x0E){ + // [port] Vanilla only disarms G_AC_THRESHOLD when the draw-mode global still reads + // 0x0E. SpritePatches.cpp forces it so a mode change cannot leak it into later draws. + if (EventSystem_Should(VB_SPRITE_RESTORE_ALPHA_COMPARE, D_80383634 == 0x0E, gfx)) { gDPSetAlphaCompare((*gfx)++, G_AC_NONE); } } @@ -285,7 +288,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr sp1B4 = *gfx; sp1B0 = var_a3; if(segment != 0){ - gSPVertex((*gfx)++, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), 0, 0); + gSPVertexSeg((*gfx)++, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, 0, 0); }else{ gSPVertex((*gfx)++, (uintptr_t)sp1B0, 0, 0); } @@ -335,7 +338,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr if (i_vtx == 0x10) { i_vtx = 0; if(segment != 0){ - gSPVertex(sp1B4, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), 16, 0); + gSPVertexSeg(sp1B4, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, 16, 0); }else{ gSPVertex(sp1B4, (uintptr_t)sp1B0, 16, 0); } @@ -343,7 +346,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr sp1B4 = *gfx; sp1B0 = var_a3; if (segment) { - gSPVertex((*gfx)++, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), 0, 0); + gSPVertexSeg((*gfx)++, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, 0, 0); } else { gSPVertex((*gfx)++, (uintptr_t)sp1B0, 0, 0); } @@ -357,7 +360,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr //rewrite vtx seg start with correct vtx count if (i_vtx > 0) { if(segment != 0){ - gSPVertex(sp1B4, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), i_vtx, 0); + gSPVertexSeg(sp1B4, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, i_vtx, 0); }else{ if(1); gSPVertex(sp1B4, (uintptr_t)sp1B0, i_vtx, 0); diff --git a/src/core2/sprite/texblock.c b/src/core2/sprite/texblock.c index 877da6005..b1f56c843 100644 --- a/src/core2/sprite/texblock.c +++ b/src/core2/sprite/texblock.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B8020.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/state_timer.c b/src/core2/statetimer.c similarity index 97% rename from src/core2/state_timer.c rename to src/core2/statetimer.c index cc4132e0e..43ec68385 100644 --- a/src/core2/state_timer.c +++ b/src/core2/statetimer.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/statetimer.c #include "core2/statetimer.h" #include "bk_time.h" diff --git a/src/core2/texture_dataaccess.c b/src/core2/texture_dataaccess.c index 164e942ed..918f00c50 100644 --- a/src/core2/texture_dataaccess.c +++ b/src/core2/texture_dataaccess.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_63690.c #include #include "functions.h" #include "variables.h" @@ -51,12 +52,12 @@ s32 textureInfo_getPaletteSize(BKTextureInfo *this){ } // texture_getOffset -s32 func_802EA6DC(BKTextureInfo *this){ +s32 textureInfo_getOffset(BKTextureInfo *this){ return this->offset; } //texture_getSize -s32 func_802EA6E4(BKTextureInfo *this){ +s32 textureInfo_getTextureSize(BKTextureInfo *this){ s32 palette_size = textureInfo_getPaletteSize(this); s32 pixel_size = textureInfo_getBitDepth(this); @@ -64,6 +65,6 @@ s32 func_802EA6E4(BKTextureInfo *this){ } //textureList_getTexture -BKTextureInfo *func_802EA748(BKTextureList *arg0, s32 indx){ +BKTextureInfo *textureList_getTextureInfo(BKTextureList *arg0, s32 indx){ return (BKTextureInfo *)(arg0 +1) + indx; } diff --git a/src/core2/time.c b/src/core2/time.c index fa7e9f224..120493fa5 100644 --- a/src/core2/time.c +++ b/src/core2/time.c @@ -1,6 +1,7 @@ #include "bk_time.h" #include "core1/vimgr.h" +#include "version.h" #ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) @@ -26,7 +27,7 @@ void time_reset(void){ void time_setDeltaReal_sec(f32 d_seconds){ if(d_seconds != 0.0f){ - s_dTimeReal_sec = MIN(d_seconds, 0.05); + s_dTimeReal_sec = MIN(d_seconds, VER_SELECT(0.05, 0.06, 0.05, 0.05)); } else{ s_dTimeReal_sec = 0.01f; @@ -35,7 +36,7 @@ void time_setDeltaReal_sec(f32 d_seconds){ void time_setDeltaReal_frames(s32 d_frames){ s_dTimeReal_frames = MAX(MIN(0xf, d_frames) , 1); - time_setDeltaReal_sec(s_dTimeReal_frames*(1/60.0)); + time_setDeltaReal_sec(s_dTimeReal_frames*(1.0/FRAMERATE)); } s32 time_getDeltaReal_frames(void){ @@ -47,11 +48,11 @@ f32 time_getDelta(void){ } f32 time_func_8033DDB8(void){ - return viMgr_func_8024BD94()*(1/60.0); + return viMgr_func_8024BD94()*(1.0/FRAMERATE); } f32 time_getDelta_frames(void){ - return time_getDelta()*30.0; + return time_getDelta()*(FRAMERATE/2.0); } void time_setMultiplier(f32 multiplier){ diff --git a/src/core2/time_framedelta.c b/src/core2/time_framedelta.c index d9ac652ca..525731e34 100644 --- a/src/core2/time_framedelta.c +++ b/src/core2/time_framedelta.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_B6C60.c #include #include "functions.h" #include "variables.h" @@ -28,22 +29,7 @@ f32 func_8033DC20(void){ u64 now = SDL_GetPerformanceCounter(); u64 freq = SDL_GetPerformanceFrequency(); f32 out; - - if (last_ticks == 0) { - last_ticks = now; - out = 1.0f / 30.0f; // first frame: assume 1/30 (N64 rate) - } else { - out = (f32)(now - last_ticks) / (f32)freq; - last_ticks = now; - } - - // Cap at 50ms (matching time_setDeltaReal_sec cap) - if (out > 0.05f) out = 0.05f; - if (out <= 0.0f) out = 1.0f / 60.0f; - - // Keep D_80384470 updated for anything that reads it - D_80384470 = (s32)(out * 60.0f + 0.5f); - if (D_80384470 < 1) D_80384470 = 1; - + D_80384470 = viMgr_func_8024BD94(); + out = (1.0 / FRAMERATE)*D_80384470; return out; } diff --git a/src/core2/timed_funcqueue.c b/src/core2/timedfuncqueue.c similarity index 99% rename from src/core2/timed_funcqueue.c rename to src/core2/timedfuncqueue.c index 6fb994e18..7bb527941 100644 --- a/src/core2/timed_funcqueue.c +++ b/src/core2/timedfuncqueue.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/timedfuncqueue.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vector.c b/src/core2/vla.c similarity index 92% rename from src/core2/vector.c rename to src/core2/vla.c index ddb6dc37b..d8c6e284a 100644 --- a/src/core2/vector.c +++ b/src/core2/vla.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/vla.c #include #include "functions.h" #include "core2/vla.h" @@ -80,7 +81,9 @@ void bk_vector_remove(VLA *this, u32 indx){ uintptr_t nextOffset = (uintptr_t)this->begin + (indx + 1) * this->elem_size;\ uintptr_t size = (uintptr_t)this->end - (uintptr_t)this->begin; - memcpy((void *)elemOffset, (void *)nextOffset, size - (indx + 1) * this->elem_size); + // [port] source and destination overlap when removing anywhere but the tail; + // memcpy on overlapping buffers is UB on PC toolchains. + memmove((void *)elemOffset, (void *)nextOffset, size - (indx + 1) * this->elem_size); this->end = (void *)((uintptr_t)this->end - this->elem_size); } diff --git a/src/core2/vtx/alphablend.c b/src/core2/vtx/alphablend.c index 32ee43d7e..bed705f72 100644 --- a/src/core2/vtx/alphablend.c +++ b/src/core2/vtx/alphablend.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C76D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/colorapply.c b/src/core2/vtx/colorapply.c index 81ab464a1..deaa3182d 100644 --- a/src/core2/vtx/colorapply.c +++ b/src/core2/vtx/colorapply.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C4F40.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/colorintensity.c b/src/core2/vtx/colorintensity.c index a27db662d..c6582ad65 100644 --- a/src/core2/vtx/colorintensity.c +++ b/src/core2/vtx/colorintensity.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C8230.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/colorset.c b/src/core2/vtx/colorset.c index c881d926f..0675a34dd 100644 --- a/src/core2/vtx/colorset.c +++ b/src/core2/vtx/colorset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C5AF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/convert.c b/src/core2/vtx/convert.c index 9d530a9c3..bfe05a056 100644 --- a/src/core2/vtx/convert.c +++ b/src/core2/vtx/convert.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C61C0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/lighting.c b/src/core2/vtx/gclights.c similarity index 94% rename from src/core2/vtx/lighting.c rename to src/core2/vtx/gclights.c index ccf12fa17..67f3e0b65 100644 --- a/src/core2/vtx/lighting.c +++ b/src/core2/vtx/gclights.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/gclights.c #include "functions.h" #include "variables.h" #include @@ -165,7 +166,7 @@ static void __lighting_setPosition(s32 index , f32 *position) { TUPLE_COPY(v0->position, position) } -static void __lighting_setUnk18AndUnk1C(s32 index , f32 *unk18_and_unk1c) { +static void __lighting_setFadeRadii(s32 index , f32 *unk18_and_unk1c) { Lighting *v0 = bk_vector_at(sLightingbk_vectorList.bk_vector_ptr, index-1); v0->fade_radius_min_unscaled = unk18_and_unk1c[0]; v0->fade_radius_max_unscaled = unk18_and_unk1c[1]; @@ -190,7 +191,7 @@ void lightingVectorList_fromFile(File *file_ptr) { ) { lighting_ptr = __lighting_create(); __lighting_setPosition(lighting_ptr, position); - __lighting_setUnk18AndUnk1C(lighting_ptr, unk18_and_unk1c); + __lighting_setFadeRadii(lighting_ptr, unk18_and_unk1c); __lighting_setRgb(lighting_ptr, rgb); } } @@ -232,6 +233,12 @@ void gclights_recolor_vertices(BKVertexList *vertex_list, f32 position[3], f32 r ref_ptr = vtxList_getVertices(ref_vertex_list); vtxList_getVtxRange(vertex_list, &i_ptr, &end_ptr); + // [port] Cancelled by PerfPatches.cpp, which runs this same loop with a + // squared-distance early-out so out-of-range lights never pay the sqrt. + if (!EventSystem_Should(VB_GCLIGHTS_RECOLOR, true, i_ptr, end_ptr, ref_ptr, &sLightingbk_vectorList.unk4[0], + sLightingbk_vectorList.unk44)) { + return; + } for(i_ptr = i_ptr; i_ptr < end_ptr; i_ptr++, ref_ptr++) { rgb_modifier[0] = rgb_modifier[1] = rgb_modifier[2] = 0.0f; TUPLE_COPY(vtx_position, ref_ptr->v.ob); diff --git a/src/core2/vtx/list.c b/src/core2/vtx/list.c index eac054e13..59eb775d5 100644 --- a/src/core2/vtx/list.c +++ b/src/core2/vtx/list.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_654C0.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -41,7 +42,7 @@ void vtxList_getBounds_f32(BKVertexList *vtxList, f32 min[3], f32 max[3]){ max[2] = (f32) vtxList->maxCoord[2]; } -void vtxList_getBoundsMlMtxTransformed(BKVertexList *self, f32 min[3], f32 max[3]) { +void vtxList_getBoundsTransformed(BKVertexList *self, f32 min[3], f32 max[3]) { Vtx *start_vtx; Vtx *end_vtx; Vtx *i_vtx; @@ -75,7 +76,7 @@ void vtxList_getBoundsMlMtxTransformed(BKVertexList *self, f32 min[3], f32 max[3 } } -void func_802EC680(BKVertexList *self, s32 arg1, f32 arg2[3], f32 arg3[3]) { +void vtxList_func_802EC680(BKVertexList *self, s32 arg1, f32 arg2[3], f32 arg3[3]) { Vtx *start_vtx; Vtx *end_vtx; Vtx *i_vtx; @@ -227,7 +228,7 @@ void vtxList_func_802ECBD4(BKVertexList *dst, BKVertexList *src, f32 position[3] s32 pad40; viewport_getPosition_vec3f(vp_position); - viewport_getLookbk_vector(vp_look); + viewport_getLookVector(vp_look); mlMtxIdent(); func_80252CC4(position, rotation, 1.0f, NULL); mlMtx_apply_vec3f(vp_position, vp_position); diff --git a/src/core2/vtx/listutils.c b/src/core2/vtx/listutils.c index f484b58bd..5c028c7dc 100644 --- a/src/core2/vtx/listutils.c +++ b/src/core2/vtx/listutils.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_5FD90.c #include #include "functions.h" #include "variables.h" @@ -204,8 +205,8 @@ bool func_802E74A0(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3[3]) { f32 sp24[3]; f32 sp20; - if (arg1 <= ml_func_802560D0(arg2, arg3, arg0)) { - return false; + if (arg1 <= ml_vec3f_distance_to_point(arg2, arg3, arg0)) { + return FALSE; } sp24[0] = (arg2[0] + arg3[0]) / 2; sp24[1] = (arg2[1] + arg3[1]) / 2; @@ -217,6 +218,7 @@ bool func_802E74A0(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3[3]) { return true; } +// Unused bool func_802E7588(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3) { return (ml_vec3f_distance(arg0, arg2) < (arg1 + arg3)); } diff --git a/src/core2/vtx/meshcount.c b/src/core2/vtx/meshcount.c index 3d553ebd1..393fd29e0 100644 --- a/src/core2/vtx/meshcount.c +++ b/src/core2/vtx/meshcount.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_62FD0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/normalset.c b/src/core2/vtx/normalset.c index 786ce7efb..e31a5efd0 100644 --- a/src/core2/vtx/normalset.c +++ b/src/core2/vtx/normalset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C5F00.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/positionset.c b/src/core2/vtx/positionset.c index 49b2cb594..0c560f4f0 100644 --- a/src/core2/vtx/positionset.c +++ b/src/core2/vtx/positionset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C8490.c #include #include "functions.h" #include "variables.h" @@ -16,7 +17,7 @@ void func_8034F434(Struct76s *arg0, s32 arg1) { arg0->alpha = 0; arg0->unk2 = randi2(200, 255); arg0->unk4 = (s32) (arg0->unk4 + 1); - arg0->unk14 = arg0->unk10 = randf2(0.08f, 0.12f); + arg0->unk14 = arg0->unk10 = randf2(VER_SELECT(0.08f, 0.12f, 0.0f, 0.0f), VER_SELECT(0.12f, 0.18f, 0.0f, 0.0f)); if ((arg0->unk4 == 1) && func_8034C4CC()) { gcsfx_playWithPitch(SFX_B5_THUNDERBOLT, randf2(0.9f, 1.1f), randi2(10000, 20000)); } @@ -56,13 +57,13 @@ void func_8034F5B0(Struct76s *arg0, BKModel *arg1, s32 arg2){ func_8034F434(arg0, 1); } if (arg0->unkC == 1) { - if (arg0->unk10 <= 0.04) { - arg0->alpha = (arg0->unk10 / 0.04) * arg0->unk2; + if (arg0->unk10 <= VER_SELECT(0.04, 0.06, 0.0, 0.0)) { + arg0->alpha = (arg0->unk10 / VER_SELECT(0.04, 0.06, 0.0, 0.0)) * arg0->unk2; } else { - if (arg0->unk10 < (arg0->unk14 - 0.04)) { + if (arg0->unk10 < (arg0->unk14 - VER_SELECT(0.04, 0.06, 0.0, 0.0))) { arg0->alpha = arg0->unk2; } else { - arg0->alpha = ((arg0->unk14 - arg0->unk10) / 0.04) * arg0->unk2; + arg0->alpha = ((arg0->unk14 - arg0->unk10) / VER_SELECT(0.04, 0.06, 0.0, 0.0)) * arg0->unk2; } } if (ml_timer_update(&arg0->unk10, sp24)) { diff --git a/src/core2/vtx/renderstart.c b/src/core2/vtx/renderstart.c index b48c8919e..f20ff1171 100644 --- a/src/core2/vtx/renderstart.c +++ b/src/core2/vtx/renderstart.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C62B0.c #include #include "functions.h" #include "variables.h" @@ -246,7 +247,7 @@ void func_8034E120(Struct6Ds *arg0, f32 arg1, f32 arg2, f32 arg3,s32 arg4){ } void func_8034E174(Struct6Ds *arg0){ - func_8034E1A4(arg0, 0x3ec, 0.7f, 0.9f); + func_8034E1A4(arg0, SFX_3EC_CCW_DOOR_OPENING, 0.7f, 0.9f); } void func_8034E1A4(Struct6Ds *arg0, enum sfx_e sfx_id, f32 arg2, f32 arg3){ diff --git a/src/core2/vtx/scale.c b/src/core2/vtx/scale.c index f0111ce62..f72955fea 100644 --- a/src/core2/vtx/scale.c +++ b/src/core2/vtx/scale.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C7CC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/transform.c b/src/core2/vtx/transform.c index d36550580..f737f7104 100644 --- a/src/core2/vtx/transform.c +++ b/src/core2/vtx/transform.c @@ -1,5 +1,7 @@ +// BanjoDecomp: core2/code_C5440.c #include #include "functions.h" +#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "model.h" #include diff --git a/src/core2/vtx/uvset.c b/src/core2/vtx/uvset.c index 57a578bec..dc4e191e3 100644 --- a/src/core2/vtx/uvset.c +++ b/src/core2/vtx/uvset.c @@ -1,3 +1,4 @@ +// BanjoDecomp: core2/code_C5CC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/cutscenes/bss_pad.c b/src/cutscenes/bss_pad.c deleted file mode 100644 index 598952dc5..000000000 --- a/src/cutscenes/bss_pad.c +++ /dev/null @@ -1,2 +0,0 @@ -// BanjoDecomp: bss_pad.c -char pad_cutscenes_8038E9E0[0x10]; diff --git a/src/cutscenes/checksums.c b/src/cutscenes/checksums.c new file mode 100644 index 000000000..6514c7fd6 --- /dev/null +++ b/src/cutscenes/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: cutscenes/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsCutscenes; diff --git a/src/cutscenes/cutscene_trigger.c b/src/cutscenes/cutscene_trigger.c index 9c9ba8858..253557059 100644 --- a/src/cutscenes/cutscene_trigger.c +++ b/src/cutscenes/cutscene_trigger.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (core2 origin - unknown exact file) +// BanjoDecomp: core2/ch/code_468E0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/cutscenes/actor_spawninit.c b/src/cutscenes/cutscenesspawnqueue.c similarity index 99% rename from src/cutscenes/actor_spawninit.c rename to src/cutscenes/cutscenesspawnqueue.c index ab09fe0e4..d3a35cd79 100644 --- a/src/cutscenes/actor_spawninit.c +++ b/src/cutscenes/cutscenesspawnqueue.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_60F0.c +// BanjoDecomp: cutscenes/cutscenesspawnqueue.c #include #include "functions.h" #include "variables.h" diff --git a/src/cutscenes/fx/glow_sparkle.c b/src/cutscenes/glow_sparkle.c similarity index 100% rename from src/cutscenes/fx/glow_sparkle.c rename to src/cutscenes/glow_sparkle.c diff --git a/src/cutscenes/fx/smoke.c b/src/cutscenes/smoke.c similarity index 100% rename from src/cutscenes/fx/smoke.c rename to src/cutscenes/smoke.c diff --git a/src/cutscenes/fx/sparkle.c b/src/cutscenes/sparkle.c similarity index 100% rename from src/cutscenes/fx/sparkle.c rename to src/cutscenes/sparkle.c diff --git a/src/cutscenes/character_parade.c b/src/cutscenes/theendsign.c similarity index 79% rename from src/cutscenes/character_parade.c rename to src/cutscenes/theendsign.c index 8948202fb..3b1665620 100644 --- a/src/cutscenes/character_parade.c +++ b/src/cutscenes/theendsign.c @@ -1,17 +1,18 @@ -// BanjoDecomp: (core2 origin - unknown exact file) +// BanjoDecomp: core2/gc/theendsign.c #include #include "functions.h" #include "variables.h" Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void func_802DC67C(Actor *this); +void gcTheEndSign_update(Actor *this); /* .data */ f32 D_80368070[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo D_8036807C = { - 0x17C, 0x19C, 0x56C, - 0x1, NULL, - func_802DC67C, actor_update_func_80326224, func_802DC320, + +ActorInfo gcTheEndSign = { + MARKER_17C_MODEL_THE_END_SIGN, ACTOR_19C_MODEL_THE_END_SIGN, ASSET_56C_MODEL_THE_END_SIGN, + 0x1, NULL, + gcTheEndSign_update, actor_update_func_80326224, func_802DC320, 0, 0, 0.0f, 0 }; @@ -24,7 +25,7 @@ void func_802DC650(Actor * this){ func_8025A7DC(COMUSIC_AC_GOOD_ENDING); } -void func_802DC67C(Actor *this){ +void gcTheEndSign_update(Actor *this){ if(!this->initialized){ this->initialized = true; diff --git a/src/emptyLvl/checksums.c b/src/emptyLvl/checksums.c new file mode 100644 index 000000000..3475b09b2 --- /dev/null +++ b/src/emptyLvl/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: emptyLvl/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsEmptyLvl; diff --git a/src/overlay_stub/empty_level.c b/src/emptyLvl/empty_level.c similarity index 75% rename from src/overlay_stub/empty_level.c rename to src/emptyLvl/empty_level.c index dbc493fde..532935b68 100644 --- a/src/overlay_stub/empty_level.c +++ b/src/emptyLvl/empty_level.c @@ -1,5 +1,5 @@ // BanjoDecomp: emptyLvl/code_0.c unsigned char emptyLvl = 0; -unsigned char emptyLvlBss[0x20]; +unsigned char emptyLvlBss[0x10]; void emptyLvl_func_803863F0(void){} diff --git a/src/FINALE/ch/chbossjinjo.c b/src/fight/chbossjinjo.c similarity index 99% rename from src/FINALE/ch/chbossjinjo.c rename to src/fight/chbossjinjo.c index 2d43be5ca..3fb61196b 100644 --- a/src/FINALE/ch/chbossjinjo.c +++ b/src/fight/chbossjinjo.c @@ -3,7 +3,7 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "../fight.h" +#include "fight.h" #include "core2/particle.h" extern void func_80324CFC(f32, enum comusic_e, s32); diff --git a/src/FINALE/ch/chbossjinjobase.c b/src/fight/chbossjinjobase.c similarity index 95% rename from src/FINALE/ch/chbossjinjobase.c rename to src/fight/chbossjinjobase.c index f73718b4c..1cc5265b1 100644 --- a/src/FINALE/ch/chbossjinjobase.c +++ b/src/fight/chbossjinjobase.c @@ -1,11 +1,13 @@ // BanjoDecomp: fight/chbossjinjobase.c -#include "../fight.h" +#include "fight.h" #include "functions.h" #include "variables.h" #include #include +#include "port/Network/Anchor/FightSync.h" + typedef struct { u8 sfxsourceIdx; } ActorLocal_BossJinjoBase; @@ -47,9 +49,15 @@ void chBossJinjoBase_func_8038D3DC(Actor *this, s32 arg1, f32 arg2, f32 arg3, f3 void chBossJinjoBase_getHitByEgg(ActorMarker *this, ActorMarker *other) { Actor *actor_bossjinjobase = marker_getActor(this); + // Anchor: follower forwards to authority; accepted egg replays here via EGG_FED (other == NULL). + if (other != NULL && FightSync_ForwardEgg(actor_bossjinjobase->actorTypeSpecificField, 0)) { + return; + } + if (actor_bossjinjobase->state != CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { comusic_playTrack(COMUSIC_2B_DING_B); actor_bossjinjobase->unk38_31++; + FightSync_ReplicateEgg(actor_bossjinjobase->actorTypeSpecificField, 0); if (actor_bossjinjobase->unk38_31 >= 3) { subaddie_set_state(actor_bossjinjobase, CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO); diff --git a/src/FINALE/ch/chbossshadow.c b/src/fight/chbossshadow.c similarity index 97% rename from src/FINALE/ch/chbossshadow.c rename to src/fight/chbossshadow.c index 153ac9ed8..48bda115e 100644 --- a/src/FINALE/ch/chbossshadow.c +++ b/src/fight/chbossshadow.c @@ -2,7 +2,7 @@ #include #include "functions.h" #include "variables.h" -#include "../fight.h" +#include "fight.h" ActorInfo chBossShadow = { MARKER_288_GRUNTY_SHADOW, ACTOR_3AF_GRUNTY_SHADOW, ASSET_3BF_MODEL_PLAYER_SHADOW, 1, NULL, chBossShadow_update, actor_update_func_80326224, chBossShadow_draw, 0, 0, 0.0f, 0 }; diff --git a/src/fight/checksums.c b/src/fight/checksums.c new file mode 100644 index 000000000..3bc3a4bea --- /dev/null +++ b/src/fight/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: fight/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsFight; diff --git a/src/FINALE/ch/chfinalboss.c b/src/fight/chfinalboss.c similarity index 95% rename from src/FINALE/ch/chfinalboss.c rename to src/fight/chfinalboss.c index 90aad6680..5b2b3f511 100644 --- a/src/FINALE/ch/chfinalboss.c +++ b/src/fight/chfinalboss.c @@ -1,15 +1,16 @@ // BanjoDecomp: fight/chfinalboss.c -#include "../fight.h" +#include "fight.h" #include "functions.h" #include "variables.h" #include #include +#include "port/Network/Anchor/FightSync.h" + extern bool func_8028F4B8(f32[3], f32, f32); extern int func_80320ED8(ActorMarker *, f32, s32); s32 subaddie_getYawToPosition(Actor*, f32*); -Actor *actor_spawnWithYaw_f32(); extern Actor* func_80329958(ActorMarker *this, s32 arg1); extern void func_803298D8(); extern void func_80324CFC(f32, enum comusic_e, s32); @@ -20,6 +21,8 @@ extern void player_setIdealRotation(f32[3]); extern f32 func_8033229C(ActorMarker *); void func_8034DF30(Struct6Ds *, f32[3], f32[3], f32); +// ActorLocal_FinalBoss moved to fight.h for the Anchor fight-sync layer. +#if 0 typedef struct chfinalboss_s { u8 phase; u8 hits; @@ -46,6 +49,7 @@ typedef struct chfinalboss_s { f32 unk28; f32 unk2C; } ActorLocal_FinalBoss; +#endif f32 fight_D_80391380[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; f32 fight_D_80391390[4] = { 0.33f, 0.33f, 0.33f, 1.0f }; @@ -140,6 +144,8 @@ f32 D_80392750; f32 D_80392758[3]; f32 D_80392768[3]; f32 D_80392778[3]; +// Anchor: lead time from the last local aim; followers reuse it to re-aim at their own player. +f32 __chFinalBossFireballFlightTime; f32 chFinalBossPlayerPosition[3]; f32 chFinalBossPosition[3]; ActorMarker *__chFinalBossShadowMarker; @@ -161,9 +167,9 @@ Actor *chfinalboss_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { Actor *this = marker_getActor(marker); ActorLocal_FinalBoss *local = (ActorLocal_FinalBoss *)&this->local; - func_8033A45C(3, local->unkD); - func_8033A45C(4, local->unkE); - func_8033A45C(5, local->unkC); + modelRender_setAppendageVisibility(3, local->unkD); + modelRender_setAppendageVisibility(4, local->unkE); + modelRender_setAppendageVisibility(5, local->unkC); if (local->phase == FINALBOSS_PHASE_1_BROOMSTICK) { modelRender_func_8033A25C(false); @@ -308,7 +314,7 @@ void chfinalboss_func_80386B54(f32 *arg0, f32 arg1) { } } -bool chfinalboss_func_80386BEC(Actor *this, f32 arg1) { +bool chfinalboss_turnTowardPlayer(Actor *this, f32 arg1) { this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, arg1); if ((this->yaw_ideal < (this->yaw + arg1)) && ((this->yaw - arg1) < this->yaw_ideal)) { @@ -347,7 +353,7 @@ void chfinalboss_func_80386CF8(Actor *actor) { sp4C[0] = sp28[0] + sp34[0]; sp4C[1] = sp28[1] + sp34[1]; sp4C[2] = sp28[2] + sp34[2]; - func_8025727C(sp28[0], sp28[1], sp28[2], sp4C[0], sp4C[1], sp4C[2], &sp40[0], &sp40[1]); + ml_horizontal_and_vertical_angles(sp28[0], sp28[1], sp28[2], sp4C[0], sp4C[1], sp4C[2], &sp40[0], &sp40[1]); sp40[0] = 360.0f - sp40[0]; sp40[2] = 0.0f; ncStaticCamera_setPositionAndRotation(sp4C, sp40); @@ -360,8 +366,13 @@ void __chfinalboss_dropHealth(ActorMarker *marker) { } void chfinalboss_despawnFlightPad(void) { + // Anchor: a follower that joined late never spawned one. + if (__chFinalBossFlightPadMarker == NULL) { + return; + } marker_despawn(__chFinalBossFlightPadMarker); __chFinalBossFlightPadMarker = NULL; + FightSync_OnFlightPadDespawned(); } void chfinalboss_spawnFlightPad(s32 arg0) { @@ -372,6 +383,7 @@ void chfinalboss_spawnFlightPad(s32 arg0) { flight_pad->alpha_124_19 = 0; flight_pad->unk38_31 = 6; __chFinalBossFlightPadMarker = flight_pad->marker; + FightSync_OnFlightPadSpawned(); } void chfinalboss_func_80386EC0(s32 arg0) { @@ -380,6 +392,8 @@ void chfinalboss_func_80386EC0(s32 arg0) { marker = actor_spawnWithYaw_f32(0x38A, D_80392758, 0)->marker; func_8030E878(SFX_147_GRUNTY_SPELL_ATTACK_2, randf2(0.95f, 1.05f), 32000, D_80392758, 5000.0f, 12000.0f); chGreenBlast_func_803900DC(marker, D_80392758, D_80392768[1], D_80392768[2]); + // Anchor: replay this green blast on followers with the exact same vectors. + FightSync_OnSpellSpawned(2); } void chfinalboss_func_80386F5C(ActorMarker * arg0, f32 arg1[3], f32 arg2, f32 arg3) { @@ -398,6 +412,8 @@ void chfinalboss_func_80386FD8(s32 arg0) { marker = actor_spawnWithYaw_f32(0x389, D_80392758, 0)->marker; func_8030E878(SFX_146_GRUNTY_SPELL_ATTACK_1, randf2(0.95f, 1.05f), 32000, D_80392758, 5000.0f, 12000.0f); chSpellFireball_func_8038FB84(marker, D_80392758, D_80392768, D_80392778); + // Anchor: replay this fireball on followers with the exact same vectors. + FightSync_OnSpellSpawned(0); } void chfinalboss_func_80387074(s32 arg0) { @@ -406,9 +422,11 @@ void chfinalboss_func_80387074(s32 arg0) { marker = actor_spawnWithYaw_f32(0x3AA, D_80392758, 0)->marker; func_8030E878(SFX_146_GRUNTY_SPELL_ATTACK_1, randf2(0.95f, 1.05f), 32000, D_80392758, 5000.0f, 12000.0f); chSpellFireball_func_8038FB84(marker, D_80392758, D_80392768, D_80392778); + // Anchor: replay this final-spell fireball on followers with the exact same vectors. + FightSync_OnSpellSpawned(1); } -void chfinalboss_func_80387110(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3) { +void chfinalboss_throwObject(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3) { Actor *temp_v0; ActorLocal_FinalBoss *local; f32 sp2C[3]; @@ -441,6 +459,7 @@ void chfinalboss_func_80387110(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 a D_80392768[i] = (sp2C[i] - arg1[i]) / arg2 - (D_80392778[i] * arg2 / 2); } if (arg3 == 0) { + __chFinalBossFireballFlightTime = arg2; SPAWNQUEUE_ADD_1(chfinalboss_func_80386FD8, marker); } else{ @@ -448,14 +467,14 @@ void chfinalboss_func_80387110(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 a } } -void chfinalboss_func_803872F8(Actor *arg0) { +void chfinalboss_throwFinalSpell(Actor *arg0) { f32 vec[3]; vec3fArray_get_vec3f(arg0->marker->unk44, 0xA, vec); - chfinalboss_func_80387110(arg0->marker, vec, 3.0f, 1); + chfinalboss_throwObject(arg0->marker, vec, 3.0f, 1); } -s32 chfinalboss_func_80387340(Actor *this, f32 arg1) { +s32 chfinalboss_throwFireball(Actor *this, f32 arg1) { f32 sp24[3]; if (actor_animationIsAt(this, 0.50f) != 0) { @@ -466,7 +485,7 @@ s32 chfinalboss_func_80387340(Actor *this, f32 arg1) { sp24[1] = this->position_y; sp24[2] = this->position_z; } - chfinalboss_func_80387110(this->marker, sp24, arg1, 0); + chfinalboss_throwObject(this->marker, sp24, arg1, 0); return 1; } return 0; @@ -928,7 +947,7 @@ void chfinalboss_phase1_update(ActorMarker *marker) { chfinalboss_func_80386600(this->marker, 0); chfinalboss_spawnBroomstickGlowParticles(this); chfinalboss_func_80387ACC(this, 60.0f * sp54); - if (chfinalboss_func_80386BEC(this, 240.0f * sp54)) { + if (chfinalboss_turnTowardPlayer(this, 240.0f * sp54)) { chfinalboss_phase1_setState(this, 5); chfinalboss_func_80386654(1.0f, fight_D_80391380, fight_D_80391390); } @@ -1026,9 +1045,9 @@ void chfinalboss_phase1_update(ActorMarker *marker) { break; case 10: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_func_80386BEC(this, 30.0f); + chfinalboss_turnTowardPlayer(this, 30.0f); chfinalboss_func_8038871C(this, 460.0f, 400.0f * sp54); - chfinalboss_func_80387340(this, 1.0f); + chfinalboss_throwFireball(this, 1.0f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_phase1_setState(this, 2); chfinalboss_func_803880A0(this, 2000.0f); @@ -1036,14 +1055,14 @@ void chfinalboss_phase1_update(ActorMarker *marker) { break; case 11: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_func_80386BEC(this, 30.0f); + chfinalboss_turnTowardPlayer(this, 30.0f); if (local->unk9) { chfinalboss_func_8038871C(this, 460.0f, 400.0f * sp54); } break; case 12: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_func_80386BEC(this, 30.0f); + chfinalboss_turnTowardPlayer(this, 30.0f); chfinalboss_func_8038871C(this, 460.0f, 400.0f * sp54); chfinalboss_func_803873DC(this, 600.0f, 2000.0f); if (actor_animationIsAt(this, 0.9999f)) { @@ -1054,7 +1073,7 @@ void chfinalboss_phase1_update(ActorMarker *marker) { break; case 13: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_func_80386BEC(this, 30.0f); + chfinalboss_turnTowardPlayer(this, 30.0f); if (actor_animationIsAt(this, 0.9999f)) { if (local->hits >= 4) { chfinalboss_phase1_setState(this, 0xB); @@ -1127,13 +1146,13 @@ void chfinalboss_phase2_update(ActorMarker *marker) { break; case 15: - if (chfinalboss_func_80386BEC(this, 9.0f)) { + if (chfinalboss_turnTowardPlayer(this, 9.0f)) { chfinalboss_phase2_setState(this, 0x10); } break; case 16: - chfinalboss_func_80386BEC(this, 3.0f); - chfinalboss_func_80387340(this, 1.3f); + chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_throwFireball(this, 1.3f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_phase2_setState(this, 0x12); local->unk3++; @@ -1147,19 +1166,19 @@ void chfinalboss_phase2_update(ActorMarker *marker) { } break; case 17: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); chfinalboss_func_803873DC(this, 1200.0f, 2400.0f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_setPhase(this->marker, FINALBOSS_PHASE_3_FLIGHT); } break; case 18: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); if (this->lifetime_value > 0.0) { this->lifetime_value = this->lifetime_value - sp4C; break; } - if (chfinalboss_func_80386BEC(this, 3.0f)) { + if (chfinalboss_turnTowardPlayer(this, 3.0f)) { chfinalboss_phase2_setState(this, 0x10); } break; @@ -1220,6 +1239,7 @@ void __chfinalboss_spawnStatue(enum ch_bossjinjo_e statue_id) { } sp1C->lifetime_value = (statue_id == BOSSJINJO_5_JINJONATOR) ? 5.25f : 1.54f; sp1C->actorTypeSpecificField = statue_id; + FightSync_OnStatueSpawned(statue_id); } void chfinalboss_spawnStatue(s32 statue_id) { @@ -1232,6 +1252,7 @@ void __chfinalboss_spawnSpellBarrier(ActorMarker *marker) { actor = marker_getActor(marker); actor->partnerActor = spawn_child_actor(ACTOR_3AB_GRUNTY_SPELL_BARRIER, &actor)->marker; __chFinalBossSpellBarrierActive = true; + FightSync_OnBarrierSpawned(); } void chfinalboss_spawnSpellBarrier(ActorMarker *arg0) { @@ -1333,13 +1354,13 @@ void chfinalboss_phase3_update(ActorMarker *marker) { } break; case 23: - if (chfinalboss_func_80386BEC(this, 9.0f) && (baiFrame_getState() != 3)) { + if (chfinalboss_turnTowardPlayer(this, 9.0f) && (baiFrame_getState() != 3)) { chfinalboss_phase3_setState(this, 0x18); } break; case 24: - chfinalboss_func_80386BEC(this, 3.0f); - if (chfinalboss_func_80387340(this, 1.3f)) { + chfinalboss_turnTowardPlayer(this, 3.0f); + if (chfinalboss_throwFireball(this, 1.3f)) { local->unk3++; } if (actor_animationIsAt(this, 0.9999f)) { @@ -1546,6 +1567,8 @@ void chfinalboss_phase4_update(ActorMarker *marker) { sp70 = local->hits; sp6C = chfinalboss_findCollidingJinjo(this, func_8033229C(this->marker)); if (sp6C != NULL) { + // Anchor: only the authority detects the slam; despawn followers' copy of this jinjo too. + FightSync_OnJinjoSlam(marker_getActor(sp6C)->actorTypeSpecificField); chbossjinjo_attack(sp6C); if (!fileProgressFlag_get(FILEPROG_D1_HAS_ACTIVATED_A_JINJO_STATUE_IN_FINAL_FIGHT)) { fileProgressFlag_set(FILEPROG_D1_HAS_ACTIVATED_A_JINJO_STATUE_IN_FINAL_FIGHT, true); @@ -1580,15 +1603,15 @@ void chfinalboss_phase4_update(ActorMarker *marker) { break; case 29: - if ((chfinalboss_func_80386BEC(this, 9.0f)) && (baiFrame_getState() != 3) && (sFinalBossJinjoStatueActivated == 0)) { + if ((chfinalboss_turnTowardPlayer(this, 9.0f)) && (baiFrame_getState() != 3) && (sFinalBossJinjoStatueActivated == 0)) { chfinalboss_phase4_setState(this, 0x1E); } break; case 30: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); if (sFinalBossJinjoStatueActivated == 0) { - chfinalboss_func_80387340(this, 1.0f); + chfinalboss_throwFireball(this, 1.0f); if (actor_animationIsAt(this, 0.9999f)) { local->unk3++; chfinalboss_phase4_setState(this, 0x1F); @@ -1600,12 +1623,12 @@ void chfinalboss_phase4_update(ActorMarker *marker) { break; case 31: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); if (this->lifetime_value > 0.0) { this->lifetime_value -= sp74; break; } - if (chfinalboss_func_80386BEC(this, 3.0f)) { + if (chfinalboss_turnTowardPlayer(this, 3.0f)) { chfinalboss_phase4_setState(this, 0x1E); } break; @@ -1617,7 +1640,7 @@ void chfinalboss_phase4_update(ActorMarker *marker) { break; case 33: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); sp5C[0] = this->position[0] + (this->velocity[0] * sp74); sp5C[1] = this->position[1] + (this->velocity[1] * sp74); sp5C[2] = this->position[2] + (this->velocity[2] * sp74); @@ -1815,22 +1838,22 @@ void chfinalboss_phase5_update(ActorMarker *marker) { } switch (this->state) { case 35: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); break; case 36: - if (chfinalboss_func_80386BEC(this, 9.0f) && (baiFrame_getState() != 3)) { + if (chfinalboss_turnTowardPlayer(this, 9.0f) && (baiFrame_getState() != 3)) { chfinalboss_phase5_setState(this, 0x25); } break; case 37: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); if (baiFrame_getState() == 3) { chfinalboss_phase5_setState(this, 0x24); break; } - if (chfinalboss_func_80387340(this, 1.0f)) { + if (chfinalboss_throwFireball(this, 1.0f)) { local->unk3++; } if ((actor_animationIsAt(this, 0.9999f)) && (local->unk3 >= 5)) { @@ -1839,7 +1862,7 @@ void chfinalboss_phase5_update(ActorMarker *marker) { break; case 38: - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); chfinalboss_func_803873DC(this, 700.0f, 2400.0f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_phase5_setState(this, 0x27); @@ -1851,7 +1874,7 @@ void chfinalboss_phase5_update(ActorMarker *marker) { if (local->unk8) { chfinalboss_func_80386C68(this, 4.5f); } else { - chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_turnTowardPlayer(this, 3.0f); } if (this->lifetime_value > 0.0) { this->lifetime_value -= dt; @@ -1924,7 +1947,7 @@ void chfinalboss_phase5_update(ActorMarker *marker) { FUNC_8030E624(SFX_130_GRUNTY_ECHOING_CRY, 1.0f, 32000); } if (actor_animationIsAt(this, 0.85f)) { - chfinalboss_func_803872F8(this); + chfinalboss_throwFinalSpell(this); } if (actor_animationIsAt(this, 0.9f)) { ncStaticCamera_exit(); @@ -2020,6 +2043,10 @@ void chfinalboss_collisionPassive(ActorMarker *marker, ActorMarker *other_marker this = marker_getActor(marker); local = (ActorLocal_FinalBoss *)&this->local; + // Anchor: follower's hit is forwarded to the authority (with phase). + if (other_marker != NULL && FightSync_ForwardBossHit(local->phase)) { + return; + } switch (local->phase) { case 1: if (local->hits == 0) { @@ -2123,6 +2150,7 @@ void chfinalboss_update(Actor *this){ local->unk8 = 0; local->unk9 = 0; local->unkB = 0; + FightSync_OnBossSpawned(); for(i = 0; i < 4; i++){ __chFinalBossJinjoStatueMarker[i] = NULL; @@ -2148,6 +2176,8 @@ void chfinalboss_update(Actor *this){ timed_playSfx(2.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 32000); }//L8038BF0C + // Anchor: followers skip the boss brain - state rides FIGHT_UPDATE/FIGHT_EVENT instead. + if (!FightSync_BossFollowerTick(this)) switch(local->phase) { case FINALBOSS_PHASE_0_INTRO: chfinalboss_phase0_update(this->marker); @@ -2241,6 +2271,7 @@ void chfinalboss_setBossDefeated(void) { sp4C = actorArray_findActorFromActorId(ACTOR_38B_GRUNTILDA_FINAL_BOSS); sp48 = (ActorLocal_FinalBoss *)&sp4C->local; + FightSync_OnBossDefeated(); sp34 = chstonejinjo_getBreakUpTime(); temp_f20 = sp34 + chjinjonator_80391234(); sp40 = chjinjonator_80391240(); diff --git a/src/FINALE/chgreenblast.c b/src/fight/chgreenblast.c similarity index 100% rename from src/FINALE/chgreenblast.c rename to src/fight/chgreenblast.c diff --git a/src/FINALE/ch/chjinjonator.c b/src/fight/chjinjonator.c similarity index 99% rename from src/FINALE/ch/chjinjonator.c rename to src/fight/chjinjonator.c index 470f72003..4566ed1b9 100644 --- a/src/FINALE/ch/chjinjonator.c +++ b/src/fight/chjinjonator.c @@ -2,7 +2,7 @@ #include #include "functions.h" #include "variables.h" -#include "../fight.h" +#include "fight.h" extern void func_80324CFC(f32, s32, s32); extern void func_802F9E44(s32, f32, f32, f32, f32); diff --git a/src/FINALE/ch/chjinjonatorbase.c b/src/fight/chjinjonatorbase.c similarity index 85% rename from src/FINALE/ch/chjinjonatorbase.c rename to src/fight/chjinjonatorbase.c index e2d52a7e4..591f74524 100644 --- a/src/FINALE/ch/chjinjonatorbase.c +++ b/src/fight/chjinjonatorbase.c @@ -2,7 +2,9 @@ #include #include "functions.h" #include "variables.h" -#include "../fight.h" +#include "fight.h" + +#include "port/Network/Anchor/FightSync.h" typedef struct { u8 egg_hits[4]; @@ -42,18 +44,16 @@ void chjinjonatorbase_func_8038E0D4(Actor *arg0, s32 arg1, f32 arg2, f32 arg3, f } } -void chjinjonatorbase_getHitByEgg(ActorMarker *this, ActorMarker *other) { - Actor *actor_jinjonatorbase = marker_getActor(this); +static void __chjinjonatorbase_applyEgg(Actor *actor_jinjonatorbase, s32 indx) { ActorLocal_BossJinjonatorBase *local = (ActorLocal_BossJinjonatorBase *) &actor_jinjonatorbase->local; - int indx = this->unk40_31 - 1; s32 remaining_hits; - f32 pad; if (actor_jinjonatorbase->state != CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { if (local->egg_hits[indx]) { local->egg_hits[indx]--; comusic_playTrack(COMUSIC_2B_DING_B); - + FightSync_ReplicateEgg(BOSSJINJO_5_JINJONATOR, indx); + if (local->egg_hits[indx] <= 0) { chjinjonatorbase_func_8038E0D4(actor_jinjonatorbase, indx + 0x19a, -100.0f, 0.0f, 1.2f); func_80324D54(1.2f, SFX_90_SWITCH_PRESS, 1.0f, 32000, actor_jinjonatorbase->position, 1000.0f, 2000.0f); @@ -70,6 +70,46 @@ void chjinjonatorbase_getHitByEgg(ActorMarker *this, ActorMarker *other) { } } +void chjinjonatorbase_getHitByEgg(ActorMarker *this, ActorMarker *other) { + Actor *actor_jinjonatorbase = marker_getActor(this); + int indx = this->unk40_31 - 1; + + // Anchor: follower forwards to authority; accepted egg replays via EGG_FED. + if (other != NULL && FightSync_ForwardEgg(BOSSJINJO_5_JINJONATOR, indx)) { + return; + } + + __chjinjonatorbase_applyEgg(actor_jinjonatorbase, indx); +} + +// Anchor: remaining-egg count per pad for the latecomer snapshot; false if pedestal isn't up. +bool chjinjonatorbase_netGetPads(u8 pads[4]) { + Actor *actor_jinjonatorbase = actorArray_findActorFromActorId(ACTOR_3A9_JINJONATOR_STATUE_BASE); + ActorLocal_BossJinjonatorBase *local; + s32 i; + + if (actor_jinjonatorbase == NULL || actor_jinjonatorbase->despawn_flag) { + for (i = 0; i < 4; i++) { + pads[i] = 5; + } + return false; + } + local = (ActorLocal_BossJinjonatorBase *) &actor_jinjonatorbase->local; + for (i = 0; i < 4; i++) { + pads[i] = local->egg_hits[i]; + } + return true; +} + +void chjinjonatorbase_netApplyEgg(s32 pad_index) { + Actor *actor_jinjonatorbase = actorArray_findActorFromActorId(ACTOR_3A9_JINJONATOR_STATUE_BASE); + + if (actor_jinjonatorbase == NULL || pad_index < 0 || pad_index >= 4) { + return; + } + __chjinjonatorbase_applyEgg(actor_jinjonatorbase, pad_index); +} + void chjinjonatorbase_spawnActivator(ActorMarker *marker) { Actor *sp24 = marker_getActor(marker); diff --git a/src/FINALE/chspellbarrier.c b/src/fight/chspellbarrier.c similarity index 100% rename from src/FINALE/chspellbarrier.c rename to src/fight/chspellbarrier.c diff --git a/src/FINALE/chspellfireball.c b/src/fight/chspellfireball.c similarity index 100% rename from src/FINALE/chspellfireball.c rename to src/fight/chspellfireball.c diff --git a/src/FINALE/chstonejinjo.c b/src/fight/chstonejinjo.c similarity index 100% rename from src/FINALE/chstonejinjo.c rename to src/fight/chstonejinjo.c diff --git a/src/FINALE/fight.c b/src/fight/fight.c similarity index 99% rename from src/FINALE/fight.c rename to src/fight/fight.c index c068e4ef9..c22543b63 100644 --- a/src/FINALE/fight.c +++ b/src/fight/fight.c @@ -6,8 +6,6 @@ #include "fight.h" #include "actor.h" -u8 sFightPadding[0x10]; - void fight_addSpawnableActors(void) { spawnableActorList_add(&chSpellFireball, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20); diff --git a/src/FINALE/fight.h b/src/fight/fight.h similarity index 94% rename from src/FINALE/fight.h rename to src/fight/fight.h index d0bcd7bda..7f960766a 100644 --- a/src/FINALE/fight.h +++ b/src/fight/fight.h @@ -84,6 +84,34 @@ extern ActorInfo chGreenBlast; extern ActorInfo chJinjonator; extern ActorInfo chBossShadow; +// Moved from chfinalboss.c for the Anchor fight-sync layer. +typedef struct chfinalboss_s { + u8 phase; + u8 hits; + u8 unk2; + u8 unk3; + u8 unk4; + u8 unk5; + u8 player_hit_in_phase3; + u8 mirror_phase5; + u8 unk8; + u8 unk9; + u8 unkA; + u8 unkB; + u8 unkC; + u8 unkD; + u8 unkE; + u8 unkF; + s32 player_hit_in_phase1; + f32 unk14; + f32 unk18; + f32 unk1C; + f32 unk20; + u8 pad24[4]; + f32 unk28; + f32 unk2C; +} ActorLocal_FinalBoss; + // fight.c extern void fight_addSpawnableActors(void); @@ -99,7 +127,7 @@ extern void chfinalboss_createGreenGlowParticle(f32 position[3], s32 color[3]); extern void chfinalboss_createSingleSpriteParticle(f32 position[3], enum asset_e sprite_id); extern void chfinalboss_spawnBroomstickGlowParticles(Actor *this); extern void chfinalboss_func_80386B54(f32 *arg0, f32 arg1); -extern bool chfinalboss_func_80386BEC(Actor *this, f32 arg1); +extern bool chfinalboss_turnTowardPlayer(Actor *this, f32 arg1); extern bool chfinalboss_func_80386C68(Actor *this, f32 arg1); extern void chfinalboss_func_80386CF8(Actor *actor); extern void __chfinalboss_dropHealth(ActorMarker *arg0); @@ -109,9 +137,9 @@ extern void chfinalboss_func_80386EC0(s32 arg0); extern void chfinalboss_func_80386F5C(ActorMarker * arg0, f32 arg1[3], f32 arg2, f32 arg3); extern void chfinalboss_func_80386FD8(s32 arg0); extern void chfinalboss_func_80387074(s32 arg0); -extern void chfinalboss_func_80387110(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3); -extern void chfinalboss_func_803872F8(Actor *arg0); -extern s32 chfinalboss_func_80387340(Actor *this, f32 arg1); +extern void chfinalboss_throwObject(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3); +extern void chfinalboss_throwFinalSpell(Actor *arg0); +extern s32 chfinalboss_throwFireball(Actor *this, f32 arg1); extern void chfinalboss_func_803873DC(Actor *actor, f32 arg1, f32 arg2); extern bool chfinalboss_flyTo(Actor *this, f32 arg1[3], f32 v_max, f32 arg3, f32 arg4, f32 arg5, f32 arg6); extern void chfinalboss_func_8038770C(Actor *actor); diff --git a/src/LAIR/ch/brentilda.c b/src/lair/ch/brentilda.c similarity index 95% rename from src/LAIR/ch/brentilda.c rename to src/lair/ch/brentilda.c index 57e78e5c4..e5398be76 100644 --- a/src/LAIR/ch/brentilda.c +++ b/src/lair/ch/brentilda.c @@ -19,13 +19,13 @@ ActorAnimationInfo chBrentildaAnimations[] ={ ActorInfo chBrentilda = { 0x1E0, 0x348, 0x539, 0x1, chBrentildaAnimations, chBrentilda_update, actor_update_func_80326224, actor_draw, 2000, 0, 2.0f, 0}; /* .code */ -void func_8038BA30(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +s32 func_8038BA30(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; s32 phi_v1; this = marker_getActor(marker); phi_v1 = this->unk10_12*2; - volatileFlag_getN(VOLATILE_FLAG_20_BEGIN_CHARACTER_PARADE + this->actorTypeSpecificField*6 + phi_v1, 2); + return volatileFlag_getN(VOLATILE_FLAG_20_BEGIN_CHARACTER_PARADE + this->actorTypeSpecificField*6 + phi_v1, 2); } void healDuoToFull(ActorMarker *marker, enum asset_e text_id, s32 arg2){ @@ -40,7 +40,8 @@ void func_8038BADC(ActorMarker *marker, enum asset_e text_id, s32 arg2) { Actor *this; this = marker_getActor(marker); - if (text_id == ((ActorLocal_lair_5640 *)&this->local)->unk0 + 2) { + if (text_id == ((ActorLocal_lair_5640 *)&this->local)->unk0 + 2 + && EventSystem_Should(VB_BRENTILDA_HEAL_DIALOG, true)) { if (!fileProgressFlag_get(this->actorTypeSpecificField - 1 + FILEPROG_E9_HEALED_BY_BRENTILDA_1)) { if (item_getCount(ITEM_14_HEALTH) < item_getCount(ITEM_15_HEALTH_TOTAL)) { gcdialog_showDialog(ASSET_10A2_DIALOG_BRENTILDA_HEAL, 0xF, this->position, this->marker, func_8038BADC, healDuoToFull); @@ -178,7 +179,7 @@ void chBrentilda_update(Actor *this) { } if( (phi_f2 < 300.0) && (player_movementGroup() == BSGROUP_0_NONE) - && func_8028F20C() + && player_isStableWithExtraSteps() && !gcdialog_hasCurrentTextId()) { if (!fileProgressFlag_get(FILEPROG_96_MET_BRENTILDA)) { gcdialog_showDialog(ASSET_10A1_DIALOG_BRENTILDA_MEET, 0xA, this->position, this->marker, func_8038BADC, NULL); diff --git a/src/LAIR/ch/cauldron.c b/src/lair/ch/cauldron.c similarity index 98% rename from src/LAIR/ch/cauldron.c rename to src/lair/ch/cauldron.c index 18ff35ec1..e2e24e790 100644 --- a/src/LAIR/ch/cauldron.c +++ b/src/lair/ch/cauldron.c @@ -166,7 +166,7 @@ void func_8038AB90(Actor *this, s32 arg1, s32 arg2, enum sfx_e sfx_id, f32 sfx_t if (arg2 == 2) { coMusicPlayer_playMusicWeak(COMUSIC_3F_MAGIC_CARPET_RISING, 32000); func_80324D2C(2.6f, COMUSIC_3F_MAGIC_CARPET_RISING); - gcsfx_playAtSampleRate(SFX_7C_CHEBOOF); + gcsfx_play(SFX_7C_CHEBOOF); } } } @@ -351,7 +351,7 @@ void chWarpCauldron_update(Actor *this) { case 5: //L8038B48C func_8038A96C(this, 3); if (actor_animationIsAt(this, 0.01f)) { - gcsfx_playAtSampleRate(SFX_7C_CHEBOOF); + gcsfx_play(SFX_7C_CHEBOOF); } if (actor_animationIsAt(this, 0.63f)) { volatileFlag_set(VOLATILE_FLAG_1E, 0); @@ -435,8 +435,8 @@ Actor *chWarpCauldron_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) this = marker_getActor(marker); if(this->modelCacheIndex == ACTOR_23B_WARP_CAULDRON) { - func_8033A45C(3, BOOL(this->unk38_0)); - func_8033A45C(4, this->unk38_0 ? false : true); + modelRender_setAppendageVisibility(3, BOOL(this->unk38_0)); + modelRender_setAppendageVisibility(4, this->unk38_0 ? false : true); } this = actor_draw(marker, gfx, mtx, vtx); if (marker->unk14_21 && this->unk38_0 && (getGameMode() != GAME_MODE_4_PAUSED)) { diff --git a/src/LAIR/ch/cheato.c b/src/lair/ch/cheato.c similarity index 96% rename from src/LAIR/ch/cheato.c rename to src/lair/ch/cheato.c index bff79a50a..0b5388c37 100644 --- a/src/LAIR/ch/cheato.c +++ b/src/lair/ch/cheato.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_9C40.c +// BanjoDecomp: lair/ch/cheato.c #include #include "functions.h" #include "variables.h" @@ -17,8 +17,8 @@ ActorInfo D_803948B8 = { 0x16F, 0x1D7, 0x54F, 0x1, D_80394860, func_803902B8, ac /* .code */ Actor *func_80390030(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C(3, 1); - func_8033A45C(4, 1); + modelRender_setAppendageVisibility(3, 1); + modelRender_setAppendageVisibility(4, 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -94,7 +94,7 @@ void func_803902B8(Actor *this) { this->has_met_before = volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE); this->initialized = true; } - _player_getPosition(sp5C); + playerPosition_get(sp5C); sp58 = ml_vec3f_within_distance(this->position, sp5C, 1750.0f) && !this->has_met_before; if (sp58 && !this->unk38_0) { func_8032BB88(this, 0, 0x1F4); diff --git a/src/LAIR/ch/minigame_ffprize.c b/src/lair/ch/furnacefunprizes.c similarity index 97% rename from src/LAIR/ch/minigame_ffprize.c rename to src/lair/ch/furnacefunprizes.c index dde3d4b26..66a69b41e 100644 --- a/src/LAIR/ch/minigame_ffprize.c +++ b/src/lair/ch/furnacefunprizes.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_BBD0.c +// BanjoDecomp: lair/ch/furnacefunprizes.c #include #include "functions.h" #include "variables.h" @@ -43,8 +43,8 @@ ActorInfo D_80394C94 = { MARKER_29A_FF_PRIZE, ACTOR_3C8_FF_PRIZE_TOOTY, ASSET_35 /* .code */ Actor *func_80391FC0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C(4, 1); - func_8033A45C(5, 1); + modelRender_setAppendageVisibility(4, 1); + modelRender_setAppendageVisibility(5, 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/LAIR/ch/gruntling.c b/src/lair/ch/gruntling.c similarity index 99% rename from src/LAIR/ch/gruntling.c rename to src/lair/ch/gruntling.c index 353e13e31..ce3125ac1 100644 --- a/src/LAIR/ch/gruntling.c +++ b/src/lair/ch/gruntling.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_A4A0.c +// BanjoDecomp: lair/ch/gruntling.c #include #include "functions.h" #include "variables.h" diff --git a/src/LAIR/ch/grunty_final.c b/src/lair/ch/lairgruntilda.c similarity index 95% rename from src/LAIR/ch/grunty_final.c rename to src/lair/ch/lairgruntilda.c index 4aad4aaa2..f635457c9 100644 --- a/src/LAIR/ch/grunty_final.c +++ b/src/lair/ch/lairgruntilda.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_C1C0.c +// BanjoDecomp: lair/ch/lairgruntilda.c #include #include "functions.h" #include "variables.h" @@ -21,9 +21,9 @@ ActorInfo D_80394CF0 = { 0x29B, 0x3C5, 0x53D, 0x1, D_80394CC0, func_80392700, fu /* .code */ Actor *func_803925B0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C(3, 0); - func_8033A45C(4, 0); - func_8033A45C(5, 0); + modelRender_setAppendageVisibility(3, 0); + modelRender_setAppendageVisibility(4, 0); + modelRender_setAppendageVisibility(5, 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/LAIR/ch/item_pillows.c b/src/lair/ch/refillpillow.c similarity index 94% rename from src/LAIR/ch/item_pillows.c rename to src/lair/ch/refillpillow.c index df541c8e5..e9b9f5d35 100644 --- a/src/LAIR/ch/item_pillows.c +++ b/src/lair/ch/refillpillow.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_A170.c +// BanjoDecomp: lair/ch/refillpillow.c #include #include "functions.h" #include "variables.h" @@ -26,8 +26,8 @@ ActorInfo D_80394958 = { 0x172, 0x1DA, 0x549, 0x1, D_80394900, func_803906A0, ac /* .code */ Actor *func_80390560(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - func_8033A45C(3, marker->collidable); - func_8033A45C(4, marker->collidable); + modelRender_setAppendageVisibility(3, marker->collidable); + modelRender_setAppendageVisibility(4, marker->collidable); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/lair/checksums.c b/src/lair/checksums.c new file mode 100644 index 000000000..dd033ff12 --- /dev/null +++ b/src/lair/checksums.c @@ -0,0 +1,7 @@ +// BanjoDecomp: lair/checksums.c +#include +#include "checksums.h" + +// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! + +/* bss */ struct overlay_checksums_s gChecksumsLair; diff --git a/src/LAIR/ch/fall_damagedetect.c b/src/lair/fall_damagedetect.c similarity index 100% rename from src/LAIR/ch/fall_damagedetect.c rename to src/lair/fall_damagedetect.c diff --git a/src/LAIR/ch/ff_lava_fireball.c b/src/lair/ff_lava_fireball.c similarity index 100% rename from src/LAIR/ch/ff_lava_fireball.c rename to src/lair/ff_lava_fireball.c diff --git a/src/LAIR/ch/ff_lava_fireball_actor.c b/src/lair/ff_lava_fireball_actor.c similarity index 100% rename from src/LAIR/ch/ff_lava_fireball_actor.c rename to src/lair/ff_lava_fireball_actor.c diff --git a/src/LAIR/ff_manager.c b/src/lair/ff_manager.c similarity index 97% rename from src/LAIR/ff_manager.c rename to src/lair/ff_manager.c index 4f93e4c56..fb12c5fd2 100644 --- a/src/LAIR/ff_manager.c +++ b/src/lair/ff_manager.c @@ -5,9 +5,8 @@ #include "model.h" #include "core2/gc/zoombox.h" -#include "core2/quiz_storage.h" #include "core2/nc/camera.h" - +#include "core2/quiz/storage.h" #define ARRLEN(x) ((s32)(sizeof(x) / sizeof(x[0]))) @@ -947,17 +946,17 @@ void ff_setState(enum FF_Action next_state) { if (((s32) ffStorage->currentBoardTile->tileType >= 7) && (quizQuestionAskedBitfield_get(func_8038D60C(ffStorage->currentTileId)) == 0)) { item_adjustByDiffWithHud(ITEM_27_JOKER_CARD, ffStorage->currentBoardTile->tileType - 6); quizQuestionAskedBitfield_set(func_8038D60C(ffStorage->currentTileId), true); - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A8_FF_GOT_JOKER); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A8_FF_GOT_JOKER); } if (ffStorage->currentTileId != 0x1EF) { gcsfx_playWithPitch(SFX_126_AUDIENCE_BOOING, 1.0f, 0x7FF8); if (ffStorage->currentBoardTile->tileType == FFTT_5_GRUNTY) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT); } if (volatileFlag_get(VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT)) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT); } - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT); } } else { if (ffStorage->currentBoardTile->tileType == FFTT_6_SKULL) { @@ -984,9 +983,9 @@ void ff_setState(enum FF_Action next_state) { lair_func_8038C640(ffStorage->currentTileId, ffStorage->currentBoardTile); } if (volatileFlag_get(VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG)) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG); } - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG); } break; @@ -1137,8 +1136,8 @@ void func_8038E070(void) void lair_func_8038E0B0(void) { s32 sp48[6]; //buttons s32 temp_v0; - s32 sp3C[2]; //joystick - s32 sp38; + s32 sp3C[3]; //side buttons (Z, L, R) + s32 ff_tile_type; s32 sp28; if( (gsworld_getMap() == MAP_8E_GL_FURNACE_FUN) @@ -1160,11 +1159,12 @@ void lair_func_8038E0B0(void) { ffStorage->currentTileId = temp_v0; ffStorage->currentBoardTile = ff_getCurrentBoardTile(ffStorage->currentTileId); } - sp38 = MIN((ffStorage->currentTileId != 0) ? ffStorage->currentBoardTile->tileType : -1, FFTT_7_JOKER); - if ((ffStorage->currentTileId != 0) && (ffStorage->currentBoardTile->unk9 == 0) && func_8028F20C()) { + // If you see FFTT_8_JOKER in the table, use FFTT_7_JOKER instead + ff_tile_type = MIN((ffStorage->currentTileId != 0) ? ffStorage->currentBoardTile->tileType : -1, FFTT_7_JOKER); + if ((ffStorage->currentTileId != 0) && (ffStorage->currentBoardTile->unk9 == 0) && player_isStableWithExtraSteps()) { ffStorage->currentBoardTile->unk9 = 2; if (ffStorage->unk11) { - switch(sp38){ + switch(ff_tile_type){ case FFTT_6_SKULL://L8038E26C comusic_playTrack(COMUSIC_7B_STEP_ON_SKULL_TILE); break; @@ -1220,23 +1220,23 @@ void lair_func_8038E0B0(void) { } code_73640_printItemCount(0x14); code_73640_printItemCount(0x16); - if (sp38 != FFTT_0_NIL) { - sp28 = sp38 - 1 + FILEPROG_55_FF_BK_SQUARE_INSTRUCTIONS; - if (!fileProgressFlag_get(sp28) && gcdialog_showDialog(sp38 + 0x101E, 0, NULL, NULL, NULL, NULL)) { + if (ff_tile_type != FFTT_0_NIL) { + sp28 = ff_tile_type - 1 + FILEPROG_55_FF_BK_SQUARE_INSTRUCTIONS; + if (!fileProgressFlag_get(sp28) && gcdialog_showDialog(ff_tile_type + 0x101E, 0, NULL, NULL, NULL, NULL)) { fileProgressFlag_set(sp28, true); } s32 ffLifeThreshold = 1; CALL_EVENT(OnFurnaceFunDialog, &ffLifeThreshold); - if ((sp38 == FFTT_6_SKULL) && (item_getCount(ITEM_16_LIFE) == ffLifeThreshold)) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL); + if ((ff_tile_type == FFTT_6_SKULL) && (item_getCount(ITEM_16_LIFE) == ffLifeThreshold)) { + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL); } else if (item_getCount(ITEM_14_HEALTH) == 1) { - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_AA_FF_LOW_HEALTH); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_AA_FF_LOW_HEALTH); } if ((ffStorage->currentBoardTile->unk9 == 2) && (player_movementGroup() == BSGROUP_0_NONE)) { if (func_8028EFEC() && (sp48[FACE_BUTTON(BUTTON_A)] == 1)) { func_803114D0(); player_getRotation(ffStorage->playerRotation); - ffStorage->ffQuestionType = ff_getQuestionType(sp38); + ffStorage->ffQuestionType = ff_getQuestionType(ff_tile_type); ff_prepareNextQuestion(ffStorage->ffQuestionType); ff_setState(3); return; @@ -1246,7 +1246,7 @@ void lair_func_8038E0B0(void) { lair_func_8038C640(ffStorage->currentTileId, ffStorage->currentBoardTile); item_dec(ITEM_27_JOKER_CARD); func_8030E6D4(SFX_3EA_BANJO_GUH_HUH); - volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A9_FF_USED_JOKER); + progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A9_FF_USED_JOKER); if (ffStorage->currentTileId == 0x1EF) { ff_setState(8); } diff --git a/src/LAIR/jigsawpicture.c b/src/lair/jigsawpicture.c similarity index 79% rename from src/LAIR/jigsawpicture.c rename to src/lair/jigsawpicture.c index da648a147..12bc1aeae 100644 --- a/src/LAIR/jigsawpicture.c +++ b/src/lair/jigsawpicture.c @@ -2,7 +2,10 @@ #include #include "functions.h" #include "variables.h" +#include "jigsawpicture.h" #include "port/Romhack/RomhackConfig.h" +#include "port/Network/Anchor/JigsawPedestal.h" +#include "port/Enhancements/Events/Hooks/Events.h" extern void player_walkToPosition(f32[3], f32, void(*)(ActorMarker *), ActorMarker *); extern void func_80324CFC(f32, enum comusic_e, s32); extern void rand_seed(s32); @@ -23,10 +26,13 @@ typedef struct { void jigsawPicture_setState(Actor *this, s32 next_state); void updateJigsawPictureActor(Actor *this); +Actor *jigsawPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); + +static s32 sBuzzedPedestalField = 0; /* .data */ -ActorInfo JIGSAW_PICTURE_ACTOR = { 0x1EB, 0x3B7, 0x48B, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo JIGSAW_PICTURE_ACTOR_2 = { 0x1EB, 0x3BC, 0x538, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo JIGSAW_PICTURE_ACTOR = { 0x1EB, 0x3B7, 0x48B, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, jigsawPicture_draw, 0, 0, 0.0f, 0}; +ActorInfo JIGSAW_PICTURE_ACTOR_2 = { 0x1EB, 0x3BC, 0x538, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, jigsawPicture_draw, 0, 0, 0.0f, 0}; Struct_lair_86F0_0 D_803947F8[0xb] ={ { 1, 0x1, FILEPROG_5D_MM_PUZZLE_PIECES_PLACED}, { 2, 0x2, FILEPROG_5E_TTC_PUZZLE_PIECES_PLACED}, @@ -55,9 +61,19 @@ s32 _puzzleCost(s32 index) { return (override >= 0) ? override : D_803947F8[index].cost; } +s32 _puzzleSize(s32 index) { + s32 override = port_getRomhackJiggyPuzzleSize(index); + return (override >= 0) ? override : D_803947F8[index].size_bits; +} + +s32 _puzzleFlag(s32 index) { + s32 override = port_getRomhackJiggyPuzzleFlag(index); + return (override >= 0) ? override : D_803947F8[index].progress_flag; +} + bool jigsawPicture_isJigsawPictureComplete(s32 arg0) { s32 cost = _puzzleCost(arg0 - 1); - return fileProgressFlag_getN(D_803947F8[arg0 -1].progress_flag, D_803947F8[arg0 -1].size_bits) == cost; + return fileProgressFlag_getN(_puzzleFlag(arg0 - 1), _puzzleSize(arg0 - 1)) == cost; } s32 getPictureCost(Actor *this){ @@ -113,7 +129,7 @@ void onJigsawPodiumCollide(ActorMarker *marker, ActorMarker *other_marker){ } bool isBanjoOnPodium(ActorMarker *marker) { - return func_8028F20C() && func_8028FB48(0x08000000) && marker->isBanjoOnTop; + return player_isStableWithExtraSteps() && func_8028FB48(0x08000000) && marker->isBanjoOnTop; } s32 isPicturePiecePlaced(Actor *this, s32 arg1){ @@ -302,6 +318,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ vec3fArray_get_vec3f(func_803097A0(), getUnknownJigsawPictureIndex(this), sp50); switch (next_state) { case 1: //L8038F3BC + port_jigsawPedestal_release(this->actorTypeSpecificField); func_8028F918(0); break; @@ -332,7 +349,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ addOrRemovePieceFromDisplay(this, temp_s1, 0); local->unk4--; local->unk0 &= ~(1 << temp_s1); - fileProgressFlag_setN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, local->unk4, D_803947F8[this->actorTypeSpecificField - 1].size_bits); + fileProgressFlag_setN(_puzzleFlag(this->actorTypeSpecificField - 1), local->unk4, _puzzleSize(this->actorTypeSpecificField - 1)); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, 1); } break; @@ -345,7 +362,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ temp_s1 = getPicturePiecePosition(this); addOrRemovePieceFromDisplay(this, temp_s1, 1); local->unk0 |= (1 << temp_s1); - fileProgressFlag_setN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, local->unk4, D_803947F8[this->actorTypeSpecificField - 1].size_bits); + fileProgressFlag_setN(_puzzleFlag(this->actorTypeSpecificField - 1), local->unk4, _puzzleSize(this->actorTypeSpecificField - 1)); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, -1); unlockAdditionalActions(this); } @@ -368,7 +385,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ local->unk0 |= (1 << temp_s1); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, -1); } - fileProgressFlag_setN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, local->unk4, D_803947F8[this->actorTypeSpecificField - 1].size_bits); + fileProgressFlag_setN(_puzzleFlag(this->actorTypeSpecificField - 1), local->unk4, _puzzleSize(this->actorTypeSpecificField - 1)); unlockAdditionalActions(this); } break; @@ -414,6 +431,44 @@ void addPieces(Actor *this, s32 arg1) { fileProgressFlag_set(FILEPROG_DE_USED_ALL_YOUR_PUZZLE_PIECES, 1); } +// [port] unk38_31 marks a podium that is spawned but not yet revealed by its switch (see boggy3). +Actor *jigsawPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this = marker_getActor(marker); + + if (this->unk38_31) return this; + + return actor_draw(marker, gfx, mtx, vtx); +} + +static void revealCcwPuzzlePodium(Actor *this) { + this->unk38_31 = false; + this->marker->propPtr->unk8_3 = true; + if (!fileProgressFlag_get(FILEPROG_54_CCW_PUZZLE_PODIUM_ACTIVE)) { + __bundle_spawnFromFirstActor(BUNDLE_20__UNKNOWN, this); + func_80324CFC(0.0f, COMUSIC_43_ENTER_LEVEL_GLITTER, 0x7FFF); + func_80324D2C(2.1f, COMUSIC_43_ENTER_LEVEL_GLITTER); + func_8030E6D4(SFX_113_PAD_APPEARS); + } +} + +static s32 jigsawPicture_placedFromFlags(Actor *this) { + return fileProgressFlag_getN(_puzzleFlag(this->actorTypeSpecificField - 1), _puzzleSize(this->actorTypeSpecificField - 1)); +} + +static void jigsawPicture_resyncFromFlags(Actor *this) { + ActorLocal_lair_86F0 *local = (ActorLocal_lair_86F0*)&this->local; + s32 placed = jigsawPicture_placedFromFlags(this); + s32 i; + + local->unk0 = 0; + local->unk4 = 0; + for(i = 0; i < placed; i++){ + local->unk4++; + local->unk0 |= (1 << getPicturePiecePosition(this)); + } + setInitialJigsawPictureOpacity(this); +} + void updateJigsawPictureActor(Actor *this) { ActorLocal_lair_86F0 *local; s32 sp7C[6]; //buttons @@ -432,7 +487,7 @@ void updateJigsawPictureActor(Actor *this) { if (!this->volatile_initialized) { // temp_v0 = &D_803947F8[this->actorTypeSpecificField - 1]; - sp64 = fileProgressFlag_getN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, D_803947F8[this->actorTypeSpecificField - 1].size_bits); + sp64 = fileProgressFlag_getN(_puzzleFlag(this->actorTypeSpecificField - 1), _puzzleSize(this->actorTypeSpecificField - 1)); local->unk0 = 0; local->unk4 = 0; local->unk8 = (isBanjoOnPodium(this->marker)) ? 0xff : 1; @@ -448,16 +503,26 @@ void updateJigsawPictureActor(Actor *this) { if (this->actorTypeSpecificField == 9) { this->unk1C[0] = 8.0f; if (!fileProgressFlag_get(FILEPROG_53_CCW_PUZZLE_PODIUM_SWITCH_PRESSED)) { - marker_despawn(this->marker); + // [port] Anchor suppresses the despawn: a despawned podium only comes back when the + // cube re-streams, which would strand a teammate standing here when the flag arrives. + if (EventSystem_Should(VB_CCW_PODIUM_DESPAWN, true, this)) { + marker_despawn(this->marker); + } else { + this->unk38_31 = true; + this->marker->propPtr->unk8_3 = false; + } return; } - if (!fileProgressFlag_get(FILEPROG_54_CCW_PUZZLE_PODIUM_ACTIVE)) { - __bundle_spawnFromFirstActor(BUNDLE_20__UNKNOWN, this); - func_80324CFC(0.0f, COMUSIC_43_ENTER_LEVEL_GLITTER, 0x7FFF); - func_80324D2C(2.1f, COMUSIC_43_ENTER_LEVEL_GLITTER); - func_8030E6D4(SFX_113_PAD_APPEARS); - } + revealCcwPuzzlePodium(this); + } + } + + // [port] Waiting on the switch: reveal in place the moment the flag lands, ours or a teammate's. + if (this->unk38_31) { + if (!fileProgressFlag_get(FILEPROG_53_CCW_PUZZLE_PODIUM_SWITCH_PRESSED)) { + return; } + revealCcwPuzzlePodium(this); } if ((this->actorTypeSpecificField == 9) && !fileProgressFlag_get(FILEPROG_54_CCW_PUZZLE_PODIUM_ACTIVE)) { @@ -486,10 +551,18 @@ void updateJigsawPictureActor(Actor *this) { controller_copyFaceButtons(0, sp7C); controller_copySideButtons(0, sp6C); func_8038EDBC(this); - switch(this->state){ - case 1://L8038FCD0 - if (!this->has_met_before && (!func_8028F20C() || !func_8028FB48(0x08000000))) { - this->has_met_before = true; + if (local->unk4 != jigsawPicture_placedFromFlags(this) && EventSystem_Should(VB_JIGSAW_PICTURE_RESYNC, false, this)) { + jigsawPicture_resyncFromFlags(this); + } + if (this->state != JIGSAW_PICTURE_LEAVE_PODIUM && !port_jigsawPedestal_isSelf(this->actorTypeSpecificField)) { + jigsawPicture_setState(this, JIGSAW_PICTURE_LEAVE_PODIUM); + return; + } + + switch (this->state) { + case JIGSAW_PICTURE_LEAVE_PODIUM: + if (!this->has_met_before && (!player_isStableWithExtraSteps() || !func_8028FB48(0x08000000))) { + this->has_met_before = TRUE; } if (subaddie_playerIsWithinSphereAndActive(this, 300)) { if ((this->actorTypeSpecificField == 0xA) && !fileProgressFlag_get(FILEPROG_F6_SEEN_DOOR_OF_GRUNTY_PUZZLE_PODIUM)) { @@ -502,11 +575,19 @@ void updateJigsawPictureActor(Actor *this) { } } if (isBanjoOnPodium(this->marker) && this->has_met_before && !isPictureComplete(this) && (player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT)) { - jigsawPicture_setState(this, 2); + if (port_jigsawPedestal_tryClaim(this->actorTypeSpecificField)) { + jigsawPicture_setState(this, 2); + } else if (sBuzzedPedestalField != this->actorTypeSpecificField) { + comusic_playTrack(COMUSIC_2C_BUZZER); + sBuzzedPedestalField = this->actorTypeSpecificField; + } + } else if (sBuzzedPedestalField == this->actorTypeSpecificField) { + sBuzzedPedestalField = 0; } break; case 4: //L8038FE28 + { CALL_EVENT(OnJigsawPodiumInput, this->actorTypeSpecificField); } if ((gcdialog_getCurrentTextId() != 0xF7C) && (gcdialog_getCurrentTextId() != 0xF7D)) { if (sp7C[FACE_BUTTON(BUTTON_A)] == 1) { addPieces(this, 5); diff --git a/src/lair/jigsawpicture.h b/src/lair/jigsawpicture.h new file mode 100644 index 000000000..9e940ac34 --- /dev/null +++ b/src/lair/jigsawpicture.h @@ -0,0 +1,11 @@ +// BanjoDecomp: lair/jigsawpicture.h +typedef enum { + JIGSAW_PICTURE_LEAVE_PODIUM = 1, + JIGSAW_PICTURE_ENTER_PODIUM = 2, + JIGSAW_PICTURE_INSTRUCTIONS = 3, + JIGSAW_PICTURE_WAITING = 4, + JIGSAW_PICTURE_ADD_PIECE = 5, + JIGSAW_PICTURE_ADD_ALL = 6, + JIGSAW_PICTURE_COMPLETE = 7, + JIGSAW_PICTURE_REMOVE_PIECE = 8 +} JigsawPictureState; diff --git a/src/LAIR/actor_spawninit.c b/src/lair/lairspawnqueue.c similarity index 73% rename from src/LAIR/actor_spawninit.c rename to src/lair/lairspawnqueue.c index 5679de22d..32751345e 100644 --- a/src/LAIR/actor_spawninit.c +++ b/src/lair/lairspawnqueue.c @@ -1,4 +1,4 @@ -// BanjoDecomp: code_0.c +// BanjoDecomp: lair/lairspawnqueue.c #include #include "functions.h" #include "variables.h" @@ -10,13 +10,14 @@ extern void func_8028F918(s32); extern void func_802D2FB0(Actor *, s32, s32, s32, f32, s32, s32, s32); extern void func_802D3CE8(Actor *); -extern void func_802D3D54(Actor *); +extern void chMMMBreakableWooden_update(Actor *); extern void func_802D3D74(Actor *this); extern void func_802D4830(Actor *, s32, f32); extern void func_80324CFC(f32, enum comusic_e, s32); extern int actor_animationIsAt(Actor *, f32); extern void subaddie_set_state_with_direction(Actor *, s32, f32, s32); -extern void func_8033A45C(s32, s32); +extern void modelRender_setAppendageVisibility(s32, s32); +extern ActorArray *suBaddieActorArray; @@ -115,53 +116,335 @@ ActorAnimationInfo D_80392CB0[] = { {0x271, 3.0f}, {0x271, 1e+08f} }; -ActorInfo lair_D_80392D90 = { 0x270, 0x2D8, 0x3B2, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80392DB4 = { 0x110, 0x214, 0x4AB, 0x1, D_80392CB0, func_803896D4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392DD8 = { 0x113, 0x217, 0x4A9, 0x1, D_80392CB0, func_803896F4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392DFC = { 0x115, 0x219, 0x4AA, 0x1, D_80392CB0, func_80389714, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392E20 = { 0x11B, 0x221, 0x4B5, 0x1, D_80392CB0, func_80389734, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392E44 = { 0x11C, 0x222, 0x4B2, 0x1, D_80392CB0, func_8038975C, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392E68 = { 0x11D, 0x223, 0x4B0, 0x1, D_80392CB0, func_80389784, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392E8C = { 0x232, 0x23C, 0x4B8, 0x1, D_80392CB0, func_803897AC, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392EB0 = { 0x23F, 0x246, 0x534, 0x1, D_80392CB0, func_80386D20, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392ED4 = { 0x241, 0x248, 0x540, 0x1, D_80392CB0, func_80386780, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392EF8 = { MARKER_109_BREAKABLE_BRICK_WALL, ACTOR_20D_BREAKABLE_BRICK_WALL, ASSET_4A1_MODEL_BREAKABLE_BRICK_WALL, 0x1, D_80392CB0, lair_func_80386550, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x85}; -ActorInfo D_80392F1C = { 0x264, 0x2E5, 0x550, 0x19, D_80392CB0, func_80388524, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80392F40 = { MARKER_224_BREAKABLE_FLOOR_COBWEB, ACTOR_230_BREAKABLE_FLOOR_COBWEB, ASSET_4BF_MODEL_FLOOR_COBWEB, 0xB, D_80392CB0, chFloorCobweb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x88}; -ActorInfo D_80392F64 = { MARKER_225_BREAKABLE_WALL_COBWEB, ACTOR_231_BREAKABLE_WALL_COBWEB, ASSET_4D5_MODEL_WALL_COBWEB, 0xE, D_80392CB0, chWallCobweb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x88}; -ActorInfo D_80392F88 = { 0x111, 0x215, 0x4A4, 0x1, NULL, func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80392FAC = { 0x112, 0x216, 0x4A5, 0x1, NULL, func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80392FD0 = { 0x114, 0x218, 0x4A6, 0x1, NULL, lair_func_80389204, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80392FF4 = { 0x10D, 0x211, 0x4A3, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80393018 = { 0x22C, 0x23A, 0x4D9, 0x1, NULL, func_803882B0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_8039303C = { 0x164, 0x259, 0x507, 0x1, NULL, func_803880BC, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80393060 = { 0x165, 0x25A, 0x508, 0x1, NULL, func_8038824C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80393084 = { MARKER_240_LAIR_SWITCH_FLIGHT_PAD, 0x247, 0x48A, 0x1, NULL, func_80386D78, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_803930A8 = { 0x242, 0x249, 0x2DD, 0x1, NULL, func_803867A8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_803930CC = { 0x11F, 0x225, 0x4B3, 0x1, NULL, func_8038A064, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_803930F0 = { 0x10A, 0x20E, 0x4A2, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_80393114 = { 0x11A, 0x220, 0x4B7, 0x1, NULL, func_80389FF4, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x91}; -ActorInfo D_80393138 = { 0x11E, 0x224, 0x4AF, 0x1, NULL, func_8038A014, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x83}; -ActorInfo D_8039315C = { 0x227, 0x234, 0x4D6, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x93}; -ActorInfo D_80393180 = { 0x228, 0x235, 0x4D7, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8B}; -ActorInfo D_803931A4 = { 0x229, 0x236, 0x4D8, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8B}; -ActorInfo D_803931C8 = { MARKER_121_GLASS_EYE, ACTOR_227_GLASS_EYE, ASSET_4BD_MODEL_GLASS_EYE, 0x1, NULL, func_8038A034, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x89}; -ActorInfo D_803931EC = { 0x116, 0x21A, 0x4AC, 0x1, NULL, func_803893B8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x82}; -ActorInfo D_80393210 = { 0x117, 0x21B, 0x4AD, 0x1, NULL, lair_func_803894B0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x82}; -ActorInfo D_80393234 = { 0x10B, 0x20F, 0x4B4, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x90}; -ActorInfo D_80393258 = { 0x10C, 0x210, 0x4AE, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x84}; -ActorInfo D_8039327C = { 0x10E, 0x212, 0x4A7, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x7F}; -ActorInfo D_803932A0 = { 0x120, 0x226, 0x4BC, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x87}; -ActorInfo D_803932C4 = { 0x122, ACTOR_228_MMM_ENTRANCE_DOOR, 0x4BE, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8C}; -ActorInfo D_803932E8 = { 0x10F, 0x213, 0x4A8, 0x1, NULL, func_803875F0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x80}; -ActorInfo D_8039330C = { 0x118, 0x21E, 0x4B1, 0x1, NULL, lair_func_8038A084, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8F}; -ActorInfo D_80393330 = { 0x119, 0x21F, 0x4B6, 0x1, NULL, func_8038A0A4, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x92}; -ActorInfo D_80393354 = { 0x266, 0x2E3, 0x563, 0x1, NULL, func_803870DC, actor_update_func_80326224, lair_func_80387560, 0, 0, 0.0f, 0}; -ActorInfo D_80393378 = { 0x17D, 0x1E1, 0x517, 0x1, NULL, func_80389D08, actor_update_func_80326224, func_80389E10, 0, 0, 0.0f, 0x8D}; -ActorInfo D_8039339C = { 0x234, 0x23E, 0x4E1, 0x12, D_80392CB0, func_8038982C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; -ActorInfo D_803933C0 = { 0x163, 0x258, 0x511, 0x12, D_80392CB0, func_80389898, actor_update_func_80326224, func_8038664C, 0, 0, 0.0f, 0x8E}; -ActorInfo D_803933E4 = { 0x160, 0x255, 0x509, 0x15, D_80392CB0, func_80389934, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo D_80393408 = { 0x102, 0x203, 0x491, 0x1, D_80392CB0, func_80387730, actor_update_func_80326224, func_80387DA8, 0, 0, 0.0f, 0}; +ActorInfo lair_D_80392D90 = { + MARKER_270_TWO_ICE_POLES_NEAR_CHEATO_3, ACTOR_2D8_TWO_ICE_POLES_NEAR_CHEATO_3, ASSET_3B2_MODEL_TWO_ICE_POLES_NEAR_CHEATO_3, + 0x1, NULL, + chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392DB4 = { + MARKER_110_RAISE_GRATE_TO_BGS_PUZZLE_SWITCH, ACTOR_214_RAISE_GRATE_TO_BGS_PUZZLE_SWITCH, ASSET_4AB_MODEL_RAISE_GRATE_TO_BGS_PUZZLE_SWITCH, + 0x1, D_80392CB0, + func_803896D4, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392DD8 = { + MARKER_113_RAISE_PIPE_TO_CC_ENTRANCE_SWITCH, ACTOR_217_RAISE_PIPE_TO_CC_ENTRANCE_SWITCH, ASSET_4A9_MODEL_RAISE_PIPE_TO_CC_ENTRANCE_SWITCH, + 0x1, D_80392CB0, + func_803896F4, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392DFC = { + MARKER_115_RAISE_PIPE_TO_BRENTILDA_SWITCH, ACTOR_219_RAISE_PIPE_TO_BRENTILDA_SWITCH, ASSET_4AA_MODEL_RAISE_PIPE_TO_BRENTILDA_SWITCH, + 0x1, D_80392CB0, + func_80389714, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392E20 = { + MARKER_11B_WATER_LEVEL_SWITCH_1, ACTOR_221_LEVEL_1_WATER_SWITCH, ASSET_4B5_MODEL_LEVEL_1_WATER_SWITCH, + 0x1, D_80392CB0, + func_80389734, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392E44 = { + MARKER_11C_WATER_LEVEL_SWITCH_2, ACTOR_222_LEVEL_2_WATER_SWITCH, ASSET_4B2_MODEL_LEVEL_2_WATER_SWITCH, + 0x1, D_80392CB0, + func_8038975C, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392E68 = { + MARKER_11D_WATER_LEVEL_SWITCH_3, ACTOR_223_LEVEL_3_WATER_SWITCH, ASSET_4B0_MODEL_LEVEL_3_WATER_SWITCH, + 0x1, D_80392CB0, + func_80389784, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392E8C = { + MARKER_232_CCW_PUZZLE_SWITCH, ACTOR_23C_CCW_PUZZLE_SWITCH, ASSET_4B8_MODEL_CCW_PUZZLE_SWITCH, + 0x1, D_80392CB0, + func_803897AC, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392EB0 = { + MARKER_23F_LAIR_FLIGHT_PAD_SWITCH, ACTOR_246_FLIGHT_PAD_SWITCH, ASSET_534_MODEL_FLIGHT_PAD_SWITCH, + 0x1, D_80392CB0, + func_80386D20, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392ED4 = { + MARKER_241_SHOCK_JUMP_PAD_SWITCH, ACTOR_248_SHOCK_JUMP_PAD_SWITCH, ASSET_540_MODEL_SHOCK_JUMP_PAD_SWITCH, + 0x1, D_80392CB0, + func_80386780, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392EF8 = { + MARKER_109_BREAKABLE_BRICK_WALL, ACTOR_20D_BREAKABLE_BRICK_WALL, ASSET_4A1_MODEL_BREAKABLE_BRICK_WALL, + 0x1, D_80392CB0, + lair_func_80386550, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0x85 +}; + +ActorInfo D_80392F1C = { + MARKER_264_LARGE_DOOR_TO_FINAL_BATTLE, ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE, ASSET_550_MODEL_LARGE_DOOR_TO_FINAL_BATTLE, + 0x19, D_80392CB0, + func_80388524, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392F40 = { + MARKER_224_BREAKABLE_FLOOR_COBWEB, ACTOR_230_BREAKABLE_FLOOR_COBWEB, ASSET_4BF_MODEL_FLOOR_COBWEB, + 0xB, D_80392CB0, + chFloorCobweb_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0x88 +}; + +ActorInfo D_80392F64 = { + MARKER_225_BREAKABLE_WALL_COBWEB, ACTOR_231_BREAKABLE_WALL_COBWEB, ASSET_4D5_MODEL_WALL_COBWEB, + 0xE, D_80392CB0, + chWallCobweb_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0x88 +}; + +ActorInfo D_80392F88 = { + MARKER_111_GL_CC_ENTRANCE_LONG_PIPE_GREEN, ACTOR_215_GL_CC_ENTRANCE_LONG_PIPE_GREEN, ASSET_4A4_MODEL_GL_CC_ENTRANCE_LONG_PIPE_GREEN, + 0x1, NULL, + func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392FAC = { + MARKER_112_GL_CC_ENTRANCE_LONG_PIPE_BLUE, ACTOR_216_GL_CC_ENTRANCE_LONG_PIPE_BLUE, ASSET_4A5_MODEL_GL_CC_ENTRANCE_LONG_PIPE_BLUE, + 0x1, NULL, + func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392FD0 = { + MARKER_114_GL_CC_ENTRANCE_SHORT_PIPE, ACTOR_218_GL_CC_ENTRANCE_SHORT_PIPE, ASSET_4A6_MODEL_GL_CC_ENTRANCE_SHORT_PIPE, + 0x1, NULL, + lair_func_80389204, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80392FF4 = { + MARKER_10D_TTC_ENTRANCE_CHEST_LID, ACTOR_211_TTC_ENTRANCE_CHEST_LID, ASSET_4A3_MODEL_GL_TTC_ENTRANCE_CHEST_LID, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80393018 = { + MARKER_22C_GL_ADVENT_CALENDAR_HATCH_DOOR, ACTOR_23A_GL_ADVENT_CALENDAR_HATCH_DOOR, ASSET_4D9_MODEL_GL_ADVENT_CALENDAR_HATCH_DOOR, + 0x1, NULL, + func_803882B0, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_8039303C = { + MARKER_164_GL_GRUNTY_FLOOR_PICTURE_EYE_1, ACTOR_259_GL_GRUNTY_FLOOR_PICTURE_EYE_1, ASSET_507_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_1, + 0x1, NULL, + func_803880BC, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80393060 = { + MARKER_165_GL_GRUNTY_FLOOR_PICTURE_EYE_2, ACTOR_25A_GL_GRUNTY_FLOOR_PICTURE_EYE_2, ASSET_508_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_2, + 0x1, NULL, + func_8038824C, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80393084 = { + MARKER_240_LAIR_SWITCH_FLIGHT_PAD, ACTOR_247_LAIR_SWITCH_FLIGHT_PAD, ASSET_48A_MODEL_FLIGHT_PAD, + 0x1, NULL, + func_80386D78, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803930A8 = { + MARKER_242_LAIR_SWITCH_SHOCK_JUMP_PAD, ACTOR_249_LAIR_SWITCH_SHOCK_JUMP_PAD, ASSET_2DD_MODEL_SHOCK_JUMP_PAD, + 0x1, NULL, + func_803867A8, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803930CC = { + MARKER_11F_RAREWARE_BOX, ACTOR_225_RAREWARE_BOX, ASSET_4B3_MODEL_RAREWARE_BOX, + 0x1, NULL, + func_8038A064, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803930F0 = { + MARKER_10A_MM_ENTRANCE_DOOR, ACTOR_20E_MM_ENTRANCE_DOOR, ASSET_4A2_MODEL_GL_MM_DOOR_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80393114 = { + MARKER_11A_GRATE_TO_RBB_PUZZLE, ACTOR_220_GRATE_TO_RBB_PUZZLE, ASSET_4B7_MODEL_GRATE_TO_RBB_PUZZLE, + 0x1, NULL, + func_80389FF4, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x91 +}; + +ActorInfo D_80393138 = { + MARKER_11E_ICE_BALL_TO_CHEATO, ACTOR_224_ICE_BALL_TO_CHEATO, ASSET_4AF_MODEL_ICE_BALL_TO_CHEATO, + 0x1, NULL, + func_8038A014, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x83 +}; + +ActorInfo D_8039315C = { + MARKER_227_CCW_ENTRANCE_DOOR, ACTOR_234_CCW_ENTRANCE_DOOR, ASSET_4D6_MODEL_GL_CCW_DOOR_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x93 +}; + +ActorInfo D_80393180 = { + MARKER_228_FP_ENTRANCE_DOOR_LEFT, ACTOR_235_FP_ENTRANCE_DOOR_LEFT, ASSET_4D7_MODEL_GL_FP_DOOR_ENTRANCE_LEFT, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x8B +}; + +ActorInfo D_803931A4 = { + MARKER_229_FP_ENTRANCE_DOOR_RIGHT, ACTOR_236_FP_ENTRANCE_DOOR_RIGHT, ASSET_4D8_MODEL_GL_FP_DOOR_ENTRANCE_LEFT, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x8B +}; + +ActorInfo D_803931C8 = { + MARKER_121_GLASS_EYE, ACTOR_227_GLASS_EYE, ASSET_4BD_MODEL_GLASS_EYE, + 0x1, NULL, + func_8038A034, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0x89 +}; + +ActorInfo D_803931EC = { + MARKER_116_IRON_BARS_UNDER_GRUNTY_STATUE, ACTOR_21A_IRON_BARS_UNDER_GRUNTY_STATUE, ASSET_4AC_MODEL_IRON_BARS_UNDER_GRUNTY_STATUE, + 0x1, NULL, + func_803893B8, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x82 +}; + +ActorInfo D_80393210 = { + MARKER_117_GRUNTY_STATUE_BREAKABLE_HAT_TOP, ACTOR_21B_GRUNTY_STATUE_BREAKABLE_HAT_TOP, ASSET_4AD_MODEL_GRUNTY_STATUE_BREAKABLE_HAT_TOP, + 0x1, NULL, + lair_func_803894B0, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x82 +}; + +ActorInfo D_80393234 = { + MARKER_10B_RBB_ENTRANCE_DOOR, ACTOR_20F_RBB_ENTRANCE_DOOR, ASSET_4B4_MODEL_GL_RBB_DOOR_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x90 +}; + +ActorInfo D_80393258 = { + MARKER_10C_BGS_ENTRANCE_DOOR, ACTOR_210_BGS_ENTRANCE_DOOR, ASSET_4AE_MODEL_GL_BGS_DOOR_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x84 +}; + +ActorInfo D_8039327C = { + MARKER_10E_CC_ENTRANCE_DOOR, ACTOR_212_CC_ENTRANCE_BARS, ASSET_4A7_MODEL_GL_CC_IRON_BARS_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x7F +}; + +ActorInfo D_803932A0 = { + MARKER_120_GV_ENTRANCE, ACTOR_226_GV_ENTRANCE, ASSET_4BC_MODEL_GL_GV_DOOR_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x87 +}; + +ActorInfo D_803932C4 = { + MARKER_122_MMM_ENTRANCE_DOOR, ACTOR_228_MMM_ENTRANCE_DOOR, ASSET_4BE_MODEL_GL_MMM_DOOR_ENTRANCE, + 0x1, NULL, + func_80388524, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x8C +}; + +ActorInfo D_803932E8 = { + MARKER_10F_GL_BGS_PUZZLE_GRATE, ACTOR_213_GL_BGS_PUZZLE_GRATE, ASSET_4A8_MODEL_GL_BGS_PUZZLE_GRATE, + 0x1, NULL, + func_803875F0, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x80 +}; + +ActorInfo D_8039330C = { + MARKER_118_GRATE_TO_LEVEL_3_WATER_SWITCH, ACTOR_21E_GRATE_TO_LEVEL_3_WATER_SWITCH, ASSET_4B1_MODEL_GRATE_TO_LEVEL_3_WATER_SWITCH, + 0x1, NULL, + lair_func_8038A084, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x8F +}; + +ActorInfo D_80393330 = { + MARKER_119_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, ACTOR_21F_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, ASSET_4B6_MODEL_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, + 0x1, NULL, + func_8038A0A4, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0x92 +}; + +ActorInfo D_80393354 = { + MARKER_266_LEVEL_ENTRY_SIGNS, ACTOR_2E3_LEVEL_ENTRY_SIGNS, ASSET_563_MODEL_LEVEL_ENTRY_SIGNS, + 0x1, NULL, + func_803870DC, actor_update_func_80326224, lair_func_80387560, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80393378 = { + MARKER_17D_IRON_GATE_NO_LOCK, ACTOR_1E1_IRON_GATE_NO_LOCK, ASSET_517_MODEL_IRON_GATE_NO_LOCK, + 0x1, NULL, + func_80389D08, actor_update_func_80326224, func_80389E10, + 0, 0, 0.0f, 0x8D +}; + +ActorInfo D_8039339C = { + MARKER_234_GL_WOODEN_COFFIN_NO_LID, ACTOR_23E_GL_WOODEN_COFFIN_NO_LID, ASSET_4E1_MODEL_GL_WOODEN_COFFIN_NO_LID, + 0x12, D_80392CB0, + func_8038982C, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803933C0 = { + MARKER_163_CRYPT_COFFIN_LID, ACTOR_258_CRYPT_COFFIN_LID, ASSET_511_MODEL_CRYPT_COFFIN_LID, + 0x12, D_80392CB0, + func_80389898, actor_update_func_80326224, func_8038664C, + 0, 0, 0.0f, 0x8E +}; + +ActorInfo D_803933E4 = { + MARKER_160_GL_SARCOPHAGUS, ACTOR_255_GL_SARCOPHAGUS, ASSET_509_MODEL_GL_SARCOPHAGUS, + 0x15, D_80392CB0, + func_80389934, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80393408 = { + MARKER_102_NOTE_DOOR, ACTOR_203_NOTE_DOOR, ASSET_491_MODEL_NOTE_DOOR, + 0x1, D_80392CB0, + func_80387730, actor_update_func_80326224, func_80387DA8, + 0, 0, 0.0f, 0 +}; + ParticleScaleAndLifetimeRanges D_8039342C = { {0.31f, 0.37f}, {0.17f, 0.22f}, @@ -216,11 +499,26 @@ s32 D_80393504[4] = {0x87, 0x87, 0x87, 0xB4}; //chcobweb void chFloorCobweb_update(Actor *this) { + enum file_progress_e brokenFlag = (this->actorTypeSpecificField == 1) + ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN + : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN; + if(!this->initialized) { func_802D3CE8(this); - if (fileProgressFlag_get(this->actorTypeSpecificField == 1 ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN)) + if (fileProgressFlag_get(brokenFlag)) + { + marker_despawn(this->marker); + return; + } + } + + // Anchor: re-check on scene-return restore, which resets volatile_initialized but not initialized. + if (!this->volatile_initialized) + { + this->volatile_initialized = true; + if (fileProgressFlag_get(brokenFlag)) { marker_despawn(this->marker); return; @@ -251,6 +549,17 @@ void chWallCobweb_update(Actor *this) } } + // [port] Re-check on scene-return restore (see chFloorCobweb_update). + if (!this->volatile_initialized) + { + this->volatile_initialized = true; + if (fileProgressFlag_get(FILEPROG_CA_COBWEB_BLOCKING_PURPLE_CAULDRON_BROKEN)) + { + marker_despawn(this->marker); + return; + } + } + if (this->state == 0xF) { if (actor_animationIsAt(this, 0.9f)) @@ -263,11 +572,26 @@ void chWallCobweb_update(Actor *this) void lair_func_80386550(Actor *this) { + enum file_progress_e brokenFlag = (this->actorTypeSpecificField == 1) + ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN + : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN; + if (!this->initialized) { func_802D3CE8(this); - if (fileProgressFlag_get(this->actorTypeSpecificField == 1 ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN)) + if (fileProgressFlag_get(brokenFlag)) + { + marker_despawn(this->marker); + return; + } + } + + // [port] Re-check on scene-return restore (see chFloorCobweb_update). + if (!this->volatile_initialized) + { + this->volatile_initialized = true; + if (fileProgressFlag_get(brokenFlag)) { marker_despawn(this->marker); return; @@ -304,8 +628,8 @@ Actor *func_8038664C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) actor = marker_getActor(marker); val = actor->unk10_12; - func_8033A45C(3, val == 1 ? 1 : 0); - func_8033A45C(4, val == 0 ? 1 : 0); + modelRender_setAppendageVisibility(3, val == 1 ? 1 : 0); + modelRender_setAppendageVisibility(4, val == 0 ? 1 : 0); return actor_draw(marker, gfx, mtx, vtx); } @@ -445,7 +769,7 @@ void func_80386D20(Actor *this) void func_80386D40(void) { - func_802D68F0(0xC); + code_4C020_setHourglassTimer(0xC); item_set(ITEM_6_HOURGLASS, true); mapSpecificFlags_set(1, true); } @@ -593,7 +917,7 @@ Actor *lair_func_80387560(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) u32 i; for (i = 0; i != 10; i++) - func_8033A45C(i + 1, actor->actorTypeSpecificField + 1 == i + 2); + modelRender_setAppendageVisibility(i + 1, actor->actorTypeSpecificField + 1 == i + 2); return actor_drawFullDepth(marker, gfx, mtx, vtx); } @@ -605,20 +929,25 @@ void func_803875F0(Actor * this) if (!this->volatile_initialized) { - if (fileProgressFlag_get(FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN)) - { - marker_despawn(this->marker); - return; - } - + // [port] Anchor: a teammate's press delivers map flag 0 and FILEPROG_1E in the same + // packet drain, so check the switch flag first -- while we're here to watch, the rise + // animation should win over the already-open catch-up despawn. if (mapSpecificFlags_get(0)) { this->unk1C_y = this->position_y; - gcStaticCamera_activate(0x2A); + // A remote press shouldn't steal our camera. + if (!port_mapFlag_wasSetRemotely(0)) { + gcStaticCamera_activate(0x2A); + } fileProgressFlag_set(FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN, true); this->volatile_initialized = true; this->unk38_31 = 0x0C; } + else if (fileProgressFlag_get(FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN)) + { + marker_despawn(this->marker); + return; + } } else { @@ -658,6 +987,7 @@ void func_80387730(Actor *this) { s32 phi_s4; s32 sp6C[3]; f32 sp60[3]; + s32 forceOpen; func_802D3D74(this); if (!this->volatile_initialized) { @@ -684,15 +1014,18 @@ void func_80387730(Actor *this) { this->unk1C[1] = 0.0f; this->unk1C[2] = 3.5f; } - if (!fileProgressFlag_get(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN) && ability_isUnlocked(ABILITY_13_1ST_NOTEDOOR)) { + // Anchor: unk1C[0] set by port_notedoor_remoteOpen = a teammate opened this door. + forceOpen = (this->unk1C[0] != 0.0f); + if (forceOpen || + (!fileProgressFlag_get(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN) && ability_isUnlocked(ABILITY_13_1ST_NOTEDOOR))) { player_getPosition(spAC); - if ((ml_vec3f_distance(spAC, this->position) < 500.0f) && (gcdialog_getCurrentTextId() != 0xF64)) { + if (!forceOpen && (ml_vec3f_distance(spAC, this->position) < 500.0f) && (gcdialog_getCurrentTextId() != 0xF64)) { code_73640_printItemCount(0xC); } doorIdx = this->actorTypeSpecificField - 1; noteThreshold = port_getRomhackNoteDoor(doorIdx); if (noteThreshold < 0) { noteThreshold = D_8039347C[doorIdx]; } - if (itemscore_noteScores_getTotal() >= noteThreshold) { + if (forceOpen || itemscore_noteScores_getTotal() >= noteThreshold) { if (this->marker->unk14_21) { func_8032BC60(this, 5, sp90); func_8032BC60(this, 6, sp84); @@ -705,11 +1038,13 @@ void func_80387730(Actor *this) { phi_f20 = 290.0f; } sp9C[1] = this->position[1]; - if ((ml_vec3f_distance(spAC, sp9C) < phi_f20) || (this->alpha_124_19 != 0xFF)) { + if (forceOpen || (ml_vec3f_distance(spAC, sp9C) < phi_f20) || (this->alpha_124_19 != 0xFF)) { if (this->alpha_124_19 == 0xFF) { func_80324CFC(0.0f, COMUSIC_43_ENTER_LEVEL_GLITTER, 32700); func_80324D2C(2.4f, COMUSIC_43_ENTER_LEVEL_GLITTER); - func_8028F918(2); + if (!forceOpen) { + func_8028F918(2); + } } if (this->alpha_124_19 < 7U) { this->alpha_124_19 = 0; @@ -717,10 +1052,14 @@ void func_80387730(Actor *this) { this->alpha_124_19 -= 7; } if (this->alpha_124_19 == 0) { - fileProgressFlag_set(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN, true); + if (!forceOpen) { + fileProgressFlag_set(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN, true); + } marker_despawn(this->marker); - func_8028F918(0); - func_8028F66C(BS_INTR_35); + if (!forceOpen) { + func_8028F918(0); + func_8028F66C(BS_INTR_35); + } return; } if (this->marker->unk14_21) { @@ -747,9 +1086,89 @@ void func_80387730(Actor *this) { } } } else if ((this->actorTypeSpecificField >= 2) && (ml_vec3f_distance(spAC, this->position) < 290.0f)) { - volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES); + progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES); + } + } +} + +// A live actor by id (and actorTypeSpecificField when >= 0), or NULL. +static Actor *__lair_findActor(s32 actorId, s32 typeField) { + s32 i; + + if (suBaddieActorArray == NULL) { + return NULL; + } + for (i = 0; i < suBaddieActorArray->cnt; i++) { + Actor *actor = &suBaddieActorArray->data[i]; + if (actor->marker != NULL && actor->modelCacheIndex == actorId && + (typeField < 0 || actor->actorTypeSpecificField == typeField)) { + return actor; } } + return NULL; +} + +// [port] Anchor: one-shot cues for a teammate's file-progress flag. +void port_progressFlag_remoteCue(s32 progressFlag) { + Actor *actor; + + port_notedoor_remoteOpen(progressFlag); + port_leveldoor_remoteOpen(progressFlag); + port_breakable_remoteBreak(progressFlag); + + switch (progressFlag) { + // Circular grate over the BGS puzzle: rise + slam (func_803875F0). + case FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN: + actor = __lair_findActor(ACTOR_213_GL_BGS_PUZZLE_GRATE, -1); + if (actor != NULL && !actor->volatile_initialized) { + actor->unk1C_y = actor->position_y; + actor->volatile_initialized = TRUE; + actor->unk38_31 = 0x0C; + } + break; + + // CC lobby pipes: rise + slam (func_80388FC8 / lair_func_80389204). + case FILEPROG_1F_CC_LOBBY_PIPE_1_RAISED: + case FILEPROG_20_CC_LOBBY_PIPE_2_RAISED: + case FILEPROG_21_CC_LOBBY_PIPE_3_RAISED: { + s32 pipeId = (progressFlag == FILEPROG_1F_CC_LOBBY_PIPE_1_RAISED) + ? ACTOR_215_GL_CC_ENTRANCE_LONG_PIPE_GREEN + : (progressFlag == FILEPROG_20_CC_LOBBY_PIPE_2_RAISED) + ? ACTOR_216_GL_CC_ENTRANCE_LONG_PIPE_BLUE + : ACTOR_218_GL_CC_ENTRANCE_SHORT_PIPE; + actor = __lair_findActor(pipeId, -1); + // initialized = rise base captured; lifetime_value != 0 = already raised. + if (actor != NULL && actor->initialized && actor->lifetime_value == 0.0f && + !actor->volatile_initialized) { + actor->volatile_initialized = TRUE; + actor->unk38_31 = 12; + } + break; + } + + // Grunty statue hat + case FILEPROG_A1_STATUE_HAT_OPEN: + actor = __lair_findActor(ACTOR_21B_GRUNTY_STATUE_BREAKABLE_HAT_TOP, -1); + if (actor != NULL && actor->volatile_initialized && actor->unk1C[0] == 0.0f) { + actor->unk1C[0] = 1.0f; + } + break; + + default: + break; + } +} + +void port_notedoor_remoteOpen(s32 progressFlag) { + Actor *actor; + + if (progressFlag < FILEPROG_3A_NOTE_DOOR_50_OPEN || progressFlag > FILEPROG_45_NOTE_DOOR_882_OPEN) { + return; + } + actor = __lair_findActor(ACTOR_203_NOTE_DOOR, progressFlag - FILEPROG_39_CCW_OPEN); + if (actor != NULL) { + actor->unk1C[0] = 1.0f; // picked up by func_80387730 next update + } } @@ -787,8 +1206,11 @@ Actor *func_80387DA8(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) * Hides all note door graphics that don't match this note door's index * e.g. for the 50 note door, hides 180, 260, etc. */ + // [port] Romhack gate: a listener may blank this door's baked number (the digits + // are a fixed mesh, so an overridden threshold would show the wrong one). + bool showNumber = EventSystem_Should(VB_NOTEDOOR_DRAW_NUMBER, true, actor->noteDoorIdx); for (i = 0; i != NUM_NOTE_DOORS; i++) - func_8033A45C(i + 1, actor->noteDoorIdx + 1 == i + 2); + modelRender_setAppendageVisibility(i + 1, showNumber && (actor->noteDoorIdx + 1 == i + 2)); /** * Draw the note door @@ -950,7 +1372,10 @@ void func_803882B0(Actor *this) this->lifetime_value = 0; } - if (this->pitch == 90.f || !volatileFlag_get(VOLATILE_FLAG_BB_WITCH_SWITCH_PRESSED_FP)) + // Anchor: also honor persistent FILEPROG_47; VOLATILE_FLAG_BB is transient. + if (this->pitch == 90.f + || !(volatileFlag_get(VOLATILE_FLAG_BB_WITCH_SWITCH_PRESSED_FP) + || fileProgressFlag_get(FILEPROG_47_FP_WITCH_SWITCH_JIGGY_PRESSED))) return; if (this->pitch == 0) @@ -980,12 +1405,46 @@ void func_80388404(enum file_progress_e progress_flag, enum sfx_e sfx, f32 a2, s fileProgressFlag_set(progress_flag, true); } +static s32 sRemoteOpenDoorActor = 0; + +static enum file_progress_e __leveldoor_persistentFlag(s32 actorId) { + switch (actorId) { + case ACTOR_20E_MM_ENTRANCE_DOOR: return FILEPROG_31_MM_OPEN; + case ACTOR_211_TTC_ENTRANCE_CHEST_LID: return FILEPROG_32_TTC_OPEN; + case ACTOR_212_CC_ENTRANCE_BARS: return FILEPROG_33_CC_OPEN; + case ACTOR_210_BGS_ENTRANCE_DOOR: return FILEPROG_34_BGS_OPEN; + case ACTOR_235_FP_ENTRANCE_DOOR_LEFT: return FILEPROG_35_FP_OPEN; + case ACTOR_226_GV_ENTRANCE: return FILEPROG_36_GV_OPEN; + case ACTOR_228_MMM_ENTRANCE_DOOR: return FILEPROG_37_MMM_OPEN; + case ACTOR_20F_RBB_ENTRANCE_DOOR: return FILEPROG_38_RBB_OPEN; + case ACTOR_234_CCW_ENTRANCE_DOOR: return FILEPROG_39_CCW_OPEN; + case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE: return FILEPROG_E2_DOOR_OF_GRUNTY_OPEN; + default: return 0; + } +} + +void port_leveldoor_remoteOpen(s32 progressFlag) { + switch (progressFlag) { + case 0x28: sRemoteOpenDoorActor = ACTOR_20E_MM_ENTRANCE_DOOR; break; + case 0x29: sRemoteOpenDoorActor = ACTOR_211_TTC_ENTRANCE_CHEST_LID; break; + case 0x2A: sRemoteOpenDoorActor = ACTOR_212_CC_ENTRANCE_BARS; break; + case 0x2B: sRemoteOpenDoorActor = ACTOR_210_BGS_ENTRANCE_DOOR; break; + case 0x2C: sRemoteOpenDoorActor = ACTOR_235_FP_ENTRANCE_DOOR_LEFT; break; + case 0x2D: sRemoteOpenDoorActor = ACTOR_226_GV_ENTRANCE; break; + case 0x2E: sRemoteOpenDoorActor = ACTOR_228_MMM_ENTRANCE_DOOR; break; + case 0x2F: sRemoteOpenDoorActor = ACTOR_20F_RBB_ENTRANCE_DOOR; break; + case 0x30: sRemoteOpenDoorActor = ACTOR_234_CCW_ENTRANCE_DOOR; break; + case 0xE2: sRemoteOpenDoorActor = ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE; break; + default: break; + } +} + void func_80388450(Actor *actor1, Actor *actor2) { f32 vec1[3]; f32 vec2[3]; void *actor3 = nodeprop_findByActorIdAndActorPosition(0x22A, actor1); - s32 val = nodeprop_getYaw(actor3); + s32 val = nodeProp_getYaw(actor3); actor2->yaw = val; actor1->yaw = val; @@ -1009,18 +1468,29 @@ void func_80388524(Actor *this) { ParticleEmitter *sp2C; Actor *sp28; - sp34 = func_802D677C(-1) + sp34 = func_802D677C(-1) && (func_802D677C(-1) == gsworld_getMap()) && (func_802D67AC(-1) >= 8) && (func_802D67AC(-1) < 0x12) && (func_802D67DC(-1) == this->modelCacheIndex) ; + if (!sp34 && this->modelCacheIndex == sRemoteOpenDoorActor) { + bool alreadyOpen = EventSystem_Should(VB_LEVELDOOR_REMOTE_OPEN_DONE, + fileProgressFlag_get(__leveldoor_persistentFlag(this->modelCacheIndex)) != 0, + this->modelCacheIndex, this->state); + if (alreadyOpen) { + sRemoteOpenDoorActor = 0; + } else { + sp34 = true; + } + } + func_802D3D74(this); if (!this->initialized) { if (!sp34) { switch(this->modelCacheIndex){ - case ACTOR_2E5_DOOR_OF_GRUNTY://L80388630 + case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE://L80388630 if (!fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) && jigsawPicture_isJigsawPictureComplete(0xA)) { fileProgressFlag_set(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN, true); } @@ -1086,7 +1556,7 @@ void func_80388524(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; switch(this->modelCacheIndex){ - case ACTOR_2E5_DOOR_OF_GRUNTY: //L80388880 + case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE: //L80388880 if (fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) && (this->state == 0x19)) { subaddie_set_state_with_direction(this, 0x1B, 0.999f, 1); } @@ -1326,7 +1796,8 @@ void func_80388FC8(Actor *this) if (mapSpecificFlags_get(1)) { - if (this->modelCacheIndex == 0x215) + // [port] Anchor: a remote press shouldn't steal our camera. + if (this->modelCacheIndex == 0x215 && !port_mapFlag_wasSetRemotely(1)) { gcStaticCamera_activate(0x2B); if (1); // oof @@ -1363,7 +1834,7 @@ void func_80388FC8(Actor *this) if (this->modelCacheIndex == 0x215) { func_802D48B8(this); - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); } this->lifetime_value = 1.f; @@ -1403,7 +1874,10 @@ void lair_func_80389204(Actor *this) if (mapSpecificFlags_get(2)) { - gcStaticCamera_activate(0x2C); + // [port] Anchor: a remote press shouldn't steal our camera. + if (!port_mapFlag_wasSetRemotely(2)) { + gcStaticCamera_activate(0x2C); + } fileProgressFlag_set(FILEPROG_21_CC_LOBBY_PIPE_3_RAISED, true); this->volatile_initialized = true; @@ -1429,7 +1903,7 @@ void lair_func_80389204(Actor *this) this->position_y = this->unk1C[1]; func_802D48B8(this); - gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); this->lifetime_value = 1.f; } @@ -1808,7 +2282,16 @@ void func_80389FA8(Actor *this, enum file_progress_e flag) { if (!this->initialized) { - func_802D3D54(this); + chMMMBreakableWooden_update(this); + + if (fileProgressFlag_get(flag)) + marker_despawn(this->marker); + } + + // Anchor: re-check on scene-return restore (see chFloorCobweb_update). + if (!this->volatile_initialized) + { + this->volatile_initialized = true; if (fileProgressFlag_get(flag)) marker_despawn(this->marker); diff --git a/src/LAIR/ch/tooty_parade.c b/src/lair/tooty_parade.c similarity index 100% rename from src/LAIR/ch/tooty_parade.c rename to src/lair/tooty_parade.c diff --git a/src/port/Audio/AudioSync.cpp b/src/port/Audio/AudioSync.cpp index c349e5986..435de1960 100644 --- a/src/port/Audio/AudioSync.cpp +++ b/src/port/Audio/AudioSync.cpp @@ -7,6 +7,9 @@ // thread-shared section with osSetIntMask(OS_IM_NONE)/restore. Routing those brackets to this // lock protects all of them with no edits to the audio code. +#include +#include +#include #include extern "C" { @@ -18,6 +21,26 @@ std::recursive_mutex gAudioLock; thread_local int gAudioMaskDepth = 0; } // namespace +// Window-freeze audio hold +namespace { +constexpr int64_t kCushionMs = 100; +std::atomic sAllowedUntilMs{ 0 }; + +int64_t NowMs() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count(); +} +} // namespace + +extern "C" void port_noteMainLoopAlive(void) { + sAllowedUntilMs.store(NowMs() + kCushionMs, std::memory_order_relaxed); +} + +extern "C" int port_audioStallHold(void) { + const int64_t allowedUntil = sAllowedUntilMs.load(std::memory_order_relaxed); + return allowedUntil != 0 && NowMs() > allowedUntil; +} + extern "C" void port_lockAudio(void) { gAudioLock.lock(); } diff --git a/src/port/Audio/mixer.h b/src/port/Audio/mixer.h index 4420a159a..c7358a110 100644 --- a/src/port/Audio/mixer.h +++ b/src/port/Audio/mixer.h @@ -36,20 +36,20 @@ void aSetVolumeImpl(uint8_t flags, int16_t v, int16_t t, int16_t r); void aPoleFilterImpl(uint8_t flags, uint16_t gain, uint8_t dmem_shift, void* state); void aDisableImpl(uint16_t outp, uint32_t b, uint32_t c); -#define aDisable(pkt, o, b, c) aDisableImpl(o, b, c) -#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c) -#define aLoadBuffer(pkt, c, d, s) aLoadBufferImpl((void*)(s), d, c) -#define aSaveBuffer(pkt, c, s, d) aSaveBufferImpl(s, (int16_t*)(d), c) -#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, (int16_t*)(d)) -#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c) -#define aSetLoop(pkt, a) aSetLoopImpl((void*)(a)) -#define aADPCMdec(pkt, s, f, c, i, o) aADPCMdecImpl(f, (void*)(s), c, i, o) -#define aResample(pkt, s, f, p, i, o) aResampleImpl(f, p, (void*)(s), i, o) -#define aInterleave(pkt) aInterleaveImpl() -#define aMix(pkt, f, g, i, o) aMixImpl(f, g, i, o) -#define aEnvMixer(pkt, f, t, s) aEnvMixerImpl(f, (void*)(s), t) -#define aSetVolume(pkt, f, v, t, r) aSetVolumeImpl(f, v, t, r) -#define aPoleFilter(pkt, f, g, t, s) aPoleFilterImpl(f, g, t, s) -#define aPlayMP3(pkt, a, b, c, r) aPlayMP3Impl((void*)(a), b, (void*)(c), r) +#define aDisable(pkt, o, b, c) ((void)(pkt), aDisableImpl(o, b, c)) +#define aClearBuffer(pkt, d, c) ((void)(pkt), aClearBufferImpl(d, c)) +#define aLoadBuffer(pkt, c, d, s) ((void)(pkt), aLoadBufferImpl((void*)(s), d, c)) +#define aSaveBuffer(pkt, c, s, d) ((void)(pkt), aSaveBufferImpl(s, (int16_t*)(d), c)) +#define aLoadADPCM(pkt, c, d) ((void)(pkt), aLoadADPCMImpl(c, (int16_t*)(d))) +#define aDMEMMove(pkt, i, o, c) ((void)(pkt), aDMEMMoveImpl(i, o, c)) +#define aSetLoop(pkt, a) ((void)(pkt), aSetLoopImpl((void*)(a))) +#define aADPCMdec(pkt, s, f, c, i, o) ((void)(pkt), aADPCMdecImpl(f, (void*)(s), c, i, o)) +#define aResample(pkt, s, f, p, i, o) ((void)(pkt), aResampleImpl(f, p, (void*)(s), i, o)) +#define aInterleave(pkt) ((void)(pkt), aInterleaveImpl()) +#define aMix(pkt, f, g, i, o) ((void)(pkt), aMixImpl(f, g, i, o)) +#define aEnvMixer(pkt, f, t, s) ((void)(pkt), aEnvMixerImpl(f, (void*)(s), t)) +#define aSetVolume(pkt, f, v, t, r) ((void)(pkt), aSetVolumeImpl(f, v, t, r)) +#define aPoleFilter(pkt, f, g, t, s) ((void)(pkt), aPoleFilterImpl(f, g, t, s)) +#define aPlayMP3(pkt, a, b, c, r) ((void)(pkt), aPlayMP3Impl((void*)(a), b, (void*)(c), r)) #endif diff --git a/src/port/Controller/ControlSchemes.cpp b/src/port/Controller/ControlSchemes.cpp index 05c55e9e1..75a725da3 100644 --- a/src/port/Controller/ControlSchemes.cpp +++ b/src/port/Controller/ControlSchemes.cpp @@ -17,13 +17,14 @@ #include #include #include -#include #include #include #include #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Camera/FreeLookCamera.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/ShipInit.hpp" #include "port/ShipUtils.h" #include "ControlSchemes.h" @@ -31,6 +32,7 @@ extern "C" { #include "enums.h" int bs_getState(void); int bsbtrot_inSet(int state); // nonzero if `state` is one of the Talon Trot states +s32 getGameMode(void); } using namespace Ship; @@ -91,20 +93,40 @@ void BindButtonToLeftStick(const std::shared_ptr& controller, Direct stick->SaveAxisDirectionMappingIdsToConfig(); } -// True if the given C-button is currently driven by a stick axis (the right -// stick), as opposed to a face button. Drives which directions the shaping pass -// regenerates from the raw right stick. -bool CButtonIsAxis(const std::shared_ptr& controller, CONTROLLERBUTTONS_T bitmask) { +// How many of a button's mappings are physically active right now. Lets a +// scheme tell one binding for a button apart from another without reaching past +// the mapper to poll hardware that the player may have unbound. +int CountActiveMappings(const std::shared_ptr& controller, CONTROLLERBUTTONS_T bitmask) { auto button = controller->GetButton(bitmask); if (button == nullptr) { - return false; + return 0; } + int active = 0; for (auto& [id, mapping] : button->GetAllButtonMappings()) { - if (dynamic_cast(mapping.get()) != nullptr) { - return true; + uint16_t held = 0; + mapping->UpdatePad(held); + if (held != 0) { + active++; + } + } + return active; +} + +// Splits a C-button's mappings into the two kinds the shaping pass cares about. +void CollectCButtonSources(const std::shared_ptr& controller, CONTROLLERBUTTONS_T bitmask, + uint16_t& axisMask, uint16_t& otherHeld) { + auto button = controller->GetButton(bitmask); + if (button == nullptr) { + return; + } + for (auto& [id, mapping] : button->GetAllButtonMappings()) { + auto axis = dynamic_cast(mapping.get()); + if (axis != nullptr && axis->AxisIsStick()) { + axisMask |= bitmask; + } else { + mapping->UpdatePad(otherHeld); } } - return false; } } // namespace @@ -130,6 +152,8 @@ void ControlSchemes_Apply(int scheme) { ClearButtonSDL(controller, BTN_CUP); BindButton(controller, BTN_CUP, SDL_CONTROLLER_BUTTON_Y); BindButton(controller, BTN_CDOWN, SDL_CONTROLLER_BUTTON_B); + BindAxisToButton(controller, BTN_CLEFT, SDL_CONTROLLER_AXIS_RIGHTX, -1); + BindAxisToButton(controller, BTN_CRIGHT, SDL_CONTROLLER_AXIS_RIGHTX, 1); // Recenter camera ClearButtonSDL(controller, BTN_R); @@ -177,8 +201,11 @@ void ControlSchemes_Apply(int scheme) { ClearButtonSDL(controller, BTN_CDOWN); BindButton(controller, BTN_CDOWN, SDL_CONTROLLER_BUTTON_B); - // Recenter camera + // Tip-toe / Talon Trot trigger. Recentering moves to a B hold, which + // frees R to carry Pocket's extra gesture as a real, rebindable + // binding instead of the shaping pass polling the trigger itself. ClearButtonSDL(controller, BTN_R); + BindAxisToButton(controller, BTN_R, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 1); // Crouch / Talon Trot ClearButtonSDL(controller, BTN_Z); @@ -200,6 +227,15 @@ void ControlSchemes_Apply(int scheme) { } } +// Frames of C-Down passthrough left for a jigsaw podium. +static int32_t sJigsawPodiumTTL = 0; + +void RegisterControlSchemes_Init() { + COND_HOOK(OnJigsawPodiumInput, EVENT_PRIORITY_NORMAL, true, [](IEvent*) { sJigsawPodiumTTL = 4; }); +} + +static RegisterShipInitFunc initControlSchemes(RegisterControlSchemes_Init); + extern "C" void port_shapeControllerInput(void* contPad) { auto* pad = static_cast(contPad); if (pad == nullptr) { @@ -214,84 +250,70 @@ extern "C" void port_shapeControllerInput(void* contPad) { return; } - const bool modern = CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_MODERN; - const bool crouched = (bs_getState() == BS_CROUCH); + const int scheme = CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO); + const bool modern = (scheme == CONTROL_SCHEME_MODERN); + const bool pocket = (scheme == CONTROL_SCHEME_POCKET); + const bool crouched = (bs_getState() == BS_7_CROUCH); const bool eggPooping = (bs_getState() == BS_A_EGG_ASS); + // Pocket takes its tip-toe / Talon Trot gesture from R and its crouch from + // Z, so both follow whatever the player has bound. Sample them here, before + // the blocks below start injecting synthetic R and Z bits, and consume R - + // in Pocket that button is the gesture channel, not the camera recenter. + bool pocketGesture = false; + bool pocketCrouch = false; + if (pocket) { + pocketGesture = (pad->button & BTN_R) != 0; + pocketCrouch = (pad->button & BTN_Z) != 0; + pad->button &= ~BTN_R; + } + int32_t rx = pad->right_stick_x; int32_t ry = pad->right_stick_y; int32_t arx = (rx < 0) ? -rx : rx; int32_t ary = (ry < 0) ? -ry : ry; + const bool onJigsawPodium = (sJigsawPodiumTTL > 0); + if (sJigsawPodiumTTL > 0) { + sJigsawPodiumTTL--; + } + if (modern) { - if (!crouched && !eggPooping) { + if (!crouched && !eggPooping && !onJigsawPodium) { pad->button &= ~BTN_CDOWN; } - // Read the raw right stick straight from SDL - int32_t sdlX = 0; - int32_t sdlY = 0; - { - auto ctx = Ship::Context::GetRawInstance(); - auto controlDeck = ctx != nullptr ? ctx->GetControlDeck() : nullptr; - auto deviceManager = controlDeck != nullptr ? controlDeck->GetConnectedPhysicalDeviceManager() : nullptr; - if (deviceManager != nullptr) { - for (auto& [instanceId, gamepad] : deviceManager->GetConnectedSDLGamepadsForPort(0)) { - if (gamepad == nullptr) { - continue; - } - int32_t x = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTX); - int32_t y = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTY); - if ((x < 0 ? -x : x) > (sdlX < 0 ? -sdlX : sdlX)) { - sdlX = x; - } - if ((y < 0 ? -y : y) > (sdlY < 0 ? -sdlY : sdlY)) { - sdlY = y; - } - } + const s32 mode = getGameMode(); + const bool picturePuzzle = (mode == GAME_MODE_8_BOTTLES_BONUS || mode == GAME_MODE_A_SNS_PICTURE); + if (!picturePuzzle) { + const uint16_t stickC = pad->button & (BTN_CLEFT | BTN_CRIGHT); + uint16_t allow = 0; + + // One action per push, so holding the stick cannot repeat Wonderwing. + static bool sStickArmed = true; + if (stickC == 0) { + sStickArmed = true; + } else if (crouched && (stickC & BTN_CRIGHT) && arx >= ary && sStickArmed) { + allow = BTN_CRIGHT; + sStickArmed = false; } - } - int32_t asx = (sdlX < 0) ? -sdlX : sdlX; - int32_t asy = (sdlY < 0) ? -sdlY : sdlY; - - // Edge press with hysteresis - static bool sStickArmed = true; - const int32_t onThreshold = 12000; - const int32_t offThreshold = 6000; - - // Standing, the camera owns the right stick - // Crouched, it yields one action - uint16_t want = 0; - if (crouched && sdlX > onThreshold && asx >= asy) { - want = BTN_CRIGHT; // stick-right -> Wonderwing - } - - if (want != 0 && sStickArmed) { - pad->button |= want; - sStickArmed = false; - } - if ((crouched ? asx : asy) < offThreshold) { - sStickArmed = true; + pad->button = (pad->button & ~(BTN_CLEFT | BTN_CRIGHT)) | allow; } } else { uint16_t axisMask = 0; - if (CButtonIsAxis(controller, BTN_CRIGHT)) { - axisMask |= BTN_CRIGHT; - } - if (CButtonIsAxis(controller, BTN_CLEFT)) { - axisMask |= BTN_CLEFT; - } - if (CButtonIsAxis(controller, BTN_CDOWN)) { - axisMask |= BTN_CDOWN; - } - if (CButtonIsAxis(controller, BTN_CUP)) { - axisMask |= BTN_CUP; + uint16_t otherHeld = 0; + static const CONTROLLERBUTTONS_T kCButtons[] = { BTN_CRIGHT, BTN_CLEFT, BTN_CDOWN, BTN_CUP }; + for (CONTROLLERBUTTONS_T cButton : kCButtons) { + CollectCButtonSources(controller, cButton, axisMask, otherHeld); } + // Directions the stick owns outright; anything a second binding is + // holding stays put instead of being cleared and regenerated. + const uint16_t clearMask = axisMask & ~otherHeld; static uint16_t sLatchDir = 0; static int32_t sLatchTTL = 0; - if (port_freeLook_isEnabled()) { + if (port_freeLook_isEnabled() && !onJigsawPodium) { uint16_t stickBits = 0; if (arx * arx + ary * ary > 24 * 24) { if (arx >= ary) { @@ -300,11 +322,11 @@ extern "C" void port_shapeControllerInput(void* contPad) { stickBits = (ry > 0) ? BTN_CUP : BTN_CDOWN; } } - pad->button &= ~(stickBits & axisMask); + pad->button &= ~(stickBits & clearMask); sLatchDir = 0; sLatchTTL = 0; } else if (axisMask != 0) { - pad->button &= ~axisMask; + pad->button &= ~clearMask; if (arx * arx + ary * ary > 24 * 24) { uint16_t dir; @@ -344,44 +366,20 @@ extern "C" void port_shapeControllerInput(void* contPad) { } // Modern Talon Trot - static bool sPrevLeftTrigger = false; - static bool sPrevRightTrigger = false; - + // + // Crouch gets bound to both triggers, and pressing the second one while the + // first is held starts the trot. Counting how many crouch bindings are live + // expresses that without naming a trigger: whatever the player has on Z is + // what works, and a trigger they have unbound does nothing. + static int sPrevCrouchBindings = 0; if (modern) { - const Sint16 kTriggerThreshold = 8000; - bool leftTrigger = false; - bool rightTrigger = false; - - auto ctx = Ship::Context::GetRawInstance(); - auto controlDeck = ctx != nullptr ? ctx->GetControlDeck() : nullptr; - auto deviceManager = controlDeck != nullptr ? controlDeck->GetConnectedPhysicalDeviceManager() : nullptr; - if (deviceManager != nullptr) { - for (auto& [instanceId, gamepad] : deviceManager->GetConnectedSDLGamepadsForPort(0)) { - if (gamepad == nullptr) { - continue; - } - if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > kTriggerThreshold) { - leftTrigger = true; - } - if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > kTriggerThreshold) { - rightTrigger = true; - } - } - } - - if (crouched) { - bool leftEdge = leftTrigger && !sPrevLeftTrigger; - bool rightEdge = rightTrigger && !sPrevRightTrigger; - if ((rightEdge && sPrevLeftTrigger) || (leftEdge && sPrevRightTrigger)) { - pad->button |= BTN_CLEFT; - } + const int crouchBindings = CountActiveMappings(controller, BTN_Z); + if (crouched && crouchBindings >= 2 && crouchBindings > sPrevCrouchBindings) { + pad->button |= BTN_CLEFT; } - - sPrevLeftTrigger = leftTrigger; - sPrevRightTrigger = rightTrigger; + sPrevCrouchBindings = crouchBindings; } else { - sPrevLeftTrigger = false; - sPrevRightTrigger = false; + sPrevCrouchBindings = 0; } // Toggle Trot @@ -419,8 +417,7 @@ extern "C" void port_shapeControllerInput(void* contPad) { static bool sBWasHeld = false; const int32_t kBHoldFrames = 12; // ~0.2s before a standing press counts as a hold bool bHeld = (pad->button & BTN_CDOWN) != 0; - if (CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_POCKET && !crouched && - !eggPooping) { + if (pocket && !crouched && !eggPooping) { pad->button &= ~BTN_CDOWN; if (bHeld) { if (sBHeldFrames < kBHoldFrames) { @@ -443,43 +440,25 @@ extern "C" void port_shapeControllerInput(void* contPad) { } sBWasHeld = bHeld; - // Pocket: Talon Trot (LT + RT) and tip-toe (RT) - // LT crouches. While crouched, an RT press injects C-Left to start the Talon Trot. - // RT on its own (no crouch) lightly touches the analog stick for a tip-toe. + // Pocket: Talon Trot (Z + R) and tip-toe (R) + // Z crouches. While crouched, an R press injects C-Left to start the Talon Trot. + // R on its own (no crouch) lightly touches the analog stick for a tip-toe. + // Both come off the mapped pad, so rebinding either button moves the gesture. static bool sTipToe = false; - static bool sPrevR2 = false; - if (CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_POCKET) { - bool r2 = false; - bool l2 = false; - auto ctx = Ship::Context::GetRawInstance(); - auto controlDeck = ctx != nullptr ? ctx->GetControlDeck() : nullptr; - auto deviceManager = controlDeck != nullptr ? controlDeck->GetConnectedPhysicalDeviceManager() : nullptr; - if (deviceManager != nullptr) { - for (auto& [instanceId, gamepad] : deviceManager->GetConnectedSDLGamepadsForPort(0)) { - if (gamepad == nullptr) { - continue; - } - if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > 8000) { - r2 = true; - } - if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > 8000) { - l2 = true; - } - } - } - - if (l2) { - // Crouching: RT is the Talon Trot trigger, not tip-toe. - if (crouched && r2 && !sPrevR2) { + static bool sPrevGesture = false; + if (pocket) { + if (pocketCrouch) { + // Crouching: R is the Talon Trot trigger, not tip-toe. + if (crouched && pocketGesture && !sPrevGesture) { pad->button |= BTN_CLEFT; // C-Left while crouched starts the Talon Trot } sTipToe = false; } else if (CVarGetInteger(CVAR_SETTING("Controls.PocketTipToeHold"), 0) != 0) { - sTipToe = r2; // hold mode - } else if (r2 && !sPrevR2) { + sTipToe = pocketGesture; // hold mode + } else if (pocketGesture && !sPrevGesture) { sTipToe = !sTipToe; // tap toggles } - sPrevR2 = r2; + sPrevGesture = pocketGesture; if (sTipToe) { const float kTipToeScale = 0.25f; @@ -488,6 +467,6 @@ extern "C" void port_shapeControllerInput(void* contPad) { } } else { sTipToe = false; - sPrevR2 = false; + sPrevGesture = false; } } diff --git a/src/port/Controller/Mapper.cpp b/src/port/Controller/Mapper.cpp new file mode 100644 index 000000000..d2b5bf956 --- /dev/null +++ b/src/port/Controller/Mapper.cpp @@ -0,0 +1,1709 @@ +#include "Mapper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/port/Engine.h" +#include "src/port/UI/LighthouseGui.hpp" +#include "src/port/UI/LighthouseMenu.h" +#include "src/port/UI/UIWidgets.hpp" +#include "src/port/UI/cvar_prefixes.h" + +#include + +namespace LighthouseGui { +extern std::shared_ptr mLighthouseMenu; +} + +namespace Mapper { + +using namespace UIWidgets; + +static const char* kUserMappingsFileName = "usergamepadmappings.txt"; + +static const char* kDiagramTextureName = "Gamepad-Mapper-Diagram"; +static const char* kDiagramTexturePath = "textures/mapping-xbox.png"; + +// --------------------------------------------------------------------------------------------------- +// Binding metadata +// --------------------------------------------------------------------------------------------------- + +static const char* kButtonNames[SDL_CONTROLLER_BUTTON_MAX] = { + "A", + "B", + "X", + "Y", + "Back", + "Guide", + "Start", + "Left Stick Click", + "Right Stick Click", + "Left Bumper", + "Right Bumper", + "D-Pad Up", + "D-Pad Down", + "D-Pad Left", + "D-Pad Right", + "Misc 1", + "Paddle 1", + "Paddle 2", + "Paddle 3", + "Paddle 4", + "Touchpad", +}; + +static const char* kAxisNames[AXIS_BINDING_MAX] = { + "Left Stick Left", "Left Stick Right", "Left Stick Up", "Left Stick Down", "Right Stick Left", + "Right Stick Right", "Right Stick Up", "Right Stick Down", "Left Trigger", "Right Trigger", +}; + +const char* BindingName(int32_t binding) { + if (binding < 0 || binding >= BINDING_COUNT) { + return "?"; + } + if (binding < SDL_CONTROLLER_BUTTON_MAX) { + return kButtonNames[binding]; + } + return kAxisNames[binding - SDL_CONTROLLER_BUTTON_MAX]; +} + +struct StickAxisPair { + SDL_GameControllerAxis axis; + int32_t negative; + int32_t positive; +}; + +static const StickAxisPair kStickAxes[] = { + { SDL_CONTROLLER_AXIS_LEFTX, AXIS_LEFTX_NEGATIVE, AXIS_LEFTX_POSITIVE }, + { SDL_CONTROLLER_AXIS_LEFTY, AXIS_LEFTY_NEGATIVE, AXIS_LEFTY_POSITIVE }, + { SDL_CONTROLLER_AXIS_RIGHTX, AXIS_RIGHTX_NEGATIVE, AXIS_RIGHTX_POSITIVE }, + { SDL_CONTROLLER_AXIS_RIGHTY, AXIS_RIGHTY_NEGATIVE, AXIS_RIGHTY_POSITIVE }, +}; + +static const int32_t kCoreBindingOrder[] = { + SDL_CONTROLLER_BUTTON_A, + SDL_CONTROLLER_BUTTON_B, + SDL_CONTROLLER_BUTTON_X, + SDL_CONTROLLER_BUTTON_Y, + SDL_CONTROLLER_BUTTON_BACK, + SDL_CONTROLLER_BUTTON_START, + SDL_CONTROLLER_BUTTON_LEFTSHOULDER, + SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, + SDL_CONTROLLER_BUTTON_LEFTSTICK, + SDL_CONTROLLER_BUTTON_RIGHTSTICK, + SDL_CONTROLLER_BUTTON_DPAD_UP, + SDL_CONTROLLER_BUTTON_DPAD_DOWN, + SDL_CONTROLLER_BUTTON_DPAD_LEFT, + SDL_CONTROLLER_BUTTON_DPAD_RIGHT, + SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_NEGATIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_POSITIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_NEGATIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_POSITIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_NEGATIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_POSITIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_NEGATIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_POSITIVE, + SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT, + SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT, +}; + +static const int32_t kExtraBindings[] = { + SDL_CONTROLLER_BUTTON_GUIDE, SDL_CONTROLLER_BUTTON_MISC1, SDL_CONTROLLER_BUTTON_PADDLE1, + SDL_CONTROLLER_BUTTON_PADDLE2, SDL_CONTROLLER_BUTTON_PADDLE3, SDL_CONTROLLER_BUTTON_PADDLE4, + SDL_CONTROLLER_BUTTON_TOUCHPAD, +}; + +// --------------------------------------------------------------------------------------------------- +// Binding helpers +// --------------------------------------------------------------------------------------------------- + +static ExtendedBind NoBind() { + ExtendedBind bind = {}; + bind.bindType = SDL_CONTROLLER_BINDTYPE_NONE; + return bind; +} + +void ClearBindings(ExtendedBind (&bindings)[BINDING_COUNT]) { + for (int32_t i = 0; i < BINDING_COUNT; i++) { + bindings[i] = NoBind(); + } +} + +bool HasAnyBinding(const ExtendedBind (&bindings)[BINDING_COUNT]) { + for (int32_t i = 0; i < BINDING_COUNT; i++) { + if (bindings[i].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { + return true; + } + } + return false; +} + +static bool IsFullRangeAxis(const ExtendedBind& bind) { + if (bind.bindType != SDL_CONTROLLER_BINDTYPE_AXIS) { + return false; + } + return (bind.value.axis.axisMin == SDL_JOYSTICK_AXIS_MIN && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MAX) || + (bind.value.axis.axisMin == SDL_JOYSTICK_AXIS_MAX && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MIN); +} + +static bool MergeAxisBindings(ExtendedBind (&bindings)[BINDING_COUNT], int32_t negative, int32_t positive) { + ExtendedBind& a = bindings[negative]; + ExtendedBind& b = bindings[positive]; + if (a.bindType == SDL_CONTROLLER_BINDTYPE_AXIS && b.bindType == SDL_CONTROLLER_BINDTYPE_AXIS && + a.value.axis.axis == b.value.axis.axis && a.value.axis.axisMin == b.value.axis.axisMin) { + a.value.axis.axisMin = a.value.axis.axisMax; + a.value.axis.axisMax = b.value.axis.axisMax; + b = NoBind(); + return true; + } + return false; +} + +static std::string EncodeBindElement(const ExtendedBind& bind) { + switch (bind.bindType) { + case SDL_CONTROLLER_BINDTYPE_BUTTON: + return StringHelper::Sprintf("b%d", bind.value.button); + case SDL_CONTROLLER_BINDTYPE_AXIS: + if (bind.value.axis.axisMin == 0 && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MIN) { + return StringHelper::Sprintf("-a%d", bind.value.axis.axis); + } + if (bind.value.axis.axisMin == 0 && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MAX) { + return StringHelper::Sprintf("+a%d", bind.value.axis.axis); + } + return StringHelper::Sprintf("a%d%s", bind.value.axis.axis, + bind.value.axis.axisMin > bind.value.axis.axisMax ? "~" : ""); + case SDL_CONTROLLER_BINDTYPE_HAT: + return StringHelper::Sprintf("h%d.%d", bind.value.hat.hat, bind.value.hat.hatMask); + default: + return ""; + } +} + +static const char* HatMaskName(int32_t mask) { + switch (mask) { + case SDL_HAT_UP: + return "Up"; + case SDL_HAT_DOWN: + return "Down"; + case SDL_HAT_LEFT: + return "Left"; + case SDL_HAT_RIGHT: + return "Right"; + case SDL_HAT_LEFTUP: + return "Up-Left"; + case SDL_HAT_RIGHTUP: + return "Up-Right"; + case SDL_HAT_LEFTDOWN: + return "Down-Left"; + case SDL_HAT_RIGHTDOWN: + return "Down-Right"; + default: + return "?"; + } +} + +std::string DescribeBind(const ExtendedBind& bind) { + switch (bind.bindType) { + case SDL_CONTROLLER_BINDTYPE_BUTTON: + return StringHelper::Sprintf("Button %d", bind.value.button); + case SDL_CONTROLLER_BINDTYPE_AXIS: + if (IsFullRangeAxis(bind)) { + return StringHelper::Sprintf("Axis %d%s", bind.value.axis.axis, + bind.value.axis.axisMin > bind.value.axis.axisMax ? " inv" : ""); + } + return StringHelper::Sprintf("Axis %d %s", bind.value.axis.axis, + bind.value.axis.axisMax < bind.value.axis.axisMin ? "-" : "+"); + case SDL_CONTROLLER_BINDTYPE_HAT: + return StringHelper::Sprintf("Hat %d %s", bind.value.hat.hat, HatMaskName(bind.value.hat.hatMask)); + default: + return ""; + } +} + +// --------------------------------------------------------------------------------------------------- +// Mapping string generation / parsing +// --------------------------------------------------------------------------------------------------- + +static std::string SanitizeName(const std::string& name) { + std::string result = name; + std::replace(result.begin(), result.end(), ',', ' '); + return result; +} + +std::string GenerateMappingString(SDL_Joystick* joystick, const ExtendedBind (&bindings)[BINDING_COUNT], + const std::string& nameOverride) { + if (joystick == nullptr) { + return ""; + } + + SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); + uint16_t crc = 0; +#if SDL_VERSION_ATLEAST(2, 26, 0) + SDL_GetJoystickGUIDInfo(guid, nullptr, nullptr, nullptr, &crc); + if (crc != 0) { + guid.data[2] = 0; + guid.data[3] = 0; + } +#endif + + char guidString[33] = ""; + SDL_JoystickGetGUIDString(guid, guidString, sizeof(guidString)); + + const char* rawName = SDL_JoystickName(joystick); + std::string name = SanitizeName(nameOverride); + if (name.find_first_not_of(' ') == std::string::npos) { + name = SanitizeName(rawName != nullptr ? rawName : guidString); + } + + std::string mapping = StringHelper::Sprintf("%s,%s,platform:%s,", guidString, name.c_str(), SDL_GetPlatform()); + if (crc != 0) { + mapping += StringHelper::Sprintf("crc:%.4x,", crc); + } + + ExtendedBind work[BINDING_COUNT]; + for (int32_t i = 0; i < BINDING_COUNT; i++) { + work[i] = bindings[i]; + } + + for (int32_t i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++) { + if (work[i].bindType == SDL_CONTROLLER_BINDTYPE_NONE) { + continue; + } + const char* name = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)i); + if (name == nullptr) { + continue; + } + mapping += StringHelper::Sprintf("%s:%s,", name, EncodeBindElement(work[i]).c_str()); + } + + for (const auto& stick : kStickAxes) { + const int32_t negative = SDL_CONTROLLER_BUTTON_MAX + stick.negative; + const int32_t positive = SDL_CONTROLLER_BUTTON_MAX + stick.positive; + const char* name = SDL_GameControllerGetStringForAxis(stick.axis); + if (name == nullptr) { + continue; + } + + MergeAxisBindings(work, negative, positive); + + if (work[negative].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { + const char* prefix = IsFullRangeAxis(work[negative]) ? "" : "-"; + mapping += StringHelper::Sprintf("%s%s:%s,", prefix, name, EncodeBindElement(work[negative]).c_str()); + } + if (work[positive].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { + mapping += StringHelper::Sprintf("+%s:%s,", name, EncodeBindElement(work[positive]).c_str()); + } + } + + const std::pair triggers[] = { + { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERLEFT }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT }, + }; + for (const auto& trigger : triggers) { + if (work[trigger.first].bindType == SDL_CONTROLLER_BINDTYPE_NONE) { + continue; + } + const char* name = SDL_GameControllerGetStringForAxis(trigger.second); + if (name == nullptr) { + continue; + } + mapping += StringHelper::Sprintf("%s:%s,", name, EncodeBindElement(work[trigger.first]).c_str()); + } + + return mapping; +} + +static int32_t BindingIndexForKey(const std::string& key) { + std::string name = key; + char sign = 0; + if (!name.empty() && (name.front() == '+' || name.front() == '-')) { + sign = name.front(); + name.erase(0, 1); + } + + const SDL_GameControllerAxis axis = SDL_GameControllerGetAxisFromString(name.c_str()); + if (axis != SDL_CONTROLLER_AXIS_INVALID) { + switch (axis) { + case SDL_CONTROLLER_AXIS_LEFTX: + return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_LEFTX_POSITIVE : AXIS_LEFTX_NEGATIVE); + case SDL_CONTROLLER_AXIS_LEFTY: + return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_LEFTY_POSITIVE : AXIS_LEFTY_NEGATIVE); + case SDL_CONTROLLER_AXIS_RIGHTX: + return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_RIGHTX_POSITIVE : AXIS_RIGHTX_NEGATIVE); + case SDL_CONTROLLER_AXIS_RIGHTY: + return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_RIGHTY_POSITIVE : AXIS_RIGHTY_NEGATIVE); + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: + return SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT; + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: + return SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT; + default: + return -1; + } + } + + if (sign != 0) { + return -1; + } + const SDL_GameControllerButton button = SDL_GameControllerGetButtonFromString(name.c_str()); + return button != SDL_CONTROLLER_BUTTON_INVALID ? (int32_t)button : -1; +} + +static bool DecodeBindElement(const std::string& value, ExtendedBind& out) { + std::string element = value; + bool inverted = false; + if (!element.empty() && element.back() == '~') { + inverted = true; + element.pop_back(); + } + + char sign = 0; + if (!element.empty() && (element.front() == '+' || element.front() == '-')) { + sign = element.front(); + element.erase(0, 1); + } + if (element.size() < 2) { + return false; + } + + out = {}; + out.committed = true; + + switch (element.front()) { + case 'b': + out.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON; + out.value.button = std::atoi(element.c_str() + 1); + return true; + case 'a': + out.bindType = SDL_CONTROLLER_BINDTYPE_AXIS; + out.value.axis.axis = std::atoi(element.c_str() + 1); + if (sign == '-') { + out.value.axis.axisMin = 0; + out.value.axis.axisMax = SDL_JOYSTICK_AXIS_MIN; + } else if (sign == '+') { + out.value.axis.axisMin = 0; + out.value.axis.axisMax = SDL_JOYSTICK_AXIS_MAX; + } else { + out.value.axis.axisMin = inverted ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN; + out.value.axis.axisMax = inverted ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX; + } + return true; + case 'h': { + int32_t hat = 0; + int32_t mask = 0; + if (std::sscanf(element.c_str() + 1, "%d.%d", &hat, &mask) != 2) { + return false; + } + out.bindType = SDL_CONTROLLER_BINDTYPE_HAT; + out.value.hat.hat = hat; + out.value.hat.hatMask = mask; + return true; + } + default: + out = NoBind(); + return false; + } +} + +int32_t ParseMappingString(const std::string& mapping, ExtendedBind (&bindings)[BINDING_COUNT]) { + ClearBindings(bindings); + + int32_t recovered = 0; + size_t start = 0; + while (start <= mapping.size()) { + const size_t end = mapping.find(',', start); + const std::string field = mapping.substr(start, end == std::string::npos ? std::string::npos : end - start); + start = end == std::string::npos ? mapping.size() + 1 : end + 1; + + const size_t colon = field.find(':'); + if (colon == std::string::npos) { + continue; + } + + const int32_t index = BindingIndexForKey(field.substr(0, colon)); + if (index < 0) { + continue; + } + if (DecodeBindElement(field.substr(colon + 1), bindings[index])) { + recovered++; + } + } + + for (const auto& stick : kStickAxes) { + const int32_t negative = SDL_CONTROLLER_BUTTON_MAX + stick.negative; + const int32_t positive = SDL_CONTROLLER_BUTTON_MAX + stick.positive; + if (!IsFullRangeAxis(bindings[negative]) || bindings[positive].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { + continue; + } + + const bool axisInverted = bindings[negative].value.axis.axisMin > bindings[negative].value.axis.axisMax; + bindings[positive] = bindings[negative]; + bindings[negative].value.axis.axisMin = 0; + bindings[negative].value.axis.axisMax = axisInverted ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN; + bindings[positive].value.axis.axisMin = 0; + bindings[positive].value.axis.axisMax = axisInverted ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX; + } + + return recovered; +} + +// --------------------------------------------------------------------------------------------------- +// MappingSession +// --------------------------------------------------------------------------------------------------- + +MappingSession::MappingSession() + : mBindings{}, mCurrentStep(0), mPendingAdvanceTime(0), mActive(false), mComplete(false) { + ClearBindings(mBindings); +} + +void MappingSession::Start(SDL_Joystick* joystick, const std::vector& order) { + mOrder = order; + mCurrentStep = 0; + mComplete = mOrder.empty(); + mActive = !mOrder.empty(); + mPendingAdvanceTime = 0; + + const int32_t axisCount = joystick != nullptr ? SDL_JoystickNumAxes(joystick) : 0; + mAxisState.assign(axisCount > 0 ? (size_t)axisCount : 0, AxisState{}); + for (int32_t i = 0; i < axisCount; i++) { + Sint16 initialValue = 0; + mAxisState[i].moving = SDL_JoystickGetAxisInitialState(joystick, i, &initialValue) == SDL_TRUE; + mAxisState[i].lastValue = initialValue; + mAxisState[i].startingValue = initialValue; + mAxisState[i].farthestValue = initialValue; + } + + if (mActive) { + mBindings[mOrder[0]] = NoBind(); + } +} + +void MappingSession::Stop() { + mActive = false; + mComplete = false; + mOrder.clear(); + mAxisState.clear(); + mPendingAdvanceTime = 0; +} + +bool MappingSession::IsActive() const { + return mActive; +} + +bool MappingSession::IsComplete() const { + return mComplete; +} + +int32_t MappingSession::CurrentStep() const { + return mCurrentStep; +} + +int32_t MappingSession::StepCount() const { + return (int32_t)mOrder.size(); +} + +int32_t MappingSession::CurrentBinding() const { + if (mCurrentStep < 0 || mCurrentStep >= (int32_t)mOrder.size()) { + return -1; + } + return mOrder[mCurrentStep]; +} + +void MappingSession::GoToStep(int32_t step) { + if (step < 0) { + return; + } + if (step >= (int32_t)mOrder.size()) { + mComplete = true; + mActive = false; + return; + } + + mCurrentStep = step; + + mBindings[mOrder[mCurrentStep]] = NoBind(); + for (auto& state : mAxisState) { + state.farthestValue = state.startingValue; + } + mPendingAdvanceTime = 0; +} + +void MappingSession::Advance() { + GoToStep(mCurrentStep + 1); +} + +void MappingSession::GoBack() { + GoToStep(mCurrentStep - 1); +} + +const ExtendedBind& MappingSession::GetBinding(int32_t index) const { + return mBindings[index]; +} + +void MappingSession::SetBindings(const ExtendedBind (&bindings)[BINDING_COUNT]) { + for (int32_t i = 0; i < BINDING_COUNT; i++) { + mBindings[i] = bindings[i]; + } +} + +void MappingSession::CopyBindingsTo(ExtendedBind (&out)[BINDING_COUNT]) const { + for (int32_t i = 0; i < BINDING_COUNT; i++) { + out[i] = mBindings[i]; + } +} + +bool MappingSession::BindingContainsBinding(const ExtendedBind& a, const ExtendedBind& b) const { + if (a.bindType != b.bindType) { + return false; + } + + if (a.bindType == SDL_CONTROLLER_BINDTYPE_AXIS) { + if (a.value.axis.axis != b.value.axis.axis || !a.committed) { + return false; + } + const int32_t minA = std::min(a.value.axis.axisMin, a.value.axis.axisMax); + const int32_t maxA = std::max(a.value.axis.axisMin, a.value.axis.axisMax); + const int32_t minB = std::min(b.value.axis.axisMin, b.value.axis.axisMax); + const int32_t maxB = std::max(b.value.axis.axisMin, b.value.axis.axisMax); + return minA <= minB && maxA >= maxB; + } + + return std::memcmp(&a, &b, sizeof(a)) == 0; +} + +void MappingSession::ConfigureBinding(const ExtendedBind& binding) { + const int32_t currentElement = CurrentBinding(); + if (currentElement < 0) { + return; + } + + for (int32_t i = 0; i < BINDING_COUNT; i++) { + if (BindingContainsBinding(mBindings[i], binding)) { + return; + } + } + + ExtendedBind& current = mBindings[currentElement]; + if (current.bindType != SDL_CONTROLLER_BINDTYPE_NONE) { + const bool nativeDPad = + currentElement == SDL_CONTROLLER_BUTTON_DPAD_UP || currentElement == SDL_CONTROLLER_BUTTON_DPAD_DOWN || + currentElement == SDL_CONTROLLER_BUTTON_DPAD_LEFT || currentElement == SDL_CONTROLLER_BUTTON_DPAD_RIGHT; + if (nativeDPad && current.bindType == SDL_CONTROLLER_BINDTYPE_HAT) { + return; + } + + const bool nativeAxis = currentElement >= SDL_CONTROLLER_BUTTON_MAX; + const bool currentIsAxis = current.bindType == SDL_CONTROLLER_BINDTYPE_AXIS; + if (nativeAxis == currentIsAxis && + (binding.bindType != SDL_CONTROLLER_BINDTYPE_AXIS || binding.value.axis.axis != current.value.axis.axis)) { + return; + } + } + + current = binding; + mPendingAdvanceTime = binding.committed ? SDL_GetTicks() : 0; +} + +void MappingSession::ProcessButtonDown(int32_t button) { + if (!mActive) { + return; + } + ExtendedBind binding = {}; + binding.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON; + binding.value.button = button; + binding.committed = true; + ConfigureBinding(binding); +} + +void MappingSession::ProcessHatMotion(int32_t hat, int32_t value) { + if (!mActive || value == SDL_HAT_CENTERED) { + return; + } + ExtendedBind binding = {}; + binding.bindType = SDL_CONTROLLER_BINDTYPE_HAT; + binding.value.hat.hat = hat; + binding.value.hat.hatMask = value; + binding.committed = true; + ConfigureBinding(binding); +} + +static int32_t StandardizeAxisValue(int32_t value) { + if (value > SDL_JOYSTICK_AXIS_MAX / 2) { + return SDL_JOYSTICK_AXIS_MAX; + } + if (value < SDL_JOYSTICK_AXIS_MIN / 2) { + return SDL_JOYSTICK_AXIS_MIN; + } + return 0; +} + +void MappingSession::ProcessAxisMotion(int32_t axis, int32_t value, SDL_Joystick* joystick) { + if (!mActive || axis < 0 || axis >= (int32_t)mAxisState.size()) { + return; + } + + constexpr int32_t MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80; + AxisState& state = mAxisState[axis]; + + if (!state.moving) { + Sint16 initialValue = 0; + state.moving = SDL_JoystickGetAxisInitialState(joystick, axis, &initialValue) == SDL_TRUE; + state.lastValue = value; + state.startingValue = initialValue; + state.farthestValue = initialValue; + } else if (std::abs(value - state.lastValue) <= MAX_ALLOWED_JITTER) { + return; + } else { + state.lastValue = value; + } + + const int32_t currentDistance = std::abs(value - state.startingValue); + int32_t farthestDistance = std::abs(state.farthestValue - state.startingValue); + if (currentDistance > farthestDistance) { + state.farthestValue = value; + farthestDistance = std::abs(state.farthestValue - state.startingValue); + } + + if (farthestDistance < AXIS_COMMIT_DISTANCE) { + return; + } + + ExtendedBind binding = {}; + binding.bindType = SDL_CONTROLLER_BINDTYPE_AXIS; + binding.value.axis.axis = axis; + binding.value.axis.axisMin = StandardizeAxisValue(state.startingValue); + binding.value.axis.axisMax = StandardizeAxisValue(state.farthestValue); + binding.committed = currentDistance <= AXIS_RETURN_DISTANCE; + ConfigureBinding(binding); +} + +void MappingSession::CheckPendingAdvance() { + if (!mActive || mPendingAdvanceTime == 0) { + return; + } + if (SDL_GetTicks() - mPendingAdvanceTime >= PENDING_ADVANCE_DELAY_MS) { + Advance(); + } +} + +// --------------------------------------------------------------------------------------------------- +// usergamepadmappings.txt +// --------------------------------------------------------------------------------------------------- + +std::string GetUserMappingsPath() { + return Ship::Context::GetPathRelativeToAppDirectory(kUserMappingsFileName); +} + +static std::string StripCrcFromGuid(const std::string& guid) { + if (guid.length() < 32) { + return guid; + } + return guid.substr(0, 4) + "0000" + guid.substr(8); +} + +static std::string MappingKey(const std::string& mapping) { + const size_t comma = mapping.find(','); + if (comma == std::string::npos || comma == 0) { + return ""; + } + std::string key = StripCrcFromGuid(mapping.substr(0, comma)); + + const size_t crcPos = mapping.find(",crc:"); + if (crcPos != std::string::npos) { + const size_t valueStart = crcPos + 1; + size_t valueEnd = mapping.find(',', valueStart); + if (valueEnd == std::string::npos) { + valueEnd = mapping.length(); + } + key += "," + mapping.substr(valueStart, valueEnd - valueStart); + } + return key; +} + +static bool IsMappingLine(const std::string& line) { + return !line.empty() && line.front() != '#'; +} + +static std::vector ReadUserMappingLines() { + std::vector lines; + std::ifstream file(GetUserMappingsPath()); + if (!file.is_open()) { + return lines; + } + + std::string line; + while (std::getline(file, line)) { + if (!line.empty() && line.back() == '\r') { + line.pop_back(); + } + lines.push_back(line); + } + return lines; +} + +static bool WriteUserMappingLines(const std::vector& lines) { + const std::string path = GetUserMappingsPath(); + const std::string tempPath = path + ".tmp"; + + { + std::ofstream file(tempPath, std::ios::binary | std::ios::trunc); + if (!file.is_open()) { + SPDLOG_ERROR("Failed to open \"{}\" for writing", tempPath); + return false; + } + file << "# SoH user gamepad mappings, written by the built-in gamepad mapper.\n"; + file << "# Loaded on top of gamecontrollerdb.txt, so entries here win.\n"; + for (const auto& line : lines) { + file << line << "\n"; + } + if (!file.good()) { + SPDLOG_ERROR("Failed while writing \"{}\"", tempPath); + return false; + } + } + + std::error_code error; + std::filesystem::rename(tempPath, path, error); + if (error) { + SPDLOG_ERROR("Failed to move \"{}\" into place: {}", tempPath, error.message()); + std::filesystem::remove(tempPath, error); + return false; + } + return true; +} + +std::string FindUserMapping(const std::string& guid) { + const std::string base = StripCrcFromGuid(guid); + for (const auto& line : ReadUserMappingLines()) { + if (!IsMappingLine(line)) { + continue; + } + const size_t comma = line.find(','); + if (comma != std::string::npos && StripCrcFromGuid(line.substr(0, comma)) == base) { + return line; + } + } + return ""; +} + +std::string MappingName(const std::string& mapping) { + const size_t first = mapping.find(','); + if (first == std::string::npos) { + return ""; + } + const size_t second = mapping.find(',', first + 1); + return mapping.substr(first + 1, second == std::string::npos ? std::string::npos : second - first - 1); +} + +bool LoadUserMappings() { + const std::string path = GetUserMappingsPath(); + + std::error_code error; + if (!std::filesystem::exists(path, error)) { + return false; + } + + const int32_t added = SDL_GameControllerAddMappingsFromFile(path.c_str()); + if (added < 0) { + SPDLOG_ERROR("Failed to add user gamepad mappings from \"{}\": {}", path, SDL_GetError()); + return false; + } + + SPDLOG_INFO("Added {} user gamepad mapping(s) from \"{}\"", added, path); + Ship::Context::GetRawInstance() + ->GetControlDeck() + ->GetConnectedPhysicalDeviceManager() + ->RefreshConnectedSDLGamepads(); + return true; +} + +bool SaveUserMapping(const std::string& mapping) { + const std::string key = MappingKey(mapping); + if (key.empty()) { + SPDLOG_ERROR("Refusing to save a gamepad mapping with no GUID"); + return false; + } + + std::vector lines; + for (const auto& line : ReadUserMappingLines()) { + if (!IsMappingLine(line)) { + continue; + } + if (MappingKey(line) == key) { + continue; + } + lines.push_back(line); + } + lines.push_back(mapping); + + if (!WriteUserMappingLines(lines)) { + return false; + } + + if (SDL_GameControllerAddMapping(mapping.c_str()) < 0) { + SPDLOG_ERROR("SDL rejected the generated mapping \"{}\": {}", mapping, SDL_GetError()); + return false; + } + + Ship::Context::GetRawInstance() + ->GetControlDeck() + ->GetConnectedPhysicalDeviceManager() + ->RefreshConnectedSDLGamepads(); + return true; +} + +bool DeleteUserMapping(const std::string& guid) { + const std::string base = StripCrcFromGuid(guid); + + std::vector lines; + bool found = false; + for (const auto& line : ReadUserMappingLines()) { + if (!IsMappingLine(line)) { + continue; + } + const size_t comma = line.find(','); + if (comma != std::string::npos && StripCrcFromGuid(line.substr(0, comma)) == base) { + found = true; + continue; + } + lines.push_back(line); + } + + if (!found) { + return false; + } + if (!WriteUserMappingLines(lines)) { + return false; + } + + Ship::Context::GetRawInstance() + ->GetControlDeck() + ->GetConnectedPhysicalDeviceManager() + ->RefreshConnectedSDLGamepads(); + return true; +} + +// --------------------------------------------------------------------------------------------------- +// Diagram layout +// --------------------------------------------------------------------------------------------------- + +struct DiagramEntry { + int32_t binding; + ImVec2 hotspot; + bool labelOnRight; +}; + +static constexpr float MAX_IMAGE_SPAN = 0.52f; +static constexpr float MIN_IMAGE_WIDTH = 360.0f; +static constexpr float FALLBACK_ART_ASPECT = 1850.0f / 1302.0f; +static constexpr ImU32 NAME_COLOR = IM_COL32(138, 144, 156, 255); + +static const DiagramEntry kDiagram[] = { + { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT, ImVec2(0.081f, 0.110f), false }, + { SDL_CONTROLLER_BUTTON_LEFTSHOULDER, ImVec2(0.234f, 0.092f), false }, + { SDL_CONTROLLER_BUTTON_BACK, ImVec2(0.426f, 0.408f), false }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_NEGATIVE, ImVec2(0.241f, 0.315f), false }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_NEGATIVE, ImVec2(0.185f, 0.401f), false }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_POSITIVE, ImVec2(0.297f, 0.401f), false }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_POSITIVE, ImVec2(0.241f, 0.487f), false }, + { SDL_CONTROLLER_BUTTON_LEFTSTICK, ImVec2(0.241f, 0.401f), false }, + { SDL_CONTROLLER_BUTTON_DPAD_UP, ImVec2(0.368f, 0.540f), false }, + { SDL_CONTROLLER_BUTTON_DPAD_LEFT, ImVec2(0.310f, 0.614f), false }, + { SDL_CONTROLLER_BUTTON_DPAD_RIGHT, ImVec2(0.416f, 0.614f), false }, + { SDL_CONTROLLER_BUTTON_DPAD_DOWN, ImVec2(0.368f, 0.690f), false }, + + { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT, ImVec2(0.919f, 0.110f), true }, + { SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, ImVec2(0.766f, 0.092f), true }, + { SDL_CONTROLLER_BUTTON_START, ImVec2(0.570f, 0.408f), true }, + { SDL_CONTROLLER_BUTTON_Y, ImVec2(0.752f, 0.328f), true }, + { SDL_CONTROLLER_BUTTON_X, ImVec2(0.689f, 0.412f), true }, + { SDL_CONTROLLER_BUTTON_B, ImVec2(0.816f, 0.412f), true }, + { SDL_CONTROLLER_BUTTON_A, ImVec2(0.752f, 0.497f), true }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_NEGATIVE, ImVec2(0.628f, 0.518f), true }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_NEGATIVE, ImVec2(0.570f, 0.595f), true }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_POSITIVE, ImVec2(0.686f, 0.595f), true }, + { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_POSITIVE, ImVec2(0.628f, 0.682f), true }, + { SDL_CONTROLLER_BUTTON_RIGHTSTICK, ImVec2(0.628f, 0.595f), true }, +}; + +// --------------------------------------------------------------------------------------------------- +// MapperWindow +// --------------------------------------------------------------------------------------------------- + +#define MAPPER_WINDOW_GAME_INPUT_BLOCK_ID 95237930 + +static constexpr uint32_t DEVICE_SCAN_INTERVAL_MS = 500; +static constexpr uint32_t FILE_WATCH_INTERVAL_MS = 1000; + +MapperWindow::~MapperWindow() { + CloseJoystick(); +} + +void MapperWindow::InitElement() { + ClearBindings(mBindings); +} + +// Records the joystick's current digital state as the baseline for edge detection, so a button already +// held when a prompt appears has to be released and pressed again to count. +void MapperWindow::SnapshotDeviceState() { + mPreviousButtons.clear(); + mPreviousHats.clear(); + if (mJoystick == nullptr) { + return; + } + + SDL_JoystickUpdate(); + for (int32_t i = 0; i < SDL_JoystickNumButtons(mJoystick); i++) { + mPreviousButtons.push_back(SDL_JoystickGetButton(mJoystick, i)); + } + for (int32_t i = 0; i < SDL_JoystickNumHats(mJoystick); i++) { + mPreviousHats.push_back(SDL_JoystickGetHat(mJoystick, i)); + } +} + +void MapperWindow::PollDeviceForSession() { + if (mJoystick == nullptr) { + return; + } + + if (SDL_JoystickGetAttached(mJoystick) == SDL_FALSE) { + EndSession(false); + mStatusMessage = "Device disconnected during mapping."; + return; + } + + SDL_JoystickUpdate(); + + const int32_t buttonCount = SDL_JoystickNumButtons(mJoystick); + mPreviousButtons.resize((size_t)std::max(buttonCount, 0), 0); + for (int32_t i = 0; i < buttonCount; i++) { + const uint8_t state = SDL_JoystickGetButton(mJoystick, i); + if (state != 0 && mPreviousButtons[i] == 0) { + mSession.ProcessButtonDown(i); + } + mPreviousButtons[i] = state; + } + + const int32_t hatCount = SDL_JoystickNumHats(mJoystick); + mPreviousHats.resize((size_t)std::max(hatCount, 0), SDL_HAT_CENTERED); + for (int32_t i = 0; i < hatCount; i++) { + const uint8_t state = SDL_JoystickGetHat(mJoystick, i); + if (state != mPreviousHats[i] && state != SDL_HAT_CENTERED) { + mSession.ProcessHatMotion(i, state); + } + mPreviousHats[i] = state; + } + + for (int32_t i = 0; i < SDL_JoystickNumAxes(mJoystick); i++) { + mSession.ProcessAxisMotion(i, SDL_JoystickGetAxis(mJoystick, i), mJoystick); + } +} + +void MapperWindow::CloseJoystick() { + if (mJoystick != nullptr) { + SDL_JoystickClose(mJoystick); + mJoystick = nullptr; + } + mPreviousButtons.clear(); + mPreviousHats.clear(); +} + +void MapperWindow::RefreshDeviceList() { + const SDL_JoystickID previousInstanceId = + mSelectedDevice >= 0 && mSelectedDevice < (int32_t)mDevices.size() ? mDevices[mSelectedDevice].instanceId : -1; + + mDevices.clear(); + + const std::vector userLines = ReadUserMappingLines(); + + for (int32_t i = 0; i < SDL_NumJoysticks(); i++) { + char guidString[33] = ""; + SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guidString, sizeof(guidString)); + + DeviceInfo info = {}; + info.deviceIndex = i; + info.instanceId = SDL_JoystickGetDeviceInstanceID(i); + const char* name = SDL_JoystickNameForIndex(i); + info.name = name != nullptr ? name : guidString; + info.guid = guidString; + info.hasMapping = SDL_IsGameController(i) == SDL_TRUE; + info.hasUserMapping = false; + + const std::string base = StripCrcFromGuid(info.guid); + for (const auto& line : userLines) { + if (!IsMappingLine(line)) { + continue; + } + const size_t comma = line.find(','); + if (comma != std::string::npos && StripCrcFromGuid(line.substr(0, comma)) == base) { + info.hasUserMapping = true; + break; + } + } + + mDevices.push_back(info); + } + + for (int32_t i = 0; i < (int32_t)mDevices.size(); i++) { + if (mDevices[i].instanceId == previousInstanceId) { + mSelectedDevice = i; + return; + } + } + + SelectDevice(mDevices.empty() ? -1 : 0); +} + +void MapperWindow::SelectDevice(int32_t listIndex) { + if (mSession.IsActive()) { + EndSession(false); + } + + CloseJoystick(); + ClearBindings(mBindings); + mDirty = false; + mStatusMessage.clear(); + mSelectedDevice = listIndex; + + if (listIndex < 0 || listIndex >= (int32_t)mDevices.size()) { + return; + } + + mJoystick = SDL_JoystickOpen(mDevices[listIndex].deviceIndex); + if (mJoystick == nullptr) { + mStatusMessage = StringHelper::Sprintf("Could not open device: %s", SDL_GetError()); + return; + } + + LoadBindingsForDevice(); +} + +void MapperWindow::LoadBindingsForDevice() { + ClearBindings(mBindings); + mCustomName.clear(); + if (mJoystick == nullptr) { + return; + } + + char guidString[33] = ""; + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(mJoystick), guidString, sizeof(guidString)); + + const std::string userMapping = FindUserMapping(guidString); + if (!userMapping.empty()) { + ParseMappingString(userMapping, mBindings); + mCustomName = MappingName(userMapping); + return; + } + + const char* joystickName = SDL_JoystickName(mJoystick); + mCustomName = joystickName != nullptr ? joystickName : ""; + + char* existing = SDL_GameControllerMappingForGUID(SDL_JoystickGetGUID(mJoystick)); + if (existing == nullptr) { + return; + } + ParseMappingString(existing, mBindings); + SDL_free(existing); +} + +void MapperWindow::StartSession(const std::vector& order) { + if (mJoystick == nullptr || order.empty()) { + return; + } + + mStatusMessage.clear(); + mSession.SetBindings(mBindings); + mSession.Start(mJoystick, order); + SnapshotDeviceState(); + + Ship::Context::GetRawInstance()->GetControlDeck()->BlockGameInput(MAPPER_WINDOW_GAME_INPUT_BLOCK_ID); + Ship::Context::GetRawInstance()->GetWindow()->GetGui()->BlockGamepadNavigation(); +} + +void MapperWindow::EndSession(bool applyResult) { + if (applyResult) { + mSession.CopyBindingsTo(mBindings); + mDirty = true; + } + mSession.Stop(); + mPreviousButtons.clear(); + mPreviousHats.clear(); + + mGameInputBlockTimer = 20; + Ship::Context::GetRawInstance()->GetWindow()->GetGui()->UnblockGamepadNavigation(); +} + +void MapperWindow::UpdateElement() { + const uint32_t now = SDL_GetTicks(); + + if (now - mLastUserFileCheckTicks >= FILE_WATCH_INTERVAL_MS || mLastUserFileCheckTicks == 0) { + mLastUserFileCheckTicks = now; + + std::error_code error; + const std::filesystem::path path = GetUserMappingsPath(); + if (std::filesystem::exists(path, error)) { + const auto writeTime = std::filesystem::last_write_time(path, error); + const uint64_t stamp = (uint64_t)writeTime.time_since_epoch().count(); + if (!error && stamp != mLastUserFileWriteTime) { + const bool firstLoad = mLastUserFileWriteTime == 0; + mLastUserFileWriteTime = stamp; + LoadUserMappings(); + if (!firstLoad && !mSession.IsActive() && !mDirty) { + LoadBindingsForDevice(); + } + } + } else { + mLastUserFileWriteTime = 0; + } + } + + if (mGameInputBlockTimer != INT32_MAX && !mSession.IsActive()) { + mGameInputBlockTimer--; + if (mGameInputBlockTimer <= 0) { + Ship::Context::GetRawInstance()->GetControlDeck()->UnblockGameInput(MAPPER_WINDOW_GAME_INPUT_BLOCK_ID); + mGameInputBlockTimer = INT32_MAX; + } + } + + if (!IsVisible()) { + if (mSession.IsActive()) { + EndSession(false); + } + if (mJoystick != nullptr) { + CloseJoystick(); + mSelectedDevice = -1; + mDevices.clear(); + } + return; + } + + if (!mSession.IsActive() && (mDevices.empty() || now - mLastDeviceScanTicks >= DEVICE_SCAN_INTERVAL_MS)) { + mLastDeviceScanTicks = now; + RefreshDeviceList(); + } + + if (mSession.IsActive()) { + Ship::Context::GetRawInstance()->GetControlDeck()->BlockGameInput(MAPPER_WINDOW_GAME_INPUT_BLOCK_ID); + Ship::Context::GetRawInstance()->GetWindow()->GetGui()->BlockGamepadNavigation(); + + PollDeviceForSession(); + mSession.CheckPendingAdvance(); + + if (mSession.IsComplete()) { + EndSession(true); + mStatusMessage = "Mapping captured. Check the diagram, then Save Mapping."; + } + } +} + +bool MapperWindow::IsBindingLive(int32_t binding) const { + if (mJoystick == nullptr || binding < 0 || binding >= BINDING_COUNT) { + return false; + } + + const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(binding) : mBindings[binding]; + + switch (bind.bindType) { + case SDL_CONTROLLER_BINDTYPE_BUTTON: + return SDL_JoystickGetButton(mJoystick, bind.value.button) != 0; + case SDL_CONTROLLER_BINDTYPE_AXIS: { + const int32_t value = SDL_JoystickGetAxis(mJoystick, bind.value.axis.axis); + if (IsFullRangeAxis(bind)) { + Sint16 rest = 0; + SDL_JoystickGetAxisInitialState(mJoystick, bind.value.axis.axis, &rest); + return std::abs(value - rest) > SDL_JOYSTICK_AXIS_MAX / 2; + } + // A half-axis counts as active once the reading is most of the way toward axisMax. + const int32_t threshold = bind.value.axis.axisMax / 2; + return bind.value.axis.axisMax < 0 ? value <= threshold : value >= threshold; + } + case SDL_CONTROLLER_BINDTYPE_HAT: + return (SDL_JoystickGetHat(mJoystick, bind.value.hat.hat) & bind.value.hat.hatMask) == + bind.value.hat.hatMask; + default: + return false; + } +} + +// --------------------------------------------------------------------------------------------------- +// Drawing +// --------------------------------------------------------------------------------------------------- + +void MapperWindow::DrawDeviceSelector() { + ImGui::AlignTextToFramePadding(); + ImGui::Text("Device"); + ImGui::SameLine(); + + std::string preview = "No joysticks detected"; + if (mSelectedDevice >= 0 && mSelectedDevice < (int32_t)mDevices.size()) { + preview = mDevices[mSelectedDevice].name; + } + + ImGui::BeginDisabled(mSession.IsActive() || mDevices.empty()); + PushStyleCombobox(THEME_COLOR); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.6f); + if (ImGui::BeginCombo("##mapperDevice", preview.c_str())) { + for (int32_t i = 0; i < (int32_t)mDevices.size(); i++) { + const DeviceInfo& device = mDevices[i]; + const char* status = device.hasUserMapping ? " [user mapping]" : (device.hasMapping ? "" : " [unmapped]"); + if (ImGui::Selectable(StringHelper::Sprintf("%s%s##dev%d", device.name.c_str(), status, i).c_str(), + i == mSelectedDevice)) { + SelectDevice(i); + } + } + ImGui::EndCombo(); + } + PopStyleCombobox(); + ImGui::EndDisabled(); + + if (mSelectedDevice < 0 || mSelectedDevice >= (int32_t)mDevices.size()) { + ImGui::TextDisabled("Connect a gamepad to get started."); + return; + } + + const DeviceInfo& device = mDevices[mSelectedDevice]; + ImGui::TextDisabled("GUID %s", device.guid.c_str()); + if (mJoystick != nullptr) { + ImGui::SameLine(); + ImGui::TextDisabled("| %d buttons, %d axes, %d hats", SDL_JoystickNumButtons(mJoystick), + SDL_JoystickNumAxes(mJoystick), SDL_JoystickNumHats(mJoystick)); + } + + if (!device.hasMapping) { + ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.2f, 1.0f), + "This device has no SDL mapping, so the game cannot see it yet. Map it below."); + } else if (device.hasUserMapping) { + ImGui::TextColored(ImVec4(0.4f, 0.85f, 0.4f, 1.0f), "Using a mapping from %s.", kUserMappingsFileName); + } +} + +void MapperWindow::DrawDiagram() { + auto gui = std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()); + const bool haveArt = gui != nullptr && gui->HasTextureByName(kDiagramTextureName); + + float artAspect = FALLBACK_ART_ASPECT; + if (haveArt) { + const ImVec2 artSize = gui->GetTextureSize(kDiagramTextureName); + if (artSize.x > 0.0f && artSize.y > 0.0f) { + artAspect = artSize.x / artSize.y; + } + } + + std::string values[IM_ARRAYSIZE(kDiagram)]; + int32_t rowsPerGutter[2] = { 0, 0 }; + float widestName = 0.0f; + float widestValue = 0.0f; + for (int32_t i = 0; i < (int32_t)IM_ARRAYSIZE(kDiagram); i++) { + const DiagramEntry& entry = kDiagram[i]; + const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(entry.binding) : mBindings[entry.binding]; + values[i] = bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE ? DescribeBind(bind) : "-"; + widestValue = std::max(widestValue, ImGui::CalcTextSize(values[i].c_str()).x); + widestName = std::max(widestName, ImGui::CalcTextSize(BindingName(entry.binding)).x); + rowsPerGutter[entry.labelOnRight ? 1 : 0]++; + } + const int32_t maxRows = std::max(rowsPerGutter[0], rowsPerGutter[1]); + + const float valueColumnWidth = std::max(widestValue, ImGui::GetFontSize() * 6.0f); + + const float valueGap = ImGui::CalcTextSize(" ").x; + + const float gutterWidth = widestName + valueColumnWidth + valueGap + ImGui::GetFontSize() * 3.0f; + const float width = std::max(ImGui::GetContentRegionAvail().x, gutterWidth * 2.0f + MIN_IMAGE_WIDTH); + const float imageWidth = std::min(width - gutterWidth * 2.0f, width * MAX_IMAGE_SPAN); + const float imageHeight = imageWidth / artAspect; + const float rowHeight = ImGui::GetTextLineHeightWithSpacing() * 1.35f; + const float height = std::max(imageHeight, rowHeight * maxRows); + + const ImVec2 origin = ImGui::GetCursorScreenPos(); + const ImVec2 canvas(width, height); + ImDrawList* drawList = ImGui::GetWindowDrawList(); + + const ImVec2 imageMin(origin.x + (width - imageWidth) * 0.5f, origin.y + (height - imageHeight) * 0.5f); + const ImVec2 imageMax(imageMin.x + imageWidth, imageMin.y + imageHeight); + + const auto toArt = [&](const ImVec2& uv) { + return ImVec2(imageMin.x + uv.x * imageWidth, imageMin.y + uv.y * imageHeight); + }; + + if (haveArt) { + drawList->AddImage(gui->GetTextureByName(kDiagramTextureName), imageMin, imageMax); + } else { + drawList->AddRectFilled(imageMin, imageMax, IM_COL32(40, 44, 52, 255), 12.0f); + drawList->AddRect(imageMin, imageMax, IM_COL32(90, 96, 110, 255), 12.0f, 0, 2.0f); + const char* placeholder = "controller image"; + const ImVec2 textSize = ImGui::CalcTextSize(placeholder); + drawList->AddText( + ImVec2((imageMin.x + imageMax.x - textSize.x) * 0.5f, (imageMin.y + imageMax.y - textSize.y) * 0.5f), + IM_COL32(120, 126, 140, 255), placeholder); + } + + const int32_t currentBinding = mSession.IsActive() ? mSession.CurrentBinding() : -1; + const float pulse = 0.55f + 0.45f * std::sin((float)ImGui::GetTime() * 6.0f); + + int32_t rowUsed[2] = { 0, 0 }; + for (int32_t i = 0; i < (int32_t)IM_ARRAYSIZE(kDiagram); i++) { + const DiagramEntry& entry = kDiagram[i]; + const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(entry.binding) : mBindings[entry.binding]; + const bool bound = bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE; + const bool active = entry.binding == currentBinding; + const bool live = IsBindingLive(entry.binding); + + const bool onRight = entry.labelOnRight; + const float lineHeight = ImGui::GetTextLineHeight(); + const ImVec2 valueSize = ImGui::CalcTextSize(values[i].c_str()); + + const int32_t gutter = onRight ? 1 : 0; + const int32_t row = rowUsed[gutter]++; + const float rowCenterY = origin.y + (row + 0.5f) * (height / rowsPerGutter[gutter]); + + const float run = ImGui::GetFontSize(); + const float elbowX = + onRight ? imageMax.x + ImGui::GetFontSize() * 0.6f : imageMin.x - ImGui::GetFontSize() * 0.6f; + const float valueEdgeX = onRight ? elbowX + run + valueGap : elbowX - run - valueGap; + + const ImVec2 cellMin(onRight ? valueEdgeX : valueEdgeX - valueColumnWidth, + rowCenterY - lineHeight * 0.5f - 2.0f); + const ImVec2 cellMax(cellMin.x + valueColumnWidth, cellMin.y + lineHeight + 4.0f); + + ImGui::SetCursorScreenPos(cellMin); + ImGui::InvisibleButton(StringHelper::Sprintf("##mapperRow%d", i).c_str(), + ImVec2(cellMax.x - cellMin.x, cellMax.y - cellMin.y), + ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); + const bool hovered = ImGui::IsItemHovered(); + if (hovered && !mSession.IsActive() && mJoystick != nullptr) { + Tooltip("Click to map this control. Right-click to clear it."); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + StartSession({ entry.binding }); + } else if (ImGui::IsItemClicked(ImGuiMouseButton_Right) && bound) { + mBindings[entry.binding] = NoBind(); + mDirty = true; + } + } + + ImU32 color; + if (active) { + color = IM_COL32(255, (int32_t)(200.0f * pulse), 60, 255); + } else if (live) { + color = IM_COL32(110, 220, 110, 255); + } else if (bound) { + color = IM_COL32(215, 220, 230, 255); + } else { + color = IM_COL32(130, 135, 145, 255); + } + + if (hovered) { + drawList->AddRectFilled(cellMin, cellMax, IM_COL32(255, 255, 255, 24), 3.0f); + } + + const ImVec2 hotspot = toArt(entry.hotspot); + const float lineStartX = onRight ? cellMin.x - valueGap : cellMax.x + valueGap; + const ImU32 lineColor = active ? color : (bound ? IM_COL32(150, 156, 168, 255) : IM_COL32(90, 94, 104, 255)); + drawList->AddLine(ImVec2(lineStartX, rowCenterY), ImVec2(elbowX, rowCenterY), lineColor, 1.5f); + drawList->AddLine(ImVec2(elbowX, rowCenterY), hotspot, lineColor, 1.5f); + drawList->AddCircleFilled(hotspot, active || live ? 5.0f : 3.5f, color); + + drawList->AddText(ImVec2(onRight ? cellMin.x : cellMax.x - valueSize.x, rowCenterY - valueSize.y * 0.5f), color, + values[i].c_str()); + + const char* name = BindingName(entry.binding); + const ImVec2 nameSize = ImGui::CalcTextSize(name); + drawList->AddText( + ImVec2(onRight ? origin.x + width - 4.0f - nameSize.x : origin.x + 4.0f, rowCenterY - nameSize.y * 0.5f), + NAME_COLOR, name); + } + + ImGui::SetCursorScreenPos(ImVec2(origin.x, origin.y + canvas.y)); + ImGui::Dummy(ImVec2(1.0f, 0.0f)); + + if (!mIncludeExtraButtons) { + return; + } + + ImGui::SeparatorText("Extra buttons"); + for (int32_t i = 0; i < (int32_t)IM_ARRAYSIZE(kExtraBindings); i++) { + const int32_t binding = kExtraBindings[i]; + const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(binding) : mBindings[binding]; + const bool bound = bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE; + const bool active = mSession.IsActive() && mSession.CurrentBinding() == binding; + + ImGui::BeginDisabled(mSession.IsActive() || mJoystick == nullptr); + PushStyleButton(active ? Colors::Orange : THEME_COLOR); + if (ImGui::Button(StringHelper::Sprintf("%s: %s##extra%d", BindingName(binding), + bound ? DescribeBind(bind).c_str() : "-", i) + .c_str())) { + StartSession({ binding }); + } + PopStyleButton(); + ImGui::EndDisabled(); + if (i % 3 != 2 && i != (int32_t)IM_ARRAYSIZE(kExtraBindings) - 1) { + ImGui::SameLine(); + } + } +} + +void MapperWindow::DrawSessionPrompt() { + if (!mSession.IsActive()) { + return; + } + + const int32_t binding = mSession.CurrentBinding(); + const ImGuiStyle& style = ImGui::GetStyle(); + + PushStyleButton(THEME_COLOR); + const float buttonHeight = ImGui::GetFrameHeight(); + PopStyleButton(); + + const float promptHeight = + style.WindowPadding.y * 2.0f + ImGui::GetTextLineHeightWithSpacing() * 2.0f + buttonHeight; + + ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.16f, 0.14f, 0.06f, 1.0f)); + ImGui::BeginChild("##mapperPrompt", ImVec2(0.0f, promptHeight), true, ImGuiWindowFlags_NoScrollbar); + + ImGui::Text("Press or move: %s", binding >= 0 ? BindingName(binding) : "?"); + if (mSession.StepCount() > 1) { + ImGui::SameLine(); + ImGui::TextDisabled("(%d / %d)", mSession.CurrentStep() + 1, mSession.StepCount()); + } + ImGui::TextDisabled("Sticks and triggers: push all the way, then let go. Space skips, Escape cancels."); + + PushStyleButton(THEME_COLOR); + const bool skip = ImGui::Button("Skip") || ImGui::IsKeyPressed(ImGuiKey_Space, false); + ImGui::SameLine(); + ImGui::BeginDisabled(mSession.CurrentStep() == 0); + const bool back = ImGui::Button("Back"); + ImGui::EndDisabled(); + ImGui::SameLine(); + const bool cancel = ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape, false); + PopStyleButton(); + + ImGui::EndChild(); + ImGui::PopStyleColor(); + + if (cancel) { + EndSession(false); + mStatusMessage = "Mapping cancelled; nothing was changed."; + } else if (back) { + mSession.GoBack(); + } else if (skip) { + mSession.Advance(); + if (mSession.IsComplete()) { + EndSession(true); + mStatusMessage = "Mapping captured. Check the diagram, then Save Mapping."; + } + } +} + +void MapperWindow::DrawActionButtons() { + const bool haveDevice = mJoystick != nullptr; + const bool busy = mSession.IsActive(); + + char nameBuffer[128] = ""; + SDL_strlcpy(nameBuffer, mCustomName.c_str(), sizeof(nameBuffer)); + ImGui::BeginDisabled(busy || !haveDevice); + PushStyleInput(THEME_COLOR); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.45f); + if (ImGui::InputText("Controller Name", nameBuffer, sizeof(nameBuffer))) { + mCustomName = nameBuffer; + mDirty = true; + } + PopStyleInput(); + ImGui::EndDisabled(); + Tooltip("Name saved into usergamepadmappings.txt for this device. Commas are replaced with spaces."); + + ImGui::BeginDisabled(busy || !haveDevice); + PushStyleButton(THEME_COLOR); + if (ImGui::Button("Map All")) { + std::vector order(std::begin(kCoreBindingOrder), std::end(kCoreBindingOrder)); + if (mIncludeExtraButtons) { + order.insert(order.end(), std::begin(kExtraBindings), std::end(kExtraBindings)); + } + StartSession(order); + } + PopStyleButton(); + ImGui::EndDisabled(); + Tooltip(haveDevice ? "Walks every control on the pad, asking for one input at a time." : "Select a device first."); + + ImGui::SameLine(); + ImGui::BeginDisabled(busy || !haveDevice || !mDirty); + PushStyleButton(THEME_COLOR); + if (ImGui::Button("Save Mapping")) { + char guidString[33] = ""; + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(mJoystick), guidString, sizeof(guidString)); + + bool ok; + if (!HasAnyBinding(mBindings)) { + ok = DeleteUserMapping(guidString); + mStatusMessage = + ok ? StringHelper::Sprintf("Removed from %s. SDL keeps the device registered until you restart.", + kUserMappingsFileName) + : "Nothing to remove; this device has no saved mapping."; + ok = true; + } else { + const std::string mapping = GenerateMappingString(mJoystick, mBindings, mCustomName); + ok = !mapping.empty() && SaveUserMapping(mapping); + mStatusMessage = ok ? StringHelper::Sprintf("Saved to %s.", kUserMappingsFileName) + : "Failed to save the mapping; see the log for details."; + } + + if (ok) { + mDirty = false; + std::error_code error; + const auto writeTime = std::filesystem::last_write_time(GetUserMappingsPath(), error); + if (!error) { + mLastUserFileWriteTime = (uint64_t)writeTime.time_since_epoch().count(); + } + RefreshDeviceList(); + } + } + PopStyleButton(); + ImGui::EndDisabled(); + + ImGui::SameLine(); + ImGui::BeginDisabled(busy || !haveDevice); + PushStyleButton(THEME_COLOR); + if (ImGui::Button("Revert")) { + LoadBindingsForDevice(); + mDirty = false; + mStatusMessage = "Reverted to the mapping SDL is currently using."; + } + PopStyleButton(); + ImGui::EndDisabled(); + Tooltip("Discards unsaved changes and reloads the mapping SDL is using for this device."); + + ImGui::SameLine(); + ImGui::BeginDisabled(busy || !haveDevice); + PushStyleButton(THEME_COLOR); + if (ImGui::Button("Clear All Bindings")) { + ClearBindings(mBindings); + mDirty = true; + } + PopStyleButton(); + ImGui::EndDisabled(); + + const bool haveUserMapping = + mSelectedDevice >= 0 && mSelectedDevice < (int32_t)mDevices.size() && mDevices[mSelectedDevice].hasUserMapping; + + ImGui::BeginDisabled(busy || !haveUserMapping); + PushStyleButton(Colors::DarkRed); + if (ImGui::Button("Delete Saved Mapping")) { + if (DeleteUserMapping(mDevices[mSelectedDevice].guid)) { + mStatusMessage = StringHelper::Sprintf("Removed from %s. Restart to fall back to gamecontrollerdb.txt.", + kUserMappingsFileName); + RefreshDeviceList(); + } else { + mStatusMessage = "No saved mapping to remove."; + } + } + PopStyleButton(); + ImGui::EndDisabled(); + Tooltip("SDL keeps the mapping in memory until the game restarts, so the device stays usable this session."); + + ImGui::SameLine(); + ImGui::BeginDisabled(busy); + PushStyleButton(THEME_COLOR); + if (ImGui::Button("Reload From File")) { + if (LoadUserMappings()) { + LoadBindingsForDevice(); + mDirty = false; + RefreshDeviceList(); + mStatusMessage = StringHelper::Sprintf("Reloaded %s.", kUserMappingsFileName); + } else { + mStatusMessage = StringHelper::Sprintf("No %s to load.", kUserMappingsFileName); + } + } + PopStyleButton(); + ImGui::EndDisabled(); + + ImGui::SameLine(); + ImGui::BeginDisabled(busy); + Checkbox("Include extra buttons", &mIncludeExtraButtons, + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Adds Guide, Misc and paddle/touchpad buttons - which most pads do not have - to the " + "diagram and the Map All walk.")); + ImGui::EndDisabled(); +} + +void MapperWindow::DrawMappingStringPreview() { + if (mJoystick == nullptr || !ImGui::CollapsingHeader("Mapping string")) { + return; + } + + const std::string mapping = GenerateMappingString(mJoystick, mBindings, mCustomName); + ImGui::TextWrapped("%s", mapping.c_str()); + PushStyleButton(THEME_COLOR); + if (ImGui::Button("Copy to Clipboard")) { + ImGui::SetClipboardText(mapping.c_str()); + mStatusMessage = "Mapping string copied to the clipboard."; + } + PopStyleButton(); +} + +void MapperWindow::DrawElement() { + static bool sDiagramTextureRequested = false; + if (!sDiagramTextureRequested) { + sDiagramTextureRequested = true; + auto gui = std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()); + auto archives = Ship::Context::GetRawInstance()->GetResourceManager()->GetArchiveManager(); + if (gui != nullptr && archives != nullptr && archives->HasFile(kDiagramTexturePath)) { + gui->LoadTextureFromRawImage(kDiagramTextureName, kDiagramTexturePath); + } + } + + ImGui::PushFont(GameEngine::Instance->fontMonoLarger); + + DrawDeviceSelector(); + Separator(); + DrawDiagram(); + DrawSessionPrompt(); + Separator(); + DrawActionButtons(); + + if (mDirty) { + ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.2f, 1.0f), "Unsaved changes."); + } + if (!mStatusMessage.empty()) { + ImGui::TextWrapped("%s", mStatusMessage.c_str()); + } + + DrawMappingStringPreview(); + + ImGui::PopFont(); +} + +// --------------------------------------------------------------------------------------------------- +// Menu registration +// --------------------------------------------------------------------------------------------------- + +static void RegisterMapperWidgets() { + WidgetPath path = { "Settings", "Controls", SECTION_COLUMN_2 }; + LighthouseGui::mLighthouseMenu->AddWidget(path, "Gamepad Mapper", WIDGET_SEPARATOR_TEXT); + LighthouseGui::mLighthouseMenu->AddWidget(path, "Open Gamepad Mapper", WIDGET_WINDOW_BUTTON) + .CVar(CVAR_WINDOW("GamepadMapper")) + .RaceDisable(false) + .WindowName("Gamepad Mapper") + .HideInSearch(true) + .Options(WindowButtonOptions() + .Tooltip("Build an SDL mapping for a gamepad the game does not recognize, or fix one that is " + "mapped wrong. Saves to usergamepadmappings.txt.") + .EmbedWindow(false)); +} + +static RegisterMenuInitFunc menuInitFunc(RegisterMapperWidgets); + +} // namespace Mapper diff --git a/src/port/Controller/Mapper.h b/src/port/Controller/Mapper.h new file mode 100644 index 000000000..0d0d41bb3 --- /dev/null +++ b/src/port/Controller/Mapper.h @@ -0,0 +1,182 @@ +#pragma once + +// Built-in SDL gamepad mapper. +// +// Produces `gamecontrollerdb.txt`-style mapping strings for a raw SDL joystick and persists them to +// `usergamepadmappings.txt` in the app directory. That file is loaded at boot (and whenever it changes on +// disk) on top of the bundled `gamecontrollerdb.txt`, so a user-authored mapping always wins. +// +// The binding state machine (axis commit/return distances, binding override rules, mapping string layout) +// is adapted from https://github.com/General-Arcade/sdl2-gamepad-tool (MIT), which in turn follows SDL's +// own `controllermap` test program. + +#include +#include +#include + +#include +#include +#include + +namespace Mapper { +enum AxisBinding { + AXIS_LEFTX_NEGATIVE, + AXIS_LEFTX_POSITIVE, + AXIS_LEFTY_NEGATIVE, + AXIS_LEFTY_POSITIVE, + AXIS_RIGHTX_NEGATIVE, + AXIS_RIGHTX_POSITIVE, + AXIS_RIGHTY_NEGATIVE, + AXIS_RIGHTY_POSITIVE, + AXIS_TRIGGERLEFT, + AXIS_TRIGGERRIGHT, + AXIS_BINDING_MAX, +}; + +constexpr int32_t BINDING_COUNT = SDL_CONTROLLER_BUTTON_MAX + AXIS_BINDING_MAX; + +struct ExtendedBind { + SDL_GameControllerBindType bindType; + union { + int32_t button; + + struct { + int32_t axis; + int32_t axisMin; + int32_t axisMax; + } axis; + + struct { + int32_t hat; + int32_t hatMask; + } hat; + } value; + bool committed; +}; + +struct AxisState { + bool moving; + int32_t lastValue; + int32_t startingValue; + int32_t farthestValue; +}; + +class MappingSession { +public: + static constexpr int32_t AXIS_COMMIT_DISTANCE = 16000; + static constexpr int32_t AXIS_RETURN_DISTANCE = 10000; + static constexpr uint32_t PENDING_ADVANCE_DELAY_MS = 100; + + MappingSession(); + + void Start(SDL_Joystick* joystick, const std::vector& order); + void Stop(); + + bool IsActive() const; + bool IsComplete() const; + + int32_t CurrentStep() const; + int32_t StepCount() const; + int32_t CurrentBinding() const; + + void GoToStep(int32_t step); + void Advance(); + void GoBack(); + + void ProcessButtonDown(int32_t button); + void ProcessHatMotion(int32_t hat, int32_t value); + void ProcessAxisMotion(int32_t axis, int32_t value, SDL_Joystick* joystick); + + void CheckPendingAdvance(); + + const ExtendedBind& GetBinding(int32_t index) const; + void SetBindings(const ExtendedBind (&bindings)[BINDING_COUNT]); + void CopyBindingsTo(ExtendedBind (&out)[BINDING_COUNT]) const; + +private: + void ConfigureBinding(const ExtendedBind& binding); + bool BindingContainsBinding(const ExtendedBind& a, const ExtendedBind& b) const; + + ExtendedBind mBindings[BINDING_COUNT]; + std::vector mOrder; + std::vector mAxisState; + int32_t mCurrentStep; + uint32_t mPendingAdvanceTime; + bool mActive; + bool mComplete; +}; + +void ClearBindings(ExtendedBind (&bindings)[BINDING_COUNT]); +bool HasAnyBinding(const ExtendedBind (&bindings)[BINDING_COUNT]); +std::string GenerateMappingString(SDL_Joystick* joystick, const ExtendedBind (&bindings)[BINDING_COUNT], + const std::string& nameOverride = ""); +int32_t ParseMappingString(const std::string& mapping, ExtendedBind (&bindings)[BINDING_COUNT]); +std::string DescribeBind(const ExtendedBind& bind); +const char* BindingName(int32_t binding); +std::string GetUserMappingsPath(); +std::string FindUserMapping(const std::string& guid); +std::string MappingName(const std::string& mapping); +bool LoadUserMappings(); +bool SaveUserMapping(const std::string& mapping); +bool DeleteUserMapping(const std::string& guid); + +class MapperWindow final : public Ship::GuiWindow { +public: + using GuiWindow::GuiWindow; + ~MapperWindow(); + +protected: + void InitElement() override; + void UpdateElement() override; + void DrawElement() override; + +private: + struct DeviceInfo { + int32_t deviceIndex; + SDL_JoystickID instanceId; + std::string name; + std::string guid; + bool hasMapping; + bool hasUserMapping; + }; + + void RefreshDeviceList(); + void SelectDevice(int32_t listIndex); + void CloseJoystick(); + void LoadBindingsForDevice(); + + void StartSession(const std::vector& order); + void EndSession(bool applyResult); + + void PollDeviceForSession(); + void SnapshotDeviceState(); + + void DrawDeviceSelector(); + void DrawDiagram(); + void DrawSessionPrompt(); + void DrawActionButtons(); + void DrawMappingStringPreview(); + + bool IsBindingLive(int32_t binding) const; + + std::vector mDevices; + int32_t mSelectedDevice = -1; + SDL_Joystick* mJoystick = nullptr; + + ExtendedBind mBindings[BINDING_COUNT] = {}; + MappingSession mSession; + bool mDirty = false; + bool mIncludeExtraButtons = false; + std::string mStatusMessage; + std::string mCustomName; + + std::vector mPreviousButtons; + std::vector mPreviousHats; + + int32_t mGameInputBlockTimer = INT32_MAX; + uint32_t mLastDeviceScanTicks = 0; + uint64_t mLastUserFileWriteTime = 0; + uint32_t mLastUserFileCheckTicks = 0; +}; + +} // namespace Mapper diff --git a/src/port/Controller/ModernCamera.cpp b/src/port/Controller/ModernCamera.cpp index e350082c5..4a097d403 100644 --- a/src/port/Controller/ModernCamera.cpp +++ b/src/port/Controller/ModernCamera.cpp @@ -1,16 +1,21 @@ // Modern control scheme camera -// -// The right stick orbits the camera in yaw around the player (no pitch). It runs -// on the shared orbit core; this file is just the modern-scheme policy. + +#include #include #include "port/UI/cvar_prefixes.h" #include "ControlSchemes.h" #include "ModernCamera.h" -#include "port/Enhancements/Camera/OrbitCameraCore.h" +#include "port/Enhancements/Camera/FreeLookCamera.h" extern "C" { +// Math helpers +void func_80256E24(float dst[3], float pitch, float yaw, float x, float y, float z); +void ml_vec3f_add(float dst[3], float a[3], float b[3]); +void ml_vec3f_clear(float dst[3]); +float mlNormalizeAngle(float deg); + extern unsigned char D_8037C061; // current zoom level extern int D_8037C07C; // level-3 distance x; 0 means level 3 is unavailable @@ -24,33 +29,66 @@ int balookat_getState(void); // nonzero while the look-around camera is activ int player_movementGroup(void); // enum bsgroup_e int ncDynamicCamera_getState(void); +void ncDynamicCamera_setState(int state); +void ncDynamicCamera_setRotation(float src[3]); +int func_8029147C(void); // current ba camera mode +void func_80291488(int mode); // set the ba camera mode +void func_802914CC(int state); // force a dynamic camera state (mode 1) int bainput_should_rotate_camera_left(void); int bainput_should_rotate_camera_right(void); int bainput_should_look_first_person_camera(void); void controller_getRightStick(int controller_index, float dst[2]); + +// Vanilla follow-camera machinery +extern float D_8037DB70; // dynamicCamB.c: orbit yaw, degrees +extern float D_8037D9C8[3]; // dynamicCamera.c: rotation spring velocity + +void func_802C0150(int mode); // select the focus target +void func_802C0370(void); // record the pre-move position (anti-flip guard) +void func_802C0394(float target[3]); // record the ideal target (anti-flip guard) +void func_802C03BC(void); // undo a collision resolve that crossed over +void func_802C0490(float dst[3]); // focus/orbit center +void func_802C04B0(void); // re-derive D_8037DB70 from the live camera + +float func_802BD51C(void); // target camera height +float func_802BD8D4(void); // target orbit distance (zoom level) +void func_802BE190(float target[3]); // position spring toward target +void func_802BE230(float gain, float damp); // position spring tuning +int func_802BE60C(void); // swept camera collision + slide +int func_802BC84C(int mode); // occluded-too-long recovery +void func_802BE6FC(float rotOut[3], float focus[3]); // look-at from the live position } -#include "enums.h" // BS_CROUCH +#include "enums.h" // BS_7_CROUCH #include "port/ShipUtils.h" namespace { bool ModernSchemeActive() { - return CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_MODERN; + return CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_MODERN && + !port_freeLook_isEnabled(); } +constexpr int kClimbCamState = 0x10; +constexpr int kSwivelCamMode = 8; +constexpr int kFollowCamMode = 2; constexpr float kYawDeadzone = 0.2f; constexpr float kYawEnter = 0.3f; constexpr float kYawSpeed = 160.0f; constexpr float kZoomOn = 0.49f; constexpr float kZoomOff = 0.21f; -constexpr float kPosSmoothRate = 40.0f; +constexpr float kPosSpringGain = 20.0f; +constexpr float kPosSpringDamp = 80.0f; +constexpr float kHeightRate = 3.0f; +constexpr float kAimHeightRate = 8.0f; -// Flat (pitch-locked) orbit on the shared core. -OrbitCamera sModern = { /*stateId*/ MODERN_ORBIT_CAM_STATE, /*allowPitch*/ 0, - /*minPitch*/ 0.0f, /*maxPitch*/ 0.0f, /*smoothRate*/ kPosSmoothRate }; +bool sActive = false; +bool sHeightValid = false; +bool sAimValid = false; +float sHeight = 0.0f; +float sAimY = 0.0f; float clampf(float v, float lo, float hi) { return v < lo ? lo : (v > hi ? hi : v); @@ -81,38 +119,85 @@ bool ManualCameraControl() { bainput_should_look_first_person_camera(); } +bool Climbing() { + return player_movementGroup() == BSGROUP_5_CLIMB; +} + +// Give the mode back +void ReleaseSwivelMode() { + if (func_8029147C() != kSwivelCamMode) { + return; + } + if (Climbing()) { + func_802914CC(kClimbCamState); + } else { + func_80291488(kFollowCamMode); + } +} + +// Take the camera over. Everything the vanilla follow camera would set up on init is +// set up here, except that the position spring velocity is deliberately left alone. +void EnterOrbit() { + func_802C0150(2); + func_802BE230(kPosSpringGain, kPosSpringDamp); + func_802C04B0(); + + // We drive the rotation directly, so nothing services the rotation spring while we + // own the camera. Park its velocity so it cannot kick the aim when camB resumes. + ml_vec3f_clear(D_8037D9C8); + + sHeightValid = false; + sAimValid = false; + sActive = true; + ncDynamicCamera_setState(MODERN_ORBIT_CAM_STATE); +} + +void ExitOrbit() { + sActive = false; + if (ncDynamicCamera_getState() == MODERN_ORBIT_CAM_STATE) { + ncDynamicCamera_setState(0xB); + } + ReleaseSwivelMode(); +} + } // namespace extern "C" int port_modernCamera_handleYaw(void) { - bool schemeOk = ModernSchemeActive() && bs_getState() != BS_CROUCH && !IsDemoMode(); + bool schemeOk = ModernSchemeActive() && bs_getState() != BS_7_CROUCH && !IsDemoMode(); if (!schemeOk) { - if (sModern.active) { - OrbitCamera_Exit(&sModern); + if (sActive) { + ExitOrbit(); } return 0; } int state = ncDynamicCamera_getState(); - if (sModern.active) { + if (sActive) { // A scripted/special camera took the state out from under us; drop the // orbit and let that camera run. if (state != MODERN_ORBIT_CAM_STATE) { - sModern.active = 0; + sActive = false; return 0; } if (ManualCameraControl()) { - OrbitCamera_Exit(&sModern); + ExitOrbit(); return 0; } + if (!Climbing()) { + ReleaseSwivelMode(); + } return 1; } float x; float y; ReadStickNorm(x, y); - if (x > kYawEnter || x < -kYawEnter) { - OrbitCamera_Enter(&sModern); + if (std::fabs(x) > kYawEnter) { + EnterOrbit(); + if (state == kClimbCamState) { + func_80291488(kSwivelCamMode); + } return 1; } return 0; @@ -123,33 +208,77 @@ extern "C" void port_modernCamera_update(void) { // Drive yaw from the stick. Freeze it during look-around so it doesn't drift // while the first-person view overrides the camera. - float yawDelta = 0.0f; - if (!sModern.justEntered && !balookat_getState()) { + if (!balookat_getState()) { float x; float y; ReadStickNorm(x, y); - yawDelta = YawInput(x) * kYawSpeed * dt * port_cameraInvertXSign(); + D_8037DB70 = mlNormalizeAngle(D_8037DB70 + YawInput(x) * kYawSpeed * dt * port_cameraInvertXSign()); + } + + // From here down this is ncDynamicCamB_update with our own yaw and height filter. + float focus[3]; + float offset[3]; + float target[3]; + + func_802C0370(); + func_802C0490(focus); + func_80256E24(offset, 0.0f, D_8037DB70, 0.0f, 0.0f, func_802BD8D4()); + ml_vec3f_add(target, focus, offset); + + float wantHeight = func_802BD51C(); + if (!sHeightValid) { + sHeight = wantHeight; + sHeightValid = true; + } else { + sHeight += (wantHeight - sHeight) * clampf(kHeightRate * dt, 0.0f, 1.0f); + } + target[1] = sHeight; + + func_802C0394(target); + func_802BE190(target); + + if (func_802BE60C()) { + // Occluded too long: func_802BC84C relocates the camera outright. Otherwise + // discard a resolve that pushed the camera back the way it came. + if (!func_802BC84C(1)) { + func_802C03BC(); + } + func_802C04B0(); // the camera slid along geometry; carry the orbit yaw with it + } + + // Aim straight at the focus from wherever the spring left the camera. The position + // is already smooth, so the look-at inherits that smoothness exactly and the player + // stays centered. + func_802C0490(focus); + if (!sAimValid) { + sAimY = focus[1]; + sAimValid = true; + } else { + sAimY += (focus[1] - sAimY) * clampf(kAimHeightRate * dt, 0.0f, 1.0f); } + focus[1] = sAimY; - OrbitCamera_Update(&sModern, yawDelta, 0.0f); + float rot[3]; + func_802BE6FC(rot, focus); + ncDynamicCamera_setRotation(rot); } extern "C" int port_camera_suppressVanillaZoom(void) { - if (IsDemoMode()) { + if (IsDemoMode() || port_freeLook_isEnabled()) { return 0; } int scheme = CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO); if (scheme == CONTROL_SCHEME_MODERN) { return 1; } - if (scheme == CONTROL_SCHEME_POCKET && bs_getState() == BS_CROUCH) { + if (scheme == CONTROL_SCHEME_POCKET && bs_getState() == BS_7_CROUCH) { return 1; } return 0; } extern "C" void port_modernCamera_handleZoom(void) { - if (!ModernSchemeActive() || bs_getState() == BS_CROUCH || IsDemoMode()) { + if (!ModernSchemeActive() || bs_getState() == BS_7_CROUCH || IsDemoMode()) { return; } diff --git a/src/port/DevTools/DevSequences.cpp b/src/port/DevTools/DevSequences.cpp index 26758347c..fc9d07cd0 100644 --- a/src/port/DevTools/DevSequences.cpp +++ b/src/port/DevTools/DevSequences.cpp @@ -14,6 +14,7 @@ extern "C" { void gcparade_beginFFParade(void); void gcparade_beginFinalParade(void); void func_8034BA7C(enum map_e map_id, int exit_id); // warp (B&K demo uses MAP_1, exit 93) +void transitionToMap(enum map_e map, int exit, int transition); void func_8034B968(void); // start the attract demo selected by D_80386110 (sets transition + D_80386114) extern int D_80386110; // attract-demo cycle index void func_8025A55C(int, int, int); // fade the active music track @@ -72,6 +73,9 @@ void RegisterDevSequences_Init() { func_8034BA7C(MAP_1_SM_SPIRAL_MOUNTAIN, 93); sPending = SEQ_MODE9_DIALOG; break; + case SEQ_ENDING_ALL_100: + transitionToMap(MAP_95_CS_END_ALL_100, 0, 1); + break; default: D_80386110 = seq - SEQ_ATTRACT_BASE; func_8034B968(); diff --git a/src/port/DevTools/DevSequences.h b/src/port/DevTools/DevSequences.h index fb850057d..1ee871283 100644 --- a/src/port/DevTools/DevSequences.h +++ b/src/port/DevTools/DevSequences.h @@ -9,6 +9,7 @@ enum DevSequenceId { SEQ_PARADE_FINAL, SEQ_MODE9_BK, SEQ_MODE9_DIALOG, + SEQ_ENDING_ALL_100, SEQ_ATTRACT_BASE, }; diff --git a/src/port/DevTools/FlagTracer.cpp b/src/port/DevTools/FlagTracer.cpp new file mode 100644 index 000000000..81dc27564 --- /dev/null +++ b/src/port/DevTools/FlagTracer.cpp @@ -0,0 +1,243 @@ +// Flag Tracer +// +// Logs every game-flag write with its enum name, optionally with the call stack +// that set it. A flag index alone is a bare number shared by unrelated actors. + +#include +#include +#include + +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/ShipInit.hpp" +#include "port/UI/cvar_prefixes.h" + +#include "FlagNames.generated.h" + +#include +#include +#include + +#if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#pragma comment(lib, "dbghelp.lib") +#define LH_FLAGTRACE_STACKS_WIN 1 +#elif defined(__linux__) || defined(__APPLE__) +#include +#include +#include +#include +#define LH_FLAGTRACE_STACKS_POSIX 1 +#endif + +extern "C" { +#include "functions.h" +} + +#define CVAR_FLAG_TRACE CVAR_DEVELOPER_TOOLS("FlagTrace") +#define CVAR_FLAG_TRACE_STACKS CVAR_DEVELOPER_TOOLS("FlagTraceStacks") +#define CVAR_FLAG_TRACE_SPACE CVAR_DEVELOPER_TOOLS("FlagTraceSpace") + +namespace { + +constexpr int32_t kSpaceAll = 0; + +const char* SpaceName(int32_t flagSpace) { + switch (flagSpace) { + case ANCHOR_FLAGSPACE_FILE_PROGRESS: + return "File Progress"; + case ANCHOR_FLAGSPACE_VOLATILE: + return "Volatile"; + case ANCHOR_FLAGSPACE_LEVEL_SPECIFIC: + return "Level"; + case ANCHOR_FLAGSPACE_MAP_SPECIFIC: + return "Map"; + case ANCHOR_FLAGSPACE_RANDO_INF: + return "Rando"; + default: + return "Unknown"; + } +} + +const char* LookupIn(const FlagName* table, int count, int index) { + for (int i = 0; i < count; i++) { + if (table[i].index == index) { + return table[i].name; + } + } + return nullptr; +} + +template const char* LookupIn(const FlagName (&table)[N], int index) { + return LookupIn(table, N, index); +} + +// The enum name behind a flag index, or "" when the decomp hasn't named it. +std::string FlagLabel(int32_t flagSpace, int32_t index) { + const char* name = nullptr; + switch (flagSpace) { + case ANCHOR_FLAGSPACE_FILE_PROGRESS: + name = LookupIn(kFileProgressNames, index); + break; + case ANCHOR_FLAGSPACE_VOLATILE: + name = LookupIn(kVolatileNames, index); + break; + case ANCHOR_FLAGSPACE_LEVEL_SPECIFIC: + name = LookupIn(kLevelNames, index); + break; + case ANCHOR_FLAGSPACE_MAP_SPECIFIC: { + const int level = (int)map_getLevel(gsworld_getMap()); + std::string joined; + for (const auto& group : kMapFlagGroups) { + if (group.level != level) { + continue; + } + if (const char* candidate = LookupIn(group.names, group.count, index)) { + if (!joined.empty()) { + joined += " | "; + } + joined += candidate; + } + } + return joined; + } + default: + break; + } + return name != nullptr ? name : ""; +} + +// Symbolized stack of whatever led here. +std::string CaptureCallerStack(int maxFrames) { + auto isPlumbing = [](const char* name) { + static const char* kPlumbing[] = { "FlagTrace", "EventSystem", "CallEvent", "Flag_set", "Flags_set", + "Flag_setEx", "Flags_setEx", "Flag_setN", "Flags_setN", "Flag_getAndSet", + "Flags_getSet", "invoke", "std::", "lambda" }; + for (const char* p : kPlumbing) { + if (std::strstr(name, p) != nullptr) { + return true; + } + } + return false; + }; + +#if defined(LH_FLAGTRACE_STACKS_WIN) + static std::once_flag symOnce; + static std::mutex symMutex; + HANDLE proc = GetCurrentProcess(); + std::call_once(symOnce, [proc] { + SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + SymInitialize(proc, nullptr, TRUE); + }); + + void* frames[48] = {}; + const USHORT captured = CaptureStackBackTrace(1, 48, frames, nullptr); + + // dbghelp is not thread safe and its handles are process-wide. + std::lock_guard lock(symMutex); + + alignas(SYMBOL_INFO) char symBuf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME] = {}; + auto* sym = reinterpret_cast(symBuf); + sym->SizeOfStruct = sizeof(SYMBOL_INFO); + sym->MaxNameLen = MAX_SYM_NAME; + + std::string out; + int shown = 0; + for (USHORT i = 0; i < captured && shown < maxFrames; i++) { + DWORD64 disp = 0; + if (!SymFromAddr(proc, (DWORD64)frames[i], &disp, sym)) { + continue; + } + if (out.empty() && isPlumbing(sym->Name)) { + continue; + } + IMAGEHLP_LINE64 line = {}; + line.SizeOfStruct = sizeof(line); + DWORD lineDisp = 0; + if (SymGetLineFromAddr64(proc, (DWORD64)frames[i], &lineDisp, &line)) { + const char* file = std::strrchr(line.FileName, '\\'); + file = file ? file + 1 : line.FileName; + out += fmt::format("\n {} ({}:{})", sym->Name, file, line.LineNumber); + } else { + out += fmt::format("\n {}", sym->Name); + } + shown++; + } + return out; + +#elif defined(LH_FLAGTRACE_STACKS_POSIX) + void* frames[48] = {}; + const int captured = backtrace(frames, 48); + + std::string out; + int shown = 0; + for (int i = 1; i < captured && shown < maxFrames; i++) { + Dl_info info = {}; + if (dladdr(frames[i], &info) == 0 || info.dli_sname == nullptr) { + out += fmt::format("\n {}", frames[i]); + shown++; + continue; + } + + int status = 0; + char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); + const char* name = (status == 0 && demangled != nullptr) ? demangled : info.dli_sname; + const bool skip = out.empty() && isPlumbing(name); + if (!skip) { + out += fmt::format("\n {}", name); + shown++; + } + std::free(demangled); + } + return out; + +#else + (void)maxFrames; + (void)isPlumbing; + return "\n (call stacks are unavailable on this platform)"; +#endif +} + +} // namespace + +void RegisterFlagTracer_Init() { + const bool enabled = CVarGetInteger(CVAR_FLAG_TRACE, 0) != 0; + + COND_HOOK(OnGameFlagSet, EVENT_PRIORITY_NORMAL, enabled, [](IEvent* event) { + auto* ev = reinterpret_cast(event); + + const int32_t spaceFilter = CVarGetInteger(CVAR_FLAG_TRACE_SPACE, kSpaceAll); + if (spaceFilter != kSpaceAll && ev->flagSpace != (spaceFilter - 1)) { + return; + } + + std::string where; + if (ev->length > 1) { + where = fmt::format("0x{:X}-0x{:X}", ev->index, ev->index + ev->length - 1); + } else { + const std::string label = FlagLabel(ev->flagSpace, ev->index); + where = label.empty() ? fmt::format("0x{:X}", ev->index) : fmt::format("0x{:X} {}", ev->index, label); + } + + std::string stack; + if (CVarGetInteger(CVAR_FLAG_TRACE_STACKS, 0)) { + stack = fmt::format("\n set by:{}", CaptureCallerStack(6)); + } + + SPDLOG_INFO("[Flag] {:<13} {} -> {}{}", SpaceName(ev->flagSpace), where, ev->value ? "ON" : "off", stack); + }); + + COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, enabled, [](IEvent* event) { + auto* ev = reinterpret_cast(event); + SPDLOG_INFO("[Flag] ===== map 0x{:X} -> 0x{:X} (level 0x{:X}, exit {}) =====", (int)ev->prevMap, + (int)ev->nextMap, (int)map_getLevel((enum map_e)ev->nextMap), ev->exit); + }); +} + +static RegisterShipInitFunc initFlagTracer(RegisterFlagTracer_Init, { CVAR_FLAG_TRACE }); diff --git a/src/port/DevTools/OcclusionDebug.cpp b/src/port/DevTools/OcclusionDebug.cpp index 0c3b72519..a21a8f8ff 100644 --- a/src/port/DevTools/OcclusionDebug.cpp +++ b/src/port/DevTools/OcclusionDebug.cpp @@ -16,9 +16,7 @@ #include "port/ShipInit.hpp" #include "port/Enhancements/Events/Hooks/Events.h" -extern "C" { #include "functions.h" // gsworld_getMap, mapModel_getModelBin -} // mapModel_getModelBin returns BKModelBin*; the debugger only compares it as an opaque // pointer, so reinterpret to const void* at the call sites. @@ -43,8 +41,7 @@ const char* CmdTypeName(int type) { } } -// Each command is keyed by (model part, byte offset within the model bin). The offset is -// fixed per asset, so it never shifts when force-drawing reveals more geometry. +// Each command is keyed by (model part, byte offset within the model's geo command list). struct Key { int part; int offset; @@ -157,7 +154,7 @@ void OcclusionDebugWindow::DrawElement() { } ImGui::TextWrapped( "Flip 'Force draw all' on for a moment to walk every cull command and populate the list (the " - "screen will look broken — that is expected), then turn it off and tick 'Force Draw' on " + "screen will look broken - that is expected), then turn it off and tick 'Force Draw' on " "individual rows to find the chunk(s) that reveal the target scenery. Offsets are stable, so the " "list never shifts. Dump the chosen set to the log when done."); diff --git a/src/port/DevTools/ThreadWatchdog.cpp b/src/port/DevTools/ThreadWatchdog.cpp new file mode 100644 index 000000000..6a0bf17be --- /dev/null +++ b/src/port/DevTools/ThreadWatchdog.cpp @@ -0,0 +1,580 @@ +#include "ThreadWatchdog.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "port/OS/OS.h" + +#if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#pragma comment(lib, "dbghelp.lib") +#define LH_WATCHDOG_STACKS 1 +#endif + +extern "C" { +#include "libultraship/libultra/types.h" +#include "libultraship/libultra/message.h" +u32 osDpGetStatus(void); +void* osViGetCurrentFramebuffer(void); +void* osViGetNextFramebuffer(void); +OSMesgQueue* thread5_getTaskQueue(void); +OSMesgQueue* thread5_getSyncQueue(void); +OSMesgQueue* pfsManager_getFrameMesgQ(void); +OSMesgQueue* pfsManager_getFrameReplyQ(void); +OSMesgQueue* pfsManager_getSiLockQueue(void); +int pfsManager_isBusy(void); +OSMesgQueue* audioManager_getFrameMesgQueue(void); +OSMesgQueue* audioManager_getReplyMesgQueue(void); +OSMesgQueue* baMotor_getRetraceQueue(void); +OSMesgQueue* viMgr_getRetraceQueue(void); +OSMesgQueue* viMgr_getFrameTokenQueue(void); +OSMesgQueue* viMgr_getTickRetraceQueue(void); +int port_audioHeld(void); +int port_renderServicePending(void); +// Repro context +int gsworld_getMap(void); +int gsworld_getExit(void); +int getGameMode(void); +extern char gBuildVersion[]; +extern char gGitBranch[]; +extern char gGitCommitHash[]; +} + +namespace { + +using Clock = std::chrono::steady_clock; + +constexpr const char* kThreadNames[WATCHDOG_NUM_THREADS] = { + "vi-ticker", "main-loop", "game-tick", "thread5", "vimgr", "pfsmanager", "audio-mgr", "rumble", +}; + +// Blocking points in each loop that are not message-queue waits. A stall with +// no queue park is in one of these; naming them gives the reader somewhere to +// look when no symbols were available to resolve a stack. +constexpr const char* kThreadNonQueueWaits[WATCHDOG_NUM_THREADS] = { + "sleep_until; OS_SendEventMesg -> sMesgMutex", + "HandleEvents (SDL/window), ProcessGfxCommands (renderer present/DXGI wait), DrainRenderService callback, " + "OS_SiService -> ControlDeck", + "port_runOnRenderThread sSvcCv handoff; port_lockAudio (gAudioLock); ProcessGfxCommands std::async waits; " + "map-load I/O", + "sMesgMutex; a handler blocking in osSendMesg on a full queue", + "sMesgMutex", + "func_8024F450 -> D_802816E8 wait; port_shapeControllerInput; CALL_EVENT(OnControllerUpdate)", + "port_lockAudio (gAudioLock) in audioManager_handleFrameMsg", + "func_8024F450 -> D_802816E8 wait via __baMotor_startRumble/stopRumble/func_80250930; __osMotorAccess -> " + "ControlDeck rumble", +}; + +// Entry point each heartbeat belongs to. +constexpr const char* kThreadLoops[WATCHDOG_NUM_THREADS] = { + "osCreateViManager ticker (OS_VI.cpp)", + "SDL_main service loop (Game.cpp)", + "push_frame -> mainLoop (Game.cpp)", + "thread5_entry (graphics_thread.c)", + "viMgr_entry (vimgr.c)", + "pfsManager_entry (pfsmanager.c)", + "audioManagerThread_entry (audio_manager.c)", + "rumbleThread_entry (bamotor.c)", +}; + +// The audio thread legitimately idles through demo audio holds, and the +// pfsmanager thread races the game tick for the same polling queue, so both +// get a longer leash than the frame-paced threads. +constexpr auto kStallAfter = std::chrono::seconds(5); +constexpr auto kRelaxedStallAfter = std::chrono::seconds(10); +constexpr auto kSampleEvery = std::chrono::milliseconds(500); +constexpr auto kRedumpEvery = std::chrono::seconds(10); + +struct Heartbeat { + std::atomic count{ 0 }; + std::atomic tid{ 0 }; // SDL thread id, recorded on first beat + // Real (non-pseudo) thread handle, so the watcher can walk this thread's + // stack when it stalls. Recorded on first beat alongside the tid. + std::atomic handle{ nullptr }; + // Watcher-thread state + uint64_t lastCount = 0; + Clock::time_point lastBeat{}; + bool started = false; +}; + +Heartbeat sBeats[WATCHDOG_NUM_THREADS]; +std::atomic sStalledFlags[WATCHDOG_NUM_THREADS] = {}; +std::thread sWatcher; +std::atomic sWatcherRun{ false }; + +// Non-zero while a serviced thread is blocked on purpose. +std::atomic sExpectedStallDepth{ 0 }; +std::atomic sExpectedStallReason{ nullptr }; + +std::string DescribeUnkFlag1(int32_t f) { + switch (f) { + case 0x04: + return "AUDIO_TASK"; + case 0x10: + return "NO_TASK"; + case 0x20: + return "TASK_YIELDED"; + default: + break; + } + if (f & 0x08) { + return fmt::format("GFX_TASK|{:#x}", f & ~0x08); + } + return fmt::format("{:#x}?", f); +} + +std::string HumanDuration(std::chrono::milliseconds ms) { + if (ms.count() < 1000) { + return fmt::format("{}ms", ms.count()); + } + return fmt::format("{:.1f}s", ms.count() / 1000.0); +} + +// A queue's name and its producers, so a blocked wait names the code to audit. +struct QueueInfo { + bool known; + const char* name; + const char* fedBy; +}; + +QueueInfo DescribeQueue(OSMesgQueue* mq) { + if (mq == thread5_getTaskQueue()) { + return { true, "sThread5MesgQueue (graphics_thread.c)", + "thread5_sendTaskToQueue, osSetTimer cbs, viMgr_entry retrace, OS_SendEventMesg(SP/DP) from " + "ServiceRcp" }; + } + if (mq == thread5_getSyncQueue()) { + return { true, "sThread5SyncMesgQueue (graphics_thread.c)", + "thread5_handleSyncEvent/handleDPEvent/handleSPEvent/handleVIRetraceEvent; all need " + "sUnkFlag1==NO_TASK + gfx ring drained" }; + } + if (mq == viMgr_getRetraceQueue()) { + return { true, "sMesgQueue1 (vimgr.c)", "OS_VI ticker via OS_EVENT_VI" }; + } + if (mq == viMgr_getFrameTokenQueue()) { + return { true, "sMesgQueue2 (vimgr.c)", + "viMgr_func_8024BFAC <- thread5_handleDPEvent (needs sUnkFlag2 bit30), func_80253FE8" }; + } + if (mq == viMgr_getTickRetraceQueue()) { + return { true, "sMesgQueue3 (vimgr.c)", "viMgr_entry" }; + } + if (mq == pfsManager_getFrameMesgQ()) { + return { true, "pfsManagerContPollingMsqQ (pfsmanager.c)", + "OS_EVENT_SI <- OS_SiService (window thread) after osContStartReadData" }; + } + if (mq == pfsManager_getFrameReplyQ()) { + return { true, "pfsManagerContReplyMsgQ (pfsmanager.c)", "pfsManager_entry when !pfsManagerBusy" }; + } + if (mq == pfsManager_getSiLockQueue()) { + return { true, "D_802816E8 (pfsmanager.c)", "func_8024F4AC via func_8024F35C(0)" }; + } + if (mq == baMotor_getRetraceQueue()) { + return { true, "D_80282390 (bamotor.c)", "viMgr_entry retrace signal (NOBLOCK, so extras drop)" }; + } + if (mq == audioManager_getFrameMesgQueue()) { + return { true, "audioFrameMsgQ (audio_manager.c)", + "thread5_handleAudioTimerEvent (skipped while port_audioHeld)" }; + } + if (mq == audioManager_getReplyMesgQueue()) { + return { true, "audioReplyMsgQ (audio_manager.c)", + "thread5_handleSPEvent when sUnkFlag1==UNKFLAG1_AUDIO_TASK" }; + } + return { false, "unmapped queue", "unknown" }; +} + +// Repo source root, derived from this file's own build-time path so the check +// holds wherever the repo was cloned. The PDB records paths from the same +// compiler invocation, so our translation units share this prefix while the +// CRT/STL ones (which also contain "\src\") do not. +const std::string& ProjectSourceRoot() { + static const std::string root = [] { + const std::string self = __FILE__; + const size_t pos = self.rfind("src"); + // Only usable if __FILE__ came through absolute; otherwise mark nothing + // rather than risk the false positives a looser match produces. + if (pos == std::string::npos || self.find(':') == std::string::npos) { + return std::string(); + } + return self.substr(0, pos); + }(); + return root; +} + +// Stack of the stalled thread, symbolized against the shipped PDB. Nothing else +// in the report can be reconstructed after the fact: by the time a maintainer +// reads the log the process is gone, so capture it here rather than asking for +// a debugger they cannot attach. +// +// Addresses are collected while the target is suspended and symbolized only +// after it resumes, to keep the window in which it is held as narrow as +// possible. See the caller for the hang risk this still carries. +std::string CaptureStalledStack(int threadIdx) { +#if defined(LH_WATCHDOG_STACKS) + HANDLE thread = (HANDLE)sBeats[threadIdx].handle.load(std::memory_order_relaxed); + if (thread == nullptr) { + return {}; + } + + HANDLE proc = GetCurrentProcess(); + static std::once_flag symOnce; + std::call_once(symOnce, [proc] { + SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + SymInitialize(proc, nullptr, TRUE); + }); + + if (SuspendThread(thread) == (DWORD)-1) { + return {}; + } + + CONTEXT ctx = {}; + ctx.ContextFlags = CONTEXT_FULL; + DWORD64 frames[32]; + int numFrames = 0; + if (GetThreadContext(thread, &ctx)) { + STACKFRAME64 sf = {}; +#if defined(_M_X64) + const DWORD machine = IMAGE_FILE_MACHINE_AMD64; + sf.AddrPC.Offset = ctx.Rip; + sf.AddrFrame.Offset = ctx.Rbp; + sf.AddrStack.Offset = ctx.Rsp; +#elif defined(_M_ARM64) + const DWORD machine = IMAGE_FILE_MACHINE_ARM64; + sf.AddrPC.Offset = ctx.Pc; + sf.AddrFrame.Offset = ctx.Fp; + sf.AddrStack.Offset = ctx.Sp; +#else + const DWORD machine = IMAGE_FILE_MACHINE_I386; + sf.AddrPC.Offset = ctx.Eip; + sf.AddrFrame.Offset = ctx.Ebp; + sf.AddrStack.Offset = ctx.Esp; +#endif + sf.AddrPC.Mode = sf.AddrFrame.Mode = sf.AddrStack.Mode = AddrModeFlat; + // Addresses only while suspended; symbol lookup happens after resume. + while (numFrames < 32 && + StackWalk64(machine, proc, thread, &sf, &ctx, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, + nullptr) && + sf.AddrPC.Offset != 0) { + frames[numFrames++] = sf.AddrPC.Offset; + } + } + ResumeThread(thread); + + if (numFrames == 0) { + return {}; + } + + const std::string& srcRoot = ProjectSourceRoot(); + std::string out = "Stack:\n"; + alignas(SYMBOL_INFO) char symBuf[sizeof(SYMBOL_INFO) + 256] = {}; + auto* sym = reinterpret_cast(symBuf); + sym->SizeOfStruct = sizeof(SYMBOL_INFO); + sym->MaxNameLen = 255; + for (int i = 0; i < numFrames; i++) { + DWORD64 symDisp = 0; + DWORD lineDisp = 0; + IMAGEHLP_LINE64 line = {}; + line.SizeOfStruct = sizeof(line); + if (SymFromAddr(proc, frames[i], &symDisp, sym)) { + if (SymGetLineFromAddr64(proc, frames[i], &lineDisp, &line)) { + // Only frames under this repo's source root are ours; CRT and + // STL paths contain "\src\" as well and must not match. + const bool ours = !srcRoot.empty() && _strnicmp(line.FileName, srcRoot.c_str(), srcRoot.size()) == 0; + out += fmt::format("{} #{:02} {}+0x{:x} ({}:{})\n", ours ? ">" : " ", i, sym->Name, symDisp, + line.FileName, line.LineNumber); + } else { + out += fmt::format(" #{:02} {}+0x{:x}\n", i, sym->Name, symDisp); + } + } else { + // No symbols (plain Release with no PDB alongside): emit + // module+offset, which stays resolvable later against a matching + // build. A raw address is meaningless once ASLR is factored in. + DWORD64 base = SymGetModuleBase64(proc, frames[i]); + char modPath[MAX_PATH] = {}; + const char* modName = "?"; + if (base != 0 && GetModuleFileNameA((HMODULE)(uintptr_t)base, modPath, MAX_PATH) != 0) { + const char* slash = strrchr(modPath, '\\'); + modName = slash != nullptr ? slash + 1 : modPath; + } + if (base != 0) { + out += fmt::format(" #{:02} {}+0x{:x}\n", i, modName, frames[i] - base); + } else { + out += fmt::format(" #{:02} 0x{:x}\n", i, frames[i]); + } + } + } + return out; +#else + (void)threadIdx; + return {}; +#endif +} + +std::string BuildDump(const bool* stalled, Clock::time_point now, const std::string& stack) { + OS_BlockedWait waits[16]; + const int numWaits = OS_MesgSnapshotBlockedWaits(waits, 16); + auto waitFor = [&](int threadIdx) -> const OS_BlockedWait* { + unsigned long tid = sBeats[threadIdx].tid.load(std::memory_order_relaxed); + for (int i = 0; i < numWaits; i++) { + if (waits[i].tid == tid) { + return &waits[i]; + } + } + return nullptr; + }; + auto ageOf = [&](int threadIdx) { + return std::chrono::duration_cast(now - sBeats[threadIdx].lastBeat); + }; + + std::string out; + + // Downstream threads stall behind the one that actually broke, so the + // longest-stalled thread is the best root-cause guess. + int firstStalled = -1; + int numStalled = 0; + if (stalled != nullptr) { + for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { + if (!stalled[i]) { + continue; + } + numStalled++; + if (firstStalled < 0 || sBeats[i].lastBeat < sBeats[firstStalled].lastBeat) { + firstStalled = i; + } + } + } + + if (firstStalled < 0) { + out += "===== Thread Watchdog: snapshot, no stall =====\n"; + } else { + out += fmt::format("===== Thread Watchdog: STALL DETECTED =====\n" + "{} has not reported for {} (tid {}){}\n" + "In loop: {}\n", + kThreadNames[firstStalled], HumanDuration(ageOf(firstStalled)), + sBeats[firstStalled].tid.load(std::memory_order_relaxed), + numStalled > 1 ? fmt::format(", {} stalled total, this one first", numStalled) : "", + kThreadLoops[firstStalled]); + if (const OS_BlockedWait* w = waitFor(firstStalled)) { + QueueInfo qi = DescribeQueue(w->mq); + out += fmt::format("Parked at: {} on {} {}/{}\n", w->isSend ? "osSendMesg (full)" : "osRecvMesg (empty)", + qi.name, w->mq->validCount, w->mq->msgCount); + out += fmt::format("Producers: {}\n", qi.fedBy); + } else if (!stack.empty()) { + out += "Parked at: no queue wait; see Stack below\n"; + } else { + out += fmt::format("Parked at: no queue wait, so loop/mutex/condvar. Candidates: {}\n", + kThreadNonQueueWaits[firstStalled]); + if (firstStalled == WATCHDOG_GAME_TICK && port_renderServicePending()) { + out += "Note: port_runOnRenderThread call is pending, so sSvcCv is the prime suspect\n"; + } + } + } + + for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { + const Heartbeat& hb = sBeats[i]; + uint64_t count = hb.count.load(std::memory_order_relaxed); + if (count == 0) { + out += fmt::format(" {:<11} never started\n", kThreadNames[i]); + continue; + } + std::string age = (hb.lastBeat == Clock::time_point{}) ? std::string("?") : HumanDuration(ageOf(i)); + std::string park; + if (const OS_BlockedWait* w = waitFor(i)) { + QueueInfo qi = DescribeQueue(w->mq); + park = + fmt::format(" {} {} {}/{}", w->isSend ? "send" : "recv", qi.name, w->mq->validCount, w->mq->msgCount); + } + out += fmt::format(" {:<11} {:<7} {:>6} tid {:<6} {} beats{}\n", kThreadNames[i], + (stalled != nullptr && stalled[i]) ? "STALLED" : "ok", age, + hb.tid.load(std::memory_order_relaxed), count, park); + } + + Thread5WatchdogState t5; + thread5_getWatchdogState(&t5); + ViMgrWatchdogState vi; + viMgr_getWatchdogState(&vi); + const u32 dpStatus = osDpGetStatus(); + void* curFb = osViGetCurrentFramebuffer(); + void* nextFb = osViGetNextFramebuffer(); + + out += fmt::format("Pipeline: sUnkFlag1={} sUnkFlag2={:#x}/saved={:#x} sSyncCounter={} task7={} " + "gfxRing={}->{} audioRing={}->{} taskQ={}/{} syncQ={}/{} FREEZE={} pendingSpTask={} " + "fb cur{}next{}\n", + DescribeUnkFlag1(t5.unkFlag1), t5.unkFlag2, t5.unkFlag2Saved, t5.syncCounter, t5.task7Handled, + t5.gfxActiveId, t5.gfxSelectedId, t5.audioActiveId, t5.audioSelectedId, t5.taskQueueCount, + t5.taskQueueCap, t5.syncQueueCount, t5.syncQueueCap, (dpStatus & 0x2) ? 1 : 0, + OS_SpPeekPendingTask() != nullptr ? "yes" : "no", + curFb == nextFb ? "==" : "!=", OS_ViBlackActive() ? " viBlack" : ""); + out += fmt::format("Frame pacing: D_802808D8={}{} frameTokenQ={} tickRetraceQ={} retraceQ={}\n", vi.retraceCount, + vi.retraceCount > 10 ? " (accumulating)" : "", vi.q2Count, vi.q3Count, vi.q1Count); + + OSMesgQueue* pfsPoll = pfsManager_getFrameMesgQ(); + OSMesgQueue* audioFrame = audioManager_getFrameMesgQueue(); + OSMesgQueue* audioReply = audioManager_getReplyMesgQueue(); + out += fmt::format("SI/audio: pfsBusy={} pollingQ={} audioFrameQ={} audioReplyQ={} audioHeld={} svcPending={}\n", + pfsManager_isBusy(), pfsPoll->validCount, audioFrame->validCount, audioReply->validCount, + port_audioHeld(), port_renderServicePending()); + out += fmt::format("Context: map={:#x} exit={:#x} gameMode={} build={} {}@{}", gsworld_getMap(), gsworld_getExit(), + getGameMode(), (char*)gBuildVersion, (char*)gGitBranch, (char*)gGitCommitHash); + + if (!stack.empty()) { + out += "\n" + stack; + } + return out; +} + +void Watcher() { + auto lastSample = Clock::now(); + auto lastReport = Clock::time_point{}; + bool wasStalled = false; + bool wasExpected = false; + + while (sWatcherRun.load(std::memory_order_relaxed)) { + std::this_thread::sleep_for(kSampleEvery); + auto now = Clock::now(); + + // A debugger pause (or system sleep) suspends every thread including + // this one; a stale "last beat" then isn't a stall. Rebaseline. + const bool suspended = (now - lastSample) > kSampleEvery * 4; + lastSample = now; + const bool expected = sExpectedStallDepth.load(std::memory_order_acquire) > 0; + const bool rebaseline = suspended || expected || wasExpected; + wasExpected = expected; + + bool stalled[WATCHDOG_NUM_THREADS] = {}; + bool anyStalled = false; + for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { + Heartbeat& hb = sBeats[i]; + uint64_t cur = hb.count.load(std::memory_order_relaxed); + if (!hb.started) { + if (cur == 0) { + continue; // thread not running yet; don't judge it + } + hb.started = true; + } + if (cur != hb.lastCount || rebaseline) { + hb.lastCount = cur; + hb.lastBeat = now; + continue; + } + const auto limit = + (i == WATCHDOG_AUDIO_MANAGER || i == WATCHDOG_PFSMANAGER) ? kRelaxedStallAfter : kStallAfter; + if (now - hb.lastBeat > limit) { + stalled[i] = true; + anyStalled = true; + } + } + for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { + sStalledFlags[i].store(stalled[i], std::memory_order_relaxed); + } + + if (!anyStalled) { + wasStalled = false; + continue; + } + // One dump when a stall appears, then a refresher while it persists. + if (wasStalled && (now - lastReport) < kRedumpEvery) { + continue; + } + const bool firstReportOfEpisode = !wasStalled; + wasStalled = true; + lastReport = now; + + int root = -1; + for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { + if (stalled[i] && (root < 0 || sBeats[i].lastBeat < sBeats[root].lastBeat)) { + root = i; + } + } + + // The stack is folded into the report below so the diagnosis is one + // block, but walking a thread means suspending it, which can hang if it + // holds a DbgHelp or loader lock and would take this watcher with it. + // Leave a breadcrumb first so a hang still names the stalled thread. + std::string stack; + if (firstReportOfEpisode && root >= 0) { + SPDLOG_ERROR("[Watchdog] {} stalled, collecting state", kThreadNames[root]); + stack = CaptureStalledStack(root); + } + SPDLOG_ERROR("{}", BuildDump(stalled, now, stack)); + } +} + +} // namespace + +extern "C" void ThreadWatchdog_Beat(WatchdogThread id) { + Heartbeat& hb = sBeats[id]; + hb.count.fetch_add(1, std::memory_order_relaxed); + if (hb.tid.load(std::memory_order_relaxed) == 0) { +#if defined(LH_WATCHDOG_STACKS) + // GetCurrentThread is a pseudo-handle only valid on this thread, so + // duplicate it into one the watcher can use. Leaked by design: it must + // outlive the thread's own loop for the whole session. + HANDLE dup = nullptr; + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &dup, + THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, 0); + hb.handle.store(dup, std::memory_order_relaxed); +#endif + hb.tid.store((unsigned long)SDL_ThreadID(), std::memory_order_relaxed); + } +} + +extern "C" void ThreadWatchdog_Start(void) { + if (sWatcherRun.exchange(true)) { + return; + } + sWatcher = std::thread(Watcher); +} + +extern "C" void ThreadWatchdog_Stop(void) { + if (!sWatcherRun.exchange(false)) { + return; + } + if (sWatcher.joinable()) { + sWatcher.join(); + } +} + +extern "C" void ThreadWatchdog_DumpNow(void) { + SPDLOG_INFO("{}", BuildDump(nullptr, Clock::now(), std::string())); +} + +extern "C" int ThreadWatchdog_IsStalled(WatchdogThread id) { + return sStalledFlags[id].load(std::memory_order_relaxed) ? 1 : 0; +} + +extern "C" void ThreadWatchdog_BeginExpectedStall(const char* reason) { + if (sExpectedStallDepth.fetch_add(1, std::memory_order_acq_rel) == 0) { + sExpectedStallReason.store(reason, std::memory_order_relaxed); + SPDLOG_DEBUG("[Watchdog] stall reporting suppressed: {}", reason ? reason : "?"); + } +} + +extern "C" void ThreadWatchdog_EndExpectedStall(void) { + const int prev = sExpectedStallDepth.fetch_sub(1, std::memory_order_acq_rel); + if (prev <= 0) { + // Unbalanced release would leave the counter negative and suppress + // every future stall, which is worse than the false positive. + sExpectedStallDepth.store(0, std::memory_order_release); + SPDLOG_WARN("[Watchdog] ThreadWatchdog_EndExpectedStall without a matching Begin"); + return; + } + if (prev == 1) { + const char* reason = sExpectedStallReason.load(std::memory_order_relaxed); + SPDLOG_DEBUG("[Watchdog] stall reporting resumed: {}", reason ? reason : "?"); + sExpectedStallReason.store(nullptr, std::memory_order_relaxed); + } +} diff --git a/src/port/DevTools/ThreadWatchdog.h b/src/port/DevTools/ThreadWatchdog.h new file mode 100644 index 000000000..35a644985 --- /dev/null +++ b/src/port/DevTools/ThreadWatchdog.h @@ -0,0 +1,94 @@ +#ifndef PORT_THREAD_WATCHDOG_H +#define PORT_THREAD_WATCHDOG_H + +#include + +// Heartbeat watchdog over the revived decomp threads. +// +// Every serviced loop beats once per iteration and a watcher thread samples the +// counters. When a thread that has already proven alive stops beating while the +// wall clock keeps moving, the watcher logs the pipeline state: thread5's flag +// words and task rings, every queue depth, who is parked where, and the stalled +// thread's stack. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum WatchdogThread { + WATCHDOG_VI_TICKER = 0, // retrace source (OS_VI.cpp); everything below is paced by it + WATCHDOG_MAIN_LOOP, // window thread: event pump + RCP service (Game.cpp) + WATCHDOG_GAME_TICK, // push_frame loop (Game.cpp) + WATCHDOG_THREAD5, // decomp graphics thread (graphics_thread.c) + WATCHDOG_VIMGR, // decomp VI manager thread (vimgr.c) + WATCHDOG_PFSMANAGER, // controller thread (pfsmanager.c) + WATCHDOG_AUDIO_MANAGER, // audio thread (audio_manager.c); idles during demo audio holds + WATCHDOG_RUMBLE, // motor thread (bamotor.c); one beat per retrace signal + WATCHDOG_NUM_THREADS +} WatchdogThread; + +// Called once per loop iteration; one relaxed atomic increment. +void ThreadWatchdog_Beat(WatchdogThread id); + +// Started once the decomp threads exist, stopped before shutdown teardown. +void ThreadWatchdog_Start(void); +void ThreadWatchdog_Stop(void); + +// Log the pipeline state immediately, stalled or not. +void ThreadWatchdog_DumpNow(void); + +// Bracket a section that blocks a serviced thread on purpose. +void ThreadWatchdog_BeginExpectedStall(const char* reason); +void ThreadWatchdog_EndExpectedStall(void); + +// Whether the watcher currently considers this thread stalled. The gui only +// draws inside serviced frames, so the main loop uses this to keep drawing +// while the tick is down instead of freezing ImGui along with it. +int ThreadWatchdog_IsStalled(WatchdogThread id); + +// Diagnostic snapshots served by the decomp thread owners; plain structs so +// the C side fills them without knowing about the watchdog's internals. +typedef struct Thread5WatchdogState { + int32_t unkFlag1; // 0x04 audio task, 0x08 gfx task, 0x10 idle, 0x20 yielded + int32_t unkFlag2; + int32_t unkFlag2Saved; + int32_t syncCounter; + int32_t task7Handled; + int32_t gfxActiveId; + int32_t gfxSelectedId; + int32_t audioActiveId; + int32_t audioSelectedId; + int32_t taskQueueCount; + int32_t taskQueueCap; + int32_t syncQueueCount; + int32_t syncQueueCap; +} Thread5WatchdogState; +void thread5_getWatchdogState(Thread5WatchdogState* out); + +typedef struct ViMgrWatchdogState { + int32_t retraceCount; // D_802808D8: retraces seen since the tick last consumed them + int32_t q1Count; // retrace event queue (viMgr_entry parks here) + int32_t q2Count; // frame token queue (the tick parks here) + int32_t q3Count; // tick retrace queue +} ViMgrWatchdogState; +void viMgr_getWatchdogState(ViMgrWatchdogState* out); + +#ifdef __cplusplus +} + +namespace Lighthouse { +class ExpectedStall { +public: + explicit ExpectedStall(const char* reason) { + ThreadWatchdog_BeginExpectedStall(reason); + } + ~ExpectedStall() { + ThreadWatchdog_EndExpectedStall(); + } + ExpectedStall(const ExpectedStall&) = delete; + ExpectedStall& operator=(const ExpectedStall&) = delete; +}; +} // namespace Lighthouse +#endif + +#endif // PORT_THREAD_WATCHDOG_H diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp index 8d8bf5e22..d8aca8698 100644 --- a/src/port/Engine.cpp +++ b/src/port/Engine.cpp @@ -1,7 +1,9 @@ #include "Engine.h" +#include #include #include #include +#include #if defined(__linux__) || defined(__APPLE__) #include #include @@ -31,8 +33,10 @@ #include "Audio/GameAudio.h" #include "build.h" #include "Extractor/GameExtractor.h" -#include "Interpolation/AdaptiveFps.h" +#include "ship/window/gui/FileBrowserWindow.h" #include "Interpolation/FrameInterpolation.h" +#include "Nametag/Nametag.h" +#include "OS/OS.h" #include "Network/Anchor/Anchor.h" #include "port/Enhancements/Events/PortEnhancements.h" #include "port/Patches/Patches.h" @@ -49,6 +53,7 @@ #include "src/port/Enhancements/Events/Hooks/Events.h" #include "UI/LighthouseGui.hpp" #include "UI/LighthouseModMenuWindow.h" +#include "LaunchArgs.h" #ifdef __SWITCH__ #include @@ -72,14 +77,6 @@ extern s32 D_80275610; bool prevAltAssets = false; // bool gEnableGammaBoost = true; -// Audio synthesis entry point (decomp n_synthesizer.c) -Acmd* n_alAudioFrame(Acmd* cmdList, s32* cmdLen, s16* outBuf, s32 outLen); -// DMA cache cleanup (decomp audio_manager.c) -void func_802403F0(void); -void func_80250650(void); -// Game mode helper -bool func_802E4A08(void); - // Soundfont ROM symbols — loaded from OTR in LoadSoundfonts() u8* soundfont1ctl_ROM_START = NULL; u8* soundfont1ctl_ROM_END = NULL; @@ -123,10 +120,9 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { return version; } -// Checks the program version stored in the otr and compares the major value to soh -// For Windows/Mac/Linux if the version doesn't match, offer to +// Reads the port version recorded in the named o2r. A missing file yields INT16_MAX in every +// field; an o2r that opens without a portVersion record yields zeros. OTRVersion DetectOTRVersion(std::string fileName) { - bool isOtrOld = false; std::string otrPath = Ship::Context::LocateFileAcrossAppDirs(fileName); // Doesn't exist so nothing to do here @@ -182,6 +178,7 @@ GameEngine::GameEngine() { lhFast3dWindow = std::make_shared(std::vector>({})); this->context->InitWindow(lhFast3dWindow); + this->context->InitAudio({ .SampleRate = 22000, .SampleLength = 736, .DesiredBuffered = 2208 }); LighthouseGui::SetupMenu(); @@ -212,6 +209,7 @@ typedef enum PromptSteps { PS_FILE_CHECK, PS_LOCAL, PS_FIRST, + PS_FIRST_WAIT, // waiting for the async file-pick result (resolves immediately on the native path) PS_WAIT, PS_NONE, } PromptSteps; @@ -228,7 +226,7 @@ bool IsSubpath(const std::filesystem::path& path, const std::filesystem::path& b return !rel.empty() && rel.native()[0] != '.'; } -bool PathTestCleanup(FILE* tfile) { +bool PathTestCleanup() { try { if (std::filesystem::exists("./text.txt")) std::filesystem::remove("./text.txt"); @@ -248,7 +246,8 @@ void CheckAndCreateModFolder() { if (std::filesystem::create_directories(modsPath)) { std::ofstream(filePath).close(); std::filesystem::create_directories(modsPath + "/~romhacks"); // BK romhacks go here - std::filesystem::create_directories(modsPath + "/shared"); // Mods usable by everything go here + std::filesystem::create_directories(modsPath + "/~lang"); // Language packs go here + std::filesystem::create_directories(modsPath + "/~shared"); // Mods usable by everything go here } } } catch (std::filesystem::filesystem_error const&) { @@ -327,7 +326,7 @@ static void LoadLooseModDirectories(const std::string& patches_path) { continue; } const std::string dirName = p.path().filename().generic_string(); - if (dirName == "~romhacks" || dirName == "shared" || dirName == "lang" || IsScopedModFolderName(dirName)) { + if (dirName == "~romhacks" || dirName == "~shared" || dirName == "~lang" || IsScopedModFolderName(dirName)) { continue; } SPDLOG_INFO("Found mod directory: {}", p.path().generic_string()); @@ -336,9 +335,9 @@ static void LoadLooseModDirectories(const std::string& patches_path) { } } -// Load every .o2r language pack from mods/lang into the ArchiveManager. +// Load every .o2r language pack from mods/~lang into the ArchiveManager. static void LoadLanguagePacks() { - const std::string lang_path = Ship::Context::GetPathRelativeToAppDirectory("mods/lang"); + const std::string lang_path = Ship::Context::GetPathRelativeToAppDirectory("mods/~lang"); if (lang_path.empty() || !std::filesystem::is_directory(lang_path)) { return; } @@ -364,6 +363,9 @@ void GameEngine::FinishInit() { std::filesystem::create_directories(patches_path); } + // Apply `-hack ` before the scan. + Lighthouse::ApplyLaunchHack(); + // Load enabled mod o2rs into the ArchiveManager. UpdateModFiles(true); LoadLooseModDirectories(patches_path); @@ -380,17 +382,21 @@ void GameEngine::FinishInit() { Ship::Context::GetRawInstance()->GetLogger()->set_pattern("[%H:%M:%S.%e] [%s:%#] [%l] %v"); SPDLOG_INFO("Starting Lighthouse version {} (Branch: {} | Commit: {})", (char*)gBuildVersion, (char*)gGitBranch, (char*)gGitCommitHash); + Lighthouse::FlushLaunchHackLog(); context->InitFileDropMgr(); context->InitCrashHandler(); context->InitEventSystem(); - this->context->InitAudio({ .SampleRate = 22000, .SampleLength = 736, .DesiredBuffered = 2208 }); - lhFast3dWindow->SetTargetFps(60); lhFast3dWindow->SetMaximumFrameLatency(1); lhFast3dWindow->SetRendererUCode(ucode_f3d); + // Opt-in to memoization + if (auto interpreter = lhFast3dWindow->GetInterpreterWeak().lock()) { + interpreter->SetResolvedResourceCacheEnabled(true); + } + #ifdef USE_NETWORKING SDLNet_Init(); #endif @@ -403,13 +409,16 @@ void GameEngine::FinishInit() { Lighthouse::RescanLanguages(); LighthouseGui::SetupGuiElements(); + // Undo the -hack override only now: LighthouseModMenuWindow::InitElement() + // re-runs UpdateModFiles(true) during SetupGuiElements and would otherwise + // re-read the restored CVars and reload the persisted hack over the override. + Lighthouse::RestoreModSelectionAfterLaunchHack(); // If UpdateModFiles(true) above quarantined conflicting romhack overlays, // surface that to the user now that the modal window is alive. MaybeShowModConflictPopup(); // Likewise if it refused romhack overlays due to a non-v1.0 base. MaybeShowRomhackBaseMismatchPopup(); Instance->AudioInit(); - AdaptiveFps_Configure(30); // BK ticks at 30 Hz // Instance->LoadDictionary(); // Instance->LoadPlayerAnims(); #if defined(__SWITCH__) || defined(__WIIU__) @@ -442,10 +451,17 @@ void GameEngine::RunExtract(int argc, char* argv[]) { std::filesystem::path ownPath; std::vector args; - if (argc > 1) { - for (int i = 1; i < argc; i++) { - args.push_back(argv[argc]); + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + std::string inlineValue; + bool takesValue = false; + if (Lighthouse::IsLaunchHackFlag(arg, inlineValue, takesValue)) { + if (takesValue) { + i++; + } + continue; } + args.push_back(arg); } GameExtractor extract; PromptSteps promptStep = PS_FILE_CHECK; @@ -453,6 +469,11 @@ void GameEngine::RunExtract(int argc, char* argv[]) { bool extractStarted = false; std::atomic extractCount{ 0 }, totalExtract{ 0 }; + // Async ROM selection: the result callback fires on this thread during the render step below, so + // these plain locals are safe to capture by reference. + bool romLoaded = false; + bool romResultReady = false; + std::string installPath = Ship::Context::GetAppBundlePath(); std::string file; @@ -511,7 +532,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) { GameExtractor::sCustomCodePromptActive = false; }); } - if (LighthouseGui::PopupsQueued() > 0 || extracting) { + if (LighthouseGui::PopupsQueued() > 0 || extracting || Ship::FileBrowserWindow::IsOpen()) { goto render; } @@ -597,8 +618,10 @@ void GameEngine::RunExtract(int argc, char* argv[]) { "Lighthouse does not have proper file permissions.\nPlease move it to a " "folder that does and run again.", "OK", "", [&]() { - fclose(tfile); - PathTestCleanup(tfile); + if (tfile != NULL) { + fclose(tfile); + } + PathTestCleanup(); threadPool = nullptr; lhFast3dWindow = nullptr; context = nullptr; @@ -606,7 +629,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) { }); } else { fclose(tfile); - if (!PathTestCleanup(tfile)) { + if (!PathTestCleanup()) { LighthouseGui::RegisterPopup( "Lighthouse Permissions Error", "Lighthouse does not have proper file permissions.\nPlease move it to a " @@ -725,10 +748,17 @@ void GameEngine::RunExtract(int argc, char* argv[]) { } case PS_LOCAL: { extract = GameExtractor(); + const std::string appDir = Ship::Context::GetAppDirectoryPath("bk"); + std::error_code sameDirEc; + const bool sameDir = std::filesystem::equivalent(installPath, appDir, sameDirEc); extract.SetSearchPath(installPath); extract.GetRoms(args); - extract.SetSearchPath(Ship::Context::GetAppDirectoryPath("bk")); - extract.GetRoms(args); + if (sameDirEc || !sameDir) { + extract.SetSearchPath(appDir); + extract.GetRoms(args); + } + std::sort(args.begin(), args.end()); + args.erase(std::unique(args.begin(), args.end()), args.end()); if (!args.empty()) { promptStep = PS_WAIT; LighthouseGui::RegisterPopup( @@ -744,8 +774,30 @@ void GameEngine::RunExtract(int argc, char* argv[]) { continue; } case PS_FIRST: { - if (args.empty() && !extract.SelectGameFromUI()) { - promptStep = PS_FILE_CHECK; + if (args.empty()) { + // Skip the picker entirely if a baserom.us.z64 is sitting in the app + // directory: load it and go straight to extraction. + std::string baserom = Ship::Context::GetPathRelativeToAppDirectory("baserom.us.z64"); + if (std::filesystem::exists(baserom) && extract.LoadRomFromPath(baserom)) { + extracting = true; + extractStarted = true; + file = extract.GetRomPath(); + (void)threadPool->submit_task([&]() -> void { + extract.GenerateOTR(extractCount, totalExtract, "bk"); + extracting = false; + }); + continue; // stay in PS_FIRST; the completion check fires when done + } + // Otherwise open the picker (native dialog on desktop, ImGui browser on + // consoles/arm). For the browser, the IsOpen() gate above keeps the loop + // rendering until the user picks or cancels; the ROM loads before the callback. + romResultReady = false; + romLoaded = false; + extract.SelectGameFromUI([&](bool ok) { + romLoaded = ok; + romResultReady = true; + }); + promptStep = PS_FIRST_WAIT; continue; } extracting = true; @@ -757,6 +809,25 @@ void GameEngine::RunExtract(int argc, char* argv[]) { }); continue; } + case PS_FIRST_WAIT: { + if (!romResultReady) { + goto render; // browser still open; keep drawing it + } + romResultReady = false; + if (!romLoaded) { + promptStep = PS_FILE_CHECK; // cancelled or failed to load + continue; + } + extracting = true; + extractStarted = true; + file = extract.GetRomPath(); + promptStep = PS_FIRST; // so the ES_EXTRACT/PS_FIRST completion check fires + (void)threadPool->submit_task([&]() -> void { + extract.GenerateOTR(extractCount, totalExtract, "bk"); + extracting = false; + }); + continue; + } default: break; } @@ -961,6 +1032,7 @@ void GameEngine::ScaleImGui() { } void GameEngine::Create(int argc, char* argv[]) { + Lighthouse::ParseLaunchArgs(argc, argv); const auto instance = Instance = new GameEngine(); // instance->AudioInit(); // DisplayListPatch::Run(); @@ -1006,7 +1078,6 @@ void GameEngine::Destroy() { // Flush all resource refs so destructors run while spdlog is still active. // sResourceRefCache holds shared_ptrs that outlive the LUS cache otherwise. - AudioExit(); ResourceHelpers_ClearRefCache(); AudioDma_Clear(); ReleaseSoundfonts(); @@ -1033,7 +1104,7 @@ void GameEngine::StartFrame() const { case KbScancode::LUS_KB_TAB: { // Toggle HD Assets CVarSetInteger(CVAR_SETTING("Mods.AlternateAssets"), - !CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 0)); + !CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 1)); break; } case KbScancode::LUS_KB_F4: { @@ -1088,33 +1159,19 @@ void GameEngine::RelaunchIfRequested(int argc, char* argv[]) { #endif } -#if 0 -// Values for 44100 hz -#define SAMPLES_HIGH 752 -#define SAMPLES_LOW 720 -#else -// Values for 32000 hz -#define SAMPLES_HIGH 560 -#define SAMPLES_LOW 528 +#define SAMPLES_PER_FRAME (560 * 2 * 2) -#endif -#define NUM_AUDIO_CHANNELS 2 -#define SAMPLES_PER_FRAME (SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 2) +// 2 VIs per game frame (30fps) +#define gVIsPerFrame 2 extern "C" uint32_t GameEngine_GetSamplesPerFrame() { return SAMPLES_PER_FRAME; } -// 2 VIs per game frame (30fps) -#define gVIsPerFrame 2 - -// 736 samples per audio update (44000/60, aligned to 184-sample boundary) -#define AlFrameSize 736 - // Attract-demo audio hold static std::atomic sHoldAudio{ false }; -static constexpr int kDemoAudioHoldFrames = 2; // frames to stay held after the load -static int sHoldFramesRemaining = 0; // game-thread countdown +static constexpr int kDemoAudioHoldFrames = 2; // drawn ticks to stay held after the load +static int sHoldFramesRemaining = 0; // game thread only extern "C" void port_beginDemoAudioHold(void) { if (kDemoAudioHoldFrames <= 0) { @@ -1124,50 +1181,14 @@ extern "C" void port_beginDemoAudioHold(void) { sHoldAudio.store(true); } -void GameEngine::HandleAudioThread() { - int16_t audioBuffer[AlFrameSize * 2]; - Acmd cmdList[0x800]; - - // Free-run: continuously keep the backend queue topped up, real-time paced and - // decoupled from the game frame, so a long game frame can't starve the device. - while (audio.running) { - if (audio.ready) { - while (audio.running && AudioPlayerBuffered() < AudioPlayerGetDesiredBuffered()) { - int samplesToGen = AlFrameSize * 2 * sizeof(int16_t); - - memset(audioBuffer, 0, samplesToGen); - - // While held, leave the buffer as silence and do NOT advance the engine. - if (!sHoldAudio) { - int32_t cmdLen = 0; - // Lock only the engine work; the volume scale and backend submit touch - // worker-local / backend state, not the synth. - port_lockAudio(); - func_802403F0(); - n_alAudioFrame(cmdList, &cmdLen, audioBuffer, AlFrameSize); - func_80250650(); - port_unlockAudio(); - - float master_vol = CVarGetInteger(CVAR_SETTING("Volume.Master"), 100) / 100.0f; - for (u32 i = 0; i < AlFrameSize * 2; i++) { - audioBuffer[i] = static_cast(audioBuffer[i] * master_vol); - } - } - AudioPlayerPlayFrame((uint8_t*)audioBuffer, samplesToGen); - } - } - std::this_thread::sleep_for(std::chrono::milliseconds(2)); +extern "C" void port_tickDemoAudioHold(void) { + if (sHoldAudio.load() && --sHoldFramesRemaining <= 0) { + sHoldAudio.store(false); } } -void GameEngine::StartAudioFrame() { - // Worker free-runs now; this only marks the engine initialized (first call is after - // audio init, once the game loop is running). - audio.ready = true; -} - -void GameEngine::EndAudioFrame() { - // No-op: audio generation is decoupled from the game frame. +extern "C" int port_audioHeld(void) { + return sHoldAudio.load() ? 1 : 0; } static std::vector> sSoundfontResources; @@ -1216,31 +1237,20 @@ void GameEngine::AudioInit() { LoadSoundfonts(); } -void GameEngine::AudioStartThread() { - if (!audio.running) { - audio.running = true; - audio.thread = std::thread(HandleAudioThread); -#ifdef _WIN32 - SetThreadPriority(audio.thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL); -#endif - } -} - -void GameEngine::AudioExit() { - // Free-run worker checks `running` each loop (~every 2 ms), so just clear it and join. - audio.running = false; - if (audio.thread.joinable()) { - audio.thread.join(); - } -} - -// Local timer helper for the per-sub-frame measurement we feed into -// AdaptiveFps_Sample. +// Local timer helper for the per-sub-frame cost measurement. namespace { using Clock = std::chrono::steady_clock; inline long long NsSince(Clock::time_point t0) { return std::chrono::duration_cast(Clock::now() - t0).count(); } + +// In-flight async builds of interpolated sub-frame replacement maps +std::vector> sMapBuildFutures; + +// Cost of the most recent sub-frame, and the wall time this pass may spend: +// subframes/paceFps is exactly the game time one task represents. +long long sLastSubFrameNs = 0; +long long sPassBudgetNs = 0; } // namespace void GameEngine::RunCommands(Gfx* Commands, const std::vector>& mtx_replacements, @@ -1262,35 +1272,51 @@ void GameEngine::RunCommands(Gfx* Commands, const std::vectorGetWindow(); + const auto passT0 = Clock::now(); for (size_t frameIdx = 0; frameIdx < frameCount; frameIdx++) { + if (frameIdx >= 1 && frameIdx - 1 < sMapBuildFutures.size()) { + sMapBuildFutures[frameIdx - 1].wait(); + } + // Stop once another sub-frame no longer fits in what the tick's worth + // of wall time has left. + if (frameIdx > 0 && sLastSubFrameNs > 0 && (sPassBudgetNs - NsSince(passT0)) < sLastSubFrameNs) { + break; + } const auto& m = mtx_replacements[frameIdx]; + // Vertex-animated models blend into one buffer per draw, so unlike the + // matrix maps this can't be precomputed per sub-frame. It has to land + // right before the pass that reads it. + const float subframeBlend = (frameCount > 1) ? (float)(frameIdx + 1) / (float)frameCount : 1.0f; + if (frameCount > 1) { + FrameInterpolation_ApplyAnimVertices(subframeBlend); + } + // Overlays drawn by the Gui pass below place themselves per tick, so they need the + // same blend the geometry is being posed with or they step while the world glides. + Nametag::SetSubframeBlend(subframeBlend); bool isFinalFrame = (frameIdx == frameCount - 1); - // Bypass IsFrameReady() when interpolation is active — render all - // frames per tick and let vsync pace them. if (frameCount > 1 || wndBase->IsFrameReady()) { + // Sample the full CPU cost of producing this sub-frame. + auto runT0 = Clock::now(); auto gui = wndBase->GetGui(); wndBase->GetMouseStateManager()->StartFrame(); gui->StartDraw(); interpreter->StartFrame(); - auto runT0 = Clock::now(); interpreter->Run(Commands, m); - AdaptiveFps_Sample(NsSince(runT0)); - // Emulate N64 osViBlack to prevent a flicker when the scene is drawn - // for the falling jiggy transition framebuffer capture. - if (port_isViBlack()) { + if (OS_ViBlackActive()) { interpreter->mGfxFrameBuffer = 0; auto rapi = interpreter->GetCurrentRenderingAPI(); rapi->StartDrawToFramebuffer(0, 1.0f); rapi->ClearFramebuffer(true, false); } gui->EndDraw(); + sLastSubFrameNs = NsSince(runT0); interpreter->EndFrame(); CALL_EVENT(FrameDrawEnd); } interpreter->mInterpolationIndex++; } - bool curAltAssets = CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 0); + bool curAltAssets = CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 1); if (prevAltAssets != curAltAssets) { prevAltAssets = curAltAssets; Ship::Context::GetRawInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets); @@ -1309,25 +1335,12 @@ namespace { struct SubframePacing { int subframes; // renders to emit this tick (>= 1) int fps; // target present fps for this tick + int viPerTick; // VIs of game time this tick covers }; SubframePacing ComputeSubframePacing() { int target_fps = (int)GameEngine::Instance->GetInterpolationFPS(); - // Demo/replay modes render at the native rate - const bool replayMode = func_802E4A08(); - if (!replayMode) { - if (CVarGetInteger(CVAR_SETTING("AdaptiveFPS"), 1)) { - target_fps = (int)AdaptiveFps_Cap((uint32_t)target_fps); - } - - // Some music-synced cutscenes cap interpolation at native 30 - int fpsCap = port_getInterpolationFpsCap(); - if (fpsCap > 0 && target_fps > fpsCap) { - target_fps = fpsCap; - } - } - // Game-logic VI per tick: gVIsPerFrame (=2 -> 30 Hz) normally; demo // replay and cutscene stutter raise it for slow N64 frames. int viPerTick = port_getDemoViCount(); @@ -1337,6 +1350,12 @@ SubframePacing ComputeSubframePacing() { if (viPerTick < gVIsPerFrame) { viPerTick = gVIsPerFrame; } + // time_setDeltaReal_frames() clamps the demo's recorded VI count to 15, so the + // tick never advances more than that no matter what the demo asks for. Match it + // here or a bogus recorded value would scale the sub-frame count with it. + if (viPerTick > 15) { + viPerTick = 15; + } int effective_logic_fps = 60 / viPerTick; if (effective_logic_fps < 1) { @@ -1351,18 +1370,16 @@ SubframePacing ComputeSubframePacing() { subframesPerTick = 1; } - // Replay modes never interpolate: one render per tick, held to viPerTick/60 by the floor. - if (replayMode) { - subframesPerTick = 1; - } - // paceFps drives DXGI's per-present wait so that subframes * 1/paceFps = - // viPerTick/60 wall (= game time per tick). When viPerTick == gVIsPerFrame - // and target_fps is a multiple of eff, paceFps == target_fps and stays - // constant. Otherwise it varies per tick to keep wall == game. - int fps = subframesPerTick * effective_logic_fps; + // viPerTick/60 wall (= game time per tick). Derived from viPerTick rather than + // effective_logic_fps: the latter is truncated (VI=7 -> 8, not 8.57), which would + // stretch wall time on the odd VI counts demo playback hands us every tick. + int fps = subframesPerTick * 60 / viPerTick; + if (fps < 1) { + fps = 1; + } - return { subframesPerTick, fps }; + return { subframesPerTick, fps, viPerTick }; } } // namespace @@ -1394,16 +1411,26 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { mtx_replacements.resize(subframesPerTick); } size_t activeFrames = 0; + sMapBuildFutures.clear(); for (int i = 1; i <= subframesPerTick; i++) { if (i < subframesPerTick) { float t = (float)i / (float)subframesPerTick; - FrameInterpolation_Interpolate(t, mtx_replacements[activeFrames]); + if (i == 1) { + FrameInterpolation_Interpolate(t, mtx_replacements[activeFrames]); + } else { + auto* map = &mtx_replacements[activeFrames]; + sMapBuildFutures.push_back( + std::async(std::launch::async, [t, map] { FrameInterpolation_Interpolate(t, *map); })); + } } else { mtx_replacements[activeFrames].clear(); } activeFrames++; } + // Wall time this tick is worth, straight from its VI count. + sPassBudgetNs = 1000000000LL * pacing.viPerTick / 60; + if (wnd != nullptr) { wnd->SetTargetFps(fps); // Hardcoded: CVarGetInteger crashes due to heap corruption in debug builds. @@ -1420,10 +1447,14 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { RunCommands(commands, mtx_replacements, activeFrames); - // [port] Release the demo audio hold after kDemoAudioHoldFrames rendered frames. - if (sHoldAudio.load() && --sHoldFramesRemaining <= 0) { - sHoldAudio.store(false); + // Drain any builds the render loop didn't consume (debugger path, early + // return) before the next tick's StartRecord resets the trees they read. + for (auto& f : sMapBuildFutures) { + if (f.valid()) { + f.wait(); + } } + sMapBuildFutures.clear(); } uint32_t GameEngine::GetInterpolationFPS() { diff --git a/src/port/Engine.h b/src/port/Engine.h index 477a785e9..c6e1b9a34 100644 --- a/src/port/Engine.h +++ b/src/port/Engine.h @@ -42,12 +42,7 @@ class GameEngine { GameEngine(); void StartFrame() const; static void Create(int argc, char* argv[]); - static void HandleAudioThread(); - static void StartAudioFrame(); - static void EndAudioFrame(); static void AudioInit(); - static void AudioStartThread(); - static void AudioExit(); void FinishInit(); void RunExtract(int argc, char* argv[]); // Render a GUI-only frame (no game tick). Used to keep the ImGui progress diff --git a/src/port/Enhancements/Backports/EggAim.cpp b/src/port/Enhancements/Backports/EggAim.cpp index ef977e452..4b4cf0d2a 100644 --- a/src/port/Enhancements/Backports/EggAim.cpp +++ b/src/port/Enhancements/Backports/EggAim.cpp @@ -13,12 +13,10 @@ #include "port/ShipInit.hpp" #include "EggAim.h" -extern "C" { #include "enums.h" #include "functions.h" #include "core2/commonParticle.h" #include "core2/abilityprogress.h" -} #define CVAR_NAME CVAR_ENHANCEMENT("Backports.EggAim") @@ -215,6 +213,10 @@ const uint8_t sCrosshairTextureData[32 * 32 * 4] = { int sFiring = 0; int sOverlayShown = 0; +bool canAimEggs() { + return can_egg() && player_getTransformation() == TRANSFORM_1_BANJO; +} + } // namespace void RegisterEggAimSpawn_Init() { @@ -224,7 +226,7 @@ void RegisterEggAimSpawn_Init() { } auto* ev = reinterpret_cast(event); float rotation[3]; - ncFirstPersonCamera_getZoomedInRotation(rotation); + ncba1p_getZoomedInRotation(rotation); *ev->pitch = -rotation[0]; *ev->spawnHeight = 100.0f; *ev->minVerticalVelocity = -99999.0f; @@ -243,11 +245,11 @@ void RegisterEggAim_Init() { return; } - if (!can_egg()) { + if (!canAimEggs()) { return; } - if (ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_2_IDLE) { + if (ncba1p_getState() == FIRSTPERSON_STATE_2_IDLE) { if (sOverlayShown < kOverlayFadeDuration) { sOverlayShown++; } @@ -303,7 +305,7 @@ void EggAimCrosshairWindow::Draw() { tex.ImageDataSize = sizeof(sCrosshairTextureData); tex.ImageData = new uint8_t[sizeof(sCrosshairTextureData)]; std::memcpy(tex.ImageData, sCrosshairTextureData, sizeof(sCrosshairTextureData)); - gui->LoadGuiTexture(kCrosshairTexture, tex, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); + gui->LoadGuiTexture(kCrosshairTexture, tex, "", ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); } const float t = (float)sOverlayShown / (float)kOverlayFadeDuration; // 0..1 diff --git a/src/port/Enhancements/Backports/FastSwim.cpp b/src/port/Enhancements/Backports/FastSwim.cpp index bb0d3e060..614c12c4c 100644 --- a/src/port/Enhancements/Backports/FastSwim.cpp +++ b/src/port/Enhancements/Backports/FastSwim.cpp @@ -8,9 +8,7 @@ // Include C decomp headers with C linkage before C++ headers to prevent // transitive includes from giving them C++ name mangling. -extern "C" { #include "core2/bonetransform.h" -} #include #include "port/UI/cvar_prefixes.h" diff --git a/src/port/Enhancements/Backports/Honeyback.cpp b/src/port/Enhancements/Backports/Honeyback.cpp index 1f1f41a04..3ae509d0f 100644 --- a/src/port/Enhancements/Backports/Honeyback.cpp +++ b/src/port/Enhancements/Backports/Honeyback.cpp @@ -7,11 +7,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -extern "C" { #include "enums.h" #include "functions.h" #include "gc/gctransition.h" -} #define CVAR_NAME CVAR_ENHANCEMENT("Backports.Honeyback") diff --git a/src/port/Enhancements/Backports/TooieJiggyDance.cpp b/src/port/Enhancements/Backports/TooieJiggyDance.cpp index 8846ed8c5..3c9da21e8 100644 --- a/src/port/Enhancements/Backports/TooieJiggyDance.cpp +++ b/src/port/Enhancements/Backports/TooieJiggyDance.cpp @@ -8,14 +8,14 @@ #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +#include "port/Rando/Rando.h" +#include "functions.h" extern "C" { #include "enums.h" -#include "functions.h" #include "core2/particle.h" ParticleEmitter* __fxSparkle_create(s16 position[3], f32 height, enum asset_e sprite_id); -f32 player_getYaw(void); } #define CVAR_TOOIE_JIGGY_DANCE CVAR_ENHANCEMENT("Backports.JiggyAnimation") @@ -114,7 +114,7 @@ void emitSparkle(f32 x, f32 y, f32 z) { } } -void spawnOrbit() { +extern "C" void spawnOrbit() { clearOrbit(); f32 banjo[3]; @@ -137,6 +137,8 @@ void spawnOrbit() { } actor->state = 0; actor_collisionOff(actor); + actor->unk44_2 = 1; // Keep this jiggy out of jiggylist_map_actors + actor->unk10_1 = 0; // Keep this jiggy out of map savestate sfxsource_playHighPriority(SFX_3E9_UNKNOWN); sMarker = (void*)actor->marker; } @@ -264,11 +266,15 @@ void updateOrbit() { } // namespace +// Romhacks that bundle wedarobi's jiggy dance should have it on by default. +// The hack may depend on the retained player motion that the animation provides. +static bool sJiggyDanceForced = false; + void RegisterJiggyCollect_Init() { clearOrbit(); const bool skip = CVarGetInteger(CVAR_SKIP_JIGGY_DANCE, 0); - const bool tooie = CVarGetInteger(CVAR_TOOIE_JIGGY_DANCE, 0); - const bool playOrbit = tooie && !skip; + const bool tooie = CVarGetInteger(CVAR_TOOIE_JIGGY_DANCE, 0) || sJiggyDanceForced; + const bool playOrbit = (tooie && !skip) || IS_RANDO; COND_VB_SHOULD(VB_PLAY_JIGGY_DANCE, EVENT_PRIORITY_NORMAL, skip || tooie, { *should = false; }); @@ -277,5 +283,10 @@ void RegisterJiggyCollect_Init() { COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, playOrbit, [](IEvent*) { forgetOrbit(); }); } +void TooieJiggyDance_ForceEnable() { + sJiggyDanceForced = true; + RegisterJiggyCollect_Init(); +} + static RegisterShipInitFunc initJiggyCollect(RegisterJiggyCollect_Init, - { CVAR_TOOIE_JIGGY_DANCE, CVAR_SKIP_JIGGY_DANCE }); + { CVAR_TOOIE_JIGGY_DANCE, CVAR_SKIP_JIGGY_DANCE, "IS_RANDO" }); diff --git a/src/port/Enhancements/Camera/FreeLookCamera.cpp b/src/port/Enhancements/Camera/FreeLookCamera.cpp index 46381bd59..a4b51e96f 100644 --- a/src/port/Enhancements/Camera/FreeLookCamera.cpp +++ b/src/port/Enhancements/Camera/FreeLookCamera.cpp @@ -1,21 +1,49 @@ +// Free look camera + +#include + #include #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Camera/FreeLookCamera.h" -#include "port/Enhancements/Camera/OrbitCameraCore.h" -// Vanilla camera / input entry points (decomp C API). extern "C" { -int ncDynamicCamera_getState(void); +// Math helpers +void func_80256E24(float dst[3], float pitch, float yaw, float x, float y, float z); +void ml_vec3f_add(float dst[3], float a[3], float b[3]); +void ml_vec3f_clear(float dst[3]); +float mlNormalizeAngle(float deg); float time_getDelta(void); -float gu_sqrtf(float x); void controller_getRightStick(int controller_index, float dst[2]); int bainput_should_rotate_camera_left(void); int bainput_should_rotate_camera_right(void); int bainput_should_look_first_person_camera(void); + +int ncDynamicCamera_getState(void); +void ncDynamicCamera_setState(int state); +void ncDynamicCamera_getPosition(float dst[3]); +void ncDynamicCamera_setRotation(float src[3]); + +// Vanilla follow-camera machinery +extern float D_8037DB70; // dynamicCamB.c: orbit yaw, degrees +extern float D_8037D9C8[3]; // dynamicCamera.c: rotation spring velocity + +void func_802C0150(int mode); // select the focus target +void func_802C0370(void); // record the pre-move position (anti-flip guard) +void func_802C0394(float target[3]); // record the ideal target (anti-flip guard) +void func_802C03BC(void); // undo a collision resolve that crossed over +void func_802C0490(float dst[3]); // focus/orbit center +void func_802C04B0(void); // re-derive D_8037DB70 from the live camera + +float func_802BD8D4(void); // target orbit distance (zoom level) +void func_802BE190(float target[3]); // position spring toward target +void func_802BE230(float gain, float damp); // position spring tuning +int func_802BE60C(void); // swept camera collision + slide +int func_802BC84C(int mode); // occluded-too-long recovery +void func_802BE6FC(float rotOut[3], float focus[3]); // look-at from the live position } namespace { @@ -26,50 +54,90 @@ namespace { #define CVAR_FREELOOK_INVERT_Y CVAR_ENHANCEMENT("Camera.FreeLook.InvertY") #define CVAR_FREELOOK_SMOOTH_RATE CVAR_ENHANCEMENT("Camera.FreeLook.SmoothRate") -// Tuning -constexpr float deadzone = 0.15f; -constexpr float enterThreshold = 0.30f; -constexpr float horizontalSpeed = 160.0f; -constexpr float verticalSpeed = 100.0f; +constexpr float kDeadzone = 0.15f; +constexpr float kEnterThreshold = 0.30f; +constexpr float kYawSpeed = 160.0f; +constexpr float kPitchSpeed = 100.0f; -constexpr float minPitch = -85.0f; // high overhead, looking down -constexpr float maxPitch = 40.0f; // low, looking up at the player +constexpr float kMinPitch = -85.0f; +constexpr float kMaxPitch = 40.0f; -// position smoothing rate (1/sec); higher = snappier -constexpr float defaultSmoothRate = 40.0f; +constexpr float kAimHeightRate = 8.0f; +constexpr float kDefaultSmooth = 40.0f; +constexpr float kSmoothToGain = 0.5f; +constexpr float kDampRatio = 4.0f; -// Pitch-enabled orbit on the shared core. Distance tracks the vanilla zoom level -// (same as the modern-scheme camera) so the normal follow distances are honored. -OrbitCamera sFreeLook = { /*stateId*/ FREELOOK_CAM_STATE, /*allowPitch*/ 1, - /*minPitch*/ minPitch, /*maxPitch*/ maxPitch, /*smoothRate*/ defaultSmoothRate }; +constexpr float kRadToDeg = 57.29577951308232f; -// Right stick with a radial deadzone, rescaled so motion ramps from 0 at the -// deadzone edge to 1 at full deflection. -float readStick(float out[2]) { +bool sActive = false; +bool sAimValid = false; +float sPitch = 0.0f; +float sAimY = 0.0f; + +float clampf(float v, float lo, float hi) { + return v < lo ? lo : (v > hi ? hi : v); +} + +float SpringGain() { + return CVarGetFloat(CVAR_FREELOOK_SMOOTH_RATE, kDefaultSmooth) * kSmoothToGain; +} + +float ReadStick(float out[2]) { controller_getRightStick(0, out); - float mag = gu_sqrtf(out[0] * out[0] + out[1] * out[1]); - if (mag < deadzone) { + float mag = std::sqrt(out[0] * out[0] + out[1] * out[1]); + if (mag < kDeadzone) { out[0] = out[1] = 0.0f; return 0.0f; } if (mag > 1.0f) { mag = 1.0f; } - float scaled = (mag - deadzone) / (1.0f - deadzone); + float scaled = (mag - kDeadzone) / (1.0f - kDeadzone); float k = scaled / mag; out[0] *= k; out[1] *= k; return scaled; } -// Explicit camera commands hand the frame back to the normal camera. Zoom is not -// one of them: it adjusts the vanilla zoom level, which free look tracks, so the -// player can re-zoom without dropping out of free look. -bool cButtonCameraControl() { +bool ManualCameraControl() { return bainput_should_rotate_camera_left() || bainput_should_rotate_camera_right() || bainput_should_look_first_person_camera(); } +float CapturePitch() { + float camPos[3]; + float focus[3]; + ncDynamicCamera_getPosition(camPos); + func_802C0490(focus); + + float diff[3] = { camPos[0] - focus[0], camPos[1] - focus[1], camPos[2] - focus[2] }; + float dist = std::sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); + if (dist < 1.0f) { + return 0.0f; + } + return clampf(std::asin(clampf(-diff[1] / dist, -1.0f, 1.0f)) * kRadToDeg, kMinPitch, kMaxPitch); +} + +void EnterOrbit() { + func_802C0150(2); + func_802BE230(SpringGain(), SpringGain() * kDampRatio); + func_802C04B0(); + sPitch = CapturePitch(); + + ml_vec3f_clear(D_8037D9C8); + + sAimValid = false; + sActive = true; + ncDynamicCamera_setState(FREELOOK_CAM_STATE); +} + +void ExitOrbit() { + sActive = false; + if (ncDynamicCamera_getState() == FREELOOK_CAM_STATE) { + ncDynamicCamera_setState(0xB); + } +} + } // namespace extern "C" int port_freeLook_isEnabled(void) { @@ -78,38 +146,37 @@ extern "C" int port_freeLook_isEnabled(void) { extern "C" int port_freeLook_handle(void) { if (!port_freeLook_isEnabled()) { - if (sFreeLook.active) { - OrbitCamera_Exit(&sFreeLook); + if (sActive) { + ExitOrbit(); } return 0; } int state = ncDynamicCamera_getState(); - if (sFreeLook.active) { + if (sActive) { if (state != FREELOOK_CAM_STATE) { - sFreeLook.active = 0; + sActive = false; return 0; } - if (cButtonCameraControl()) { - OrbitCamera_Exit(&sFreeLook); + if (ManualCameraControl()) { + ExitOrbit(); return 0; } - return 1; // hold the angle; consume the frame + return 1; } - if (cButtonCameraControl()) { + if (ManualCameraControl()) { return 0; } - // Only enter from a normal follow/orbit camera. if (state != 0xB && state != 0x1 && state != 0xA) { return 0; } float stick[2]; - if (readStick(stick) >= enterThreshold) { - OrbitCamera_Enter(&sFreeLook); + if (ReadStick(stick) >= kEnterThreshold) { + EnterOrbit(); return 1; } @@ -118,23 +185,47 @@ extern "C" int port_freeLook_handle(void) { extern "C" void port_freeLookCamera_update(void) { float dt = time_getDelta(); - sFreeLook.smoothRate = CVarGetFloat(CVAR_FREELOOK_SMOOTH_RATE, defaultSmoothRate); - - float yawDelta = 0.0f; - float pitchDelta = 0.0f; - if (!sFreeLook.justEntered) { - float stick[2]; - readStick(stick); - - float yawSens = CVarGetFloat(CVAR_FREELOOK_YAW_SENS, 1.0f); - float pitchSens = CVarGetFloat(CVAR_FREELOOK_PITCH_SENS, 1.0f); - bool invertX = CVarGetInteger(CVAR_FREELOOK_INVERT_X, 0) != 0; - bool invertY = CVarGetInteger(CVAR_FREELOOK_INVERT_Y, 0) != 0; - - yawDelta = (invertX ? -stick[0] : stick[0]) * horizontalSpeed * yawSens * dt; - // Default: push up -> camera rises and looks down (overhead). InvertY flips it. - pitchDelta = (invertY ? stick[1] : -stick[1]) * verticalSpeed * pitchSens * dt; + + float stick[2]; + ReadStick(stick); + + float yawSens = CVarGetFloat(CVAR_FREELOOK_YAW_SENS, 1.0f); + float pitchSens = CVarGetFloat(CVAR_FREELOOK_PITCH_SENS, 1.0f); + bool invertX = CVarGetInteger(CVAR_FREELOOK_INVERT_X, 0) != 0; + bool invertY = CVarGetInteger(CVAR_FREELOOK_INVERT_Y, 0) != 0; + + D_8037DB70 = mlNormalizeAngle(D_8037DB70 + (invertX ? -stick[0] : stick[0]) * kYawSpeed * yawSens * dt); + sPitch = clampf(sPitch + (invertY ? stick[1] : -stick[1]) * kPitchSpeed * pitchSens * dt, kMinPitch, kMaxPitch); + + float focus[3]; + float offset[3]; + float target[3]; + + func_802C0370(); + func_802C0490(focus); + func_80256E24(offset, sPitch, D_8037DB70, 0.0f, 0.0f, func_802BD8D4()); + ml_vec3f_add(target, focus, offset); + + func_802C0394(target); + func_802BE190(target); + + if (func_802BE60C()) { + if (!func_802BC84C(1)) { + func_802C03BC(); + } + func_802C04B0(); + } + + func_802C0490(focus); + if (!sAimValid) { + sAimY = focus[1]; + sAimValid = true; + } else { + sAimY += (focus[1] - sAimY) * clampf(kAimHeightRate * dt, 0.0f, 1.0f); } + focus[1] = sAimY; - OrbitCamera_Update(&sFreeLook, yawDelta, pitchDelta); + float rot[3]; + func_802BE6FC(rot, focus); + ncDynamicCamera_setRotation(rot); } diff --git a/src/port/Enhancements/Camera/OrbitCameraCore.cpp b/src/port/Enhancements/Camera/OrbitCameraCore.cpp deleted file mode 100644 index 3ca4e8d3d..000000000 --- a/src/port/Enhancements/Camera/OrbitCameraCore.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// Shared right-stick orbit camera core. See OrbitCameraCore.h. - -#include "port/Enhancements/Camera/OrbitCameraCore.h" - -extern "C" { -// Vanilla camera / math entry points used to drive the orbit state. -void ncDynamicCamera_getPosition(float dst[3]); -void ncDynamicCamera_setPosition(float src[3]); -void ncDynamicCamera_setRotation(float src[3]); -int ncDynamicCamera_getState(void); -void ncDynamicCamera_setState(int state); - -void func_802C02D4(float center[3]); // camera focus/orbit center -void func_80256E24(float dst[3], float pitch, float yaw, float x, float y, float z); // spherical -> offset -int func_8025801C(float vec[3], float* yaw); // vector -> yaw (degrees) -void func_802BC434(float rotOut[3], float fromPos[3], float targetPos[3]); // look-at rotation -int func_802BE60C(void); // swept camera collision + slide -float func_802BD8D4(void); // target orbit distance (zoom level) -float func_802BD51C(void); // target camera height - -float ml_acosf(float x); -float mlNormalizeAngle(float deg); -float gu_sqrtf(float x); -float time_getDelta(void); -} - -namespace { - -// 1/sec; how fast distance chases the zoom-level target. -constexpr float kDistanceRate = 8.0f; -// 1/sec; vertical follow (flat-pitch mode only). Matched to the vanilla camera, -// whose Y lerp is target*dt*2, so the camera stays mostly put during a jump -// (Banjo rises in frame) instead of choppily chasing the parabola up and down. -constexpr float kHeightRate = 2.0f; -// 1/sec; how fast the look-at target's Y chases its raw value. The orbit center -// Y is derived from the floor height under the player, which snaps up in discrete -// steps on stairs; smoothing it de-steps the aim pitch the way the vanilla camera's -// rotation tracker (func_802BD904) does, without adding lag to the stick-driven yaw. -constexpr float kAimHeightRate = 8.0f; - -float clampf(float v, float lo, float hi) { - return v < lo ? lo : (v > hi ? hi : v); -} - -} // namespace - -extern "C" void OrbitCamera_Capture(OrbitCamera* c) { - float camPos[3]; - float center[3]; - ncDynamicCamera_getPosition(camPos); - func_802C02D4(center); - - float diff[3] = { camPos[0] - center[0], camPos[1] - center[1], camPos[2] - center[2] }; - - c->yaw = 0.0f; - func_8025801C(diff, &c->yaw); - - if (c->allowPitch) { - float dist = gu_sqrtf(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); - c->distance = dist; - float sinPitch = clampf(-diff[1] / dist, -1.0f, 1.0f); - float pitchMag = ml_acosf(sinPitch); - c->pitch = clampf(sinPitch < 0.0f ? -pitchMag : pitchMag, c->minPitch, c->maxPitch); - } else { - c->distance = gu_sqrtf(diff[0] * diff[0] + diff[2] * diff[2]); - c->height = camPos[1]; - c->pitch = 0.0f; - } - - c->justEntered = 1; - c->smoothValid = 0; - c->aimValid = 0; -} - -extern "C" void OrbitCamera_Enter(OrbitCamera* c) { - OrbitCamera_Capture(c); - c->active = 1; - ncDynamicCamera_setState(c->stateId); -} - -extern "C" void OrbitCamera_Exit(OrbitCamera* c) { - c->active = 0; - if (ncDynamicCamera_getState() == c->stateId) { - ncDynamicCamera_setState(0xB); // hand back to the normal follow camera - } -} - -extern "C" void OrbitCamera_Update(OrbitCamera* c, float yawDelta, float pitchDelta) { - float dt = time_getDelta(); - float center[3]; - func_802C02D4(center); - - c->yaw = mlNormalizeAngle(c->yaw + yawDelta); - if (c->allowPitch) { - c->pitch = clampf(c->pitch + pitchDelta, c->minPitch, c->maxPitch); - } - c->justEntered = 0; - - // Track the vanilla zoom-level distance so the normal zoom controls still take - // effect while orbiting. - float distTrack = clampf(kDistanceRate * dt, 0.0f, 1.0f); - c->distance += (func_802BD8D4() - c->distance) * distTrack; - - float offset[3]; - func_80256E24(offset, c->allowPitch ? c->pitch : 0.0f, c->yaw, 0.0f, 0.0f, c->distance); - - float pos[3]; - pos[0] = center[0] + offset[0]; - pos[2] = center[2] + offset[2]; - if (c->allowPitch) { - // Pitch carries the vertical offset. - pos[1] = center[1] + offset[1]; - } else { - // Flat orbit: height follows the vanilla target, more slowly than distance - // so jumps read as natural rather than choppy. - float heightTrack = clampf(kHeightRate * dt, 0.0f, 1.0f); - c->height += (func_802BD51C() - c->height) * heightTrack; - pos[1] = c->height; - } - ncDynamicCamera_setPosition(pos); - - // Resolve geometry. - func_802BE60C(); - - float resolved[3]; - ncDynamicCamera_getPosition(resolved); - - if (!c->smoothValid) { - c->smoothPos[0] = resolved[0]; - c->smoothPos[1] = resolved[1]; - c->smoothPos[2] = resolved[2]; - c->smoothValid = 1; - } else { - // Smooth the resolved position to prevent hitching on edges. - float f = clampf(c->smoothRate * dt, 0.0f, 1.0f); - c->smoothPos[0] += (resolved[0] - c->smoothPos[0]) * f; - c->smoothPos[1] += (resolved[1] - c->smoothPos[1]) * f; - c->smoothPos[2] += (resolved[2] - c->smoothPos[2]) * f; - } - ncDynamicCamera_setPosition(c->smoothPos); - - // Aim back at the player from the smoothed position. Smooth only the target's - // Y: the orbit center Y steps with the floor height under the player. - // X/Z follow the player directly so horizontal aim stays responsive. - if (!c->aimValid) { - c->aimCenterY = center[1]; - c->aimValid = 1; - } else { - float aimTrack = clampf(kAimHeightRate * dt, 0.0f, 1.0f); - c->aimCenterY += (center[1] - c->aimCenterY) * aimTrack; - } - float aimCenter[3] = { center[0], c->aimCenterY, center[2] }; - - float rot[3]; - func_802BC434(rot, aimCenter, c->smoothPos); - ncDynamicCamera_setRotation(rot); -} diff --git a/src/port/Enhancements/Camera/OrbitCameraCore.h b/src/port/Enhancements/Camera/OrbitCameraCore.h deleted file mode 100644 index ba10397dc..000000000 --- a/src/port/Enhancements/Camera/OrbitCameraCore.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef PORT_ORBIT_CAMERA_CORE_H -#define PORT_ORBIT_CAMERA_CORE_H - -// Shared right-stick orbit camera core. -// -// Both the modern control scheme's yaw orbit and the Free Look enhancement are -// configurations of the same machinery: capture the current camera, drive yaw -// (and optionally pitch) from the right stick, track the vanilla zoom-level -// distance, resolve geometry collision, smooth, and aim back at the player. -// -// The two only differ in policy (when to enter/hold/hand back, how the stick is -// read, whether pitch is live) and in a couple of tuning values. Each owns an -// OrbitCamera instance and supplies those via the config fields below; the core -// owns the per-frame math so the behavior stays identical between them. - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - // // Config (set by the owner) - int stateId; // dynamic camera state this orbit runs as - int allowPitch; // 1: stick Y drives pitch and feeds the vertical offset. - // 0: pitch is locked flat and height tracks the vanilla target. - float minPitch; // pitch clamp, degrees (only used when allowPitch) - float maxPitch; - float smoothRate; // position smoothing rate, 1/sec - - // Runtime state - int active; - int justEntered; - int smoothValid; - int aimValid; // aimCenterY has been seeded - float yaw; - float pitch; - float distance; // spherical radius; tracks the vanilla zoom-level target - float height; // absolute Y, only used when !allowPitch - float aimCenterY; // smoothed Y of the look-at target (de-steps stairs) - float smoothPos[3]; -} OrbitCamera; - -// Seed yaw/pitch/distance(/height) from wherever the live camera currently sits, -// so the orbit starts without a jump. -void OrbitCamera_Capture(OrbitCamera* c); - -// Capture and take ownership of the camera state. -void OrbitCamera_Enter(OrbitCamera* c); - -// Release the camera state back to the normal follow camera (state 0xB). -void OrbitCamera_Exit(OrbitCamera* c); - -// Advance one frame. -void OrbitCamera_Update(OrbitCamera* c, float yawDelta, float pitchDelta); - -#ifdef __cplusplus -} -#endif - -#endif // PORT_ORBIT_CAMERA_CORE_H diff --git a/src/port/Enhancements/Cheats/Cheats.cpp b/src/port/Enhancements/Cheats/Cheats.cpp index 2de8b7d81..178e3faa8 100644 --- a/src/port/Enhancements/Cheats/Cheats.cpp +++ b/src/port/Enhancements/Cheats/Cheats.cpp @@ -5,20 +5,16 @@ #include #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/RomhackConfig.h" #include "port/ShipInit.hpp" #include "port/ShipUtils.h" -extern "C" { #include "enums.h" #include "core2/statetimer.h" +#include "core2/ba/physics.h" #include "bs_funcs.h" #include "functions.h" -s32 port_getRomhackMaxEggs(void); -s32 port_getRomhackMaxGoldFeathers(void); -s32 port_getRomhackMaxRedFeathers(void); -} - // ============================================================================ // CVAR DEFINITIONS // ============================================================================ @@ -141,7 +137,7 @@ void RegisterTalonTrotCycle_Init() { // D-pad cycling - only works while Talon Trot is active if (bakey_pressed(BUTTON_D_RIGHT) || bakey_pressed(BUTTON_D_LEFT)) { s32 currentState = bs_getState(); - bool inTalonTrot = bsbtrot_inSet((enum bs_e)currentState) || bslongleg_inSet(0); // Also in longleg state + bool inTalonTrot = bsbtrot_inSet(currentState) || bslongleg_inSet(currentState); if (inTalonTrot) { bool inBoots = stateTimer_isActive(STATE_TIMER_2_LONGLEG); @@ -184,23 +180,28 @@ void RegisterTalonTrotCycle_Init() { // MOVEMENT CHEATS // ============================================================================ -// Levitate — Hold L to float upward with gravity disabled +// Levitate — Hold L to float straight up; tapping L out of a damaging fall cancels the fall. void RegisterLevitate_Init() { + static const f32 LEVITATE_VELOCITY = 500.0f; static bool levitateActive = false; COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_LEVITATE, 0), [](IEvent* event) { - if (bakey_held(BUTTON_L)) { + // Suspend levitation while dialog is up. + // Cancel fall damage and the tumble/splat animation if pressed mid-fall. + if (bakey_held(BUTTON_L) && !gcdialog_hasCurrentTextId()) { + if (bakey_pressed(BUTTON_L) && !player_isStable()) { + s32 fallDamage = 0; + if (bafalldamage_get_damage(&fallDamage) != 0) { + bafalldamage_start(); + bs_setState(BS_1_IDLE); + } + } baphysics_set_gravity(0.0f); - f32 pos[3]; - player_getPosition(pos); - pos[1] += 20.0f; - player_setPosition(pos); + baphysics_set_vertical_velocity(LEVITATE_VELOCITY); levitateActive = true; - } else { - // Only reset gravity once when L is released, not every frame - if (levitateActive) { - baphysics_reset_gravity(); - levitateActive = false; - } + } else if (levitateActive) { + // Only reset gravity once when L is released, not every frame. + baphysics_reset_gravity(); + levitateActive = false; } }); } @@ -209,9 +210,14 @@ void RegisterLevitate_Init() { // TRANSFORMATION CHEATS // ============================================================================ +static const s32 BAANIM_WISHYWASHY = 0x80; +static bool isWishyWashyUnlocked() { + return (baanim_getActiveBottlesBonusMask() & BAANIM_WISHYWASHY) != 0; +} + // Transformation cycling with D-pad Up/Down -// D-pad Up: Cycle forward through transformations (Banjo -> Mumbo -> Termite -> ... -> Wishy -> Banjo) -// D-pad Down: Cycle backward through transformations (Banjo -> Wishy -> ... -> Termite -> Mumbo -> Banjo) +// D-pad Up: Cycle forward through transformations (Banjo -> Termite -> ... -> Bee -> [Wishy] -> Banjo) +// D-pad Down: Cycle backward through transformations (Banjo -> [Wishy] -> Bee -> ... -> Termite -> Banjo) void RegisterCycleTransform_Init() { COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_CYCLE_TRANSFORM, 0), [](IEvent* event) { s32 currentTransform = (s32)player_getTransformation(); @@ -222,7 +228,10 @@ void RegisterCycleTransform_Init() { if (currentTransform > TRANSFORM_7_WISHWASHY) { currentTransform = TRANSFORM_1_BANJO; } - func_8028FB88((enum transformation_e)currentTransform); + if (currentTransform == TRANSFORM_7_WISHWASHY && !isWishyWashyUnlocked()) { + currentTransform = TRANSFORM_1_BANJO; // skip Wishy Washy -> wrap to Banjo + } + player_transform((enum transformation_e)currentTransform); } // D-pad Down: Cycle backward through transformations else if (bakey_pressed(BUTTON_D_DOWN)) { @@ -230,11 +239,56 @@ void RegisterCycleTransform_Init() { if (currentTransform < TRANSFORM_1_BANJO) { currentTransform = TRANSFORM_7_WISHWASHY; } - func_8028FB88((enum transformation_e)currentTransform); + if (currentTransform == TRANSFORM_7_WISHWASHY && !isWishyWashyUnlocked()) { + currentTransform = TRANSFORM_6_BEE; // skip Wishy Washy -> step to Bee + } + player_transform((enum transformation_e)currentTransform); } }); } +// Copies of chMumbo_update state 5's 0.01 and 0.999 beats minus the audio; keep in step with it. +extern "C" { +void chMumbo_func_802D1B8C(Actor* actor, enum transformation_e transform_id); +extern u8 D_8037DDF0; // the transformation this hut offers +} + +static bool sMumboFastXformStarted = false; + +static bool FastTransform_startHutTransform(Actor* actor) { + if (actor->has_met_before || (actor->unk10_12 == 0 && (s32)player_getTransformation() != TRANSFORM_1_BANJO && + (s32)player_getTransformation() != romhack_mumboWishwashyId())) { + return romhack_mumboTransform(TRANSFORM_1_BANJO); + } + if (romhack_mumboTransform(D_8037DDF0)) { + if (D_8037DDF0 != romhack_mumboWishwashyId()) { + enum file_progress_e paidFlag = + (enum file_progress_e)((D_8037DDF0 - TRANSFORM_2_TERMITE) + FILEPROG_90_PAID_TERMITE_COST); + if (fileProgressFlag_getAndSet(paidFlag, true)) { + actor->velocity[0] = 1.0f; + } + actor->unk38_31 = 0; + } + if (actor->unk10_12 == 1) { + actor->unk10_12 = 0; + } + return true; + } + return false; +} + +// No has_met_before branch: those sequences are left to vanilla below. +static void FastTransform_endHutTransform(Actor* actor) { + func_8028F918(0); // pops the look-at lock state 4 pushed + if ((s32)player_getTransformation() != TRANSFORM_1_BANJO) { + subaddie_set_state(actor, 3); + chMumbo_func_802D1B8C(actor, (enum transformation_e)D_8037DDF0); + return; + } + gcpausemenu_80314AC8(1); + subaddie_set_state(actor, 4); +} + // Fast Transformation — speeds up Mumbo transformation animation by 3x void RegisterFastTransform_Init() { COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), [](IEvent* event) { @@ -248,6 +302,27 @@ void RegisterFastTransform_Init() { } } }); + + // Hut transforms ignore that timer; Mumbo's state 5 paces off his own 7.5s animation instead. + COND_VB_SHOULD(VB_MUMBO_HUT_TRANSFORM_CUTSCENE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), { + Actor* actor = va_arg(args, Actor*); + // T-Rex/mistake gags end in a dialog wired to a callback private to mumbo.c. + if (actor != nullptr && !actor->has_met_before) { + // Only latch once the spell has been accepted. Gags don't count as valid. + if (!sMumboFastXformStarted) { + sMumboFastXformStarted = FastTransform_startHutTransform(actor); + } else if (!baflag_isTrue(BA_FLAG_1B_TRANSFORMING)) { + // Safe to read as "the transformation ended" only because of the latch above. + sMumboFastXformStarted = false; + FastTransform_endHutTransform(actor); + } + *should = false; + } + }); + + // A map torn down mid-transform would leave the next one thinking it had already run. + COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), + [](IEvent* event) { sMumboFastXformStarted = false; }); } // ============================================================================ @@ -256,12 +331,8 @@ void RegisterFastTransform_Init() { // Disable Mumbo untransform when going too far void RegisterNoMumboUntransform_Init() { - COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_MUMBO_UNTRANSFORM, 0), [](IEvent* event) { - // Prevent Mumbo from triggering untransform dialog/warn - // These functions check game state and show dialog - // We disable them by setting a flag they check - volatileFlag_set((enum volatile_flags_e)207, 1); // Prevents detransform warning - }); + COND_VB_SHOULD(VB_MUMBO_DETRANSFORM, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_MUMBO_UNTRANSFORM, 0), + { *should = false; }); } // ============================================================================ diff --git a/src/port/Enhancements/Cosmetics/PlayerColors.cpp b/src/port/Enhancements/Cosmetics/PlayerColors.cpp new file mode 100644 index 000000000..e625e0971 --- /dev/null +++ b/src/port/Enhancements/Cosmetics/PlayerColors.cpp @@ -0,0 +1,480 @@ +#include "PlayerColors.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "port/UI/cvar_prefixes.h" + +extern "C" { +#include "model.h" +#include "enums.h" +#include "core2/modelRender.h" +s32 port_anchor_isConnected(void); +} + +namespace { + +// --------------------------------------------------------------------------- +// Part tables +// +// Derived from the two player model bins: every CI4 texture and every distinct +// vertex colour was attributed to a bone (via the geo layout) and to a body +// region, then grouped by part. Textures are listed per model because the +// low- and high-poly bins have different texture counts and orderings. +// --------------------------------------------------------------------------- + +struct ChannelInfo { + u8 vanilla[3]; + float minSaturation; + float minHueDeg, maxHueDeg; +}; + +const ChannelInfo kChannels[] = { + /* BANJO_FUR */ { { 0x83, 0x32, 0x03 }, 0.50f, 5.0f, 50.0f }, + /* BANJO_SHORTS */ { { 0xFF, 0xF6, 0x20 }, 0.50f, 0.0f, 70.0f }, + /* KAZOOIE_FEATHERS */ { { 0xF6, 0x10, 0x00 }, 0.50f, 0.0f, 70.0f }, + /* KAZOOIE_BEAK */ { { 0xFE, 0xA1, 0x31 }, 0.12f, 0.0f, 70.0f }, + /* BANJO_BACKPACK */ { { 0x00, 0x4A, 0xE0 }, 0.35f, 190.0f, 250.0f }, + /* BANJO_SKIN */ { { 0xEB, 0x83, 0x6D }, 0.15f, 0.0f, 60.0f }, +}; + +struct TextureTable { + const s16* index; + s32 count; +}; + +// ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY +const s16 kLowFur[] = { 12, 13, 15, 18 }; +const s16 kLowShorts[] = { 5, 6 }; +const s16 kLowFeathers[] = { 14 }; +const s16 kLowBeak[] = { 19, 20 }; +const s16 kLowSkin[] = { 2, 7 }; + +// ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY +const s16 kHighFur[] = { 13, 14, 16, 19 }; +const s16 kHighShorts[] = { 6, 7 }; +const s16 kHighFeathers[] = { 15 }; +const s16 kHighBeak[] = { 20, 21 }; +const s16 kHighSkin[] = { 3, 8 }; + +#define TEXTABLE(array) \ + { array, (s32)(sizeof(array) / sizeof((array)[0])) } + +// The backpack is shaded entirely by vertex colour. The only blue palettes in +// the model belong to the eyes and Banjo's claws, which must stay put. +const TextureTable kLowTextures[] = { TEXTABLE(kLowFur), TEXTABLE(kLowShorts), TEXTABLE(kLowFeathers), + TEXTABLE(kLowBeak), { nullptr, 0 }, TEXTABLE(kLowSkin) }; +const TextureTable kHighTextures[] = { TEXTABLE(kHighFur), TEXTABLE(kHighShorts), TEXTABLE(kHighFeathers), + TEXTABLE(kHighBeak), { nullptr, 0 }, TEXTABLE(kHighSkin) }; + +#undef TEXTABLE + +const u32 kFurVerts[] = { 0xFA6F12, 0xCC560B, 0xAE4707, 0x833203, 0x632501, 0x411700, 0x270E00 }; +const u32 kShortsVerts[] = { 0xFFFF28, 0xEAEA00, 0xF6B400, 0xCE8700, 0xBA5500, 0x874708 }; +const u32 kFeatherVerts[] = { 0xFF3300, 0xD00000, 0x880000, 0x520000, 0xFF5F00, 0xFF8900 }; +const u32 kBeakVerts[] = { 0xFFFF9F, 0xFFCF3D, 0xFFC700, 0xFEA131, 0xBA7F4B, 0x923900, 0xC74700, 0x662300 }; +const u32 kBackpackVerts[] = { 0x7FA9FF, 0x558DFF, 0x2B71FF, 0x004AE0, 0x003092, 0x002268, 0x001A4E }; +const u32 kSkinVerts[] = { 0xFFEAB4, 0xFFBE97, 0xFFA385, 0xEB836D, 0xC66E5C, 0x995447, 0x66372F, 0x45251F }; + +struct VertexTable { + const u32* color; + s32 count; +}; + +#define VTXTABLE(array) \ + { array, (s32)(sizeof(array) / sizeof((array)[0])) } +const VertexTable kVertexTables[] = { VTXTABLE(kFurVerts), VTXTABLE(kShortsVerts), VTXTABLE(kFeatherVerts), + VTXTABLE(kBeakVerts), VTXTABLE(kBackpackVerts), VTXTABLE(kSkinVerts) }; +#undef VTXTABLE + +// --------------------------------------------------------------------------- +// Color math +// --------------------------------------------------------------------------- + +struct Hsv { + float hue; // degrees, 0..360 + float saturation, value; +}; + +Hsv ToHsv(float red, float green, float blue) { + const float maxComponent = std::max({ red, green, blue }); + const float minComponent = std::min({ red, green, blue }); + const float chroma = maxComponent - minComponent; + Hsv hsv{ 0.0f, maxComponent > 0.0f ? chroma / maxComponent : 0.0f, maxComponent }; + if (chroma > 0.0f) { + if (maxComponent == red) { + hsv.hue = 60.0f * std::fmod((green - blue) / chroma, 6.0f); + } else if (maxComponent == green) { + hsv.hue = 60.0f * (((blue - red) / chroma) + 2.0f); + } else { + hsv.hue = 60.0f * (((red - green) / chroma) + 4.0f); + } + if (hsv.hue < 0.0f) { + hsv.hue += 360.0f; + } + } + return hsv; +} + +void FromHsv(const Hsv& hsv, float* red, float* green, float* blue) { + const float chroma = hsv.value * hsv.saturation; + const float sector = std::fmod(std::fmod(hsv.hue, 360.0f) + 360.0f, 360.0f) / 60.0f; + const float ramp = chroma * (1.0f - std::fabs(std::fmod(sector, 2.0f) - 1.0f)); + float highest = 0.0f, middle = 0.0f, lowest = 0.0f; + switch ((int)sector) { + case 0: + highest = chroma; + middle = ramp; + break; + case 1: + highest = ramp; + middle = chroma; + break; + case 2: + middle = chroma; + lowest = ramp; + break; + case 3: + middle = ramp; + lowest = chroma; + break; + case 4: + highest = ramp; + lowest = chroma; + break; + default: + highest = chroma; + lowest = ramp; + break; + } + const float offset = hsv.value - chroma; + *red = highest + offset; + *green = middle + offset; + *blue = lowest + offset; +} + +float Clamp01(float value) { + return value < 0.0f ? 0.0f : (value > 1.0f ? 1.0f : value); +} + +// Re-tints one source colour so the channel's vanilla colour lands exactly on `target` and +// every other shade of the part keeps its position in the shading ramp. +void Recolor(const ChannelInfo& channel, const BKColorChannelSetting& target, u8 sourceRed, u8 sourceGreen, + u8 sourceBlue, u8* outRed, u8* outGreen, u8* outBlue) { + const Hsv source = ToHsv(sourceRed / 255.0f, sourceGreen / 255.0f, sourceBlue / 255.0f); + const Hsv vanilla = ToHsv(channel.vanilla[0] / 255.0f, channel.vanilla[1] / 255.0f, channel.vanilla[2] / 255.0f); + const Hsv chosen = ToHsv(target.r / 255.0f, target.g / 255.0f, target.b / 255.0f); + + float hueOffset = source.hue - vanilla.hue; + while (hueOffset > 180.0f) { + hueOffset -= 360.0f; + } + while (hueOffset < -180.0f) { + hueOffset += 360.0f; + } + const float rampPosition = std::min(std::fabs(hueOffset), 45.0f) / 45.0f; + + Hsv result; + result.hue = chosen.hue + (hueOffset < 0.0f ? -1.0f : 1.0f) * rampPosition * 8.0f; + result.saturation = + vanilla.saturation > 0.001f ? chosen.saturation * (source.saturation / vanilla.saturation) : chosen.saturation; + result.value = vanilla.value > 0.001f ? chosen.value * (source.value / vanilla.value) : chosen.value; + result.saturation = Clamp01(result.saturation * (1.0f - 0.55f * rampPosition)); + result.value = Clamp01(result.value * (1.0f + 0.55f * rampPosition)); + + float red, green, blue; + FromHsv(result, &red, &green, &blue); + *outRed = (u8)std::lround(Clamp01(red) * 255.0f); + *outGreen = (u8)std::lround(Clamp01(green) * 255.0f); + *outBlue = (u8)std::lround(Clamp01(blue) * 255.0f); +} + +bool PassesFilter(const ChannelInfo& channel, u8 red, u8 green, u8 blue) { + const Hsv hsv = ToHsv(red / 255.0f, green / 255.0f, blue / 255.0f); + if (hsv.value <= 0.0f || hsv.saturation < channel.minSaturation) { + return false; + } + return hsv.hue >= channel.minHueDeg && hsv.hue <= channel.maxHueDeg; +} + +// --------------------------------------------------------------------------- +// Per-owner recolored copies +// --------------------------------------------------------------------------- + +constexpr size_t kPaletteArenaWords = 128 * 1024; // 1 MiB + +void* PaletteArenaTake(size_t bytes) { + static std::unique_ptr arena; + static size_t usedWords = 0; + + const size_t wordCount = (bytes + 7) / 8; + if (wordCount > kPaletteArenaWords) { + return nullptr; + } + if (arena == nullptr) { + arena = std::make_unique(kPaletteArenaWords); + } + if (usedWords + wordCount > kPaletteArenaWords) { + usedWords = 0; + } + u64* region = arena.get() + usedWords; + usedWords += wordCount; + return region; +} + +struct Variant { + const void* sourceBin = nullptr; + u64 colorHash = 0; + // Palettes live in the ring arena above; vertices are read fresh every draw and are not + // cached by address, so they can be rebuilt in place. + void* textures = nullptr; + std::unique_ptr vertices; +}; + +std::unordered_map sVariants; + +u64 VariantKey(u32 ownerKey, s32 modelId) { + return ((u64)ownerKey << 32) | (u32)modelId; +} + +u64 HashColors(const BKPlayerColorSet& colors) { + u64 hash = 1469598103934665603ull; + const u8* bytes = (const u8*)&colors; + for (size_t index = 0; index < sizeof(colors); index++) { + hash = (hash ^ bytes[index]) * 1099511628211ull; + } + return hash; +} + +bool AnyEnabled(const BKPlayerColorSet& colors) { + for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { + if (colors.channel[channelIndex].enabled) { + return true; + } + } + return false; +} + +const TextureTable* TexturesForModel(s32 modelId) { + switch (modelId) { + case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: + return kLowTextures; + case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: + return kHighTextures; + default: + return nullptr; + } +} + +void RecolorTextures(void* textureBlob, const TextureTable* textureTable, const BKPlayerColorSet& colors) { + BKTextureList* textureList = (BKTextureList*)textureBlob; + u8* pixelBase = (u8*)textureList + sizeof(BKTextureList) + (size_t)textureList->count * sizeof(BKTextureInfo); + + for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { + if (!colors.channel[channelIndex].enabled) { + continue; + } + const ChannelInfo& channel = kChannels[channelIndex]; + for (s32 entry = 0; entry < textureTable[channelIndex].count; entry++) { + const s16 textureIndex = textureTable[channelIndex].index[entry]; + if (textureIndex < 0 || textureIndex >= textureList->count) { + continue; + } + BKTextureInfo* texture = &textureList->texture_infos[textureIndex]; + const s32 paletteBytes = textureInfo_getPaletteSize(texture); + if (paletteBytes <= 0) { + continue; + } + if ((size_t)texture->offset + (size_t)paletteBytes > (size_t)textureList->size) { + continue; + } + // TLUT entries are big-endian RGBA5551, matching what the RDP (and Fast3D's + // CI4 importer) reads out of DRAM. + u8* palette = pixelBase + texture->offset; + for (s32 paletteEntry = 0; paletteEntry < paletteBytes / 2; paletteEntry++) { + const u16 packedColor = (u16)((palette[paletteEntry * 2] << 8) | palette[paletteEntry * 2 + 1]); + const u8 red = (u8)(((packedColor >> 11) & 0x1F) * 255 / 31); + const u8 green = (u8)(((packedColor >> 6) & 0x1F) * 255 / 31); + const u8 blue = (u8)(((packedColor >> 1) & 0x1F) * 255 / 31); + if (!PassesFilter(channel, red, green, blue)) { + continue; + } + u8 newRed, newGreen, newBlue; + Recolor(channel, colors.channel[channelIndex], red, green, blue, &newRed, &newGreen, &newBlue); + const u16 recolored = (u16)(((newRed * 31 / 255) << 11) | ((newGreen * 31 / 255) << 6) | + ((newBlue * 31 / 255) << 1) | (packedColor & 1)); + palette[paletteEntry * 2] = (u8)(recolored >> 8); + palette[paletteEntry * 2 + 1] = (u8)(recolored & 0xFF); + } + } + } +} + +void RecolorVertices(void* vertexBlob, const BKPlayerColorSet& colors) { + BKVertexList* vertexList = (BKVertexList*)vertexBlob; + Vtx* vertices = vertexList->vertices; + const s32 vertexCount = vertexList->count; + + for (s32 vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { + Vtx_t& vertex = vertices[vertexIndex].v; + const u32 packedColor = ((u32)vertex.cn[0] << 16) | ((u32)vertex.cn[1] << 8) | (u32)vertex.cn[2]; + for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { + if (!colors.channel[channelIndex].enabled) { + continue; + } + const VertexTable& vertexColors = kVertexTables[channelIndex]; + bool matched = false; + for (s32 entry = 0; entry < vertexColors.count; entry++) { + if (vertexColors.color[entry] == packedColor) { + matched = true; + break; + } + } + if (!matched) { + continue; + } + u8 newRed, newGreen, newBlue; + Recolor(kChannels[channelIndex], colors.channel[channelIndex], vertex.cn[0], vertex.cn[1], vertex.cn[2], + &newRed, &newGreen, &newBlue); + vertex.cn[0] = newRed; + vertex.cn[1] = newGreen; + vertex.cn[2] = newBlue; + break; + } + } +} + +Variant* BuildVariant(u32 ownerKey, s32 modelId, BKModelBin* modelBin, const BKPlayerColorSet& colors) { + const TextureTable* textureTable = TexturesForModel(modelId); + if (textureTable == nullptr || modelBin == nullptr || modelBin->texture_list_offset == 0 || + modelBin->vtx_list_offset == 0) { + return nullptr; + } + + Variant& variant = sVariants[VariantKey(ownerKey, modelId)]; + const u64 colorHash = HashColors(colors); + if (variant.sourceBin == modelBin && variant.colorHash == colorHash && variant.textures != nullptr) { + return &variant; + } + + const BKTextureList* sourceTextures = modelbin_getTextureList(modelBin); + const BKVertexList* sourceVertices = modelbin_getVtxList(modelBin); + if (sourceTextures == nullptr || sourceVertices == nullptr) { + return nullptr; + } + + const size_t textureBytes = + sizeof(BKTextureList) + (size_t)sourceTextures->count * sizeof(BKTextureInfo) + (size_t)sourceTextures->size; + const size_t vertexBytes = sizeof(BKVertexList) + (size_t)sourceVertices->count * sizeof(Vtx); + + void* textures = PaletteArenaTake(textureBytes); + if (textures == nullptr) { + return nullptr; + } + std::memcpy(textures, sourceTextures, textureBytes); + + variant.vertices = std::make_unique((vertexBytes + 7) / 8); + std::memcpy(variant.vertices.get(), sourceVertices, vertexBytes); + + variant.sourceBin = modelBin; + variant.colorHash = colorHash; + variant.textures = textures; + + RecolorTextures(variant.textures, textureTable, colors); + RecolorVertices(variant.vertices.get(), colors); + return &variant; +} + +const char* kChannelCVars[] = { + CVAR_REMOTE_ANCHOR("Colors.BanjoFur"), CVAR_REMOTE_ANCHOR("Colors.BanjoShorts"), + CVAR_REMOTE_ANCHOR("Colors.KazooieFeathers"), CVAR_REMOTE_ANCHOR("Colors.KazooieBeak"), + CVAR_REMOTE_ANCHOR("Colors.BanjoBackpack"), CVAR_REMOTE_ANCHOR("Colors.BanjoSkin"), +}; + +#define CHANNEL_TABLE_COMPLETE(table) \ + static_assert(sizeof(table) / sizeof((table)[0]) == BK_COLOR_CHANNEL_COUNT, #table) +CHANNEL_TABLE_COMPLETE(kChannelCVars); +CHANNEL_TABLE_COMPLETE(kChannels); +CHANNEL_TABLE_COMPLETE(kVertexTables); +CHANNEL_TABLE_COMPLETE(kLowTextures); +CHANNEL_TABLE_COMPLETE(kHighTextures); +#undef CHANNEL_TABLE_COMPLETE + +} // namespace + +extern "C" { + +const char* PlayerColors_getChannelCVar(s32 channel) { + if (channel < 0 || channel >= BK_COLOR_CHANNEL_COUNT) { + return nullptr; + } + return kChannelCVars[channel]; +} + +void PlayerColors_getVanilla(s32 channel, u8* red, u8* green, u8* blue) { + if (channel < 0 || channel >= BK_COLOR_CHANNEL_COUNT) { + return; + } + *red = kChannels[channel].vanilla[0]; + *green = kChannels[channel].vanilla[1]; + *blue = kChannels[channel].vanilla[2]; +} + +void PlayerColors_getLocal(BKPlayerColorSet* out) { + if (out == nullptr) { + return; + } + for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { + const ChannelInfo& channel = kChannels[channelIndex]; + const std::string valueCVar = std::string(kChannelCVars[channelIndex]) + ".Value"; + const std::string enabledCVar = std::string(kChannelCVars[channelIndex]) + ".Enabled"; + const Color_RGBA8 vanilla = { channel.vanilla[0], channel.vanilla[1], channel.vanilla[2], 255 }; + const Color_RGBA8 chosen = CVarGetColor(valueCVar.c_str(), vanilla); + out->channel[channelIndex].enabled = CVarGetInteger(enabledCVar.c_str(), 0) ? 1 : 0; + out->channel[channelIndex].r = chosen.r; + out->channel[channelIndex].g = chosen.g; + out->channel[channelIndex].b = chosen.b; + } +} + +void PlayerColors_applyForDraw(u32 ownerKey, s32 modelId, void* modelBin, const BKPlayerColorSet* colors) { + if (!port_anchor_isConnected()) { + return; + } + if (colors == nullptr || modelBin == nullptr || !AnyEnabled(*colors)) { + return; + } + Variant* variant = BuildVariant(ownerKey, modelId, (BKModelBin*)modelBin, *colors); + if (variant == nullptr) { + return; + } + modelRender_setTextureList((BKTextureList*)variant->textures); + modelRender_setVertexList((BKVertexList*)variant->vertices.get()); +} + +void PlayerColors_applyLocalForDraw(s32 modelId, void* modelBin) { + if (TexturesForModel(modelId) == nullptr) { + return; + } + BKPlayerColorSet colors; + PlayerColors_getLocal(&colors); + PlayerColors_applyForDraw(BK_COLORS_LOCAL_OWNER, modelId, modelBin, &colors); +} + +void PlayerColors_forgetOwner(u32 ownerKey) { + for (auto entry = sVariants.begin(); entry != sVariants.end();) { + entry = ((u32)(entry->first >> 32) == ownerKey) ? sVariants.erase(entry) : std::next(entry); + } +} + +void PlayerColors_reset(void) { + sVariants.clear(); +} + +} // extern "C" diff --git a/src/port/Enhancements/Cosmetics/PlayerColors.h b/src/port/Enhancements/Cosmetics/PlayerColors.h new file mode 100644 index 000000000..c7aae365c --- /dev/null +++ b/src/port/Enhancements/Cosmetics/PlayerColors.h @@ -0,0 +1,43 @@ +#ifndef PORT_ENHANCEMENTS_COSMETICS_PLAYERCOLORS_H +#define PORT_ENHANCEMENTS_COSMETICS_PLAYERCOLORS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BK_COLOR_BANJO_FUR = 0, + BK_COLOR_BANJO_SHORTS, + BK_COLOR_KAZOOIE_FEATHERS, + BK_COLOR_KAZOOIE_BEAK, + BK_COLOR_BANJO_BACKPACK, + BK_COLOR_BANJO_SKIN, + BK_COLOR_CHANNEL_COUNT +} BKColorChannel; + +typedef struct { + u8 enabled; + u8 r, g, b; +} BKColorChannelSetting; + +typedef struct { + BKColorChannelSetting channel[BK_COLOR_CHANNEL_COUNT]; +} BKPlayerColorSet; + +#define BK_COLORS_LOCAL_OWNER 0u + +void PlayerColors_getVanilla(s32 channel, u8* red, u8* green, u8* blue); +const char* PlayerColors_getChannelCVar(s32 channel); +void PlayerColors_applyForDraw(u32 ownerKey, s32 modelId, void* modelBin, const BKPlayerColorSet* colors); +void PlayerColors_applyLocalForDraw(s32 modelId, void* modelBin); +void PlayerColors_getLocal(BKPlayerColorSet* out); +void PlayerColors_forgetOwner(u32 ownerKey); +void PlayerColors_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif /* PORT_ENHANCEMENTS_COSMETICS_PLAYERCOLORS_H */ diff --git a/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp b/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp index b22e94f9b..3d32eea8d 100644 --- a/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp +++ b/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp @@ -15,12 +15,15 @@ enum level_e level_get(void); int volatileFlag_get(enum volatile_flags_e index); int func_8028F070(void); void gcparade_beginFFParade(void); +void baflag_clear(enum misc_flag_e arg0); +void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume); } #define CVAR_SKIP_BOOT_LOGOS CVAR_ENHANCEMENT("Cutscenes.SkipBootLogos") #define CVAR_SKIP_INTRO CVAR_ENHANCEMENT("Cutscenes.StartSkipIntro") #define CVAR_SKIP_MISC_CUTSCENES CVAR_ENHANCEMENT("Cutscenes.SkipMiscCutscenes") #define CVAR_SKIP_CLUCKER_CUTSCENE CVAR_ENHANCEMENT("Cutscenes.SkipCluckerCutscene") +#define CVAR_SKIP_NOTEDOOR_DANCE CVAR_ENHANCEMENT("Cutscenes.SkipNoteDoorDance") #define CVAR_TRIGGER_FF_PARADE CVAR_DEVELOPER_TOOLS("TriggerFFParade") void RegisterSkipBootLogos_Init() { @@ -52,6 +55,16 @@ void RegisterSkipCluckerCutscene_Init() { }); } +void RegisterSkipNoteDoorDance_Init() { + COND_VB_SHOULD(VB_PLAY_NOTEDOOR_DANCE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_SKIP_NOTEDOOR_DANCE, 0), { + // Clear the flag so the (per-frame) state check doesn't retrigger, and still play the + // opening fanfare so the door-opened cue is preserved, then skip the dance state. + baflag_clear(BA_FLAG_1A_OPEN_NOTEDOOR); + // coMusicPlayer_playMusic(COMUSIC_42_NOTEDOOR_OPENING_FANFARE, -1); + *should = false; + }); +} + void RegisterTriggerFFParade_Init() { COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_TRIGGER_FF_PARADE, 0), [](IEvent* event) { if (getGameMode() != GAME_MODE_3_NORMAL || level_get() <= 0 || !func_8028F070()) { @@ -70,4 +83,5 @@ static RegisterShipInitFunc initSkipIntroFunc(RegisterSkipIntroCutscene_Init, { static RegisterShipInitFunc initSkipMiscCutscenesFunc(RegisterSkipMiscCutscenes_Init, { CVAR_SKIP_MISC_CUTSCENES }); static RegisterShipInitFunc initSkipCluckerCutsceneFunc(RegisterSkipCluckerCutscene_Init, { CVAR_SKIP_CLUCKER_CUTSCENE }); +static RegisterShipInitFunc initSkipNoteDoorDanceFunc(RegisterSkipNoteDoorDance_Init, { CVAR_SKIP_NOTEDOOR_DANCE }); static RegisterShipInitFunc initTriggerFFParadeFunc(RegisterTriggerFFParade_Init, { CVAR_TRIGGER_FF_PARADE }); diff --git a/src/port/Enhancements/Cutscenes/IntroLogos.cpp b/src/port/Enhancements/Cutscenes/IntroLogos.cpp new file mode 100644 index 000000000..7ff2ec4f0 --- /dev/null +++ b/src/port/Enhancements/Cutscenes/IntroLogos.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/ShipInit.hpp" +#include "port/UI/cvar_prefixes.h" +#include "port/UI/enhancementTypes.h" + +#include + +extern "C" { +#include "enums.h" +int port_getBootSequence(void); +void ResourceMgr_RegisterAssetOverride(uint32_t assetId, const char* customPath); +} + +namespace { + +constexpr const char* kXylophoneNintendoTex = "assets/model/ASSET_3B1_UNNAMED_tex_6"; +constexpr const char* kXylophoneReplacementTex = "textures/intro/xylophone"; +constexpr const char* kIntroCubeReplacementModel = "models/lighthouse"; +constexpr uint32_t kAssetNintendoWalkAnim = 0x8F; +constexpr uint32_t kAssetNintendoShrugAnim = 0x90; +constexpr const char* kIntroCubeWalkAnim = "anim/lighthouse_walk"; +constexpr const char* kIntroCubeShrugAnim = "anim/lighthouse_shrug"; + +bool bootSequenceIsDefault() { + return port_getBootSequence() == BOOTSEQUENCE_DEFAULT; +} + +void stripXylophoneNintendoLogo() { + auto& rm = *Ship::Context::GetRawInstance()->GetResourceManager(); + if (!rm.GetArchiveManager()->HasFile(kXylophoneReplacementTex)) { + return; + } + auto replacement = rm.LoadResource(kXylophoneReplacementTex); + if (replacement != nullptr && std::static_pointer_cast(replacement)->ImageData != nullptr) { + rm.CacheExternalResource(kXylophoneNintendoTex, replacement); + } +} + +} // namespace + +void RegisterIntroLogos_Init() { + COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, bootSequenceIsDefault(), [](IEvent* event) { + auto* ev = (OnMapLoad*)event; + ResourceMgr_RegisterAssetOverride(ASSET_3A6_MODEL_INTRO_N64_CUBE, kIntroCubeReplacementModel); + ResourceMgr_RegisterAssetOverride(kAssetNintendoWalkAnim, kIntroCubeWalkAnim); + ResourceMgr_RegisterAssetOverride(kAssetNintendoShrugAnim, kIntroCubeShrugAnim); + + if (ev->nextMap == MAP_1E_CS_START_NINTENDO || ev->nextMap == MAP_1F_CS_START_RAREWARE) { + stripXylophoneNintendoLogo(); + } + }); +} + +static RegisterShipInitFunc introLogosInit(RegisterIntroLogos_Init, { CVAR_SETTING("BootSequence") }); diff --git a/src/port/Enhancements/Events/Hooks/Events.h b/src/port/Enhancements/Events/Hooks/Events.h index 2e6699ded..fe10572df 100644 --- a/src/port/Enhancements/Events/Hooks/Events.h +++ b/src/port/Enhancements/Events/Hooks/Events.h @@ -6,19 +6,30 @@ #include +// Grouped by the system that listens for them. Nothing depends on the numeric values -- +// every reference is by name at compile time and none are serialized -- so ids can be +// added to the group they belong to rather than to the end. typedef enum VBehaviorID { + // Return to Lair restoration, and the pause-menu adjustments VB_INIT_RETURN_TO_LAIR, VB_PAUSE_MENU_PORTRAIT_DEPTH, VB_ZOOMBOX_TEXT_ADJUST, // text scale (shrink pause text) + X nudge (JP kana clearance) + + // Camera behavior VB_STATIC_CAMERA_SET, VB_STATIC_CAMERA_EXIT, VB_CAMERA_LIVE_ASPECT, VB_CAMERA_FOLLOW, - VB_GRUNTY_DEFEATED_FLAG_BOSS, - VB_PLAY_JIGGY_DANCE, + VB_CAMERA_APPLY_SHAKE, + + // Cutscene and celebration skips VB_PLAY_BOOT_LOGOS, VB_PLAY_INTRO_CUTSCENE, - VB_DISABLE_SNACKER, + VB_PLAY_JIGGY_DANCE, + VB_PLAY_NOTEDOOR_DANCE, + + // Vanilla bug fixes and corrections + VB_GRUNTY_DEFEATED_FLAG_BOSS, VB_VOID_OUT_GAME_OVER, VB_CCW_GNAWTY_SPRING_ROCK, VB_CCW_FLOWER_REPLANT, @@ -26,32 +37,100 @@ typedef enum VBehaviorID { VB_CLAW_SWIPE_SLIDE, VB_BOGGY_RACE_GAME_OVER, VB_JINJO_CHARGE_SOUND, + VB_ENEMY_BECOME_BUNDLE, VB_YUMYUM_DROP, + VB_MM_CHIMPY_STUMP_RUMBLE, + VB_MM_CHIMPY_NOISE, + VB_SPLINE_PATH_SFX, + VB_MAP_SAVESTATE_USE, + + // Gameplay options and cheats + VB_DISABLE_SNACKER, + VB_SAVE_AND_EXIT, + VB_MUMBO_HUT_TRANSFORM_CUTSCENE, + VB_MUMBO_DETRANSFORM, + + // Rando object behavior VB_OVERRIDE_BOTTLES_TEXT_CALLBACK, VB_OVERRIDE_MOLEHILL_ABILITY, VB_OVERRIDE_JIGGY_SPAWN, VB_OVERRIDE_PROP_SPAWN, VB_OVERRIDE_BUNDLE_SPAWN, + VB_BUNDLE_SPAWN_SET_ACTOR_DATA, + VB_NAPPER_SET_JIGGY_POSITION, VB_OVERRIDE_SNS_MAP_CHECK, VB_OVERRIDE_TIMED_DIALOGUE, - VB_ENEMY_BECOME_BUNDLE, VB_UPDATE_JINJO_HUD, VB_SET_JINJO_COUNT, - VB_BUNDLE_SPAWN_SET_ACTOR_DATA, - VB_NAPPER_SET_JIGGY_POSITION, + + // Dialog and localization VB_RESET_DIALOG_LANGUAGE, - // Cancellable at the single dialog choke point (gcdialog_showDialogConditional). - // Listeners receive the dialog's text_id; returning should=true suppresses the popup. VB_OVERRIDE_DIALOG_SHOW, - // Mr. Vile minigame (Anchor authority gating): cancelled on clients following a - // remote authority so local random logic yields to network state. + + // Rendering and performance + VB_CUBE_PROP_SORT, + VB_GCLIGHTS_RECOLOR, + VB_SNOW_CAMERA_ROTATION, + VB_SNOW_RENDER_STATE, + VB_MODEL_DRAWDIST_FADE_ALPHA, + VB_SPRITE_RESTORE_ALPHA_COMPARE, + VB_DRAWDIST_BOX_CULL, + VB_PICTUREBOX_TARGET_FB, + VB_PICTUREBOX_SUBMIT_FRAME, + + // Anchor VB_VILE_YUMBLIE_EMERGE, VB_VILE_YUMBLIE_HIDE, VB_VILE_PLAYER_EAT_PIECE, VB_VILE_GAME_UPDATE, VB_VILE_CPU_AI, + VB_CCW_FLOWER_REMOTE_GROW, // Lets a remotely-watered CCW flower grow without local camera/fanfare/jiggy. + VB_FP_TWINKLY_START, // Gates FP twinkly minigame start so only one client owns a run at a time. + VB_SM_TUTORIAL_CHOICE_OPEN, // True while the SM tutorial choice is still open to the local player. + VB_SM_MOLEHILL_ACTIVE, // SM ability molehills stay inert until the tutorial choice is made. + VB_DOOR_OPEN_CAMERA, // Suppresses door-open camera lock when the flag came from a teammate, not us. + VB_CC_RINGS_SNAP_WATER, // CC rings water snap on run teardown: suppressed when a teammate finished the rings. + VB_LEVELDOOR_REMOTE_OPEN_DONE, // Lair door remote-open "already handled" test. + VB_CCW_PODIUM_DESPAWN, // Despawn the unrevealed CCW puzzle podium: suppressed so a teammate's switch press can + // reveal it live. + VB_JIGSAW_PICTURE_RESYNC, // Rebuild a lair podium's cached piece state when the synced flags disagree with it. + + // Romhack port gates + VB_JIGGYSCORE_LEVEL_TOTAL, + VB_PAUSEMENU_LEVEL_TO_PAGE, + VB_PAUSEMENU_SET_NEXT_PAGE, + VB_PAUSEMENU_DRAW_JOYSTICKS, + VB_PAUSEMENU_BOLD_FONT_TEXTURE, + VB_PAUSEMENU_LEVEL_NAME_X, + VB_PAUSEMENU_ROW_VISIBLE, + VB_MAP_CHANGE_REQUEST, + VB_MAP_TRANSITION_IN_INDEX, + VB_VOID_OUT_RESPAWN_TRANSITION, + VB_EGG_FIRE_SFX, + VB_WARP_KEEPS_MUSIC, + VB_BUMP_REBOUNDS_PLAYER, + VB_WARP_DISPATCH, + VB_GAMESELECT_START_NEW_GAME, + VB_NOTEDOOR_DRAW_NUMBER, + VB_JIGGY_COLLECT_TUTORIAL, + VB_HONEYCOMB_PUMPKIN_REQUIREMENT, // also read by rando + VB_BRENTILDA_HEAL_DIALOG, + VB_SKY_UPDATE, + VB_SKY_DRAW_BACKDROP_RECT, + VB_GROUND_HAZARD_ACTIVE, + VB_CCW_SEASON_SWITCH_PRESSED_INIT, + VB_XMAS_TREE_ICE_UPDATE, + VB_BOGGY_HOME_VISIBLE, } VBehaviorID; +typedef enum DoorCameraId { + GV_DOOR_CAM_SUN, // sun switch (flag 3) + GV_DOOR_CAM_STAR, // star switch / trapdoor (flag 5) + GV_DOOR_CAM_KAZOOIE, // beak-bomb door (flag 6) + GV_DOOR_CAM_JINXY, // Jinxy sneeze (flags 0, 1) + MMM_DOOR_CAM_CHURCH, // church door, Tumblar challenge (flag 0) +} DoorCameraId; + DEFINE_EVENT(VanillaBehavior, VBehaviorID id; bool* should; va_list * originalArgs;); #ifdef __cplusplus diff --git a/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h b/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h index 2d43b2418..458e9073c 100644 --- a/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h @@ -20,6 +20,7 @@ DEFINE_EVENT(OnGruntyJinjonatorComplete) DEFINE_EVENT(OnIntroCutsceneCheck, bool* skipIntro;) DEFINE_EVENT(OnMiscCutscenesCheck, bool* skipMiscCutscenes;) DEFINE_EVENT(OnTooieJiggyCollect, f32* position;) +DEFINE_EVENT(OnJigsawPodiumInput, s32 podiumId;) DEFINE_EVENT(OnMumboTokenUpdate, Actor* actor;) DEFINE_EVENT(OnMumboTokenIdResolve, s32* tokenId; s32 * position; s32 mapId;) DEFINE_EVENT(OnPlayerAnimChange, AssetID anim_id; f32 duration; AnimControl control; f32 start_position; diff --git a/src/port/Enhancements/Events/Hooks/List/EngineEvent.h b/src/port/Enhancements/Events/Hooks/List/EngineEvent.h index b01226a3b..20cdb1dfc 100644 --- a/src/port/Enhancements/Events/Hooks/List/EngineEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/EngineEvent.h @@ -14,12 +14,22 @@ extern "C" { DEFINE_EVENT(GameFrameUpdate); DEFINE_EVENT(FrameDrawEnd); +DEFINE_EVENT(OnControllerUpdate); DEFINE_EVENT(OnMapLoad, GameMap prevMap; GameMap nextMap; s32 exit;); DEFINE_EVENT(OnDialogLoaded, s32 textId; char* text;); DEFINE_EVENT(OnModelLoad, s32 modelId; void* modelInfo; s32 * reload;); + +// Declared texture dimensions from a model's BKTextureInfo table. +typedef struct { + u8 width; + u8 height; +} ModelTexSize; + +DEFINE_EVENT(OnModelDisplayListLoad, const char* path; u32 * dlWords; u32 dlWordCount; const ModelTexSize* texSizes; + u16 texCount;); DEFINE_EVENT(ViewportFrustumUpdate, float* frustumX; float* frustumY;); DEFINE_EVENT(OnTransitionModelScale, Gfx** gfx; Mtx * *mtx; s32 uid; f32 * scale;); DEFINE_EVENT(OnTransitionStateUpdate, s32 modelId; s32 uid; s32 substate;); @@ -44,4 +54,5 @@ DEFINE_EVENT(ParadeCreditDialogId, int32_t index; int32_t * dialogId;); DEFINE_EVENT(ResolveBoldFontSlot, int32_t* slot; int32_t * letterId;); DEFINE_EVENT(OnWorldDraw, Gfx** gfx; Mtx * *mtx; Vtx * *vtx;); DEFINE_EVENT(OnPlayerDraw, Gfx** gfx; Mtx * *mtx; Vtx * *vtx;); +DEFINE_EVENT(OnHudDraw, Gfx** gfx; Mtx * *mtx; Vtx * *vtx;); DEFINE_EVENT(OnReset); \ No newline at end of file diff --git a/src/port/Enhancements/Events/Hooks/List/GameEvent.h b/src/port/Enhancements/Events/Hooks/List/GameEvent.h index e53254847..6f682b5c6 100644 --- a/src/port/Enhancements/Events/Hooks/List/GameEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/GameEvent.h @@ -3,8 +3,22 @@ #include DEFINE_EVENT(OnActorDestroy, Actor* actor;) +DEFINE_EVENT(OnPlayerDeath) +DEFINE_EVENT(OnGameFileErase, int32_t gamenum;) DEFINE_EVENT(OnGameSave, int32_t fileNum;) DEFINE_EVENT(OnGameLoad, int32_t fileNum;) +DEFINE_EVENT(OnGameErase, int32_t gameNum;) +// flagSpace = AnchorFlagSpace; length = 1 for single sets, bit count for setN. +DEFINE_EVENT(OnGameFlagSet, int32_t flagSpace; int32_t index; int32_t value; int32_t length;) +// count is the resulting absolute value. +DEFINE_EVENT(OnItemCountChanged, int32_t item; int32_t count;) +// kind = AnchorCollectibleSpace. +DEFINE_EVENT(OnCollectibleCollected, int32_t kind; int32_t id;) +// move = ability_e; value = 1 learned, 0 cleared. +DEFINE_EVENT(OnAbilityLearned, int32_t move; int32_t value;) +DEFINE_EVENT(OnJiggySpawned, int32_t jiggyId; float x; float y; float z;) +DEFINE_EVENT(OnHoneycombDropSpawn, int32_t honeycombId; int32_t bundleId; float x; float y; float z;) +DEFINE_EVENT(OnTimedJiggyExpired, int32_t jiggyId;) DEFINE_EVENT(OnPropInit, Prop* propPtr;) DEFINE_EVENT(OnBottlesBonusComplete, int32_t index;) DEFINE_EVENT(OnSaveFileLoad, int32_t fileNum; void* saveBuffer; int32_t result;) @@ -14,10 +28,16 @@ DEFINE_EVENT(OnSaveFileSave, void* saveBuffer; int32_t fileNum; int32_t * result typedef enum WarpId { WARP_ID_SM_EXIT_BANJOS_HOUSE = 1, WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL = 2, + // Also lands in the MM Lobby, but from the post-cutscene branch of a different + // dispatcher. Listeners that treat both lair entrances alike should match on 2 || 3. + WARP_ID_LAIR_ENTER_LAIR_FROM_SM_LEVEL = 3, } WarpId; DEFINE_EVENT(OnWarpResolveDest, int32_t warpId; int32_t defaultDest; int32_t bkcfOverride; int32_t * dest;) DEFINE_EVENT(OnNewGame, int32_t* skipIntro;) +// The file-select commit, for both new game and continue. Unlike OnGameLoad this +// does not fire for the zoombox preview. +DEFINE_EVENT(OnGameStart) DEFINE_EVENT(EggHeadSpawn, float* pitch; float* spawnHeight; float* minVerticalVelocity; float* yawBias; int32_t * flattenTrajectory;) diff --git a/src/port/Enhancements/Events/Hooks/List/RandoEvent.h b/src/port/Enhancements/Events/Hooks/List/RandoEvent.h index cdb556cd6..4b2da34a9 100644 --- a/src/port/Enhancements/Events/Hooks/List/RandoEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/RandoEvent.h @@ -46,6 +46,8 @@ DEFINE_EVENT(OnIsJiggyScoreSpawned, int32_t jiggyId; int32_t result;) DEFINE_EVENT(SetRandoInfFlag, int32_t flagId; int32_t flagState;) +DEFINE_EVENT(OnRandoCheckObtained, int32_t randoCheckId; int32_t map;) + DEFINE_EVENT(OnIsHoneycombScoreCollected, int32_t honeycombId; int32_t result;) DEFINE_EVENT(ClearBundleDespawnQueue); diff --git a/src/port/Enhancements/Events/PortEnhancements.cpp b/src/port/Enhancements/Events/PortEnhancements.cpp index f369bb3be..05c4dac0a 100644 --- a/src/port/Enhancements/Events/PortEnhancements.cpp +++ b/src/port/Enhancements/Events/PortEnhancements.cpp @@ -19,10 +19,12 @@ void PortEnhancements_Register() { // Register engine events REGISTER_EVENT(GameFrameUpdate); REGISTER_EVENT(FrameDrawEnd); + REGISTER_EVENT(OnControllerUpdate); REGISTER_EVENT(VanillaBehavior); REGISTER_EVENT(OnMapLoad); REGISTER_EVENT(OnDialogLoaded); REGISTER_EVENT(OnModelLoad); + REGISTER_EVENT(OnModelDisplayListLoad); REGISTER_EVENT(ViewportFrustumUpdate); REGISTER_EVENT(OnTransitionModelScale); REGISTER_EVENT(OnTransitionStateUpdate); @@ -49,6 +51,7 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnBoldFontReset); REGISTER_EVENT(OnWorldDraw); REGISTER_EVENT(OnPlayerDraw); + REGISTER_EVENT(OnHudDraw); // Register behavior events REGISTER_EVENT(OnBeakSwimVelocitySet); @@ -60,6 +63,7 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnIntroCutsceneCheck); REGISTER_EVENT(OnMiscCutscenesCheck); REGISTER_EVENT(OnTooieJiggyCollect); + REGISTER_EVENT(OnJigsawPodiumInput); REGISTER_EVENT(OnMumboTokenUpdate); REGISTER_EVENT(OnMumboTokenIdResolve); REGISTER_EVENT(OnNametagDraw); @@ -72,8 +76,18 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnVileGameStateChange); // Register game events + REGISTER_EVENT(OnGameFlagSet); + REGISTER_EVENT(OnItemCountChanged); + REGISTER_EVENT(OnCollectibleCollected); + REGISTER_EVENT(OnAbilityLearned); + REGISTER_EVENT(OnJiggySpawned); + REGISTER_EVENT(OnHoneycombDropSpawn); + REGISTER_EVENT(OnTimedJiggyExpired); + REGISTER_EVENT(OnPlayerDeath); + REGISTER_EVENT(OnGameFileErase); REGISTER_EVENT(OnGameLoad); REGISTER_EVENT(OnGameSave); + REGISTER_EVENT(OnGameErase); REGISTER_EVENT(OnBottlesBonusComplete); REGISTER_EVENT(OnSaveFileLoad); REGISTER_EVENT(OnSaveFileSave); @@ -81,6 +95,7 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnPropInit); REGISTER_EVENT(OnWarpResolveDest); REGISTER_EVENT(OnNewGame); + REGISTER_EVENT(OnGameStart); REGISTER_EVENT(EggHeadSpawn); REGISTER_EVENT(OnActorDestroy); REGISTER_EVENT(OnCheckSpiralMountainAbilities); @@ -104,6 +119,7 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnIsJiggyScoreCollected); REGISTER_EVENT(OnIsJiggyScoreSpawned); REGISTER_EVENT(SetRandoInfFlag); + REGISTER_EVENT(OnRandoCheckObtained); REGISTER_EVENT(OnIsHoneycombScoreCollected); REGISTER_EVENT(ClearBundleDespawnQueue); REGISTER_EVENT(OnIsMumboTokenScoreCollected); diff --git a/src/port/Enhancements/Fixes/GameFixes.cpp b/src/port/Enhancements/Fixes/GameFixes.cpp index d4d5c8dc4..113f16768 100644 --- a/src/port/Enhancements/Fixes/GameFixes.cpp +++ b/src/port/Enhancements/Fixes/GameFixes.cpp @@ -8,9 +8,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +#include "functions.h" extern "C" { #include "enums.h" -#include "functions.h" enum map_e gsworld_getMap(void); } @@ -34,6 +34,7 @@ extern "C" int port_isInCharacterParade(void) { #define CVAR_JINJO_SOUND CVAR_ENHANCEMENT("Fixes.JinjoChargeSound") #define CVAR_GRUNTY_BOUNCE CVAR_ENHANCEMENT("Fixes.GruntyBounce") #define CVAR_CONGA_TEXT CVAR_ENHANCEMENT("Fixes.CongaText") +#define CVAR_STUMP_RUMBLE CVAR_ENHANCEMENT("Fixes.ChimpyStumpRumble") void RegisterVoidOutGameOver_Init() { COND_VB_SHOULD(VB_VOID_OUT_GAME_OVER, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_VOID_OUT, 0), @@ -140,6 +141,29 @@ void RegisterCongaDialog_Init() { }); } +// MM Chimpy stump: Chimpy respawns and walks off again on every entry to MM once his jiggy has +// spawned, so the stump drops in low and grinds back up with the rumble sfx each time. Mute the +// rumble for those replays only; the first rise (jiggy spawns 2.9s after the shake starts, so it +// isn't marked spawned yet) keeps its sound. +static bool IsChimpyWalkOffReplay() { + return jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY) && + !mapSpecificFlags_get(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED); +} + +void RegisterChimpyStumpRumble_Init() { + COND_VB_SHOULD(VB_MM_CHIMPY_STUMP_RUMBLE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_STUMP_RUMBLE, 1), + { *should = !jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY); }); + COND_VB_SHOULD(VB_MM_CHIMPY_NOISE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_STUMP_RUMBLE, 1), + { *should = !IsChimpyWalkOffReplay(); }); + COND_VB_SHOULD(VB_SPLINE_PATH_SFX, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_STUMP_RUMBLE, 1), { + Actor* pathWalker = va_arg(args, Actor*); + if (pathWalker != NULL && pathWalker->actor_info != NULL && pathWalker->actor_info->actorId == ACTOR_F_CHIMPY && + IsChimpyWalkOffReplay()) { + *should = false; + } + }); +} + // Mumbo token duplicate-id fix: rewrite the resolved id for the two tokens that share an id. void RegisterMumboTokenIdResolve_Init() { COND_HOOK(OnMumboTokenIdResolve, EVENT_PRIORITY_NORMAL, @@ -158,6 +182,23 @@ void RegisterMumboTokenIdResolve_Init() { }); } +// Map savestates and demo playback +static bool isPlaybackMode(s32 mode) { + return (mode == GAME_MODE_5_UNKNOWN) || (mode == GAME_MODE_6_FILE_PLAYBACK) || (mode == GAME_MODE_7_ATTRACT_DEMO) || + (mode == GAME_MODE_8_BOTTLES_BONUS) || (mode == GAME_MODE_9_BANJO_AND_KAZOOIE) || + (mode == GAME_MODE_A_SNS_PICTURE); +} + +void RegisterMapSavestatePlayback_Init() { + REGISTER_VB_SHOULD(VB_MAP_SAVESTATE_USE, EVENT_PRIORITY_NORMAL, { + s32 mode = va_arg(args, s32); + if (isPlaybackMode(mode)) { + *should = false; + } + }); +} + +static RegisterShipInitFunc initMapSavestatePlaybackFunc(RegisterMapSavestatePlayback_Init); static RegisterShipInitFunc initVoidOutFunc(RegisterVoidOutGameOver_Init, { CVAR_VOID_OUT }); static RegisterShipInitFunc initFurnaceFunDialogFunc(RegisterFurnaceFunDialog_Init, { CVAR_FF_DIALOG }); static RegisterShipInitFunc initGruntyDefeatedFlagFunc(RegisterGruntyDefeatedFlag_Init, { CVAR_GRUNTY_FLAG }); @@ -171,5 +212,6 @@ static RegisterShipInitFunc initJinjoChargeSoundFunc(RegisterJinjoChargeSound_In static RegisterShipInitFunc initGruntyBounceFunc(RegisterGruntyBounce_Init, { CVAR_GRUNTY_BOUNCE }); static RegisterShipInitFunc initYumYumDropFunc(RegisterYumYumDrop_Init); static RegisterShipInitFunc initCongaDialogFunc(RegisterCongaDialog_Init, { CVAR_CONGA_TEXT }); +static RegisterShipInitFunc initChimpyStumpRumbleFunc(RegisterChimpyStumpRumble_Init, { CVAR_STUMP_RUMBLE }); static RegisterShipInitFunc initMumboTokenIdResolveFunc(RegisterMumboTokenIdResolve_Init, { CVAR_TOKEN_MMM, CVAR_TOKEN_CCW }); diff --git a/src/port/Enhancements/Fixes/TransientLevelState.cpp b/src/port/Enhancements/Fixes/TransientLevelState.cpp new file mode 100644 index 000000000..3c81868e2 --- /dev/null +++ b/src/port/Enhancements/Fixes/TransientLevelState.cpp @@ -0,0 +1,62 @@ +// Transient Level State +// +// The per-level stores Anchor replicates (huts, breakables, egg tolls, puzzle steps, carried +// collectibles) are written unconditionally by decomp, but only Anchor's sweep ever cleared +// them — offline, a smashed hut survived a level exit that should have restored it. +// +// Per level, not per map, so sub-area hops keep their state like the actor savestate did. + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include "functions.h" +extern "C" { +#include "enums.h" +s32 port_anchor_isWorldSyncActive(void); +} + +void port_breakable_clearForLevel(int32_t levelId); +void port_hutSmash_clearForLevel(int32_t levelId); +void port_eggToll_clearForLevel(int32_t levelId); +void port_puzzleStep_clearForLevel(int32_t levelId); +void port_carriedSync_clearForLevel(int32_t levelId); + +namespace { + +int32_t sCurrentLevel = -1; + +// 0 for maps outside the section table; map_getLevel would deref null on those. +int32_t levelOfMap(int32_t map) { + if (map <= 0 || map >= MAP_NUM_MAPS) { + return 0; + } + return (int32_t)map_getLevel((enum map_e)map); +} + +} // namespace + +void RegisterTransientLevelState_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { sCurrentLevel = -1; }); + + // HIGH so the stores are empty before this event's NORMAL listeners read them for the new + // map (port_breakable_despawnBrokenRestores). + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_HIGH, [](IEvent* event) { + OnMapLoad* ev = (OnMapLoad*)event; + int32_t nextLevel = levelOfMap((int32_t)ev->nextMap); + if (nextLevel == 0 || nextLevel == sCurrentLevel) { + return; + } + sCurrentLevel = nextLevel; + if (port_anchor_isWorldSyncActive()) { + return; + } + port_breakable_clearForLevel(nextLevel); + port_hutSmash_clearForLevel(nextLevel); + port_eggToll_clearForLevel(nextLevel); + port_puzzleStep_clearForLevel(nextLevel); + port_carriedSync_clearForLevel(nextLevel); + }); +} + +static RegisterShipInitFunc initTransientLevelState(RegisterTransientLevelState_Init, {}); diff --git a/src/port/Enhancements/Gameplay/DamageScale.cpp b/src/port/Enhancements/Gameplay/DamageScale.cpp deleted file mode 100644 index 7893a0f2f..000000000 --- a/src/port/Enhancements/Gameplay/DamageScale.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include "port/UI/cvar_prefixes.h" - -extern "C" int port_scalePlayerDamage(int damage) { - if (damage <= 0) { - return damage; - } - int mode = CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.Difficulty"), 1); - if (mode >= 4) { - return 9999; - } - return damage * (mode < 1 ? 1 : mode); -} \ No newline at end of file diff --git a/src/port/Enhancements/Gameplay/Difficulty.cpp b/src/port/Enhancements/Gameplay/Difficulty.cpp new file mode 100644 index 000000000..fdf918b3e --- /dev/null +++ b/src/port/Enhancements/Gameplay/Difficulty.cpp @@ -0,0 +1,53 @@ +#include +#include "port/UI/cvar_prefixes.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/ShipInit.hpp" +#include "port/Romhack/RomhackConfig.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +} + +static bool sSaveErased = false; + +extern "C" int port_scalePlayerDamage(int damage) { + if (damage <= 0) { + return damage; + } + int mode = CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.Difficulty"), 1); + if (mode >= 4) { + return 9999; + } + return damage * (mode < 1 ? 1 : mode); +} + +void RegisterDifficulty_Init() { + // Permadeath, ignore lives and game over with file erase + COND_HOOK(OnPlayerDeath, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.Permadeath"), 0), + [](IEvent* event) { + if (port_isRomhack()) { + return; + } + item_adjustByDiffWithoutHud(ITEM_16_LIFE, -item_getCount(ITEM_16_LIFE)); + + s32 gamenum = gameSelect_getGameNumber(); + if (gamenum == -1) { + return; + } + + gameFile_clear(gamenum); + gameFile_8033CFD4(gamenum); + sSaveErased = true; + }); + + COND_HOOK(OnGameLoad, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { sSaveErased = false; }); + + COND_VB_SHOULD(VB_SAVE_AND_EXIT, EVENT_PRIORITY_NORMAL, true, { + if (sSaveErased) { + *should = false; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterDifficulty_Init, { CVAR_ENHANCEMENT("Gameplay.Permadeath") }); diff --git a/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp b/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp index 26fbfc32e..f422874be 100644 --- a/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp +++ b/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp @@ -7,9 +7,7 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -extern "C" { #include "enums.h" -} #define CVAR_NAME CVAR_ENHANCEMENT("EasierBoggyRaces") #define CVAR CVarGetInteger(CVAR_NAME, 0) diff --git a/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp b/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp index b53ea3979..f76860273 100644 --- a/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp +++ b/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp @@ -4,11 +4,9 @@ #include "port/ShipInit.hpp" #include "port/Romhack/RomhackConfig.h" -extern "C" { #include "enums.h" #include "functions.h" #include "core2/abilityprogress.h" -} #define CVAR_NAME CVAR_ENHANCEMENT("Gameplay.FurnaceFunMoves") @@ -23,7 +21,12 @@ void RegisterFurnaceFunMoves_Init() { continue; } ability_unlock(static_cast(ability)); + ability_setHasUsed(static_cast(ability)); } + // Outside the loop's range. Without it the note doors never open and Bottles + // force-triggers his tutorial on approach to the 50-note door. + ability_unlock(ABILITY_13_1ST_NOTEDOOR); + ability_setHasUsed(ABILITY_13_1ST_NOTEDOOR); }); } diff --git a/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp b/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp index 749413da7..6c7ee0cc0 100644 --- a/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp +++ b/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp @@ -3,12 +3,11 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" #include "port/Romhack/RomhackConfig.h" +#include "port/Rando/Rando.h" -extern "C" { #include "enums.h" #include "functions.h" #include "core2/abilityprogress.h" -} extern "C" float D_80386000[]; @@ -36,20 +35,23 @@ void RegisterSkipSMTutorial_Init() { } auto* ev = reinterpret_cast(event); - for (ability_e ability : kSpiralMountainAbilities) { - ability_unlock(ability); - } - - for (ability_used move : kSpiralMountainUsedMoves) { - ability_setHasUsed(static_cast(move)); + if (!IS_RANDO) { + for (ability_e ability : kSpiralMountainAbilities) { + ability_unlock(ability); + } + + for (ability_used move : kSpiralMountainUsedMoves) { + ability_setHasUsed(static_cast(move)); + } + + for (int honeycomb = HONEYCOMB_13_SM_STUMP; honeycomb <= HONEYCOMB_18_SM_QUARRIES; honeycomb++) { + honeycombscore_set((honeycomb_e)honeycomb, true); + } + func_8034789C(); + item_adjustByDiffWithoutHud(ITEM_14_HEALTH, + item_getCount(ITEM_15_HEALTH_TOTAL) - item_getCount(ITEM_14_HEALTH)); } - for (int honeycomb = HONEYCOMB_13_SM_STUMP; honeycomb <= HONEYCOMB_18_SM_QUARRIES; honeycomb++) { - honeycombscore_set((honeycomb_e)honeycomb, true); - } - func_8034789C(); - item_adjustByDiffWithoutHud(ITEM_14_HEALTH, - item_getCount(ITEM_15_HEALTH_TOTAL) - item_getCount(ITEM_14_HEALTH)); fileProgressFlag_set(FILEPROG_BD_ENTER_LAIR_CUTSCENE, 1); D_80386000[LEVEL_B_SPIRAL_MOUNTAIN] = 122.0f; // Average speedrun time for SM completion (2:02) diff --git a/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp b/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp index f5e185807..ad5748a71 100644 --- a/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp +++ b/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp @@ -7,9 +7,7 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -extern "C" { #include "enums.h" -} #define CVAR_NAME CVAR_ENHANCEMENT("Gameplay.WaterPyramidTimer") diff --git a/src/port/Enhancements/JinjoRetention/JinjoRetention.cpp b/src/port/Enhancements/JinjoRetention/JinjoRetention.cpp deleted file mode 100644 index 4eb3ba567..000000000 --- a/src/port/Enhancements/JinjoRetention/JinjoRetention.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// Jinjo Collection Retention -// -// Vanilla resets ITEM_12_JINJOS on every level entry (itemscore_levelReset), so jinjos -// respawn each visit and must all be collected in one go to earn the jiggy. This persists -// the per-level set of collected jinjo colors so individually collected jinjos stay -// collected across visits. -// -// How it works: -// - Saving is ALWAYS ON: collecting a jinjo records its color bit for the current -// level (same 5-bit layout as ITEM_12_JINJOS). -// - Application is behind an enhancement toggle (default off): when on, ITEM_12_JINJOS -// is seeded on level load from the saved bits, and already collected jinjos are not -// respawned. Collecting the remaining jinjos then completes the vanilla 0x1f mask and -// spawns the jiggy as usual. -// -// Stranded-jiggy guard: if all 5 of a level's jinjos are recorded but that level's jinjo -// jiggy has not been obtained (player got all 5 but skipped the jiggy), retention is not -// applied for that level -- the jinjos respawn so the jiggy can still be earned. -// -#include -#include - -#include "port/UI/cvar_prefixes.h" -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Enhancements/JinjoRetention/JinjoRetention.h" -#include "port/Rando/Rando.h" - -extern "C" { -#include "enums.h" -#include "actor.h" -#include "prop.h" -#include "functions.h" -} - -#define CVAR_JINJO_RETENTION CVAR_ENHANCEMENT("Gameplay.JinjoRetention") -#define CVAR_VALUE CVarGetInteger(CVAR_JINJO_RETENTION, 0) - -constexpr u8 kAllJinjos = 0x1F; // all five color bits collected - -// gameFile_saveData index of the live save slot for the current game, or -1. -int32_t activeSlot() { - if (selectedFileNum == DEFAULT_FILE_NUM || selectedFileNum < 0 || selectedFileNum >= 4) { - return -1; - } - return (int32_t)selectedFileNum; -} - -// Don't run during demos, Bottles bonus games, or rando files. -bool systemActive() { - int32_t slot = activeSlot(); - if (slot < 0 || gameFile_saveData[slot].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { - return false; - } - switch (getGameMode()) { - case GAME_MODE_7_ATTRACT_DEMO: - case GAME_MODE_8_BOTTLES_BONUS: - case GAME_MODE_9_BANJO_AND_KAZOOIE: - case GAME_MODE_A_SNS_PICTURE: - return false; - default: - return true; - } -} - -bool applyEnabled() { - return CVarGetInteger(CVAR_JINJO_RETENTION, 0) != 0; -} - -JinjoRetentionSaveData* store() { - int32_t slot = activeSlot(); - return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.jinjoRetention : nullptr; -} - -bool levelInRange(int32_t level) { - return level > 0 && level < JINJO_RETENTION_LEVEL_SLOTS; -} - -u8 collectedBits(int32_t level) { - JinjoRetentionSaveData* s = store(); - return (s != nullptr && levelInRange(level)) ? s->collected[level] : 0; -} - -u8 jinjoBitFromMarker(int32_t markerId) { - switch (markerId) { - case MARKER_5A_JINJO_BLUE: - case MARKER_5B_JINJO_GREEN: - case MARKER_5C_JINJO_ORANGE: - case MARKER_5D_JINJO_PINK: - case MARKER_5E_JINJO_YELLOW: - return (u8)(1 << ((markerId + 6) & 0x1F)); - default: - return 0; - } -} - -u8 jinjoBitFromActor(int32_t actorId) { - switch (actorId) { - case ACTOR_60_JINJO_BLUE: - return 1 << 0; - case ACTOR_62_JINJO_GREEN: - return 1 << 1; - case ACTOR_5F_JINJO_ORANGE: - return 1 << 2; - case ACTOR_61_JINJO_PINK: - return 1 << 3; - case ACTOR_5E_JINJO_YELLOW: - return 1 << 4; - default: - return 0; - } -} - -// Whether retention should seed/suppress jinjos for this level. False when retention is -// off, and false in the stranded-jiggy case so the jinjos respawn and the jiggy is still -// earnable. Seeding and suppression both gate on this so ITEM_12_JINJOS stays consistent. -bool retentionActiveForLevel(int32_t level) { - if (!applyEnabled() || !levelInRange(level)) { - return false; - } - if (collectedBits(level) == kAllJinjos && !jiggyscore_isCollected((enum jiggy_e)(10 * level - 9))) { - return false; - } - return true; -} - -void RegisterJinjoRetention_Init() { - // Record collection. Don't cancel: vanilla still updates ITEM_12_JINJOS / spawns the - // jiggy and despawns the jinjo. - COND_HOOK(OnActorCollision, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnActorCollision* ev = (OnActorCollision*)event; - if (!systemActive() || !ev->propId->markerFlag) { - return; - } - ActorMarker* marker = ev->propId->actorProp.marker; - if (marker == nullptr) { - return; - } - u8 bit = jinjoBitFromMarker(marker->id); - if (bit == 0) { - return; - } - int32_t level = level_get(); - JinjoRetentionSaveData* s = store(); - if (s != nullptr && levelInRange(level)) { - s->collected[level] |= bit; - } - }); - - // Seed ITEM_12_JINJOS from the saved bits so prior progress carries across visits and - // the HUD reflects it. Mirrors note retention's OnSetJiggyList seeding. - COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnSetJiggyList* ev = (OnSetJiggyList*)event; - if (!systemActive() || !retentionActiveForLevel(ev->levelId)) { - return; - } - u8 bits = collectedBits(ev->levelId); - if (bits != 0) { - item_set(ITEM_12_JINJOS, bits); - } - }); - - // Suppress respawning already-collected jinjos. OnActorSpawn is cancellable; returning - // a null result with Cancelled means no actor spawns. - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - if (!systemActive()) { - return; - } - u8 bit = jinjoBitFromActor(ev->actorId); - if (bit == 0) { - return; - } - int32_t level = level_get(); - if (!retentionActiveForLevel(level) || !(collectedBits(level) & bit)) { - return; - } - ev->result = nullptr; - event->Cancelled = true; - }); - - // The engine's save double-buffers into a scratch slot via bcopy, which doesn't carry - // our bits. Sync the live slot's jinjoRetention into the buffer about to be serialized. - COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, CVAR_VALUE, [](IEvent* event) { - OnSaveFileSave* ev = (OnSaveFileSave*)event; - SaveData* buf = (SaveData*)ev->saveBuffer; - JinjoRetentionSaveData* live = store(); - if (buf != nullptr && live != nullptr && &buf->shipSaveData.jinjoRetention != live) { - buf->shipSaveData.jinjoRetention = *live; - } - }); -} - -static RegisterShipInitFunc initJinjoRetention(RegisterJinjoRetention_Init, { CVAR_JINJO_RETENTION }); diff --git a/src/port/Enhancements/JinjoRetention/JinjoRetention.h b/src/port/Enhancements/JinjoRetention/JinjoRetention.h deleted file mode 100644 index 91363c9d8..000000000 --- a/src/port/Enhancements/JinjoRetention/JinjoRetention.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PORT_JINJO_RETENTION_H -#define PORT_JINJO_RETENTION_H - -// Jinjo Collection Retention is implemented entirely with port event listeners -// (collection, level-load seeding, spawn suppression) and needs no engine-side hooks, -// so this header only marks the module's presence for consistency with NoteRetention. - -#endif diff --git a/src/port/Enhancements/NoteRetention/NoteRetention.cpp b/src/port/Enhancements/NoteRetention/NoteRetention.cpp deleted file mode 100644 index 0f5651ff2..000000000 --- a/src/port/Enhancements/NoteRetention/NoteRetention.cpp +++ /dev/null @@ -1,425 +0,0 @@ -// Note Collection Retention -// -// Persists which individual music notes the player has collected so they don't respawn -// on revisit. Works for vanilla and romhacks because each note is identified -// by (mapId, spawn-order index) within the map's deterministic cube-prop parse. -// -// How it works: -// - Static note sprite-props are replaced with ACTOR_51_MUSIC_NOTE actors so a -// stable spawn-order index can be attached to each via ObjectExtension. -// - Dynamically-spawned note bundles (hut/switch triggers) are also replaced with -// our own actors, given indices that continue AFTER the static notes for the map. -// Their identity resides in actor->local (not ObjectExtension) because bundle notes -// persist across sub-area save/restore, which copies the actor struct but assigns -// a fresh marker, so a marker-keyed extension wouldn't survive. -// - Saving is ALWAYS ON: collecting a note records (mapId, index) to the save. -// - Application is behind an enhancement toggle (default off): when on, already -// collected notes are not respawned, and ITEM_C_NOTE is seeded on level load -// from the collected count so totals stay reachable. Note-door logic is left -// to the vanilla per-level high score, unchanged. -// -#include "port/ObjectExtension/ObjectExtension.h" -#include -#include - -#include "port/UI/cvar_prefixes.h" -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Enhancements/NoteRetention/NoteRetention.h" -#include "port/Rando/Rando.h" -#include "port/Rando/CustomObject/CustomObject.h" - -#include -#include - -extern "C" { -#include "enums.h" -#include "actor.h" -#include "prop.h" -#include "functions.h" - -extern f32 gBundle_yaw; -extern ActorInfo sumusicNote; -} - -namespace { - -#define CVAR_NOTE_RETENTION CVAR_ENHANCEMENT("Gameplay.NoteRetention") -#define CVAR_VALUE CVarGetInteger(CVAR_NOTE_RETENTION, 0) - -// The note sprite asset id passed through VB_OVERRIDE_PROP_SPAWN identifies notes. -constexpr s32 kNoteSpriteAsset = ASSET_6D6_SPRITE_MUSIC_NOTE; - -// Per-actor note identity, attached via ObjectExtension. The constructor lets us -// build instances with parentheses, since brace-init commas break the event macros. -struct NoteRetentionData { - int32_t mapId; - int32_t noteIndex; - NoteRetentionData(int32_t map = 0, int32_t index = 0) : mapId(map), noteIndex(index) { - } -}; -ObjectExtension::Register NoteRetentionDataRegister; - -// Identity for bundle notes, stored in the actor's local data block. Unlike static -// notes, bundle notes are restored across sub-area transitions by the engine's actor -// save-state, which memcpy's the whole Actor struct (so local survives) but assigns -// a new marker (so an extension wouldn't). -// magic distinguishes our data from the uninitialized garbage actor_new leaves -// in local, and from notes we didn't spawn. -constexpr uint32_t kNoteLocalMagic = 0x4E4F5445u; // 'NOTE' -struct NoteLocal { - uint32_t magic; - int32_t mapId; - int32_t noteIndex; -}; - -NoteLocal* bundleNoteLocal(Actor* actor) { - if (actor == nullptr) { - return nullptr; - } - NoteLocal* nl = reinterpret_cast(actor->local); - return (nl->magic == kNoteLocalMagic) ? nl : nullptr; -} - -struct QueuedNote { - int32_t pos[3]; - int32_t mapId; - int32_t noteIndex; - bool spawned; -}; - -int32_t noteCounter = 0; -std::vector noteActorQueue; -std::unordered_map activeNoteSet; - -int64_t noteKey(int32_t mapId, int32_t noteIndex) { - return ((int64_t)mapId << 32) | (uint32_t)noteIndex; -} - -// Active slot is wobbly -int32_t activeSlot() { - if (selectedFileNum == DEFAULT_FILE_NUM || selectedFileNum < 0 || selectedFileNum >= 4) { - return -1; - } - return (int32_t)selectedFileNum; -} - -bool fileValid() { - return activeSlot() >= 0; -} - -// Don't run during demos, Bottles bonus games, or rando files -bool systemActive() { - int32_t slot = activeSlot(); - if (slot < 0 || gameFile_saveData[slot].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { - return false; - } - switch (getGameMode()) { - case GAME_MODE_7_ATTRACT_DEMO: - case GAME_MODE_8_BOTTLES_BONUS: - case GAME_MODE_9_BANJO_AND_KAZOOIE: - case GAME_MODE_A_SNS_PICTURE: - return false; - default: - return true; - } -} - -bool applyEnabled() { - return CVarGetInteger(CVAR_NOTE_RETENTION, 0) != 0; -} - -NoteRetentionSaveData* store() { - int32_t slot = activeSlot(); - return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.noteRetention : nullptr; -} - -bool indexInRange(int32_t mapId, int32_t index) { - return mapId >= 0 && mapId < NOTE_RETENTION_MAP_SLOTS && index >= 0 && index < NOTE_RETENTION_NOTES_PER_MAP; -} - -bool isCollected(int32_t mapId, int32_t index) { - NoteRetentionSaveData* s = store(); - if (s == nullptr || !indexInRange(mapId, index)) { - return false; - } - return (s->collected[mapId][index >> 3] >> (index & 7)) & 1; -} - -void setCollected(int32_t mapId, int32_t index) { - NoteRetentionSaveData* s = store(); - if (s == nullptr || !indexInRange(mapId, index)) { - return; - } - s->collected[mapId][index >> 3] |= (uint8_t)(1 << (index & 7)); -} - -int32_t countCollectedForLevel(int32_t levelId) { - NoteRetentionSaveData* s = store(); - if (s == nullptr) { - return 0; - } - int32_t total = 0; - for (int32_t mapId = 0; mapId < NOTE_RETENTION_MAP_SLOTS; mapId++) { - // Count this map's collected bits first; only real maps that have been - // played ever get bits set. Skipping empties keeps us from calling - // map_getLevel on non-existent map ids (e.g. MAP_0_UNKNOWN), which crashes. - int32_t mapTotal = 0; - for (int32_t b = 0; b < NOTE_RETENTION_BYTES_PER_MAP; b++) { - uint8_t byte = s->collected[mapId][b]; - while (byte) { - mapTotal += byte & 1; - byte >>= 1; - } - } - if (mapTotal == 0) { - continue; - } - if (map_getLevel((enum map_e)mapId) == (enum level_e)levelId) { - total += mapTotal; - } - } - return total; -} - -} // namespace - -// Called from gsworld_load (the single entry that parses a map's cubes) before any -// cube is read. This is the reliable once-per-parse-pass signal -- it fires on every -// map load AND on intra-level warps/sub-area transitions that re-parse the cubes, -// even when OnMapLoad doesn't. Resetting the counter here keeps spawn-order indices -// stable across re-parses. The live-actor set is NOT cleared here: our note actors -// persist across map changes (they're only torn down by actorArray_free), so the set -// must persist too, or returning to a map would duplicate its still-live notes. -extern "C" void port_noteRetention_beginMapLoad(int32_t mapId) { - (void)mapId; - noteCounter = 0; - noteActorQueue.clear(); -} - -// Called from actorArray_free. At this point every note actor is gone, so drop the -// live-actor set and detach the ObjectExtension data. -extern "C" void port_noteRetention_onActorsFreed(void) { - for (auto& [key, marker] : activeNoteSet) { - ObjectExtension::GetInstance().Remove(marker); - } - activeNoteSet.clear(); - noteActorQueue.clear(); -} - -void RegisterNoteRetention_Init() { - COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { - s16* spawnPosition = va_arg(args, s16*); - s32 spriteAsset = va_arg(args, s32); - - if (!systemActive() || spriteAsset != kNoteSpriteAsset) { - return; - } - - int32_t mapId = (int32_t)gsworld_getMap(); - int32_t noteIndex = noteCounter++; - if (!indexInRange(mapId, noteIndex)) { - return; // out of addressable range: leave as a vanilla sprite prop - } - - // From here we own this note: suppress the static sprite prop. - *should = true; - - if (activeNoteSet.count(noteKey(mapId, noteIndex))) { - return; // a live actor already exists (re-parse): don't duplicate it - } - - if (applyEnabled() && isCollected(mapId, noteIndex)) { - return; // already collected and retention on: don't respawn it - } - - QueuedNote queued; - queued.pos[0] = spawnPosition[0]; - queued.pos[1] = spawnPosition[1]; - queued.pos[2] = spawnPosition[2]; - queued.mapId = mapId; - queued.noteIndex = noteIndex; - queued.spawned = false; - noteActorQueue.push_back(queued); - }); - - // Flush queued notes into actors. actor_new does not re-fire OnActorSpawn, so no recursion. - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - if (!systemActive() || noteActorQueue.empty()) { - return; - } - for (auto& q : noteActorQueue) { - if (q.spawned) { - continue; - } - int32_t pos[3]; - pos[0] = q.pos[0]; - pos[1] = q.pos[1]; - pos[2] = q.pos[2]; - Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); - ActorMarker* marker = (note != nullptr) ? note->marker : nullptr; - if (marker != nullptr) { - // Key on the marker (stable across the actor's life and what the collision event hands us). - ObjectExtension::GetInstance().Set(marker, NoteRetentionData(q.mapId, q.noteIndex)); - activeNoteSet[noteKey(q.mapId, q.noteIndex)] = marker; - } - q.spawned = true; - } - }); - - // Note bundles get spawn-order indices that continue after the map's static - // note count. We override the vanilla bundle spawn to substitute our own actor (carrying - // identity in local) and re-apply the vanilla fly-out physics. Detection is by the - // bundle's spawned actor type, so it stays romhack-agnostic. - COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, true, { - bundle_e bundleId = (bundle_e)va_arg(args, int); - BundleInfo* bundleInfo = va_arg(args, BundleInfo*); - va_arg(args, s32); // index within the bundle (unused: we use our own counter) - f32* position = va_arg(args, f32*); - Actor** actorOut = va_arg(args, Actor**); - - if (!systemActive() || bundleInfo == nullptr || bundleInfo->actor_id != ACTOR_51_MUSIC_NOTE) { - return; // not our note bundle: leave it to vanilla (or rando) - } - - int32_t mapId = (int32_t)gsworld_getMap(); - int32_t noteIndex = noteCounter++; - if (!indexInRange(mapId, noteIndex)) { - return; // out of addressable range: let vanilla spawn it normally - } - - // From here we own this note: suppress the vanilla bundle spawn. - *should = true; - - int64_t key = noteKey(mapId, noteIndex); - if (activeNoteSet.count(key)) { - return; // a live actor already exists (re-trigger this load): don't duplicate - } - if (applyEnabled() && isCollected(mapId, noteIndex)) { - return; // already collected and retention on: don't respawn it - } - - int32_t pos[3]; - pos[0] = (int32_t)position[0]; - pos[1] = (int32_t)position[1]; - pos[2] = (int32_t)position[2]; - Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); - if (note == nullptr) { - return; - } - NoteLocal* nl = reinterpret_cast(note->local); - nl->magic = kNoteLocalMagic; - nl->mapId = mapId; - nl->noteIndex = noteIndex; - - ApplyBundleActorPhysics(note, (int32_t)bundleId, bundleInfo, gBundle_yaw); - - activeNoteSet[key] = note->marker; - *actorOut = note; - }); - - // Prevent restoration from save states, as actors get re-added by the cubeprop parse. - COND_HOOK(OnLoadActorSaveState, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnLoadActorSaveState* ev = (OnLoadActorSaveState*)event; - if (!systemActive() || ev->actor == nullptr) { - return; - } - if ((int32_t)ev->actor->modelCacheIndex != ACTOR_51_MUSIC_NOTE) { - return; - } - if (ev->actor->is_bundle && bundleNoteLocal(ev->actor) != nullptr) { - return; // keep restored bundle notes alive - } - event->Cancelled = true; - }); - - // Record collection. Don't cancel: vanilla still increments ITEM_C_NOTE and despawns. - COND_HOOK(OnActorCollision, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnActorCollision* ev = (OnActorCollision*)event; - if (!systemActive() || !ev->propId->markerFlag) { - return; - } - ActorMarker* marker = ev->propId->actorProp.marker; - if (marker == nullptr || marker->id != MARKER_5F_MUSIC_NOTE) { - return; - } - int32_t mapId; - int32_t noteIndex; - NoteRetentionData* data = ObjectExtension::GetInstance().Get(marker); - if (data != nullptr) { - mapId = data->mapId; - noteIndex = data->noteIndex; - ObjectExtension::GetInstance().Remove(marker); - } else if (NoteLocal* nl = bundleNoteLocal(marker_getActor(marker))) { - mapId = nl->mapId; - noteIndex = nl->noteIndex; - nl->magic = 0; // consumed - } else { - return; // not one of ours - } - setCollected(mapId, noteIndex); - activeNoteSet.erase(noteKey(mapId, noteIndex)); - }); - - // Seed the level's note counter from collected notes so totals stay reachable. - COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnSetJiggyList* ev = (OnSetJiggyList*)event; - if (!systemActive() || !applyEnabled()) { - return; - } - item_set(ITEM_C_NOTE, countCollectedForLevel(ev->levelId)); - }); - - // With retention applied, the vanilla note-score messages become misleading or fire - // spuriously (seeding ITEM_C_NOTE on load re-triggers the high-score milestones), so - // suppress them while the CVar is on. - COND_VB_SHOULD(VB_OVERRIDE_DIALOG_SHOW, EVENT_PRIORITY_NORMAL, true, { - s32 textId = va_arg(args, s32); - if (!applyEnabled()) { - return; - } - switch (textId) { - case 0xD9C: // Bottles' first-note text: "you can't take notes with you" - case 0xF76: // "you just beat your high score" - case 0xF74: // milestone: 50 notes (Mumbo's Mountain) - *should = true; - break; - default: - break; - } - }); - - // Clean up per-marker data when actors are destroyed (marker pointers get reused). - COND_HOOK(OnActorDestroy, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnActorDestroy* ev = (OnActorDestroy*)event; - if (ev->actor == nullptr) { - return; - } - if (ev->actor->marker != nullptr) { - NoteRetentionData* data = ObjectExtension::GetInstance().Get(ev->actor->marker); - if (data != nullptr) { - activeNoteSet.erase(noteKey(data->mapId, data->noteIndex)); - } - ObjectExtension::GetInstance().Remove(ev->actor->marker); - } - if (NoteLocal* nl = bundleNoteLocal(ev->actor)) { - activeNoteSet.erase(noteKey(nl->mapId, nl->noteIndex)); - nl->magic = 0; - } - }); - - // The engine's save double-buffers into a scratch slot via bcopy, which doesn't - // reliably carry our note bits. Sync the live active slot's noteRetention into the - // buffer about to be serialized. - COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, CVAR_VALUE, [](IEvent* event) { - OnSaveFileSave* ev = (OnSaveFileSave*)event; - SaveData* buf = (SaveData*)ev->saveBuffer; - NoteRetentionSaveData* live = store(); - if (buf != nullptr && live != nullptr && &buf->shipSaveData.noteRetention != live) { - buf->shipSaveData.noteRetention = *live; - } - }); -} - -static RegisterShipInitFunc initNoteRetention(RegisterNoteRetention_Init); diff --git a/src/port/Enhancements/NoteRetention/NoteRetention.h b/src/port/Enhancements/NoteRetention/NoteRetention.h deleted file mode 100644 index 9022e9bef..000000000 --- a/src/port/Enhancements/NoteRetention/NoteRetention.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef PORT_NOTE_RETENTION_H -#define PORT_NOTE_RETENTION_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void port_noteRetention_beginMapLoad(int32_t mapId); -void port_noteRetention_onActorsFreed(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/port/Enhancements/Restorations/ReturnToLair.cpp b/src/port/Enhancements/Restorations/ReturnToLair.cpp index 8de5916f2..b19587756 100644 --- a/src/port/Enhancements/Restorations/ReturnToLair.cpp +++ b/src/port/Enhancements/Restorations/ReturnToLair.cpp @@ -8,9 +8,9 @@ #include "include/core2/anctrl.h" #include "include/core2/gc/zoombox.h" -extern "C" struct1Bs D_8036C560[]; -extern "C" enum level_e level_get(void); -extern "C" bool fileProgressFlag_get(enum file_progress_e index); +#include "functions.h" + +extern "C" struct1Bs D_8036C560[]; // not declared in variables.h typedef struct struct_1A_s { f32 delay; diff --git a/src/port/Enhancements/Retention/JinjoRetention.cpp b/src/port/Enhancements/Retention/JinjoRetention.cpp new file mode 100644 index 000000000..e280ed9e5 --- /dev/null +++ b/src/port/Enhancements/Retention/JinjoRetention.cpp @@ -0,0 +1,271 @@ +// Jinjo Collection Retention +// +// Vanilla resets ITEM_12_JINJOS (per-level jinjo count) every level entry; this persists +// per-level collected colors across visits. +// +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Enhancements/Retention/Retention.h" +#include "port/Rando/Rando.h" +#include "port/Rando/CustomObject/CustomObject.h" + +#include "enums.h" +#include "actor.h" +#include "prop.h" +#include "functions.h" + +extern "C" int32_t port_jiggySpawn_isRecorded(int32_t jiggyId); + +static bool sForcedByAnchor = false; +#define CVAR_JINJO_RETENTION CVAR_ENHANCEMENT("Gameplay.JinjoRetention") +#define CVAR_VALUE (CVarGetInteger(CVAR_JINJO_RETENTION, 0) || sForcedByAnchor) + +constexpr u8 kAllJinjos = 0x1F; // all five color bits collected + +using retention::activeSlot; +using retention::systemActive; + +static bool applyEnabled() { + return CVAR_VALUE; +} + +extern "C" void port_jinjoRetention_setForced(int32_t forced) { + sForcedByAnchor = forced != 0; + ShipInit::Init(CVAR_JINJO_RETENTION); +} + +static JinjoRetentionSaveData* store() { + int32_t slot = activeSlot(); + return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.jinjoRetention : nullptr; +} + +extern "C" void port_jinjoRetention_getSizeAndPtr(int32_t* size, uint8_t** addr) { + JinjoRetentionSaveData* s = store(); + if (s == nullptr) { + *size = 0; + *addr = nullptr; + return; + } + *size = (int32_t)sizeof(JinjoRetentionSaveData); + *addr = (uint8_t*)s; +} + +static bool levelInRange(int32_t level) { + return level > 0 && level < JINJO_RETENTION_LEVEL_SLOTS; +} + +uint8_t collectedBits(int32_t level) { + JinjoRetentionSaveData* s = store(); + return (s != nullptr && levelInRange(level)) ? s->collected[level] : 0; +} + +void setCollectedBits(int32_t level, u8 bits) { + JinjoRetentionSaveData* s = store(); + if (s != nullptr && levelInRange(level)) { + s->collected[level] = bits; + } +} + +static enum jiggy_e jinjoJiggy(int32_t level) { + return (enum jiggy_e)(10 * level - 9); +} + +static u8 jinjoBitFromMarker(int32_t markerId) { + switch (markerId) { + case MARKER_5A_JINJO_BLUE: + case MARKER_5B_JINJO_GREEN: + case MARKER_5C_JINJO_ORANGE: + case MARKER_5D_JINJO_PINK: + case MARKER_5E_JINJO_YELLOW: + return (u8)(1 << ((markerId + 6) & 0x1F)); + default: + return 0; + } +} + +uint8_t jinjoBitFromActor(int32_t actorId) { + switch (actorId) { + case ACTOR_60_JINJO_BLUE: + return 1 << 0; + case ACTOR_62_JINJO_GREEN: + return 1 << 1; + case ACTOR_5F_JINJO_ORANGE: + return 1 << 2; + case ACTOR_61_JINJO_PINK: + return 1 << 3; + case ACTOR_5E_JINJO_YELLOW: + return 1 << 4; + default: + return 0; + } +} + +static int32_t jinjoActorFromBit(u8 bit) { + switch (bit) { + case 1 << 0: + return ACTOR_60_JINJO_BLUE; + case 1 << 1: + return ACTOR_62_JINJO_GREEN; + case 1 << 2: + return ACTOR_5F_JINJO_ORANGE; + case 1 << 3: + return ACTOR_61_JINJO_PINK; + case 1 << 4: + return ACTOR_5E_JINJO_YELLOW; + default: + return 0; + } +} + +extern "C" int32_t port_jinjoRetention_debugPickLive(void) { + static const enum actor_e kJinjoActors[] = { ACTOR_60_JINJO_BLUE, ACTOR_62_JINJO_GREEN, ACTOR_5F_JINJO_ORANGE, + ACTOR_61_JINJO_PINK, ACTOR_5E_JINJO_YELLOW }; + for (enum actor_e id : kJinjoActors) { + Actor* a = actorArray_findActorFromActorId(id); + if (a != nullptr && a->marker != nullptr) { + return jinjoBitFromActor(id); + } + } + return 0; +} + +extern "C" void port_jinjoRetention_applyRemoteCollect(int32_t map, int32_t bit, int32_t sameMap) { + int32_t level = map_getLevel((enum map_e)map); + JinjoRetentionSaveData* s = store(); + if (s != nullptr && levelInRange(level)) { + s->collected[level] |= (u8)bit; + } + // ITEM_12_JINJOS is per-level, not per-map; sub-areas are separate maps but share the count. + if (level == (int32_t)level_get()) { + item_set(ITEM_12_JINJOS, collectedBits(level)); + } + if (sameMap) { + int32_t actorId = jinjoActorFromBit((u8)bit); + if (actorId != 0) { + Actor* a = actorArray_findActorFromActorId((enum actor_e)actorId); + if (a != nullptr && a->marker != nullptr) { + marker_despawn(a->marker); + } + } + } +} + +// Called from the actual pickup (__chJinjo_802CDBA8), not broad-phase collision. +extern "C" void port_jinjoRetention_onLocalJinjoCollected(int32_t markerId) { + if (!systemActive()) { + return; + } + u8 bit = jinjoBitFromMarker(markerId); + if (bit == 0) { + return; + } + int32_t level = level_get(); + JinjoRetentionSaveData* s = store(); + bool wasSet = (s != nullptr) && levelInRange(level) && ((s->collected[level] & bit) != 0); + if (s != nullptr && levelInRange(level)) { + s->collected[level] |= bit; + } + if (!wasSet) { + CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_JINJO, bit); + } +} + +// False when retention is off, or when the jiggy is stranded (all 5 recorded but not +// collected/spawned). +static bool retentionActiveForLevel(int32_t level) { + if (!applyEnabled() || !levelInRange(level)) { + return false; + } + if (collectedBits(level) == kAllJinjos && !jiggyscore_isCollected(jinjoJiggy(level)) && + !jiggyscore_isSpawned(jinjoJiggy(level)) && !port_jiggySpawn_isRecorded(jinjoJiggy(level))) { + return false; + } + return true; +} + +void RegisterJinjoRetention_Init() { + // Seed ITEM_12_JINJOS from saved bits on entry. + COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnSetJiggyList* ev = (OnSetJiggyList*)event; + if (!systemActive() || !applyEnabled() || !levelInRange(ev->levelId)) { + return; + } + int32_t level = ev->levelId; + if (jiggyscore_isCollected(jinjoJiggy(level))) { + // Jiggy earned but record out of sync — force all five. + if (collectedBits(level) != kAllJinjos) { + setCollectedBits(level, kAllJinjos); + } + } else if (collectedBits(level) == kAllJinjos && !jiggyscore_isSpawned(jinjoJiggy(level)) && + !port_jiggySpawn_isRecorded(jinjoJiggy(level))) { + // Orphaned: all recorded but jiggy neither collected nor spawned. + setCollectedBits(level, 0); + } + if (!retentionActiveForLevel(level)) { + return; + } + u8 bits = collectedBits(ev->levelId); + if (bits != 0) { + item_adjustByDiffWithoutHud(ITEM_12_JINJOS, bits - item_getCount(ITEM_12_JINJOS)); + } + }); + + // Suppress respawn of already-collected jinjos; null result + Cancelled = no spawn. + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + if (!systemActive()) { + return; + } + u8 bit = jinjoBitFromActor(ev->actorId); + if (bit == 0) { + return; + } + int32_t level = level_get(); + if (!retentionActiveForLevel(level) || !(collectedBits(level) & bit)) { + return; + } + ev->result = nullptr; + event->Cancelled = true; + }); + + COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, CVAR_VALUE, { + (void)va_arg(args, int); + BundleInfo* bundleInfo = va_arg(args, BundleInfo*); + (void)va_arg(args, s32); + (void)va_arg(args, f32*); + (void)va_arg(args, Actor**); + + if (!systemActive() || bundleInfo == nullptr) { + return; + } + u8 bit = jinjoBitFromActor(bundleInfo->actor_id); + if (bit == 0) { + return; + } + int32_t level = level_get(); + if (!retentionActiveForLevel(level) || !(collectedBits(level) & bit)) { + return; + } + *should = true; + }); +} + +static RegisterShipInitFunc initJinjoRetention(RegisterJinjoRetention_Init, { CVAR_JINJO_RETENTION }); + +static void RegisterRetentionSaving_Init() { + // bcopy's scratch-slot save buffer doesn't carry our bits; sync them in. + COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { + OnSaveFileSave* ev = (OnSaveFileSave*)event; + SaveData* buf = (SaveData*)ev->saveBuffer; + JinjoRetentionSaveData* live = store(); + if (buf != nullptr && live != nullptr && &buf->shipSaveData.jinjoRetention != live) { + buf->shipSaveData.jinjoRetention = *live; + } + }); +} + +static RegisterShipInitFunc initRetentionSaving(RegisterRetentionSaving_Init); diff --git a/src/port/Enhancements/Retention/NoteRetention.cpp b/src/port/Enhancements/Retention/NoteRetention.cpp new file mode 100644 index 000000000..4c4d23bac --- /dev/null +++ b/src/port/Enhancements/Retention/NoteRetention.cpp @@ -0,0 +1,495 @@ +// Note Collection Retention +// +// Notes are identified by (mapId, spawn-order index) from the map's deterministic cube parse. +// Bundle notes store identity in actor->local (survives sub-area save/restore, which copies +// the actor struct but assigns a new marker). +// +#include "port/ObjectExtension/ObjectExtension.h" +#include +#include + +#include "port/UI/cvar_prefixes.h" +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Enhancements/Retention/Retention.h" +#include "port/Romhack/RomhackConfig.h" +#include "port/Rando/Rando.h" +#include "port/Rando/CustomObject/CustomObject.h" + +#include +#include +#include + +#include "functions.h" +extern "C" { +#include "enums.h" +#include "actor.h" +#include "prop.h" + +extern f32 gBundle_yaw; +extern ActorInfo sumusicNote; +} + +namespace { + +#define CVAR_NOTE_RETENTION CVAR_ENHANCEMENT("Gameplay.NoteRetention") +static bool sForcedByAnchor = false; +#define CVAR_VALUE (CVarGetInteger(CVAR_NOTE_RETENTION, 0) || sForcedByAnchor) + +constexpr s32 kNoteSpriteAsset = ASSET_6D6_SPRITE_MUSIC_NOTE; + +// Per-actor note identity. Parenthesized ctor avoids brace-init commas breaking event macros. +struct NoteRetentionData { + int32_t mapId; + int32_t noteIndex; + NoteRetentionData(int32_t map = 0, int32_t index = 0) : mapId(map), noteIndex(index) { + } +}; +ObjectExtension::Register NoteRetentionDataRegister; + +// Identity for bundle notes, stored in actor->local (survives sub-area restore; a new marker +// is assigned, so an extension wouldn't). magic distinguishes our data from garbage. +constexpr uint32_t kNoteLocalMagic = 0x4E4F5445u; // 'NOTE' +struct NoteLocal { + uint32_t magic; + int32_t mapId; + int32_t noteIndex; +}; + +NoteLocal* bundleNoteLocal(Actor* actor) { + if (actor == nullptr) { + return nullptr; + } + NoteLocal* nl = reinterpret_cast(actor->local); + return (nl->magic == kNoteLocalMagic) ? nl : nullptr; +} + +struct QueuedNote { + int32_t pos[3]; + int32_t mapId; + int32_t noteIndex; + bool spawned; +}; + +int32_t noteCounter = 0; +std::vector noteActorQueue; +std::unordered_map activeNoteSet; + +// Notes taken since entering this level: reproduces the prop "taken" bit they lost to actors. +std::unordered_set collectedThisVisit; +int32_t sVisitLevel = -1; + +int64_t noteKey(int32_t mapId, int32_t noteIndex) { + return ((int64_t)mapId << 32) | (uint32_t)noteIndex; +} + +// 0 for maps outside the section table; map_getLevel would deref null on those. +int32_t levelOfMap(int32_t map) { + if (map <= 0 || map >= MAP_NUM_MAPS) { + return 0; + } + return (int32_t)map_getLevel((enum map_e)map); +} + +using retention::activeSlot; +using retention::systemActive; + +// Level whose note count is waiting to be seeded; -1 when nothing is pending. +int32_t sPendingSeedLevel = -1; + +bool applyEnabled() { + return CVAR_VALUE; +} + +// Rando drives note props on this same VB when they're shuffled, writing *should for every one +// of them — hand the class over rather than race it on listener order. +bool randoOwnsNoteProps() { + return IS_RANDO && RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue; +} + +NoteRetentionSaveData* store() { + int32_t slot = activeSlot(); + return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.noteRetention : nullptr; +} + +bool indexInRange(int32_t mapId, int32_t index) { + return mapId >= 0 && mapId < NOTE_RETENTION_MAP_SLOTS && index >= 0 && index < NOTE_RETENTION_NOTES_PER_MAP; +} + +bool isCollected(int32_t mapId, int32_t index) { + NoteRetentionSaveData* s = store(); + if (s == nullptr || !indexInRange(mapId, index)) { + return false; + } + return (s->collected[mapId][index >> 3] >> (index & 7)) & 1; +} + +void setCollected(int32_t mapId, int32_t index) { + NoteRetentionSaveData* s = store(); + if (s == nullptr || !indexInRange(mapId, index)) { + return; + } + s->collected[mapId][index >> 3] |= (uint8_t)(1 << (index & 7)); +} + +int32_t countCollectedForLevel(int32_t levelId) { + NoteRetentionSaveData* s = store(); + if (s == nullptr) { + return 0; + } + int32_t total = 0; + for (int32_t mapId = 0; mapId < NOTE_RETENTION_MAP_SLOTS; mapId++) { + // Skip empty maps: map_getLevel crashes on non-existent ids (e.g. MAP_0_UNKNOWN). + int32_t mapTotal = 0; + for (int32_t b = 0; b < NOTE_RETENTION_BYTES_PER_MAP; b++) { + uint8_t byte = s->collected[mapId][b]; + while (byte) { + mapTotal += byte & 1; + byte >>= 1; + } + } + if (mapTotal == 0) { + continue; + } + if (map_getLevel((enum map_e)mapId) == (enum level_e)levelId) { + total += mapTotal; + } + } + return total; +} + +bool isInParade() { + return volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) || + volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE); +} + +} // namespace + +extern "C" void port_noteRetention_getSizeAndPtr(int32_t* size, uint8_t** addr) { + NoteRetentionSaveData* s = store(); + if (s == nullptr) { + *size = 0; + *addr = nullptr; + return; + } + *size = (int32_t)sizeof(NoteRetentionSaveData); + *addr = (uint8_t*)s; +} + +// Called from the actual pickup (MARKER_5F_MUSIC_NOTE), not broad-phase collision. +extern "C" void port_noteRetention_onLocalNoteCollected(void* markerPtr) { + if (!systemActive()) { + return; + } + ActorMarker* marker = (ActorMarker*)markerPtr; + if (marker == nullptr || marker->id != MARKER_5F_MUSIC_NOTE) { + return; + } + int32_t mapId; + int32_t noteIndex; + NoteRetentionData* data = ObjectExtension::GetInstance().Get(marker); + if (data != nullptr) { + mapId = data->mapId; + noteIndex = data->noteIndex; + ObjectExtension::GetInstance().Remove(marker); + } else if (NoteLocal* nl = bundleNoteLocal(marker_getActor(marker))) { + mapId = nl->mapId; + noteIndex = nl->noteIndex; + nl->magic = 0; // consumed + } else { + return; // not one of ours + } + bool wasCollected = isCollected(mapId, noteIndex); + setCollected(mapId, noteIndex); + collectedThisVisit.insert(noteKey(mapId, noteIndex)); + activeNoteSet.erase(noteKey(mapId, noteIndex)); + if (!wasCollected) { + CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_NOTE, noteIndex); + } +} + +extern "C" void port_noteRetention_applyRemoteCollect(int32_t mapId, int32_t noteIndex, int32_t sameMap) { + bool already = isCollected(mapId, noteIndex); + setCollected(mapId, noteIndex); + if (!already) { + // ITEM_C_NOTE is per-level; item_inc also bumps the high score and pause total. + int32_t level = map_getLevel((enum map_e)mapId); + if (level == (int32_t)level_get()) { + item_inc(ITEM_C_NOTE); + } else { + // Different level: can't touch live ITEM_C_NOTE, still bump its high score. + itemscore_noteScores_setLevel((enum level_e)level, countCollectedForLevel(level)); + } + } + if (sameMap) { + // Erase before despawn: OnActorDestroy's hook also erases this key. + auto it = activeNoteSet.find(noteKey(mapId, noteIndex)); + if (it != activeNoteSet.end()) { + ActorMarker* m = it->second; + activeNoteSet.erase(it); + if (m != nullptr) { + marker_despawn(m); + } + } + } +} + +// Called from gsworld_load before cube parsing; fires on every re-parse (map load, intra- +// level warps). Resets the index counter. +extern "C" void port_noteRetention_beginMapLoad(int32_t mapId) { + noteCounter = 0; + noteActorQueue.clear(); + // Sub-area hops stay within the visit; only a real level change lets notes come back. + int32_t level = levelOfMap(mapId); + if (level != sVisitLevel) { + sVisitLevel = level; + collectedThisVisit.clear(); + } +} + +extern "C" void port_noteRetention_onActorsFreed(void) { + for (auto& [key, marker] : activeNoteSet) { + ObjectExtension::GetInstance().Remove(marker); + } + activeNoteSet.clear(); + noteActorQueue.clear(); +} + +extern "C" void port_noteRetention_setForced(int32_t forced) { + sForcedByAnchor = forced != 0; + ShipInit::Init(CVAR_NOTE_RETENTION); +} + +extern "C" int32_t port_noteRetention_debugPickLive(int32_t mapId) { + for (auto& [key, marker] : activeNoteSet) { + int32_t keyMap = (int32_t)(key >> 32); + int32_t index = (int32_t)(uint32_t)(key & 0xFFFFFFFF); + if (keyMap == mapId && !isCollected(keyMap, index)) { + return index; + } + } + return -1; +} + +void RegisterNoteRetention_Init() { + // Bundle notes continue the map's index counter; identity stored in actor->local. + COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, true, { + bundle_e bundleId = (bundle_e)va_arg(args, int); + BundleInfo* bundleInfo = va_arg(args, BundleInfo*); + va_arg(args, s32); // index within the bundle (unused) + f32* position = va_arg(args, f32*); + Actor** actorOut = va_arg(args, Actor**); + + if (!systemActive() || bundleInfo == nullptr || bundleInfo->actor_id != ACTOR_51_MUSIC_NOTE) { + return; // not our note bundle + } + + int32_t mapId = (int32_t)gsworld_getMap(); + int32_t noteIndex = noteCounter++; + if (!indexInRange(mapId, noteIndex)) { + return; // out of addressable range + } + + // We own this note: suppress the vanilla bundle spawn. + *should = true; + + int64_t key = noteKey(mapId, noteIndex); + if (activeNoteSet.count(key)) { + return; // a live actor already exists (re-trigger this load) + } + if ((applyEnabled() && isCollected(mapId, noteIndex)) || collectedThisVisit.count(key)) { + return; + } + + int32_t pos[3]; + pos[0] = (int32_t)position[0]; + pos[1] = (int32_t)position[1]; + pos[2] = (int32_t)position[2]; + Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); + if (note == nullptr) { + return; + } + NoteLocal* nl = reinterpret_cast(note->local); + nl->magic = kNoteLocalMagic; + nl->mapId = mapId; + nl->noteIndex = noteIndex; + + ApplyBundleActorPhysics(note, (int32_t)bundleId, bundleInfo, gBundle_yaw); + + activeNoteSet[key] = note->marker; + *actorOut = note; + }); + + // Seed the level's note counter from collected notes. + COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnSetJiggyList* ev = (OnSetJiggyList*)event; + sPendingSeedLevel = ev->levelId; + }); + + COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent*) { + if (sPendingSeedLevel < 0) { + return; + } + if (getGameMode() != GAME_MODE_3_NORMAL) { + // Demo or playback: drop the seed, its score state is scratch. Anything else + // (transition, pause) just waits for normal play to resume. + if (func_802E4A08()) { + sPendingSeedLevel = -1; + } + return; + } + const int32_t level = sPendingSeedLevel; + sPendingSeedLevel = -1; + if (!systemActive() || !applyEnabled() || isInParade()) { + return; + } + item_adjustByDiffWithoutHud(ITEM_C_NOTE, countCollectedForLevel(level) - item_getCount(ITEM_C_NOTE)); + }); + + // Seeding ITEM_C_NOTE re-triggers vanilla high-score dialogs; suppress them. + COND_VB_SHOULD(VB_OVERRIDE_DIALOG_SHOW, EVENT_PRIORITY_NORMAL, true, { + s32 textId = va_arg(args, s32); + // Bottles' 50-note-door line assumes vanilla note-door costs, which + // romhacks retune, so it is wrong for them whether or not retention is + // on. In vanilla it stays: it's an aide for new players. + if (textId == 0xF74 && port_isRomhack()) { + *should = true; + } else if (applyEnabled()) { + switch (textId) { + case 0xD9C: // Bottles' first-note text: "you can't take notes with you" + case 0xF76: // "you just beat your high score" + // 0xF78 (every note in the level) is left alone here; hacks that + // want it gone suppress it per-hack, as Gruntch does. + *should = true; + break; + default: + break; + } + } + }); +} + +static RegisterShipInitFunc initNoteRetention(RegisterNoteRetention_Init, { CVAR_NOTE_RETENTION }); + +// Always registered: the sprite-prop pickup path has no marker to record through, so notes must +// be actors even when the enhancement isn't applying. Only the suppression below is gated. +static void RegisterRetentionSaving_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { + collectedThisVisit.clear(); + sVisitLevel = -1; + }); + + // The cube parse rebuilds static notes every map load, so a restored copy would double them + // on a sub-area round trip. Bundle notes have no parse to come from and must survive. + REGISTER_LISTENER(OnLoadActorSaveState, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnLoadActorSaveState* ev = (OnLoadActorSaveState*)event; + if (!systemActive() || ev->actor == nullptr) { + return; + } + if ((int32_t)ev->actor->modelCacheIndex != ACTOR_51_MUSIC_NOTE) { + return; + } + if (ev->actor->is_bundle && bundleNoteLocal(ev->actor) != nullptr) { + return; // keep restored bundle notes alive + } + event->Cancelled = true; + }); + + COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { + s16* spawnPosition = va_arg(args, s16*); + s32 spriteAsset = va_arg(args, s32); + + if (!systemActive() || spriteAsset != kNoteSpriteAsset) { + return; + } + + int32_t mapId = (int32_t)gsworld_getMap(); + int32_t noteIndex = noteCounter++; + if (!indexInRange(mapId, noteIndex)) { + return; // out of addressable range + } + + // Counter already advanced, so indices stay aligned; rando spawns these itself. + if (randoOwnsNoteProps()) { + return; + } + + // We own this note: suppress the static sprite prop. + *should = true; + + if (activeNoteSet.count(noteKey(mapId, noteIndex))) { + return; // a live actor already exists (re-parse) + } + + if ((applyEnabled() && isCollected(mapId, noteIndex)) || collectedThisVisit.count(noteKey(mapId, noteIndex))) { + return; + } + + QueuedNote queued; + queued.pos[0] = spawnPosition[0]; + queued.pos[1] = spawnPosition[1]; + queued.pos[2] = spawnPosition[2]; + queued.mapId = mapId; + queued.noteIndex = noteIndex; + queued.spawned = false; + noteActorQueue.push_back(queued); + }); + + // Flush queued notes into actors. actor_new does not re-fire OnActorSpawn. + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { + if (!systemActive() || noteActorQueue.empty()) { + return; + } + for (auto& q : noteActorQueue) { + if (q.spawned) { + continue; + } + int32_t pos[3]; + pos[0] = q.pos[0]; + pos[1] = q.pos[1]; + pos[2] = q.pos[2]; + Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); + if (note != nullptr) { + note->unk124_6 = 0; + } + ActorMarker* marker = (note != nullptr) ? note->marker : nullptr; + if (marker != nullptr) { + // Key on the marker (stable across the actor's life). + ObjectExtension::GetInstance().Set(marker, NoteRetentionData(q.mapId, q.noteIndex)); + activeNoteSet[noteKey(q.mapId, q.noteIndex)] = marker; + } + q.spawned = true; + } + }); + + COND_HOOK(OnActorDestroy, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { + OnActorDestroy* ev = (OnActorDestroy*)event; + if (ev->actor == nullptr) { + return; + } + if (ev->actor->marker != nullptr) { + NoteRetentionData* data = ObjectExtension::GetInstance().Get(ev->actor->marker); + if (data != nullptr) { + activeNoteSet.erase(noteKey(data->mapId, data->noteIndex)); + } + ObjectExtension::GetInstance().Remove(ev->actor->marker); + } + if (NoteLocal* nl = bundleNoteLocal(ev->actor)) { + activeNoteSet.erase(noteKey(nl->mapId, nl->noteIndex)); + nl->magic = 0; + } + }); + + // bcopy's scratch-slot save buffer doesn't carry our bits; sync them in. + COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { + OnSaveFileSave* ev = (OnSaveFileSave*)event; + SaveData* buf = (SaveData*)ev->saveBuffer; + NoteRetentionSaveData* live = store(); + if (buf != nullptr && live != nullptr && &buf->shipSaveData.noteRetention != live) { + buf->shipSaveData.noteRetention = *live; + } + }); +} + +static RegisterShipInitFunc initRetentionSaving(RegisterRetentionSaving_Init); diff --git a/src/port/Enhancements/Retention/Retention.cpp b/src/port/Enhancements/Retention/Retention.cpp new file mode 100644 index 000000000..0c26dfc39 --- /dev/null +++ b/src/port/Enhancements/Retention/Retention.cpp @@ -0,0 +1,31 @@ +// Helpers shared by the note and jinjo retention systems. +// +// libultraship must precede the decomp headers: core2/timedfunc.h (via functions.h) defines a +// C-compat `reinterpret_cast` macro that breaks the MSVC C++ standard library. +#include +#include "port/Enhancements/Retention/Retention.h" +#include "port/Rando/Rando.h" // selectedFileNum, gameFile_saveData, DEFAULT_FILE_NUM, FILE_TYPE_SAVE_RANDO + +#include "functions.h" +extern "C" { +#include "enums.h" +} + +namespace retention { + +int32_t activeSlot() { + if (selectedFileNum == DEFAULT_FILE_NUM || selectedFileNum < 0 || selectedFileNum >= 4) { + return -1; + } + return (int32_t)selectedFileNum; +} + +bool systemActive() { + int32_t slot = activeSlot(); + if (slot < 0 || gameFile_saveData[slot].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { + return false; + } + return !func_802E4A08(); +} + +} // namespace retention diff --git a/src/port/Enhancements/Retention/Retention.h b/src/port/Enhancements/Retention/Retention.h new file mode 100644 index 000000000..63a19352a --- /dev/null +++ b/src/port/Enhancements/Retention/Retention.h @@ -0,0 +1,80 @@ +#ifndef PORT_RETENTION_H +#define PORT_RETENTION_H + +// Shared header for the vanilla collectible-retention systems (notes and jinjos). + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// --- Note retention --- + +void port_noteRetention_beginMapLoad(int32_t mapId); +void port_noteRetention_onActorsFreed(void); + +// Live slot's note-retention bytes for Anchor team-state sync (size 0 / null if no slot). +void port_noteRetention_getSizeAndPtr(int32_t* size, uint8_t** addr); + +void port_noteRetention_applyRemoteCollect(int32_t mapId, int32_t noteIndex, int32_t sameMap); + +// Record + broadcast a local note pickup (marker is ActorMarker*, void* to avoid engine types). +void port_noteRetention_onLocalNoteCollected(void* marker); + +// Force retention on/off regardless of the user CVar (Anchor uses this while connected). +void port_noteRetention_setForced(int32_t forced); + +// --- Jinjo retention --- + +// Live slot's jinjo-retention bytes for Anchor team-state sync (size 0 / null if no slot). +void port_jinjoRetention_getSizeAndPtr(int32_t* size, uint8_t** addr); + +void port_jinjoRetention_applyRemoteCollect(int32_t map, int32_t bit, int32_t sameMap); + +// Record + broadcast a local jinjo pickup. Call from the actual collection, not proximity. +void port_jinjoRetention_onLocalJinjoCollected(int32_t markerId); + +// Force retention on/off regardless of the user CVar (Anchor uses this while connected). +void port_jinjoRetention_setForced(int32_t forced); + +// --- CCW carried-collectible live-despawn sync (worms for Eyrie, acorns for Nabnut) --- +// +// Carried count is ITEM_22/23. Object identity is a hash of its fixed spawn position. `kind` = +// ANCHOR_COLLECTIBLE_WORM/_ACORN; marker is ActorMarker* (void* to avoid engine types). + +void port_carriedSync_beginMapLoad(int32_t mapId); + +// Registers a world object, attaching spawn-position identity to the marker. Sets *suppress +// non-zero if a teammate already collected it. +void port_carriedSync_register(int32_t kind, void* marker, int32_t x, int32_t y, int32_t z, int32_t* suppress); + +void port_carriedSync_onLocalCollect(int32_t kind, void* marker); + +// Broadcast a local spend (feeding Eyrie/Nabnut): -1 to the shared pool. +void port_carriedSync_onLocalSpend(int32_t kind); + +// Apply a teammate's pickup (id = spawn-position hash): marks it collected. +void port_carriedSync_applyRemoteCollect(int32_t kind, int32_t mapId, int32_t id, int32_t sameMap); + +// True if a teammate collected this object (caller should despawn). +int32_t port_carriedSync_consumeRemoteDespawn(int32_t kind, void* marker); + +int32_t port_carriedSync_collectedCount(int32_t kind); + +void setCollectedBits(int32_t level, u8 bits); +uint8_t jinjoBitFromActor(int32_t actorId); +uint8_t collectedBits(int32_t level); + +#ifdef __cplusplus +} + +namespace retention { +// Active save slot index (0-3) for the current game, or -1 (default/demo file). +int32_t activeSlot(); +// False during demos, Bottles bonus games, and rando files. +bool systemActive(); +} // namespace retention +#endif + +#endif diff --git a/src/port/Enhancements/Retention/WormSync.cpp b/src/port/Enhancements/Retention/WormSync.cpp new file mode 100644 index 000000000..b2716fd09 --- /dev/null +++ b/src/port/Enhancements/Retention/WormSync.cpp @@ -0,0 +1,199 @@ +// CCW Carried-Collectible Live-Despawn Sync (worms for Eyrie, acorns for Nabnut). +// +// Carried count is ITEM_22/23. Object identity is a hash of its fixed spawn position, keyed +// with (kind, mapId, hash). +// +#include +#include "port/ObjectExtension/ObjectExtension.h" +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Enhancements/Retention/Retention.h" + +#include +#include + +#include "functions.h" +extern "C" { +#include "enums.h" +#include "actor.h" +} + +namespace { + +// Per-object identity. Parenthesized ctor avoids brace-init commas breaking event macros. +struct CarriedSpawnData { + int32_t mapId; + int32_t hash; + CarriedSpawnData(int32_t m = 0, int32_t h = 0) : mapId(m), hash(h) { + } +}; +ObjectExtension::Register CarriedSpawnDataRegister; + +// (slot, mapId, hash) of every carried collectible the team has picked up this session. +std::set> sCollected; + +int32_t slotForKind(int32_t kind) { + switch (kind) { + case ANCHOR_COLLECTIBLE_WORM: + return 0; + case ANCHOR_COLLECTIBLE_ACORN: + return 1; + case ANCHOR_COLLECTIBLE_PRESENT_BLUE: + return 2; + case ANCHOR_COLLECTIBLE_PRESENT_GREEN: + return 3; + case ANCHOR_COLLECTIBLE_PRESENT_RED: + return 4; + case ANCHOR_COLLECTIBLE_GOLD: + return 5; + case ANCHOR_COLLECTIBLE_ORANGE: + return 6; + default: + return -1; + } +} + +// Identity from spawn position; masked non-negative to avoid the -1 spend sentinel. +int32_t spawnHash(int32_t x, int32_t y, int32_t z) { + uint32_t h = (uint32_t)x * 73856093u ^ (uint32_t)y * 19349663u ^ (uint32_t)z * 83492791u; + return (int32_t)(h & 0x7FFFFFFFu); +} + +bool isCollected(int32_t slot, int32_t mapId, int32_t hash) { + return sCollected.count({ slot, mapId, hash }) != 0; +} + +// Gold and the presents feed a credit-back reconcile that rebuilds carried counts as +// collected-minus-delivered. Respawn suppression and that credit must fire together +// or a collected item is lost across a reload, so both are scoped to the consumer's +// level; outside it, neither runs and the collectible simply respawns, as on hardware. +bool kindAllowedFor(int32_t kind, int32_t mapId) { + switch (kind) { + case ANCHOR_COLLECTIBLE_GOLD: + return (int32_t)map_getLevel((enum map_e)mapId) == LEVEL_2_TREASURE_TROVE_COVE; + case ANCHOR_COLLECTIBLE_PRESENT_BLUE: + case ANCHOR_COLLECTIBLE_PRESENT_GREEN: + case ANCHOR_COLLECTIBLE_PRESENT_RED: + return (int32_t)map_getLevel((enum map_e)mapId) == LEVEL_5_FREEZEEZY_PEAK; + default: + return true; + } +} + +bool inDemoPlayback() { + return func_802E4A08() != 0; +} + +} // namespace + +extern "C" void port_carriedSync_beginMapLoad(int32_t mapId) { + (void)mapId; +} + +extern "C" void port_carriedSync_register(int32_t kind, void* marker, int32_t x, int32_t y, int32_t z, + int32_t* suppress) { + *suppress = 0; + int32_t slot = slotForKind(kind); + if (slot < 0 || marker == nullptr) { + return; + } + int32_t mapId = (int32_t)gsworld_getMap(); + int32_t hash = spawnHash(x, y, z); + ObjectExtension::GetInstance().Set(marker, CarriedSpawnData(mapId, hash)); + if (!inDemoPlayback() && kindAllowedFor(kind, mapId) && isCollected(slot, mapId, hash)) { + *suppress = 1; + } +} + +extern "C" void port_carriedSync_onLocalCollect(int32_t kind, void* marker) { + int32_t slot = slotForKind(kind); + if (slot < 0 || inDemoPlayback()) { + return; + } + CarriedSpawnData* d = ObjectExtension::GetInstance().Get(marker); + if (d == nullptr) { + return; + } + sCollected.insert({ slot, d->mapId, d->hash }); + CALL_EVENT(OnCollectibleCollected, kind, d->hash); +} + +extern "C" void port_carriedSync_onLocalSpend(int32_t kind) { + if (slotForKind(kind) < 0 || inDemoPlayback()) { + return; + } + // A spend (feeding Eyrie/Nabnut) is -1 to the shared pool. + CALL_EVENT(OnCollectibleCollected, kind, -1); +} + +extern "C" void port_carriedSync_applyRemoteCollect(int32_t kind, int32_t mapId, int32_t id, int32_t sameMap) { + (void)sameMap; + int32_t slot = slotForKind(kind); + if (slot < 0 || id < 0) { + return; + } + sCollected.insert({ slot, mapId, id }); +} + +// Snapshot/restore as flat [slot, mapId, hash] tuples. +std::vector port_carriedSync_snapshotCollected() { + std::vector flat; + flat.reserve(sCollected.size() * 3); + for (const auto& e : sCollected) { + flat.insert(flat.end(), e.begin(), e.end()); + } + return flat; +} + +void port_carriedSync_restoreCollected(const std::vector& flat) { + sCollected.clear(); + for (size_t i = 0; i + 3 <= flat.size(); i += 3) { + sCollected.insert({ flat[i], flat[i + 1], flat[i + 2] }); + } +} + +extern "C" int32_t port_carriedSync_collectedCount(int32_t kind) { + int32_t slot = slotForKind(kind); + if (slot < 0) { + return 0; + } + int32_t count = 0; + for (const auto& e : sCollected) { + if (e[0] == slot && kindAllowedFor(kind, e[1])) { + count++; + } + } + return count; +} + +void port_carriedSync_clearForLevel(int32_t levelId) { + std::erase_if(sCollected, [levelId](const std::array& e) { + return (int32_t)map_getLevel((enum map_e)e[1]) == levelId; + }); +} + +extern "C" int32_t port_carriedSync_consumeRemoteDespawn(int32_t kind, void* marker) { + int32_t slot = slotForKind(kind); + if (slot < 0) { + return 0; + } + CarriedSpawnData* d = ObjectExtension::GetInstance().Get(marker); + if (d == nullptr) { + return 0; + } + return isCollected(slot, d->mapId, d->hash) ? 1 : 0; +} + +void RegisterWormSync_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sCollected.clear(); }); + + REGISTER_LISTENER(OnActorDestroy, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnActorDestroy* ev = (OnActorDestroy*)event; + if (ev->actor != nullptr && ev->actor->marker != nullptr) { + ObjectExtension::GetInstance().Remove(ev->actor->marker); + } + }); +} + +static RegisterShipInitFunc initWormSync(RegisterWormSync_Init, {}); diff --git a/src/port/Enhancements/Trackers/DisplayOverlay.cpp b/src/port/Enhancements/Trackers/DisplayOverlay.cpp index bc8bdf4be..97a97f822 100644 --- a/src/port/Enhancements/Trackers/DisplayOverlay.cpp +++ b/src/port/Enhancements/Trackers/DisplayOverlay.cpp @@ -10,20 +10,12 @@ #include "save.h" #include "enums.h" +#include "functions.h" extern "C" { -enum map_e gsworld_getMap(void); -enum level_e map_getLevel(enum map_e map); -u16 itemscore_timeScores_get(enum level_e level_id); - -uint64_t GetUnixTimestamp(); extern SaveData gameFile_saveData[4]; } -float windowScale = 1.0f; -ImVec4 windowBG = ImVec4(0, 0, 0, 0.5f); -static constexpr ImVec4 tintColor = {}; - const std::vector timerDisplayOptions = { "Display Off", // TIMER_DISPLAY_NONE "Real-Time", // TIMER_DISPLAY_RTA @@ -39,7 +31,7 @@ int64_t DisplayOverlay_GetTotalInGameTime() { } void DisplayOverlayWindow::Draw() { - if (!IsVisible() || gsworld_getMap() == MAP_91_FILE_SELECT) { + if (gsworld_getMap() == MAP_91_FILE_SELECT) { return; } diff --git a/src/port/Extractor/GameExtractor.cpp b/src/port/Extractor/GameExtractor.cpp index cb82abfb3..d20911f0e 100644 --- a/src/port/Extractor/GameExtractor.cpp +++ b/src/port/Extractor/GameExtractor.cpp @@ -14,6 +14,7 @@ #include #include "ship/Context.h" +#include "port/FilePicker.h" #include "spdlog/spdlog.h" #include @@ -27,10 +28,7 @@ #ifndef __SWITCH__ #include "Companion.h" #include "factories/bk64/ConfigFactory.h" - -#if !defined(__IOS__) && !defined(__ANDROID__) && !defined(__SWITCH__) -#include "portable-file-dialogs.h" -#endif +#include "port/Romhack/RomhackTable.h" std::string GameExtractor::sStatusText; std::string GameExtractor::sLastError; @@ -97,53 +95,21 @@ bool GameExtractor::RunStandalone(std::string rom) { return true; } -bool GameExtractor::SelectGameFromUI() { - //// Store both path and already-read data - std::string romPath; - std::vector romData; - -#if !defined(__IOS__) && !defined(__ANDROID__) && !defined(__SWITCH__) - // Desktop: fallback to file dialogue if no baserom found - // if (!foundGame) { - if (!pfd::settings::available()) { - SPDLOG_ERROR("portable-file-dialogs is not available on this system."); +// Load a ROM from disk into mGameData. The caller does the picking (asynchronously on the boot path — +// see Engine.cpp PS_FIRST/PS_FIRST_WAIT), so this is just the read. +bool GameExtractor::LoadRomFromPath(const std::string& romPath) { + if (!std::filesystem::exists(romPath)) { + SPDLOG_ERROR("Failed to find ROM at path: {}", romPath); return false; } - auto selection = pfd::open_file("Select a file", ".", { "N64 Roms", "*.z64" }).result(); - if (selection.empty()) { - return false; - } - - romPath = selection[0]; - //} -#else - // Mobile: fallback to baserom.us.z64 - if (/*!foundGame && */ !std::filesystem::exists(Ship::Context::GetPathRelativeToAppDirectory("baserom.us.z64"))) { - SPDLOG_ERROR("baserom not found"); + std::ifstream inFile(romPath, std::ios::binary); + if (!inFile.is_open()) { return false; } - // if (!foundGame) { - romPath = Ship::Context::GetPathRelativeToAppDirectory("baserom.us.z64"); - //} -#endif - - // Load file if it is not already open - if (romData.empty()) { - if (!std::filesystem::exists(romPath)) { - SPDLOG_ERROR("Failed to find ROM at path: {}", romPath); - return false; - } - - std::ifstream inFile(romPath, std::ios::binary); - if (!inFile.is_open()) { - return false; - } - - romData = std::vector(std::istreambuf_iterator(inFile), {}); - inFile.close(); - } + std::vector romData(std::istreambuf_iterator(inFile), {}); + inFile.close(); this->mGamePath = romPath; this->mGameData = std::move(romData); @@ -168,7 +134,7 @@ void GameExtractor::GetRoms(std::vector& roms) { // Check for any standard N64 rom file extensions. if (ext != NULL && (strcmp(ext, ".z64") == 0) /* || (strcmp(ext, ".n64") == 0) || (strcmp(ext, ".v64") == 0)*/) - roms.push_back(ffd.cFileName); + roms.push_back(mSearchPath + "/" + ffd.cFileName); } } while (FindNextFileA(h, &ffd) != 0); FindClose(h); @@ -182,20 +148,23 @@ void GameExtractor::GetRoms(std::vector& roms) { while ((dir = readdir(d)) != NULL) { struct stat path; - // Check if current entry is not folder - stat(dir->d_name, &path); - if (S_ISREG(path.st_mode)) { + // Against the full path: a bare name would be resolved relative to the + // working directory, so searching anywhere else stat'd the wrong file (or + // nothing) and left path uninitialised for the S_ISREG test below. + const std::string fullPath = mSearchPath + "/" + dir->d_name; + if (stat(fullPath.c_str(), &path) != 0 || !S_ISREG(path.st_mode)) { + continue; + } - // Get the position of the extension character. - char* ext = strrchr(dir->d_name, '.'); - if (ext != NULL && - (strcmp(ext, ".z64") == 0 /* || strcmp(ext, ".n64") == 0 || strcmp(ext, ".v64") == 0*/)) { - roms.push_back(dir->d_name); - } + // Get the position of the extension character. + char* ext = strrchr(dir->d_name, '.'); + if (ext != NULL && + (strcmp(ext, ".z64") == 0 /* || strcmp(ext, ".n64") == 0 || strcmp(ext, ".v64") == 0*/)) { + roms.push_back(fullPath); } } + closedir(d); } - closedir(d); #else for (const auto& file : std::filesystem::directory_iterator(mSearchPath)) { if (file.is_directory()) { @@ -339,9 +308,31 @@ bool GameExtractor::GenerateOTR(std::atomic& assetCount, std::atomicmGameData)) { - SPDLOG_WARN("[GameExtractor] Custom MIPS code detected in ROM; prompting user before extraction."); + // Detect custom code: an injected MIPS blob or a rebuilt code overlay. + BK64::CustomCodeKind ccKind = BK64::CustomCodeKind::NONE; + char ccSha1[41] = {}; + const bool hasBlob = BK64::GetCustomCodeBlobInfo(this->mGameData, ccKind, ccSha1); + const bool rebuiltOverlay = BK64::ClassifyRomhack(this->mGameData) == BK64::RomhackKind::CustomBuild; + bool promptCustomCode = rebuiltOverlay; + if (!promptCustomCode && hasBlob) { + if (const auto* entry = Lighthouse::LookupRomhackEntry(ccSha1)) { + // Known blob: the table's verdict beats the location heuristic — an + // isPorted=false row means analysis found real un-ported code even + // inside a globalization-kind blob (e.g. Nostalgia 64). + promptCustomCode = !entry->isPorted; + if (!promptCustomCode) { + SPDLOG_INFO("[GameExtractor] Custom code blob {} is ported ({}); no warning needed.", ccSha1, + entry->identifier); + } + } else { + // Unknown blob: only injected blobs warrant the prompt; the stock + // globalization framework is covered by the statically linked build. + promptCustomCode = (ccKind == BK64::CustomCodeKind::BB_INJECTED); + } + } + if (promptCustomCode) { + SPDLOG_WARN("[GameExtractor] Romhack ships custom code ({}); prompting user before extraction.", + rebuiltOverlay ? "rebuilt code overlay, non-BB build" : "injected MIPS code blob"); sCustomCodePromptResult = -1; sCustomCodePromptActive = true; sCustomCodePromptRequested = true; @@ -400,7 +391,7 @@ std::optional GameExtractor::ValidateChecksum() const { return std::nullopt; } -bool GameExtractor::SelectGameFromUI() { +bool GameExtractor::LoadRomFromPath(const std::string& romPath) { return false; } @@ -416,3 +407,18 @@ void GameExtractor::WritePortVersion() { // None } #endif + +// No #ifdef needed: Lighthouse::PickFile picks the backend (native dialog on desktop, ImGui browser +// on consoles/arm). The N64-ROM title/filters live here so libultraship stays game-agnostic. +void GameExtractor::SelectGameFromUI(std::function onComplete) { + Ship::FileBrowserRequest req; + req.Title = "Select a N64 ROM"; + req.Filters = { { "N64 ROMs (.z64, .n64, .v64)", { "*.z64", "*.n64", "*.v64" } }, { "All files", { "*" } } }; + Lighthouse::PickFile(std::move(req), + [this, onComplete = std::move(onComplete)](std::optional path) { + const bool ok = path.has_value() && LoadRomFromPath(path->string()); + if (onComplete) { + onComplete(ok); + } + }); +} diff --git a/src/port/Extractor/GameExtractor.h b/src/port/Extractor/GameExtractor.h index faa77dfcc..c754938f7 100644 --- a/src/port/Extractor/GameExtractor.h +++ b/src/port/Extractor/GameExtractor.h @@ -2,6 +2,8 @@ #include "Companion.h" #include +#include +#include #include #include #include @@ -11,7 +13,11 @@ class GameExtractor { static bool GenAssetFile(); std::optional ValidateChecksum() const; bool RunStandalone(std::string rom); - bool SelectGameFromUI(); + bool LoadRomFromPath(const std::string& romPath); + // Open the file picker for an N64 ROM, then load the choice into this extractor. onComplete + // reports whether a ROM was both picked and loaded. Treat as async: the extractor must outlive + // the pick (the boot flow keeps a long-lived instance; the Mod Menu holds a shared_ptr). + void SelectGameFromUI(std::function onComplete); void SetSearchPath(const std::string& path); void GetRoms(std::vector& roms); std::string GetRomPath(); diff --git a/src/port/FilePicker.cpp b/src/port/FilePicker.cpp new file mode 100644 index 000000000..438c242df --- /dev/null +++ b/src/port/FilePicker.cpp @@ -0,0 +1,66 @@ +#include "port/FilePicker.h" + +#if LIGHTHOUSE_NATIVE_FILE_DIALOG +#include +#include +#include "portable-file-dialogs.h" +#include "port/DevTools/ThreadWatchdog.h" +#endif + +namespace fs = std::filesystem; + +namespace Lighthouse { + +#if LIGHTHOUSE_NATIVE_FILE_DIALOG +// portable-file-dialogs takes a flat filter list: { label, "*.a *.b", label2, "*.c", ... }. +static std::vector ToPfdFilters(const std::vector& filters) { + std::vector out; + for (const auto& filter : filters) { + out.push_back(filter.Label); + std::string patterns; + for (const auto& pattern : filter.Patterns) { + if (!patterns.empty()) { + patterns += " "; + } + patterns += pattern; + } + out.push_back(patterns); + } + if (out.empty()) { + out = { "All Files", "*" }; + } + return out; +} +#endif + +void PickFile(Ship::FileBrowserRequest request, std::function)> onResult) { +#if LIGHTHOUSE_NATIVE_FILE_DIALOG + const std::string startDir = request.StartDir.empty() ? "." : request.StartDir.string(); + const std::vector filters = ToPfdFilters(request.Filters); + + std::optional result; + { + Lighthouse::ExpectedStall watchdogPause("native file dialog"); + if (request.Save) { + const std::string defaultPath = (fs::path(startDir) / request.DefaultName).string(); + std::string selection = pfd::save_file(request.Title, defaultPath, filters).result(); + if (!selection.empty()) { + result = fs::path(selection); + } + } else { + std::vector selection = pfd::open_file(request.Title, startDir, filters).result(); + if (!selection.empty()) { + result = fs::path(selection.front()); + } + } + } + if (onResult) { + onResult(result); + } +#else + request.OnResult = std::move(onResult); + Ship::FileBrowserWindow::Open(std::move(request)); +#endif +} + +} // namespace Lighthouse diff --git a/src/port/FilePicker.h b/src/port/FilePicker.h new file mode 100644 index 000000000..2cb6ff821 --- /dev/null +++ b/src/port/FilePicker.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +#include "ship/window/gui/FileBrowserWindow.h" + +// Desktop platforms have a usable native file dialog (portable-file-dialogs). Consoles and Linux +// handhelds (arm) generally lack a native dialog / display server, so they fall back to +// libultraship's in-game ImGui file browser. Define LIGHTHOUSE_NATIVE_FILE_DIALOG to override. +#ifndef LIGHTHOUSE_NATIVE_FILE_DIALOG +#if defined(__SWITCH__) || defined(__WIIU__) || (defined(__linux__) && (defined(__aarch64__) || defined(__arm__))) +#define LIGHTHOUSE_NATIVE_FILE_DIALOG 0 +#else +#define LIGHTHOUSE_NATIVE_FILE_DIALOG 1 +#endif +#endif + +namespace Lighthouse { + +// Show a file picker described by @p request and deliver the chosen path (std::nullopt on cancel) to +// @p onResult. +// +// - Native builds (desktop): a blocking portable-file-dialogs dialog. onResult fires synchronously +// on the calling thread before PickFile returns. +// - ImGui builds (consoles / arm-linux): libultraship's FileBrowserWindow. onResult fires later on +// the render thread; PickFile returns immediately and is safe to call from any thread. +// +// Callers written for the async form (kick off, then poll a flag the callback sets) work with both +// backends unchanged: the native path just sets that flag before returning. +void PickFile(Ship::FileBrowserRequest request, std::function)> onResult); + +} // namespace Lighthouse diff --git a/src/port/Game.cpp b/src/port/Game.cpp index 9cf767564..05a50561e 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -1,8 +1,13 @@ #include "Engine.h" +#include +#include #include #include #include #include +#include +#include +#include #include #include @@ -13,12 +18,15 @@ #endif #include +#include "DevTools/ThreadWatchdog.h" #include "GameStatus.h" -#include "Interpolation/AdaptiveFps.h" #include "Interpolation/FrameInterpolation.h" +#include "Nametag/Nametag.h" #include "Network/Anchor/Anchor.h" +#include "OS/OS.h" #include "Patches/Patches.h" #include "ShipUtils.h" +#include "ShipInit.hpp" #include "src/port/Enhancements/Events/Hooks/Events.h" #include "UI/LighthouseModMenuWindow.h" @@ -26,47 +34,219 @@ extern "C" { #include "enums.h" #include "core1/core1.h" #include "core1/main.h" -// Non-interactive demo/playback modes (attract demo, file playback, etc.) -- decomp gameloop.c -bool func_802E4A08(void); +#include "core1/thread5.h" +void viMgr_entry(void* arg); +void thread5_entry(void* arg); +void audioManagerThread_entry(void* arg); +void core1_15B30_sendMesg3ToRenderThread(void); +OSMesgQueue* thread5_getTaskQueue(void); +OSMesgQueue* thread5_getSyncQueue(void); +} + +// The game tick runs on its own thread and submits display lists through the +// decomp's thread5 queue; this thread stays behind as the RCP and event pump. +namespace { +std::atomic sGameThreadDone{ false }; +std::thread sGameThread; +thread_local bool tIsGameThread = false; + +// The interpolation pair a submitted list was built from, carried to whoever +// renders it. At most a couple are live at once. +struct InterpPair { + int prev = -1; + int curr = -1; + bool should = false; + uint64_t serial = 0; +}; +std::mutex sInterpMutex; +std::map sTaskInterp; +uint64_t sInterpSerial = 0; +// Submissions of slack before an unrendered pair is assumed dropped. The ring is +// 4 slots, so by then its trees have been recycled regardless. +constexpr uint64_t kInterpStaleAfter = 4; + +// Renderer calls made from tick code, run by the main loop between services. +std::mutex sSvcMutex; +std::condition_variable sSvcCv; +void (*sSvcFn)(void*) = nullptr; +void* sSvcArg = nullptr; +std::atomic sShutdownRequested{ false }; + +int sTitleMap = 0; + +void DrainRenderService() { + std::unique_lock lock(sSvcMutex); + if (sSvcFn != nullptr) { + auto* fn = sSvcFn; + void* arg = sSvcArg; + lock.unlock(); + fn(arg); + lock.lock(); + sSvcFn = nullptr; + sSvcCv.notify_all(); + } +} + +// False on the window thread, including everything that runs during init +// before the tick thread exists. +bool OnGameThread() { + return tIsGameThread; +} +} // namespace + +// A list is submitted while its tick is still recording, so the pair is +// captured here and travels with the task. +extern "C" void port_thread5_onSubmit(void* taskData) { + if (!OnGameThread() || (uintptr_t)taskData < 100) { + return; + } + struct ucode_task_data_s* task = (struct ucode_task_data_s*)taskData; + if (task->task_type != UCODE_TASK_TYPE_F3DEX && task->task_type != UCODE_TASK_TYPE_L3DEX) { + return; + } + InterpPair pair; + FrameInterpolation_GetRecordingPair(&pair.prev, &pair.curr, &pair.should); + FrameInterpolation_ClaimPair(pair.prev, pair.curr); + FrameInterpolation_StopRecord(); + Nametag::SubmitFrame(task->data_ptr); + std::lock_guard lock(sInterpMutex); + pair.serial = ++sInterpSerial; + auto [it, inserted] = sTaskInterp.emplace(task->data_ptr, pair); + if (!inserted) { + FrameInterpolation_ReleasePair(it->second.prev, it->second.curr); + it->second = pair; + } + + // Anything still here after a full trip round the ring can no longer be + // blended against a live tree, so its claim is only holding a slot hostage. + // Dropping the entry leaves RenderTask with a -1 pair, which renders + // uninterpolated rather than against a recycled tree. + for (auto stale = sTaskInterp.begin(); stale != sTaskInterp.end();) { + if (stale->second.serial + kInterpStaleAfter < pair.serial) { + FrameInterpolation_ReleasePair(stale->second.prev, stale->second.curr); + stale = sTaskInterp.erase(stale); + } else { + ++stale; + } + } +} + +namespace { +void RenderTask(void* dlStart) { + InterpPair pair; + { + std::lock_guard lock(sInterpMutex); + auto it = sTaskInterp.find(dlStart); + if (it != sTaskInterp.end()) { + pair = it->second; + sTaskInterp.erase(it); + } + } + FrameInterpolation_BeginRenderPass(pair.prev, pair.curr, pair.should); + Nametag::BeginRenderPass(dlStart, pair.should); + GameEngine::ProcessGfxCommands((Gfx*)dlStart); + FrameInterpolation_ReleasePair(pair.prev, pair.curr); +} + +// This thread plays the RCP: thread5 hands over a task, +// we run it and raise SP then DP. +int ServiceRcp() { + OSTask* task = OS_SpTakePendingTask(); + if (task == nullptr) { + return 0; + } + RenderTask(task->t.data_ptr); + OS_SendEventMesg(OS_EVENT_SP); + OS_SendEventMesg(OS_EVENT_DP); + return 1; +} + +// Called before core1_init, which is where these threads are created. +void EnableThread5() { + OS_EnableThreadEntry((void*)thread5_entry); + OS_SetQueueBlocking(thread5_getTaskQueue(), 1); + OS_SetQueueBlocking(thread5_getSyncQueue(), 1); + // The controller manager parks on its polling queue waiting for OS_EVENT_SI. + OS_EnableThreadEntry((void*)pfsManager_entry); + OS_SetQueueBlocking(pfsManager_getFrameMesgQ(), 1); + OS_EnableThreadEntry((void*)audioManagerThread_entry); + OS_SetQueueBlocking(audioManager_getFrameMesgQueue(), 1); + OS_SetQueueBlocking(audioManager_getReplyMesgQueue(), 1); +} +} // namespace + +// Drain submitted lists for safety. +static void RegisterThread5MapSync_Init() { + COND_HOOK(OnMapLoad, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { + (void)event; + port_pipelineSyncPoint(); + }); +} + +static RegisterShipInitFunc sThread5MapSyncInit(RegisterThread5MapSync_Init); + +// Whether a tick-side renderer call is waiting on the window thread. The +// handshake below is a condvar rather than a message queue, so it is the one +// park the watchdog's blocked-wait registry cannot see. +extern "C" int port_renderServicePending(void) { + return sSvcFn != nullptr; +} + +// Renderer calls from tick code come through here; D3D11 hangs if they run +// off the window thread. Inline when there is no separate tick thread. +extern "C" void port_runOnRenderThread(void (*fn)(void*), void* arg) { + if (!OnGameThread()) { + fn(arg); + return; + } + std::unique_lock lock(sSvcMutex); + auto done = [] { return sSvcFn == nullptr || sShutdownRequested.load(std::memory_order_acquire); }; + if (sShutdownRequested.load(std::memory_order_acquire)) { + return; + } + sSvcCv.wait(lock, done); + if (sShutdownRequested.load(std::memory_order_acquire)) { + return; + } + sSvcFn = fn; + sSvcArg = arg; + sSvcCv.wait(lock, done); +} + +// Barrier before the tick frees or reads memory an in-flight list references. +// The game's own EVENT_SYNC handshake is the RDP-done wait. +extern "C" void port_pipelineSyncPoint(void) { + if (OnGameThread()) { + core1_15B30_sendMesg3ToRenderThread(); + } } // Tracks whether mainLoop actually fed the renderer this iteration. // BK's gameloop conditionally skips game_draw during scene transitions. static bool sFrameRendered = false; -// Start of this tick. The gap until drawing begins is how long the game spent -// updating; Adaptive FPS uses it to budget how many interpolated frames fit. -static std::chrono::steady_clock::time_point sTickStart; - +// The list itself reaches the renderer through thread5's task queue, submitted +// by core1_15B30_addF3DEXTaskData right after this call; all that is left here +// is noting that the tick drew. extern "C" void Graphics_PushFrame(Gfx* data) { - // Only measure the first draw of the tick. - if (!sFrameRendered) { - auto logicNs = - std::chrono::duration_cast(std::chrono::steady_clock::now() - sTickStart).count(); - AdaptiveFps_SampleTick((long long)logicNs); - } + (void)data; sFrameRendered = true; - GameEngine::ProcessGfxCommands(data); } void push_frame() { static int sTitleCounter = 0; sFrameRendered = false; - // While an inline mod extraction runs on its worker thread, freeze the game - // and render only the GUI so the progress modal stays live and the extractor - // gets the machine instead of fighting a full-speed game loop. The delay - // keeps the otherwise-idle main thread from busy-spinning a core. + // The window thread keeps the progress modal alive while an inline mod + // extraction runs; the tick just idles so the extractor gets the machine. if (IsInlineModExtractionBusy()) { - GameEngine::Instance->RenderGuiFrame(); SDL_Delay(16); return; } - sTickStart = std::chrono::steady_clock::now(); GameEngine::Instance->StartFrame(); - // Demo/playback modes render at native rate with no interpolation, so skip recording it. - const bool recordInterpolation = GameEngine::IsInterpolationEnabled() && !func_802E4A08(); + port_animVtx_beginTick(); + const bool recordInterpolation = GameEngine::IsInterpolationEnabled(); if (recordInterpolation) { FrameInterpolation_StartRecord(); } @@ -74,13 +254,16 @@ void push_frame() { if (recordInterpolation) { FrameInterpolation_StopRecord(); } - GameEngine::StartAudioFrame(); - GameEngine::EndAudioFrame(); + if (sFrameRendered) { + port_tickDemoAudioHold(); + } - // Refresh window title stats once per second (every 30 game ticks) + // Refresh window title stats once per second (every 30 game ticks). The + // window belongs to the other thread, so hand the call over. if (++sTitleCounter >= 30) { sTitleCounter = 0; - port_setWindowTitle(gsworld_getMap()); + sTitleMap = gsworld_getMap(); + port_runOnRenderThread([](void*) { port_setWindowTitle(sTitleMap); }, nullptr); } if (!sFrameRendered) { @@ -102,8 +285,13 @@ int SDL_main(int argc, char* argv[]) { // when SHIP_HOME is not in use std::error_code ec; const char* shipHome = std::getenv("SHIP_HOME"); + const char* appImage = std::getenv("APPIMAGE"); if (shipHome != nullptr && shipHome[0] != '\0') { std::filesystem::current_path(shipHome, ec); + } else if (appImage != nullptr && appImage[0] != '\0') { + // Running from an AppImage: the executable lives in a read-only squashfs + // mount under /tmp, so anchor to the .AppImage file's directory instead. + std::filesystem::current_path(std::filesystem::path(appImage).parent_path(), ec); } else { std::string base = Ship::Context::GetAppBundlePath(); if (!base.empty() && base != ".") { @@ -112,11 +300,64 @@ int SDL_main(int argc, char* argv[]) { } GameEngine::Create(argc, argv); + // Both threads are created during core1_init, so allowlist them first. + OS_EnableThreadEntry((void*)viMgr_entry); + EnableThread5(); core1_init(); + ThreadWatchdog_Start(); + + sGameThread = std::thread([] { + tIsGameThread = true; + while (WindowIsRunning()) { + ThreadWatchdog_Beat(WATCHDOG_GAME_TICK); + push_frame(); + } + sGameThreadDone.store(true); + }); + while (WindowIsRunning() || !sGameThreadDone.load()) { + ThreadWatchdog_Beat(WATCHDOG_MAIN_LOOP); + port_noteMainLoopAlive(); + // Pump events every iteration: a task-starved pass must not starve + // input and window messages. + Ship::Context::GetRawInstance()->GetWindow()->HandleEvents(); + OS_SiService(); + if (IsInlineModExtractionBusy()) { + GameEngine::Instance->RenderGuiFrame(); + SDL_Delay(16); + continue; + } + DrainRenderService(); + if (!ServiceRcp()) { + // The gui only draws inside serviced frames, so a stalled game + // thread would freeze ImGui with it. Render gui-only frames during + // a stall so the menu (and the watchdog dump) stays reachable. + if (ThreadWatchdog_IsStalled(WATCHDOG_GAME_TICK)) { + GameEngine::Instance->RenderGuiFrame(); + SDL_Delay(16); + continue; + } + SDL_Delay(1); + } + } + // Ask first, then release: a thread woken before the request is set would just + // park again. + OS_RequestThreadExit(); + { + std::lock_guard lock(sSvcMutex); + sShutdownRequested.store(true, std::memory_order_release); + sSvcFn = nullptr; + } + sSvcCv.notify_all(); + OS_BeginShutdown(); - while (WindowIsRunning()) { - push_frame(); + if (sGameThread.joinable()) { + sGameThread.join(); } + // Before Destroy: these threads draw and play audio through the engine. + OS_JoinDecompThreads(); + ThreadWatchdog_Stop(); + OS_StopViTicker(); + OS_StopTimerWorker(); #ifdef USE_NETWORKING Anchor::GetInstance()->Disable(); SDLNet_Quit(); diff --git a/src/port/GameStatus.cpp b/src/port/GameStatus.cpp index fd67e994a..b316614da 100644 --- a/src/port/GameStatus.cpp +++ b/src/port/GameStatus.cpp @@ -2,28 +2,73 @@ #include "ShipUtils.h" #include #include +#include #ifdef _WIN32 #include +#include +#include #endif #include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Patches/Patches.h" +#include "port/Romhack/RomhackConfig.h" #include "port/ShipInit.hpp" +#ifdef _WIN32 +namespace { +HWND ResolveGameWindow() { + static HWND sCached = nullptr; + if (sCached != nullptr && IsWindow(sCached)) { + return sCached; + } + for (Uint32 id = 1; id <= 16 && sCached == nullptr; id++) { + SDL_Window* window = SDL_GetWindowFromID(id); + if (window == nullptr) { + continue; + } + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + if (SDL_GetWindowWMInfo(window, &info) == SDL_TRUE && info.subsystem == SDL_SYSWM_WINDOWS) { + sCached = info.info.win.window; + } + } + if (sCached == nullptr) { + struct Search { + DWORD pid; + HWND gameWindow; + HWND fallback; + }; + Search search{ GetCurrentProcessId(), nullptr, nullptr }; + EnumWindows( + [](HWND hwnd, LPARAM param) -> BOOL { + Search* s = reinterpret_cast(param); + DWORD pid = 0; + GetWindowThreadProcessId(hwnd, &pid); + if (pid != s->pid || GetWindow(hwnd, GW_OWNER) != nullptr || !IsWindowVisible(hwnd)) { + return TRUE; + } + char cls[64] = { 0 }; + GetClassNameA(hwnd, cls, (int)sizeof(cls)); + if (strcmp(cls, "N64GAME") == 0) { + s->gameWindow = hwnd; + return FALSE; + } + if (s->fallback == nullptr && strcmp(cls, "ConsoleWindowClass") != 0) { + s->fallback = hwnd; + } + return TRUE; + }, + reinterpret_cast(&search)); + sCached = (search.gameWindow != nullptr) ? search.gameWindow : search.fallback; + } + return sCached; +} +} // namespace +#endif + +#include "functions.h" extern "C" { #include "enums.h" -enum level_e map_getLevel(enum map_e map); -s32 itemscore_noteScores_get(enum level_e lvl_id); -s32 jiggyscore_leveltotal(s32 lvl); -s32 honeycombscore_get_level_total(enum level_e level_id); -u16 itemscore_timeScores_get(enum level_e level_id); -int port_getRomhackNotesMax(void); -int port_getRomhackJiggiesPerWorld(void); -int port_getRomhackHoneycombsPerWorld(void); -int port_getRomhackSpecialLevel(void); -int port_getRomhackExtraHcStart(void); -int port_getRomhackHideCollectiblesLevel(void); -int port_getRomhackHideJiggiesLevel(void); -const char* port_getRomhackLevelName(int level_index); // Pause menu level name table (supports romhack string patches via Torch config) typedef struct { @@ -151,17 +196,20 @@ extern "C" void port_setWindowTitle(int map_id) { noteStr, jiggyStr, hcStr, timeStr); #ifdef _WIN32 - HWND hwnd = GetActiveWindow(); + HWND hwnd = ResolveGameWindow(); if (hwnd) { SetWindowTextA(hwnd, title); } #endif } +static int sPendingTitleMap = 0; + void RegisterGameStatus_Init() { COND_HOOK(OnMapLoad, EVENT_PRIORITY_LOW, true, [](IEvent* event) { OnMapLoad* ev = (OnMapLoad*)event; - port_setWindowTitle(ev->nextMap); + sPendingTitleMap = ev->nextMap; + port_runOnRenderThread([](void*) { port_setWindowTitle(sPendingTitleMap); }, nullptr); }); } diff --git a/src/port/GameVersion/AssetVersionRemap.h b/src/port/GameVersion/AssetVersionRemap.h index 395ecdf5e..5d17eb6f1 100644 --- a/src/port/GameVersion/AssetVersionRemap.h +++ b/src/port/GameVersion/AssetVersionRemap.h @@ -4,575 +4,580 @@ #include #include -// v1.0 -> v1.1 asset ID remap table. 1300 entries. +// v1.0 -> v1.1 asset ID remap table. 1313 entries. static const std::unordered_map sV10toV11Remap = { { 2468, 2212 }, { 2469, 2213 }, { 2470, 2214 }, { 2471, 2215 }, { 2472, 2268 }, { 2473, 2269 }, { 2474, 2218 }, { 2475, 2219 }, { 2476, 2220 }, { 2477, 2221 }, { 2478, 2274 }, { 2481, 2277 }, { 2483, 2279 }, { 2484, 2228 }, { 2485, 2229 }, { 2487, 2283 }, { 2488, 2232 }, { 2489, 2233 }, { 2490, 2234 }, { 2491, 2235 }, { 2498, 2294 }, - { 2504, 2248 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, - { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, - { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, - { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, - { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, - { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, - { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, - { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, - { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, - { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, - { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, - { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, - { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, - { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, - { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, - { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, - { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, - { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, - { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, - { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, - { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, - { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, - { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, - { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, - { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, - { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, - { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, - { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, - { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, - { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, - { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, - { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, - { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, - { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, - { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, - { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, - { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, - { 3382, 2569 }, { 3383, 2570 }, { 3384, 3024 }, { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, - { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, - { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, - { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, - { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, - { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, - { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, - { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, - { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, - { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, - { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, - { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, - { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, - { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, - { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, - { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, - { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, - { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, - { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, - { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, - { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, - { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, - { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, - { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, - { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, - { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, - { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, - { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, - { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, - { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, - { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, - { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, - { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, - { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, - { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, - { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, - { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, - { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, - { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, - { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, - { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, - { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, - { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, - { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, - { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, - { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, - { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, - { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, - { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, - { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, - { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, - { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, - { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, - { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, - { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, - { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, - { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, - { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, - { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, - { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, { 4400, 2994 }, { 4406, 3000 }, { 4407, 3001 }, { 4408, 3002 }, - { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, { 4414, 3008 }, { 4415, 3009 }, - { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, { 4421, 3015 }, { 4422, 3016 }, - { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, - { 4434, 3028 }, { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, - { 4441, 3035 }, { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, - { 4448, 3042 }, { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, - { 4531, 3049 }, { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, - { 4538, 3056 }, { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, - { 4545, 3063 }, { 4546, 3064 }, { 4547, 3065 }, { 4548, 3066 }, { 4549, 3067 }, { 4550, 3068 }, { 4551, 3069 }, - { 4552, 3070 }, { 4553, 3071 }, { 4627, 3072 }, { 4628, 3073 }, { 4629, 3074 }, { 4630, 3075 }, { 4631, 3076 }, - { 4632, 3077 }, { 4633, 3078 }, { 4634, 3079 }, { 4635, 3080 }, { 4636, 3081 }, { 4637, 3082 }, { 4638, 3083 }, - { 4639, 3084 }, { 4640, 3085 }, { 4641, 3086 }, { 4642, 3087 }, { 4643, 3088 }, { 4644, 3089 }, { 4645, 3090 }, - { 4646, 3091 }, { 4647, 3092 }, { 4648, 3093 }, { 4649, 3094 }, { 4650, 3095 }, { 4651, 3096 }, { 4652, 3097 }, - { 4653, 3098 }, { 4654, 3099 }, { 4655, 3100 }, { 4656, 3101 }, { 4657, 3102 }, { 4658, 3103 }, { 4659, 3104 }, - { 4660, 3105 }, { 4661, 3106 }, { 4662, 3107 }, { 4663, 3108 }, { 4664, 3109 }, { 4665, 3110 }, { 4666, 3111 }, - { 4667, 3112 }, { 4668, 3113 }, { 4669, 3114 }, { 4670, 3115 }, { 4671, 3116 }, { 4672, 3117 }, { 4673, 3118 }, - { 4674, 3119 }, { 4675, 3120 }, { 4676, 3121 }, { 4677, 3122 }, { 4678, 3123 }, { 4679, 3124 }, { 4680, 3125 }, - { 4681, 3126 }, { 4682, 3127 }, { 4683, 3128 }, { 4684, 3129 }, { 4685, 3130 }, { 4686, 3131 }, { 4687, 3132 }, - { 4688, 3133 }, { 4689, 3134 }, { 4690, 3135 }, { 4691, 3136 }, { 4692, 3137 }, { 4693, 3138 }, { 4694, 3139 }, - { 4695, 3140 }, { 4696, 3141 }, { 4697, 3142 }, { 4698, 3143 }, { 4699, 3144 }, { 4700, 3145 }, { 4701, 3146 }, - { 4702, 3147 }, { 4703, 3148 }, { 4704, 3149 }, { 4705, 3150 }, { 4706, 3151 }, { 4707, 3152 }, { 4708, 3153 }, - { 4709, 3154 }, { 4710, 3155 }, { 4711, 3156 }, { 4712, 3157 }, { 4713, 3158 }, { 4714, 3159 }, { 4715, 3160 }, - { 4716, 3161 }, { 4717, 3162 }, { 4718, 3163 }, { 4719, 3164 }, { 4720, 3165 }, { 4721, 3166 }, { 4722, 3167 }, - { 4723, 3168 }, { 4724, 3169 }, { 4725, 3170 }, { 4726, 3171 }, { 4827, 3172 }, { 4828, 3173 }, { 4829, 3174 }, - { 4830, 3175 }, { 4831, 3176 }, { 4832, 3177 }, { 4833, 3178 }, { 4834, 3179 }, { 4835, 3180 }, { 4836, 3181 }, - { 4837, 3182 }, { 4838, 3183 }, { 4839, 3184 }, { 4840, 3185 }, { 4841, 3186 }, { 4842, 3187 }, { 4843, 3188 }, - { 4844, 3189 }, { 4845, 3190 }, { 5027, 3191 }, { 5028, 3192 }, { 5029, 3193 }, { 5030, 3194 }, { 5031, 3195 }, - { 5032, 3196 }, { 5033, 3197 }, { 5034, 3198 }, { 5035, 3199 }, { 5036, 3200 }, { 5037, 3201 }, { 5038, 3202 }, - { 5039, 3203 }, { 5040, 3204 }, { 5041, 3205 }, { 5042, 3206 }, { 5043, 3207 }, { 5044, 3208 }, { 5045, 3209 }, - { 5046, 3210 }, { 5047, 3211 }, { 5048, 3212 }, { 5049, 3213 }, { 5050, 3214 }, { 5051, 3215 }, { 5052, 3216 }, - { 5053, 3217 }, { 5054, 3218 }, { 5055, 3219 }, { 5056, 3220 }, { 5057, 3221 }, { 5058, 3222 }, { 5059, 3223 }, - { 5060, 3224 }, { 5061, 3225 }, { 5062, 3226 }, { 5063, 3227 }, { 5064, 3228 }, { 5065, 3229 }, { 5066, 3230 }, - { 5067, 3231 }, { 5068, 3232 }, { 5069, 3233 }, { 5070, 3234 }, { 5071, 3235 }, { 5072, 3236 }, { 5073, 3237 }, - { 5074, 3238 }, { 5075, 3239 }, { 5076, 3240 }, { 5077, 3241 }, { 5127, 3242 }, { 5128, 3243 }, { 5129, 3244 }, - { 5130, 3245 }, { 5131, 3246 }, { 5132, 3247 }, { 5133, 3248 }, { 5134, 3249 }, { 5135, 3250 }, { 5136, 3251 }, - { 5137, 3252 }, { 5138, 3253 }, { 5139, 3254 }, { 5140, 3255 }, { 5141, 3256 }, { 5142, 3257 }, { 5143, 3258 }, - { 5144, 3259 }, { 5145, 3260 }, { 5146, 3261 }, { 5147, 3262 }, { 5148, 3263 }, { 5149, 3264 }, { 5150, 3265 }, - { 5151, 3266 }, { 5152, 3267 }, { 5153, 3268 }, { 5154, 3269 }, { 5155, 3270 }, { 5156, 3271 }, { 5227, 3272 }, - { 5228, 3273 }, { 5229, 3274 }, { 5230, 3275 }, { 5231, 3276 }, { 5232, 3277 }, { 5233, 3278 }, { 5234, 3279 }, - { 5235, 3280 }, { 5236, 3281 }, { 5237, 3282 }, { 5238, 3283 }, { 5240, 3285 }, { 5241, 3286 }, { 5242, 3287 }, - { 5243, 3288 }, { 5244, 3289 }, { 5245, 3290 }, { 5246, 3291 }, { 5247, 3292 }, { 5248, 3293 }, { 5249, 3294 }, - { 5250, 3295 }, { 5251, 3296 }, { 5252, 3297 }, { 5253, 3298 }, { 5254, 3299 }, { 5255, 3300 }, { 5256, 3301 }, - { 5257, 3302 }, { 5258, 3303 }, { 5259, 3304 }, { 5260, 3305 }, { 5261, 3306 }, { 5262, 3307 }, { 5263, 3308 }, - { 5264, 3309 }, { 5265, 3310 }, { 5266, 3311 }, { 5267, 3312 }, { 5268, 3313 }, { 5269, 3314 }, { 5270, 3315 }, - { 5271, 3316 }, { 5272, 3317 }, { 5273, 3318 }, { 5274, 3319 }, { 5275, 3320 }, { 5276, 3321 }, { 5277, 3322 }, - { 5278, 3323 }, { 5279, 3324 }, { 5280, 3325 }, { 5281, 3326 }, { 5282, 3327 }, { 5283, 3328 }, { 5284, 3329 }, - { 5285, 3330 }, { 5286, 3331 }, { 5288, 3333 }, { 5289, 3334 }, { 5290, 3335 }, { 5291, 3336 }, { 5292, 3337 }, - { 5293, 3338 }, { 5294, 3339 }, { 5296, 3341 }, { 5297, 3342 }, { 5298, 3343 }, { 5299, 3344 }, { 5300, 3345 }, - { 5301, 3346 }, { 5302, 3347 }, { 5303, 3348 }, { 5304, 3349 }, { 5305, 3350 }, { 5306, 3351 }, { 5307, 3352 }, - { 5308, 3353 }, { 5309, 3354 }, { 5310, 3355 }, { 5311, 3356 }, { 5312, 3357 }, { 5313, 3358 }, { 5314, 3359 }, - { 5315, 3360 }, { 5316, 3361 }, { 5317, 3362 }, { 5318, 3363 }, { 5319, 3364 }, { 5320, 3365 }, { 5321, 3366 }, - { 5322, 3367 }, { 5323, 3368 }, { 5324, 3369 }, { 5325, 3370 }, { 5326, 3371 }, { 5327, 3372 }, { 5328, 3373 }, - { 5329, 3374 }, { 5330, 3375 }, { 5331, 3376 }, { 5332, 3377 }, { 5333, 3378 }, { 5336, 3381 }, { 5337, 3382 }, - { 5338, 3383 }, { 5339, 3384 }, { 5340, 3385 }, { 5341, 3386 }, { 5342, 3387 }, { 5343, 3388 }, { 5344, 3389 }, - { 5345, 3390 }, { 5346, 3391 }, { 5347, 3392 }, { 5348, 3393 }, { 5349, 3394 }, { 5350, 3395 }, { 5351, 3396 }, - { 5352, 3397 }, { 5357, 3402 }, { 5358, 3403 }, { 5359, 3404 }, { 5360, 3405 }, { 5361, 3406 }, { 5362, 3407 }, - { 5363, 3408 }, { 5364, 3409 }, { 5365, 3410 }, { 5366, 3411 }, { 5367, 3412 }, { 5368, 3413 }, { 5369, 3414 }, - { 5370, 3415 }, { 5371, 3416 }, { 5372, 3417 }, { 5373, 3418 }, { 5374, 3419 }, { 5375, 3420 }, { 5376, 3421 }, - { 5377, 3422 }, { 5378, 3423 }, { 5379, 3424 }, { 5380, 3425 }, { 5381, 3426 }, { 5382, 3427 }, { 5383, 3428 }, - { 5384, 3429 }, { 5385, 3430 }, { 5386, 3431 }, { 5387, 3432 }, { 5388, 3433 }, { 5389, 3434 }, { 5390, 3435 }, - { 5391, 3436 }, { 5392, 3437 }, { 5393, 3438 }, { 5394, 3439 }, { 5395, 3440 }, { 5396, 3441 }, { 5397, 3442 }, - { 5398, 3443 }, { 5399, 3444 }, { 5400, 3445 }, { 5401, 3446 }, { 5402, 3447 }, { 5403, 3448 }, { 5404, 3449 }, - { 5405, 3450 }, { 5406, 3451 }, { 5407, 3452 }, { 5408, 3453 }, { 5409, 3454 }, { 5410, 3455 }, { 5411, 3456 }, - { 5412, 3457 }, { 5413, 3458 }, { 5414, 3459 }, { 5415, 3460 }, { 5416, 3461 }, { 5417, 3462 }, { 5418, 3463 }, - { 5419, 3464 }, { 5420, 3465 }, { 5421, 3466 }, { 5422, 3467 }, { 5423, 3468 }, { 5424, 3469 }, { 5425, 3470 }, - { 5426, 3471 }, { 5427, 3472 }, { 5428, 3473 }, { 5429, 3474 }, { 5430, 3475 }, { 5431, 3476 }, { 5432, 3477 }, - { 5433, 3478 }, { 5434, 3479 }, { 5435, 3480 }, { 5436, 3481 }, { 5437, 3482 }, { 5438, 3483 }, { 5439, 3484 }, - { 5440, 3485 }, { 5441, 3486 }, { 5442, 3487 }, { 5443, 3488 }, { 5444, 3489 }, { 5445, 3490 }, { 5446, 3491 }, - { 5447, 3492 }, { 5448, 3493 }, { 5449, 3494 }, { 5450, 3495 }, { 5451, 3496 }, { 5452, 3497 }, { 5453, 3498 }, - { 5454, 3499 }, { 5455, 3500 }, { 5456, 3501 }, { 5457, 3502 }, { 5458, 3503 }, { 5459, 3504 }, { 5460, 3505 }, - { 5461, 3506 }, { 5462, 3507 }, { 5463, 3508 }, { 5464, 3509 }, { 5465, 3510 }, { 5466, 3511 }, { 5467, 3512 }, - { 5468, 3513 }, { 5469, 3514 }, { 5470, 3515 }, { 5471, 3516 }, { 5472, 3517 }, { 5473, 3518 }, { 5474, 3519 }, - { 5475, 3520 }, { 5476, 3521 }, { 5477, 3522 }, { 5478, 3523 }, { 5479, 3524 }, { 5480, 3525 }, { 5481, 3526 }, - { 5482, 3527 }, { 5483, 3528 }, { 5484, 3529 }, { 5485, 3530 }, { 5486, 3531 }, { 5487, 3532 }, { 5488, 3533 }, - { 5489, 3534 }, { 5490, 3535 }, { 5491, 3536 }, { 5492, 3537 }, { 5493, 3538 }, { 5494, 3539 }, { 5495, 3540 }, - { 5496, 3541 }, { 5497, 3542 }, { 5498, 3543 }, { 5499, 3544 }, { 5500, 3545 }, { 5501, 3546 }, { 5502, 3547 }, - { 5503, 3548 }, { 5504, 3549 }, { 5505, 3550 }, { 5506, 3551 }, { 5507, 3552 }, { 5508, 3553 }, { 5509, 3554 }, - { 5510, 3555 }, { 5511, 3556 }, { 5512, 3557 }, { 5513, 3558 }, { 5514, 3559 }, { 5515, 3560 }, { 5516, 3561 }, - { 5517, 3562 }, { 5518, 3563 }, { 5519, 3564 }, { 5520, 3565 }, { 5521, 3566 }, { 5522, 3567 }, { 5523, 3568 }, - { 5524, 3569 }, { 5525, 3570 }, { 5526, 3571 }, { 5527, 3572 }, { 5528, 3573 }, { 5529, 3574 }, { 5530, 3575 }, - { 5531, 3576 }, { 5532, 3577 }, { 5533, 3578 }, { 5534, 3579 }, { 5535, 3580 }, { 5536, 3581 }, { 5537, 3582 }, - { 5538, 3583 }, { 5539, 3584 }, { 5540, 3585 }, { 5541, 3586 }, { 5542, 3587 }, { 5543, 3588 }, { 5544, 3589 }, - { 5545, 3590 }, { 5546, 3591 }, { 5547, 3592 }, { 5548, 3593 }, { 5549, 3594 }, { 5550, 3595 }, { 5551, 3596 }, - { 5552, 3597 }, { 5553, 3598 }, { 5554, 3599 }, { 5555, 3600 }, { 5556, 3601 }, { 5557, 3602 }, { 5558, 3603 }, - { 5559, 3604 }, { 5560, 3605 }, { 5561, 3606 }, { 5562, 3607 }, { 5563, 3608 }, { 5564, 3609 }, { 5565, 3610 }, - { 5566, 3611 }, { 5567, 3612 }, { 5568, 3613 }, { 5569, 3614 }, { 5570, 3615 } + { 2504, 2248 }, { 2508, 2252 }, { 2511, 2255 }, { 2513, 2257 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, + { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, + { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, + { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, + { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, + { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, + { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, + { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, + { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, + { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, + { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, + { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, + { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2878, 2396 }, + { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, + { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, + { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, + { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, + { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, + { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, + { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, + { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, + { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, + { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, + { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, + { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, + { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, + { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, + { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, + { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, + { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, + { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, + { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, + { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, + { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, + { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, + { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, + { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, + { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, { 3382, 2569 }, { 3383, 2570 }, { 3384, 2571 }, + { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, + { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, + { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, + { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, + { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, + { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, + { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, + { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, + { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, + { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, + { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, + { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, + { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, + { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, + { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, + { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, + { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, + { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, + { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, + { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, + { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, + { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, + { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, + { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, + { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, + { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, + { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, + { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, + { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, + { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, + { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, + { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, + { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, + { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, + { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, + { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, + { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, + { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, + { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, + { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, + { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, + { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, + { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, + { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, + { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, + { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, + { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, + { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, + { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, + { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, + { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, + { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, + { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, + { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, + { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, + { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, + { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, + { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, + { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, + { 4400, 2994 }, { 4401, 2995 }, { 4402, 2996 }, { 4403, 2997 }, { 4404, 2998 }, { 4405, 2999 }, { 4406, 3000 }, + { 4407, 3001 }, { 4408, 3002 }, { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, + { 4414, 3008 }, { 4415, 3009 }, { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, + { 4421, 3015 }, { 4422, 3016 }, { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4427, 3021 }, + { 4428, 3022 }, { 4429, 3023 }, { 4430, 3024 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, { 4434, 3028 }, + { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, { 4441, 3035 }, + { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, { 4448, 3042 }, + { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, { 4531, 3049 }, + { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, { 4538, 3056 }, + { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, { 4545, 3063 }, + { 4546, 3064 }, { 4547, 3065 }, { 4548, 3066 }, { 4549, 3067 }, { 4550, 3068 }, { 4551, 3069 }, { 4552, 3070 }, + { 4553, 3071 }, { 4627, 3072 }, { 4628, 3073 }, { 4629, 3074 }, { 4630, 3075 }, { 4631, 3076 }, { 4632, 3077 }, + { 4633, 3078 }, { 4634, 3079 }, { 4635, 3080 }, { 4636, 3081 }, { 4637, 3082 }, { 4638, 3083 }, { 4639, 3084 }, + { 4640, 3085 }, { 4641, 3086 }, { 4642, 3087 }, { 4643, 3088 }, { 4644, 3089 }, { 4645, 3090 }, { 4646, 3091 }, + { 4647, 3092 }, { 4648, 3093 }, { 4649, 3094 }, { 4650, 3095 }, { 4651, 3096 }, { 4652, 3097 }, { 4653, 3098 }, + { 4654, 3099 }, { 4655, 3100 }, { 4656, 3101 }, { 4657, 3102 }, { 4658, 3103 }, { 4659, 3104 }, { 4660, 3105 }, + { 4661, 3106 }, { 4662, 3107 }, { 4663, 3108 }, { 4664, 3109 }, { 4665, 3110 }, { 4666, 3111 }, { 4667, 3112 }, + { 4668, 3113 }, { 4669, 3114 }, { 4670, 3115 }, { 4671, 3116 }, { 4672, 3117 }, { 4673, 3118 }, { 4674, 3119 }, + { 4675, 3120 }, { 4676, 3121 }, { 4677, 3122 }, { 4678, 3123 }, { 4679, 3124 }, { 4680, 3125 }, { 4681, 3126 }, + { 4682, 3127 }, { 4683, 3128 }, { 4684, 3129 }, { 4685, 3130 }, { 4686, 3131 }, { 4687, 3132 }, { 4688, 3133 }, + { 4689, 3134 }, { 4690, 3135 }, { 4691, 3136 }, { 4692, 3137 }, { 4693, 3138 }, { 4694, 3139 }, { 4695, 3140 }, + { 4696, 3141 }, { 4697, 3142 }, { 4698, 3143 }, { 4699, 3144 }, { 4700, 3145 }, { 4701, 3146 }, { 4702, 3147 }, + { 4703, 3148 }, { 4704, 3149 }, { 4705, 3150 }, { 4706, 3151 }, { 4707, 3152 }, { 4708, 3153 }, { 4709, 3154 }, + { 4710, 3155 }, { 4711, 3156 }, { 4712, 3157 }, { 4713, 3158 }, { 4714, 3159 }, { 4715, 3160 }, { 4716, 3161 }, + { 4717, 3162 }, { 4718, 3163 }, { 4719, 3164 }, { 4720, 3165 }, { 4721, 3166 }, { 4722, 3167 }, { 4723, 3168 }, + { 4724, 3169 }, { 4725, 3170 }, { 4726, 3171 }, { 4827, 3172 }, { 4828, 3173 }, { 4829, 3174 }, { 4830, 3175 }, + { 4831, 3176 }, { 4832, 3177 }, { 4833, 3178 }, { 4834, 3179 }, { 4835, 3180 }, { 4836, 3181 }, { 4837, 3182 }, + { 4838, 3183 }, { 4839, 3184 }, { 4840, 3185 }, { 4841, 3186 }, { 4842, 3187 }, { 4843, 3188 }, { 4844, 3189 }, + { 4845, 3190 }, { 5027, 3191 }, { 5028, 3192 }, { 5029, 3193 }, { 5030, 3194 }, { 5031, 3195 }, { 5032, 3196 }, + { 5033, 3197 }, { 5034, 3198 }, { 5035, 3199 }, { 5036, 3200 }, { 5037, 3201 }, { 5038, 3202 }, { 5039, 3203 }, + { 5040, 3204 }, { 5041, 3205 }, { 5042, 3206 }, { 5043, 3207 }, { 5044, 3208 }, { 5045, 3209 }, { 5046, 3210 }, + { 5047, 3211 }, { 5048, 3212 }, { 5049, 3213 }, { 5050, 3214 }, { 5051, 3215 }, { 5052, 3216 }, { 5053, 3217 }, + { 5054, 3218 }, { 5055, 3219 }, { 5056, 3220 }, { 5057, 3221 }, { 5058, 3222 }, { 5059, 3223 }, { 5060, 3224 }, + { 5061, 3225 }, { 5062, 3226 }, { 5063, 3227 }, { 5064, 3228 }, { 5065, 3229 }, { 5066, 3230 }, { 5067, 3231 }, + { 5068, 3232 }, { 5069, 3233 }, { 5070, 3234 }, { 5071, 3235 }, { 5072, 3236 }, { 5073, 3237 }, { 5074, 3238 }, + { 5075, 3239 }, { 5076, 3240 }, { 5077, 3241 }, { 5127, 3242 }, { 5128, 3243 }, { 5129, 3244 }, { 5130, 3245 }, + { 5131, 3246 }, { 5132, 3247 }, { 5133, 3248 }, { 5134, 3249 }, { 5135, 3250 }, { 5136, 3251 }, { 5137, 3252 }, + { 5138, 3253 }, { 5139, 3254 }, { 5140, 3255 }, { 5141, 3256 }, { 5142, 3257 }, { 5143, 3258 }, { 5144, 3259 }, + { 5145, 3260 }, { 5146, 3261 }, { 5147, 3262 }, { 5148, 3263 }, { 5149, 3264 }, { 5150, 3265 }, { 5151, 3266 }, + { 5152, 3267 }, { 5153, 3268 }, { 5154, 3269 }, { 5155, 3270 }, { 5156, 3271 }, { 5227, 3272 }, { 5228, 3273 }, + { 5229, 3274 }, { 5230, 3275 }, { 5231, 3276 }, { 5232, 3277 }, { 5233, 3278 }, { 5234, 3279 }, { 5235, 3280 }, + { 5236, 3281 }, { 5237, 3282 }, { 5238, 3283 }, { 5240, 3285 }, { 5241, 3286 }, { 5242, 3287 }, { 5243, 3288 }, + { 5244, 3289 }, { 5245, 3290 }, { 5246, 3291 }, { 5247, 3292 }, { 5248, 3293 }, { 5249, 3294 }, { 5250, 3295 }, + { 5251, 3296 }, { 5252, 3297 }, { 5253, 3298 }, { 5254, 3299 }, { 5255, 3300 }, { 5256, 3301 }, { 5257, 3302 }, + { 5258, 3303 }, { 5259, 3304 }, { 5260, 3305 }, { 5261, 3306 }, { 5262, 3307 }, { 5263, 3308 }, { 5264, 3309 }, + { 5265, 3310 }, { 5266, 3311 }, { 5267, 3312 }, { 5268, 3313 }, { 5269, 3314 }, { 5270, 3315 }, { 5271, 3316 }, + { 5272, 3317 }, { 5273, 3318 }, { 5274, 3319 }, { 5275, 3320 }, { 5276, 3321 }, { 5277, 3322 }, { 5278, 3323 }, + { 5279, 3324 }, { 5280, 3325 }, { 5281, 3326 }, { 5282, 3327 }, { 5283, 3328 }, { 5284, 3329 }, { 5285, 3330 }, + { 5286, 3331 }, { 5288, 3333 }, { 5289, 3334 }, { 5290, 3335 }, { 5291, 3336 }, { 5292, 3337 }, { 5293, 3338 }, + { 5294, 3339 }, { 5296, 3341 }, { 5297, 3342 }, { 5298, 3343 }, { 5299, 3344 }, { 5300, 3345 }, { 5301, 3346 }, + { 5302, 3347 }, { 5303, 3348 }, { 5304, 3349 }, { 5305, 3350 }, { 5306, 3351 }, { 5307, 3352 }, { 5308, 3353 }, + { 5309, 3354 }, { 5310, 3355 }, { 5311, 3356 }, { 5312, 3357 }, { 5313, 3358 }, { 5314, 3359 }, { 5315, 3360 }, + { 5316, 3361 }, { 5317, 3362 }, { 5318, 3363 }, { 5319, 3364 }, { 5320, 3365 }, { 5321, 3366 }, { 5322, 3367 }, + { 5323, 3368 }, { 5324, 3369 }, { 5325, 3370 }, { 5326, 3371 }, { 5327, 3372 }, { 5328, 3373 }, { 5329, 3374 }, + { 5330, 3375 }, { 5331, 3376 }, { 5332, 3377 }, { 5333, 3378 }, { 5336, 3381 }, { 5337, 3382 }, { 5338, 3383 }, + { 5339, 3384 }, { 5340, 3385 }, { 5341, 3386 }, { 5342, 3387 }, { 5343, 3388 }, { 5344, 3389 }, { 5345, 3390 }, + { 5346, 3391 }, { 5347, 3392 }, { 5348, 3393 }, { 5349, 3394 }, { 5350, 3395 }, { 5351, 3396 }, { 5352, 3397 }, + { 5357, 3402 }, { 5358, 3403 }, { 5359, 3404 }, { 5360, 3405 }, { 5361, 3406 }, { 5362, 3407 }, { 5363, 3408 }, + { 5364, 3409 }, { 5365, 3410 }, { 5366, 3411 }, { 5367, 3412 }, { 5368, 3413 }, { 5369, 3414 }, { 5370, 3415 }, + { 5371, 3416 }, { 5372, 3417 }, { 5373, 3418 }, { 5374, 3419 }, { 5375, 3420 }, { 5376, 3421 }, { 5377, 3422 }, + { 5378, 3423 }, { 5379, 3424 }, { 5380, 3425 }, { 5381, 3426 }, { 5382, 3427 }, { 5383, 3428 }, { 5384, 3429 }, + { 5385, 3430 }, { 5386, 3431 }, { 5387, 3432 }, { 5388, 3433 }, { 5389, 3434 }, { 5390, 3435 }, { 5391, 3436 }, + { 5392, 3437 }, { 5393, 3438 }, { 5394, 3439 }, { 5395, 3440 }, { 5396, 3441 }, { 5397, 3442 }, { 5398, 3443 }, + { 5399, 3444 }, { 5400, 3445 }, { 5401, 3446 }, { 5402, 3447 }, { 5403, 3448 }, { 5404, 3449 }, { 5405, 3450 }, + { 5406, 3451 }, { 5407, 3452 }, { 5408, 3453 }, { 5409, 3454 }, { 5410, 3455 }, { 5411, 3456 }, { 5412, 3457 }, + { 5413, 3458 }, { 5414, 3459 }, { 5415, 3460 }, { 5416, 3461 }, { 5417, 3462 }, { 5418, 3463 }, { 5419, 3464 }, + { 5420, 3465 }, { 5421, 3466 }, { 5422, 3467 }, { 5423, 3468 }, { 5424, 3469 }, { 5425, 3470 }, { 5426, 3471 }, + { 5427, 3472 }, { 5428, 3473 }, { 5429, 3474 }, { 5430, 3475 }, { 5431, 3476 }, { 5432, 3477 }, { 5433, 3478 }, + { 5434, 3479 }, { 5435, 3480 }, { 5436, 3481 }, { 5437, 3482 }, { 5438, 3483 }, { 5439, 3484 }, { 5440, 3485 }, + { 5441, 3486 }, { 5442, 3487 }, { 5443, 3488 }, { 5444, 3489 }, { 5445, 3490 }, { 5446, 3491 }, { 5447, 3492 }, + { 5448, 3493 }, { 5449, 3494 }, { 5450, 3495 }, { 5451, 3496 }, { 5452, 3497 }, { 5453, 3498 }, { 5454, 3499 }, + { 5455, 3500 }, { 5456, 3501 }, { 5457, 3502 }, { 5458, 3503 }, { 5459, 3504 }, { 5460, 3505 }, { 5461, 3506 }, + { 5462, 3507 }, { 5463, 3508 }, { 5464, 3509 }, { 5465, 3510 }, { 5466, 3511 }, { 5467, 3512 }, { 5468, 3513 }, + { 5469, 3514 }, { 5470, 3515 }, { 5471, 3516 }, { 5472, 3517 }, { 5473, 3518 }, { 5474, 3519 }, { 5475, 3520 }, + { 5476, 3521 }, { 5477, 3522 }, { 5478, 3523 }, { 5479, 3524 }, { 5480, 3525 }, { 5481, 3526 }, { 5482, 3527 }, + { 5483, 3528 }, { 5484, 3529 }, { 5485, 3530 }, { 5486, 3531 }, { 5487, 3532 }, { 5488, 3533 }, { 5489, 3534 }, + { 5490, 3535 }, { 5491, 3536 }, { 5492, 3537 }, { 5493, 3538 }, { 5494, 3539 }, { 5495, 3540 }, { 5496, 3541 }, + { 5497, 3542 }, { 5498, 3543 }, { 5499, 3544 }, { 5500, 3545 }, { 5501, 3546 }, { 5502, 3547 }, { 5503, 3548 }, + { 5504, 3549 }, { 5505, 3550 }, { 5506, 3551 }, { 5507, 3552 }, { 5508, 3553 }, { 5509, 3554 }, { 5510, 3555 }, + { 5511, 3556 }, { 5512, 3557 }, { 5513, 3558 }, { 5514, 3559 }, { 5515, 3560 }, { 5516, 3561 }, { 5517, 3562 }, + { 5518, 3563 }, { 5519, 3564 }, { 5520, 3565 }, { 5521, 3566 }, { 5522, 3567 }, { 5523, 3568 }, { 5524, 3569 }, + { 5525, 3570 }, { 5526, 3571 }, { 5527, 3572 }, { 5528, 3573 }, { 5529, 3574 }, { 5530, 3575 }, { 5531, 3576 }, + { 5532, 3577 }, { 5533, 3578 }, { 5534, 3579 }, { 5535, 3580 }, { 5536, 3581 }, { 5537, 3582 }, { 5538, 3583 }, + { 5539, 3584 }, { 5540, 3585 }, { 5541, 3586 }, { 5542, 3587 }, { 5543, 3588 }, { 5544, 3589 }, { 5545, 3590 }, + { 5546, 3591 }, { 5547, 3592 }, { 5548, 3593 }, { 5549, 3594 }, { 5550, 3595 }, { 5551, 3596 }, { 5552, 3597 }, + { 5553, 3598 }, { 5554, 3599 }, { 5555, 3600 }, { 5556, 3601 }, { 5557, 3602 }, { 5558, 3603 }, { 5559, 3604 }, + { 5560, 3605 }, { 5561, 3606 }, { 5562, 3607 }, { 5563, 3608 }, { 5564, 3609 }, { 5565, 3610 }, { 5566, 3611 }, + { 5567, 3612 }, { 5568, 3613 }, { 5569, 3614 }, { 5570, 3615 } }; -// v1.0 -> PAL asset ID remap table. 1300 entries. +// v1.0 -> PAL asset ID remap table. 1314 entries. static const std::unordered_map sV10toPALRemap = { { 2468, 2212 }, { 2469, 2213 }, { 2470, 2214 }, { 2471, 2215 }, { 2472, 2268 }, { 2473, 2269 }, { 2474, 2218 }, { 2475, 2219 }, { 2476, 2220 }, { 2477, 2221 }, { 2478, 2274 }, { 2481, 2277 }, { 2483, 2279 }, { 2484, 2228 }, { 2485, 2229 }, { 2487, 2283 }, { 2488, 2232 }, { 2489, 2233 }, { 2490, 2234 }, { 2491, 2235 }, { 2498, 2294 }, - { 2504, 2248 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, - { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, - { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, - { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, - { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, - { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, - { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, - { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, - { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, - { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, - { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, - { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, - { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, - { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, - { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, - { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, - { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, - { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, - { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, - { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, - { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, - { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, - { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, - { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, - { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, - { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, - { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, - { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, - { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, - { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, - { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, - { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, - { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, - { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, - { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, - { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, - { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, - { 3382, 2569 }, { 3383, 2570 }, { 3384, 3024 }, { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, - { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, - { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, - { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, - { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, - { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, - { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, - { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, - { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, - { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, - { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, - { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, - { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, - { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, - { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, - { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, - { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, - { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, - { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, - { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, - { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, - { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, - { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, - { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, - { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, - { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, - { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, - { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, - { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, - { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, - { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, - { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, - { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, - { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, - { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, - { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, - { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, - { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, - { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, - { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, - { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, - { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, - { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, - { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, - { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, - { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, - { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, - { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, - { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, - { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, - { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, - { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, - { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, - { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, - { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, - { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, - { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, - { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, - { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, - { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, { 4400, 2994 }, { 4406, 3000 }, { 4407, 3001 }, { 4408, 3002 }, - { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, { 4414, 3008 }, { 4415, 3009 }, - { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, { 4421, 3015 }, { 4422, 3016 }, - { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, - { 4434, 3028 }, { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, - { 4441, 3035 }, { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, - { 4448, 3042 }, { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, - { 4531, 3049 }, { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, - { 4538, 3056 }, { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, - { 4545, 3063 }, { 4546, 3064 }, { 4547, 3066 }, { 4548, 3067 }, { 4549, 3068 }, { 4550, 3069 }, { 4551, 3070 }, - { 4552, 3071 }, { 4553, 3072 }, { 4627, 3073 }, { 4628, 3074 }, { 4629, 3075 }, { 4630, 3076 }, { 4631, 3077 }, - { 4632, 3078 }, { 4633, 3079 }, { 4634, 3080 }, { 4635, 3081 }, { 4636, 3082 }, { 4637, 3083 }, { 4638, 3084 }, - { 4639, 3085 }, { 4640, 3086 }, { 4641, 3087 }, { 4642, 3088 }, { 4643, 3089 }, { 4644, 3090 }, { 4645, 3091 }, - { 4646, 3092 }, { 4647, 3093 }, { 4648, 3094 }, { 4649, 3095 }, { 4650, 3096 }, { 4651, 3097 }, { 4652, 3098 }, - { 4653, 3099 }, { 4654, 3100 }, { 4655, 3101 }, { 4656, 3102 }, { 4657, 3103 }, { 4658, 3104 }, { 4659, 3105 }, - { 4660, 3106 }, { 4661, 3107 }, { 4662, 3108 }, { 4663, 3109 }, { 4664, 3110 }, { 4665, 3111 }, { 4666, 3112 }, - { 4667, 3113 }, { 4668, 3114 }, { 4669, 3115 }, { 4670, 3116 }, { 4671, 3117 }, { 4672, 3118 }, { 4673, 3119 }, - { 4674, 3120 }, { 4675, 3121 }, { 4676, 3122 }, { 4677, 3123 }, { 4678, 3124 }, { 4679, 3125 }, { 4680, 3126 }, - { 4681, 3127 }, { 4682, 3128 }, { 4683, 3129 }, { 4684, 3130 }, { 4685, 3131 }, { 4686, 3132 }, { 4687, 3133 }, - { 4688, 3134 }, { 4689, 3135 }, { 4690, 3136 }, { 4691, 3137 }, { 4692, 3138 }, { 4693, 3139 }, { 4694, 3140 }, - { 4695, 3141 }, { 4696, 3142 }, { 4697, 3143 }, { 4698, 3144 }, { 4699, 3145 }, { 4700, 3146 }, { 4701, 3147 }, - { 4702, 3148 }, { 4703, 3149 }, { 4704, 3150 }, { 4705, 3151 }, { 4706, 3152 }, { 4707, 3153 }, { 4708, 3154 }, - { 4709, 3155 }, { 4710, 3156 }, { 4711, 3157 }, { 4712, 3158 }, { 4713, 3159 }, { 4714, 3160 }, { 4715, 3161 }, - { 4716, 3162 }, { 4717, 3163 }, { 4718, 3164 }, { 4719, 3165 }, { 4720, 3166 }, { 4721, 3167 }, { 4722, 3168 }, - { 4723, 3169 }, { 4724, 3170 }, { 4725, 3171 }, { 4726, 3172 }, { 4827, 3173 }, { 4828, 3174 }, { 4829, 3175 }, - { 4830, 3176 }, { 4831, 3177 }, { 4832, 3178 }, { 4833, 3179 }, { 4834, 3180 }, { 4835, 3181 }, { 4836, 3182 }, - { 4837, 3183 }, { 4838, 3184 }, { 4839, 3185 }, { 4840, 3186 }, { 4841, 3187 }, { 4842, 3188 }, { 4843, 3189 }, - { 4844, 3190 }, { 4845, 3191 }, { 5027, 3192 }, { 5028, 3193 }, { 5029, 3194 }, { 5030, 3195 }, { 5031, 3196 }, - { 5032, 3197 }, { 5033, 3198 }, { 5034, 3199 }, { 5035, 3200 }, { 5036, 3201 }, { 5037, 3202 }, { 5038, 3203 }, - { 5039, 3204 }, { 5040, 3205 }, { 5041, 3206 }, { 5042, 3207 }, { 5043, 3208 }, { 5044, 3209 }, { 5045, 3210 }, - { 5046, 3211 }, { 5047, 3212 }, { 5048, 3213 }, { 5049, 3214 }, { 5050, 3215 }, { 5051, 3216 }, { 5052, 3217 }, - { 5053, 3218 }, { 5054, 3219 }, { 5055, 3220 }, { 5056, 3221 }, { 5057, 3222 }, { 5058, 3223 }, { 5059, 3224 }, - { 5060, 3225 }, { 5061, 3226 }, { 5062, 3227 }, { 5063, 3228 }, { 5064, 3229 }, { 5065, 3230 }, { 5066, 3231 }, - { 5067, 3232 }, { 5068, 3233 }, { 5069, 3234 }, { 5070, 3235 }, { 5071, 3236 }, { 5072, 3237 }, { 5073, 3238 }, - { 5074, 3239 }, { 5075, 3240 }, { 5076, 3241 }, { 5077, 3242 }, { 5127, 3243 }, { 5128, 3244 }, { 5129, 3245 }, - { 5130, 3246 }, { 5131, 3247 }, { 5132, 3248 }, { 5133, 3249 }, { 5134, 3250 }, { 5135, 3251 }, { 5136, 3252 }, - { 5137, 3253 }, { 5138, 3254 }, { 5139, 3255 }, { 5140, 3256 }, { 5141, 3257 }, { 5142, 3258 }, { 5143, 3259 }, - { 5144, 3260 }, { 5145, 3261 }, { 5146, 3262 }, { 5147, 3263 }, { 5148, 3264 }, { 5149, 3265 }, { 5150, 3266 }, - { 5151, 3267 }, { 5152, 3268 }, { 5153, 3269 }, { 5154, 3270 }, { 5155, 3271 }, { 5156, 3272 }, { 5227, 3273 }, - { 5228, 3274 }, { 5229, 3275 }, { 5230, 3276 }, { 5231, 3277 }, { 5232, 3278 }, { 5233, 3279 }, { 5234, 3280 }, - { 5235, 3281 }, { 5236, 3282 }, { 5237, 3283 }, { 5238, 3284 }, { 5240, 3286 }, { 5241, 3287 }, { 5242, 3288 }, - { 5243, 3289 }, { 5244, 3290 }, { 5245, 3291 }, { 5246, 3292 }, { 5247, 3293 }, { 5248, 3294 }, { 5249, 3295 }, - { 5250, 3296 }, { 5251, 3297 }, { 5252, 3298 }, { 5253, 3299 }, { 5254, 3300 }, { 5255, 3301 }, { 5256, 3302 }, - { 5257, 3303 }, { 5258, 3304 }, { 5259, 3305 }, { 5260, 3306 }, { 5261, 3307 }, { 5262, 3308 }, { 5263, 3309 }, - { 5264, 3310 }, { 5265, 3311 }, { 5266, 3312 }, { 5267, 3313 }, { 5268, 3314 }, { 5269, 3315 }, { 5270, 3316 }, - { 5271, 3317 }, { 5272, 3318 }, { 5273, 3319 }, { 5274, 3320 }, { 5275, 3321 }, { 5276, 3322 }, { 5277, 3323 }, - { 5278, 3324 }, { 5279, 3325 }, { 5280, 3326 }, { 5281, 3327 }, { 5282, 3328 }, { 5283, 3329 }, { 5284, 3330 }, - { 5285, 3331 }, { 5286, 3332 }, { 5288, 3334 }, { 5289, 3335 }, { 5290, 3336 }, { 5291, 3337 }, { 5292, 3338 }, - { 5293, 3339 }, { 5294, 3340 }, { 5296, 3342 }, { 5297, 3343 }, { 5298, 3344 }, { 5299, 3345 }, { 5300, 3346 }, - { 5301, 3347 }, { 5302, 3348 }, { 5303, 3349 }, { 5304, 3350 }, { 5305, 3351 }, { 5306, 3352 }, { 5307, 3353 }, - { 5308, 3354 }, { 5309, 3355 }, { 5310, 3356 }, { 5311, 3357 }, { 5312, 3358 }, { 5313, 3359 }, { 5314, 3360 }, - { 5315, 3361 }, { 5316, 3362 }, { 5317, 3363 }, { 5318, 3364 }, { 5319, 3365 }, { 5320, 3366 }, { 5321, 3367 }, - { 5322, 3368 }, { 5323, 3369 }, { 5324, 3370 }, { 5325, 3371 }, { 5326, 3372 }, { 5327, 3373 }, { 5328, 3374 }, - { 5329, 3375 }, { 5330, 3376 }, { 5331, 3377 }, { 5332, 3378 }, { 5333, 3379 }, { 5336, 3382 }, { 5337, 3383 }, - { 5338, 3384 }, { 5339, 3385 }, { 5340, 3386 }, { 5341, 3387 }, { 5342, 3388 }, { 5343, 3389 }, { 5344, 3390 }, - { 5345, 3391 }, { 5346, 3392 }, { 5347, 3393 }, { 5348, 3394 }, { 5349, 3395 }, { 5350, 3396 }, { 5351, 3397 }, - { 5352, 3398 }, { 5357, 3403 }, { 5358, 3404 }, { 5359, 3405 }, { 5360, 3406 }, { 5361, 3407 }, { 5362, 3408 }, - { 5363, 3409 }, { 5364, 3410 }, { 5365, 3411 }, { 5366, 3412 }, { 5367, 3413 }, { 5368, 3414 }, { 5369, 3415 }, - { 5370, 3416 }, { 5371, 3417 }, { 5372, 3418 }, { 5373, 3419 }, { 5374, 3420 }, { 5375, 3421 }, { 5376, 3422 }, - { 5377, 3423 }, { 5378, 3424 }, { 5379, 3425 }, { 5380, 3426 }, { 5381, 3427 }, { 5382, 3428 }, { 5383, 3429 }, - { 5384, 3430 }, { 5385, 3431 }, { 5386, 3432 }, { 5387, 3433 }, { 5388, 3434 }, { 5389, 3435 }, { 5390, 3436 }, - { 5391, 3437 }, { 5392, 3438 }, { 5393, 3439 }, { 5394, 3440 }, { 5395, 3441 }, { 5396, 3442 }, { 5397, 3443 }, - { 5398, 3444 }, { 5399, 3445 }, { 5400, 3446 }, { 5401, 3447 }, { 5402, 3448 }, { 5403, 3449 }, { 5404, 3450 }, - { 5405, 3451 }, { 5406, 3452 }, { 5407, 3453 }, { 5408, 3454 }, { 5409, 3455 }, { 5410, 3456 }, { 5411, 3457 }, - { 5412, 3458 }, { 5413, 3459 }, { 5414, 3460 }, { 5415, 3461 }, { 5416, 3462 }, { 5417, 3463 }, { 5418, 3464 }, - { 5419, 3465 }, { 5420, 3466 }, { 5421, 3467 }, { 5422, 3468 }, { 5423, 3469 }, { 5424, 3470 }, { 5425, 3471 }, - { 5426, 3472 }, { 5427, 3473 }, { 5428, 3474 }, { 5429, 3475 }, { 5430, 3476 }, { 5431, 3477 }, { 5432, 3478 }, - { 5433, 3479 }, { 5434, 3480 }, { 5435, 3481 }, { 5436, 3482 }, { 5437, 3483 }, { 5438, 3484 }, { 5439, 3485 }, - { 5440, 3486 }, { 5441, 3487 }, { 5442, 3488 }, { 5443, 3489 }, { 5444, 3490 }, { 5445, 3491 }, { 5446, 3492 }, - { 5447, 3493 }, { 5448, 3494 }, { 5449, 3495 }, { 5450, 3496 }, { 5451, 3497 }, { 5452, 3498 }, { 5453, 3499 }, - { 5454, 3500 }, { 5455, 3501 }, { 5456, 3502 }, { 5457, 3503 }, { 5458, 3504 }, { 5459, 3505 }, { 5460, 3506 }, - { 5461, 3507 }, { 5462, 3508 }, { 5463, 3509 }, { 5464, 3510 }, { 5465, 3511 }, { 5466, 3512 }, { 5467, 3513 }, - { 5468, 3514 }, { 5469, 3515 }, { 5470, 3516 }, { 5471, 3517 }, { 5472, 3518 }, { 5473, 3519 }, { 5474, 3520 }, - { 5475, 3521 }, { 5476, 3522 }, { 5477, 3523 }, { 5478, 3524 }, { 5479, 3525 }, { 5480, 3526 }, { 5481, 3527 }, - { 5482, 3528 }, { 5483, 3529 }, { 5484, 3530 }, { 5485, 3531 }, { 5486, 3532 }, { 5487, 3533 }, { 5488, 3534 }, - { 5489, 3535 }, { 5490, 3536 }, { 5491, 3537 }, { 5492, 3538 }, { 5493, 3539 }, { 5494, 3540 }, { 5495, 3541 }, - { 5496, 3542 }, { 5497, 3543 }, { 5498, 3544 }, { 5499, 3545 }, { 5500, 3546 }, { 5501, 3547 }, { 5502, 3548 }, - { 5503, 3549 }, { 5504, 3550 }, { 5505, 3551 }, { 5506, 3552 }, { 5507, 3553 }, { 5508, 3554 }, { 5509, 3555 }, - { 5510, 3556 }, { 5511, 3557 }, { 5512, 3558 }, { 5513, 3559 }, { 5514, 3560 }, { 5515, 3561 }, { 5516, 3562 }, - { 5517, 3563 }, { 5518, 3564 }, { 5519, 3565 }, { 5520, 3566 }, { 5521, 3567 }, { 5522, 3568 }, { 5523, 3569 }, - { 5524, 3570 }, { 5525, 3571 }, { 5526, 3572 }, { 5527, 3573 }, { 5528, 3574 }, { 5529, 3575 }, { 5530, 3576 }, - { 5531, 3577 }, { 5532, 3578 }, { 5533, 3579 }, { 5534, 3580 }, { 5535, 3581 }, { 5536, 3582 }, { 5537, 3583 }, - { 5538, 3584 }, { 5539, 3585 }, { 5540, 3586 }, { 5541, 3587 }, { 5542, 3588 }, { 5543, 3589 }, { 5544, 3590 }, - { 5545, 3591 }, { 5546, 3592 }, { 5547, 3593 }, { 5548, 3594 }, { 5549, 3595 }, { 5550, 3596 }, { 5551, 3597 }, - { 5552, 3598 }, { 5553, 3599 }, { 5554, 3600 }, { 5555, 3601 }, { 5556, 3602 }, { 5557, 3603 }, { 5558, 3604 }, - { 5559, 3605 }, { 5560, 3606 }, { 5561, 3607 }, { 5562, 3608 }, { 5563, 3609 }, { 5564, 3610 }, { 5565, 3611 }, - { 5566, 3612 }, { 5567, 3613 }, { 5568, 3614 }, { 5569, 3615 }, { 5570, 3616 }, { 4554, 3065 }, + { 2504, 2248 }, { 2508, 2252 }, { 2511, 2255 }, { 2513, 2257 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, + { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, + { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, + { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, + { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, + { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, + { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, + { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, + { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, + { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, + { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, + { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, + { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2878, 2396 }, + { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, + { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, + { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, + { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, + { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, + { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, + { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, + { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, + { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, + { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, + { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, + { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, + { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, + { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, + { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, + { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, + { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, + { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, + { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, + { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, + { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, + { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, + { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, + { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, + { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, { 3382, 2569 }, { 3383, 2570 }, { 3384, 2571 }, + { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, + { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, + { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, + { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, + { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, + { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, + { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, + { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, + { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, + { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, + { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, + { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, + { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, + { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, + { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, + { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, + { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, + { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, + { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, + { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, + { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, + { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, + { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, + { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, + { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, + { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, + { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, + { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, + { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, + { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, + { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, + { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, + { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, + { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, + { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, + { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, + { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, + { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, + { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, + { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, + { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, + { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, + { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, + { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, + { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, + { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, + { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, + { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, + { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, + { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, + { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, + { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, + { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, + { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, + { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, + { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, + { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, + { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, + { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, + { 4400, 2994 }, { 4401, 2995 }, { 4402, 2996 }, { 4403, 2997 }, { 4404, 2998 }, { 4405, 2999 }, { 4406, 3000 }, + { 4407, 3001 }, { 4408, 3002 }, { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, + { 4414, 3008 }, { 4415, 3009 }, { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, + { 4421, 3015 }, { 4422, 3016 }, { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4427, 3021 }, + { 4428, 3022 }, { 4429, 3023 }, { 4430, 3024 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, { 4434, 3028 }, + { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, { 4441, 3035 }, + { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, { 4448, 3042 }, + { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, { 4531, 3049 }, + { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, { 4538, 3056 }, + { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, { 4545, 3063 }, + { 4546, 3064 }, { 4547, 3066 }, { 4548, 3067 }, { 4549, 3068 }, { 4550, 3069 }, { 4551, 3070 }, { 4552, 3071 }, + { 4553, 3072 }, { 4627, 3073 }, { 4628, 3074 }, { 4629, 3075 }, { 4630, 3076 }, { 4631, 3077 }, { 4632, 3078 }, + { 4633, 3079 }, { 4634, 3080 }, { 4635, 3081 }, { 4636, 3082 }, { 4637, 3083 }, { 4638, 3084 }, { 4639, 3085 }, + { 4640, 3086 }, { 4641, 3087 }, { 4642, 3088 }, { 4643, 3089 }, { 4644, 3090 }, { 4645, 3091 }, { 4646, 3092 }, + { 4647, 3093 }, { 4648, 3094 }, { 4649, 3095 }, { 4650, 3096 }, { 4651, 3097 }, { 4652, 3098 }, { 4653, 3099 }, + { 4654, 3100 }, { 4655, 3101 }, { 4656, 3102 }, { 4657, 3103 }, { 4658, 3104 }, { 4659, 3105 }, { 4660, 3106 }, + { 4661, 3107 }, { 4662, 3108 }, { 4663, 3109 }, { 4664, 3110 }, { 4665, 3111 }, { 4666, 3112 }, { 4667, 3113 }, + { 4668, 3114 }, { 4669, 3115 }, { 4670, 3116 }, { 4671, 3117 }, { 4672, 3118 }, { 4673, 3119 }, { 4674, 3120 }, + { 4675, 3121 }, { 4676, 3122 }, { 4677, 3123 }, { 4678, 3124 }, { 4679, 3125 }, { 4680, 3126 }, { 4681, 3127 }, + { 4682, 3128 }, { 4683, 3129 }, { 4684, 3130 }, { 4685, 3131 }, { 4686, 3132 }, { 4687, 3133 }, { 4688, 3134 }, + { 4689, 3135 }, { 4690, 3136 }, { 4691, 3137 }, { 4692, 3138 }, { 4693, 3139 }, { 4694, 3140 }, { 4695, 3141 }, + { 4696, 3142 }, { 4697, 3143 }, { 4698, 3144 }, { 4699, 3145 }, { 4700, 3146 }, { 4701, 3147 }, { 4702, 3148 }, + { 4703, 3149 }, { 4704, 3150 }, { 4705, 3151 }, { 4706, 3152 }, { 4707, 3153 }, { 4708, 3154 }, { 4709, 3155 }, + { 4710, 3156 }, { 4711, 3157 }, { 4712, 3158 }, { 4713, 3159 }, { 4714, 3160 }, { 4715, 3161 }, { 4716, 3162 }, + { 4717, 3163 }, { 4718, 3164 }, { 4719, 3165 }, { 4720, 3166 }, { 4721, 3167 }, { 4722, 3168 }, { 4723, 3169 }, + { 4724, 3170 }, { 4725, 3171 }, { 4726, 3172 }, { 4827, 3173 }, { 4828, 3174 }, { 4829, 3175 }, { 4830, 3176 }, + { 4831, 3177 }, { 4832, 3178 }, { 4833, 3179 }, { 4834, 3180 }, { 4835, 3181 }, { 4836, 3182 }, { 4837, 3183 }, + { 4838, 3184 }, { 4839, 3185 }, { 4840, 3186 }, { 4841, 3187 }, { 4842, 3188 }, { 4843, 3189 }, { 4844, 3190 }, + { 4845, 3191 }, { 5027, 3192 }, { 5028, 3193 }, { 5029, 3194 }, { 5030, 3195 }, { 5031, 3196 }, { 5032, 3197 }, + { 5033, 3198 }, { 5034, 3199 }, { 5035, 3200 }, { 5036, 3201 }, { 5037, 3202 }, { 5038, 3203 }, { 5039, 3204 }, + { 5040, 3205 }, { 5041, 3206 }, { 5042, 3207 }, { 5043, 3208 }, { 5044, 3209 }, { 5045, 3210 }, { 5046, 3211 }, + { 5047, 3212 }, { 5048, 3213 }, { 5049, 3214 }, { 5050, 3215 }, { 5051, 3216 }, { 5052, 3217 }, { 5053, 3218 }, + { 5054, 3219 }, { 5055, 3220 }, { 5056, 3221 }, { 5057, 3222 }, { 5058, 3223 }, { 5059, 3224 }, { 5060, 3225 }, + { 5061, 3226 }, { 5062, 3227 }, { 5063, 3228 }, { 5064, 3229 }, { 5065, 3230 }, { 5066, 3231 }, { 5067, 3232 }, + { 5068, 3233 }, { 5069, 3234 }, { 5070, 3235 }, { 5071, 3236 }, { 5072, 3237 }, { 5073, 3238 }, { 5074, 3239 }, + { 5075, 3240 }, { 5076, 3241 }, { 5077, 3242 }, { 5127, 3243 }, { 5128, 3244 }, { 5129, 3245 }, { 5130, 3246 }, + { 5131, 3247 }, { 5132, 3248 }, { 5133, 3249 }, { 5134, 3250 }, { 5135, 3251 }, { 5136, 3252 }, { 5137, 3253 }, + { 5138, 3254 }, { 5139, 3255 }, { 5140, 3256 }, { 5141, 3257 }, { 5142, 3258 }, { 5143, 3259 }, { 5144, 3260 }, + { 5145, 3261 }, { 5146, 3262 }, { 5147, 3263 }, { 5148, 3264 }, { 5149, 3265 }, { 5150, 3266 }, { 5151, 3267 }, + { 5152, 3268 }, { 5153, 3269 }, { 5154, 3270 }, { 5155, 3271 }, { 5156, 3272 }, { 5227, 3273 }, { 5228, 3274 }, + { 5229, 3275 }, { 5230, 3276 }, { 5231, 3277 }, { 5232, 3278 }, { 5233, 3279 }, { 5234, 3280 }, { 5235, 3281 }, + { 5236, 3282 }, { 5237, 3283 }, { 5238, 3284 }, { 5240, 3286 }, { 5241, 3287 }, { 5242, 3288 }, { 5243, 3289 }, + { 5244, 3290 }, { 5245, 3291 }, { 5246, 3292 }, { 5247, 3293 }, { 5248, 3294 }, { 5249, 3295 }, { 5250, 3296 }, + { 5251, 3297 }, { 5252, 3298 }, { 5253, 3299 }, { 5254, 3300 }, { 5255, 3301 }, { 5256, 3302 }, { 5257, 3303 }, + { 5258, 3304 }, { 5259, 3305 }, { 5260, 3306 }, { 5261, 3307 }, { 5262, 3308 }, { 5263, 3309 }, { 5264, 3310 }, + { 5265, 3311 }, { 5266, 3312 }, { 5267, 3313 }, { 5268, 3314 }, { 5269, 3315 }, { 5270, 3316 }, { 5271, 3317 }, + { 5272, 3318 }, { 5273, 3319 }, { 5274, 3320 }, { 5275, 3321 }, { 5276, 3322 }, { 5277, 3323 }, { 5278, 3324 }, + { 5279, 3325 }, { 5280, 3326 }, { 5281, 3327 }, { 5282, 3328 }, { 5283, 3329 }, { 5284, 3330 }, { 5285, 3331 }, + { 5286, 3332 }, { 5288, 3334 }, { 5289, 3335 }, { 5290, 3336 }, { 5291, 3337 }, { 5292, 3338 }, { 5293, 3339 }, + { 5294, 3340 }, { 5296, 3342 }, { 5297, 3343 }, { 5298, 3344 }, { 5299, 3345 }, { 5300, 3346 }, { 5301, 3347 }, + { 5302, 3348 }, { 5303, 3349 }, { 5304, 3350 }, { 5305, 3351 }, { 5306, 3352 }, { 5307, 3353 }, { 5308, 3354 }, + { 5309, 3355 }, { 5310, 3356 }, { 5311, 3357 }, { 5312, 3358 }, { 5313, 3359 }, { 5314, 3360 }, { 5315, 3361 }, + { 5316, 3362 }, { 5317, 3363 }, { 5318, 3364 }, { 5319, 3365 }, { 5320, 3366 }, { 5321, 3367 }, { 5322, 3368 }, + { 5323, 3369 }, { 5324, 3370 }, { 5325, 3371 }, { 5326, 3372 }, { 5327, 3373 }, { 5328, 3374 }, { 5329, 3375 }, + { 5330, 3376 }, { 5331, 3377 }, { 5332, 3378 }, { 5333, 3379 }, { 5336, 3382 }, { 5337, 3383 }, { 5338, 3384 }, + { 5339, 3385 }, { 5340, 3386 }, { 5341, 3387 }, { 5342, 3388 }, { 5343, 3389 }, { 5344, 3390 }, { 5345, 3391 }, + { 5346, 3392 }, { 5347, 3393 }, { 5348, 3394 }, { 5349, 3395 }, { 5350, 3396 }, { 5351, 3397 }, { 5352, 3398 }, + { 5357, 3403 }, { 5358, 3404 }, { 5359, 3405 }, { 5360, 3406 }, { 5361, 3407 }, { 5362, 3408 }, { 5363, 3409 }, + { 5364, 3410 }, { 5365, 3411 }, { 5366, 3412 }, { 5367, 3413 }, { 5368, 3414 }, { 5369, 3415 }, { 5370, 3416 }, + { 5371, 3417 }, { 5372, 3418 }, { 5373, 3419 }, { 5374, 3420 }, { 5375, 3421 }, { 5376, 3422 }, { 5377, 3423 }, + { 5378, 3424 }, { 5379, 3425 }, { 5380, 3426 }, { 5381, 3427 }, { 5382, 3428 }, { 5383, 3429 }, { 5384, 3430 }, + { 5385, 3431 }, { 5386, 3432 }, { 5387, 3433 }, { 5388, 3434 }, { 5389, 3435 }, { 5390, 3436 }, { 5391, 3437 }, + { 5392, 3438 }, { 5393, 3439 }, { 5394, 3440 }, { 5395, 3441 }, { 5396, 3442 }, { 5397, 3443 }, { 5398, 3444 }, + { 5399, 3445 }, { 5400, 3446 }, { 5401, 3447 }, { 5402, 3448 }, { 5403, 3449 }, { 5404, 3450 }, { 5405, 3451 }, + { 5406, 3452 }, { 5407, 3453 }, { 5408, 3454 }, { 5409, 3455 }, { 5410, 3456 }, { 5411, 3457 }, { 5412, 3458 }, + { 5413, 3459 }, { 5414, 3460 }, { 5415, 3461 }, { 5416, 3462 }, { 5417, 3463 }, { 5418, 3464 }, { 5419, 3465 }, + { 5420, 3466 }, { 5421, 3467 }, { 5422, 3468 }, { 5423, 3469 }, { 5424, 3470 }, { 5425, 3471 }, { 5426, 3472 }, + { 5427, 3473 }, { 5428, 3474 }, { 5429, 3475 }, { 5430, 3476 }, { 5431, 3477 }, { 5432, 3478 }, { 5433, 3479 }, + { 5434, 3480 }, { 5435, 3481 }, { 5436, 3482 }, { 5437, 3483 }, { 5438, 3484 }, { 5439, 3485 }, { 5440, 3486 }, + { 5441, 3487 }, { 5442, 3488 }, { 5443, 3489 }, { 5444, 3490 }, { 5445, 3491 }, { 5446, 3492 }, { 5447, 3493 }, + { 5448, 3494 }, { 5449, 3495 }, { 5450, 3496 }, { 5451, 3497 }, { 5452, 3498 }, { 5453, 3499 }, { 5454, 3500 }, + { 5455, 3501 }, { 5456, 3502 }, { 5457, 3503 }, { 5458, 3504 }, { 5459, 3505 }, { 5460, 3506 }, { 5461, 3507 }, + { 5462, 3508 }, { 5463, 3509 }, { 5464, 3510 }, { 5465, 3511 }, { 5466, 3512 }, { 5467, 3513 }, { 5468, 3514 }, + { 5469, 3515 }, { 5470, 3516 }, { 5471, 3517 }, { 5472, 3518 }, { 5473, 3519 }, { 5474, 3520 }, { 5475, 3521 }, + { 5476, 3522 }, { 5477, 3523 }, { 5478, 3524 }, { 5479, 3525 }, { 5480, 3526 }, { 5481, 3527 }, { 5482, 3528 }, + { 5483, 3529 }, { 5484, 3530 }, { 5485, 3531 }, { 5486, 3532 }, { 5487, 3533 }, { 5488, 3534 }, { 5489, 3535 }, + { 5490, 3536 }, { 5491, 3537 }, { 5492, 3538 }, { 5493, 3539 }, { 5494, 3540 }, { 5495, 3541 }, { 5496, 3542 }, + { 5497, 3543 }, { 5498, 3544 }, { 5499, 3545 }, { 5500, 3546 }, { 5501, 3547 }, { 5502, 3548 }, { 5503, 3549 }, + { 5504, 3550 }, { 5505, 3551 }, { 5506, 3552 }, { 5507, 3553 }, { 5508, 3554 }, { 5509, 3555 }, { 5510, 3556 }, + { 5511, 3557 }, { 5512, 3558 }, { 5513, 3559 }, { 5514, 3560 }, { 5515, 3561 }, { 5516, 3562 }, { 5517, 3563 }, + { 5518, 3564 }, { 5519, 3565 }, { 5520, 3566 }, { 5521, 3567 }, { 5522, 3568 }, { 5523, 3569 }, { 5524, 3570 }, + { 5525, 3571 }, { 5526, 3572 }, { 5527, 3573 }, { 5528, 3574 }, { 5529, 3575 }, { 5530, 3576 }, { 5531, 3577 }, + { 5532, 3578 }, { 5533, 3579 }, { 5534, 3580 }, { 5535, 3581 }, { 5536, 3582 }, { 5537, 3583 }, { 5538, 3584 }, + { 5539, 3585 }, { 5540, 3586 }, { 5541, 3587 }, { 5542, 3588 }, { 5543, 3589 }, { 5544, 3590 }, { 5545, 3591 }, + { 5546, 3592 }, { 5547, 3593 }, { 5548, 3594 }, { 5549, 3595 }, { 5550, 3596 }, { 5551, 3597 }, { 5552, 3598 }, + { 5553, 3599 }, { 5554, 3600 }, { 5555, 3601 }, { 5556, 3602 }, { 5557, 3603 }, { 5558, 3604 }, { 5559, 3605 }, + { 5560, 3606 }, { 5561, 3607 }, { 5562, 3608 }, { 5563, 3609 }, { 5564, 3610 }, { 5565, 3611 }, { 5566, 3612 }, + { 5567, 3613 }, { 5568, 3614 }, { 5569, 3615 }, { 5570, 3616 }, { 4554, 3065 }, }; -// v1.0 -> JP asset ID remap table. 1309 entries. +// v1.0 -> JP asset ID remap table. 1312 entries. static const std::unordered_map sV10toJPRemap = { { 2468, 2212 }, { 2469, 2213 }, { 2470, 2214 }, { 2471, 2215 }, { 2472, 2216 }, { 2473, 2217 }, { 2474, 2218 }, { 2475, 2219 }, { 2476, 2220 }, { 2477, 2221 }, { 2478, 2222 }, { 2481, 2225 }, { 2483, 2227 }, { 2484, 2228 }, { 2485, 2229 }, { 2487, 2231 }, { 2488, 2232 }, { 2489, 2233 }, { 2490, 2234 }, { 2491, 2235 }, { 2498, 2242 }, - { 2504, 2248 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, - { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, - { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, - { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, - { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, - { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, - { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, - { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, - { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, - { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, - { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, - { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, - { 2877, 2395 }, { 2878, 2396 }, { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, - { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, - { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, - { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, - { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, - { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, - { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, - { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, - { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, - { 3104, 2463 }, { 3105, 2464 }, { 3106, 2466 }, { 3107, 2467 }, { 3108, 2468 }, { 3109, 2469 }, { 3110, 2470 }, - { 3111, 2471 }, { 3112, 2472 }, { 3113, 2473 }, { 3114, 2474 }, { 3115, 2475 }, { 3171, 2476 }, { 3172, 2477 }, - { 3173, 2478 }, { 3174, 2479 }, { 3175, 2480 }, { 3176, 2481 }, { 3177, 2482 }, { 3178, 2483 }, { 3179, 2484 }, - { 3180, 2485 }, { 3181, 2486 }, { 3182, 2487 }, { 3183, 2488 }, { 3184, 2489 }, { 3185, 2490 }, { 3186, 2491 }, - { 3187, 2492 }, { 3188, 2493 }, { 3189, 2494 }, { 3190, 2495 }, { 3191, 2496 }, { 3192, 2497 }, { 3193, 2498 }, - { 3194, 2499 }, { 3195, 2500 }, { 3196, 2501 }, { 3197, 2502 }, { 3198, 2503 }, { 3199, 2504 }, { 3200, 2505 }, - { 3201, 2506 }, { 3202, 2507 }, { 3203, 2508 }, { 3204, 2509 }, { 3205, 2510 }, { 3206, 2511 }, { 3207, 2512 }, - { 3208, 2513 }, { 3209, 2514 }, { 3210, 2515 }, { 3211, 2516 }, { 3212, 2517 }, { 3213, 2518 }, { 3214, 2519 }, - { 3215, 2520 }, { 3216, 2521 }, { 3217, 2522 }, { 3218, 2523 }, { 3219, 2524 }, { 3220, 2525 }, { 3221, 2526 }, - { 3222, 2527 }, { 3223, 2528 }, { 3224, 2529 }, { 3271, 2530 }, { 3272, 2531 }, { 3273, 2532 }, { 3274, 2533 }, - { 3275, 2534 }, { 3276, 2535 }, { 3277, 2536 }, { 3278, 2537 }, { 3279, 2538 }, { 3280, 2539 }, { 3281, 2540 }, - { 3282, 2541 }, { 3283, 2542 }, { 3284, 2543 }, { 3285, 2544 }, { 3286, 2545 }, { 3287, 2546 }, { 3288, 2547 }, - { 3289, 2548 }, { 3290, 2549 }, { 3291, 2550 }, { 3292, 2551 }, { 3293, 2552 }, { 3294, 2553 }, { 3295, 2554 }, - { 3296, 2555 }, { 3297, 2556 }, { 3298, 2557 }, { 3299, 2558 }, { 3300, 2559 }, { 3301, 2560 }, { 3302, 2561 }, - { 3303, 2562 }, { 3304, 2563 }, { 3371, 2564 }, { 3372, 2565 }, { 3373, 2566 }, { 3374, 2567 }, { 3375, 2568 }, - { 3376, 2569 }, { 3377, 2570 }, { 3378, 2571 }, { 3379, 2572 }, { 3380, 2573 }, { 3381, 2574 }, { 3382, 2575 }, - { 3383, 2576 }, { 3384, 2577 }, { 3385, 2578 }, { 3471, 2579 }, { 3472, 2580 }, { 3473, 2581 }, { 3474, 2582 }, - { 3475, 2583 }, { 3476, 2584 }, { 3477, 2585 }, { 3478, 2586 }, { 3479, 2587 }, { 3480, 2588 }, { 3481, 2589 }, - { 3482, 2590 }, { 3483, 2591 }, { 3484, 2592 }, { 3485, 2593 }, { 3486, 2594 }, { 3487, 2595 }, { 3488, 2596 }, - { 3489, 2597 }, { 3490, 2598 }, { 3491, 2599 }, { 3492, 2600 }, { 3493, 2601 }, { 3494, 2602 }, { 3495, 2603 }, - { 3496, 2604 }, { 3497, 2605 }, { 3498, 2606 }, { 3499, 2607 }, { 3500, 2608 }, { 3501, 2609 }, { 3502, 2610 }, - { 3503, 2611 }, { 3504, 2612 }, { 3505, 2613 }, { 3506, 2614 }, { 3507, 2615 }, { 3508, 2616 }, { 3509, 2617 }, - { 3510, 2618 }, { 3571, 2619 }, { 3572, 2620 }, { 3573, 2621 }, { 3574, 2622 }, { 3575, 2623 }, { 3576, 2624 }, - { 3577, 2625 }, { 3578, 2626 }, { 3579, 2627 }, { 3580, 2628 }, { 3581, 2629 }, { 3582, 2630 }, { 3583, 2631 }, - { 3584, 2632 }, { 3585, 2633 }, { 3586, 2634 }, { 3587, 2635 }, { 3588, 2636 }, { 3589, 2637 }, { 3590, 2638 }, - { 3591, 2639 }, { 3592, 2640 }, { 3593, 2641 }, { 3594, 2642 }, { 3595, 2643 }, { 3596, 2644 }, { 3597, 2645 }, - { 3598, 2646 }, { 3599, 2647 }, { 3600, 2648 }, { 3601, 2649 }, { 3602, 2650 }, { 3603, 2651 }, { 3604, 2652 }, - { 3605, 2653 }, { 3606, 2654 }, { 3607, 2655 }, { 3608, 2656 }, { 3609, 2657 }, { 3610, 2658 }, { 3611, 2659 }, - { 3612, 2660 }, { 3613, 2661 }, { 3614, 2662 }, { 3615, 2663 }, { 3616, 2664 }, { 3617, 2665 }, { 3618, 2666 }, - { 3619, 2667 }, { 3620, 2668 }, { 3621, 2669 }, { 3622, 2670 }, { 3623, 2671 }, { 3624, 2672 }, { 3625, 2673 }, - { 3626, 2674 }, { 3627, 2675 }, { 3628, 2676 }, { 3629, 2677 }, { 3630, 2678 }, { 3631, 2679 }, { 3632, 2680 }, - { 3633, 2681 }, { 3634, 2682 }, { 3635, 2683 }, { 3636, 2684 }, { 3637, 2685 }, { 3638, 2686 }, { 3639, 2687 }, - { 3640, 2688 }, { 3641, 2689 }, { 3642, 2690 }, { 3643, 2691 }, { 3644, 2692 }, { 3645, 2693 }, { 3646, 2694 }, - { 3671, 2696 }, { 3672, 2697 }, { 3673, 2698 }, { 3674, 2699 }, { 3675, 2700 }, { 3676, 2701 }, { 3677, 2702 }, - { 3678, 2703 }, { 3679, 2704 }, { 3680, 2705 }, { 3681, 2706 }, { 3682, 2707 }, { 3683, 2708 }, { 3684, 2709 }, - { 3685, 2710 }, { 3686, 2711 }, { 3687, 2712 }, { 3688, 2713 }, { 3689, 2714 }, { 3690, 2715 }, { 3691, 2716 }, - { 3692, 2717 }, { 3693, 2718 }, { 3694, 2719 }, { 3695, 2720 }, { 3696, 2721 }, { 3697, 2722 }, { 3698, 2723 }, - { 3699, 2724 }, { 3700, 2725 }, { 3701, 2726 }, { 3702, 2727 }, { 3703, 2728 }, { 3704, 2729 }, { 3705, 2730 }, - { 3706, 2731 }, { 3707, 2732 }, { 3708, 2733 }, { 3709, 2734 }, { 3710, 2735 }, { 3711, 2736 }, { 3712, 2737 }, - { 3713, 2738 }, { 3714, 2739 }, { 3715, 2740 }, { 3716, 2741 }, { 3717, 2742 }, { 3718, 2743 }, { 3719, 2744 }, - { 3720, 2745 }, { 3721, 2746 }, { 3722, 2747 }, { 3723, 2748 }, { 3724, 2749 }, { 3725, 2750 }, { 3726, 2751 }, - { 3727, 2752 }, { 3728, 2753 }, { 3729, 2754 }, { 3730, 2755 }, { 3927, 2756 }, { 3928, 2757 }, { 3929, 2758 }, - { 3930, 2759 }, { 3931, 2760 }, { 3932, 2761 }, { 3933, 2762 }, { 3934, 2763 }, { 3940, 2769 }, { 3941, 2770 }, - { 3942, 2771 }, { 3943, 2772 }, { 3944, 2773 }, { 3945, 2774 }, { 3946, 2775 }, { 3947, 2776 }, { 3948, 2777 }, - { 3949, 2778 }, { 3950, 2779 }, { 3951, 2780 }, { 3952, 2781 }, { 3953, 2782 }, { 3954, 2783 }, { 3955, 2784 }, - { 3956, 2785 }, { 3957, 2786 }, { 3958, 2787 }, { 3959, 2788 }, { 3960, 2789 }, { 3961, 2790 }, { 3962, 2791 }, - { 3963, 2792 }, { 3964, 2793 }, { 3965, 2794 }, { 3966, 2795 }, { 3967, 2796 }, { 3968, 2797 }, { 3969, 2798 }, - { 3970, 2799 }, { 3971, 2800 }, { 3972, 2801 }, { 3973, 2802 }, { 3974, 2803 }, { 3975, 2804 }, { 3976, 2805 }, - { 3977, 2806 }, { 3978, 2807 }, { 3979, 2808 }, { 3980, 2809 }, { 3981, 2810 }, { 3982, 2811 }, { 3983, 2812 }, - { 3984, 2813 }, { 3985, 2814 }, { 3986, 2815 }, { 3987, 2816 }, { 3988, 2817 }, { 3989, 2818 }, { 3990, 2819 }, - { 3991, 2820 }, { 3992, 2821 }, { 3993, 2822 }, { 3994, 2823 }, { 3995, 2824 }, { 3996, 2825 }, { 3997, 2826 }, - { 3998, 2827 }, { 3999, 2828 }, { 4000, 2829 }, { 4001, 2830 }, { 4002, 2831 }, { 4003, 2832 }, { 4004, 2833 }, - { 4005, 2834 }, { 4006, 2835 }, { 4007, 2836 }, { 4008, 2837 }, { 4009, 2838 }, { 4010, 2839 }, { 4011, 2840 }, - { 4012, 2841 }, { 4013, 2842 }, { 4014, 2843 }, { 4015, 2844 }, { 4016, 2845 }, { 4017, 2846 }, { 4018, 2847 }, - { 4019, 2848 }, { 4020, 2849 }, { 4021, 2850 }, { 4022, 2851 }, { 4023, 2852 }, { 4024, 2853 }, { 4025, 2854 }, - { 4026, 2855 }, { 4027, 2856 }, { 4028, 2857 }, { 4029, 2858 }, { 4030, 2859 }, { 4031, 2860 }, { 4032, 2861 }, - { 4127, 2863 }, { 4128, 2864 }, { 4129, 2865 }, { 4130, 2866 }, { 4131, 2867 }, { 4132, 2868 }, { 4133, 2869 }, - { 4134, 2870 }, { 4135, 2871 }, { 4136, 2872 }, { 4137, 2873 }, { 4138, 2874 }, { 4139, 2875 }, { 4140, 2876 }, - { 4145, 2881 }, { 4146, 2882 }, { 4147, 2883 }, { 4148, 2884 }, { 4149, 2885 }, { 4150, 2886 }, { 4151, 2887 }, - { 4152, 2888 }, { 4153, 2889 }, { 4154, 2890 }, { 4155, 2891 }, { 4156, 2892 }, { 4157, 2893 }, { 4158, 2894 }, - { 4159, 2895 }, { 4160, 2896 }, { 4227, 2897 }, { 4228, 2898 }, { 4229, 2899 }, { 4230, 2900 }, { 4231, 2901 }, - { 4232, 2902 }, { 4233, 2903 }, { 4234, 2904 }, { 4235, 2905 }, { 4236, 2906 }, { 4237, 2907 }, { 4238, 2908 }, - { 4239, 2909 }, { 4240, 2910 }, { 4241, 2911 }, { 4242, 2912 }, { 4243, 2913 }, { 4244, 2914 }, { 4245, 2915 }, - { 4246, 2916 }, { 4247, 2917 }, { 4248, 2918 }, { 4249, 2919 }, { 4250, 2920 }, { 4251, 2921 }, { 4252, 2922 }, - { 4253, 2923 }, { 4254, 2924 }, { 4255, 2925 }, { 4256, 2926 }, { 4257, 2927 }, { 4258, 2928 }, { 4327, 2929 }, - { 4328, 2930 }, { 4329, 2931 }, { 4330, 2932 }, { 4331, 2933 }, { 4332, 2934 }, { 4333, 2935 }, { 4334, 2936 }, - { 4335, 2937 }, { 4336, 2938 }, { 4337, 2939 }, { 4338, 2940 }, { 4339, 2941 }, { 4340, 2942 }, { 4341, 2943 }, - { 4342, 2944 }, { 4343, 2945 }, { 4344, 2946 }, { 4345, 2947 }, { 4346, 2948 }, { 4347, 2949 }, { 4348, 2950 }, - { 4349, 2951 }, { 4350, 2952 }, { 4351, 2953 }, { 4352, 2954 }, { 4353, 2955 }, { 4354, 2956 }, { 4355, 2957 }, - { 4356, 2958 }, { 4357, 2959 }, { 4358, 2960 }, { 4359, 2961 }, { 4360, 2962 }, { 4361, 2963 }, { 4362, 2964 }, - { 4363, 2965 }, { 4364, 2966 }, { 4365, 2967 }, { 4366, 2968 }, { 4367, 2969 }, { 4368, 2970 }, { 4369, 2971 }, - { 4370, 2972 }, { 4371, 2973 }, { 4372, 2974 }, { 4373, 2975 }, { 4374, 2976 }, { 4375, 2977 }, { 4376, 2978 }, - { 4377, 2979 }, { 4378, 2980 }, { 4379, 2981 }, { 4380, 2982 }, { 4381, 2983 }, { 4382, 2984 }, { 4383, 2985 }, - { 4384, 2986 }, { 4385, 2987 }, { 4386, 2988 }, { 4387, 2989 }, { 4388, 2990 }, { 4389, 2991 }, { 4390, 2992 }, - { 4391, 2993 }, { 4392, 2994 }, { 4393, 2995 }, { 4394, 2996 }, { 4395, 2997 }, { 4396, 2998 }, { 4397, 2999 }, - { 4398, 3000 }, { 4399, 3001 }, { 4400, 3002 }, { 4401, 3003 }, { 4402, 3004 }, { 4403, 3005 }, { 4404, 3006 }, - { 4405, 3007 }, { 4406, 3008 }, { 4407, 3009 }, { 4408, 3010 }, { 4409, 3011 }, { 4410, 3012 }, { 4411, 3013 }, - { 4412, 3014 }, { 4413, 3015 }, { 4414, 3016 }, { 4415, 3017 }, { 4416, 3018 }, { 4417, 3019 }, { 4418, 3020 }, - { 4419, 3021 }, { 4420, 3022 }, { 4421, 3023 }, { 4422, 3024 }, { 4423, 3025 }, { 4424, 3026 }, { 4425, 3027 }, - { 4426, 3028 }, { 4427, 3029 }, { 4428, 3030 }, { 4429, 3031 }, { 4430, 3032 }, { 4431, 3033 }, { 4432, 3034 }, - { 4433, 3035 }, { 4434, 3036 }, { 4435, 3037 }, { 4436, 3038 }, { 4437, 3039 }, { 4438, 3040 }, { 4439, 3041 }, - { 4440, 3042 }, { 4441, 3043 }, { 4442, 3044 }, { 4443, 3045 }, { 4444, 3046 }, { 4445, 3047 }, { 4446, 3048 }, - { 4447, 3049 }, { 4448, 3050 }, { 4449, 3051 }, { 4450, 3052 }, { 4527, 3053 }, { 4528, 3054 }, { 4529, 3055 }, - { 4530, 3056 }, { 4531, 3057 }, { 4532, 3058 }, { 4533, 3059 }, { 4534, 3060 }, { 4535, 3061 }, { 4536, 3062 }, - { 4537, 3063 }, { 4538, 3064 }, { 4539, 3065 }, { 4540, 3066 }, { 4541, 3067 }, { 4542, 3068 }, { 4543, 3069 }, - { 4544, 3070 }, { 4545, 3071 }, { 4546, 3072 }, { 4547, 3074 }, { 4548, 3075 }, { 4549, 3076 }, { 4550, 3077 }, - { 4551, 3078 }, { 4552, 3079 }, { 4553, 3080 }, { 4554, 3073 }, { 4627, 3081 }, { 4628, 3082 }, { 4629, 3083 }, - { 4630, 3084 }, { 4631, 3085 }, { 4632, 3086 }, { 4633, 3087 }, { 4634, 3088 }, { 4635, 3089 }, { 4636, 3090 }, - { 4637, 3091 }, { 4638, 3092 }, { 4639, 3093 }, { 4640, 3094 }, { 4641, 3095 }, { 4642, 3096 }, { 4643, 3097 }, - { 4644, 3098 }, { 4645, 3099 }, { 4646, 3100 }, { 4647, 3101 }, { 4648, 3102 }, { 4649, 3103 }, { 4650, 3104 }, - { 4651, 3105 }, { 4652, 3106 }, { 4653, 3107 }, { 4654, 3108 }, { 4655, 3109 }, { 4656, 3110 }, { 4657, 3111 }, - { 4658, 3112 }, { 4659, 3113 }, { 4660, 3114 }, { 4661, 3115 }, { 4662, 3116 }, { 4663, 3117 }, { 4664, 3118 }, - { 4665, 3119 }, { 4666, 3120 }, { 4667, 3121 }, { 4668, 3122 }, { 4669, 3123 }, { 4670, 3124 }, { 4671, 3125 }, - { 4672, 3126 }, { 4673, 3127 }, { 4674, 3128 }, { 4675, 3129 }, { 4676, 3130 }, { 4677, 3131 }, { 4678, 3132 }, - { 4679, 3133 }, { 4680, 3134 }, { 4681, 3135 }, { 4682, 3136 }, { 4683, 3137 }, { 4684, 3138 }, { 4685, 3139 }, - { 4686, 3140 }, { 4687, 3141 }, { 4688, 3142 }, { 4689, 3143 }, { 4690, 3144 }, { 4691, 3145 }, { 4692, 3146 }, - { 4693, 3147 }, { 4694, 3148 }, { 4695, 3149 }, { 4696, 3150 }, { 4697, 3151 }, { 4698, 3152 }, { 4699, 3153 }, - { 4700, 3154 }, { 4701, 3155 }, { 4702, 3156 }, { 4703, 3157 }, { 4704, 3158 }, { 4705, 3159 }, { 4706, 3160 }, - { 4707, 3161 }, { 4708, 3162 }, { 4709, 3163 }, { 4710, 3164 }, { 4711, 3165 }, { 4712, 3166 }, { 4713, 3167 }, - { 4714, 3168 }, { 4715, 3169 }, { 4716, 3170 }, { 4717, 3171 }, { 4718, 3172 }, { 4719, 3173 }, { 4720, 3174 }, - { 4721, 3175 }, { 4722, 3176 }, { 4723, 3177 }, { 4724, 3178 }, { 4725, 3179 }, { 4726, 3180 }, { 4827, 3181 }, - { 4828, 3182 }, { 4829, 3183 }, { 4830, 3184 }, { 4831, 3185 }, { 4832, 3186 }, { 4833, 3187 }, { 4834, 3188 }, - { 4835, 3189 }, { 4836, 3190 }, { 4837, 3191 }, { 4838, 3192 }, { 4839, 3193 }, { 4840, 3194 }, { 4841, 3195 }, - { 4842, 3196 }, { 4843, 3197 }, { 4844, 3198 }, { 4845, 3199 }, { 5027, 3200 }, { 5028, 3201 }, { 5029, 3202 }, - { 5030, 3203 }, { 5031, 3204 }, { 5032, 3205 }, { 5033, 3206 }, { 5034, 3207 }, { 5035, 3208 }, { 5036, 3209 }, - { 5037, 3210 }, { 5038, 3211 }, { 5039, 3212 }, { 5040, 3213 }, { 5041, 3214 }, { 5042, 3215 }, { 5043, 3216 }, - { 5044, 3217 }, { 5045, 3218 }, { 5046, 3219 }, { 5047, 3220 }, { 5048, 3221 }, { 5049, 3222 }, { 5050, 3223 }, - { 5051, 3224 }, { 5052, 3225 }, { 5053, 3226 }, { 5054, 3227 }, { 5055, 3228 }, { 5056, 3229 }, { 5057, 3230 }, - { 5058, 3231 }, { 5059, 3232 }, { 5060, 3233 }, { 5061, 3234 }, { 5062, 3235 }, { 5063, 3236 }, { 5064, 3237 }, - { 5065, 3238 }, { 5066, 3239 }, { 5067, 3240 }, { 5068, 3241 }, { 5069, 3242 }, { 5070, 3243 }, { 5071, 3244 }, - { 5072, 3245 }, { 5073, 3246 }, { 5074, 3247 }, { 5075, 3248 }, { 5076, 3249 }, { 5077, 3250 }, { 5127, 3251 }, - { 5128, 3252 }, { 5129, 3253 }, { 5130, 3254 }, { 5131, 3255 }, { 5132, 3256 }, { 5133, 3257 }, { 5134, 3258 }, - { 5135, 3259 }, { 5136, 3260 }, { 5137, 3261 }, { 5138, 3262 }, { 5139, 3263 }, { 5140, 3264 }, { 5141, 3265 }, - { 5142, 3266 }, { 5143, 3267 }, { 5144, 3268 }, { 5145, 3269 }, { 5146, 3270 }, { 5147, 3271 }, { 5148, 3272 }, - { 5149, 3273 }, { 5150, 3274 }, { 5151, 3275 }, { 5152, 3276 }, { 5153, 3277 }, { 5154, 3278 }, { 5155, 3279 }, - { 5156, 3280 }, { 5227, 3281 }, { 5228, 3282 }, { 5229, 3283 }, { 5230, 3284 }, { 5231, 3285 }, { 5232, 3286 }, - { 5233, 3287 }, { 5234, 3288 }, { 5235, 3289 }, { 5236, 3290 }, { 5237, 3291 }, { 5238, 3292 }, { 5240, 3294 }, - { 5241, 3295 }, { 5242, 3296 }, { 5243, 3297 }, { 5244, 3298 }, { 5245, 3299 }, { 5246, 3300 }, { 5247, 3301 }, - { 5248, 3302 }, { 5249, 3303 }, { 5250, 3304 }, { 5251, 3305 }, { 5252, 3306 }, { 5253, 3307 }, { 5254, 3308 }, - { 5255, 3309 }, { 5256, 3310 }, { 5257, 3311 }, { 5258, 3312 }, { 5259, 3313 }, { 5260, 3314 }, { 5261, 3315 }, - { 5262, 3316 }, { 5263, 3317 }, { 5264, 3318 }, { 5265, 3319 }, { 5266, 3320 }, { 5267, 3321 }, { 5268, 3322 }, - { 5269, 3323 }, { 5270, 3324 }, { 5271, 3325 }, { 5272, 3326 }, { 5273, 3327 }, { 5274, 3328 }, { 5275, 3329 }, - { 5276, 3330 }, { 5277, 3331 }, { 5278, 3332 }, { 5279, 3333 }, { 5280, 3334 }, { 5281, 3335 }, { 5282, 3336 }, - { 5283, 3337 }, { 5284, 3338 }, { 5285, 3339 }, { 5286, 3340 }, { 5288, 3342 }, { 5289, 3343 }, { 5290, 3344 }, - { 5291, 3345 }, { 5292, 3346 }, { 5293, 3347 }, { 5294, 3348 }, { 5296, 3350 }, { 5297, 3351 }, { 5298, 3352 }, - { 5299, 3353 }, { 5300, 3354 }, { 5301, 3355 }, { 5302, 3356 }, { 5303, 3357 }, { 5304, 3358 }, { 5305, 3359 }, - { 5306, 3360 }, { 5307, 3361 }, { 5308, 3362 }, { 5309, 3363 }, { 5310, 3364 }, { 5311, 3365 }, { 5312, 3366 }, - { 5313, 3367 }, { 5314, 3368 }, { 5315, 3369 }, { 5316, 3370 }, { 5317, 3371 }, { 5318, 3372 }, { 5319, 3373 }, - { 5320, 3374 }, { 5321, 3375 }, { 5322, 3376 }, { 5323, 3377 }, { 5324, 3378 }, { 5325, 3379 }, { 5326, 3380 }, - { 5327, 3381 }, { 5328, 3382 }, { 5329, 3383 }, { 5330, 3384 }, { 5331, 3385 }, { 5332, 3386 }, { 5333, 3387 }, - { 5336, 3390 }, { 5337, 3391 }, { 5338, 3392 }, { 5339, 3393 }, { 5340, 3394 }, { 5341, 3395 }, { 5342, 3396 }, - { 5343, 3397 }, { 5344, 3398 }, { 5345, 3399 }, { 5346, 3400 }, { 5347, 3401 }, { 5348, 3402 }, { 5349, 3403 }, - { 5350, 3404 }, { 5351, 3405 }, { 5352, 3406 }, { 5357, 3411 }, { 5358, 3412 }, { 5359, 3413 }, { 5360, 3414 }, - { 5361, 3415 }, { 5362, 3416 }, { 5363, 3417 }, { 5364, 3418 }, { 5365, 3419 }, { 5366, 3420 }, { 5367, 3421 }, - { 5368, 3422 }, { 5369, 3423 }, { 5370, 3424 }, { 5371, 3425 }, { 5372, 3426 }, { 5373, 3427 }, { 5374, 3428 }, - { 5375, 3429 }, { 5376, 3430 }, { 5377, 3431 }, { 5378, 3432 }, { 5379, 3433 }, { 5380, 3434 }, { 5381, 3435 }, - { 5382, 3436 }, { 5383, 3437 }, { 5384, 3438 }, { 5385, 3439 }, { 5386, 3440 }, { 5387, 3441 }, { 5388, 3442 }, - { 5389, 3443 }, { 5390, 3444 }, { 5391, 3445 }, { 5392, 3446 }, { 5393, 3447 }, { 5394, 3448 }, { 5395, 3449 }, - { 5396, 3450 }, { 5397, 3451 }, { 5398, 3452 }, { 5399, 3453 }, { 5400, 3454 }, { 5401, 3455 }, { 5402, 3456 }, - { 5403, 3457 }, { 5404, 3458 }, { 5405, 3459 }, { 5406, 3460 }, { 5407, 3461 }, { 5408, 3462 }, { 5409, 3463 }, - { 5410, 3464 }, { 5411, 3465 }, { 5412, 3466 }, { 5413, 3467 }, { 5414, 3468 }, { 5415, 3469 }, { 5416, 3470 }, - { 5417, 3471 }, { 5418, 3472 }, { 5419, 3473 }, { 5420, 3474 }, { 5421, 3475 }, { 5422, 3476 }, { 5423, 3477 }, - { 5424, 3478 }, { 5425, 3479 }, { 5426, 3480 }, { 5427, 3481 }, { 5428, 3482 }, { 5429, 3483 }, { 5430, 3484 }, - { 5431, 3485 }, { 5432, 3486 }, { 5433, 3487 }, { 5434, 3488 }, { 5435, 3489 }, { 5436, 3490 }, { 5437, 3491 }, - { 5438, 3492 }, { 5439, 3493 }, { 5440, 3494 }, { 5441, 3495 }, { 5442, 3496 }, { 5443, 3497 }, { 5444, 3498 }, - { 5445, 3499 }, { 5446, 3500 }, { 5447, 3501 }, { 5448, 3502 }, { 5449, 3503 }, { 5450, 3504 }, { 5451, 3505 }, - { 5452, 3506 }, { 5453, 3507 }, { 5454, 3508 }, { 5455, 3509 }, { 5456, 3510 }, { 5457, 3511 }, { 5458, 3512 }, - { 5459, 3513 }, { 5460, 3514 }, { 5461, 3515 }, { 5462, 3516 }, { 5463, 3517 }, { 5464, 3518 }, { 5465, 3519 }, - { 5466, 3520 }, { 5467, 3521 }, { 5468, 3522 }, { 5469, 3523 }, { 5470, 3524 }, { 5471, 3525 }, { 5472, 3526 }, - { 5473, 3527 }, { 5474, 3528 }, { 5475, 3529 }, { 5476, 3530 }, { 5477, 3531 }, { 5478, 3532 }, { 5479, 3533 }, - { 5480, 3534 }, { 5481, 3535 }, { 5482, 3536 }, { 5483, 3537 }, { 5484, 3538 }, { 5485, 3539 }, { 5486, 3540 }, - { 5487, 3541 }, { 5488, 3542 }, { 5489, 3543 }, { 5490, 3544 }, { 5491, 3545 }, { 5492, 3546 }, { 5493, 3547 }, - { 5494, 3548 }, { 5495, 3549 }, { 5496, 3550 }, { 5497, 3551 }, { 5498, 3552 }, { 5499, 3553 }, { 5500, 3554 }, - { 5501, 3555 }, { 5502, 3556 }, { 5503, 3557 }, { 5504, 3558 }, { 5505, 3559 }, { 5506, 3560 }, { 5507, 3561 }, - { 5508, 3562 }, { 5509, 3563 }, { 5510, 3564 }, { 5511, 3565 }, { 5512, 3566 }, { 5513, 3567 }, { 5514, 3568 }, - { 5515, 3569 }, { 5516, 3570 }, { 5517, 3571 }, { 5518, 3572 }, { 5519, 3573 }, { 5520, 3574 }, { 5521, 3575 }, - { 5522, 3576 }, { 5523, 3577 }, { 5524, 3578 }, { 5525, 3579 }, { 5526, 3580 }, { 5527, 3581 }, { 5528, 3582 }, - { 5529, 3583 }, { 5530, 3584 }, { 5531, 3585 }, { 5532, 3586 }, { 5533, 3587 }, { 5534, 3588 }, { 5535, 3589 }, - { 5536, 3590 }, { 5537, 3591 }, { 5538, 3592 }, { 5539, 3593 }, { 5540, 3594 }, { 5541, 3595 }, { 5542, 3596 }, - { 5543, 3597 }, { 5544, 3598 }, { 5545, 3599 }, { 5546, 3600 }, { 5547, 3601 }, { 5548, 3602 }, { 5549, 3603 }, - { 5550, 3604 }, { 5551, 3605 }, { 5552, 3606 }, { 5553, 3607 }, { 5554, 3608 }, { 5555, 3609 }, { 5556, 3610 }, - { 5557, 3611 }, { 5558, 3612 }, { 5559, 3613 }, { 5560, 3614 }, { 5561, 3615 }, { 5562, 3616 }, { 5563, 3617 }, - { 5564, 3618 }, { 5565, 3619 }, { 5566, 3620 }, { 5567, 3621 }, { 5568, 3622 }, { 5569, 3623 }, { 5570, 3624 }, + { 2504, 2248 }, { 2508, 2252 }, { 2511, 2255 }, { 2513, 2257 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, + { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, + { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, + { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, + { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, + { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, + { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, + { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, + { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, + { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, + { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, + { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, + { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2878, 2396 }, { 2879, 2397 }, { 2880, 2398 }, + { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, + { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, + { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, + { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, + { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, + { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, + { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, + { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, + { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, { 3104, 2463 }, { 3105, 2464 }, { 3106, 2466 }, { 3107, 2467 }, + { 3108, 2468 }, { 3109, 2469 }, { 3110, 2470 }, { 3111, 2471 }, { 3112, 2472 }, { 3113, 2473 }, { 3114, 2474 }, + { 3115, 2475 }, { 3171, 2476 }, { 3172, 2477 }, { 3173, 2478 }, { 3174, 2479 }, { 3175, 2480 }, { 3176, 2481 }, + { 3177, 2482 }, { 3178, 2483 }, { 3179, 2484 }, { 3180, 2485 }, { 3181, 2486 }, { 3182, 2487 }, { 3183, 2488 }, + { 3184, 2489 }, { 3185, 2490 }, { 3186, 2491 }, { 3187, 2492 }, { 3188, 2493 }, { 3189, 2494 }, { 3190, 2495 }, + { 3191, 2496 }, { 3192, 2497 }, { 3193, 2498 }, { 3194, 2499 }, { 3195, 2500 }, { 3196, 2501 }, { 3197, 2502 }, + { 3198, 2503 }, { 3199, 2504 }, { 3200, 2505 }, { 3201, 2506 }, { 3202, 2507 }, { 3203, 2508 }, { 3204, 2509 }, + { 3205, 2510 }, { 3206, 2511 }, { 3207, 2512 }, { 3208, 2513 }, { 3209, 2514 }, { 3210, 2515 }, { 3211, 2516 }, + { 3212, 2517 }, { 3213, 2518 }, { 3214, 2519 }, { 3215, 2520 }, { 3216, 2521 }, { 3217, 2522 }, { 3218, 2523 }, + { 3219, 2524 }, { 3220, 2525 }, { 3221, 2526 }, { 3222, 2527 }, { 3223, 2528 }, { 3224, 2529 }, { 3271, 2530 }, + { 3272, 2531 }, { 3273, 2532 }, { 3274, 2533 }, { 3275, 2534 }, { 3276, 2535 }, { 3277, 2536 }, { 3278, 2537 }, + { 3279, 2538 }, { 3280, 2539 }, { 3281, 2540 }, { 3282, 2541 }, { 3283, 2542 }, { 3284, 2543 }, { 3285, 2544 }, + { 3286, 2545 }, { 3287, 2546 }, { 3288, 2547 }, { 3289, 2548 }, { 3290, 2549 }, { 3291, 2550 }, { 3292, 2551 }, + { 3293, 2552 }, { 3294, 2553 }, { 3295, 2554 }, { 3296, 2555 }, { 3297, 2556 }, { 3298, 2557 }, { 3299, 2558 }, + { 3300, 2559 }, { 3301, 2560 }, { 3302, 2561 }, { 3303, 2562 }, { 3304, 2563 }, { 3371, 2564 }, { 3372, 2565 }, + { 3373, 2566 }, { 3374, 2567 }, { 3375, 2568 }, { 3376, 2569 }, { 3377, 2570 }, { 3378, 2571 }, { 3379, 2572 }, + { 3380, 2573 }, { 3381, 2574 }, { 3382, 2575 }, { 3383, 2576 }, { 3384, 2577 }, { 3385, 2578 }, { 3471, 2579 }, + { 3472, 2580 }, { 3473, 2581 }, { 3474, 2582 }, { 3475, 2583 }, { 3476, 2584 }, { 3477, 2585 }, { 3478, 2586 }, + { 3479, 2587 }, { 3480, 2588 }, { 3481, 2589 }, { 3482, 2590 }, { 3483, 2591 }, { 3484, 2592 }, { 3485, 2593 }, + { 3486, 2594 }, { 3487, 2595 }, { 3488, 2596 }, { 3489, 2597 }, { 3490, 2598 }, { 3491, 2599 }, { 3492, 2600 }, + { 3493, 2601 }, { 3494, 2602 }, { 3495, 2603 }, { 3496, 2604 }, { 3497, 2605 }, { 3498, 2606 }, { 3499, 2607 }, + { 3500, 2608 }, { 3501, 2609 }, { 3502, 2610 }, { 3503, 2611 }, { 3504, 2612 }, { 3505, 2613 }, { 3506, 2614 }, + { 3507, 2615 }, { 3508, 2616 }, { 3509, 2617 }, { 3510, 2618 }, { 3571, 2619 }, { 3572, 2620 }, { 3573, 2621 }, + { 3574, 2622 }, { 3575, 2623 }, { 3576, 2624 }, { 3577, 2625 }, { 3578, 2626 }, { 3579, 2627 }, { 3580, 2628 }, + { 3581, 2629 }, { 3582, 2630 }, { 3583, 2631 }, { 3584, 2632 }, { 3585, 2633 }, { 3586, 2634 }, { 3587, 2635 }, + { 3588, 2636 }, { 3589, 2637 }, { 3590, 2638 }, { 3591, 2639 }, { 3592, 2640 }, { 3593, 2641 }, { 3594, 2642 }, + { 3595, 2643 }, { 3596, 2644 }, { 3597, 2645 }, { 3598, 2646 }, { 3599, 2647 }, { 3600, 2648 }, { 3601, 2649 }, + { 3602, 2650 }, { 3603, 2651 }, { 3604, 2652 }, { 3605, 2653 }, { 3606, 2654 }, { 3607, 2655 }, { 3608, 2656 }, + { 3609, 2657 }, { 3610, 2658 }, { 3611, 2659 }, { 3612, 2660 }, { 3613, 2661 }, { 3614, 2662 }, { 3615, 2663 }, + { 3616, 2664 }, { 3617, 2665 }, { 3618, 2666 }, { 3619, 2667 }, { 3620, 2668 }, { 3621, 2669 }, { 3622, 2670 }, + { 3623, 2671 }, { 3624, 2672 }, { 3625, 2673 }, { 3626, 2674 }, { 3627, 2675 }, { 3628, 2676 }, { 3629, 2677 }, + { 3630, 2678 }, { 3631, 2679 }, { 3632, 2680 }, { 3633, 2681 }, { 3634, 2682 }, { 3635, 2683 }, { 3636, 2684 }, + { 3637, 2685 }, { 3638, 2686 }, { 3639, 2687 }, { 3640, 2688 }, { 3641, 2689 }, { 3642, 2690 }, { 3643, 2691 }, + { 3644, 2692 }, { 3645, 2693 }, { 3646, 2694 }, { 3671, 2696 }, { 3672, 2697 }, { 3673, 2698 }, { 3674, 2699 }, + { 3675, 2700 }, { 3676, 2701 }, { 3677, 2702 }, { 3678, 2703 }, { 3679, 2704 }, { 3680, 2705 }, { 3681, 2706 }, + { 3682, 2707 }, { 3683, 2708 }, { 3684, 2709 }, { 3685, 2710 }, { 3686, 2711 }, { 3687, 2712 }, { 3688, 2713 }, + { 3689, 2714 }, { 3690, 2715 }, { 3691, 2716 }, { 3692, 2717 }, { 3693, 2718 }, { 3694, 2719 }, { 3695, 2720 }, + { 3696, 2721 }, { 3697, 2722 }, { 3698, 2723 }, { 3699, 2724 }, { 3700, 2725 }, { 3701, 2726 }, { 3702, 2727 }, + { 3703, 2728 }, { 3704, 2729 }, { 3705, 2730 }, { 3706, 2731 }, { 3707, 2732 }, { 3708, 2733 }, { 3709, 2734 }, + { 3710, 2735 }, { 3711, 2736 }, { 3712, 2737 }, { 3713, 2738 }, { 3714, 2739 }, { 3715, 2740 }, { 3716, 2741 }, + { 3717, 2742 }, { 3718, 2743 }, { 3719, 2744 }, { 3720, 2745 }, { 3721, 2746 }, { 3722, 2747 }, { 3723, 2748 }, + { 3724, 2749 }, { 3725, 2750 }, { 3726, 2751 }, { 3727, 2752 }, { 3728, 2753 }, { 3729, 2754 }, { 3730, 2755 }, + { 3927, 2756 }, { 3928, 2757 }, { 3929, 2758 }, { 3930, 2759 }, { 3931, 2760 }, { 3932, 2761 }, { 3933, 2762 }, + { 3934, 2763 }, { 3940, 2769 }, { 3941, 2770 }, { 3942, 2771 }, { 3943, 2772 }, { 3944, 2773 }, { 3945, 2774 }, + { 3946, 2775 }, { 3947, 2776 }, { 3948, 2777 }, { 3949, 2778 }, { 3950, 2779 }, { 3951, 2780 }, { 3952, 2781 }, + { 3953, 2782 }, { 3954, 2783 }, { 3955, 2784 }, { 3956, 2785 }, { 3957, 2786 }, { 3958, 2787 }, { 3959, 2788 }, + { 3960, 2789 }, { 3961, 2790 }, { 3962, 2791 }, { 3963, 2792 }, { 3964, 2793 }, { 3965, 2794 }, { 3966, 2795 }, + { 3967, 2796 }, { 3968, 2797 }, { 3969, 2798 }, { 3970, 2799 }, { 3971, 2800 }, { 3972, 2801 }, { 3973, 2802 }, + { 3974, 2803 }, { 3975, 2804 }, { 3976, 2805 }, { 3977, 2806 }, { 3978, 2807 }, { 3979, 2808 }, { 3980, 2809 }, + { 3981, 2810 }, { 3982, 2811 }, { 3983, 2812 }, { 3984, 2813 }, { 3985, 2814 }, { 3986, 2815 }, { 3987, 2816 }, + { 3988, 2817 }, { 3989, 2818 }, { 3990, 2819 }, { 3991, 2820 }, { 3992, 2821 }, { 3993, 2822 }, { 3994, 2823 }, + { 3995, 2824 }, { 3996, 2825 }, { 3997, 2826 }, { 3998, 2827 }, { 3999, 2828 }, { 4000, 2829 }, { 4001, 2830 }, + { 4002, 2831 }, { 4003, 2832 }, { 4004, 2833 }, { 4005, 2834 }, { 4006, 2835 }, { 4007, 2836 }, { 4008, 2837 }, + { 4009, 2838 }, { 4010, 2839 }, { 4011, 2840 }, { 4012, 2841 }, { 4013, 2842 }, { 4014, 2843 }, { 4015, 2844 }, + { 4016, 2845 }, { 4017, 2846 }, { 4018, 2847 }, { 4019, 2848 }, { 4020, 2849 }, { 4021, 2850 }, { 4022, 2851 }, + { 4023, 2852 }, { 4024, 2853 }, { 4025, 2854 }, { 4026, 2855 }, { 4027, 2856 }, { 4028, 2857 }, { 4029, 2858 }, + { 4030, 2859 }, { 4031, 2860 }, { 4032, 2861 }, { 4127, 2863 }, { 4128, 2864 }, { 4129, 2865 }, { 4130, 2866 }, + { 4131, 2867 }, { 4132, 2868 }, { 4133, 2869 }, { 4134, 2870 }, { 4135, 2871 }, { 4136, 2872 }, { 4137, 2873 }, + { 4138, 2874 }, { 4139, 2875 }, { 4140, 2876 }, { 4145, 2881 }, { 4146, 2882 }, { 4147, 2883 }, { 4148, 2884 }, + { 4149, 2885 }, { 4150, 2886 }, { 4151, 2887 }, { 4152, 2888 }, { 4153, 2889 }, { 4154, 2890 }, { 4155, 2891 }, + { 4156, 2892 }, { 4157, 2893 }, { 4158, 2894 }, { 4159, 2895 }, { 4160, 2896 }, { 4227, 2897 }, { 4228, 2898 }, + { 4229, 2899 }, { 4230, 2900 }, { 4231, 2901 }, { 4232, 2902 }, { 4233, 2903 }, { 4234, 2904 }, { 4235, 2905 }, + { 4236, 2906 }, { 4237, 2907 }, { 4238, 2908 }, { 4239, 2909 }, { 4240, 2910 }, { 4241, 2911 }, { 4242, 2912 }, + { 4243, 2913 }, { 4244, 2914 }, { 4245, 2915 }, { 4246, 2916 }, { 4247, 2917 }, { 4248, 2918 }, { 4249, 2919 }, + { 4250, 2920 }, { 4251, 2921 }, { 4252, 2922 }, { 4253, 2923 }, { 4254, 2924 }, { 4255, 2925 }, { 4256, 2926 }, + { 4257, 2927 }, { 4258, 2928 }, { 4327, 2929 }, { 4328, 2930 }, { 4329, 2931 }, { 4330, 2932 }, { 4331, 2933 }, + { 4332, 2934 }, { 4333, 2935 }, { 4334, 2936 }, { 4335, 2937 }, { 4336, 2938 }, { 4337, 2939 }, { 4338, 2940 }, + { 4339, 2941 }, { 4340, 2942 }, { 4341, 2943 }, { 4342, 2944 }, { 4343, 2945 }, { 4344, 2946 }, { 4345, 2947 }, + { 4346, 2948 }, { 4347, 2949 }, { 4348, 2950 }, { 4349, 2951 }, { 4350, 2952 }, { 4351, 2953 }, { 4352, 2954 }, + { 4353, 2955 }, { 4354, 2956 }, { 4355, 2957 }, { 4356, 2958 }, { 4357, 2959 }, { 4358, 2960 }, { 4359, 2961 }, + { 4360, 2962 }, { 4361, 2963 }, { 4362, 2964 }, { 4363, 2965 }, { 4364, 2966 }, { 4365, 2967 }, { 4366, 2968 }, + { 4367, 2969 }, { 4368, 2970 }, { 4369, 2971 }, { 4370, 2972 }, { 4371, 2973 }, { 4372, 2974 }, { 4373, 2975 }, + { 4374, 2976 }, { 4375, 2977 }, { 4376, 2978 }, { 4377, 2979 }, { 4378, 2980 }, { 4379, 2981 }, { 4380, 2982 }, + { 4381, 2983 }, { 4382, 2984 }, { 4383, 2985 }, { 4384, 2986 }, { 4385, 2987 }, { 4386, 2988 }, { 4387, 2989 }, + { 4388, 2990 }, { 4389, 2991 }, { 4390, 2992 }, { 4391, 2993 }, { 4392, 2994 }, { 4393, 2995 }, { 4394, 2996 }, + { 4395, 2997 }, { 4396, 2998 }, { 4397, 2999 }, { 4398, 3000 }, { 4399, 3001 }, { 4400, 3002 }, { 4401, 3003 }, + { 4402, 3004 }, { 4403, 3005 }, { 4404, 3006 }, { 4405, 3007 }, { 4406, 3008 }, { 4407, 3009 }, { 4408, 3010 }, + { 4409, 3011 }, { 4410, 3012 }, { 4411, 3013 }, { 4412, 3014 }, { 4413, 3015 }, { 4414, 3016 }, { 4415, 3017 }, + { 4416, 3018 }, { 4417, 3019 }, { 4418, 3020 }, { 4419, 3021 }, { 4420, 3022 }, { 4421, 3023 }, { 4422, 3024 }, + { 4423, 3025 }, { 4424, 3026 }, { 4425, 3027 }, { 4426, 3028 }, { 4427, 3029 }, { 4428, 3030 }, { 4429, 3031 }, + { 4430, 3032 }, { 4431, 3033 }, { 4432, 3034 }, { 4433, 3035 }, { 4434, 3036 }, { 4435, 3037 }, { 4436, 3038 }, + { 4437, 3039 }, { 4438, 3040 }, { 4439, 3041 }, { 4440, 3042 }, { 4441, 3043 }, { 4442, 3044 }, { 4443, 3045 }, + { 4444, 3046 }, { 4445, 3047 }, { 4446, 3048 }, { 4447, 3049 }, { 4448, 3050 }, { 4449, 3051 }, { 4450, 3052 }, + { 4527, 3053 }, { 4528, 3054 }, { 4529, 3055 }, { 4530, 3056 }, { 4531, 3057 }, { 4532, 3058 }, { 4533, 3059 }, + { 4534, 3060 }, { 4535, 3061 }, { 4536, 3062 }, { 4537, 3063 }, { 4538, 3064 }, { 4539, 3065 }, { 4540, 3066 }, + { 4541, 3067 }, { 4542, 3068 }, { 4543, 3069 }, { 4544, 3070 }, { 4545, 3071 }, { 4546, 3072 }, { 4547, 3074 }, + { 4548, 3075 }, { 4549, 3076 }, { 4550, 3077 }, { 4551, 3078 }, { 4552, 3079 }, { 4553, 3080 }, { 4554, 3073 }, + { 4627, 3081 }, { 4628, 3082 }, { 4629, 3083 }, { 4630, 3084 }, { 4631, 3085 }, { 4632, 3086 }, { 4633, 3087 }, + { 4634, 3088 }, { 4635, 3089 }, { 4636, 3090 }, { 4637, 3091 }, { 4638, 3092 }, { 4639, 3093 }, { 4640, 3094 }, + { 4641, 3095 }, { 4642, 3096 }, { 4643, 3097 }, { 4644, 3098 }, { 4645, 3099 }, { 4646, 3100 }, { 4647, 3101 }, + { 4648, 3102 }, { 4649, 3103 }, { 4650, 3104 }, { 4651, 3105 }, { 4652, 3106 }, { 4653, 3107 }, { 4654, 3108 }, + { 4655, 3109 }, { 4656, 3110 }, { 4657, 3111 }, { 4658, 3112 }, { 4659, 3113 }, { 4660, 3114 }, { 4661, 3115 }, + { 4662, 3116 }, { 4663, 3117 }, { 4664, 3118 }, { 4665, 3119 }, { 4666, 3120 }, { 4667, 3121 }, { 4668, 3122 }, + { 4669, 3123 }, { 4670, 3124 }, { 4671, 3125 }, { 4672, 3126 }, { 4673, 3127 }, { 4674, 3128 }, { 4675, 3129 }, + { 4676, 3130 }, { 4677, 3131 }, { 4678, 3132 }, { 4679, 3133 }, { 4680, 3134 }, { 4681, 3135 }, { 4682, 3136 }, + { 4683, 3137 }, { 4684, 3138 }, { 4685, 3139 }, { 4686, 3140 }, { 4687, 3141 }, { 4688, 3142 }, { 4689, 3143 }, + { 4690, 3144 }, { 4691, 3145 }, { 4692, 3146 }, { 4693, 3147 }, { 4694, 3148 }, { 4695, 3149 }, { 4696, 3150 }, + { 4697, 3151 }, { 4698, 3152 }, { 4699, 3153 }, { 4700, 3154 }, { 4701, 3155 }, { 4702, 3156 }, { 4703, 3157 }, + { 4704, 3158 }, { 4705, 3159 }, { 4706, 3160 }, { 4707, 3161 }, { 4708, 3162 }, { 4709, 3163 }, { 4710, 3164 }, + { 4711, 3165 }, { 4712, 3166 }, { 4713, 3167 }, { 4714, 3168 }, { 4715, 3169 }, { 4716, 3170 }, { 4717, 3171 }, + { 4718, 3172 }, { 4719, 3173 }, { 4720, 3174 }, { 4721, 3175 }, { 4722, 3176 }, { 4723, 3177 }, { 4724, 3178 }, + { 4725, 3179 }, { 4726, 3180 }, { 4827, 3181 }, { 4828, 3182 }, { 4829, 3183 }, { 4830, 3184 }, { 4831, 3185 }, + { 4832, 3186 }, { 4833, 3187 }, { 4834, 3188 }, { 4835, 3189 }, { 4836, 3190 }, { 4837, 3191 }, { 4838, 3192 }, + { 4839, 3193 }, { 4840, 3194 }, { 4841, 3195 }, { 4842, 3196 }, { 4843, 3197 }, { 4844, 3198 }, { 4845, 3199 }, + { 5027, 3200 }, { 5028, 3201 }, { 5029, 3202 }, { 5030, 3203 }, { 5031, 3204 }, { 5032, 3205 }, { 5033, 3206 }, + { 5034, 3207 }, { 5035, 3208 }, { 5036, 3209 }, { 5037, 3210 }, { 5038, 3211 }, { 5039, 3212 }, { 5040, 3213 }, + { 5041, 3214 }, { 5042, 3215 }, { 5043, 3216 }, { 5044, 3217 }, { 5045, 3218 }, { 5046, 3219 }, { 5047, 3220 }, + { 5048, 3221 }, { 5049, 3222 }, { 5050, 3223 }, { 5051, 3224 }, { 5052, 3225 }, { 5053, 3226 }, { 5054, 3227 }, + { 5055, 3228 }, { 5056, 3229 }, { 5057, 3230 }, { 5058, 3231 }, { 5059, 3232 }, { 5060, 3233 }, { 5061, 3234 }, + { 5062, 3235 }, { 5063, 3236 }, { 5064, 3237 }, { 5065, 3238 }, { 5066, 3239 }, { 5067, 3240 }, { 5068, 3241 }, + { 5069, 3242 }, { 5070, 3243 }, { 5071, 3244 }, { 5072, 3245 }, { 5073, 3246 }, { 5074, 3247 }, { 5075, 3248 }, + { 5076, 3249 }, { 5077, 3250 }, { 5127, 3251 }, { 5128, 3252 }, { 5129, 3253 }, { 5130, 3254 }, { 5131, 3255 }, + { 5132, 3256 }, { 5133, 3257 }, { 5134, 3258 }, { 5135, 3259 }, { 5136, 3260 }, { 5137, 3261 }, { 5138, 3262 }, + { 5139, 3263 }, { 5140, 3264 }, { 5141, 3265 }, { 5142, 3266 }, { 5143, 3267 }, { 5144, 3268 }, { 5145, 3269 }, + { 5146, 3270 }, { 5147, 3271 }, { 5148, 3272 }, { 5149, 3273 }, { 5150, 3274 }, { 5151, 3275 }, { 5152, 3276 }, + { 5153, 3277 }, { 5154, 3278 }, { 5155, 3279 }, { 5156, 3280 }, { 5227, 3281 }, { 5228, 3282 }, { 5229, 3283 }, + { 5230, 3284 }, { 5231, 3285 }, { 5232, 3286 }, { 5233, 3287 }, { 5234, 3288 }, { 5235, 3289 }, { 5236, 3290 }, + { 5237, 3291 }, { 5238, 3292 }, { 5240, 3294 }, { 5241, 3295 }, { 5242, 3296 }, { 5243, 3297 }, { 5244, 3298 }, + { 5245, 3299 }, { 5246, 3300 }, { 5247, 3301 }, { 5248, 3302 }, { 5249, 3303 }, { 5250, 3304 }, { 5251, 3305 }, + { 5252, 3306 }, { 5253, 3307 }, { 5254, 3308 }, { 5255, 3309 }, { 5256, 3310 }, { 5257, 3311 }, { 5258, 3312 }, + { 5259, 3313 }, { 5260, 3314 }, { 5261, 3315 }, { 5262, 3316 }, { 5263, 3317 }, { 5264, 3318 }, { 5265, 3319 }, + { 5266, 3320 }, { 5267, 3321 }, { 5268, 3322 }, { 5269, 3323 }, { 5270, 3324 }, { 5271, 3325 }, { 5272, 3326 }, + { 5273, 3327 }, { 5274, 3328 }, { 5275, 3329 }, { 5276, 3330 }, { 5277, 3331 }, { 5278, 3332 }, { 5279, 3333 }, + { 5280, 3334 }, { 5281, 3335 }, { 5282, 3336 }, { 5283, 3337 }, { 5284, 3338 }, { 5285, 3339 }, { 5286, 3340 }, + { 5288, 3342 }, { 5289, 3343 }, { 5290, 3344 }, { 5291, 3345 }, { 5292, 3346 }, { 5293, 3347 }, { 5294, 3348 }, + { 5296, 3350 }, { 5297, 3351 }, { 5298, 3352 }, { 5299, 3353 }, { 5300, 3354 }, { 5301, 3355 }, { 5302, 3356 }, + { 5303, 3357 }, { 5304, 3358 }, { 5305, 3359 }, { 5306, 3360 }, { 5307, 3361 }, { 5308, 3362 }, { 5309, 3363 }, + { 5310, 3364 }, { 5311, 3365 }, { 5312, 3366 }, { 5313, 3367 }, { 5314, 3368 }, { 5315, 3369 }, { 5316, 3370 }, + { 5317, 3371 }, { 5318, 3372 }, { 5319, 3373 }, { 5320, 3374 }, { 5321, 3375 }, { 5322, 3376 }, { 5323, 3377 }, + { 5324, 3378 }, { 5325, 3379 }, { 5326, 3380 }, { 5327, 3381 }, { 5328, 3382 }, { 5329, 3383 }, { 5330, 3384 }, + { 5331, 3385 }, { 5332, 3386 }, { 5333, 3387 }, { 5336, 3390 }, { 5337, 3391 }, { 5338, 3392 }, { 5339, 3393 }, + { 5340, 3394 }, { 5341, 3395 }, { 5342, 3396 }, { 5343, 3397 }, { 5344, 3398 }, { 5345, 3399 }, { 5346, 3400 }, + { 5347, 3401 }, { 5348, 3402 }, { 5349, 3403 }, { 5350, 3404 }, { 5351, 3405 }, { 5352, 3406 }, { 5357, 3411 }, + { 5358, 3412 }, { 5359, 3413 }, { 5360, 3414 }, { 5361, 3415 }, { 5362, 3416 }, { 5363, 3417 }, { 5364, 3418 }, + { 5365, 3419 }, { 5366, 3420 }, { 5367, 3421 }, { 5368, 3422 }, { 5369, 3423 }, { 5370, 3424 }, { 5371, 3425 }, + { 5372, 3426 }, { 5373, 3427 }, { 5374, 3428 }, { 5375, 3429 }, { 5376, 3430 }, { 5377, 3431 }, { 5378, 3432 }, + { 5379, 3433 }, { 5380, 3434 }, { 5381, 3435 }, { 5382, 3436 }, { 5383, 3437 }, { 5384, 3438 }, { 5385, 3439 }, + { 5386, 3440 }, { 5387, 3441 }, { 5388, 3442 }, { 5389, 3443 }, { 5390, 3444 }, { 5391, 3445 }, { 5392, 3446 }, + { 5393, 3447 }, { 5394, 3448 }, { 5395, 3449 }, { 5396, 3450 }, { 5397, 3451 }, { 5398, 3452 }, { 5399, 3453 }, + { 5400, 3454 }, { 5401, 3455 }, { 5402, 3456 }, { 5403, 3457 }, { 5404, 3458 }, { 5405, 3459 }, { 5406, 3460 }, + { 5407, 3461 }, { 5408, 3462 }, { 5409, 3463 }, { 5410, 3464 }, { 5411, 3465 }, { 5412, 3466 }, { 5413, 3467 }, + { 5414, 3468 }, { 5415, 3469 }, { 5416, 3470 }, { 5417, 3471 }, { 5418, 3472 }, { 5419, 3473 }, { 5420, 3474 }, + { 5421, 3475 }, { 5422, 3476 }, { 5423, 3477 }, { 5424, 3478 }, { 5425, 3479 }, { 5426, 3480 }, { 5427, 3481 }, + { 5428, 3482 }, { 5429, 3483 }, { 5430, 3484 }, { 5431, 3485 }, { 5432, 3486 }, { 5433, 3487 }, { 5434, 3488 }, + { 5435, 3489 }, { 5436, 3490 }, { 5437, 3491 }, { 5438, 3492 }, { 5439, 3493 }, { 5440, 3494 }, { 5441, 3495 }, + { 5442, 3496 }, { 5443, 3497 }, { 5444, 3498 }, { 5445, 3499 }, { 5446, 3500 }, { 5447, 3501 }, { 5448, 3502 }, + { 5449, 3503 }, { 5450, 3504 }, { 5451, 3505 }, { 5452, 3506 }, { 5453, 3507 }, { 5454, 3508 }, { 5455, 3509 }, + { 5456, 3510 }, { 5457, 3511 }, { 5458, 3512 }, { 5459, 3513 }, { 5460, 3514 }, { 5461, 3515 }, { 5462, 3516 }, + { 5463, 3517 }, { 5464, 3518 }, { 5465, 3519 }, { 5466, 3520 }, { 5467, 3521 }, { 5468, 3522 }, { 5469, 3523 }, + { 5470, 3524 }, { 5471, 3525 }, { 5472, 3526 }, { 5473, 3527 }, { 5474, 3528 }, { 5475, 3529 }, { 5476, 3530 }, + { 5477, 3531 }, { 5478, 3532 }, { 5479, 3533 }, { 5480, 3534 }, { 5481, 3535 }, { 5482, 3536 }, { 5483, 3537 }, + { 5484, 3538 }, { 5485, 3539 }, { 5486, 3540 }, { 5487, 3541 }, { 5488, 3542 }, { 5489, 3543 }, { 5490, 3544 }, + { 5491, 3545 }, { 5492, 3546 }, { 5493, 3547 }, { 5494, 3548 }, { 5495, 3549 }, { 5496, 3550 }, { 5497, 3551 }, + { 5498, 3552 }, { 5499, 3553 }, { 5500, 3554 }, { 5501, 3555 }, { 5502, 3556 }, { 5503, 3557 }, { 5504, 3558 }, + { 5505, 3559 }, { 5506, 3560 }, { 5507, 3561 }, { 5508, 3562 }, { 5509, 3563 }, { 5510, 3564 }, { 5511, 3565 }, + { 5512, 3566 }, { 5513, 3567 }, { 5514, 3568 }, { 5515, 3569 }, { 5516, 3570 }, { 5517, 3571 }, { 5518, 3572 }, + { 5519, 3573 }, { 5520, 3574 }, { 5521, 3575 }, { 5522, 3576 }, { 5523, 3577 }, { 5524, 3578 }, { 5525, 3579 }, + { 5526, 3580 }, { 5527, 3581 }, { 5528, 3582 }, { 5529, 3583 }, { 5530, 3584 }, { 5531, 3585 }, { 5532, 3586 }, + { 5533, 3587 }, { 5534, 3588 }, { 5535, 3589 }, { 5536, 3590 }, { 5537, 3591 }, { 5538, 3592 }, { 5539, 3593 }, + { 5540, 3594 }, { 5541, 3595 }, { 5542, 3596 }, { 5543, 3597 }, { 5544, 3598 }, { 5545, 3599 }, { 5546, 3600 }, + { 5547, 3601 }, { 5548, 3602 }, { 5549, 3603 }, { 5550, 3604 }, { 5551, 3605 }, { 5552, 3606 }, { 5553, 3607 }, + { 5554, 3608 }, { 5555, 3609 }, { 5556, 3610 }, { 5557, 3611 }, { 5558, 3612 }, { 5559, 3613 }, { 5560, 3614 }, + { 5561, 3615 }, { 5562, 3616 }, { 5563, 3617 }, { 5564, 3618 }, { 5565, 3619 }, { 5566, 3620 }, { 5567, 3621 }, + { 5568, 3622 }, { 5569, 3623 }, { 5570, 3624 }, }; #endif // ASSET_VERSION_REMAP_H diff --git a/src/port/GameVersion/BaseGameVersion.cpp b/src/port/GameVersion/BaseGameVersion.cpp index 43fe141cf..a38b55c0c 100644 --- a/src/port/GameVersion/BaseGameVersion.cpp +++ b/src/port/GameVersion/BaseGameVersion.cpp @@ -12,6 +12,22 @@ namespace Lighthouse { namespace { +bool IsKnownVersion(uint32_t crc) { + switch (crc) { + case BK_VER_US_10: + case BK_VER_US_11: + case BK_VER_PAL: + case BK_VER_JP: + return true; + default: + return false; + } +} + +uint32_t ByteSwap32(uint32_t v) { + return (v >> 24) | ((v >> 8) & 0x0000FF00u) | ((v << 8) & 0x00FF0000u) | (v << 24); +} + bool ReadStampedCrc(const std::string& archivePath, uint32_t& outCrc) { int err = 0; zip_t* z = zip_open(archivePath.c_str(), ZIP_RDONLY, &err); @@ -23,12 +39,9 @@ bool ReadStampedCrc(const std::string& archivePath, uint32_t& outCrc) { if (zip_int64_t idx = zip_name_locate(z, "version", 0); idx >= 0) { if (zip_file_t* f = zip_fopen_index(z, idx, 0)) { uint8_t buf[5] = {}; - if (zip_fread(f, buf, sizeof(buf)) == static_cast(sizeof(buf))) { - const bool big = buf[0] != 0; - outCrc = big ? (static_cast(buf[1]) << 24 | static_cast(buf[2]) << 16 | - static_cast(buf[3]) << 8 | static_cast(buf[4])) - : (static_cast(buf[4]) << 24 | static_cast(buf[3]) << 16 | - static_cast(buf[2]) << 8 | static_cast(buf[1])); + if (zip_fread(f, buf, sizeof(buf)) == sizeof(buf)) { + outCrc = (static_cast(buf[1]) << 24) | (static_cast(buf[2]) << 16) | + (static_cast(buf[3]) << 8) | static_cast(buf[4]); ok = true; } zip_fclose(f); @@ -39,23 +52,16 @@ bool ReadStampedCrc(const std::string& archivePath, uint32_t& outCrc) { return ok; } -BKVersion ClassifyCrc(uint32_t crc) { - switch (crc) { - case BK_VER_US_11: - return BK_VER_US_11; - case BK_VER_PAL: - return BK_VER_PAL; - case BK_VER_JP: - return BK_VER_JP; - case BK_VER_US_10: - default: - // Vanilla v1.0, a v1.0-based romhack, or an unknown dump. - return BK_VER_US_10; +} // namespace + +std::string BaseArchivePath() { + std::string basePath = Ship::Context::LocateFileAcrossAppDirs("bk.o2r", "bk"); + if (basePath.empty() || !std::filesystem::exists(basePath)) { + return std::string(); // not extracted yet } + return basePath; } -} // namespace - BKVersion GetBaseVersion() { static BKVersion sVersion = BK_VER_US_10; static bool sResolved = false; @@ -63,19 +69,33 @@ BKVersion GetBaseVersion() { return sVersion; } - std::string basePath = Ship::Context::LocateFileAcrossAppDirs("bk.o2r", "bk"); - if (basePath.empty() || !std::filesystem::exists(basePath)) { + const std::string basePath = BaseArchivePath(); + if (basePath.empty()) { return sVersion; // not extracted yet — retry on the next call } uint32_t crc = 0; - if (ReadStampedCrc(basePath, crc)) { - sVersion = ClassifyCrc(crc); + BKVersion version = BK_VER_US_10; + if (ReadStampedCrc(basePath, crc) && ClassifyArchiveVersion(crc, version)) { + sVersion = version; sResolved = true; SPDLOG_INFO("[BaseGameVersion] base bk.o2r CRC 0x{:08X} -> BKVersion 0x{:08X}", crc, static_cast(sVersion)); } - return sVersion; + return sVersion; // unstamped or unrecognised: stay on the v1.0 default and retry +} + +bool ClassifyArchiveVersion(uint32_t rawVersion, BKVersion& out) { + if (IsKnownVersion(rawVersion)) { + out = static_cast(rawVersion); + return true; + } + const uint32_t swapped = ByteSwap32(rawVersion); + if (IsKnownVersion(swapped)) { + out = static_cast(swapped); + return true; + } + return false; } bool BaseGameSupportsRomhacks() { diff --git a/src/port/GameVersion/BaseGameVersion.h b/src/port/GameVersion/BaseGameVersion.h index 4d463b806..a6c9ae2f0 100644 --- a/src/port/GameVersion/BaseGameVersion.h +++ b/src/port/GameVersion/BaseGameVersion.h @@ -9,6 +9,12 @@ namespace Lighthouse { // The ROM CRC that Torch inserts into the o2r version file BKVersion GetBaseVersion(); +// Classify a version stamp taken from an archive +bool ClassifyArchiveVersion(uint32_t rawVersion, BKVersion& out); + +// Filesystem path of the base bk.o2r, or empty if it hasn't been extracted yet +std::string BaseArchivePath(); + // Romhacks are generally only supported by US 1.0 bool BaseGameSupportsRomhacks(); diff --git a/src/port/Interpolation/AdaptiveFps.cpp b/src/port/Interpolation/AdaptiveFps.cpp deleted file mode 100644 index c2ad62710..000000000 --- a/src/port/Interpolation/AdaptiveFps.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "AdaptiveFps.h" - -#include -#include - -namespace { - -using Clock = std::chrono::steady_clock; - -// Tuning knobs - -// How much of each update's time we'll spend drawing once things are steady. -// Raise toward 1.0 if FPS dips in scenes that look fine; lower if it stutters. -constexpr double kSafetySteady = 0.95; - -// Same, but used the moment a scene gets busier (more cautious). Lower if busy -// scenes still hitch; raise if FPS drops more than needed when they start. -constexpr double kSafetyRising = 0.75; - -// How much busier a scene must get to count as "getting busy". Lower reacts -// sooner but trips on normal noise; raise to ignore small bumps. -constexpr double kRisingThreshold = 1.20; - -// How long to stay cautious after a scene gets busy. Raise if FPS wobbles in -// steady scenes; lower if it feels slow to speed back up. -constexpr int kRisingHoldWindows = 3; - -// How often measurements are averaged. Shorter reacts quicker but is jumpier; -// longer is steadier but slower to react. -constexpr auto kSampleWindow = std::chrono::milliseconds(200); - -// How much each new measurement counts vs. past ones when averaging. -// 1.0 = only the latest; 0.0 = never changes. -constexpr double kEmaAlpha = 0.5; - -// How much busier one frame must be than usual to count as a spike. Lower -// reacts harder to one-off heavy frames; raise to ignore them. -constexpr double kSpikeFactor = 1.25; - -// How strongly a spike pulls the estimate up. 1.0 = snap to it instantly; -// 0.0 = ignore spikes. 0.5 lets a sustained busy scene ramp up over a few frames. -constexpr double kSpikeBlend = 0.5; - -// How quickly the busy estimate eases back down each averaging period. 0 = -// never; 1 = drop to the latest right away. Higher recovers FPS faster. -constexpr double kPeakDecay = 0.40; - -// How fast the reserved game-update time follows the latest tick: jump up -// quickly when a scene gets busy, ease back down slowly when it calms. -constexpr double kLogicRiseAlpha = 0.5; -constexpr double kLogicFallAlpha = 0.1; - -// Default game update rate (times per second) if none is given. -constexpr uint32_t kDefaultTickHz = 30; - -struct State { - uint32_t tickHz = kDefaultTickHz; - double tickBudgetUs = 1'000'000.0 / kDefaultTickHz; - double emaPerSubFrameUs = 0.0; // Average time to draw one frame. - double peakPerSubFrameUs = 0.0; // Busiest recent frame; the cap is based on this. - double envLogicUs = 0.0; // Reserved game-update time per tick. - long long winRunNs = 0; // Totals for the current measurement period. - int winSubFrames = 0; - double winMaxUs = 0.0; - Clock::time_point winStart = Clock::now(); - double safety = kSafetySteady; - int risingHoldRemaining = 0; -}; - -State& state() { - static State s; - return s; -} - -} // namespace - -extern "C" { - -void AdaptiveFps_Configure(uint32_t tickHz) { - if (tickHz == 0) { - tickHz = kDefaultTickHz; - } - auto& s = state(); - s.tickHz = tickHz; - s.tickBudgetUs = 1'000'000.0 / tickHz; - s.emaPerSubFrameUs = 0.0; - s.peakPerSubFrameUs = 0.0; - s.envLogicUs = 0.0; - s.winRunNs = 0; - s.winSubFrames = 0; - s.winMaxUs = 0.0; - s.winStart = Clock::now(); - s.safety = kSafetySteady; - s.risingHoldRemaining = 0; -} - -uint32_t AdaptiveFps_Cap(uint32_t userTarget) { - auto& s = state(); - // Base the cap on the busiest recent frame, not the average: every frame we - // promise gets drawn, so the time has to fit the worst one. - double costUs = std::max(s.peakPerSubFrameUs, s.emaPerSubFrameUs); - if (costUs <= 0.0) { - return userTarget; - } - // Set aside the time the game spent updating, then share what's left among - // interpolated frames so a busy scene can't overshoot the tick's budget. - double renderBudgetUs = s.tickBudgetUs - s.envLogicUs; - if (renderBudgetUs <= 0.0) { - return s.tickHz; - } - double maxSubPerTick = (renderBudgetUs * s.safety) / costUs; - if (maxSubPerTick < 1.0) { - return s.tickHz; - } - uint32_t maxFps = (uint32_t)(maxSubPerTick * s.tickHz); - if (maxFps < s.tickHz) { - maxFps = s.tickHz; - } - return std::min(userTarget, maxFps); -} - -void AdaptiveFps_SampleTick(long long logicNs) { - auto& s = state(); - double us = (double)logicNs / 1000.0; - if (us < 0.0) { - return; - } - if (s.envLogicUs == 0.0) { - s.envLogicUs = us; - } else { - // Rise fast when the scene gets busier, fall slow when it calms. - double alpha = us > s.envLogicUs ? kLogicRiseAlpha : kLogicFallAlpha; - s.envLogicUs = alpha * us + (1.0 - alpha) * s.envLogicUs; - } -} - -void AdaptiveFps_Sample(long long runNs) { - auto& s = state(); - double sampleUs = (double)runNs / 1000.0; - - s.winRunNs += runNs; - s.winSubFrames++; - if (sampleUs > s.winMaxUs) { - s.winMaxUs = sampleUs; - } - - // If one frame is suddenly much busier than usual, bump the estimate up - // right away and stay cautious, so the next cap already reflects it. - if (s.peakPerSubFrameUs == 0.0) { - s.peakPerSubFrameUs = sampleUs; - s.safety = kSafetyRising; - s.risingHoldRemaining = kRisingHoldWindows; - } else if (sampleUs > s.peakPerSubFrameUs * kSpikeFactor) { - s.peakPerSubFrameUs = kSpikeBlend * sampleUs + (1.0 - kSpikeBlend) * s.peakPerSubFrameUs; - s.safety = kSafetyRising; - s.risingHoldRemaining = kRisingHoldWindows; - } - - auto now = Clock::now(); - if (now - s.winStart < kSampleWindow) { - return; - } - - // End of a measurement period: refresh the average, decide whether the - // scene is still getting busier, and ease the busy estimate back down. - double mean = (double)s.winRunNs / s.winSubFrames / 1000.0; - s.emaPerSubFrameUs = s.emaPerSubFrameUs == 0.0 ? mean : kEmaAlpha * mean + (1.0 - kEmaAlpha) * s.emaPerSubFrameUs; - - bool rising = s.peakPerSubFrameUs > 0.0 && s.winMaxUs > s.peakPerSubFrameUs * kRisingThreshold; - if (rising) { - s.risingHoldRemaining = kRisingHoldWindows; - } else if (s.risingHoldRemaining > 0) { - s.risingHoldRemaining--; - } - s.safety = s.risingHoldRemaining > 0 ? kSafetyRising : kSafetySteady; - - s.peakPerSubFrameUs = std::max(s.winMaxUs, s.peakPerSubFrameUs * (1.0 - kPeakDecay) + s.winMaxUs * kPeakDecay); - - s.winRunNs = 0; - s.winSubFrames = 0; - s.winMaxUs = 0.0; - s.winStart = now; -} - -} // extern "C" diff --git a/src/port/Interpolation/AdaptiveFps.h b/src/port/Interpolation/AdaptiveFps.h deleted file mode 100644 index c2422b545..000000000 --- a/src/port/Interpolation/AdaptiveFps.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include - -// Adaptive interpolation FPS cap. -// -// Drawing each extra interpolated frame is expensive, so asking for too many -// in a busy scene can starve the game and make it stutter. This times how long -// drawing takes and lowers the FPS just enough to keep the game smooth, then -// raises it again once the scene clears. -// -// Call order (from the gfx pipeline): -// AdaptiveFps_Configure(tickHz) // once at startup -// AdaptiveFps_SampleTick(logicNs) // each tick, before Cap -// AdaptiveFps_Cap(userTarget) // pick the allowed FPS -// AdaptiveFps_Sample(runNs) // after each frame is drawn -// -// Defaults assume the game runs at 30 fps native; pass a different rate to -// Configure() if not. On a 60 Hz display the result is either 60 or 30 with -// nothing in between (no whole number of frames fits), so it switches directly. - -#ifdef __cplusplus -extern "C" { -#endif - -// Set how many times per second the game updates. Also clears past -// measurements so a freshly loaded game starts fresh. Safe to call repeatedly. -void AdaptiveFps_Configure(uint32_t tickHz); - -// Returns the highest FPS the current scene can sustain, never above what the -// user asked for nor below the game's update rate. Returns the user's value -// until it has measured at least once. -uint32_t AdaptiveFps_Cap(uint32_t userTarget); - -// Report how long it took to draw one frame (nanoseconds), so the module can -// gauge how heavy the scene is. -void AdaptiveFps_Sample(long long runNs); - -// Report how long the game spent updating this tick before drawing started. -// Adaptive FPS reserves that time so a busy scene can't make it schedule too -// many interpolated frames. Call once per tick, before Cap(). -void AdaptiveFps_SampleTick(long long logicNs); - -#ifdef __cplusplus -} -#endif diff --git a/src/port/Interpolation/FrameInterpolation.cpp b/src/port/Interpolation/FrameInterpolation.cpp index c24118306..a8d4fd90f 100644 --- a/src/port/Interpolation/FrameInterpolation.cpp +++ b/src/port/Interpolation/FrameInterpolation.cpp @@ -1,5 +1,7 @@ #include "FrameInterpolation.h" +#include +#include #include #include #include @@ -7,86 +9,37 @@ #include #include - -// Double-buffered op recorder. Matrix primitives in core1/math/matrix_stack.c -// append into gCurrent between StartRecord/StopRecord; Interpolate(t) pairs -// ops across two consecutive ticks (gPrevious vs gCurrent) by scope-path and -// lerps the inputs. Camera projection rotations and sprite inputs go through -// angle-space lerp (not matrix-lerp) to avoid the paper-fold artifact on fast -// spins. See docs/INTERPOLATION.md for the full design. +#include namespace { -enum class Op : uint8_t { - OpenChild, - CloseChild, - Marker, - - MatrixIdent, - MatrixTranslate, - MatrixRotYaw, - MatrixRotPitch, - MatrixRotRoll, - MatrixScale, - MatrixSet, - MatrixMult, - MatrixToMtx, - - CameraProjectionRotation, - SpriteDraw, -}; - -// Heavy ops (Set/Mult/ToMtx/Camera/Sprite) stash their payload in per-tree -// side vectors and reference it via side_index. -struct OpNode { - Op op; - union { - struct { - float x, y, z; - } vec3; - struct { - float degrees; - } rotate; - struct { - const void* key; - uintptr_t id; - } open_child; - struct { - const char* file; - int line; - } marker; - uint32_t side_index; - }; - - OpNode() : op(Op::Marker), side_index(0) { - } -}; - -struct MatrixSetData { - float m[4][4]; -}; - -struct MatrixMultData { - float l[4][4]; - float r[4][4]; -}; +constexpr uint64_t kFnvSeed = 0xcbf29ce484222325ULL; +constexpr uint64_t kSigKindToMtx = 0x1ULL; +constexpr uint64_t kSigKindSprite = 0x2ULL; +constexpr uint64_t kSigKindAnimVtx = 0x3ULL; +constexpr uint64_t kSigKindProjRot = 0x4ULL; +constexpr float kAnimVtxSnapRatio = 0.5f; +constexpr float kSpriteSnapDistSq = 300.0f * 300.0f; +constexpr int kRingSlots = 4; +constexpr uint32_t kAmbiguousSig = UINT32_MAX; struct ToMtxData { void* dst; float src[4][4]; - // Cross-tick pairing key, built at record time from the live FNV scope - // hash; same scope path on both ticks → same sig → O(1) pair lookup. uint64_t pathSig; - // Sprites flag this so the lerp loop leaves their dst alone — cube - // culling reorders sprites between ticks so index pairing mismatches. bool noInterpolate; + bool camRelFixup; + bool ambiguousSig; +}; + +struct AnimVtxData { + void* dst; + uint32_t count; + uint64_t pathSig; + bool ambiguousSig; + std::vector pos; }; -// Sprites record raw inputs (angles for rotations, linear for pos/scale) -// rather than the final matrix, so replay can lerp in natural spaces and -// rebuild a matrix that stays consistent with the angle-lerped projection. -// Which fields matter depends on kind: billboards use camYaw/camPitch, -// FULL uses rotation[], only BILLBOARD_ROLL cares about spriteRoll. struct SpriteDrawData { void* dst; float camRelPos[3]; @@ -98,11 +51,9 @@ struct SpriteDrawData { uint64_t pathSig; uint8_t kind; bool mirrored; + bool ambiguousSig; }; -// We record the three Euler angles behind BK's projection rotation rather -// than the matrices, so replay can shortest-path angle-lerp and rebuild via -// guRotateF — element-wise lerp on these matrices folds during fast spins. struct CameraProjRotData { void* rollMtx; void* pitchMtx; @@ -110,113 +61,160 @@ struct CameraProjRotData { float rollDeg; float pitchDeg; float yawDeg; + uint64_t pathSig; + bool ambiguousSig; }; struct ScopeFrame { uint64_t pathHash; uint32_t toMtxIdx; uint32_t spriteIdx; + uint32_t animVtxIdx; + uint32_t projRotIdx; + const char* key; + uintptr_t id; }; -constexpr uint64_t kFnvSeed = 0xcbf29ce484222325ULL; -// Disambiguators so a ToMtx and a Sprite at the same in-scope index don't -// collide on a single signature. -constexpr uint64_t kSigKindToMtx = 0x1ULL; -constexpr uint64_t kSigKindSprite = 0x2ULL; - -inline uint64_t fnvMix(uint64_t h, uint64_t v) { - h ^= v; - h *= 0x100000001b3ULL; - return h; -} - -// Sig maps are populated live during recording. After StopRecord swaps -// trees, gPrevious already has its maps and BuildInterpolationCache can -// pair entries with O(1) lookups instead of re-walking the prev tree. struct FrameTree { - std::vector ops; - std::vector sets; - std::vector mults; std::vector toMtxs; std::vector projRots; std::vector sprites; + std::vector animVtxs; std::unordered_map sigToToMtx; std::unordered_map sigToSprite; + std::unordered_map sigToAnimVtx; + std::unordered_map sigToProjRot; std::vector scopeStack; float cameraPos[3] = { 0.0f, 0.0f, 0.0f }; bool hasCameraPos = false; bool valid = false; + uint32_t sigCollisions = 0; + std::atomic generation{ 0 }; void reset() { - ops.clear(); - sets.clear(); - mults.clear(); + generation.fetch_add(1, std::memory_order_release); toMtxs.clear(); projRots.clear(); sprites.clear(); + animVtxs.clear(); sigToToMtx.clear(); sigToSprite.clear(); + sigToAnimVtx.clear(); + sigToProjRot.clear(); scopeStack.clear(); cameraPos[0] = cameraPos[1] = cameraPos[2] = 0.0f; hasCameraPos = false; valid = false; + sigCollisions = 0; } }; -FrameTree gTreeA; -FrameTree gTreeB; -FrameTree* gCurrent = &gTreeA; -FrameTree* gPrevious = &gTreeB; - -bool gRecording = false; -bool gShouldInterpolate = true; -int gNoInterpolateDepth = 0; - -// Monotonic ids for heap pointers that get reused by the allocator. Without -// these, a freed object's address gets reused by the next allocation and -// the new one inherits the dead one's matrix pairing. -std::unordered_map gIdMap; -uint64_t gNextId = 1; - -// Per-tick cache built lazily on the first Interpolate(t) call and reused -// for every sub-frame within the tick. Stores only (curr, prev) pairs whose -// lerped output differs from c.src — no-prev and bit-identical entries are -// skipped because the interpreter's fallback path decodes the DL bytes that -// c.src was already encoded into, producing the same matrix without a map -// lookup. Shrinking the map this way speeds up every interpreter find() -// across the whole DL on top of cheaper inserts. struct PairedToMtx { uint32_t currIdx; uint32_t prevIdx; - // Hemisphere check is stable across t for a (prev, curr) pair, so we - // do it once at cache build instead of 6 fmuls + cmps per sub-frame. bool snap; }; + struct PairedSprite { uint32_t currIdx; uint32_t prevIdx; + bool snap; +}; + +struct PairedAnimVtx { + uint32_t currIdx; + uint32_t prevIdx; + bool snap; +}; + +struct PairedProjRot { + uint32_t currIdx; + uint32_t prevIdx; }; + struct InterpolationCache { + bool built = false; bool valid = false; std::vector pairedToMtxs; std::vector pairedSprites; + std::vector pairedAnimVtxs; + std::vector pairedProjRots; + std::vector camRelFixups; + float cameraDelta[3] = { 0.0f, 0.0f, 0.0f }; + bool hasCameraDelta = false; bool prevHasCameraPos = false; float prevCameraPos[3] = { 0.0f, 0.0f, 0.0f }; void reset() { + built = false; valid = false; pairedToMtxs.clear(); pairedSprites.clear(); + pairedAnimVtxs.clear(); + pairedProjRots.clear(); + camRelFixups.clear(); + hasCameraDelta = false; prevHasCameraPos = false; } }; + +// Ring of trees +FrameTree gRing[kRingSlots]; +std::atomic gSlotClaims[kRingSlots] = {}; +int gRecordSlot = 0; +int gLastRecordedSlot = -1; +FrameTree* gRecord = &gRing[0]; +FrameTree* gRenderPrev = nullptr; +FrameTree* gRenderCurr = nullptr; +bool gRenderShould = false; + +bool gRecording = false; +bool gShouldInterpolate = true; +int gNoInterpolateDepth = 0; +int gCameraRelativeDepth = 0; + +std::unordered_map gIdMap; +uint64_t gNextId = 1; + InterpolationCache gCache; -OpNode& append(Op op) { - gCurrent->ops.emplace_back(); - OpNode& n = gCurrent->ops.back(); - n.op = op; - return n; +// First scope identity to collide this tick, reported once by StopRecord so a +// busy frame cannot flood the log. Cleared per tick in StartRecord; nullptr +// means nothing has collided yet. +const char* gCollidedScopeKey = nullptr; +uintptr_t gCollidedScopeId = 0; +const char* gCollidedParentKey = nullptr; +uintptr_t gCollidedParentId = 0; + +inline uint64_t fnvMix(uint64_t h, uint64_t v) { + h ^= v; + h *= 0x100000001b3ULL; + return h; +} + +template +void recordSigCollision(Map& sigMap, Vec& entries, uint64_t sig, uint32_t idx, uint32_t& collisionCount, + const std::vector& stack) { + const ScopeFrame& scope = stack.back(); + auto [it, inserted] = sigMap.emplace(sig, idx); + if (inserted) { + return; + } + if (it->second < entries.size()) { + entries[it->second].ambiguousSig = true; + } + entries[idx].ambiguousSig = true; + it->second = kAmbiguousSig; + collisionCount++; + if (gCollidedScopeKey == nullptr) { + gCollidedScopeKey = scope.key; + gCollidedScopeId = scope.id; + if (stack.size() >= 2) { + const ScopeFrame& parent = stack[stack.size() - 2]; + gCollidedParentKey = parent.key; + gCollidedParentId = parent.id; + } + } } } // namespace @@ -224,166 +222,156 @@ OpNode& append(Op op) { extern "C" { void FrameInterpolation_StartRecord(void) { - gCurrent->reset(); - // Reserve once; subsequent ticks reuse the existing capacity. - gCurrent->ops.reserve(4096); - gCurrent->sets.reserve(128); - gCurrent->mults.reserve(256); - gCurrent->toMtxs.reserve(512); - gCurrent->projRots.reserve(4); - gCurrent->sprites.reserve(256); - gCurrent->sigToToMtx.reserve(512); - gCurrent->sigToSprite.reserve(64); - gCurrent->scopeStack.push_back({ kFnvSeed, 0, 0 }); + for (int i = 0; i < kRingSlots; i++) { + gRecordSlot = (gRecordSlot + 1) % kRingSlots; + if (gSlotClaims[gRecordSlot].load(std::memory_order_acquire) == 0 && gRecordSlot != gLastRecordedSlot) { + break; + } + } + if (gSlotClaims[gRecordSlot].load(std::memory_order_acquire) != 0) { + // Should be impossible, but if it ever prints, a claim leaked. + SPDLOG_WARN("interp record forced into claimed slot {} claims=[{},{},{},{}]", gRecordSlot, + gSlotClaims[0].load(), gSlotClaims[1].load(), gSlotClaims[2].load(), gSlotClaims[3].load()); + } + gRecord = &gRing[gRecordSlot]; + gCollidedScopeKey = nullptr; + gCollidedScopeId = 0; + gCollidedParentKey = nullptr; + gCollidedParentId = 0; + gRecord->reset(); + gRecord->toMtxs.reserve(512); + gRecord->projRots.reserve(16); + gRecord->sprites.reserve(256); + gRecord->sigToToMtx.reserve(512); + gRecord->sigToSprite.reserve(64); + gRecord->sigToProjRot.reserve(16); + gRecord->scopeStack.push_back({ kFnvSeed, 0, 0, 0, 0, "root", 0 }); gShouldInterpolate = true; gNoInterpolateDepth = 0; + gCameraRelativeDepth = 0; gRecording = true; - // The cache built during the prior render pass references trees that - // are about to be reused for this tick. - gCache.valid = false; } +// Idempotent: a threaded submitter has to close the session early, before the +// tree goes to another thread, so the tick's own call then finds it closed. void FrameInterpolation_StopRecord(void) { - gRecording = false; - gCurrent->valid = gShouldInterpolate; - // What we just recorded becomes `previous` for the next tick. - std::swap(gCurrent, gPrevious); -} - -void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate) { - gShouldInterpolate = shouldInterpolate; -} - -void FrameInterpolation_RecordOpenChild(const void* key, uintptr_t id) { - if (!gRecording) { - return; - } - OpNode& n = append(Op::OpenChild); - n.open_child.key = key; - n.open_child.id = id; - uint64_t h = gCurrent->scopeStack.back().pathHash; - h = fnvMix(h, reinterpret_cast(key)); - h = fnvMix(h, static_cast(id)); - gCurrent->scopeStack.push_back({ h, 0, 0 }); -} - -void FrameInterpolation_RecordCloseChild(void) { if (!gRecording) { return; } - append(Op::CloseChild); - if (gCurrent->scopeStack.size() > 1) { - gCurrent->scopeStack.pop_back(); + gRecording = false; + gRecord->valid = gShouldInterpolate; + gLastRecordedSlot = gRecordSlot; + + // One line per affected tick, not per collision: a scope whose id repeats + // usually repeats for every instance behind it. + if (gRecord->sigCollisions != 0) { + static uint32_t sReported = 0; + if (sReported < 20) { + sReported++; + SPDLOG_WARN("interp scope id collided {}x this tick under \"{}\" id={:#x} > \"{}\" id={:#x} " + "({} matrices, {} sprites)", + gRecord->sigCollisions, gCollidedParentKey != nullptr ? gCollidedParentKey : "?", + gCollidedParentId, gCollidedScopeKey != nullptr ? gCollidedScopeKey : "?", gCollidedScopeId, + gRecord->toMtxs.size(), gRecord->sprites.size()); + } } } -uintptr_t FrameInterpolation_Hash3(uint64_t a, uint64_t b, uint64_t c) { - // Three distinct odd primes keep the three inputs separable even when - // they share most of their bytes. - uint64_t h = a * 0x9E3779B97F4A7C15ULL; - h ^= b * 0x100000001b3ULL; - h ^= c * 0xbf58476d1ce4e5b9ULL; - return static_cast(h); -} - -void FrameInterpolation_RecordOpenChildHash3(const char* key, uint64_t a, uint64_t b, uint64_t c) { - FrameInterpolation_RecordOpenChild(key, FrameInterpolation_Hash3(a, b, c)); -} - -void FrameInterpolation_RecordMarker(const char* file, int line) { +// The pair for the tick being recorded right now, grabbed when a display list +// is handed off so it renders against the trees it was built from. +void FrameInterpolation_GetRecordingPair(int* prevSlot, int* currSlot, bool* shouldInterpolate) { if (!gRecording) { + *prevSlot = -1; + *currSlot = -1; + *shouldInterpolate = false; return; } - OpNode& n = append(Op::Marker); - n.marker.file = file; - n.marker.line = line; + *prevSlot = gLastRecordedSlot; + *currSlot = gRecordSlot; + *shouldInterpolate = gShouldInterpolate; } -void FrameInterpolation_RecordMatrixIdent(void) { - if (!gRecording) { - return; +// Claim and release bracket a pair's render lifetime: claimed on the tick side +// at submission, released once the render (and its workers) are done reading. +void FrameInterpolation_ClaimPair(int prevSlot, int currSlot) { + if (prevSlot >= 0 && prevSlot < kRingSlots) { + gSlotClaims[prevSlot].fetch_add(1, std::memory_order_release); + } + if (currSlot >= 0 && currSlot < kRingSlots) { + gSlotClaims[currSlot].fetch_add(1, std::memory_order_release); } - append(Op::MatrixIdent); } -void FrameInterpolation_RecordMatrixTranslate(float x, float y, float z) { - if (!gRecording) { - return; +void FrameInterpolation_ReleasePair(int prevSlot, int currSlot) { + if (prevSlot >= 0 && prevSlot < kRingSlots) { + gSlotClaims[prevSlot].fetch_sub(1, std::memory_order_release); + } + if (currSlot >= 0 && currSlot < kRingSlots) { + gSlotClaims[currSlot].fetch_sub(1, std::memory_order_release); } - OpNode& n = append(Op::MatrixTranslate); - n.vec3.x = x; - n.vec3.y = y; - n.vec3.z = z; } -void FrameInterpolation_RecordMatrixRotYaw(float degrees) { - if (!gRecording) { - return; - } - append(Op::MatrixRotYaw).rotate.degrees = degrees; +// Pins the trees this pass blends and drops the previous pass's pairing cache. +void FrameInterpolation_BeginRenderPass(int prevSlot, int currSlot, bool shouldInterpolate) { + gRenderPrev = (prevSlot >= 0 && prevSlot < kRingSlots) ? &gRing[prevSlot] : nullptr; + gRenderCurr = (currSlot >= 0 && currSlot < kRingSlots) ? &gRing[currSlot] : nullptr; + gRenderShould = shouldInterpolate && gRenderCurr != nullptr && gRenderPrev != nullptr; + gCache.built = false; + gCache.valid = false; } -void FrameInterpolation_RecordMatrixRotPitch(float degrees) { - if (!gRecording) { - return; - } - append(Op::MatrixRotPitch).rotate.degrees = degrees; +void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate) { + gShouldInterpolate = shouldInterpolate; } -void FrameInterpolation_RecordMatrixRotRoll(float degrees) { +void FrameInterpolation_RecordOpenChild(const void* key, uintptr_t id) { if (!gRecording) { return; } - append(Op::MatrixRotRoll).rotate.degrees = degrees; + uint64_t h = gRecord->scopeStack.back().pathHash; + h = fnvMix(h, reinterpret_cast(key)); + h = fnvMix(h, static_cast(id)); + gRecord->scopeStack.push_back({ h, 0, 0, 0, 0, static_cast(key), id }); } -void FrameInterpolation_RecordMatrixScale(float x, float y, float z) { +void FrameInterpolation_RecordCloseChild(void) { if (!gRecording) { return; } - OpNode& n = append(Op::MatrixScale); - n.vec3.x = x; - n.vec3.y = y; - n.vec3.z = z; + if (gRecord->scopeStack.size() > 1) { + gRecord->scopeStack.pop_back(); + } } -void FrameInterpolation_RecordMatrixSet(const float src[4][4]) { - if (!gRecording) { - return; - } - gCurrent->sets.emplace_back(); - std::memcpy(gCurrent->sets.back().m, src, sizeof(float) * 16); - append(Op::MatrixSet).side_index = static_cast(gCurrent->sets.size() - 1); +uintptr_t FrameInterpolation_Hash3(uint64_t a, uint64_t b, uint64_t c) { + uint64_t h = a * 0x9E3779B97F4A7C15ULL; + h ^= b * 0x100000001b3ULL; + h ^= c * 0xbf58476d1ce4e5b9ULL; + return static_cast(h); } -void FrameInterpolation_RecordMatrixMult(const float l[4][4], const float r[4][4]) { - if (!gRecording) { - return; - } - gCurrent->mults.emplace_back(); - MatrixMultData& d = gCurrent->mults.back(); - std::memcpy(d.l, l, sizeof(float) * 16); - std::memcpy(d.r, r, sizeof(float) * 16); - append(Op::MatrixMult).side_index = static_cast(gCurrent->mults.size() - 1); +void FrameInterpolation_RecordOpenChildHash3(const char* key, uint64_t a, uint64_t b, uint64_t c) { + FrameInterpolation_RecordOpenChild(key, FrameInterpolation_Hash3(a, b, c)); } void FrameInterpolation_RecordMatrixToMtx(void* dst, const float src[4][4]) { if (!gRecording) { return; } - ScopeFrame& scope = gCurrent->scopeStack.back(); + ScopeFrame& scope = gRecord->scopeStack.back(); uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindToMtx), scope.toMtxIdx); scope.toMtxIdx++; - uint32_t idx = static_cast(gCurrent->toMtxs.size()); - gCurrent->toMtxs.emplace_back(); - ToMtxData& d = gCurrent->toMtxs.back(); + uint32_t idx = static_cast(gRecord->toMtxs.size()); + gRecord->toMtxs.emplace_back(); + ToMtxData& d = gRecord->toMtxs.back(); d.dst = dst; std::memcpy(d.src, src, sizeof(float) * 16); d.pathSig = sig; - d.noInterpolate = (gNoInterpolateDepth > 0); - gCurrent->sigToToMtx.emplace(sig, idx); - append(Op::MatrixToMtx).side_index = idx; + d.noInterpolate = (gNoInterpolateDepth > 0 || gCameraRelativeDepth > 0); + d.camRelFixup = (gCameraRelativeDepth > 0); + d.ambiguousSig = false; + recordSigCollision(gRecord->sigToToMtx, gRecord->toMtxs, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); } void FrameInterpolation_RecordCameraProjectionRotation(void* rollMtx, float rollDeg, void* pitchMtx, float pitchDeg, @@ -391,25 +379,33 @@ void FrameInterpolation_RecordCameraProjectionRotation(void* rollMtx, float roll if (!gRecording) { return; } - gCurrent->projRots.emplace_back(); - CameraProjRotData& d = gCurrent->projRots.back(); + + ScopeFrame& scope = gRecord->scopeStack.back(); + uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindProjRot), scope.projRotIdx); + scope.projRotIdx++; + + uint32_t idx = static_cast(gRecord->projRots.size()); + gRecord->projRots.emplace_back(); + CameraProjRotData& d = gRecord->projRots.back(); d.rollMtx = rollMtx; d.pitchMtx = pitchMtx; d.yawMtx = yawMtx; d.rollDeg = rollDeg; d.pitchDeg = pitchDeg; d.yawDeg = yawDeg; - append(Op::CameraProjectionRotation).side_index = static_cast(gCurrent->projRots.size() - 1); + d.pathSig = sig; + d.ambiguousSig = false; + recordSigCollision(gRecord->sigToProjRot, gRecord->projRots, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); } void FrameInterpolation_RecordCameraPosition(const float pos[3]) { if (!gRecording || pos == nullptr) { return; } - gCurrent->cameraPos[0] = pos[0]; - gCurrent->cameraPos[1] = pos[1]; - gCurrent->cameraPos[2] = pos[2]; - gCurrent->hasCameraPos = true; + gRecord->cameraPos[0] = pos[0]; + gRecord->cameraPos[1] = pos[1]; + gRecord->cameraPos[2] = pos[2]; + gRecord->hasCameraPos = true; } void FrameInterpolation_NoInterpolatePush(void) { @@ -422,19 +418,29 @@ void FrameInterpolation_NoInterpolatePop(void) { } } +void FrameInterpolation_CameraRelativePush(void) { + gCameraRelativeDepth++; +} + +void FrameInterpolation_CameraRelativePop(void) { + if (gCameraRelativeDepth > 0) { + gCameraRelativeDepth--; + } +} + void FrameInterpolation_RecordSpriteDraw(int kind, void* dst, const float camRelPos[3], const float scale[3], float camYaw, float camPitch, float spriteRoll, const float rotation[3], int mirrored) { if (!gRecording) { return; } - ScopeFrame& scope = gCurrent->scopeStack.back(); + ScopeFrame& scope = gRecord->scopeStack.back(); uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindSprite), scope.spriteIdx); scope.spriteIdx++; - uint32_t idx = static_cast(gCurrent->sprites.size()); - gCurrent->sprites.emplace_back(); - SpriteDrawData& d = gCurrent->sprites.back(); + uint32_t idx = static_cast(gRecord->sprites.size()); + gRecord->sprites.emplace_back(); + SpriteDrawData& d = gRecord->sprites.back(); d.dst = dst; std::memcpy(d.camRelPos, camRelPos, sizeof(float) * 3); std::memcpy(d.scale, scale, sizeof(float) * 3); @@ -449,15 +455,41 @@ void FrameInterpolation_RecordSpriteDraw(int kind, void* dst, const float camRel d.pathSig = sig; d.kind = static_cast(kind); d.mirrored = (mirrored != 0); - gCurrent->sigToSprite.emplace(sig, idx); - append(Op::SpriteDraw).side_index = idx; + d.ambiguousSig = false; + recordSigCollision(gRecord->sigToSprite, gRecord->sprites, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); +} + +void FrameInterpolation_RecordAnimVertices(void* dst, const void* vertices, int32_t count) { + if (!gRecording || dst == nullptr || vertices == nullptr || count <= 0) { + return; + } + ScopeFrame& scope = gRecord->scopeStack.back(); + uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindAnimVtx), scope.animVtxIdx); + scope.animVtxIdx++; + + uint32_t idx = static_cast(gRecord->animVtxs.size()); + gRecord->animVtxs.emplace_back(); + AnimVtxData& d = gRecord->animVtxs.back(); + d.dst = dst; + d.count = static_cast(count); + d.pathSig = sig; + d.ambiguousSig = false; + d.pos.resize(static_cast(count) * 3); + + // Only ob[] moves; everything else in the Vtx (uv, colour/normal) is what + // the tick's own copy already put in dst. + const Vtx* src = static_cast(vertices); + for (int32_t i = 0; i < count; i++) { + d.pos[i * 3 + 0] = src[i].v.ob[0]; + d.pos[i * 3 + 1] = src[i].v.ob[1]; + d.pos[i * 3 + 2] = src[i].v.ob[2]; + } + recordSigCollision(gRecord->sigToAnimVtx, gRecord->animVtxs, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); } void FrameInterpolation_DontInterpolateCamera(void) { - // Prev's matrices belong to a scene the camera just left; dropping the - // tree makes the next Interpolate() bail and replay uses curr as-is. - if (gPrevious != nullptr) { - gPrevious->valid = false; + if (gLastRecordedSlot >= 0) { + gRing[gLastRecordedSlot].valid = false; } } @@ -478,7 +510,6 @@ uintptr_t FrameInterpolation_GetId(const void* ptr) { if (it != gIdMap.end()) { return static_cast(it->second); } - // Fallback for callers that don't Register; ABA-prone. return reinterpret_cast(ptr); } @@ -493,15 +524,14 @@ void FrameInterpolation_UnregisterId(const void* ptr) { namespace { -// Snap to curr when prev/curr point apart on X or Y (>90° rotation): -// element-wise lerp on those folds the character inside-out. +// Blending across a >90 degree turn drags the model through itself for a frame; +// snap to the new orientation instead. inline bool shouldSnap(const float pa[4][4], const float ca[4][4]) { float dotX = pa[0][0] * ca[0][0] + pa[0][1] * ca[0][1] + pa[0][2] * ca[0][2]; float dotY = pa[1][0] * ca[1][0] + pa[1][1] * ca[1][1] + pa[1][2] * ca[1][2]; return dotX < 0.0f || dotY < 0.0f; } -// Shortest-path angle lerp in degrees. inline float lerpAngleDegSP(float a, float b, float tt) { float d = b - a; d = std::fmod(d + 540.0f, 360.0f) - 180.0f; @@ -510,42 +540,82 @@ inline float lerpAngleDegSP(float a, float b, float tt) { void BuildInterpolationCache() { gCache.reset(); - if (!gPrevious->valid) { + gCache.built = true; + if (gRenderPrev == nullptr || gRenderCurr == nullptr || !gRenderPrev->valid) { return; } + const uint32_t prevGen = gRenderPrev->generation.load(std::memory_order_acquire); + const uint32_t currGen = gRenderCurr->generation.load(std::memory_order_acquire); - // Snapshot prev's camera pos so Interpolate's cut detector reads only - // gCache for tick-stable state. - gCache.prevHasCameraPos = gPrevious->hasCameraPos; + gCache.prevHasCameraPos = gRenderPrev->hasCameraPos; if (gCache.prevHasCameraPos) { - gCache.prevCameraPos[0] = gPrevious->cameraPos[0]; - gCache.prevCameraPos[1] = gPrevious->cameraPos[1]; - gCache.prevCameraPos[2] = gPrevious->cameraPos[2]; + gCache.prevCameraPos[0] = gRenderPrev->cameraPos[0]; + gCache.prevCameraPos[1] = gRenderPrev->cameraPos[1]; + gCache.prevCameraPos[2] = gRenderPrev->cameraPos[2]; + } + + // Same two positions the cut heuristic below compares, so a fixup can never + // shift further than the cut threshold before Interpolate() bails outright. + gCache.hasCameraDelta = false; + if (gRenderPrev->hasCameraPos && gRenderCurr->hasCameraPos) { + for (int k = 0; k < 3; k++) { + gCache.cameraDelta[k] = gRenderCurr->cameraPos[k] - gRenderPrev->cameraPos[k]; + gCache.hasCameraDelta |= (gCache.cameraDelta[k] != 0.0f); + } } - const std::vector& currToMtxs = gCurrent->toMtxs; - const std::vector& prevToMtxs = gPrevious->toMtxs; - const std::vector& currSprites = gCurrent->sprites; - const std::vector& prevSprites = gPrevious->sprites; - const std::unordered_map& prevSigMap = gPrevious->sigToToMtx; - const std::unordered_map& prevSpriteMap = gPrevious->sigToSprite; + const std::vector& currToMtxs = gRenderCurr->toMtxs; + const std::vector& prevToMtxs = gRenderPrev->toMtxs; + const std::vector& currSprites = gRenderCurr->sprites; + const std::vector& prevSprites = gRenderPrev->sprites; + const std::unordered_map& prevSigMap = gRenderPrev->sigToToMtx; + const std::unordered_map& prevSpriteMap = gRenderPrev->sigToSprite; gCache.pairedToMtxs.reserve(currToMtxs.size()); gCache.pairedSprites.reserve(currSprites.size()); - // Only pair ToMtxs whose replacement actually differs from the curr - // matrix. The interpreter's fallback path decodes the DL bytes at - // c.dst, which the game wrote from the same float matrix that's now - // c.src — so unpaired AND bit-identical entries decode to the same - // result without a map lookup. Skipping them shrinks the replacement - // map and speeds up every interpreter find() across the whole DL. + // Camera/viewport projection rotations, matched by path signature. Anything + // without a partner this tick keeps the matrix the game already wrote, which + // is this tick's own end state. + const std::vector& currProjRots = gRenderCurr->projRots; + const std::vector& prevProjRots = gRenderPrev->projRots; + gCache.pairedProjRots.reserve(currProjRots.size()); + for (uint32_t i = 0; i < currProjRots.size(); i++) { + const CameraProjRotData& c = currProjRots[i]; + if (c.ambiguousSig) { + continue; + } + auto it = gRenderPrev->sigToProjRot.find(c.pathSig); + if (it == gRenderPrev->sigToProjRot.end() || it->second >= prevProjRots.size()) { + continue; + } + if (prevProjRots[it->second].ambiguousSig) { + continue; + } + gCache.pairedProjRots.push_back({ i, it->second }); + } + + // Whatever stays out of the cache falls back to the interpreter decoding + // the Mtx bytes the game itself wrote, which already hold the correct + // end-of-tick matrix. Entries with no previous partner, or whose + // matrix didn't change, can simply be dropped here. for (uint32_t i = 0; i < currToMtxs.size(); i++) { const ToMtxData& c = currToMtxs[i]; - if (c.dst == nullptr || c.noInterpolate) { + if (c.dst == nullptr) { + continue; + } + // Camera-relative fixups skip pairing entirely. + if (c.camRelFixup) { + if (gCache.hasCameraDelta) { + gCache.camRelFixups.push_back(i); + } + continue; + } + if (c.noInterpolate || c.ambiguousSig) { continue; } auto it = prevSigMap.find(c.pathSig); - if (it == prevSigMap.end()) { + if (it == prevSigMap.end() || it->second >= prevToMtxs.size()) { continue; } const ToMtxData& p = prevToMtxs[it->second]; @@ -555,25 +625,93 @@ void BuildInterpolationCache() { gCache.pairedToMtxs.push_back({ i, it->second, shouldSnap(p.src, c.src) }); } - // Sprites always pair (or get a sentinel prev-idx) because the matrix - // must be rebuilt every sub-frame anyway — billboard rotations follow - // the lerped projection. + // Sprites whose inputs didn't move at all are dropped for the same + // reason; the rest get their matrix rebuilt every sub-frame so billboards + // keep facing the blended camera. for (uint32_t i = 0; i < currSprites.size(); i++) { const SpriteDrawData& c = currSprites[i]; + if (c.ambiguousSig) { + continue; + } auto it = prevSpriteMap.find(c.pathSig); - if (it == prevSpriteMap.end() || prevSprites[it->second].kind != c.kind) { - gCache.pairedSprites.push_back({ i, UINT32_MAX }); - } else { - gCache.pairedSprites.push_back({ i, it->second }); + if (it == prevSpriteMap.end() || it->second >= prevSprites.size() || prevSprites[it->second].kind != c.kind) { + gCache.pairedSprites.push_back({ i, UINT32_MAX, false }); + continue; + } + const SpriteDrawData& p = prevSprites[it->second]; + if (std::memcmp(p.camRelPos, c.camRelPos, sizeof(c.camRelPos)) == 0 && + std::memcmp(p.scale, c.scale, sizeof(c.scale)) == 0 && p.camYaw == c.camYaw && p.camPitch == c.camPitch && + p.spriteRoll == c.spriteRoll && std::memcmp(p.rotation, c.rotation, sizeof(c.rotation)) == 0 && + p.mirrored == c.mirrored) { + continue; + } + bool snap = false; + if (gRenderPrev->hasCameraPos && gRenderCurr->hasCameraPos) { + float d[3]; + for (int k = 0; k < 3; k++) { + d[k] = (c.camRelPos[k] + gRenderCurr->cameraPos[k]) - (p.camRelPos[k] + gRenderPrev->cameraPos[k]); + } + snap = (d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) > kSpriteSnapDistSq; + } + gCache.pairedSprites.push_back({ i, it->second, snap }); + } + + // Same pairing as the sprite path. A vertex blend can't go degenerate the way + // a matrix lerp does, but blending across an animation cut still drags the + // model through itself, so measure the jump against the model's own size. + const std::vector& currAnimVtxs = gRenderCurr->animVtxs; + const std::vector& prevAnimVtxs = gRenderPrev->animVtxs; + const std::unordered_map& prevAnimVtxMap = gRenderPrev->sigToAnimVtx; + gCache.pairedAnimVtxs.reserve(currAnimVtxs.size()); + for (uint32_t i = 0; i < currAnimVtxs.size(); i++) { + const AnimVtxData& c = currAnimVtxs[i]; + if (c.dst == nullptr || c.ambiguousSig) { + continue; + } + auto it = prevAnimVtxMap.find(c.pathSig); + if (it == prevAnimVtxMap.end() || it->second >= prevAnimVtxs.size()) { + continue; + } + const AnimVtxData& p = prevAnimVtxs[it->second]; + // A different vertex count means the sig landed on a different model. + if (p.count != c.count || p.pos.size() != c.pos.size()) { + continue; + } + if (p.pos == c.pos) { + continue; // pose held still; dst already has it } + int32_t maxExtent = 0; + int32_t maxDelta = 0; + for (size_t k = 0; k < c.pos.size(); k++) { + int32_t a = std::abs(static_cast(c.pos[k])); + int32_t d = std::abs(static_cast(c.pos[k]) - static_cast(p.pos[k])); + if (a > maxExtent) { + maxExtent = a; + } + if (d > maxDelta) { + maxDelta = d; + } + } + bool snap = maxExtent > 0 && static_cast(maxDelta) > kAnimVtxSnapRatio * static_cast(maxExtent); + gCache.pairedAnimVtxs.push_back({ i, it->second, snap }); + } + + // A tree recycled while we walked it means every index above is suspect. + // Drop the pass to uninterpolated and say which slot collided. + if (gRenderPrev->generation.load(std::memory_order_acquire) != prevGen || + gRenderCurr->generation.load(std::memory_order_acquire) != currGen) { + SPDLOG_WARN("interp tree recycled mid-pass: prev={} curr={} record={} last={} claims=[{},{},{},{}]", + (int)(gRenderPrev - gRing), (int)(gRenderCurr - gRing), gRecordSlot, gLastRecordedSlot, + gSlotClaims[0].load(), gSlotClaims[1].load(), gSlotClaims[2].load(), gSlotClaims[3].load()); + gCache.reset(); + gCache.built = true; + return; } - gCache.valid = true; } -// Build a sprite modelview from lerped inputs. Mirrors the decomp -// composition for each kind so the replay matrix stays consistent with -// the record-site one. +// Rebuilds the sprite modelview the same way sprite/render.c composes it, so +// a replayed matrix can't drift from what the game would have written. void emitSprite(const SpriteDrawData& L, std::unordered_map& replacements) { if (L.dst == nullptr) { return; @@ -582,7 +720,6 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace std::memset(m, 0, sizeof(m)); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; - // Rotations match the matrix_stack.c primitives — rows 0-2 only. auto rotYaw = [&](float deg) { if (deg == 0.0f) return; @@ -618,8 +755,6 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace }; if (L.kind == FI_SPRITE_KIND_FULL) { - // FULL: translate first (the game's func_80252330 stomps mf[3]), - // then rotate — rotations only touch rows 0-2. m[3][0] = L.camRelPos[0]; m[3][1] = L.camRelPos[1]; m[3][2] = L.camRelPos[2]; @@ -627,8 +762,6 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace rotPitch(L.rotation[0]); rotRoll(L.rotation[2]); } else { - // Billboard: cam-aligned rotations, optional sprite roll, then - // translate overwrites mf[3]. rotYaw(L.camYaw); rotPitch(L.camPitch); if (L.kind == FI_SPRITE_KIND_BILLBOARD_ROLL) { @@ -639,7 +772,6 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace m[3][2] = L.camRelPos[2]; } - // mlMtxScale_xyz: rows 0-2 only, translation preserved. float sx = L.mirrored ? -L.scale[0] : L.scale[0]; for (int i = 0; i < 3; i++) { m[0][i] *= sx; @@ -653,43 +785,89 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace } // namespace +void FrameInterpolation_ApplyAnimVertices(float t) { + if (!gRenderShould) { + return; + } + if (!gCache.built) { + BuildInterpolationCache(); + } + if (!gCache.valid) { + return; + } + if (gCache.prevHasCameraPos && gRenderCurr->hasCameraPos) { + float dx = gRenderCurr->cameraPos[0] - gCache.prevCameraPos[0]; + float dy = gRenderCurr->cameraPos[1] - gCache.prevCameraPos[1]; + float dz = gRenderCurr->cameraPos[2] - gCache.prevCameraPos[2]; + constexpr float kCutDistSq = 1000.0f * 1000.0f; + if (dx * dx + dy * dy + dz * dz > kCutDistSq) { + return; + } + } + + const std::vector& currAnimVtxs = gRenderCurr->animVtxs; + const std::vector& prevAnimVtxs = gRenderPrev->animVtxs; + const float w = 1.0f - t; + + for (const PairedAnimVtx& pair : gCache.pairedAnimVtxs) { + const AnimVtxData& c = currAnimVtxs[pair.currIdx]; + if (pair.snap) { + continue; // never written, so dst still holds this tick's pose + } + const AnimVtxData& p = prevAnimVtxs[pair.prevIdx]; + Vtx* dst = reinterpret_cast(c.dst); + for (uint32_t i = 0; i < c.count; i++) { + for (int k = 0; k < 3; k++) { + float blended = w * static_cast(p.pos[i * 3 + k]) + t * static_cast(c.pos[i * 3 + k]); + dst[i].v.ob[k] = static_cast(std::lrintf(blended)); + } + } + } +} + void FrameInterpolation_Interpolate(float t, std::unordered_map& replacements) { - // Cache is built lazily by the first sub-frame call per render pass and - // reused; StartRecord clears it for the next tick. Caller owns - // `replacements` so its bucket array persists across sub-frames. replacements.clear(); - if (!gShouldInterpolate) { + if (!gRenderShould) { return; } - if (!gCache.valid) { + if (!gCache.built) { BuildInterpolationCache(); - if (!gCache.valid) { - return; - } + } + if (!gCache.valid) { + return; } - // Cut detector: a >1000-unit camera jump means a teleport (warp, - // fixed-cam snap). Lerping across that places the world between two - // scenes for one sub-frame. - if (gCache.prevHasCameraPos && gCurrent->hasCameraPos) { - float dx = gCurrent->cameraPos[0] - gCache.prevCameraPos[0]; - float dy = gCurrent->cameraPos[1] - gCache.prevCameraPos[1]; - float dz = gCurrent->cameraPos[2] - gCache.prevCameraPos[2]; + // A large camera jump means a warp or camera cut. + if (gCache.prevHasCameraPos && gRenderCurr->hasCameraPos) { + float dx = gRenderCurr->cameraPos[0] - gCache.prevCameraPos[0]; + float dy = gRenderCurr->cameraPos[1] - gCache.prevCameraPos[1]; + float dz = gRenderCurr->cameraPos[2] - gCache.prevCameraPos[2]; constexpr float kCutDistSq = 1000.0f * 1000.0f; if (dx * dx + dy * dy + dz * dz > kCutDistSq) { return; } } - const std::vector& prevToMtxs = gPrevious->toMtxs; - const std::vector& currToMtxs = gCurrent->toMtxs; - const std::vector& prevSpritesData = gPrevious->sprites; - const std::vector& currSpritesData = gCurrent->sprites; + const std::vector& prevToMtxs = gRenderPrev->toMtxs; + const std::vector& currToMtxs = gRenderCurr->toMtxs; + const std::vector& prevSpritesData = gRenderPrev->sprites; + const std::vector& currSpritesData = gRenderCurr->sprites; - replacements.reserve(gCache.pairedToMtxs.size() + gCache.pairedSprites.size() + gCurrent->projRots.size() * 3); + replacements.reserve(gCache.pairedToMtxs.size() + gCache.pairedSprites.size() + gCache.camRelFixups.size() + + gRenderCurr->projRots.size() * 3); const float w = 1.0f - t; + // Re-aim the frozen matrix at the sub-frame's camera. + for (uint32_t idx : gCache.camRelFixups) { + const ToMtxData& c = currToMtxs[idx]; + MtxF& out = replacements[reinterpret_cast(c.dst)]; + std::memcpy(out.mf, c.src, sizeof(out.mf)); + for (int k = 0; k < 3; k++) { + out.mf[3][k] += w * gCache.cameraDelta[k]; + } + } + for (const PairedToMtx& pair : gCache.pairedToMtxs) { const ToMtxData& c = currToMtxs[pair.currIdx]; const ToMtxData& p = prevToMtxs[pair.prevIdx]; @@ -705,12 +883,10 @@ void FrameInterpolation_Interpolate(float t, std::unordered_map& rep } } - // Even unpaired sprites need a per-sub-frame matrix rebuild because - // their billboard rotations follow the lerped projection. for (const PairedSprite& pair : gCache.pairedSprites) { const SpriteDrawData& c = currSpritesData[pair.currIdx]; SpriteDrawData L = c; - if (pair.prevIdx != UINT32_MAX) { + if (pair.prevIdx != UINT32_MAX && !pair.snap) { const SpriteDrawData& p = prevSpritesData[pair.prevIdx]; for (int k = 0; k < 3; k++) { L.camRelPos[k] = w * p.camRelPos[k] + t * c.camRelPos[k]; @@ -726,23 +902,21 @@ void FrameInterpolation_Interpolate(float t, std::unordered_map& rep emitSprite(L, replacements); } - const std::vector& prevProj = gPrevious->projRots; - const std::vector& currProj = gCurrent->projRots; - if (prevProj.size() == currProj.size()) { - for (size_t i = 0; i < currProj.size(); i++) { - const CameraProjRotData& p = prevProj[i]; - const CameraProjRotData& c = currProj[i]; - auto emitProj = [&](void* dst, float deg, float ax, float ay, float az) { - if (dst == nullptr) { - return; - } - MtxF& out = replacements[reinterpret_cast(dst)]; - guRotateF(out.mf, deg, ax, ay, az); - }; - // Axes match viewport.c: roll Z-, pitch X+, yaw Y+. - emitProj(c.rollMtx, lerpAngleDegSP(p.rollDeg, c.rollDeg, t), 0.0f, 0.0f, -1.0f); - emitProj(c.pitchMtx, lerpAngleDegSP(p.pitchDeg, c.pitchDeg, t), 1.0f, 0.0f, 0.0f); - emitProj(c.yawMtx, lerpAngleDegSP(p.yawDeg, c.yawDeg, t), 0.0f, 1.0f, 0.0f); - } + const std::vector& prevProj = gRenderPrev->projRots; + const std::vector& currProj = gRenderCurr->projRots; + for (const PairedProjRot& pair : gCache.pairedProjRots) { + const CameraProjRotData& c = currProj[pair.currIdx]; + const CameraProjRotData& p = prevProj[pair.prevIdx]; + auto emitProj = [&](void* dst, float deg, float ax, float ay, float az) { + if (dst == nullptr) { + return; + } + MtxF& out = replacements[reinterpret_cast(dst)]; + guRotateF(out.mf, deg, ax, ay, az); + }; + // Axis conventions per viewport.c: roll about -Z, pitch +X, yaw +Y. + emitProj(c.rollMtx, lerpAngleDegSP(p.rollDeg, c.rollDeg, t), 0.0f, 0.0f, -1.0f); + emitProj(c.pitchMtx, lerpAngleDegSP(p.pitchDeg, c.pitchDeg, t), 1.0f, 0.0f, 0.0f); + emitProj(c.yawMtx, lerpAngleDegSP(p.yawDeg, c.yawDeg, t), 0.0f, 1.0f, 0.0f); } } diff --git a/src/port/Interpolation/FrameInterpolation.h b/src/port/Interpolation/FrameInterpolation.h index 44d05a9bf..d462bb3a6 100644 --- a/src/port/Interpolation/FrameInterpolation.h +++ b/src/port/Interpolation/FrameInterpolation.h @@ -21,10 +21,17 @@ void FrameInterpolation_StartRecord(void); void FrameInterpolation_StopRecord(void); void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate); +// Which pair of recorded ticks a render pass blends between. The threaded +// path captures the pair when a display list is submitted and applies it when +// that list renders; the single-threaded path uses the live variant. +void FrameInterpolation_GetRecordingPair(int* prevSlot, int* currSlot, bool* shouldInterpolate); +void FrameInterpolation_ClaimPair(int prevSlot, int currSlot); +void FrameInterpolation_ReleasePair(int prevSlot, int currSlot); +void FrameInterpolation_BeginRenderPass(int prevSlot, int currSlot, bool shouldInterpolate); + // Hierarchical scope (cross-tick pairing identity). void FrameInterpolation_RecordOpenChild(const void* key, uintptr_t id); void FrameInterpolation_RecordCloseChild(void); -void FrameInterpolation_RecordMarker(const char* file, int line); // Mix three scalar fields into a stable scope id when no single field is // unique on its own (e.g. modelId+pos, particle spawn randomness). @@ -38,15 +45,7 @@ static inline uint64_t FrameInterpolation_FloatBits(float f) { return (uint64_t)u; } -// Low-level matrix primitives (from src/core1/math/matrix_stack.c). -void FrameInterpolation_RecordMatrixIdent(void); -void FrameInterpolation_RecordMatrixTranslate(float x, float y, float z); -void FrameInterpolation_RecordMatrixRotYaw(float degrees); -void FrameInterpolation_RecordMatrixRotPitch(float degrees); -void FrameInterpolation_RecordMatrixRotRoll(float degrees); -void FrameInterpolation_RecordMatrixScale(float x, float y, float z); -void FrameInterpolation_RecordMatrixSet(const float src[4][4]); -void FrameInterpolation_RecordMatrixMult(const float l[4][4], const float r[4][4]); +// Final matrix output of a mlMtxApply — the only matrix event replay needs. void FrameInterpolation_RecordMatrixToMtx(void* dst, const float src[4][4]); // BK puts camera rotation in projection, not modelview. We record the @@ -67,6 +66,10 @@ void FrameInterpolation_RecordCameraPosition(const float pos[3]); void FrameInterpolation_NoInterpolatePush(void); void FrameInterpolation_NoInterpolatePop(void); +// Like NoInterpolatePush, but keeps the camera half of the transform live. +void FrameInterpolation_CameraRelativePush(void); +void FrameInterpolation_CameraRelativePop(void); + // kind matches the three sprite paths in sprite/render.c: // BILLBOARD — func_80344138. camYaw/camPitch, no spriteRoll. // BILLBOARD_ROLL — func_80344424. camYaw/camPitch + spriteRoll forward. @@ -80,6 +83,9 @@ void FrameInterpolation_RecordSpriteDraw(int kind, void* dst, const float camRel float camYaw, float camPitch, float spriteRoll, const float rotation[3], int mirrored); +void FrameInterpolation_RecordAnimVertices(void* dst, const void* vertices, int32_t count); +void FrameInterpolation_ApplyAnimVertices(float t); + // Drop the prev tree at known camera cuts (map load, camera type change). void FrameInterpolation_DontInterpolateCamera(void); diff --git a/src/port/LaunchArgs.cpp b/src/port/LaunchArgs.cpp new file mode 100644 index 000000000..33c8c817d --- /dev/null +++ b/src/port/LaunchArgs.cpp @@ -0,0 +1,148 @@ +#include "LaunchArgs.h" + +#include +#include + +#include +#include + +#include "UI/LighthouseModMenuWindow.h" +#include "UI/cvar_prefixes.h" + +namespace Lighthouse { + +namespace { + +// Romhack requested via `-hack `; empty when the flag was not passed. +std::string sLaunchHack; + +// Persisted mod selection captured before the override, so it can be restored. +std::string sSavedEnabledMods; +std::string sSavedDisabledMods; +bool sLaunchHackApplied = false; + +// Everything here runs before context->InitLogging(), so diagnostics are buffered +// and emitted by FlushLaunchHackLog() once the logger is live. +std::string sLaunchHackLog; +bool sLaunchHackLogIsError = false; + +void SetLaunchHackLog(bool isError, std::string message) { + sLaunchHackLog = std::move(message); + sLaunchHackLogIsError = isError; +} + +} // namespace + +bool IsLaunchHackFlag(const std::string& arg, std::string& outInlineValue, bool& outTakesValue) { + static const char* kFlags[] = { "-hack", "--hack", "-romhack", "--romhack" }; + for (const char* flag : kFlags) { + if (arg == flag) { + outTakesValue = true; + return true; + } + const std::string prefix = std::string(flag) + "="; + if (arg.rfind(prefix, 0) == 0) { + outInlineValue = arg.substr(prefix.size()); + outTakesValue = false; + return true; + } + } + return false; +} + +void ParseLaunchArgs(int argc, char* argv[]) { + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + std::string inlineValue; + bool takesValue = false; + if (!IsLaunchHackFlag(arg, inlineValue, takesValue)) { + continue; + } + if (takesValue) { + if (i + 1 < argc) { + sLaunchHack = argv[++i]; + } else { + SetLaunchHackLog(true, "[Launch] " + arg + " requires a romhack name"); + } + } else { + sLaunchHack = inlineValue; + } + } +} + +void ApplyLaunchHack() { + if (sLaunchHack.empty()) { + return; + } + + // Only strip the extension when it is actually ".o2r", so a hack whose stem + // contains a dot ("my.hack") still resolves when named without the suffix. + const std::filesystem::path requested(sLaunchHack); + const std::string wanted = StringHelper::IEquals(requested.extension().string(), ".o2r") + ? requested.stem().generic_string() + : requested.filename().generic_string(); + + const std::string modsPath = Ship::Context::GetPathRelativeToAppDirectory("mods"); + if (modsPath.empty() || !std::filesystem::is_directory(modsPath)) { + SetLaunchHackLog(true, "[Launch] -hack '" + sLaunchHack + "': no mods directory to search"); + return; + } + + std::string resolved; + std::string available; + std::error_code ec; + for (const auto& entry : std::filesystem::recursive_directory_iterator( + modsPath, std::filesystem::directory_options::follow_directory_symlink, ec)) { + if (entry.is_directory() || !StringHelper::IEquals(entry.path().extension().string(), ".o2r")) { + continue; + } + const std::string stem = entry.path().stem().generic_string(); + if (!available.empty()) { + available += ", "; + } + available += stem; + if (StringHelper::IEquals(stem, wanted)) { + resolved = stem; + } + } + + if (resolved.empty()) { + SetLaunchHackLog(true, "[Launch] -hack '" + sLaunchHack + "': no matching .o2r under mods/. Available: " + + (available.empty() ? std::string("(none)") : available)); + return; + } + + // Snapshot before overriding so RestoreModSelectionAfterLaunchHack() can put + // the user's own selection back once the archives are loaded. + sSavedEnabledMods = CVarGetString(CVAR_SETTING("EnabledMods"), ""); + sSavedDisabledMods = CVarGetString(CVAR_SETTING("DisabledMods"), ""); + sLaunchHackApplied = true; + + // Validates that the match actually carries an aGameConfig, and disables any + // other overlay so the boot-time conflict check does not quarantine them. + SetLaunchHackLog(false, "[Launch] -hack '" + sLaunchHack + "': enabling romhack overlay '" + resolved + "'"); + SetSoleEnabledRomhack(resolved); +} + +void RestoreModSelectionAfterLaunchHack() { + if (!sLaunchHackApplied) { + return; + } + CVarSetString(CVAR_SETTING("EnabledMods"), sSavedEnabledMods.c_str()); + CVarSetString(CVAR_SETTING("DisabledMods"), sSavedDisabledMods.c_str()); + Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); +} + +void FlushLaunchHackLog() { + if (sLaunchHackLog.empty()) { + return; + } + if (sLaunchHackLogIsError) { + SPDLOG_ERROR("{}", sLaunchHackLog); + } else { + SPDLOG_INFO("{}", sLaunchHackLog); + } + sLaunchHackLog.clear(); +} + +} // namespace Lighthouse diff --git a/src/port/LaunchArgs.h b/src/port/LaunchArgs.h new file mode 100644 index 000000000..3277382fd --- /dev/null +++ b/src/port/LaunchArgs.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace Lighthouse { + +void ParseLaunchArgs(int argc, char* argv[]); +bool IsLaunchHackFlag(const std::string& arg, std::string& outInlineValue, bool& outTakesValue); +void ApplyLaunchHack(); +void RestoreModSelectionAfterLaunchHack(); +void FlushLaunchHackLog(); + +} // namespace Lighthouse diff --git a/src/port/Localization/Language.cpp b/src/port/Localization/Language.cpp index 4318c10e6..85c2a3ef6 100644 --- a/src/port/Localization/Language.cpp +++ b/src/port/Localization/Language.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "libultraship/libultraship.h" #include "ship/Context.h" @@ -138,6 +139,61 @@ bool ArchiveHasAssetHex(Ship::Archive* archive, uint32_t hex) { return false; } +bool IsLocalizedText(const std::string& path) { + return path.find("/dialog/") != std::string::npos || path.find("/quizq/") != std::string::npos || + path.find("/gruntyq/") != std::string::npos; +} + +bool EntryStamp(zip_t* z, const std::string& entryPath, uint32_t& outCrc, uint64_t& outSize) { + zip_stat_t st; + zip_stat_init(&st); + if (zip_stat(z, entryPath.c_str(), 0, &st) != 0 || !(st.valid & ZIP_STAT_CRC) || !(st.valid & ZIP_STAT_SIZE)) { + return false; + } + outCrc = static_cast(st.crc); + outSize = static_cast(st.size); + return true; +} + +size_t DropUnchangedOverrides(const std::string& packArchivePath, + std::unordered_map& overrides) { + const std::string basePath = BaseArchivePath(); + if (basePath.empty() || packArchivePath.empty()) { + return 0; + } + zip_t* packZip = zip_open(packArchivePath.c_str(), ZIP_RDONLY, nullptr); + if (packZip == nullptr) { + return 0; // a folder-based archive, not a zip: no cheap stamp to compare + } + zip_t* baseZip = zip_open(basePath.c_str(), ZIP_RDONLY, nullptr); + if (baseZip == nullptr) { + zip_close(packZip); + return 0; + } + + size_t dropped = 0; + for (auto it = overrides.begin(); it != overrides.end();) { + if (IsLocalizedText(it->second)) { + ++it; + continue; + } + uint32_t packCrc = 0, baseCrc = 0; + uint64_t packSize = 0, baseSize = 0; + const std::string baseEntry = ResourceHelpers_GetBaseAssetPath(it->first); + if (baseEntry.empty() || !EntryStamp(packZip, it->second, packCrc, packSize) || + !EntryStamp(baseZip, baseEntry, baseCrc, baseSize) || packCrc != baseCrc || packSize != baseSize) { + ++it; + continue; + } + it = overrides.erase(it); + dropped++; + } + + zip_close(baseZip); + zip_close(packZip); + return dropped; +} + const LanguageEntry* FindLanguage(const std::string& name) { for (const auto& e : sLanguages) { if (e.name == name) { @@ -221,8 +277,14 @@ void SetActiveLanguage(const std::string& name) { std::unordered_map dialogOverride; if (entry->source != nullptr) { + // The pack's assets are numbered for the ROM it was extracted from, so they have + // to be translated into the base's v1.0 id space before they can override anything. + const uint32_t rawVersion = static_cast(entry->source->GetGameVersion()); + BKVersion packVersion = BK_VER_US_10; + const bool classified = ClassifyArchiveVersion(rawVersion, packVersion); + const std::unordered_map* remap = nullptr; - switch (static_cast(entry->source->GetGameVersion())) { + switch (packVersion) { case BK_VER_US_11: remap = &sV10toV11Remap; break; @@ -232,9 +294,20 @@ void SetActiveLanguage(const std::string& name) { case BK_VER_JP: remap = &sV10toJPRemap; break; + case BK_VER_US_10: default: break; // pack ids already match v1.0 } + + // Without a recognised stamp there is no way to know which id space the pack is in. + // Installing its assets under their own ids would drop them onto whatever v1.0 asset + // happens to share the number, so leave the language alone instead. + if (!classified) { + SPDLOG_ERROR("[Lang] '{}': pack version stamp {:#010x} matches no known ROM; refusing to apply it " + "(its asset ids cannot be translated to the base game's).", + name, rawVersion); + return; + } std::unordered_map inverse; if (remap != nullptr) { for (const auto& [v10Id, targetId] : *remap) { @@ -263,16 +336,23 @@ void SetActiveLanguage(const std::string& name) { } else if (auto it = inverse.find(packId); it != inverse.end()) { v10Id = it->second; } else { + // Nothing to translate: the asset has no v1.0 counterpart (the JP-only + // font and friends, which the port asks for by their pack id). v10Id = packId; } dialogOverride[v10Id] = path; } + + if (const size_t dropped = DropUnchangedOverrides(entry->source->GetPath(), dialogOverride); dropped > 0) { + SPDLOG_INFO("[Lang] '{}': {} pack asset(s) are identical to the base game and were left un-repointed", name, + dropped); + } } // Hand the computed language to the resource layer const size_t repointed = dialogOverride.size(); ResourceHelpers_ApplyLanguage(std::move(dialogOverride), entry->script == SCRIPT_JP, entry->count, entry->index); - SPDLOG_INFO("[Lang] Active language '{}' ({} ids re-pointed)", name, repointed); + SPDLOG_INFO("[Lang] Active language '{}'", name, repointed); } void RescanLanguages() { diff --git a/src/port/Localization/Localization.cpp b/src/port/Localization/Localization.cpp index d5a738d64..0e0fde746 100644 --- a/src/port/Localization/Localization.cpp +++ b/src/port/Localization/Localization.cpp @@ -6,20 +6,14 @@ #include #include #include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Patches/Patches.h" +#include "port/ResourceHelpers.h" #include "port/ShipInit.hpp" #include "port/UI/cvar_prefixes.h" typedef unsigned char u8; extern "C" { -int ResourceMgr_IsJapanese(void); -int ResourceMgr_GetDialogLanguageCount(void); // 1 = US, 3 = PAL (EN/FR/DE) -int ResourceMgr_GetDialogLanguage(void); // PAL only: 0=English, 1=French, 2=German -int ResourceMgr_GetLanguageGeneration(void); -int ResourceMgr_IsAssetRepointed(uint32_t assetId); -const char* ResourceMgr_GetLangString(const char* english); // active pack's translation, or the key itself -int ResourceMgr_HasLangStrings(void); // active language is a pack carrying UI overrides - bool gameFile_isNotEmpty(int gamenum); int jiggyscore_total(void); int itemscore_noteScores_getTotal(void); @@ -37,15 +31,14 @@ int code94620_func_8031B5B0(void); // current dialog-language index (0 int func_8031877C(void* zoombox); // clear a zoombox's strings before re-setting // Print font internals -extern void* D_80380AB8[]; // BKSprite*[5]: font alphamask assets (slot 2 = JP font) -extern void* print_sFonts[]; // FontLetter*[4]: decoded glyph tables per slot +extern void* print_sFontSpriteAssets[]; // BKSprite*[5]: font alphamask assets (slot 2 = JP font) +extern void* print_sFonts[]; // FontLetter*[4]: decoded glyph tables per slot void* print_getLettersFromFont(void* alphaMask, void* textureSprite); int print_getCurrentMapBoldFontTexture(void); void print_setBoldFontTexture(int textureId); void* assetcache_get(int assetId); void assetcache_release(void* ptr); void bk_free(void* ptr); -void port_refreshDialogFontGlyphCount(void); } // Live language change reactions @@ -65,37 +58,39 @@ void FreeJpFontSlot() { bk_free(print_sFonts[2]); print_sFonts[2] = nullptr; } - if (D_80380AB8[2] != nullptr) { - assetcache_release(D_80380AB8[2]); - D_80380AB8[2] = nullptr; + if (print_sFontSpriteAssets[2] != nullptr) { + assetcache_release(print_sFontSpriteAssets[2]); + print_sFontSpriteAssets[2] = nullptr; } } void LoadJpFontSlot() { // Bail early if print_init hasn't run to load this slot yet - if (D_80380AB8[0] == nullptr) { + if (print_sFontSpriteAssets[0] == nullptr) { return; } FreeJpFontSlot(); // drop any stale font first (e.g. a different pack) void* tex = assetcache_get(print_getCurrentMapBoldFontTexture()); - D_80380AB8[2] = assetcache_get(kJpDialogFontAssetId); - print_sFonts[2] = print_getLettersFromFont(D_80380AB8[2], tex); + print_sFontSpriteAssets[2] = assetcache_get(kJpDialogFontAssetId); + print_sFonts[2] = print_getLettersFromFont(print_sFontSpriteAssets[2], tex); assetcache_release(tex); } // Re-decode the base dialog font (slot 0) from its current asset. void ReloadDialogFontSlot() { - if (D_80380AB8[0] == nullptr) { + if (print_sFontSpriteAssets[0] == nullptr) { return; // print_init hasn't run yet } void* tex = assetcache_get(print_getCurrentMapBoldFontTexture()); - assetcache_release(D_80380AB8[0]); - D_80380AB8[0] = assetcache_get(kDialogFontAssetId); + assetcache_release(print_sFontSpriteAssets[0]); + print_sFontSpriteAssets[0] = assetcache_get(kDialogFontAssetId); bk_free(print_sFonts[0]); - print_sFonts[0] = print_getLettersFromFont(D_80380AB8[0], tex); + print_sFonts[0] = print_getLettersFromFont(print_sFontSpriteAssets[0], tex); assetcache_release(tex); // A pack may ship an extended dialog font; refresh the reachable glyph count to match. port_refreshDialogFontGlyphCount(); + // Build cross-revision-corrected HD glyph textures for the current base (no-op without a pack). + port_dialogFontHd_rebuild(); } // Per cached-model-slot generation @@ -517,8 +512,7 @@ static void buildPalJpParades() { // present in the active language (sDialogOverride) rather than on the base version. static constexpr uint32_t kMotzandParadeCreditId = 0x11CA; static bool port_useMotzandParade() { - return ResourceMgr_IsJapanese() || ResourceMgr_GetDialogLanguageCount() > 1 || - ResourceMgr_IsAssetRepointed(kMotzandParadeCreditId) != 0; + return ResourceMgr_IsJapanese() || ResourceMgr_IsPal() || ResourceMgr_IsAssetRepointed(kMotzandParadeCreditId) != 0; } // Swap the active parade table for the Motzand variant. @@ -561,7 +555,7 @@ static void RegisterLocalizedText() { if (ResourceMgr_IsJapanese()) { sJpFontFreeDelay = 0; // cancel a pending free; ensure slot 2 is current LoadJpFontSlot(); - } else if (D_80380AB8[2] != nullptr) { + } else if (print_sFontSpriteAssets[2] != nullptr) { sJpFontFreeDelay = kJpFontFreeDelayFrames; } bool fontOverridden = ResourceMgr_IsAssetRepointed(kDialogFontAssetId) != 0; @@ -585,7 +579,7 @@ static void RegisterLocalizedText() { // frame instead of letting the draw dereference a NULL slot. REGISTER_LISTENER(ResolveBoldFontSlot, EVENT_PRIORITY_NORMAL, [](IEvent* event) { auto* ev = (ResolveBoldFontSlot*)event; - if (D_80380AB8[*ev->slot] == nullptr) { + if (print_sFontSpriteAssets[*ev->slot] == nullptr) { *ev->slot = 0; *ev->letterId = 0; } diff --git a/src/port/Nametag/Nametag.cpp b/src/port/Nametag/Nametag.cpp index 116777e54..3c0a52518 100644 --- a/src/port/Nametag/Nametag.cpp +++ b/src/port/Nametag/Nametag.cpp @@ -2,7 +2,9 @@ #include #include +#include #include +#include #include #include @@ -29,16 +31,61 @@ constexpr float kBorderThickness = 1.5f; constexpr float kGameAspect = 4.0f / 3.0f; constexpr float kLowResAspect = 320.0f / 240.0f; +// Distance over which a tag fades out as it reaches the edge of its range. +constexpr float kFadeBand = 500.0f; +constexpr float kMaxFadeShare = 0.25f; + struct Entry { - float pos[3]; + uint32_t id; + float screen[2]; + bool onScreen; + float alpha; std::string text; }; -std::vector sQueue; +ImU32 WithAlpha(ImU32 color, float alpha) { + const float scaled = (float)((color >> IM_COL32_A_SHIFT) & 0xFF) * alpha; + const ImU32 value = (ImU32)(scaled < 0.0f ? 0.0f : (scaled > 255.0f ? 255.0f : scaled)); + return (color & ~IM_COL32_A_MASK) | (value << IM_COL32_A_SHIFT); +} + +// Game thread only. +std::vector sRecording; +bool sRecordingStale = false; + +void RetireRecording() { + sRecording.clear(); +} + +struct FrameTags { + uint64_t serial; + std::vector entries; +}; +std::mutex sHandoffMutex; +std::unordered_map sHandoff; +uint64_t sHandoffSerial = 0; +constexpr uint64_t kHandoffStaleAfter = 8; + +// Render thread only. +std::vector sRenderCurr; +std::vector sRenderPrev; +bool sRenderInterpolate = false; +float sSubframeBlend = 1.0f; + Nametag::ProjectFn sProject = nullptr; +Nametag::DistanceFn sDistance = nullptr; const int* sFbWidth = nullptr; const int* sFbHeight = nullptr; +const Entry* FindPrevious(uint32_t id) { + for (const auto& entry : sRenderPrev) { + if (entry.id == id) { + return &entry; + } + } + return nullptr; +} + // Mirrors LUS Gui::GetIntegerScaleFactor; mGameWindowViewport lags one // frame, matching DrawGame's own read order. int16_t ComputeIntegerScaleFactor(const std::shared_ptr& interp) { @@ -174,19 +221,28 @@ class NametagOverlay : public Ship::GuiWindow { const float scaleY = contentH / static_cast(*sFbHeight); ImDrawList* drawList = ImGui::GetForegroundDrawList(); - for (const auto& entry : sQueue) { - float pos[3] = { entry.pos[0], entry.pos[1], entry.pos[2] }; - float screen[2]; - if (sProject(pos, screen)) { - ImVec2 textSize = ImGui::CalcTextSize(entry.text.c_str()); - ImVec2 anchor(originX + screen[0] * scaleX, originY + screen[1] * scaleY); - ImVec2 textTL(anchor.x - textSize.x * 0.5f, anchor.y - textSize.y * 0.5f); - ImVec2 boxTL(textTL.x - kPaddingX, textTL.y - kPaddingY); - ImVec2 boxBR(textTL.x + textSize.x + kPaddingX, textTL.y + textSize.y + kPaddingY); - drawList->AddRectFilled(boxTL, boxBR, kBgColor, kCornerRadius); - drawList->AddRect(boxTL, boxBR, kBorderColor, kCornerRadius, 0, kBorderThickness); - drawList->AddText(textTL, kTextColor, entry.text.c_str()); + for (const auto& entry : sRenderCurr) { + if (!entry.onScreen) { + continue; } + float screenX = entry.screen[0]; + float screenY = entry.screen[1]; + float alpha = entry.alpha; + const Entry* previous = sRenderInterpolate ? FindPrevious(entry.id) : nullptr; + if (previous != nullptr && previous->onScreen) { + screenX = previous->screen[0] + (screenX - previous->screen[0]) * sSubframeBlend; + screenY = previous->screen[1] + (screenY - previous->screen[1]) * sSubframeBlend; + alpha = previous->alpha + (alpha - previous->alpha) * sSubframeBlend; + } + + ImVec2 textSize = ImGui::CalcTextSize(entry.text.c_str()); + ImVec2 anchor(originX + screenX * scaleX, originY + screenY * scaleY); + ImVec2 textTL(anchor.x - textSize.x * 0.5f, anchor.y - textSize.y * 0.5f); + ImVec2 boxTL(textTL.x - kPaddingX, textTL.y - kPaddingY); + ImVec2 boxBR(textTL.x + textSize.x + kPaddingX, textTL.y + textSize.y + kPaddingY); + drawList->AddRectFilled(boxTL, boxBR, WithAlpha(kBgColor, alpha), kCornerRadius); + drawList->AddRect(boxTL, boxBR, WithAlpha(kBorderColor, alpha), kCornerRadius, 0, kBorderThickness); + drawList->AddText(textTL, WithAlpha(kTextColor, alpha), entry.text.c_str()); } } }; @@ -199,6 +255,10 @@ void SetProjectFn(ProjectFn fn) { sProject = fn; } +void SetDistanceFn(DistanceFn fn) { + sDistance = fn; +} + void SetNativeFramebufferSize(const int* width, const int* height) { sFbWidth = width; sFbHeight = height; @@ -211,20 +271,88 @@ void RegisterOverlay() { overlay->Show(); } -void Clear() { - sQueue.clear(); +void BeginDraw() { + if (sRecordingStale) { + RetireRecording(); + } + sRecordingStale = true; } -void Push(float x, float y, float z, const char* label) { - if (label == nullptr) { +void Push(uint32_t id, float x, float y, float z, const char* label, float alpha) { + if (label == nullptr || alpha <= 0.0f || sProject == nullptr) { return; } + if (sRecordingStale) { + RetireRecording(); + sRecordingStale = false; + } Entry entry; - entry.pos[0] = x; - entry.pos[1] = y; - entry.pos[2] = z; + entry.id = id; + float pos[3] = { x, y, z }; + entry.onScreen = sProject(pos, entry.screen); + entry.alpha = alpha > 1.0f ? 1.0f : alpha; entry.text = label; - sQueue.push_back(std::move(entry)); + sRecording.push_back(std::move(entry)); +} + +// Game thread. A list is submitted while its tick is still recording, so the +// tags travel with the task the same way the interpolation pair does. +void SubmitFrame(const void* key) { + std::lock_guard lock(sHandoffMutex); + const uint64_t serial = ++sHandoffSerial; + auto [it, inserted] = sHandoff.emplace(key, FrameTags{ serial, sRecording }); + if (!inserted) { + it->second.serial = serial; + it->second.entries = sRecording; + } + + // Anything still here after a full trip round the ring will never be picked + // up by a render pass, so drop it rather than grow the map forever. + for (auto stale = sHandoff.begin(); stale != sHandoff.end();) { + if (stale->second.serial + kHandoffStaleAfter < serial) { + stale = sHandoff.erase(stale); + } else { + ++stale; + } + } +} + +// Render thread. Adopt the tags submitted with this list; what the previous +// pass drew stays behind as the interpolation source. +void BeginRenderPass(const void* key, bool interpolate) { + std::vector tags; + { + std::lock_guard lock(sHandoffMutex); + auto it = sHandoff.find(key); + if (it != sHandoff.end()) { + tags = std::move(it->second.entries); + sHandoff.erase(it); + } + } + sRenderPrev = std::move(sRenderCurr); + sRenderCurr = std::move(tags); + sRenderInterpolate = interpolate; +} + +float FadeForDistance(float x, float y, float z, float maxDistance) { + if (sDistance == nullptr) { + return 1.0f; + } + float pos[3] = { x, y, z }; + const float distance = sDistance(pos); + if (distance >= maxDistance) { + return 0.0f; + } + const float band = std::min(kFadeBand, maxDistance * kMaxFadeShare); + const float fadeStart = maxDistance - band; + if (distance <= fadeStart || band <= 0.0f) { + return 1.0f; + } + return (maxDistance - distance) / band; +} + +void SetSubframeBlend(float blend) { + sSubframeBlend = blend < 0.0f ? 0.0f : (blend > 1.0f ? 1.0f : blend); } } // namespace Nametag \ No newline at end of file diff --git a/src/port/Nametag/Nametag.h b/src/port/Nametag/Nametag.h index 478fde36a..32a767787 100644 --- a/src/port/Nametag/Nametag.h +++ b/src/port/Nametag/Nametag.h @@ -10,12 +10,17 @@ namespace Nametag { // World -> native-framebuffer-pixel projector. Writes (screen[0], screen[1]) // and returns true if the point is in front of the camera. using ProjectFn = bool (*)(float pos[3], float* screen); +using DistanceFn = float (*)(float pos[3]); void SetProjectFn(ProjectFn fn); +void SetDistanceFn(DistanceFn fn); void SetNativeFramebufferSize(const int* width, const int* height); void RegisterOverlay(); - -void Clear(); -void Push(float x, float y, float z, const char* label); +void BeginDraw(); +void Push(uint32_t id, float x, float y, float z, const char* label, float alpha = 1.0f); +float FadeForDistance(float x, float y, float z, float maxDistance); +void SetSubframeBlend(float blend); +void SubmitFrame(const void* key); +void BeginRenderPass(const void* key, bool interpolate); } // namespace Nametag \ No newline at end of file diff --git a/src/port/Nametag/NametagBindings.cpp b/src/port/Nametag/NametagBindings.cpp index 88220be18..c3fb481ce 100644 --- a/src/port/Nametag/NametagBindings.cpp +++ b/src/port/Nametag/NametagBindings.cpp @@ -1,16 +1,13 @@ -// BK-specific bindings for the portable Nametag overlay: projection, FB -// dimensions, tick-event listeners, and the asset-id -> label table. +// BK-specific bindings for the portable Nametag overlay: projection, distance, +// FB dimensions, and the per-draw tick listener. #include #include "Nametag.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -#include "port/UI/cvar_prefixes.h" -#include "port/ObjectExtension/ObjectExtension.h" extern "C" { -#include "enums.h" #include "core1/viewport.h" extern int gFramebufferWidth; extern int gFramebufferHeight; @@ -18,41 +15,9 @@ extern int gFramebufferHeight; namespace { -struct NametagTableEntry { - int32_t assetId; - const char* label; - float yOffset; -}; - -// Asset-id -> nametag lookup. Shared across the actor / prop / sprite-prop paths. -constexpr NametagTableEntry sNametagTable[] = { - { ASSET_350_MODEL_TERMITE, "Termite", 150.0f }, { ASSET_3C5_MODEL_GRUBLIN, "Grublin", 150.0f }, - { ASSET_353_MODEL_BIGBUTT, "BigButt", 150.0f }, { ASSET_3C0_MODEL_JINJO_BLUE, "Blue Jinjo", 150.0f }, - { ASSET_3C2_MODEL_JINJO_GREEN, "Green Jinjo", 150.0f }, { ASSET_3BC_MODEL_JINJO_ORANGE, "Orange Jinjo", 150.0f }, - { ASSET_3C1_MODEL_JINJO_PINK, "Pink Jinjo", 150.0f }, { ASSET_3BB_MODEL_JINJO_YELLOW, "Yellow Jinjo", 150.0f }, - { ASSET_6D6_SPRITE_MUSIC_NOTE, "Note", 80.0f }, { ASSET_41A_SPRITE_MUMBO_TOKEN, "Mumbo Token", 80.0f }, -}; - -const NametagTableEntry* LookupNametag(int32_t assetId) { - for (const auto& entry : sNametagTable) { - if (entry.assetId == assetId) { - return &entry; - } - } - return nullptr; -} - -static bool inRange(float x, float y, float z) { - float pos[3] = { x, y, z }; - return viewport_getDistance(pos) < CVarGetFloat(CVAR_DEVELOPER_TOOLS("NametagDist"), 3000.0f); -} - -static bool inRange(int16_t pos[3]) { - return inRange((float)pos[0], (float)pos[1], (float)pos[2]); -} - void InitNametagBindings() { Nametag::SetProjectFn(&viewport_func_8024E030); + Nametag::SetDistanceFn(&viewport_getDistance); Nametag::SetNativeFramebufferSize(&gFramebufferWidth, &gFramebufferHeight); Nametag::RegisterOverlay(); } @@ -60,6 +25,9 @@ void InitNametagBindings() { } // namespace static RegisterShipInitFunc initNametagBindings(InitNametagBindings, { "BOOT" }); + +// Tags are queued during the world draw, so the queue turns over on OnPlayerDraw rather than +// on the game tick. Ordering against the producers on this event does not matter. static RegisterShipInitFunc init([]() { - REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_HIGH, [](IEvent* event) { Nametag::Clear(); }); -}); \ No newline at end of file + REGISTER_LISTENER(OnPlayerDraw, EVENT_PRIORITY_HIGH, [](IEvent* event) { Nametag::BeginDraw(); }); +}); diff --git a/src/port/Network/Anchor/Anchor.cpp b/src/port/Network/Anchor/Anchor.cpp index f33f51ca1..3b515d58d 100644 --- a/src/port/Network/Anchor/Anchor.cpp +++ b/src/port/Network/Anchor/Anchor.cpp @@ -1,17 +1,16 @@ #include "Anchor.h" #include "Authority.h" +#include #include #include #include "port/Engine.h" #include "port/Nametag/Nametag.h" #include "port/Interpolation/FrameInterpolation.h" #include "port/ObjectExtension/ObjectExtension.h" +#include "port/Enhancements/Retention/Retention.h" -extern "C" { #include "variables.h" #include "functions.h" -// extern PlayState* gPlayState; -} // MARK: - Overrides @@ -30,7 +29,15 @@ void Anchor::Enable() { Network::Enable(CVarGetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org"), CVarGetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383)); ownClientId = CVarGetInteger(CVAR_REMOTE_ANCHOR("LastClientId"), 0); - roomState.ownerClientId = 0; + roomState = RoomState{}; +} + +bool Anchor::IsGlobalRoom() { + return strcmp(CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), ""), "lh-global") == 0; +} + +bool Anchor::IsWorldSyncActive() { + return isConnected && !IsGlobalRoom() && roomState.syncItemsAndFlags != 0; } void Anchor::Disable() { @@ -45,6 +52,7 @@ void Anchor::Disable() { } } clients.clear(); + PlayerColors_reset(); RefreshClientActors(); } @@ -52,14 +60,22 @@ void Anchor::OnConnected() { SendPacket_Handshake(); RegisterHooks(); + port_noteRetention_setForced(IsGlobalRoom() ? 0 : 1); + port_jinjoRetention_setForced(IsGlobalRoom() ? 0 : 1); + if (IsSaveLoaded()) { SendPacket_RequestTeamState(); + hasRequestedTeamState = true; + reloadMapOnTeamState = true; } } void Anchor::OnDisconnected() { Authority_Reset(); RegisterHooks(); + + port_noteRetention_setForced(0); + port_jinjoRetention_setForced(0); } void Anchor::ProcessOutgoingPackets() { @@ -82,11 +98,22 @@ void Anchor::ProcessOutgoingPackets() { } } +bool Anchor::AllowedWithoutGameSync(const std::string& packetType) { + return packetType == HANDSHAKE || packetType == ALL_CLIENT_STATE || packetType == UPDATE_CLIENT_STATE || + packetType == UPDATE_ROOM_STATE || packetType == MAP_LOAD || packetType == PLAYER_UPDATE || + packetType == PLAYER_UPDATE_FULL || packetType == PLAYER_ANIM || packetType == PLAYER_SUBRANGE || + packetType == PLAYER_TRANSFORM || packetType == PLAYER_SFX || packetType == SERVER_MESSAGE; +} + void Anchor::SendJsonToRemote(nlohmann::json payload) { if (!isConnected) { return; } + if (!roomState.syncItemsAndFlags && !AllowedWithoutGameSync(payload.value("type", std::string()))) { + return; + } + payload["clientId"] = ownClientId; if (!payload.contains("quiet")) { SPDLOG_DEBUG("[Anchor] Queuing payload:\n{}", payload.dump()); @@ -115,6 +142,12 @@ void Anchor::OnIncomingJson(nlohmann::json payload) { std::string packetType = payload["type"].get(); + // Same rule inbound: a peer on an older build must not push world state into a room + // that isn't syncing it. + if (!roomState.syncItemsAndFlags && !AllowedWithoutGameSync(packetType)) { + return; + } + // Ignore packets from mismatched clients, except for ALL_CLIENT_STATE, UPDATE_CLIENT_STATE, and // PLAYER_UPDATE(_FULL) if (packetType != ALL_CLIENT_STATE && packetType != UPDATE_CLIENT_STATE && packetType != PLAYER_UPDATE && @@ -187,6 +220,40 @@ void Anchor::ProcessIncomingPacketQueue() { HandlePacket_SetCheckStatus(payload); else if (packetType == SET_FLAG) HandlePacket_SetFlag(payload); + else if (packetType == ITEM_COUNT) + HandlePacket_SetItemCount(payload); + else if (packetType == SET_ABILITY) + HandlePacket_SetAbility(payload); + else if (packetType == SCOPED_FLAG) + HandlePacket_ScopedFlag(payload); + else if (packetType == REQUEST_SCOPED_STATE) + HandlePacket_RequestScopedState(payload); + else if (packetType == SCOPED_STATE) + HandlePacket_ScopedState(payload); + else if (packetType == COLLECT_ITEM) + HandlePacket_CollectItem(payload); + else if (packetType == CARRY_THROW) + HandlePacket_CarryThrow(payload); + else if (packetType == BREAK_OBJECT) + HandlePacket_BreakObject(payload); + else if (packetType == EGG_TOLL) + HandlePacket_EggToll(payload); + else if (packetType == PUZZLE_STEP) + HandlePacket_PuzzleStep(payload); + else if (packetType == WATER_RISE) + HandlePacket_WaterRise(payload); + else if (packetType == PUZZLE_COUNT) + HandlePacket_PuzzleCount(payload); + else if (packetType == HUT_SMASH) + HandlePacket_HutSmash(payload); + else if (packetType == JIGGY_CRANE) + HandlePacket_JiggyCrane(payload); + else if (packetType == PEDESTAL_OWNER) + HandlePacket_PedestalOwner(payload); + else if (packetType == JIGGY_SPAWN) + HandlePacket_SpawnJiggy(payload); + else if (packetType == HONEYCOMB_SPAWN) + HandlePacket_SpawnHoneycomb(payload); else if (packetType == TELEPORT_TO) HandlePacket_TeleportTo(payload); else if (packetType == UNSET_FLAG) @@ -207,6 +274,12 @@ void Anchor::ProcessIncomingPacketQueue() { HandlePacket_VileHoleState(payload); else if (packetType == VILE_UPDATE) HandlePacket_VileUpdate(payload); + else if (packetType == FIGHT_UPDATE) + HandlePacket_FightUpdate(payload); + else if (packetType == FIGHT_EVENT) + HandlePacket_FightEvent(payload); + else if (packetType == FIGHT_STATE) + HandlePacket_FightState(payload); } catch (const std::exception& e) { SPDLOG_ERROR("[Anchor] Exception while processing incoming packet {}", e.what()); SPDLOG_ERROR("[Anchor] Packet: {}", payload.dump()); @@ -234,26 +307,67 @@ void Anchor::SetDummyPlayerClientId(const Actor* actor, uint32_t clientId) { ObjectExtension::GetInstance().Set(actor, DummyPlayerClientId{ clientId }); } +// Roughly the top of Banjo's head. +static constexpr f32 kNametagHeight = 155.0f; + +// The menu exposes the nametag range as a multiplier of this, the same way Extended Draw +// Distance scales off its own base. +static constexpr f32 kNametagRangeUnit = 3000.0f; + void Anchor::DrawDummies(OnPlayerDraw* event) { if (!isConnected) return; + const bool showNametags = CVarGetInteger(CVAR_REMOTE_ANCHOR("Nametags"), 1) != 0; + const f32 nametagRange = kNametagRangeUnit * CVarGetFloat(CVAR_REMOTE_ANCHOR("NametagScale"), 1.0f); for (const auto& [id, dummy] : dummies) { FrameInterpolation_RecordOpenChild(clients[id].name.c_str(), 0); dummy->Draw(event->gfx, event->mtx, event->vtx); FrameInterpolation_RecordCloseChild(); + + // A nameless client would otherwise get an empty tag box floating over them. + const std::string label = showNametags ? GetNametagLabel(id) : std::string(); + if (dummy->dummy_isVisible() && !label.empty()) { + f32 position[3]; + dummy->dummy_getPosition(position); + position[1] += kNametagHeight; + const f32 fade = Nametag::FadeForDistance(position[0], position[1], position[2], nametagRange); + Nametag::Push(id, position[0], position[1], position[2], label.c_str(), fade); + } } } void Anchor::ClearDummies() { for (auto& [id, dummy] : dummies) { - dummy->dummy_detachActor(); + dummy->dummy_despawnActor(); // skips if already detached by map teardown } dummies.clear(); } -// Takes the map explicitly rather than reading gsworld_getMap(): during the -// OnMapLoad event the new map hasn't been committed yet, so gsworld_getMap() -// still reports the map being left. +// Presence only: true in any room, including the global one. For dummy-player visuals. +extern "C" s32 port_anchor_isConnected(void) { + Anchor* anchor = Anchor::GetInstance(); + return (anchor != nullptr && anchor->isConnected) ? 1 : 0; +} + +// Lets decomp gate Anchor-only catch-up paths so single player keeps vanilla behaviour. +extern "C" s32 port_anchor_isWorldSyncActive(void) { + Anchor* anchor = Anchor::GetInstance(); + return (anchor != nullptr && anchor->IsWorldSyncActive()) ? 1 : 0; +} + +// actorArray_free tears down actors/markers without firing OnActorDestroy; forget them all. +extern "C" void port_anchorDummies_onActorsFreed(void) { + Anchor* anchor = Anchor::GetInstance(); + if (anchor == nullptr) { + return; + } + for (auto& [clientId, client] : anchor->clients) { + if (client.dummy != nullptr) { + client.dummy->dummy_detachActor(); + } + } +} + void Anchor::PopulateDummies(GameMap map) { for (const auto& [clientId, client] : clients) { if (client.map == map && !client.self && !dummies.contains(clientId) && client.online) { @@ -276,25 +390,124 @@ void Anchor::UpdateDummies() { } void Anchor::OnActorDestroyed(Actor* actor) { - // for (auto& [clientId, client] : clients) { - // if (client.dummy != nullptr && client.dummy->getDummyActor() == actor) { - // client.dummy->dummy_detachActor(); - // RemoveDummy(clientId); - // return; - // } - // } + // Stand-in was destroyed externally; forget its marker, dummy stays registered. + if (actor == nullptr || actor->marker == nullptr) { + return; + } + for (auto& [clientId, client] : clients) { + if (client.dummy != nullptr && client.dummy->dummy_getMarker() == actor->marker) { + client.dummy->dummy_detachActor(); + return; + } + } +} + +// Queues the honeycomb spawn the switch press performs. +extern "C" void __baMarker_8028BA00(s32 honeycombId); + +// The GV cactus and RBB boathouse honeycombs only exist once their switch is +// beak-busted: marker.c sets a map flag and spawns the actor. A teammate's press +// reaches us as flag state, so spawn the same actor the local press would have. +void Anchor::RevealSwitchHoneycomb() { + s32 uid; + s32 flag; + + switch (gsworld_getMap()) { + case MAP_12_GV_GOBIS_VALLEY: + uid = HONEYCOMB_B_GV_CACTUS; + flag = 0xD; + break; + case MAP_36_RBB_BOATHOUSE: + uid = HONEYCOMB_F_RBB_BOAT_HOUSE; + flag = 0; + break; + default: + return; + } + + if (!mapSpecificFlags_get(flag) || honeycombscore_get((enum honeycomb_e)uid)) { + return; + } + __baMarker_8028BA00(uid); } void Anchor::RemoveDummy(uint32_t clientId) { if (dummies.contains(clientId)) { + dummies[clientId]->dummy_despawnActor(); dummies.erase(clientId); } } +extern "C" s32 port_cutsceneWarp_getReturnMap(void); +extern void port_breakable_clearForLevel(int32_t levelId); +extern void port_hutSmash_clearForLevel(int32_t levelId); +extern void port_eggToll_clearForLevel(int32_t levelId); +extern void port_puzzleStep_clearForLevel(int32_t levelId); +extern void port_carriedSync_clearForLevel(int32_t levelId); + +s32 Anchor_LevelOfMap(s32 map) { + if (map <= 0 || map >= MAP_NUM_MAPS) { + return 0; + } + s32 level = (s32)map_getLevel((enum map_e)map); + return (level > 0 && level < 0x20) ? level : 0; +} + +void Anchor::SweepUnoccupiedLevelState(GameMap selfMap) { + // Nothing is shared without world sync, so these stores hold only our own progress — + // dropping them on a level change would undo single-player state. + if (!IsWorldSyncActive()) { + return; + } + + s32 selfLevel = Anchor_LevelOfMap((s32)selfMap); + if (selfLevel == 0 || selfLevel == (s32)LEVEL_D_CUTSCENE || selfMap == MAP_91_FILE_SELECT) { + return; + } + + bool occupied[0x20] = { false }; // level_e ids are small; matches jinjo retention slot count + auto markOccupied = [&occupied](s32 map) { + s32 level = Anchor_LevelOfMap(map); + if (level != 0) { + occupied[level] = true; + } + }; + markOccupied((s32)selfMap); + markOccupied(port_cutsceneWarp_getReturnMap()); + for (auto& [clientId, client] : clients) { + if (!client.self && client.online && client.isSaveLoaded) { + markOccupied((s32)client.map); + markOccupied(client.cutsceneReturnMap); + } + } + for (s32 level = 1; level < 0x20; level++) { + if (!occupied[level]) { + port_breakable_clearForLevel(level); + port_hutSmash_clearForLevel(level); + port_eggToll_clearForLevel(level); + port_puzzleStep_clearForLevel(level); + port_carriedSync_clearForLevel(level); + } + } +} + void Anchor::RegisterDummy(DummyPlayer* dummy, uint32_t clientID) { dummies.emplace(clientID, dummy); } +// Pushes a client's chosen model colours onto their stand-in so the next draw picks them up. +void Anchor::ApplyClientCosmetics(uint32_t clientId) { + if (!clients.contains(clientId)) { + return; + } + AnchorClient& client = clients[clientId]; + if (client.dummy == nullptr) { + return; + } + client.dummy->dummy_setOwner(clientId); + client.dummy->dummy_setColors(client.colors); +} + void Anchor::EvaluateDummyForClient(uint32_t clientId) { if (!clients.contains(clientId)) return; @@ -323,23 +536,37 @@ void Anchor::RefreshClientActors() { } bool Anchor::IsSaveLoaded() { + s32 gameMode = getGameMode(); + if (gameMode == GAME_MODE_6_FILE_PLAYBACK || gameMode == GAME_MODE_7_ATTRACT_DEMO) { + return false; + } auto map = gsworld_getMap(); return map != MAP_1E_CS_START_NINTENDO && map != MAP_1F_CS_START_RAREWARE && map != MAP_91_FILE_SELECT; - /* if (gPlayState == nullptr) { - return false; - } - - if (GET_PLAYER(gPlayState) == nullptr) { - return false; - } +} - if (gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) { - return false; - } +bool Anchor::ShouldShowNotifications() { + return CVarGetInteger(CVAR_REMOTE_ANCHOR("Notifications"), 1) != 0; +} - if (gSaveContext.gameMode != GAMEMODE_NORMAL) { - return false; - }*/ +// Public global room shows player number instead of custom name +std::string Anchor::GetNametagLabel(uint32_t clientId) { + auto it = clients.find(clientId); + if (it == clients.end()) { + return ""; + } + if (!IsGlobalRoom()) { + return it->second.name; + } + if (it->second.joinOrder == 0) { + return "Player"; + } + return "Player " + std::to_string(it->second.joinOrder); +} - // return true; +std::string Anchor::GetClientName(uint32_t clientId) { + auto it = clients.find(clientId); + if (it != clients.end() && !it->second.name.empty()) { + return it->second.name; + } + return "A teammate"; } diff --git a/src/port/Network/Anchor/Anchor.h b/src/port/Network/Anchor/Anchor.h index 5ffbdbcb7..f70139bd8 100644 --- a/src/port/Network/Anchor/Anchor.h +++ b/src/port/Network/Anchor/Anchor.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include "port/Enhancements/Events/Hooks/Events.h" #include "port/Network/Anchor/DummyPlayer.h" @@ -13,40 +15,41 @@ extern "C" { #include "prop.h" #include "variables.h" -//#include "z64.h" } -// void DummyPlayer_Init(Actor* actor, PlayState* play); -// void DummyPlayer_Update(Actor* actor, PlayState* play); -// void DummyPlayer_Draw(Actor* actor, PlayState* play); -// void DummyPlayer_Destroy(Actor* actor, PlayState* play); - typedef struct { uint32_t clientId; std::string name; - // Color_RGB8 color; + BKPlayerColorSet colors; std::string clientVersion; std::string teamId; bool online; bool self; + uint32_t joinOrder; uint32_t seed; bool isSaveLoaded; bool isGameComplete; GameMap map, prevMap; s32 exit, prevExit; + s32 cutsceneReturnMap; DummyPlayer* dummy; } AnchorClient; -typedef struct { - uint32_t ownerClientId; - u8 pvpMode; // 0 = off, 1 = on, 2 = on with friendly fire - u8 showLocationsMode; // 0 = none, 1 = team, 2 = all - u8 teleportMode; // 0 = off, 1 = team, 2 = all - u8 syncItemsAndFlags; // 0 = off, 1 = on - bool isRomhack; +struct RoomState { + uint32_t ownerClientId = 0; + u8 pvpMode = 0; // 0 = off, 1 = on, 2 = on with friendly fire + u8 showLocationsMode = 0; // 0 = none, 1 = team, 2 = all + u8 teleportMode = 0; // 0 = off, 1 = team, 2 = all + u8 syncItemsAndFlags = 0; // 0 = off, 1 = on + u8 shareConsumables = 0; // 0 = off, 1 = on — share egg/feather counts in team state + bool isRomhack = false; std::string romhackName; -} RoomState; + bool isRando = false; + int32_t seed = 0; // rando seed id (0 when the room is vanilla) +}; + +bool Anchor_ScopedFlagExcluded(s32 space, s32 index); class Anchor : public Network { private: @@ -55,12 +58,15 @@ class Anchor : public Network { bool justLoadedSave = false; bool isHandlingUpdateTeamState = false; bool isProcessingIncomingPacket = false; + bool hasRequestedTeamState = false; std::queue incomingPacketQueue; std::mutex incomingPacketQueueMutex; std::queue outgoingPacketQueue; std::mutex outgoingPacketQueueMutex; std::unordered_map dummies; + void FlushPendingJiggySpawns(); + nlohmann::json PrepClientState(); nlohmann::json PrepRoomState(); void RegisterHooks(); @@ -75,6 +81,7 @@ class Anchor : public Network { void RemoveDummy(uint32_t clientId); void EvaluateDummyForClient(uint32_t clientId); + void ApplyClientCosmetics(uint32_t clientId); void HandlePacket_AllClientState(nlohmann::json& payload); void HandlePacket_AuthorityState(nlohmann::json& payload); @@ -94,6 +101,26 @@ class Anchor : public Network { void HandlePacket_ServerMessage(nlohmann::json& payload); void HandlePacket_SetCheckStatus(nlohmann::json& payload); void HandlePacket_SetFlag(nlohmann::json& payload); + void HandlePacket_SetItemCount(nlohmann::json& payload); + void HandlePacket_SetAbility(nlohmann::json& payload); + void HandlePacket_ScopedFlag(nlohmann::json& payload); + void HandlePacket_RequestScopedState(nlohmann::json& payload); + void HandlePacket_ScopedState(nlohmann::json& payload); + void HandlePacket_CollectItem(nlohmann::json& payload); + void HandlePacket_CarryThrow(nlohmann::json& payload); + void HandlePacket_BreakObject(nlohmann::json& payload); + void HandlePacket_EggToll(nlohmann::json& payload); + void HandlePacket_FightEvent(nlohmann::json& payload); + void HandlePacket_FightState(nlohmann::json& payload); + void HandlePacket_FightUpdate(nlohmann::json& payload); + void HandlePacket_PuzzleStep(nlohmann::json& payload); + void HandlePacket_PuzzleCount(nlohmann::json& payload); + void HandlePacket_WaterRise(nlohmann::json& payload); + void HandlePacket_HutSmash(nlohmann::json& payload); + void HandlePacket_JiggyCrane(nlohmann::json& payload); + void HandlePacket_PedestalOwner(nlohmann::json& payload); + void HandlePacket_SpawnJiggy(nlohmann::json& payload); + void HandlePacket_SpawnHoneycomb(nlohmann::json& payload); void HandlePacket_TeleportTo(nlohmann::json& payload); void HandlePacket_UnsetFlag(nlohmann::json& payload); void HandlePacket_UpdateClientState(nlohmann::json& payload); @@ -107,6 +134,7 @@ class Anchor : public Network { public: uint32_t ownClientId; + bool reloadMapOnTeamState = false; inline static const std::string clientVersion = (char*)gGitCommitHash; // Packet types // @@ -130,6 +158,26 @@ class Anchor : public Network { inline static const std::string SERVER_MESSAGE = "SERVER_MESSAGE"; inline static const std::string SET_CHECK_STATUS = "SET_CHECK_STATUS"; inline static const std::string SET_FLAG = "SET_FLAG"; + inline static const std::string ITEM_COUNT = "ITEM_COUNT"; + inline static const std::string SET_ABILITY = "SET_ABILITY"; + inline static const std::string SCOPED_FLAG = "SCOPED_FLAG"; + inline static const std::string REQUEST_SCOPED_STATE = "REQUEST_SCOPED_STATE"; + inline static const std::string SCOPED_STATE = "SCOPED_STATE"; + inline static const std::string COLLECT_ITEM = "COLLECT_ITEM"; + inline static const std::string CARRY_THROW = "CARRY_THROW"; + inline static const std::string BREAK_OBJECT = "BREAK_OBJECT"; + inline static const std::string EGG_TOLL = "EGG_TOLL"; + inline static const std::string FIGHT_EVENT = "FIGHT_EVENT"; + inline static const std::string FIGHT_STATE = "FIGHT_STATE"; + inline static const std::string FIGHT_UPDATE = "FIGHT_UPDATE"; + inline static const std::string PUZZLE_STEP = "PUZZLE_STEP"; + inline static const std::string PUZZLE_COUNT = "PUZZLE_COUNT"; + inline static const std::string WATER_RISE = "WATER_RISE"; + inline static const std::string HUT_SMASH = "HUT_SMASH"; + inline static const std::string JIGGY_CRANE = "JIGGY_CRANE"; + inline static const std::string PEDESTAL_OWNER = "PEDESTAL_OWNER"; + inline static const std::string JIGGY_SPAWN = "JIGGY_SPAWN"; + inline static const std::string HONEYCOMB_SPAWN = "HONEYCOMB_SPAWN"; inline static const std::string TELEPORT_TO = "TELEPORT_TO"; inline static const std::string UNSET_FLAG = "UNSET_FLAG"; inline static const std::string UPDATE_CLIENT_STATE = "UPDATE_CLIENT_STATE"; @@ -143,6 +191,9 @@ class Anchor : public Network { std::map clients; RoomState roomState; + std::string lastWarnedRomhackLabel; + std::string lastWarnedRandoState; + bool hasCheckedRandoCompat = false; void Enable(); void Disable(); @@ -158,10 +209,24 @@ class Anchor : public Network { uint32_t GetDummyPlayerClientId(const Actor* actor); bool GetCurrentMapPlayers(); - void PrepDirectionPayload(nlohmann::json& payload); - void PrepTransformationPayload(nlohmann::json& payload); - void PrepAnimStatePayload(nlohmann::json& payload); - void PrepAnimSubRangePayload(nlohmann::json& payload); + bool IsGlobalRoom(); + + // The single gate for every Anchor behaviour that touches the world. A presence-only + // room (the global room, or a private room with "Sync Items & Flags" off) has to play + // exactly like single player, so only dummy players are allowed past this. + bool IsWorldSyncActive(); + + // Presence/position/plumbing packets, the only ones allowed through when the room + // is not syncing game state. Anything absent is treated as world state and dropped + // at the send and receive choke points, so a new packet type is unsynced by default. + static bool AllowedWithoutGameSync(const std::string& packetType); + + void AdoptRemoteCheck(s32 rc); + void CheckRandoRoomCompatibility(); + + bool ShouldShowNotifications(); + std::string GetClientName(uint32_t clientId); + std::string GetNametagLabel(uint32_t clientId); void SendPacket_AuthorityState(u8 activity, bool claimed); void SendPacket_ClearTeamState(std::string teamId); @@ -180,12 +245,31 @@ class Anchor : public Network { // client (used to hand a late arrival our current state directly). void SendPacket_PlayerTransformChange(Transformation tf_id, uint32_t targetClientId = 0); void SendPacket_PlayerUpdate(bool full = false, uint32_t targetClientId = 0); - void SendPacket_RequestTeamState(); - void SendPacket_RequestTeleport(u32 clientId); - void SendPacket_SetCheckStatus(/*RandomizerCheck rc*/); - void SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag); - void SendPacket_TeleportTo(u32 clientId); - void SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag); + void SendPacket_RequestTeamState(bool force = false); + void SendPacket_RequestTeleport(uint32_t clientId); + void SendPacket_SetCheckStatus(s32 rc, s32 map); + void SendPacket_SetFlag(u8 flagSpace, s16 flag); + void SendPacket_SetItemCount(s16 item, s32 count); + void SendPacket_SetAbility(s16 move, u8 value); + void SendPacket_ScopedFlag(u8 space, s16 index, u8 value); + void SendPacket_RequestScopedState(GameMap map); + void SendPacket_CollectItem(u8 kind, s32 id); + void SendPacket_CarryThrow(s32 markerId, f32 start[3], f32 target[3]); + void SendPacket_BreakObject(s16 markerId, s32 x, s32 y, s32 z, s32 map, bool replay = true); + void SendPacket_EggToll(s16 secondaryId, s32 stage, s32 map); + void SendPacket_FightEvent(s32 ev, s32 a, s32 b, const f32 v0[3], const f32 v1[3], const f32 v2[3]); + void SendPacket_FightState(u32 targetClientId); + void SendPacket_FightUpdate(const f32 pos[3], f32 yaw, s32 state, s32 phase, s32 mirror, s32 vuln); + void SendPacket_PuzzleStep(s32 puzzleId, s32 bits, s32 map, s32 phash = 0); + void SendPacket_PuzzleCount(s32 counterId, s32 delta, s32 map); + void SendPacket_WaterRise(s32 map, s32 kind, s32 p1, s32 p2, f32 duration); + void SendPacket_HutSmash(s32 x, s32 y, s32 z, s32 loot, s32 map); + void SendPacket_JiggyCrane(s32 stage); + void SendPacket_PedestalOwner(s32 id, bool claimed); + void SendPacket_SpawnJiggy(s16 jiggyId, f32 x, f32 y, f32 z); + void SendPacket_SpawnHoneycomb(s16 honeycombId, s32 bundleId, f32 x, f32 y, f32 z); + void SendPacket_TeleportTo(uint32_t clientId); + void SendPacket_UnsetFlag(u8 flagSpace, s16 flag); void SendPacket_UpdateClientState(); void SendPacket_UpdateRoomState(); void SendPacket_UpdateTeamState(); @@ -195,7 +279,10 @@ class Anchor : public Network { void SendPacket_VileHoleState(u8 holeId, u8 holeState, u8 pieceType, u32 eaterClientId); void SendPacket_VileUpdate(const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 animMode); void OnActorDestroyed(Actor* actor); + void RevealSwitchHoneycomb(); void SendToCurrentMapPlayers(nlohmann::json& payload); + void SendToCurrentLevelPlayers(nlohmann::json& payload); + void SweepUnoccupiedLevelState(GameMap selfMap); static Anchor* GetInstance(); static void Init(); diff --git a/src/port/Network/Anchor/AnchorRoomWindow.cpp b/src/port/Network/Anchor/AnchorRoomWindow.cpp index 589ccd760..47cb82725 100644 --- a/src/port/Network/Anchor/AnchorRoomWindow.cpp +++ b/src/port/Network/Anchor/AnchorRoomWindow.cpp @@ -1,11 +1,11 @@ #include "Anchor.h" #include "port/Engine.h" +#include "port/Rando/Rando.h" +#include "port/GameStatus.h" -extern "C" { #include "variables.h" #include "functions.h" // extern PlayState* gPlayState; -} void AnchorRoomWindow::Draw() { if (!IsVisible() || !Anchor::GetInstance()->isConnected) { @@ -34,9 +34,7 @@ void AnchorRoomWindow::Draw() { } void AnchorRoomWindow::DrawElement() { - bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); - - if (isGlobalRoom) { + if (Anchor::GetInstance()->IsGlobalRoom()) { u32 activeClients = 0; for (auto& [clientId, client] : Anchor::GetInstance()->clients) { if (client.online) { @@ -84,9 +82,8 @@ void AnchorRoomWindow::DrawElement() { (Anchor::GetInstance()->roomState.showLocationsMode == 1 && isOwnTeam)) { if ((client.self ? Anchor::GetInstance()->IsSaveLoaded() : client.isSaveLoaded)) { ImGui::SameLine(); - ImGui::TextColored( - ImVec4(1, 1, 1, 0.5f), "- %s", - /*SohUtils::GetSceneName(client.self ? gPlayState->sceneNum : client.sceneNum).c_str()*/ ""); + ImGui::TextColored(ImVec4(1, 1, 1, 0.5f), "- %s", + port_getLevelName((int)(client.self ? gsworld_getMap() : client.map))); } } @@ -110,7 +107,7 @@ void AnchorRoomWindow::DrawElement() { ImGui::EndTooltip(); } } - uint32_t seed = /*IS_RANDO ? Rando::Context::GetRawInstance()->GetSeed() :*/ 0; + uint32_t seed = IS_RANDO ? (uint32_t)RANDO_SEED : 0; if (client.isSaveLoaded && Anchor::GetInstance()->IsSaveLoaded() && client.seed != seed && client.online && !client.self) { ImGui::SameLine(); diff --git a/src/port/Network/Anchor/Authority.cpp b/src/port/Network/Anchor/Authority.cpp index 0c88144e6..7a689f011 100644 --- a/src/port/Network/Anchor/Authority.cpp +++ b/src/port/Network/Anchor/Authority.cpp @@ -1,11 +1,11 @@ #include "port/Network/Anchor/Authority.h" #include "port/Network/Anchor/Anchor.h" +#include "port/Network/Anchor/JigsawPedestal.h" #include "port/Network/Anchor/VileSync.h" +#include "port/Network/Anchor/FightSync.h" #include -extern "C" { #include "enums.h" -} struct ActivityState { bool claimed = false; @@ -16,7 +16,10 @@ static ActivityState sActivities[NET_ACTIVITY_COUNT]; // The map each activity lives in. A claim is only valid while its owner is in this map. static const int32_t sActivityMap[NET_ACTIVITY_COUNT] = { - MAP_10_BGS_MR_VILE, // NET_ACTIVITY_VILE_MINIGAME + MAP_10_BGS_MR_VILE, // NET_ACTIVITY_VILE_MINIGAME + MAP_90_GL_BATTLEMENTS, // NET_ACTIVITY_FINAL_BOSS + MAP_27_FP_FREEZEEZY_PEAK, // NET_ACTIVITY_FP_TWINKLY + MAP_1_SM_SPIRAL_MOUNTAIN, // NET_ACTIVITY_SM_TUTORIAL }; static bool Authority_IsValidActivity(NetworkActivityId activity) { @@ -29,6 +32,9 @@ static void Authority_OnOwnerChanged(NetworkActivityId activity) { case NET_ACTIVITY_VILE_MINIGAME: VileSync_OnAuthorityChanged(); break; + case NET_ACTIVITY_FINAL_BOSS: + FightSync_OnAuthorityChanged(); + break; default: break; } @@ -42,9 +48,14 @@ static void Authority_ClearClaim(NetworkActivityId activity) { } } +static bool Authority_SyncActive() { + Anchor* anchor = Anchor::GetInstance(); + return anchor != nullptr && anchor->IsWorldSyncActive(); +} + bool NetAuthority_IsSelf(NetworkActivityId activity) { Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected || !Authority_IsValidActivity(activity)) { + if (!Authority_SyncActive() || !Authority_IsValidActivity(activity)) { return true; } const ActivityState& state = sActivities[activity]; @@ -52,7 +63,7 @@ bool NetAuthority_IsSelf(NetworkActivityId activity) { } bool NetAuthority_IsClaimed(NetworkActivityId activity) { - return Authority_IsValidActivity(activity) && sActivities[activity].claimed; + return Authority_SyncActive() && Authority_IsValidActivity(activity) && sActivities[activity].claimed; } uint32_t NetAuthority_GetOwner(NetworkActivityId activity) { @@ -64,12 +75,11 @@ uint32_t NetAuthority_GetOwner(NetworkActivityId activity) { void NetAuthority_Claim(NetworkActivityId activity) { Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected || !Authority_IsValidActivity(activity)) { + if (!Authority_SyncActive() || !Authority_IsValidActivity(activity)) { return; } ActivityState& state = sActivities[activity]; if (state.claimed && state.owner != anchor->ownClientId) { - SPDLOG_WARN("[Authority] Tried to claim activity {} already owned by client {}", (int)activity, state.owner); return; } if (!state.claimed || state.owner != anchor->ownClientId) { @@ -82,7 +92,7 @@ void NetAuthority_Claim(NetworkActivityId activity) { void NetAuthority_Release(NetworkActivityId activity) { Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected || !Authority_IsValidActivity(activity)) { + if (!Authority_SyncActive() || !Authority_IsValidActivity(activity)) { return; } ActivityState& state = sActivities[activity]; @@ -116,6 +126,9 @@ void Authority_ApplyRemote(NetworkActivityId activity, uint32_t clientId, bool c } void Authority_OnClientStateChanged(uint32_t clientId, bool online, int32_t map) { + if (!online) { + JigsawPedestal_ClearClient(clientId); + } for (int32_t i = 0; i < NET_ACTIVITY_COUNT; i++) { ActivityState& state = sActivities[i]; if (state.claimed && state.owner == clientId && (!online || map != sActivityMap[i])) { @@ -125,6 +138,7 @@ void Authority_OnClientStateChanged(uint32_t clientId, bool online, int32_t map) } void Authority_OnPeerMapLoad(uint32_t clientId, int32_t map) { + JigsawPedestal_ClearClient(clientId); Anchor* anchor = Anchor::GetInstance(); for (int32_t i = 0; i < NET_ACTIVITY_COUNT; i++) { ActivityState& state = sActivities[i]; @@ -137,11 +151,15 @@ void Authority_OnPeerMapLoad(uint32_t clientId, int32_t map) { } else if (anchor != nullptr && state.owner == anchor->ownClientId && map == sActivityMap[i]) { // A peer just entered the map of an activity we own; make sure they know. anchor->SendPacket_AuthorityState((uint8_t)i, true); + if (i == NET_ACTIVITY_FINAL_BOSS) { + FightSync_SendSnapshot(clientId); + } } } } void Authority_OnSelfMapChanged(int32_t map) { + JigsawPedestal_ReleaseAllSelf(); Anchor* anchor = Anchor::GetInstance(); if (anchor == nullptr) { return; @@ -155,6 +173,7 @@ void Authority_OnSelfMapChanged(int32_t map) { } void Authority_Reset() { + JigsawPedestal_Reset(); for (int32_t i = 0; i < NET_ACTIVITY_COUNT; i++) { Authority_ClearClaim((NetworkActivityId)i); } diff --git a/src/port/Network/Anchor/Authority.h b/src/port/Network/Anchor/Authority.h index 8aa49d6d4..573d889b9 100644 --- a/src/port/Network/Anchor/Authority.h +++ b/src/port/Network/Anchor/Authority.h @@ -25,6 +25,9 @@ typedef enum NetworkActivityId { NET_ACTIVITY_NONE = -1, NET_ACTIVITY_VILE_MINIGAME, + NET_ACTIVITY_FINAL_BOSS, + NET_ACTIVITY_FP_TWINKLY, + NET_ACTIVITY_SM_TUTORIAL, NET_ACTIVITY_COUNT } NetworkActivityId; @@ -38,10 +41,7 @@ bool NetAuthority_IsSelf(NetworkActivityId activity); bool NetAuthority_IsClaimed(NetworkActivityId activity); // Owning clientId, or 0 when unclaimed. uint32_t NetAuthority_GetOwner(NetworkActivityId activity); -// Claim authority for the local client and broadcast it. No-op offline, or if another -// client already holds the claim. void NetAuthority_Claim(NetworkActivityId activity); -// Release our own claim and broadcast it. No-op unless we are the owner. void NetAuthority_Release(NetworkActivityId activity); #ifdef __cplusplus diff --git a/src/port/Network/Anchor/DummyPlayer.cpp b/src/port/Network/Anchor/DummyPlayer.cpp index 209a30316..88fe6e033 100644 --- a/src/port/Network/Anchor/DummyPlayer.cpp +++ b/src/port/Network/Anchor/DummyPlayer.cpp @@ -1,9 +1,9 @@ #include "Anchor.h" #include "port/Nametag/Nametag.h" +#include "functions.h" extern "C" { #include -#include "functions.h" #include "variables.h" void func_802D729C(Actor* actor, f32 arg1); } @@ -11,12 +11,22 @@ void func_802D729C(Actor* actor, f32 arg1); #include "bk_math.h" #include "port/Patches/Patches.h" +static s32 sActiveDummyBottlesBonus = 0; + +static void dummy_applyBottlesBonus(uintptr_t boneList, uintptr_t arg1) { + baanim_applyBottlesBonusMask(boneList, sActiveDummyBottlesBonus); +} + DummyPlayer::DummyPlayer(){}; void DummyPlayer::dummy_setTransformation(Transformation transform) { dummy_transformation = transform; } +void DummyPlayer::dummy_setBottlesBonus(s32 mask) { + dummyBottlesBonus = mask; +} + Transformation DummyPlayer::dummy_getTransformation() { return dummy_transformation; } @@ -49,28 +59,28 @@ void DummyPlayer::dummy_func_8029DBF0(void) { switch (dummy_getModelId()) { case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: // L8029DC24 case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: // L8029DC24 - temp_s0 = (s32)ml_interpolate_f(dummy_modelEyeBlendUpper, 1.0f, 8.0f); - func_8033A45C(0x1B, temp_s0); - func_8033A45C(0x1D, temp_s0); - func_8033A45C(0x1F, temp_s0); - func_8033A45C(0x21, temp_s0); - temp_s0 = (s32)ml_interpolate_f(dummy_modelEyeBlendLower, 1.0f, 8.0f); - func_8033A45C(0x1A, temp_s0); - func_8033A45C(0x1C, temp_s0); - func_8033A45C(0x1E, temp_s0); - func_8033A45C(0x20, temp_s0); + temp_s0 = (s32)ml_interpolate_f(dummy_banjoLeftEye, 1.0f, 8.0f); + modelRender_setAppendageVisibility(0x1B, temp_s0); + modelRender_setAppendageVisibility(0x1D, temp_s0); + modelRender_setAppendageVisibility(0x1F, temp_s0); + modelRender_setAppendageVisibility(0x21, temp_s0); + temp_s0 = (s32)ml_interpolate_f(dummy_banjoRightEye, 1.0f, 8.0f); + modelRender_setAppendageVisibility(0x1A, temp_s0); + modelRender_setAppendageVisibility(0x1C, temp_s0); + modelRender_setAppendageVisibility(0x1E, temp_s0); + modelRender_setAppendageVisibility(0x20, temp_s0); break; case ASSET_34F_MODEL_BANJO_TERMITE: // L8029DCCC case ASSET_359_MODEL_BANJO_WALRUS: // L8029DCCC case ASSET_36F_MODEL_BANJO_PUMPKIN: // L8029DCCC case ASSET_374_MODEL_BANJO_CROC: // L8029DCCC - func_8033A45C(0x1B, (s32)ml_interpolate_f(dummy_modelEyeBlendUpper, 1.0f, 6.0f)); - func_8033A45C(0x1A, (s32)ml_interpolate_f(dummy_modelEyeBlendLower, 1.0f, 6.0f)); + modelRender_setAppendageVisibility(0x1B, (s32)ml_interpolate_f(dummy_banjoLeftEye, 1.0f, 6.0f)); + modelRender_setAppendageVisibility(0x1A, (s32)ml_interpolate_f(dummy_banjoRightEye, 1.0f, 6.0f)); break; case ASSET_356_MODEL_BANJO_WISHYWASHY: // L8029DD2C - func_8033A45C(1, (s32)ml_interpolate_f(dummy_modelEyeBlendLower, 1.0f, 4.0f)); + modelRender_setAppendageVisibility(1, (s32)ml_interpolate_f(dummy_banjoRightEye, 1.0f, 4.0f)); break; } } @@ -80,59 +90,59 @@ AnimCtrl* DummyPlayer::dummy_getAnimCtrl() { } void DummyPlayer::dummy_setEyeState(bool squint, bool wink, bool isHat) { - dummy_modelSquint = squint; - dummy_modelWink = wink; + dummy_kazooieLower = squint; + dummy_kazooieFeet = wink; dummy_D_8037D230 = 1.0f; dummy_D_8037D234 = isHat; } -void DummyPlayer::func_8029DD6C(void) { +void DummyPlayer::modelAppendages_loadAppendage(void) { s32 temp_s0; // [port] must hold values > 1 for geo selector branches modelRender_func_8033A1FC(); switch (dummy_getModelId()) { case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: - func_8033A45C(1, dummy_kazooieVisible); - func_8033A45C(9, dummy_kazooieVisible); - func_8033A45C(0xC, dummy_kazooieVisible); - func_8033A45C(0xF, dummy_kazooieVisible); - func_8033A45C(2, dummy_modelWink); - func_8033A45C(0xA, dummy_modelWink); - func_8033A45C(0xD, dummy_modelWink); - func_8033A45C(0x10, dummy_modelWink); - func_8033A45C(8, dummy_modelSquint); - func_8033A45C(0xB, dummy_modelSquint); - func_8033A45C(0xE, dummy_modelSquint); - func_8033A45C(0x11, dummy_modelSquint); - temp_s0 = dummy_modelMouth1 + 1; - func_8033A45C(0x12, temp_s0); - func_8033A45C(0x14, temp_s0); - func_8033A45C(0x16, temp_s0); - func_8033A45C(0x18, temp_s0); - func_8033A45C(0x13, temp_s0); - func_8033A45C(0x15, temp_s0); - func_8033A45C(0x17, temp_s0); - func_8033A45C(0x19, temp_s0); - temp_s0 = dummy_modelMouth2 + 1; - func_8033A45C(0x22, temp_s0); - func_8033A45C(0x24, temp_s0); - func_8033A45C(0x26, temp_s0); - func_8033A45C(0x28, temp_s0); - func_8033A45C(0x23, temp_s0); - func_8033A45C(0x25, temp_s0); - func_8033A45C(0x27, temp_s0); - func_8033A45C(0x29, temp_s0); + modelRender_setAppendageVisibility(1, dummy_kazooieUpper); + modelRender_setAppendageVisibility(9, dummy_kazooieUpper); + modelRender_setAppendageVisibility(0xC, dummy_kazooieUpper); + modelRender_setAppendageVisibility(0xF, dummy_kazooieUpper); + modelRender_setAppendageVisibility(2, dummy_kazooieFeet); + modelRender_setAppendageVisibility(0xA, dummy_kazooieFeet); + modelRender_setAppendageVisibility(0xD, dummy_kazooieFeet); + modelRender_setAppendageVisibility(0x10, dummy_kazooieFeet); + modelRender_setAppendageVisibility(8, dummy_kazooieLower); + modelRender_setAppendageVisibility(0xB, dummy_kazooieLower); + modelRender_setAppendageVisibility(0xE, dummy_kazooieLower); + modelRender_setAppendageVisibility(0x11, dummy_kazooieLower); + temp_s0 = dummy_kazooieTurbos + 1; + modelRender_setAppendageVisibility(0x12, temp_s0); + modelRender_setAppendageVisibility(0x14, temp_s0); + modelRender_setAppendageVisibility(0x16, temp_s0); + modelRender_setAppendageVisibility(0x18, temp_s0); + modelRender_setAppendageVisibility(0x13, temp_s0); + modelRender_setAppendageVisibility(0x15, temp_s0); + modelRender_setAppendageVisibility(0x17, temp_s0); + modelRender_setAppendageVisibility(0x19, temp_s0); + temp_s0 = dummy_kazooieBoots + 1; + modelRender_setAppendageVisibility(0x22, temp_s0); + modelRender_setAppendageVisibility(0x24, temp_s0); + modelRender_setAppendageVisibility(0x26, temp_s0); + modelRender_setAppendageVisibility(0x28, temp_s0); + modelRender_setAppendageVisibility(0x23, temp_s0); + modelRender_setAppendageVisibility(0x25, temp_s0); + modelRender_setAppendageVisibility(0x27, temp_s0); + modelRender_setAppendageVisibility(0x29, temp_s0); break; case ASSET_359_MODEL_BANJO_WALRUS: - func_8033A45C(3, dummy_D_8037D23A); + modelRender_setAppendageVisibility(3, dummy_D_8037D23A); break; case ASSET_374_MODEL_BANJO_CROC: - temp_s0 = dummy_modelMouth1 + 1; - func_8033A45C(4, temp_s0); - func_8033A45C(5, temp_s0); - func_8033A45C(6, temp_s0); - func_8033A45C(7, temp_s0); + temp_s0 = dummy_kazooieTurbos + 1; + modelRender_setAppendageVisibility(4, temp_s0); + modelRender_setAppendageVisibility(5, temp_s0); + modelRender_setAppendageVisibility(6, temp_s0); + modelRender_setAppendageVisibility(7, temp_s0); break; } dummy_func_8029DBF0(); @@ -179,13 +189,18 @@ void DummyPlayer::Draw(Gfx** gfx, Mtx** mtx, Vtx** vtx) { sp38[2] += dummyDisplacement[2]; if (dummyBin) { + // anctrl_drawSetup re-runs anim_update, which invokes the bonus-mask callback. + sActiveDummyBottlesBonus = dummyBottlesBonus; anctrl_drawSetup(dummyAnimCtrl, dummyPosition, 1); - func_8029DD6C(); + sActiveDummyBottlesBonus = 0; + modelAppendages_loadAppendage(); modelRender_setEnvColor(env_color[0], env_color[1], env_color[2], dummyEnvAlpha); modelRender_func_8033A280(2.0f); // modelRender_preDraw((GenFunction_1)_dummy_preDraw, 0); modelRender_setRefPoints(dummy_D_80363780); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); + // Each dummy draws the shared model bin through its own recolored palettes. + PlayerColors_applyForDraw(dummyOwnerId, dummy_getModelId(), dummyBin, &dummyColors); if (dummy_D_8037C150.unk0) { dummy_D_8037C150.unk0 = 0; modelRender_draw(gfx, mtx, dummy_D_8037C150.unk4, rotation, dummyScale, sp38, dummyBin); @@ -227,9 +242,7 @@ void DummyPlayer::dummy_updateModel(void) { } void DummyPlayer::dummy_reset(void) { - // Clear stale actor reference — the game engine owns actor lifetime and may have - // already freed it (e.g. after a map transition). Don't dereference the old pointer. - // dummyActor = NULL; + dummy_despawnActor(); // skips if already detached if (dummyAnimCtrl) { dummyAnim_free(); dummyAnimCtrl = NULL; @@ -266,23 +279,31 @@ void DummyPlayer::dummy_reset(void) { dummyAnim_reset(); } +// Forget the stand-in without despawning it. void DummyPlayer::dummy_detachActor(void) { - // dummyActor = nullptr; + dummyMarker = nullptr; } -void DummyPlayer::dummy_free(void) { - /*if (dummyActor) { - if (dummyActor->unk104) { - Actor *shadow = marker_getActor(dummyActor->unk104); - shadow->unk104 = NULL; - shadow->despawn_flag = true; - dummyActor->unk104 = NULL; - } - if (dummyActor->marker) { - marker_despawn(dummyActor->marker); +void DummyPlayer::dummy_despawnActor(void) { + if (dummyMarker == nullptr) { + return; + } + Actor* actor = marker_getActor(dummyMarker); + if (actor != nullptr && actor->unk104 != nullptr) { + ActorMarker* shadowMarker = actor->unk104; + Actor* shadow = marker_getActor(shadowMarker); + if (shadow != nullptr) { + shadow->unk104 = nullptr; } - dummyActor = NULL; - }*/ + actor->unk104 = nullptr; + marker_despawn(shadowMarker); + } + marker_despawn(dummyMarker); + dummyMarker = nullptr; +} + +void DummyPlayer::dummy_free(void) { + dummy_despawnActor(); if (dummyBin) { assetcache_release(dummyBin); dummyBin = NULL; @@ -301,25 +322,41 @@ void DummyPlayer::dummy_free(void) { void DummyPlayer::dummyAnim_reset() { dummy_D_8037D230 = 0; dummy_D_8037D234 = 0; - dummy_kazooieVisible = 0; - dummy_modelWink = 0; - dummy_modelSquint = 0; - dummy_modelEyeBlendUpper = 0.0f; - dummy_modelEyeBlendLower = 0.0f; - dummy_modelMouth1 = 0; - dummy_modelMouth2 = 0; + dummy_kazooieUpper = 0; + dummy_kazooieFeet = 0; + dummy_kazooieLower = 0; + dummy_banjoLeftEye = 0.0f; + dummy_banjoRightEye = 0.0f; + dummy_kazooieTurbos = 0; + dummy_kazooieBoots = 0; dummy_D_8037D23A = 0; } +// func_802D7124 (core2/fx/enemy_shadow.c): distance-gated drop-shadow attach + keep-alive. +extern "C" void func_802D7124(Actor* actor, f32 scale); + void DummyPlayer::dummy_update(void) { dummyAnim_update(); - // if (dummyActor && !dummyActor->despawn_flag) { - // dummyActor->position[0] = dummyPosition[0]; - // dummyActor->position[1] = dummyPosition[1]; - // dummyActor->position[2] = dummyPosition[2]; - // func_802D729C(dummyActor, 1.0f); - // } + if (dummyMarker == nullptr) { + Actor* spawned = actor_spawnWithYaw_f32(ACTOR_3CC_DUMMY_PLAYER_ANCHOR, dummyPosition, (s32)dummyYaw); + if (spawned == nullptr) { + return; + } + dummyMarker = spawned->marker; + } + + Actor* actor = marker_getActor(dummyMarker); + if (actor == nullptr || actor->despawn_flag) { + return; + } + actor->position[0] = dummyPosition[0]; + actor->position[1] = dummyPosition[1]; + actor->position[2] = dummyPosition[2]; + actor->yaw = dummyYaw; + if (dummyIsVisible) { + func_802D7124(actor, 1.0f); + } } BKModelBin* DummyPlayer::dummy_getModelBin(void) { @@ -459,8 +496,7 @@ void DummyPlayer::dummyAnim_init(void) { dummyAnimCtrl = anctrl_new(1); func_80287784(dummyAnimCtrl, 0); anctrl_setSmoothTransition(dummyAnimCtrl, false); - // func_8028746C(dummyAnimCtrl, __baanim_applyBottlesBonus); - // AnimModifyFunction = NULL; + func_8028746C(dummyAnimCtrl, dummy_applyBottlesBonus); anctrl_drawSetup(dummyAnimCtrl, dummyPosition, 1); dummyAnimUpdateType = BAANIM_UPDATE_0_NONE; //__baanim_setUpdateType(BAANIM_UPDATE_1_NORMAL); @@ -503,18 +539,20 @@ void DummyPlayer::dummyAnim_update(void) { default: break; } + sActiveDummyBottlesBonus = dummyBottlesBonus; anctrl_update(dummyAnimCtrl); + sActiveDummyBottlesBonus = 0; } void DummyPlayer::setModelSubStates(bool kazooie, bool squint, bool wink, bool mouth1, bool mouth2, f32 eyeBlendUpper, f32 eyeBlendLower) { - dummy_kazooieVisible = kazooie; - dummy_modelSquint = squint; - dummy_modelWink = wink; - dummy_modelMouth1 = mouth1; - dummy_modelMouth2 = mouth2; - dummy_modelEyeBlendUpper = eyeBlendUpper; - dummy_modelEyeBlendLower = eyeBlendLower; + dummy_kazooieUpper = kazooie; + dummy_kazooieLower = squint; + dummy_kazooieFeet = wink; + dummy_kazooieTurbos = mouth1; + dummy_kazooieBoots = mouth2; + dummy_banjoLeftEye = eyeBlendUpper; + dummy_banjoRightEye = eyeBlendLower; } void DummyPlayer::dummyAnim_setUpdateType(s32 state) { diff --git a/src/port/Network/Anchor/DummyPlayer.h b/src/port/Network/Anchor/DummyPlayer.h index 9eb364c84..c472559f6 100644 --- a/src/port/Network/Anchor/DummyPlayer.h +++ b/src/port/Network/Anchor/DummyPlayer.h @@ -1,9 +1,8 @@ #pragma once -extern "C" { #include "functions.h" #include "core2/ba/model.h" #include "variables.h" -} +#include "port/Enhancements/Cosmetics/PlayerColors.h" class DummyPlayer { public: @@ -49,13 +48,15 @@ class DummyPlayer { void dummy_setScale(f32 scale); void dummy_setTransformation(Transformation transform); Transformation dummy_getTransformation(); + // Bottles-bonus effect mask (D_803635EC bitfield). + void dummy_setBottlesBonus(s32 mask); void dummy_setVisible(s32 arg0); void dummy_setYDisplacement(f32 arg0); void dummy_setYaw(f32 yaw); void dummy_update(void); void dummy_updateModel(void); // void func_80254008(void); - void func_8029DD6C(void); + void modelAppendages_loadAppendage(void); // void modelRender_func_8033A280(f32); // anim void dummyAnim_init(void); @@ -77,7 +78,17 @@ class DummyPlayer { // eye/mouth void dummy_setEyeState(bool squint, bool wink, bool isHat); AnimCtrl* dummy_getAnimCtrl(); - // Actor* getDummyActor() const { return dummyActor; } + ActorMarker* dummy_getMarker() const { + return dummyMarker; + } + void dummy_despawnActor(void); + // Cosmetics: which Anchor client this stand-in belongs to, and the model colors they chose. + void dummy_setOwner(uint32_t clientId) { + dummyOwnerId = clientId; + } + void dummy_setColors(const BKPlayerColorSet& colors) { + dummyColors = colors; + } private: uint32_t PlayerID; @@ -112,8 +123,7 @@ class DummyPlayer { } dummyAnimScale; AnimCtrl* dummyAnimCtrl = nullptr; f32 dummyVelocity[3]; - ActorMarker* dummyMarker; - Actor* dummyActor = nullptr; + ActorMarker* dummyMarker = nullptr; f32 dummy_D_8037C100[3]; f32 dummy_D_8037C110[3]; f32 dummyDisplacement[3]; @@ -126,13 +136,16 @@ class DummyPlayer { f32 dummy_D_8037D230; u8 dummy_D_8037D234; - u8 dummy_modelSquint; - u8 dummy_modelWink; - u8 dummy_modelMouth1; - u8 dummy_kazooieVisible; - u8 dummy_modelMouth2; + u8 dummy_kazooieLower; + u8 dummy_kazooieFeet; + u8 dummy_kazooieTurbos; + u8 dummy_kazooieUpper; + u8 dummy_kazooieBoots; u8 dummy_D_8037D23A; - f32 dummy_modelEyeBlendUpper; - f32 dummy_modelEyeBlendLower; + f32 dummy_banjoLeftEye; + f32 dummy_banjoRightEye; Transformation dummy_transformation; + s32 dummyBottlesBonus = 0; + uint32_t dummyOwnerId = 0; + BKPlayerColorSet dummyColors = {}; }; \ No newline at end of file diff --git a/src/port/Network/Anchor/FightSync.c b/src/port/Network/Anchor/FightSync.c new file mode 100644 index 000000000..d53fd8551 --- /dev/null +++ b/src/port/Network/Anchor/FightSync.c @@ -0,0 +1,554 @@ +#include "FightSync.h" +#include "port/Network/Anchor/Authority.h" + +#include +#include "functions.h" +#include "variables.h" +#include "prop.h" +#include "fight/fight.h" + +// chfinalboss.c globals. D_803927xx = spell-spawn scratch vectors. +extern f32 D_80392758[3]; +extern f32 D_80392768[3]; +extern f32 D_80392778[3]; +extern f32 __chFinalBossFireballFlightTime; +extern ActorMarker* __chFinalBossFlightPadMarker; +extern u8 __chFinalBossSpellBarrierActive; +extern ActorArray* suBaddieActorArray; +extern u8 sFinalBossJinjoStatueActivated; +// Collision radius for the jinjo-into-Grunty test. +extern f32 func_8033229C(ActorMarker* marker); + +// Set once the ending script takes over (chfinalboss_setBossDefeated). +static u8 sFightNetCinematic = 0; +static u8 sFightNetWasFollower = 0; +// Bit per jinjo statue id (1-4): its jinjo already slammed Grunty. +static u8 sFightNetJinjoSlammed = 0; +static FightWorldSnapshot sFightNetSnap; +static u8 sFightNetCatchupActive = 0; +static u8 sFightNetCatchupSpawned[6]; // statue spawn already queued, indexed by statue id +static u8 sFightNetCatchupPadDone = 0; +static u8 sFightNetCatchupBarrierDone = 0; + +static bool FightSync_IsFollower(void) { + return NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS) && !NetAuthority_IsSelf(NET_ACTIVITY_FINAL_BOSS); +} + +static bool FightSync_IsLiveAuthority(void) { + return NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS) && NetAuthority_IsSelf(NET_ACTIVITY_FINAL_BOSS); +} + +static Actor* FightSync_FindBoss(void) { + Actor* boss = actorArray_findActorFromActorId(ACTOR_38B_GRUNTILDA_FINAL_BOSS); + + if (boss == NULL || !boss->volatile_initialized || boss->despawn_flag) { + return NULL; + } + return boss; +} + +// The jinjo statue bases share one actor id, so find by their statue id (1-4). +static Actor* FightSync_FindStatueBase(s32 statue_id) { + s32 i; + + if (suBaddieActorArray == NULL) { + return NULL; + } + for (i = 0; i < suBaddieActorArray->cnt; i++) { + Actor* actor = &suBaddieActorArray->data[i]; + if (actor->marker == NULL || actor->marker->id != MARKER_27A_JINJO_STATUE_BASE) { + continue; + } + if (actor->actorTypeSpecificField != statue_id || actor->despawn_flag) { + continue; + } + return actor; + } + return NULL; +} + +// Apply a networked egg via getHitByEgg(other == NULL), the counting path. +static void FightSync_ApplyJinjoStatueEgg(s32 statue_id) { + Actor* base = FightSync_FindStatueBase(statue_id); + + if (base != NULL) { + chBossJinjoBase_getHitByEgg(base->marker, NULL); + } +} + +static void FightSync_ReleaseFirstStatueCutscene(void) { + if (sFinalBossJinjoStatueActivated) { + sFinalBossJinjoStatueActivated = 0; + timed_exitStaticCamera(1.0f); + func_80324E38(1.0f, 0); + } +} + +// --- boss lifecycle hooks (called from chfinalboss.c) ----------------------------------------- + +void FightSync_OnBossSpawned(void) { + s32 i; + sFightNetCinematic = 0; + sFightNetWasFollower = 0; + sFightNetJinjoSlammed = 0; + sFightNetCatchupActive = 0; + // Cleared on a fresh boss spawn, not in ApplyWorld, so a repeat snapshot can't re-run catch-up. + sFightNetCatchupPadDone = 0; + sFightNetCatchupBarrierDone = 0; + for (i = 0; i < 6; i++) { + sFightNetCatchupSpawned[i] = 0; + } +} + +void FightSync_OnBossDefeated(void) { + sFightNetCinematic = 1; +} + +// --- authority replication hooks ------------------------------------------------------------- + +void FightSync_OnSpellSpawned(s32 kind) { + if (FightSync_IsLiveAuthority()) { + // Kind 0 (ballistic fireball) carries lead time; each follower re-aims at its own player. + s32 leadMs = (kind == 0) ? (s32)(__chFinalBossFireballFlightTime * 1000.0f) : 0; + FightSync_SendEvent(FIGHT_EV_SPELL, kind, leadMs, D_80392758, D_80392768, D_80392778); + } +} + +void FightSync_OnFlightPadSpawned(void) { + if (FightSync_IsLiveAuthority()) { + FightSync_SendEvent(FIGHT_EV_PAD_SPAWN, 0, 0, NULL, NULL, NULL); + } +} + +void FightSync_OnFlightPadDespawned(void) { + if (FightSync_IsLiveAuthority()) { + FightSync_SendEvent(FIGHT_EV_PAD_DESPAWN, 0, 0, NULL, NULL, NULL); + } +} + +void FightSync_OnBarrierSpawned(void) { + if (FightSync_IsLiveAuthority()) { + FightSync_SendEvent(FIGHT_EV_BARRIER, 0, 0, NULL, NULL, NULL); + } +} + +void FightSync_OnStatueSpawned(s32 statue_id) { + if (FightSync_IsLiveAuthority()) { + FightSync_SendEvent(FIGHT_EV_STATUE_SPAWN, statue_id, 0, NULL, NULL, NULL); + } +} + +void FightSync_OnJinjoSlam(s32 statue_id) { + sFightNetJinjoSlammed |= 1 << statue_id; + if (FightSync_IsLiveAuthority()) { + FightSync_SendEvent(FIGHT_EV_JINJO_ATTACK, statue_id, 0, NULL, NULL, NULL); + } +} + +void FightSync_ReplicateEgg(s32 statue_id, s32 pad_index) { + if (FightSync_IsLiveAuthority()) { + FightSync_SendEvent(FIGHT_EV_EGG_FED, statue_id, pad_index, NULL, NULL, NULL); + } +} + +// --- follower input forwarding ---------------------------------------------------------------- + +bool FightSync_ForwardBossHit(s32 phase) { + if (!FightSync_IsFollower()) { + return false; + } + FightSync_SendEvent(FIGHT_EV_BOSS_HIT, phase, 0, NULL, NULL, NULL); + return true; +} + +bool FightSync_ForwardEgg(s32 statue_id, s32 pad_index) { + if (!FightSync_IsFollower()) { + return false; + } + FightSync_SendEvent(FIGHT_EV_EGG, statue_id, pad_index, NULL, NULL, NULL); + return true; +} + +// --- stream: gather (authority) / apply (follower) --------------------------------------------- + +bool FightSync_GatherUpdate(f32 pos[3], f32* yaw, s32* state, s32* phase, s32* mirror, s32* vuln) { + Actor* boss; + ActorLocal_FinalBoss* local; + + if (sFightNetCinematic) { + return false; + } + boss = FightSync_FindBoss(); + if (boss == NULL) { + return false; + } + local = (ActorLocal_FinalBoss*)&boss->local; + pos[0] = boss->position[0]; + pos[1] = boss->position[1]; + pos[2] = boss->position[2]; + *yaw = boss->yaw; + *state = boss->state; + *phase = local->phase; + *mirror = local->mirror_phase5; + // Phase-2 vulnerability toggle (unkA). + *vuln = local->unkA; + return true; +} + +static void FightSync_ApplyBossState(Actor* this, s32 phase, s32 state) { + ActorLocal_FinalBoss* local = (ActorLocal_FinalBoss*)&this->local; + + // unk44_31 = broomstick motor sfx source. + if (this->unk44_31 != 0 && phase != FINALBOSS_PHASE_1_BROOMSTICK) { + sfxsource_freeSfxsourceByIndex(this->unk44_31); + this->unk44_31 = 0; + } + local->phase = phase; + subaddie_set_state_with_direction(this, state, 0.0001f, 1); + if (state == 9 || state == 0x21 || state == 0x22 || state == 0x2B) { + actor_playAnimationOnce(this); + } else { + actor_loopAnimation(this); + } + chfinalboss_func_80386600(this->marker, (state == 6 || state == 7 || state == 8) ? 1 : 0); + if (phase == FINALBOSS_PHASE_5_JINJONATOR || state == 0x21 || state == 0x22) { + chfinalboss_func_80386628(this->marker, 0); + } else { + chfinalboss_func_80386628(this->marker, 1); + } + if (state == 0x21) { + // State 0x21 = broom shatters (end of phase 4); replay the burst. + chfinalboss_createBroomstickParticles(this->position, ASSET_552_MODEL_BROOMSTICK_PIECE_HEAD, 1); + chfinalboss_createBroomstickParticles(this->position, ASSET_553_MODEL_BROOMSTICK_PIECE_SHORT, 12); + chfinalboss_createBroomstickParticles(this->position, ASSET_554_MODEL_BROOMSTICK_PIECE_LONG, 20); + chfinalboss_createBroomstickParticles(this->position, ASSET_555_MODEL_BROOMSTICK_PIECE_EYE, 2); + } +} + +void FightSync_ApplyUpdate(const f32 pos[3], f32 yaw, s32 state, s32 phase, s32 mirror, s32 vuln) { + Actor* boss; + ActorLocal_FinalBoss* local; + + if (!FightSync_IsFollower() || sFightNetCinematic) { + return; + } + boss = FightSync_FindBoss(); + if (boss == NULL) { + return; + } + sFightNetWasFollower = 1; + local = (ActorLocal_FinalBoss*)&boss->local; + boss->position[0] = pos[0]; + boss->position[1] = pos[1]; + boss->position[2] = pos[2]; + boss->yaw = yaw; + boss->yaw_ideal = yaw; + local->mirror_phase5 = mirror; + // Applied every frame, not just on state change (see FightSync_GatherUpdate). + local->unkA = (u8)vuln; + if (local->phase != (u8)phase || boss->state != state) { + FightSync_ApplyBossState(boss, phase, state); + } +} + +// --- latecomer world snapshot ------------------------------------------------------------------- + +bool FightSync_GatherWorld(FightWorldSnapshot* snap) { + Actor* base; + s32 i; + + if (sFightNetCinematic || !FightSync_IsLiveAuthority() || FightSync_FindBoss() == NULL) { + return false; + } + snap->pad = (__chFinalBossFlightPadMarker != NULL) ? 1 : 0; + snap->barrier = __chFinalBossSpellBarrierActive ? 1 : 0; + for (i = 0; i < 4; i++) { + base = FightSync_FindStatueBase(i + 1); + if (base == NULL) { + snap->statue[i] = 0xFF; + snap->jinjoGone[i] = 0; + } else if (base->state == CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { + snap->statue[i] = 3; + snap->jinjoGone[i] = (sFightNetJinjoSlammed & (1 << (i + 1))) ? 1 : 0; + } else { + snap->statue[i] = base->unk38_31; + snap->jinjoGone[i] = 0; + } + } + snap->jbase = chjinjonatorbase_netGetPads(snap->jpads) ? 1 : 0; + return true; +} + +void FightSync_ApplyWorld(const FightWorldSnapshot* snap) { + s32 i; + + if (!FightSync_IsFollower() || sFightNetCinematic) { + return; + } + sFightNetSnap = *snap; + sFightNetCatchupActive = 1; + // Seed the slammed set from the snapshot so a jinjo that reaches Grunty before catch-up + // rebuilds its statue is removed by the phase-4 guard rather than replaying the attack. + for (i = 0; i < 4; i++) { + if (snap->jinjoGone[i]) { + sFightNetJinjoSlammed |= 1 << (i + 1); + } + } +} + +static void FightSync_CatchupTick(Actor* boss) { + Actor* base; + Actor* jinjo; + u8 pads[4]; + s32 i; + s32 done = 1; + + if (!sFightNetCatchupActive) { + return; + } + + if (sFightNetSnap.pad && !sFightNetCatchupPadDone) { + sFightNetCatchupPadDone = 1; + __spawnQueue_add_1((GenFunction_1)chfinalboss_spawnFlightPad, 0); + } + if (sFightNetSnap.barrier && !sFightNetCatchupBarrierDone) { + sFightNetCatchupBarrierDone = 1; + chfinalboss_spawnSpellBarrier(boss->marker); + } + + for (i = 0; i < 4; i++) { + if (sFightNetSnap.statue[i] == 0xFF) { + continue; + } + base = FightSync_FindStatueBase(i + 1); + if (base == NULL) { + if (!sFightNetCatchupSpawned[i + 1]) { + sFightNetCatchupSpawned[i + 1] = 1; + chfinalboss_spawnStatue(i + 1); + } + done = 0; + continue; + } + if (base->state != CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO && base->unk38_31 < sFightNetSnap.statue[i]) { + chBossJinjoBase_getHitByEgg(base->marker, NULL); + done = 0; + continue; + } + if (sFightNetSnap.jinjoGone[i]) { + jinjo = actorArray_findActorFromActorId(ACTOR_3A4_BOSS_JINJO_BASE_IDX + i + 1); + if (jinjo != NULL) { + sFightNetJinjoSlammed |= 1 << (i + 1); + marker_despawn(jinjo->marker); + sFightNetSnap.jinjoGone[i] = 0; + } else if (base->state == CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { + done = 0; + } + } + } + + if (sFightNetSnap.jbase) { + if (!chjinjonatorbase_netGetPads(pads)) { + if (!sFightNetCatchupSpawned[5]) { + sFightNetCatchupSpawned[5] = 1; + chfinalboss_spawnStatue(BOSSJINJO_5_JINJONATOR); + } + done = 0; + } else { + for (i = 0; i < 4; i++) { + if (pads[i] > sFightNetSnap.jpads[i]) { + chjinjonatorbase_netApplyEgg(i); + done = 0; + break; + } + } + } + } + + if (done) { + sFightNetCatchupActive = 0; + } +} + +bool FightSync_BossFollowerTick(void* bossPtr) { + Actor* boss = (Actor*)bossPtr; + + if (!FightSync_IsFollower() || sFightNetCinematic) { + return false; + } + FightSync_CatchupTick(boss); + + // Detect a jinjo-into-Grunty collision locally (display-only) ahead of the authority's slam event. + if (((ActorLocal_FinalBoss*)&boss->local)->phase == FINALBOSS_PHASE_4_JINJOS) { + ActorMarker* jinjoMarker = chfinalboss_findCollidingJinjo(boss, func_8033229C(boss->marker)); + if (jinjoMarker != NULL) { + Actor* jinjo = marker_getActor(jinjoMarker); + s32 sid = (jinjo != NULL) ? jinjo->actorTypeSpecificField : 0; + if (sid >= BOSSJINJO_1_ORANGE && sid <= BOSSJINJO_4_YELLOW && (sFightNetJinjoSlammed & (1 << sid))) { + marker_despawn(jinjoMarker); + } else { + if (sid >= BOSSJINJO_1_ORANGE && sid <= BOSSJINJO_4_YELLOW) { + sFightNetJinjoSlammed |= 1 << sid; + } + chbossjinjo_attack(jinjoMarker); + FightSync_ReleaseFirstStatueCutscene(); + } + } + } + + switch (boss->state) { + case 2: + case 3: + case 4: + case 6: + case 7: + case 8: + case 14: + case 21: + case 28: + chfinalboss_spawnBroomstickGlowParticles(boss); + break; + } + return true; +} + +// --- one-shot event dispatch -------------------------------------------------------------------- + +void FightSync_ApplyEvent(s32 ev, s32 a, s32 b, const f32 v0[3], const f32 v1[3], const f32 v2[3]) { + Actor* boss = FightSync_FindBoss(); + s32 i; + + switch (ev) { + case FIGHT_EV_SPELL: + if (!FightSync_IsFollower() || v0 == NULL) { + return; + } + // Kind 0 (ballistic fireball) is re-aimed at this client's own player. + if (a == 0) { + if (boss != NULL) { + f32 src[3]; + f32 leadTime = (b > 0) ? (b / 1000.0f) : 1.3f; + src[0] = boss->position[0]; + src[1] = boss->position[1]; + src[2] = boss->position[2]; + chfinalboss_throwObject(boss->marker, src, leadTime, 0); + } + break; + } + // Spawn helpers read these globals; set them before queueing. + for (i = 0; i < 3; i++) { + D_80392758[i] = v0[i]; + D_80392768[i] = v1[i]; + D_80392778[i] = v2[i]; + } + if (a == 2) { + __spawnQueue_add_1((GenFunction_1)chfinalboss_func_80386EC0, 0); + } else if (a == 1) { + __spawnQueue_add_1((GenFunction_1)chfinalboss_func_80387074, 0); + } + break; + + case FIGHT_EV_PAD_SPAWN: + if (!FightSync_IsFollower()) { + return; + } + __spawnQueue_add_1((GenFunction_1)chfinalboss_spawnFlightPad, 0); + break; + + case FIGHT_EV_PAD_DESPAWN: + if (!FightSync_IsFollower()) { + return; + } + chfinalboss_despawnFlightPad(); + break; + + case FIGHT_EV_BARRIER: + if (!FightSync_IsFollower() || boss == NULL) { + return; + } + chfinalboss_spawnSpellBarrier(boss->marker); + break; + + case FIGHT_EV_STATUE_SPAWN: + if (!FightSync_IsFollower() || a < BOSSJINJO_1_ORANGE || a > BOSSJINJO_5_JINJONATOR) { + return; + } + chfinalboss_spawnStatue(a); + break; + + case FIGHT_EV_EGG_FED: + if (!FightSync_IsFollower()) { + return; + } + if (a == BOSSJINJO_5_JINJONATOR) { + chjinjonatorbase_netApplyEgg(b); + } else { + FightSync_ApplyJinjoStatueEgg(a); + } + break; + + case FIGHT_EV_JINJO_ATTACK: { + Actor* jinjo; + if (!FightSync_IsFollower() || a < BOSSJINJO_1_ORANGE || a > BOSSJINJO_4_YELLOW) { + return; + } + sFightNetJinjoSlammed |= 1 << a; + jinjo = actorArray_findActorFromActorId(ACTOR_3A4_BOSS_JINJO_BASE_IDX + a); + if (jinjo != NULL) { + chbossjinjo_attack(jinjo->marker); + } + FightSync_ReleaseFirstStatueCutscene(); + break; + } + + case FIGHT_EV_BOSS_HIT: + if (!FightSync_IsLiveAuthority() || boss == NULL) { + return; + } + if (getGameMode() == GAME_MODE_4_PAUSED) { + return; + } + if (((ActorLocal_FinalBoss*)&boss->local)->phase != (u8)a) { + return; + } + chfinalboss_collisionPassive(boss->marker, NULL); + break; + + case FIGHT_EV_EGG: + if (!FightSync_IsLiveAuthority()) { + return; + } + if (getGameMode() == GAME_MODE_4_PAUSED) { + return; + } + if (a == BOSSJINJO_5_JINJONATOR) { + chjinjonatorbase_netApplyEgg(b); + } else { + if (sFinalBossJinjoStatueActivated != 0) { + return; + } + FightSync_ApplyJinjoStatueEgg(a); + } + break; + } +} + +void FightSync_OnAuthorityChanged(void) { + Actor* boss; + ActorLocal_FinalBoss* local; + + FightSyncSeq_Reset(); + if (sFightNetCinematic) { + return; + } + boss = FightSync_FindBoss(); + if (boss == NULL) { + return; + } + if (sFightNetWasFollower && FightSync_IsLiveAuthority()) { + sFightNetWasFollower = 0; + local = (ActorLocal_FinalBoss*)&boss->local; + if (local->phase != FINALBOSS_PHASE_0_INTRO) { + chfinalboss_setPhase(boss->marker, local->phase); + } + } +} diff --git a/src/port/Network/Anchor/FightSync.h b/src/port/Network/Anchor/FightSync.h new file mode 100644 index 000000000..2c6127966 --- /dev/null +++ b/src/port/Network/Anchor/FightSync.h @@ -0,0 +1,98 @@ +#pragma once +#include +#include + +// Final Grunty fight sync (Anchor). +// +// First client in the fight map with the boss spawned claims NET_ACTIVITY_FINAL_BOSS and runs +// the fight; everyone else mirrors it. +// +// FIGHT_UPDATE: authority -> map, per-frame transform/state stream, sequence-guarded. +// FIGHT_STATE: authority -> joining client, world catch-up snapshot. +// FIGHT_EVENT: one-shot; authority -> map for spells/pads/barrier/statues/eggs/jinjo +// attacks, follower -> authority for boss hits and statue eggs. + +// FIGHT_EVENT ids ('ev' field). +enum FightSyncEvent { + // authority -> followers + FIGHT_EV_SPELL = 0, // a = kind (0 fireball, 1 final fireball, 2 green blast); p/v/w = spawn vectors + FIGHT_EV_PAD_SPAWN, // flight pad appears (end of phase 2) + FIGHT_EV_PAD_DESPAWN, // flight pad removed (during phase 3 barrier cast) + FIGHT_EV_BARRIER, // spell barrier spawns on Grunty + FIGHT_EV_STATUE_SPAWN, // a = ch_bossjinjo_e statue id (1-4 jinjos, 5 jinjonator) + FIGHT_EV_EGG_FED, // a = statue id (1-4 jinjos, 5 jinjonator), b = jinjonator pad index + FIGHT_EV_JINJO_ATTACK, // a = jinjo statue id whose jinjo just slammed Grunty + // followers -> authority + FIGHT_EV_BOSS_HIT, // a = the phase the hitting client believed Grunty was in + FIGHT_EV_EGG, // a = statue id, b = jinjonator pad index +}; + +// FIGHT_STATE catch-up snapshot for a client joining mid-fight. +typedef struct FightWorldSnapshot { + uint8_t pad; // flight pad present + uint8_t barrier; // spell barrier up on Grunty + uint8_t statue[4]; // jinjo statue bases (ids 1-4): 0xFF absent, else eggs fed (3 = broken) + uint8_t jinjoGone[4]; // statue broken and its jinjo has already slammed into Grunty + uint8_t jbase; // jinjonator pedestal present + uint8_t jpads[4]; // remaining eggs per jinjonator pedestal pad +} FightWorldSnapshot; + +#ifdef __cplusplus +extern "C" { +#endif + +// --- hooks called by the FINALE actors (implemented in FightSync.c) -------------------- + +// Boss lifecycle: spawn resets sync state; defeat drops every client to local simulation. +void FightSync_OnBossSpawned(void); +void FightSync_OnBossDefeated(void); + +// True = a remote authority drives this boss; chfinalboss_update should skip its brain. +bool FightSync_BossFollowerTick(void* boss /* Actor* */); + +// Forward follower input to the authority; true = handled remotely, skip local apply. +bool FightSync_ForwardBossHit(int32_t phase); +bool FightSync_ForwardEgg(int32_t statue_id, int32_t pad_index); + +// Authority world replication (acts only as the live authority). +void FightSync_ReplicateEgg(int32_t statue_id, int32_t pad_index); +void FightSync_OnSpellSpawned(int32_t kind); +void FightSync_OnFlightPadSpawned(void); +void FightSync_OnFlightPadDespawned(void); +void FightSync_OnBarrierSpawned(void); +void FightSync_OnStatueSpawned(int32_t statue_id); +void FightSync_OnJinjoSlam(int32_t statue_id); + +// --- FINALE entry points used by FightSync.c (implemented in the decomp actors) -------- + +void chjinjonatorbase_netApplyEgg(int32_t pad_index); +bool chjinjonatorbase_netGetPads(uint8_t pads[4]); + +// --- C -> network (bridges implemented in the packet .cpp files) ----------------------- + +void FightSync_SendUpdate(const float pos[3], float yaw, int32_t state, int32_t phase, int32_t mirror, int32_t vuln); +// v0/v1/v2 may be NULL for events that carry no vectors. +void FightSync_SendEvent(int32_t ev, int32_t a, int32_t b, const float v0[3], const float v1[3], const float v2[3]); +void FightSync_SendSnapshot(uint32_t clientId); + +uint32_t FightSyncSeq_Next(void); +bool FightSyncSeq_Accept(uint32_t seq); +void FightSyncSeq_Reset(void); + +// --- network -> sync layer (implemented in FightSync.c) -------------------------------- + +void FightSync_OnAuthorityChanged(void); + +// Fill the stream fields from the live boss; false if there's no boss to stream. +bool FightSync_GatherUpdate(float pos[3], float* yaw, int32_t* state, int32_t* phase, int32_t* mirror, int32_t* vuln); + +void FightSync_ApplyUpdate(const float pos[3], float yaw, int32_t state, int32_t phase, int32_t mirror, int32_t vuln); +void FightSync_ApplyEvent(int32_t ev, int32_t a, int32_t b, const float v0[3], const float v1[3], const float v2[3]); + +// Gather on the authority (false = nothing to send) / apply on a joining follower. +bool FightSync_GatherWorld(FightWorldSnapshot* snap); +void FightSync_ApplyWorld(const FightWorldSnapshot* snap); + +#ifdef __cplusplus +} +#endif diff --git a/src/port/Network/Anchor/HookHandlers.cpp b/src/port/Network/Anchor/HookHandlers.cpp index 884a69486..6963775f7 100644 --- a/src/port/Network/Anchor/HookHandlers.cpp +++ b/src/port/Network/Anchor/HookHandlers.cpp @@ -1,17 +1,37 @@ #include "Anchor.h" #include "Authority.h" #include "VileSync.h" +#include "FightSync.h" #include //#include "soh/frame_interpolation.h" #include "port/Engine.h" +#include "port/UI/Notification.h" +#include "port/Patches/Patches.h" +#include +#include "functions.h" extern "C" { #include "variables.h" -#include "functions.h" float OTRGetDimensionFromLeftEdge(float v); float OTRGetDimensionFromRightEdge(float v); -s32 chvile_netGetAnimMode(Actor* actor); +s32 chMrVile_netGetAnimMode(Actor* actor); +void port_jiggySpawn_remove(int32_t jiggyId); +int32_t port_mapFlag_wasSetRemotely(int32_t index); +bool __chSmBottles_isAnySpiralMountainAbilityLearned(void); +} + +extern "C" void port_fpTwinkly_release(void) { + NetAuthority_Release(NET_ACTIVITY_FP_TWINKLY); +} + +s32 Anchor_LevelOfMap(s32 map); + +// Every listener below that alters vanilla behaviour is wrapped in this. Presence-only rooms +// (the global room, or sync turned off) must play exactly like single player. +static bool Anchor_WorldSyncActive() { + Anchor* anchor = Anchor::GetInstance(); + return anchor != nullptr && anchor->IsWorldSyncActive(); } // True when a remote client owns the Mr. Vile minigame (our local logic must follow). @@ -21,8 +41,7 @@ static bool Anchor_IsVileFollower() { // True when we are the live, connected authority for the Mr. Vile minigame. static bool Anchor_IsVileAuthority() { - return Anchor::GetInstance()->isConnected && NetAuthority_IsClaimed(NET_ACTIVITY_VILE_MINIGAME) && - NetAuthority_IsSelf(NET_ACTIVITY_VILE_MINIGAME); + return NetAuthority_IsClaimed(NET_ACTIVITY_VILE_MINIGAME) && NetAuthority_IsSelf(NET_ACTIVITY_VILE_MINIGAME); } // Authority-side per-frame work: stream Mr. Vile's transform and broadcast the periodic @@ -37,7 +56,7 @@ static void Anchor_UpdateVileSync() { Actor* vile = actorArray_findClosestActorFromActorId(origin, ACTOR_13A_MR_VILE, -1, &dist); if (vile != nullptr) { Anchor::GetInstance()->SendPacket_VileUpdate(vile->position, vile->pitch, vile->yaw, vile->roll, - (u8)chvile_netGetAnimMode(vile)); + (u8)chMrVile_netGetAnimMode(vile)); } static u32 sSnapshotTimer = 0; @@ -47,6 +66,103 @@ static void Anchor_UpdateVileSync() { } } +static void Anchor_UpdateFightSync() { + auto* anchor = Anchor::GetInstance(); + if (!Anchor_WorldSyncActive() || !anchor->IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { + return; + } + + f32 pos[3]; + f32 yaw; + s32 state, phase, mirror, vuln; + if (!FightSync_GatherUpdate(pos, &yaw, &state, &phase, &mirror, &vuln)) { + return; + } + + if (!NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS)) { + NetAuthority_Claim(NET_ACTIVITY_FINAL_BOSS); + } + if (NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS) && NetAuthority_IsSelf(NET_ACTIVITY_FINAL_BOSS)) { + anchor->SendPacket_FightUpdate(pos, yaw, state, phase, mirror, vuln); + } +} + +static bool Anchor_ShouldBroadcastVolatileFlag(s32 index) { + static const std::unordered_set syncList = { + VOLATILE_FLAG_B6_WITCH_SWITCH_PRESSED_MM, VOLATILE_FLAG_B7_WITCH_SWITCH_PRESSED_MMM, + VOLATILE_FLAG_B8_WITCH_SWITCH_PRESSED_TTC, VOLATILE_FLAG_B9_WITCH_SWITCH_PRESSED_RBB, + VOLATILE_FLAG_BA_WITCH_SWITCH_PRESSED_CCW, VOLATILE_FLAG_BB_WITCH_SWITCH_PRESSED_FP, + VOLATILE_FLAG_BC_WITCH_SWITCH_PRESSED_CC, VOLATILE_FLAG_BD_WITCH_SWITCH_PRESSED_BGS, + VOLATILE_FLAG_BE_WITCH_SWITCH_PRESSED_GV, + }; + return syncList.contains(index); +} + +bool Anchor_ScopedFlagExcluded(s32 space, s32 index) { + static const std::unordered_set excluded = { + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_5_TTC_UNKNOWN, // TTC sandcastle drain + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, // FP xmas-tree ice shatter + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_30_RBB_UNKNOWN, // RBB anchor/Snorkel chain cutscene + // GV water-pyramid rise: reapplied live from JIGGY_42 in water_pyramidrot.c. + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_6_GV_UNKNOWN, + (ANCHOR_FLAGSPACE_MAP_SPECIFIC << 16) | MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1C_MM_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1D_TTC_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1E_CC_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1F_BGS_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_20_FP_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_21_GV_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_22_MMM_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_23_RBB_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_24_CCW_OPEN, + (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_3F_LAIR_GRUNTY_DOOR_OPEN, + }; + if (excluded.contains((space << 16) | index)) { + return true; + } + // BGS jiggy-switch timers (walkway=3, maze=0xC): kept local. + if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_D_BGS_BUBBLEGLOOP_SWAMP && + (index == 3 || index == 0xC)) { + return true; + } + if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_7_TTC_TREASURE_TROVE_COVE && + index <= TTC_SPECIFIC_FLAG_3_BLUBBER_SHOW_JIGGY_SPAWNED_TEXT_FLAG) { + return true; + } + // FP xmas tree star minigame (flags 2/3): per-player, kept local; result syncs via ANCHOR_PUZZLE_FP_TREE_ICE. + if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK && + (index == 2 || index == 3)) { + return true; + } + // FP bear cubs' presents-received flags: kept local; ANCHOR_PUZZLE_FP_PRESENTS syncs the result. + if (space == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC && + (s32)map_getLevel(gsworld_getMap()) == (s32)LEVEL_5_FREEZEEZY_PEAK && + (index == LEVEL_FLAG_11_FP_UNKNOWN || index == LEVEL_FLAG_12_FP_UNKNOWN || index == LEVEL_FLAG_13_FP_UNKNOWN)) { + return true; + } + // SM map flags are entirely Bottles-tutorial choreography; + // syncing any of them runs someone else's state machine. + if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) { + return true; + } + return false; +} + +static bool Anchor_ShouldSyncItemCount(s32 item, const RoomState& room) { + switch (item) { + // Progress counters, not consumables; the caller already gates on syncItemsAndFlags. + case ITEM_1C_MUMBO_TOKEN: + case ITEM_26_JIGGY_TOTAL: + return true; + case ITEM_D_EGGS: + case ITEM_F_RED_FEATHER: + case ITEM_10_GOLD_FEATHER: + return room.shareConsumables != 0; + default: + return false; + } +} + void Anchor::RegisterHooks() { // #region Hooks that are required for basic Anchor functionality @@ -68,25 +184,88 @@ void Anchor::RegisterHooks() { Anchor::GetInstance()->ClearDummies(); Anchor::GetInstance()->PopulateDummies((GameMap)ev->nextMap); Authority_OnSelfMapChanged(ev->nextMap); + s32 prevLevel = Anchor_LevelOfMap((s32)ev->prevMap); + if (prevLevel == 0 || prevLevel != Anchor_LevelOfMap((s32)ev->nextMap)) { + Anchor::GetInstance()->SweepUnoccupiedLevelState((GameMap)ev->nextMap); + } Anchor::GetInstance()->SendPacket_MapLoad((GameMap)ev->nextMap, ev->exit); // Anchor::GetInstance()->SendPacket_PlayerUpdate(true); + + auto* anchor = Anchor::GetInstance(); + if (Anchor_WorldSyncActive() && ev->nextMap != MAP_91_FILE_SELECT && ev->nextMap != MAP_1E_CS_START_NINTENDO && + ev->nextMap != MAP_1F_CS_START_RAREWARE) { + anchor->SendPacket_RequestScopedState((GameMap)ev->nextMap); + + s32 enteredFlag = -1; + switch (ev->nextMap) { + case MAP_2_MM_MUMBOS_MOUNTAIN: + enteredFlag = FILEPROG_B0_HAS_ENTERED_MM; + break; + case MAP_7_TTC_TREASURE_TROVE_COVE: + enteredFlag = FILEPROG_B2_HAS_ENTERED_TTC; + break; + case MAP_B_CC_CLANKERS_CAVERN: + enteredFlag = FILEPROG_B8_HAS_ENTERED_CC; + break; + case MAP_D_BGS_BUBBLEGLOOP_SWAMP: + enteredFlag = FILEPROG_B1_HAS_ENTERED_BGS; + break; + case MAP_12_GV_GOBIS_VALLEY: + enteredFlag = FILEPROG_B3_HAS_ENTERED_GV; + break; + case MAP_1B_MMM_MAD_MONSTER_MANSION: + enteredFlag = FILEPROG_B7_HAS_ENTERED_MMM; + break; + case MAP_27_FP_FREEZEEZY_PEAK: + enteredFlag = FILEPROG_B6_HAS_ENTERED_FP; + break; + case MAP_31_RBB_RUSTY_BUCKET_BAY: + enteredFlag = FILEPROG_B4_HAS_ENTERED_RBB; + break; + case MAP_40_CCW_HUB: + enteredFlag = FILEPROG_B5_HAS_ENTERED_CCW; + break; + default: + break; + } + if (enteredFlag >= 0 && fileProgressFlag_get((enum file_progress_e)enteredFlag)) { + anchor->SendPacket_SetFlag((u8)ANCHOR_FLAGSPACE_FILE_PROGRESS, (s16)enteredFlag); + } + } }); COND_HOOK(OnReset, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { Anchor::GetInstance()->SendPacket_MapLoad((GameMap)getDefaultBootMap(), gsworld_getExit()); }); + COND_HOOK(OnGameLoad, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + anchor->hasCheckedRandoCompat = false; + anchor->reloadMapOnTeamState = false; + anchor->SendPacket_RequestTeamState(true); + }); + COND_HOOK(OnPlayerDraw, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { auto drawEv = reinterpret_cast(event); Anchor::GetInstance()->DrawDummies(reinterpret_cast(drawEv)); }); COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_HIGH, isConnected, [](IEvent* event) { - Anchor::GetInstance()->SendPacket_PlayerUpdate(); - Anchor::GetInstance()->ProcessIncomingPacketQueue(); - Anchor::GetInstance()->RefreshClientActors(); - Anchor::GetInstance()->UpdateDummies(); + auto* anchor = Anchor::GetInstance(); + anchor->SendPacket_PlayerUpdate(); + anchor->ProcessIncomingPacketQueue(); + anchor->RefreshClientActors(); + anchor->UpdateDummies(); Anchor_UpdateVileSync(); + Anchor_UpdateFightSync(); + + if (Anchor_WorldSyncActive() && anchor->IsSaveLoaded()) { + anchor->FlushPendingJiggySpawns(); + if (!anchor->hasCheckedRandoCompat) { + anchor->CheckRandoRoomCompatibility(); + anchor->hasCheckedRandoCompat = true; + } + } }); COND_HOOK(OnPlayerTransformChange, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { @@ -100,14 +279,12 @@ void Anchor::RegisterHooks() { // returning to idle (or the player declining) releases it. COND_HOOK(OnVileGameStateChange, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { auto ev = reinterpret_cast(event); - if (!Anchor::GetInstance()->isConnected || gsworld_getMap() != MAP_10_BGS_MR_VILE) { + if (!Anchor_WorldSyncActive() || gsworld_getMap() != MAP_10_BGS_MR_VILE) { return; } if (ev->state >= 2) { NetAuthority_Claim(NET_ACTIVITY_VILE_MINIGAME); - // Push the transition immediately (round start, round end with its result - // jingle) instead of waiting for the next periodic snapshot. Gather rejects - // the non-broadcast states, so this is a no-op for dialog transitions. + // Push round start/end immediately rather than waiting for the periodic snapshot. if (Anchor_IsVileAuthority()) { Anchor::GetInstance()->SendPacket_VileGameState(); } @@ -133,6 +310,78 @@ void Anchor::RegisterHooks() { }); // Followers: suppress local random logic; network state drives these instead. + COND_VB_SHOULD(VB_CCW_FLOWER_REMOTE_GROW, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + s32 stageFlag = va_arg(args, s32); + *should = fileProgressFlag_get((enum file_progress_e)stageFlag) != 0; + } + }); + + COND_VB_SHOULD(VB_CC_RINGS_SNAP_WATER, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + *should = false; + } + }); + + // Vanilla despawns the CCW podium until its switch is pressed, and only rebuilds it when the cube + // re-streams. Keep the actor alive (hidden) instead, so a teammate's press reveals it in place. + COND_VB_SHOULD(VB_CCW_PODIUM_DESPAWN, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + *should = false; + } + }); + + COND_VB_SHOULD(VB_JIGSAW_PICTURE_RESYNC, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + *should = true; + } + }); + + // Lair door remote-open: Door of Grunty's open flag (0xE2) is already set on arrival; key off + // visual state (fully open == 0x1B) instead. Other lair doors stay flag-based. + COND_VB_SHOULD(VB_LEVELDOOR_REMOTE_OPEN_DONE, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + s32 doorActorId = va_arg(args, s32); + s32 doorState = va_arg(args, s32); + if (doorActorId == ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE) { + *should = (doorState == 0x1B); + } + } + }); + + COND_VB_SHOULD(VB_FP_TWINKLY_START, EVENT_PRIORITY_NORMAL, isConnected, { + if (NetAuthority_IsClaimed(NET_ACTIVITY_FP_TWINKLY) && !NetAuthority_IsSelf(NET_ACTIVITY_FP_TWINKLY)) { + *should = false; + } else { + NetAuthority_Claim(NET_ACTIVITY_FP_TWINKLY); + } + }); + + COND_VB_SHOULD(VB_DOOR_OPEN_CAMERA, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + s32 doorId = va_arg(args, s32); + switch (doorId) { + case GV_DOOR_CAM_SUN: + *should = !port_mapFlag_wasSetRemotely(3); + break; + case GV_DOOR_CAM_STAR: + *should = !port_mapFlag_wasSetRemotely(5); + break; + case GV_DOOR_CAM_KAZOOIE: + *should = !port_mapFlag_wasSetRemotely(6); + break; + case GV_DOOR_CAM_JINXY: + *should = !(port_mapFlag_wasSetRemotely(0) && port_mapFlag_wasSetRemotely(1)); + break; + case MMM_DOOR_CAM_CHURCH: + *should = !port_mapFlag_wasSetRemotely(0); // MMM_SPECIFIC_FLAG_0_UNKNOWN + break; + default: + break; + } + } + }); + COND_VB_SHOULD(VB_VILE_YUMBLIE_EMERGE, EVENT_PRIORITY_NORMAL, true, { if (Anchor_IsVileFollower()) { *should = false; @@ -188,29 +437,139 @@ void Anchor::RegisterHooks() { Anchor::GetInstance()->OnActorDestroyed(ev->actor); }); + // #region Flag sync + + COND_HOOK(OnGameFlagSet, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { + return; + } + auto ev = reinterpret_cast(event); + for (s32 i = 0; i < ev->length; i++) { + s32 index = ev->index + i; + if (ev->flagSpace == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC) { + if (Anchor_ScopedFlagExcluded(ev->flagSpace, index)) { + continue; + } + anchor->SendPacket_ScopedFlag((u8)ev->flagSpace, (s16)index, + (u8)(levelSpecificFlags_get(index) ? 1 : 0)); + continue; + } + if (ev->flagSpace == ANCHOR_FLAGSPACE_MAP_SPECIFIC) { + if (Anchor_ScopedFlagExcluded(ev->flagSpace, index)) { + continue; + } + anchor->SendPacket_ScopedFlag((u8)ev->flagSpace, (s16)index, (u8)(mapSpecificFlags_get(index) ? 1 : 0)); + continue; + } + s32 bit; + if (ev->flagSpace == ANCHOR_FLAGSPACE_VOLATILE) { + if (!Anchor_ShouldBroadcastVolatileFlag(index)) { + continue; + } + bit = volatileFlag_get((enum volatile_flags_e)index); + } else { + bit = fileProgressFlag_get((enum file_progress_e)index); + } + if (bit) { + anchor->SendPacket_SetFlag((u8)ev->flagSpace, (s16)index); + } else { + anchor->SendPacket_UnsetFlag((u8)ev->flagSpace, (s16)index); + } + } + }); + + COND_HOOK(OnItemCountChanged, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { + return; + } + auto ev = reinterpret_cast(event); + if (Anchor_ShouldSyncItemCount(ev->item, anchor->roomState)) { + anchor->SendPacket_SetItemCount((s16)ev->item, ev->count); + } + }); + + COND_HOOK(OnAbilityLearned, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { + return; + } + auto ev = reinterpret_cast(event); + anchor->SendPacket_SetAbility((s16)ev->move, (u8)ev->value); + }); + + COND_HOOK(OnCollectibleCollected, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { + return; + } + auto ev = reinterpret_cast(event); + anchor->SendPacket_CollectItem((u8)ev->kind, (s32)ev->id); + }); + + COND_HOOK(OnRandoCheckObtained, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { + return; + } + auto ev = reinterpret_cast(event); + anchor->SendPacket_SetCheckStatus((s32)ev->randoCheckId, (s32)ev->map); + }); + + COND_HOOK(OnJiggySpawned, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto* anchor = Anchor::GetInstance(); + if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { + return; + } + auto ev = reinterpret_cast(event); + anchor->SendPacket_SpawnJiggy((s16)ev->jiggyId, ev->x, ev->y, ev->z); + }); + + COND_HOOK(OnHoneycombDropSpawn, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + auto ev = reinterpret_cast(event); + Anchor::GetInstance()->SendPacket_SpawnHoneycomb((s16)ev->honeycombId, ev->bundleId, ev->x, ev->y, ev->z); + }); + + // SM intro Bottles: the tutorial offer is first-answer-wins for the team. + COND_VB_SHOULD(VB_SM_TUTORIAL_CHOICE_OPEN, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive()) { + // By level, not map: a romhack's Spiral Mountain may be a different map id. + if (__chSmBottles_isAnySpiralMountainAbilityLearned() || + (port_puzzleStep_getForLevel(LEVEL_B_SPIRAL_MOUNTAIN, ANCHOR_PUZZLE_SM_TUTORIAL) & 1)) { + *should = false; + } else if (NetAuthority_IsClaimed(NET_ACTIVITY_SM_TUTORIAL) && + !NetAuthority_IsSelf(NET_ACTIVITY_SM_TUTORIAL)) { + *should = false; + } else { + NetAuthority_Claim(NET_ACTIVITY_SM_TUTORIAL); + } + } + }); + + // Ability molehills wake up only after the tutorial choice exists: the offer was + // answered (synced bit) or a move is already known (covers skip-tutorial saves). + COND_VB_SHOULD(VB_SM_MOLEHILL_ACTIVE, EVENT_PRIORITY_NORMAL, isConnected, { + if (Anchor_WorldSyncActive() && !__chSmBottles_isAnySpiralMountainAbilityLearned() && + !(port_puzzleStep_getForLevel(LEVEL_B_SPIRAL_MOUNTAIN, ANCHOR_PUZZLE_SM_TUTORIAL) & 1)) { + *should = false; + } + }); + + COND_HOOK(OnTimedJiggyExpired, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { + if (!Anchor_WorldSyncActive()) { + return; + } + auto ev = reinterpret_cast(event); + port_jiggySpawn_remove(ev->jiggyId); + }); + + COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_NORMAL, isConnected, + [](IEvent* event) { Anchor::GetInstance()->SendPacket_UpdateTeamState(); }); + + // #endregion + // COND_HOOK(OnPlayerSfx, isConnected, [&](u16 sfxId) { SendPacket_PlayerSfx(sfxId); }); - // COND_HOOK(OnOcarinaNote, isConnected, - // [&](uint8_t note, float modulator, int8_t bend) { SendPacket_OcarinaSfx(note, modulator, bend); }); - // - // COND_HOOK(OnLoadGame, isConnected, [&](s16 fileNum) { justLoadedSave = true; }); - // - // COND_HOOK(OnSaveFile, isConnected, [&](s16 fileNum, int sectionID) { - // if (sectionID == 0) { - // SendPacket_UpdateTeamState(); - // } - // }); - // - // COND_HOOK(OnFlagSet, isConnected, - // [&](s16 flagType, s16 flag) { SendPacket_SetFlag(SCENE_ID_MAX, flagType, flag); }); - // - // COND_HOOK(OnFlagUnset, isConnected, - // [&](s16 flagType, s16 flag) { SendPacket_UnsetFlag(SCENE_ID_MAX, flagType, flag); }); - // - // COND_HOOK(OnSceneFlagSet, isConnected, - // [&](s16 sceneNum, s16 flagType, s16 flag) { SendPacket_SetFlag(sceneNum, flagType, flag); }); - // - // COND_HOOK(OnSceneFlagUnset, isConnected, - // [&](s16 sceneNum, s16 flagType, s16 flag) { SendPacket_UnsetFlag(sceneNum, flagType, flag); }); // // COND_HOOK(OnRandoSetCheckStatus, isConnected, [&](RandomizerCheck rc, RandomizerCheckStatus status) { // if (!isHandlingUpdateTeamState) { diff --git a/src/port/Network/Anchor/JigsawPedestal.cpp b/src/port/Network/Anchor/JigsawPedestal.cpp new file mode 100644 index 000000000..7341efcbb --- /dev/null +++ b/src/port/Network/Anchor/JigsawPedestal.cpp @@ -0,0 +1,93 @@ +#include "port/Network/Anchor/JigsawPedestal.h" +#include "port/Network/Anchor/Anchor.h" +#include "functions.h" +#include +#include + +static std::unordered_map sPedestalOwner; + +static bool JigsawPedestal_SyncActive() { + Anchor* anchor = Anchor::GetInstance(); + return anchor != nullptr && anchor->IsWorldSyncActive(); +} + +int32_t port_jigsawPedestal_tryClaim(int32_t id) { + Anchor* anchor = Anchor::GetInstance(); + if (!JigsawPedestal_SyncActive()) { + return 1; + } + auto it = sPedestalOwner.find(id); + if (it != sPedestalOwner.end() && it->second != anchor->ownClientId) { + return 0; + } + sPedestalOwner[id] = anchor->ownClientId; + anchor->SendPacket_PedestalOwner(id, true); + return 1; +} + +int32_t port_jigsawPedestal_isSelf(int32_t id) { + Anchor* anchor = Anchor::GetInstance(); + if (!JigsawPedestal_SyncActive()) { + return 1; + } + auto it = sPedestalOwner.find(id); + return (it == sPedestalOwner.end() || it->second == anchor->ownClientId) ? 1 : 0; +} + +void port_jigsawPedestal_release(int32_t id) { + Anchor* anchor = Anchor::GetInstance(); + if (!JigsawPedestal_SyncActive()) { + return; + } + // Keep a finished picture's claim until we leave the map: vanilla already refuses to let anyone + // step back on it, and holding covers a teammate whose completion bits are still in flight. + if (jigsawPicture_isJigsawPictureComplete(id)) { + return; + } + auto it = sPedestalOwner.find(id); + if (it != sPedestalOwner.end() && it->second == anchor->ownClientId) { + sPedestalOwner.erase(it); + anchor->SendPacket_PedestalOwner(id, false); + } +} + +void JigsawPedestal_ApplyRemote(int32_t id, uint32_t clientId, bool claimed) { + auto it = sPedestalOwner.find(id); + if (claimed) { + // Simultaneous-claim tie-break: lowest clientId wins. + if (it == sPedestalOwner.end() || clientId < it->second) { + sPedestalOwner[id] = clientId; + } + } else if (it != sPedestalOwner.end() && it->second == clientId) { + sPedestalOwner.erase(it); + } +} + +void JigsawPedestal_ClearClient(uint32_t clientId) { + for (auto it = sPedestalOwner.begin(); it != sPedestalOwner.end();) { + it = (it->second == clientId) ? sPedestalOwner.erase(it) : std::next(it); + } +} + +void JigsawPedestal_ReleaseAllSelf() { + Anchor* anchor = Anchor::GetInstance(); + if (anchor == nullptr) { + return; + } + std::vector mine; + for (auto& [id, owner] : sPedestalOwner) { + if (owner == anchor->ownClientId) { + mine.push_back(id); + } + } + for (int32_t id : mine) { + sPedestalOwner.erase(id); + if (anchor->isConnected) { + anchor->SendPacket_PedestalOwner(id, false); + } + } +} + +void JigsawPedestal_Reset() { + sPedestalOwner.clear(); +} diff --git a/src/port/Network/Anchor/JigsawPedestal.h b/src/port/Network/Anchor/JigsawPedestal.h new file mode 100644 index 000000000..dbf37379e --- /dev/null +++ b/src/port/Network/Anchor/JigsawPedestal.h @@ -0,0 +1,23 @@ +#pragma once +#include + +// Per-pedestal interaction lock for the Lair jigsaw podiums (keyed by actorTypeSpecificField). + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t port_jigsawPedestal_tryClaim(int32_t id); +// 1 if we may drive this podium (unowned/self/offline), 0 if another owns it. +int32_t port_jigsawPedestal_isSelf(int32_t id); +void port_jigsawPedestal_release(int32_t id); + +#ifdef __cplusplus +} + +// Network-internal entry points (Anchor packet handlers / lifecycle). +void JigsawPedestal_ApplyRemote(int32_t id, uint32_t clientId, bool claimed); +void JigsawPedestal_ClearClient(uint32_t clientId); +void JigsawPedestal_ReleaseAllSelf(); +void JigsawPedestal_Reset(); +#endif diff --git a/src/port/Network/Anchor/JsonConversions.hpp b/src/port/Network/Anchor/JsonConversions.hpp index 243b8b25e..b9d250b77 100644 --- a/src/port/Network/Anchor/JsonConversions.hpp +++ b/src/port/Network/Anchor/JsonConversions.hpp @@ -22,9 +22,42 @@ inline void to_json(json& j, const Color_RGB8& color) { j = json{ { "r", color.r }, { "g", color.g }, { "b", color.b } }; } +// Model colors travel as a fixed-length array, one entry per BKColorChannel. Clients that +// predate the feature simply omit the key and everyone renders them with vanilla colors. +inline void from_json(const json& j, BKPlayerColorSet& colors) { + colors = BKPlayerColorSet{}; + if (!j.is_array()) { + return; + } + for (size_t i = 0; i < j.size() && i < (size_t)BK_COLOR_CHANNEL_COUNT; i++) { + const json& entry = j[i]; + if (!entry.is_object()) { + continue; + } + colors.channel[i].enabled = entry.value("on", false) ? 1 : 0; + colors.channel[i].r = entry.value("r", (u8)0); + colors.channel[i].g = entry.value("g", (u8)0); + colors.channel[i].b = entry.value("b", (u8)0); + } +} + +inline void to_json(json& j, const BKPlayerColorSet& colors) { + j = json::array(); + for (int i = 0; i < BK_COLOR_CHANNEL_COUNT; i++) { + j.push_back(json{ { "on", colors.channel[i].enabled != 0 }, + { "r", colors.channel[i].r }, + { "g", colors.channel[i].g }, + { "b", colors.channel[i].b } }); + } +} + inline void from_json(const json& j, AnchorClient& client) { client.clientId = j.value("clientId", (u32)0); client.name = j.value("name", "???"); + client.colors = BKPlayerColorSet{}; + if (j.contains("colors")) { + from_json(j.at("colors"), client.colors); + } client.clientVersion = j.value("clientVersion", "???"); client.teamId = j.value("teamId", "default"); client.online = j.value("online", false); @@ -34,6 +67,7 @@ inline void from_json(const json& j, AnchorClient& client) { client.map = j.value("map", MAP_0_UNKNOWN); client.exit = j.value("exit", (s32)0); client.self = j.value("self", false); + client.cutsceneReturnMap = 0; } #endif // __cplusplus diff --git a/src/port/Network/Anchor/Menu.cpp b/src/port/Network/Anchor/Menu.cpp index afff951ed..f9080c128 100644 --- a/src/port/Network/Anchor/Menu.cpp +++ b/src/port/Network/Anchor/Menu.cpp @@ -1,8 +1,12 @@ #include "Anchor.h" +#include #include #include "port/UI/LighthouseGui.hpp" #include "port/UI/LighthouseMenu.h" #include "port/ShipUtils.h" +#include "port/Romhack/RomhackConfig.h" +#include "port/Romhack/RomhackCompat.h" +#include "port/Rando/Rando.h" namespace LighthouseGui { extern std::shared_ptr mLighthouseMenu; @@ -13,6 +17,68 @@ static const char* pvpModes[3] = { "Off", "On", "On + Friendly Fire" }; static std::vector teleportModes = { "None", "Team Only", "All" }; static std::vector showLocationsModes = { "None", "Team Only", "All" }; +static const char* playerColorLabels[BK_COLOR_CHANNEL_COUNT] = { + "Banjo's fur", "Banjo's shorts", "Kazooie's feathers", "Kazooie's beak & legs", "Banjo's backpack", "Banjo's skin", +}; + +// Channel order is the wire order; this is the order the rows are listed in. +static const int playerColorOrder[BK_COLOR_CHANNEL_COUNT] = { + BK_COLOR_BANJO_FUR, BK_COLOR_BANJO_SKIN, BK_COLOR_BANJO_SHORTS, + BK_COLOR_BANJO_BACKPACK, BK_COLOR_KAZOOIE_FEATHERS, BK_COLOR_KAZOOIE_BEAK, +}; + +// Per-part recoloring of the player model. Any mix of channels can be enabled; each one +// re-tints only the palette entries and vertex colors belonging to that part, so shading +// is preserved. The selection is part of client state, so everyone in the room sees it. +static void AnchorPlayerColorSection(Anchor* anchor) { + UIWidgets::PushStyleHeader(THEME_COLOR); + if (!ImGui::CollapsingHeader("Player Colors")) { + UIWidgets::PopStyleHeader(); + return; + } + + ImGui::TextWrapped("Tick a part and pick a color to recolor Banjo & Kazooie. Other players in your " + "room see your choices. Transformations keep their own colors."); + ImGui::Spacing(); + + for (int row = 0; row < BK_COLOR_CHANNEL_COUNT; row++) { + const int i = playerColorOrder[row]; + const char* baseCVar = PlayerColors_getChannelCVar(i); + if (baseCVar == nullptr) { + continue; + } + u8 r, g, b; + PlayerColors_getVanilla(i, &r, &g, &b); + const Color_RGBA8 vanilla = { r, g, b, 255 }; + const std::string enabledCVar = std::string(baseCVar) + ".Enabled"; + const std::string pickerLabel = std::string("##") + baseCVar; + + ImGui::PushID(i); + UIWidgets::CVarColorPicker(pickerLabel.c_str(), baseCVar, vanilla, false, + UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRandomButton, THEME_COLOR); + ImGui::SameLine(); + UIWidgets::CVarCheckbox(playerColorLabels[i], enabledCVar.c_str(), + UIWidgets::CheckboxOptions().DefaultValue(false).Color(THEME_COLOR)); + ImGui::PopID(); + } + + // Compare the resulting set rather than the widgets' return values: Reset and Random + // write the CVar without reporting a change. + static BKPlayerColorSet lastSent = {}; + static bool haveLastSent = false; + BKPlayerColorSet current; + PlayerColors_getLocal(¤t); + if (!haveLastSent || std::memcmp(¤t, &lastSent, sizeof(current)) != 0) { + lastSent = current; + haveLastSent = true; + if (anchor->isEnabled) { + anchor->SendPacket_UpdateClientState(); + } + } + + UIWidgets::PopStyleHeader(); +} + void AnchorMainMenu(WidgetInfo& info) { auto anchor = Anchor::GetInstance(); @@ -45,10 +111,7 @@ void AnchorMainMenu(WidgetInfo& info) { } UIWidgets::PopStyleInput(); - ImGui::Text("Name & Color"); - static Color_RGBA8 defaultColor = { 100, 255, 100, 255 }; - UIWidgets::CVarColorPicker("##Color", CVAR_REMOTE_ANCHOR("Color"), defaultColor); - ImGui::SameLine(); + ImGui::Text("Name"); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (UIWidgets::InputString("##Name", &anchorName, UIWidgets::InputOptions().Color(THEME_COLOR))) { CVarSetString(CVAR_REMOTE_ANCHOR("Name"), anchorName.c_str()); @@ -84,12 +147,13 @@ void AnchorMainMenu(WidgetInfo& info) { if (UIWidgets::Button("Global Room", UIWidgets::ButtonOptions() .Color(UIWidgets::Colors::Blue) - .Tooltip("Always-online public room so you don't have to experience " - "Hyrule alone. PVP and syncing are disabled."))) { + .Tooltip("Always-online public room so you don't have to explore alone. " + "You'll see other players' characters, but nothing is synced - " + "no items, flags, PvP, or teleporting."))) { CVarSetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org"); CVarSetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383); CVarSetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), "soh-global"); + CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), "lh-global"); Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); } @@ -116,6 +180,42 @@ void AnchorMainMenu(WidgetInfo& info) { ImGui::EndDisabled(); ImGui::Spacing(); + AnchorPlayerColorSection(anchor); + + ImGui::Spacing(); + + UIWidgets::CVarCheckbox("Show Player Nametags", CVAR_REMOTE_ANCHOR("Nametags"), + UIWidgets::CheckboxOptions() + .DefaultValue(true) + .Color(THEME_COLOR) + .Tooltip("Draw each other player's name above their character.")); + + if (CVarGetInteger(CVAR_REMOTE_ANCHOR("Nametags"), 1)) { + UIWidgets::CVarSliderFloat("Nametag Distance", CVAR_REMOTE_ANCHOR("NametagScale"), + UIWidgets::FloatSliderOptions() + .Min(0.5f) + .Max(6.0f) + .Step(0.5f) + .DefaultValue(1.0f) + .ShowButtons(true) + .Format("%.1fx") + .Color(THEME_COLOR) + .Tooltip("Multiplies how far away another player's nametag stays visible.")); + } + + ImGui::Spacing(); + + UIWidgets::CVarCheckbox( + "Show Teammate Notifications", CVAR_REMOTE_ANCHOR("Notifications"), + UIWidgets::CheckboxOptions() + .DefaultValue(true) + .Color(THEME_COLOR) + .Tooltip("Show a notification when a teammate collects a jiggy, opens a level, or (in a " + "randomizer) obtains a shuffled check. Randomizer check notifications also require " + "\"Send Collection Notifications\" to be enabled in the Randomizer settings.")); + + ImGui::Spacing(); + if (!anchor->isEnabled) { return; } @@ -128,45 +228,32 @@ void AnchorMainMenu(WidgetInfo& info) { ImGui::SeparatorText("Current Room"); ImGui::Text("%s Connected", ICON_FA_CHECK); - UIWidgets::PushStyleButton(THEME_COLOR); - if (ImGui::Button("Request Team State")) { - anchor->SendPacket_RequestTeamState(); - } - UIWidgets::Tooltip("Try this if you are missing items or flags that your team members have collected"); - UIWidgets::PopStyleButton(); + if (!anchor->IsGlobalRoom()) { + UIWidgets::PushStyleButton(THEME_COLOR); + if (ImGui::Button("Request Team State")) { + anchor->SendPacket_RequestTeamState(); + anchor->reloadMapOnTeamState = true; + } + UIWidgets::Tooltip("Try this if you are missing items or flags that your team members have collected"); + UIWidgets::PopStyleButton(); - ImGui::SameLine(); + ImGui::SameLine(); + } - // UIWidgets::WindowButton("Toggle Anchor Room Window", CVAR_WINDOW("AnchorRoom"), SohGui::mAnchorRoomWindow); + UIWidgets::WindowButton("Toggle Anchor Room Window", CVAR_WINDOW("AnchorRoom"), LighthouseGui::mAnchorRoomWindow); ImGui::Spacing(); - bool hideLocations = Anchor::GetInstance()->roomState.showLocationsMode == 0; - ImGui::BeginDisabled(hideLocations); - UIWidgets::CVarCheckbox( - "Show Other Players on Minimap", CVAR_REMOTE_ANCHOR("ShowOtherPlayersOnMinimap"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .DefaultValue(true) - .Tooltip(!hideLocations - ? "Other players will appear on the minimap in areas where you have the compass. " - "Visibility is restricted according to the Show Locations mode for the room." - : "Cannot show other players because the room's Show Locations mode is set to None.")); - ImGui::EndDisabled(); - - ImGui::Spacing(); - - /*if (!SohGui::mAnchorRoomWindow->IsVisible()) { - SohGui::mAnchorRoomWindow->DrawElement(); - }*/ + if (!LighthouseGui::mAnchorRoomWindow->IsVisible()) { + LighthouseGui::mAnchorRoomWindow->DrawElement(); + } } void AnchorAdminMenu(WidgetInfo& info) { auto anchor = Anchor::GetInstance(); - bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); if (!anchor->isEnabled || !anchor->isConnected || anchor->roomState.ownerClientId != anchor->ownClientId || - isGlobalRoom) { + anchor->IsGlobalRoom()) { return; } @@ -181,16 +268,23 @@ void AnchorAdminMenu(WidgetInfo& info) { for (auto& team : teams) { anchor->SendPacket_ClearTeamState(team); } + anchor->roomState.isRomhack = port_isRomhack(); + anchor->roomState.romhackName = Lighthouse::CurrentRomhackLabel(); + anchor->roomState.isRando = IS_RANDO; + anchor->roomState.seed = IS_RANDO ? (int32_t)RANDO_SEED : 0; + anchor->lastWarnedRomhackLabel.clear(); + anchor->lastWarnedRandoState.clear(); + anchor->SendPacket_UpdateRoomState(); } UIWidgets::PopStyleButton(); - if (UIWidgets::CVarCombobox("PvP Mode:", CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), pvpModes, - UIWidgets::ComboboxOptions() - .DefaultIndex(1) - .LabelPosition(UIWidgets::LabelPositions::Above) - .Color(THEME_COLOR))) { - anchor->SendPacket_UpdateRoomState(); - } + // if (UIWidgets::CVarCombobox("PvP Mode:", CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), pvpModes, + // UIWidgets::ComboboxOptions() + // .DefaultIndex(1) + // .LabelPosition(UIWidgets::LabelPositions::Above) + // .Color(THEME_COLOR))) { + // anchor->SendPacket_UpdateRoomState(); + // } if (UIWidgets::CVarCombobox("Show Locations For:", CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), showLocationsModes, UIWidgets::ComboboxOptions() @@ -210,6 +304,11 @@ void AnchorAdminMenu(WidgetInfo& info) { UIWidgets::CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { anchor->SendPacket_UpdateRoomState(); } + if (UIWidgets::CVarCheckbox("Share Consumables (Eggs/Feathers)", + CVAR_REMOTE_ANCHOR("RoomSettings.ShareConsumables"), + UIWidgets::CheckboxOptions().DefaultValue(false).Color(THEME_COLOR))) { + anchor->SendPacket_UpdateRoomState(); + } } void AnchorInstructionsMenu(WidgetInfo& info) { @@ -222,16 +321,13 @@ void AnchorInstructionsMenu(WidgetInfo& info) { ImGui::TextWrapped("2. Come up with a unique Room ID (this is basically your password) and enter it, along with " "your desired player name and team ID and click Enable"); - ImGui::TextWrapped("3. The host should configure the randomizer settings and generate a seed, then share the newly " - "generated JSON spoiler file with other players."); - - ImGui::TextWrapped("4. All players should load the same JSON spoiler file (drag it into SoH window), make sure " - "seed icons match, then create a new file."); + ImGui::TextWrapped("3. For Rando: The host should configure the randomizer settings and generate a seed, then get " + "in game to create a save file to share."); - ImGui::TextWrapped("5. All players should now load into their game. IMPORTANT! If using an existing save/seed " + ImGui::TextWrapped("4. All players should now load into their game. IMPORTANT! If using an existing save/seed " "ensure the player with the most progress loads the file first."); - ImGui::TextWrapped("6. After everyone has loaded in, verify on the network tab that it doesn't warn about anyone " + ImGui::TextWrapped("5. After everyone has loaded in, verify on the network tab that it doesn't warn about anyone " "being on a wrong version or seed."); ImGui::Spacing(); diff --git a/src/port/Network/Anchor/Packets/AllClientState.cpp b/src/port/Network/Anchor/Packets/AllClientState.cpp index 0def295e9..59d6ee01a 100644 --- a/src/port/Network/Anchor/Packets/AllClientState.cpp +++ b/src/port/Network/Anchor/Packets/AllClientState.cpp @@ -6,9 +6,7 @@ #include "port/Engine.h" #include "port/UI/Notification.h" -extern "C" { #include "functions.h" -} /** * ALL_CLIENT_STATE @@ -20,11 +18,13 @@ extern "C" { void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { std::vector newClients = payload["state"].get>(); - bool isGlobalRoom = (std::string("lh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); + bool isGlobalRoom = IsGlobalRoom(); std::vector clientsToRemove; + uint32_t joinOrder = 0; // add new clients for (auto& client : newClients) { + client.joinOrder = client.online ? ++joinOrder : 0; if (!client.online && clients.contains(client.clientId)) { clientsToRemove.push_back(client.clientId); } @@ -64,6 +64,9 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { clients[client.clientId].isGameComplete = client.isGameComplete; clients[client.clientId].map = client.map; clients[client.clientId].exit = client.exit; + clients[client.clientId].joinOrder = client.joinOrder; + clients[client.clientId].colors = client.colors; + ApplyClientCosmetics(client.clientId); Authority_OnClientStateChanged(client.clientId, client.online, client.map); } @@ -80,6 +83,7 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { if (dummies.contains(clientId)) { dummies.erase(clientId); } + PlayerColors_forgetOwner(clientId); if (clients.at(clientId).dummy != nullptr) { clients.at(clientId).dummy->dummy_free(); free(clients.at(clientId).dummy); @@ -88,5 +92,6 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { } PopulateDummies((GameMap)gsworld_getMap()); + SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); SendPacket_PlayerUpdate(true); } diff --git a/src/port/Network/Anchor/Packets/BreakObject.cpp b/src/port/Network/Anchor/Packets/BreakObject.cpp new file mode 100644 index 000000000..ae42e9d20 --- /dev/null +++ b/src/port/Network/Anchor/Packets/BreakObject.cpp @@ -0,0 +1,114 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include +#include + +#include "functions.h" + +#include "port/Patches/Patches.h" + +/** + * BREAK_OBJECT + */ + +std::set> sBrokenObjects; + +extern "C" int32_t port_breakable_isBroken(int32_t map, int32_t markerId, int32_t x, int32_t y, int32_t z) { + return sBrokenObjects.count({ map, markerId, x, y, z }) != 0 ? 1 : 0; +} + +std::vector port_breakable_snapshotBroken() { + std::vector flat; + flat.reserve(sBrokenObjects.size() * 5); + for (const auto& e : sBrokenObjects) { + flat.insert(flat.end(), e.begin(), e.end()); + } + return flat; +} + +void port_breakable_restoreBroken(const std::vector& flat) { + sBrokenObjects.clear(); + for (size_t i = 0; i + 5 <= flat.size(); i += 5) { + sBrokenObjects.insert({ flat[i], flat[i + 1], flat[i + 2], flat[i + 3], flat[i + 4] }); + } +} + +void port_breakable_clearForLevel(int32_t levelId) { + std::erase_if(sBrokenObjects, [levelId](const std::array& e) { + return (int32_t)map_getLevel((enum map_e)e[0]) == levelId; + }); +} + +void Anchor::SendPacket_BreakObject(s16 markerId, s32 x, s32 y, s32 z, s32 map, bool replay) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = BREAK_OBJECT; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["marker"] = markerId; + payload["x"] = x; + payload["y"] = y; + payload["z"] = z; + payload["map"] = map; + payload["replay"] = replay; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_BreakObject(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s16 markerId = payload.at("marker").get(); + s32 x = payload.at("x").get(); + s32 y = payload.at("y").get(); + s32 z = payload.at("z").get(); + s32 map = payload.at("map").get(); + bool replay = payload.contains("replay") ? payload.at("replay").get() : true; + + sBrokenObjects.insert({ map, markerId, x, y, z }); + if (replay && (s32)gsworld_getMap() == map) { + port_breakable_remoteBreakAt(markerId, x, y, z); + } +} + +extern "C" void port_breakable_broadcastBreak(int32_t markerId, int32_t x, int32_t y, int32_t z) { + s32 map = (s32)gsworld_getMap(); + if (sBrokenObjects.count({ map, markerId, x, y, z }) != 0) { + return; + } + sBrokenObjects.insert({ map, markerId, x, y, z }); + Anchor::GetInstance()->SendPacket_BreakObject((s16)markerId, x, y, z, map); +} + +extern "C" void port_breakable_recordBreak(int32_t markerId, int32_t x, int32_t y, int32_t z) { + s32 map = (s32)gsworld_getMap(); + if (sBrokenObjects.count({ map, markerId, x, y, z }) != 0) { + return; + } + sBrokenObjects.insert({ map, markerId, x, y, z }); + Anchor::GetInstance()->SendPacket_BreakObject((s16)markerId, x, y, z, map, false); +} + +extern "C" void port_breakable_despawnBrokenRestores(s32 map); + +void RegisterBreakObject_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sBrokenObjects.clear(); }); + + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnMapLoad* ev = (OnMapLoad*)event; + port_breakable_despawnBrokenRestores((s32)ev->nextMap); + }); +} + +static RegisterShipInitFunc initBreakObject(RegisterBreakObject_Init, {}); diff --git a/src/port/Network/Anchor/Packets/CarryThrow.cpp b/src/port/Network/Anchor/Packets/CarryThrow.cpp new file mode 100644 index 000000000..a74d22195 --- /dev/null +++ b/src/port/Network/Anchor/Packets/CarryThrow.cpp @@ -0,0 +1,64 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/Patches/Patches.h" + +#include "functions.h" + +/** + * CARRY_THROW + */ + +void Anchor::SendPacket_CarryThrow(s32 markerId, f32 start[3], f32 target[3]) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = CARRY_THROW; + payload["marker"] = markerId; + payload["start"] = { start[0], start[1], start[2] }; + payload["target"] = { target[0], target[1], target[2] }; + + SendToCurrentMapPlayers(payload); +} + +void Anchor::HandlePacket_CarryThrow(nlohmann::json& payload) { + if (!IsSaveLoaded()) { + return; + } + + uint32_t clientId = payload.value("clientId", 0u); + s32 markerId = payload.value("marker", 0); + std::vector start = payload["start"].get>(); + std::vector target = payload["target"].get>(); + if (start.size() < 3 || target.size() < 3) { + return; + } + + port_remoteCarry_throw(clientId, markerId, start.data(), target.data()); +} + +extern "C" void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]) { + Anchor* anchor = Anchor::GetInstance(); + if (anchor == nullptr || !anchor->isConnected) { + return; + } + anchor->SendPacket_CarryThrow(markerId, start, target); +} + +extern "C" s32 port_anchor_getDummyTransform(u32 clientId, f32 pos[3], f32* yaw) { + Anchor* anchor = Anchor::GetInstance(); + if (anchor == nullptr || !anchor->isConnected) { + return 0; + } + auto it = anchor->clients.find(clientId); + if (it == anchor->clients.end() || !it->second.online || it->second.dummy == nullptr || + (s32)it->second.map != (s32)gsworld_getMap()) { + return 0; + } + it->second.dummy->dummy_getPosition(pos); + *yaw = it->second.dummy->dummy_getYaw(); + return 1; +} diff --git a/src/port/Network/Anchor/Packets/CollectItem.cpp b/src/port/Network/Anchor/Packets/CollectItem.cpp new file mode 100644 index 000000000..0c02282e9 --- /dev/null +++ b/src/port/Network/Anchor/Packets/CollectItem.cpp @@ -0,0 +1,152 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include +#include "port/Enhancements/Retention/Retention.h" +#include "port/Rando/Rando.h" +#include "port/UI/Notification.h" + +#include "functions.h" + +static const char* const kJiggyLevelNames[10] = { + "Mumbo's Mountain", "Treasure Trove Cove", "Clanker's Cavern", "Bubblegloop Swamp", "Freezeezy Peak", + "Gruntilda's Lair", "Gobi's Valley", "Click Clock Wood", "Rusty Bucket Bay", "Mad Monster Mansion", +}; + +/** + * COLLECT_ITEM + */ + +void Anchor::SendPacket_CollectItem(u8 kind, s32 id) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = COLLECT_ITEM; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["kind"] = kind; + payload["id"] = id; + payload["map"] = (s32)gsworld_getMap(); + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_CollectItem(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + u8 kind = payload.at("kind").get(); + s32 id = payload.at("id").get(); + s32 map = payload.at("map").get(); + bool sameMap = (s32)gsworld_getMap() == map; + + switch (kind) { + case ANCHOR_COLLECTIBLE_JIGGY: + if (!jiggyscore_isCollected((enum jiggy_e)id)) { + jiggyscore_setCollected(id, true); + func_8034798C(); // recompute the current-level jiggy HUD count + if ((s32)map_getLevel((enum map_e)map) == (s32)level_get()) { + code_73640_printItemCount(ITEM_E_JIGGY); + } else { + code_73640_printItemCount(ITEM_26_JIGGY_TOTAL); + } + if (!IS_RANDO && ShouldShowNotifications()) { + size_t levelIdx = (size_t)(id - 1) / 10; + const char* where = levelIdx < (sizeof(kJiggyLevelNames) / sizeof(kJiggyLevelNames[0])) + ? kJiggyLevelNames[levelIdx] + : "an unknown level"; + Notification::Emit({ + .prefix = GetClientName(payload.value("clientId", 0u)), + .message = "collected Jiggy #" + std::to_string(((id - 1) % 10) + 1) + " in " + where, + }); + } + } + if (sameMap) { + ActorMarker* m = func_8032B16C((enum jiggy_e)id); + if (m != nullptr) { + marker_despawn(m); + } + if (id == JIGGY_20_BGS_ELEVATED_WALKWAY || id == JIGGY_25_BGS_MAZE) { + func_802D6924(); + } + } + break; + case ANCHOR_COLLECTIBLE_HONEYCOMB: + if (!honeycombscore_get((enum honeycomb_e)id)) { + honeycombscore_set((enum honeycomb_e)id, 1); + item_inc(ITEM_13_EMPTY_HONEYCOMB); + if (!(item_getCount(ITEM_13_EMPTY_HONEYCOMB) < 6)) { + gcpausemenu_80314AC8(0); + } + } + if (sameMap) { + ActorMarker* m = actorArray_findHoneycombMarkerById((enum honeycomb_e)id); + if (m != nullptr) { + marker_despawn(m); + } + } + break; + case ANCHOR_COLLECTIBLE_MUMBO: + if (!mumboscore_get((enum mumbotoken_e)id)) { + mumboscore_set((enum mumbotoken_e)id, true); + } + if (sameMap) { + ActorMarker* m = actorArray_findMumboTokenMarkerById((enum mumbotoken_e)id); + if (m != nullptr) { + marker_despawn(m); + } + } + break; + case ANCHOR_COLLECTIBLE_NOTE: + port_noteRetention_applyRemoteCollect(map, id, sameMap ? 1 : 0); + break; + case ANCHOR_COLLECTIBLE_JINJO: + port_jinjoRetention_applyRemoteCollect(map, id, sameMap ? 1 : 0); + break; + case ANCHOR_COLLECTIBLE_WORM: + case ANCHOR_COLLECTIBLE_ACORN: + case ANCHOR_COLLECTIBLE_PRESENT_BLUE: + case ANCHOR_COLLECTIBLE_PRESENT_GREEN: + case ANCHOR_COLLECTIBLE_PRESENT_RED: + case ANCHOR_COLLECTIBLE_GOLD: + case ANCHOR_COLLECTIBLE_ORANGE: { + enum item_e item; + switch (kind) { + case ANCHOR_COLLECTIBLE_WORM: + item = ITEM_22_CATERPILLAR; + break; + case ANCHOR_COLLECTIBLE_ACORN: + item = ITEM_23_ACORNS; + break; + case ANCHOR_COLLECTIBLE_PRESENT_BLUE: + item = ITEM_20_BLUE_PRESENT; + break; + case ANCHOR_COLLECTIBLE_PRESENT_GREEN: + item = ITEM_1F_GREEN_PRESENT; + break; + case ANCHOR_COLLECTIBLE_PRESENT_RED: + item = ITEM_21_RED_PRESENT; + break; + case ANCHOR_COLLECTIBLE_ORANGE: + item = ITEM_19_ORANGE; + break; + default: + item = ITEM_18_GOLD_BULLIONS; + break; + } + bool noHud = (kind == ANCHOR_COLLECTIBLE_ORANGE) && !sameMap; + s32 delta = (id < 0) ? -1 : 1; + if (noHud) { + item_adjustByDiffWithoutHud(item, delta); + } else { + item_adjustByDiffWithHud(item, delta); + } + if (id >= 0) { + port_carriedSync_applyRemoteCollect(kind, map, id, sameMap ? 1 : 0); + } + break; + } + } +} diff --git a/src/port/Network/Anchor/Packets/DamagePlayer.cpp b/src/port/Network/Anchor/Packets/DamagePlayer.cpp index 09322c944..adb708b7a 100644 --- a/src/port/Network/Anchor/Packets/DamagePlayer.cpp +++ b/src/port/Network/Anchor/Packets/DamagePlayer.cpp @@ -1,14 +1,9 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -extern "C" { #include "macros.h" #include "functions.h" -// extern PlayState* gPlayState; -// void func_80838280(Player* player); -} /** * DAMAGE_PLAYER @@ -29,37 +24,8 @@ void Anchor::SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage) { } void Anchor::HandlePacket_DamagePlayer(nlohmann::json& payload) { + return; // unimplemented uint32_t clientId = payload.at("clientId").get(); - // if (!clients.contains(clientId) || clients[clientId].player == nullptr) { - // return; - // } AnchorClient& anchorClient = clients[clientId]; - // Player* otherPlayer = anchorClient.player; - // Player* self = GET_PLAYER(gPlayState); - - //// Prevent incoming damage during cutscenes or item get sequences - // if (Player_InBlockingCsMode(gPlayState, self) || self->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || - // self->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) { - // return; - // } - - // u8 damageEffect = payload.at("damageEffect").get(); - // u8 damage = payload.at("damage").get(); - - // self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune - - // if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_FIRE) { - // for (int i = 0; i < ARRAY_COUNT(self->bodyFlameTimers); i++) { - // self->bodyFlameTimers[i] = Rand_S16Offset(0, 200); - // } - // self->bodyIsBurning = true; - // } else if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_STUN) { - // self->actor.freezeTimer = 20; - // Actor_SetColorFilter(&self->actor, 0, 0xFF, 0, 24); - // return; - // } - - // func_80837C0C(gPlayState, self, damageEffect, 4.0f, 5.0f, - // Actor_WorldYawTowardActor(&otherPlayer->actor, &self->actor), 20); } diff --git a/src/port/Network/Anchor/Packets/DisableAnchor.cpp b/src/port/Network/Anchor/Packets/DisableAnchor.cpp index ec047c3b5..9a4a322e6 100644 --- a/src/port/Network/Anchor/Packets/DisableAnchor.cpp +++ b/src/port/Network/Anchor/Packets/DisableAnchor.cpp @@ -1,7 +1,6 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" /** * DISABLE_ANCHOR diff --git a/src/port/Network/Anchor/Packets/EggToll.cpp b/src/port/Network/Anchor/Packets/EggToll.cpp new file mode 100644 index 000000000..584372f93 --- /dev/null +++ b/src/port/Network/Anchor/Packets/EggToll.cpp @@ -0,0 +1,108 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include +#include +#include + +#include "functions.h" + +#include "port/Patches/Patches.h" + +/** + * EGG_TOLL + */ + +std::map, int32_t> sStages; + +void recordStage(int32_t map, int32_t secondaryId, int32_t stage) { + std::array key = { map, secondaryId }; + auto it = sStages.find(key); + if (it == sStages.end() || stage > it->second) { + sStages[key] = stage; + } +} + +extern "C" int32_t port_eggToll_getStage(int32_t map, int32_t secondaryId) { + auto it = sStages.find({ map, secondaryId }); + return it != sStages.end() ? it->second : 0; +} + +extern "C" void port_eggToll_onAdvance(int32_t map, int32_t secondaryId, int32_t stage) { + recordStage(map, secondaryId, stage); + Anchor::GetInstance()->SendPacket_EggToll((s16)secondaryId, stage, map); +} + +void Anchor::SendPacket_EggToll(s16 secondaryId, s32 stage, s32 map) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = EGG_TOLL; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["sec"] = secondaryId; + payload["stage"] = stage; + payload["map"] = map; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_EggToll(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s16 secondaryId = payload.at("sec").get(); + s32 stage = payload.at("stage").get(); + s32 map = payload.at("map").get(); + + recordStage(map, secondaryId, stage); + if ((s32)gsworld_getMap() == map) { + port_eggToll_remoteApply(map, secondaryId, stage); + } +} + +std::vector port_eggToll_snapshot() { + std::vector flat; + flat.reserve(sStages.size() * 3); + for (const auto& [key, stage] : sStages) { + flat.push_back(key[0]); + flat.push_back(key[1]); + flat.push_back(stage); + } + return flat; +} + +void port_eggToll_restore(const std::vector& flat) { + sStages.clear(); + for (size_t i = 0; i + 3 <= flat.size(); i += 3) { + sStages[{ flat[i], flat[i + 1] }] = flat[i + 2]; + } +} + +void port_eggToll_clearForLevel(int32_t levelId) { + std::erase_if(sStages, + [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); +} + +void RegisterEggToll_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sStages.clear(); }); + + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnMapLoad* ev = (OnMapLoad*)event; + for (const auto& [key, stage] : sStages) { + if (key[0] == (int32_t)ev->nextMap) { + port_eggToll_remoteApply(key[0], key[1], stage); + } + } + }); +} + +static RegisterShipInitFunc initEggToll(RegisterEggToll_Init, {}); diff --git a/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp b/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp index ab6192cdb..fd4017e11 100644 --- a/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp +++ b/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp @@ -1,12 +1,11 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -//#include "soh/Enhancements/randomizer/randomizer_entrance.h" -//#include "soh/OTRGlobals.h" /** * ENTRANCE_DISCOVERED + * + * currently unimplemented */ void Anchor::SendPacket_EntranceDiscovered(u16 entranceIndex) { @@ -29,5 +28,4 @@ void Anchor::HandlePacket_EntranceDiscovered(nlohmann::json& payload) { } u16 entranceIndex = payload.at("entranceIndex").get(); - // Entrance_SetEntranceDiscovered(entranceIndex, 1); } diff --git a/src/port/Network/Anchor/Packets/FightEvent.cpp b/src/port/Network/Anchor/Packets/FightEvent.cpp new file mode 100644 index 000000000..75babb01c --- /dev/null +++ b/src/port/Network/Anchor/Packets/FightEvent.cpp @@ -0,0 +1,72 @@ +#include "port/Network/Anchor/Anchor.h" +#include "port/Network/Anchor/Authority.h" +#include "port/Network/Anchor/FightSync.h" +#include +#include + +#include "functions.h" +extern "C" { +#include "variables.h" +} + +/** + * FIGHT_EVENT + */ + +void Anchor::SendPacket_FightEvent(s32 ev, s32 a, s32 b, const f32 v0[3], const f32 v1[3], const f32 v2[3]) { + if (!IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS || GetCurrentMapPlayers() == 0) { + return; + } + + nlohmann::json payload; + payload["type"] = FIGHT_EVENT; + payload["ev"] = ev; + payload["a"] = a; + payload["b"] = b; + if (v0 != nullptr && v1 != nullptr && v2 != nullptr) { + payload["p"] = { v0[0], v0[1], v0[2] }; + payload["v"] = { v1[0], v1[1], v1[2] }; + payload["w"] = { v2[0], v2[1], v2[2] }; + } + + SendToCurrentMapPlayers(payload); +} + +extern "C" void FightSync_SendEvent(int32_t ev, int32_t a, int32_t b, const float v0[3], const float v1[3], + const float v2[3]) { + Anchor* anchor = Anchor::GetInstance(); + if (anchor == nullptr || !anchor->isConnected) { + return; + } + anchor->SendPacket_FightEvent(ev, a, b, v0, v1, v2); +} + +void Anchor::HandlePacket_FightEvent(nlohmann::json& payload) { + if (gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { + return; + } + + s32 ev = payload.value("ev", (s32)-1); + s32 a = payload.value("a", (s32)0); + s32 b = payload.value("b", (s32)0); + f32 p[3] = { 0.0f, 0.0f, 0.0f }; + f32 v[3] = { 0.0f, 0.0f, 0.0f }; + f32 w[3] = { 0.0f, 0.0f, 0.0f }; + bool hasVectors = payload.contains("p"); + + if (hasVectors) { + std::vector pv = payload["p"].get>(); + std::vector vv = payload["v"].get>(); + std::vector wv = payload["w"].get>(); + if (pv.size() < 3 || vv.size() < 3 || wv.size() < 3) { + return; + } + for (s32 i = 0; i < 3; i++) { + p[i] = pv[i]; + v[i] = vv[i]; + w[i] = wv[i]; + } + } + + FightSync_ApplyEvent(ev, a, b, hasVectors ? p : nullptr, hasVectors ? v : nullptr, hasVectors ? w : nullptr); +} diff --git a/src/port/Network/Anchor/Packets/FightState.cpp b/src/port/Network/Anchor/Packets/FightState.cpp new file mode 100644 index 000000000..97fb84e25 --- /dev/null +++ b/src/port/Network/Anchor/Packets/FightState.cpp @@ -0,0 +1,70 @@ +#include "port/Network/Anchor/Anchor.h" +#include "port/Network/Anchor/Authority.h" +#include "port/Network/Anchor/FightSync.h" +#include +#include + +#include "functions.h" +extern "C" { +#include "variables.h" +} + +/** + * FIGHT_STATE + */ + +void Anchor::SendPacket_FightState(u32 targetClientId) { + if (!IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { + return; + } + + FightWorldSnapshot snap; + if (!FightSync_GatherWorld(&snap)) { + return; + } + + nlohmann::json payload; + payload["type"] = FIGHT_STATE; + payload["targetClientId"] = targetClientId; + payload["pad"] = snap.pad; + payload["bar"] = snap.barrier; + payload["st"] = { snap.statue[0], snap.statue[1], snap.statue[2], snap.statue[3] }; + payload["jg"] = { snap.jinjoGone[0], snap.jinjoGone[1], snap.jinjoGone[2], snap.jinjoGone[3] }; + payload["jb"] = snap.jbase; + payload["jp"] = { snap.jpads[0], snap.jpads[1], snap.jpads[2], snap.jpads[3] }; + + SendJsonToRemote(payload); +} + +extern "C" void FightSync_SendSnapshot(uint32_t clientId) { + Anchor* anchor = Anchor::GetInstance(); + if (anchor == nullptr || !anchor->isConnected) { + return; + } + anchor->SendPacket_FightState(clientId); +} + +void Anchor::HandlePacket_FightState(nlohmann::json& payload) { + if (gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { + return; + } + + FightWorldSnapshot snap; + std::vector st = payload["st"].get>(); + std::vector jg = payload["jg"].get>(); + std::vector jp = payload["jp"].get>(); + if (st.size() < 4 || jg.size() < 4 || jp.size() < 4) { + return; + } + + snap.pad = payload.value("pad", (u8)0); + snap.barrier = payload.value("bar", (u8)0); + snap.jbase = payload.value("jb", (u8)0); + for (s32 i = 0; i < 4; i++) { + snap.statue[i] = st[i]; + snap.jinjoGone[i] = jg[i]; + snap.jpads[i] = jp[i]; + } + + FightSync_ApplyWorld(&snap); +} diff --git a/src/port/Network/Anchor/Packets/FightUpdate.cpp b/src/port/Network/Anchor/Packets/FightUpdate.cpp new file mode 100644 index 000000000..bf3ff9887 --- /dev/null +++ b/src/port/Network/Anchor/Packets/FightUpdate.cpp @@ -0,0 +1,75 @@ +#include "port/Network/Anchor/Anchor.h" +#include "port/Network/Anchor/Authority.h" +#include "port/Network/Anchor/FightSync.h" +#include +#include + +#include "functions.h" +extern "C" { +#include "variables.h" +} + +/** + * FIGHT_UPDATE + */ + +static uint32_t sOutgoingSeq = 0; +static uint32_t sLastAcceptedSeq = 0; + +extern "C" uint32_t FightSyncSeq_Next(void) { + return ++sOutgoingSeq; +} + +extern "C" bool FightSyncSeq_Accept(uint32_t seq) { + if (seq <= sLastAcceptedSeq) { + return false; + } + sLastAcceptedSeq = seq; + return true; +} + +extern "C" void FightSyncSeq_Reset(void) { + sOutgoingSeq = 0; + sLastAcceptedSeq = 0; +} + +void Anchor::SendPacket_FightUpdate(const f32 pos[3], f32 yaw, s32 state, s32 phase, s32 mirror, s32 vuln) { + if (!IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS || GetCurrentMapPlayers() == 0) { + return; + } + + nlohmann::json payload; + payload["type"] = FIGHT_UPDATE; + payload["seq"] = FightSyncSeq_Next(); + payload["pos"] = { pos[0], pos[1], pos[2] }; + payload["yaw"] = yaw; + payload["st"] = state; + payload["ph"] = phase; + payload["mir"] = mirror; + payload["vuln"] = vuln; + payload["quiet"] = true; + + SendToCurrentMapPlayers(payload); +} + +extern "C" void FightSync_SendUpdate(const float pos[3], float yaw, int32_t state, int32_t phase, int32_t mirror, + int32_t vuln) { + Anchor::GetInstance()->SendPacket_FightUpdate(pos, yaw, state, phase, mirror, vuln); +} + +void Anchor::HandlePacket_FightUpdate(nlohmann::json& payload) { + if (gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { + return; + } + if (!FightSyncSeq_Accept(payload.value("seq", (u32)0))) { + return; + } + + std::vector pos = payload["pos"].get>(); + if (pos.size() < 3) { + return; + } + + FightSync_ApplyUpdate(pos.data(), payload.value("yaw", 0.0f), payload.value("st", (s32)1), + payload.value("ph", (s32)0), payload.value("mir", (s32)0), payload.value("vuln", (s32)0)); +} diff --git a/src/port/Network/Anchor/Packets/GameComplete.cpp b/src/port/Network/Anchor/Packets/GameComplete.cpp index 44f314762..b502d8f31 100644 --- a/src/port/Network/Anchor/Packets/GameComplete.cpp +++ b/src/port/Network/Anchor/Packets/GameComplete.cpp @@ -1,9 +1,7 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "port/UI/Notification.h" -//#include "soh/ShipUtils.h" const std::string gameCompleteMessages[] = { "killed Ganon", "saved Zelda", "proved their Courage", @@ -12,6 +10,8 @@ const std::string gameCompleteMessages[] = { /** * GAME_COMPLETE + * + * unimplemented */ void Anchor::SendPacket_GameComplete() { @@ -33,10 +33,9 @@ void Anchor::HandlePacket_GameComplete(nlohmann::json& payload) { AnchorClient& anchorClient = clients[clientId]; anchorClient.isGameComplete = true; - bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); // Notification::Emit({ - // .prefix = isGlobalRoom ? "Someone" : anchorClient.name, + // .prefix = IsGlobalRoom() ? "Someone" : anchorClient.name, // .message = ShipUtils::RandomElement(gameCompleteMessages), // }); } diff --git a/src/port/Network/Anchor/Packets/GiveItem.cpp b/src/port/Network/Anchor/Packets/GiveItem.cpp index 3c4828fb1..8d7f3801e 100644 --- a/src/port/Network/Anchor/Packets/GiveItem.cpp +++ b/src/port/Network/Anchor/Packets/GiveItem.cpp @@ -1,20 +1,15 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "port/UI/Notification.h" -//#include "soh/Enhancements/randomizer/randomizer.h" -//#include "soh/SohGui/ImGuiUtils.h" -//#include "soh/Enhancements/item-tables/ItemTableManager.h" -//#include "soh/OTRGlobals.h" -extern "C" { #include "functions.h" // extern PlayState* gPlayState; -} /** * GIVE_ITEM + * + * unimplemented */ uint8_t incomingIceTrapsFromAnchor = 0; diff --git a/src/port/Network/Anchor/Packets/Handshake.cpp b/src/port/Network/Anchor/Packets/Handshake.cpp index 0c80b0393..ce7d6dd78 100644 --- a/src/port/Network/Anchor/Packets/Handshake.cpp +++ b/src/port/Network/Anchor/Packets/Handshake.cpp @@ -1,8 +1,6 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -//#include "soh/OTRGlobals.h" /** * HANDSHAKE diff --git a/src/port/Network/Anchor/Packets/HutSmash.cpp b/src/port/Network/Anchor/Packets/HutSmash.cpp new file mode 100644 index 000000000..4ba1718b7 --- /dev/null +++ b/src/port/Network/Anchor/Packets/HutSmash.cpp @@ -0,0 +1,108 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include +#include +#include + +#include "functions.h" + +/** + * HUT_SMASH + */ + +std::map, int32_t> sHuts; + +extern "C" int32_t port_hutSmash_get(int32_t x, int32_t y, int32_t z) { + auto it = sHuts.find({ (int32_t)gsworld_getMap(), x, y, z }); + return it != sHuts.end() ? it->second : -1; +} + +extern "C" int32_t port_hutSmash_countForCurrentLevel(void) { + int32_t level = (int32_t)map_getLevel(gsworld_getMap()); + int32_t count = 0; + for (const auto& [key, loot] : sHuts) { + if ((int32_t)map_getLevel((enum map_e)key[0]) == level) { + count++; + } + } + return count; +} + +extern "C" void port_hutSmash_record(int32_t x, int32_t y, int32_t z, int32_t loot) { + int32_t map = (int32_t)gsworld_getMap(); + std::array key = { map, x, y, z }; + if (sHuts.find(key) != sHuts.end()) { + return; + } + sHuts[key] = loot; + Anchor::GetInstance()->SendPacket_HutSmash(x, y, z, loot, map); +} + +void Anchor::SendPacket_HutSmash(s32 x, s32 y, s32 z, s32 loot, s32 map) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = HUT_SMASH; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["x"] = x; + payload["y"] = y; + payload["z"] = z; + payload["loot"] = loot; + payload["map"] = map; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_HutSmash(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s32 x = payload.at("x").get(); + s32 y = payload.at("y").get(); + s32 z = payload.at("z").get(); + s32 loot = payload.at("loot").get(); + s32 map = payload.at("map").get(); + + sHuts.emplace(std::array{ map, x, y, z }, loot); +} + +std::vector port_hutSmash_snapshot() { + std::vector flat; + flat.reserve(sHuts.size() * 5); + for (const auto& [key, loot] : sHuts) { + flat.push_back(key[0]); + flat.push_back(key[1]); + flat.push_back(key[2]); + flat.push_back(key[3]); + flat.push_back(loot); + } + return flat; +} + +void port_hutSmash_restore(const std::vector& flat) { + sHuts.clear(); + for (size_t i = 0; i + 5 <= flat.size(); i += 5) { + sHuts[{ flat[i], flat[i + 1], flat[i + 2], flat[i + 3] }] = flat[i + 4]; + } +} + +void port_hutSmash_clearForLevel(int32_t levelId) { + std::erase_if(sHuts, + [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); +} + +void RegisterHutSmash_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sHuts.clear(); }); +} + +static RegisterShipInitFunc initHutSmash(RegisterHutSmash_Init, {}); diff --git a/src/port/Network/Anchor/Packets/JiggyCrane.cpp b/src/port/Network/Anchor/Packets/JiggyCrane.cpp new file mode 100644 index 000000000..863a4b6d1 --- /dev/null +++ b/src/port/Network/Anchor/Packets/JiggyCrane.cpp @@ -0,0 +1,35 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "functions.h" + +#include "port/Patches/Patches.h" + +/** + * JIGGY_CRANE + */ + +void Anchor::SendPacket_JiggyCrane(s32 stage) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags || GetCurrentMapPlayers() == 0) { + return; + } + + nlohmann::json payload; + payload["type"] = JIGGY_CRANE; + payload["stage"] = stage; + + SendToCurrentMapPlayers(payload); +} + +void Anchor::HandlePacket_JiggyCrane(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + port_jiggyCrane_remoteApply(payload.at("stage").get()); +} + +extern "C" void port_jiggyCrane_broadcast(int32_t stage) { + Anchor::GetInstance()->SendPacket_JiggyCrane(stage); +} diff --git a/src/port/Network/Anchor/Packets/MapLoad.cpp b/src/port/Network/Anchor/Packets/MapLoad.cpp index 6765b0aa1..f22fc1167 100644 --- a/src/port/Network/Anchor/Packets/MapLoad.cpp +++ b/src/port/Network/Anchor/Packets/MapLoad.cpp @@ -3,10 +3,9 @@ #include #include -extern "C" { #include "variables.h" #include "functions.h" -} +#include "port/Patches/Patches.h" /** * MAP_LOAD @@ -20,6 +19,7 @@ void Anchor::SendPacket_MapLoad(GameMap map, s32 exit) { payload["type"] = MAP_LOAD; payload["map"] = map; payload["exit"] = exit; + payload["returnMap"] = port_cutsceneWarp_getReturnMap(); SendJsonToRemote(payload); } @@ -30,11 +30,13 @@ void Anchor::HandlePacket_MapLoad(nlohmann::json& payload) { clients[clientId].map = payload.at("map").get(); clients[clientId].exit = payload.at("exit").get(); + clients[clientId].cutsceneReturnMap = payload.value("returnMap", (s32)0); clients[clientId].isSaveLoaded = clients[clientId].map != MAP_1E_CS_START_NINTENDO && clients[clientId].map != MAP_1F_CS_START_RAREWARE && clients[clientId].map != MAP_91_FILE_SELECT; EvaluateDummyForClient(clientId); Authority_OnPeerMapLoad(clientId, clients[clientId].map); + SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); // Handle instances where map-specific updates aren't captured by other clients, causing transformations // and animation states to be desynced until updated again while the client is in the map. diff --git a/src/port/Network/Anchor/Packets/PedestalOwner.cpp b/src/port/Network/Anchor/Packets/PedestalOwner.cpp new file mode 100644 index 000000000..cd3ceca92 --- /dev/null +++ b/src/port/Network/Anchor/Packets/PedestalOwner.cpp @@ -0,0 +1,27 @@ +#include "port/Network/Anchor/Anchor.h" +#include "port/Network/Anchor/JigsawPedestal.h" +#include +#include + +/** + * PEDESTAL_OWNER + * + * Claim/release of a jigsaw podium lock; conflicts resolve by lowest clientId. + */ + +void Anchor::SendPacket_PedestalOwner(s32 id, bool claimed) { + nlohmann::json payload; + payload["type"] = PEDESTAL_OWNER; + payload["id"] = id; + payload["claimed"] = claimed; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_PedestalOwner(nlohmann::json& payload) { + uint32_t clientId = payload.at("clientId").get(); + s32 id = payload.at("id").get(); + bool claimed = payload.value("claimed", false); + + JigsawPedestal_ApplyRemote(id, clientId, claimed); +} diff --git a/src/port/Network/Anchor/Packets/PlayerSfx.cpp b/src/port/Network/Anchor/Packets/PlayerSfx.cpp index a3c2bdf5e..bafc83537 100644 --- a/src/port/Network/Anchor/Packets/PlayerSfx.cpp +++ b/src/port/Network/Anchor/Packets/PlayerSfx.cpp @@ -3,12 +3,9 @@ #include #include -extern "C" { #include "macros.h" #include "functions.h" #include "variables.h" -// extern PlayState* gPlayState; -} /** * PLAYER_SFX @@ -26,22 +23,7 @@ void Anchor::SendPacket_PlayerSfx(u16 sfxId) { payload["type"] = PLAYER_SFX; payload["sfxId"] = sfxId; payload["quiet"] = true; - - // for (auto& [clientId, client] : clients) { - // if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded && !client.self) { - // payload["targetClientId"] = clientId; - // SendJsonToRemote(payload); - // } - // } } void Anchor::HandlePacket_PlayerSfx(nlohmann::json& payload) { - // uint32_t clientId = payload.at("clientId").get(); - // u16 sfxId = payload.at("sfxId").get(); - - // if (!clients.contains(clientId) || !clients[clientId].player) { - // return; - // } - - // Player_PlaySfx((Actor*)clients[clientId].player, sfxId); } diff --git a/src/port/Network/Anchor/Packets/PlayerUpdate.cpp b/src/port/Network/Anchor/Packets/PlayerUpdate.cpp index 861451017..71987a608 100644 --- a/src/port/Network/Anchor/Packets/PlayerUpdate.cpp +++ b/src/port/Network/Anchor/Packets/PlayerUpdate.cpp @@ -3,11 +3,13 @@ #include #include -extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" -} + +extern "C" ActorMarker* bacarry_getMarker(void); + +#include "port/Patches/Patches.h" /** * PLAYER_UPDATE @@ -28,6 +30,16 @@ void Anchor::SendToCurrentMapPlayers(nlohmann::json& payload) { } } +void Anchor::SendToCurrentLevelPlayers(nlohmann::json& payload) { + enum level_e myLevel = map_getLevel(gsworld_getMap()); + for (auto& [clientId, client] : clients) { + if (client.online && client.isSaveLoaded && !client.self && map_getLevel((enum map_e)client.map) == myLevel) { + payload["targetClientId"] = clientId; + SendJsonToRemote(payload); + } + } +} + void Anchor::SendPacket_PlayerSubRangeChange(f32 duration, f32 end) { if (!IsSaveLoaded() || GetCurrentMapPlayers() == 0) { return; @@ -161,19 +173,36 @@ void Anchor::SendPacket_PlayerUpdate(bool full, uint32_t targetClientId) { anctrl_getSubRange(baanim_getAnimCtrlPtr(), &sub_start, &sub_end); payload["subrange_end"] = sub_end; } - payload["kazooieVisible"] = func_8029DFBC(); // Kazooie visibility (Kazooie popped out) - payload["modelSquint"] = func_8029DFA4(); // squint - payload["modelWink"] = func_8029DFB0(); // wink - payload["modelMouth1"] = func_8029DFE0(); // mouth - payload["modelMouth2"] = func_8029DFEC(); // mouth 2 - payload["modelEyeBlendUpper"] = func_8029DFC8(); // eye blend upper - payload["modelEyeBlendLower"] = func_8029DFD4(); // eye blend lower + payload["kazooieUpper"] = modelAppendages_showKazooiesUpperHalf(); + payload["kazooieLower"] = modelAppendages_showKazooiesAss(); + payload["kazooieFeet"] = modelAppendages_showKazooiesFeetAndShoes(); + payload["kazooieTurbos"] = modelAppendages_hideTurboTrainers(); + payload["kazooieBoots"] = modelAppendages_hideWadingBoots(); + payload["banjoLeftEye"] = modelAppendages_showBanjosLeftEye(); + payload["banjoRightEye"] = modelAppendages_showBanjosRightEye(); + payload["bottlesBonus"] = baanim_getActiveBottlesBonusMask(); + { + // Carried-collectible marker id (0 = none); skipped once thrown (unk138_21 = in flight). + s32 carryId = 0; + ActorMarker* carryMarker = bacarry_getMarker(); + if (carryMarker != nullptr) { + Actor* carried = marker_getActor(carryMarker); + if (carried != nullptr && !carried->unk138_21) { + carryId = carryMarker->id; + payload["carryOff"] = { carried->position[0] - pos[0], carried->position[1] - pos[1], + carried->position[2] - pos[2] }; + payload["carryYaw"] = mlNormalizeAngle(carried->yaw - player_getYaw()); + } + } + payload["carry"] = carryId; + } if (full) { payload["anim_id"] = anctrl_getIndex(baanim_getAnimCtrlPtr()); payload["anim_control"] = anctrl_getPlaybackType(baanim_getAnimCtrlPtr()); } payload["type"] = full ? PLAYER_UPDATE_FULL : PLAYER_UPDATE; + payload["quiet"] = true; if (targetClientId != 0) { payload["targetClientId"] = targetClientId; @@ -234,9 +263,24 @@ void Anchor::HandlePacket_PlayerUpdate(nlohmann::json& payload) { (AnimControl)payload.value("anim_control", (int)ANIMCTRL_LOOP), 0.0f, payload.value("subrange_end", 1.0f), false); } - client.dummy->setModelSubStates(payload.value("kazooieVisible", false), payload.value("modelSquint", false), - payload.value("modelWink", false), payload.value("modelMouth1", false), - payload.value("modelMouth2", false), payload.value("modelEyeBlendUpper", 0.0f), - payload.value("modelEyeBlendLower", 0.0f)); + client.dummy->setModelSubStates(payload.value("kazooieUpper", false), payload.value("kazooieLower", false), + payload.value("kazooieFeet", false), payload.value("kazooieTurbos", false), + payload.value("kazooieBoots", false), payload.value("banjoLeftEye", 0.0f), + payload.value("banjoRightEye", 0.0f)); + client.dummy->dummy_setBottlesBonus(payload.value("bottlesBonus", 0)); + { + f32 carryOff[3] = { 0.0f, 0.0f, 0.0f }; + f32 carryYaw = 0.0f; + if (payload.contains("carryOff")) { + std::vector off = payload["carryOff"].get>(); + if (off.size() >= 3) { + carryOff[0] = off[0]; + carryOff[1] = off[1]; + carryOff[2] = off[2]; + } + carryYaw = payload.value("carryYaw", 0.0f); + } + port_remoteCarry_setCarried(clientId, payload.value("carry", 0), carryOff, carryYaw); + } } } diff --git a/src/port/Network/Anchor/Packets/PuzzleStep.cpp b/src/port/Network/Anchor/Packets/PuzzleStep.cpp new file mode 100644 index 000000000..638f20dd9 --- /dev/null +++ b/src/port/Network/Anchor/Packets/PuzzleStep.cpp @@ -0,0 +1,340 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include +#include +#include +#include + +#include "functions.h" +extern "C" { +void chTreasurehunt_netTick(void); +} + +#include "port/Patches/Patches.h" + +/** + * PUZZLE_STEP + * + * Syncs multi-step world puzzles with no flag of their own (Tanktup's legs, croctus feed, pink + * eggs). Progress is an OR-merged bitmask keyed by (map, puzzleId); never saved. + */ + +std::map, int32_t> sPuzzleBits; +std::map, int32_t> sPuzzleCounts; +// PUZZLE_POS: (map, puzzleId) -> set of spawn-position hashes for positional puzzles (see below). +std::map, std::set> sPuzzlePos; + +static int32_t puzzlePosHash(int32_t x, int32_t y, int32_t z) { + uint32_t h = (uint32_t)x * 73856093u ^ (uint32_t)y * 19349663u ^ (uint32_t)z * 83492791u; + return (int32_t)((h & 0x7FFFFFFFu) | 1u); // never 0 (the "no positional hash" sentinel) +} + +/** + * Every bitmask entry is written by one vanilla actor that lives in one known map, and + * some entries are derived from -- or applied back to -- raw map/level flag indices whose + * meaning is map-relative. A romhack that relocates such an actor makes it read one map's + * flag and republish it as another's. To avoid complications, each puzzle id is scoped to + * its actor's home: outside it every leg is inert. + * + * Vanilla is unaffected, and a romhack keeps live sync for every puzzle it didn't relocate. + */ +struct PuzzleHome { + std::set maps; + int32_t level = -1; // home is a whole level (romhacks may remap a level's maps) +}; + +static const std::map& puzzleHomes() { + static const std::map homes = { + { ANCHOR_PUZZLE_BGS_TANKTUP, { { MAP_D_BGS_BUBBLEGLOOP_SWAMP } } }, + { ANCHOR_PUZZLE_BGS_CROCTUS, { { MAP_D_BGS_BUBBLEGLOOP_SWAMP } } }, + // The egg chain's map isn't pinned down in the decomp; its readback only drives + // actor state, so the whole level is safe. + { ANCHOR_PUZZLE_BGS_PINKEGG, { {}, LEVEL_4_BUBBLEGLOOP_SWAMP } }, + { ANCHOR_PUZZLE_CC_CLANKER_TEETH, { { MAP_B_CC_CLANKERS_CAVERN } } }, + { ANCHOR_PUZZLE_GV_JINXY_DOOR, { { MAP_12_GV_GOBIS_VALLEY } } }, + { ANCHOR_PUZZLE_MM_JUJU, { { MAP_2_MM_MUMBOS_MOUNTAIN } } }, + { ANCHOR_PUZZLE_TTC_NIPPER, { { MAP_7_TTC_TREASURE_TROVE_COVE } } }, + { ANCHOR_PUZZLE_TTC_BLUBBER, { { MAP_7_TTC_TREASURE_TROVE_COVE } } }, + { ANCHOR_PUZZLE_TTC_XHUNT, { { MAP_7_TTC_TREASURE_TROVE_COVE } } }, + { ANCHOR_PUZZLE_FP_TREE_ICE, { { MAP_53_FP_CHRISTMAS_TREE } } }, + { ANCHOR_PUZZLE_FP_PRESENTS, { { MAP_27_FP_FREEZEEZY_PEAK } } }, + { ANCHOR_PUZZLE_FP_SNOWBUTTONS, { { MAP_27_FP_FREEZEEZY_PEAK } } }, + { ANCHOR_PUZZLE_FP_SLUSHES, { { MAP_27_FP_FREEZEEZY_PEAK } } }, + { ANCHOR_PUZZLE_RBB_ENGINE_FANS, { { MAP_34_RBB_ENGINE_ROOM } } }, + // Tutorial choreography follows the level, not the map. + { ANCHOR_PUZZLE_SM_TUTORIAL, { {}, LEVEL_B_SPIRAL_MOUNTAIN } }, + }; + return homes; +} + +static bool mirrorAllowedFor(int32_t puzzleId, int32_t map) { + auto it = puzzleHomes().find(puzzleId); + if (it == puzzleHomes().end()) { + return false; // unknown id: fail inert + } + if (it->second.maps.count(map)) { + return true; + } + return it->second.level >= 0 && (int32_t)map_getLevel((enum map_e)map) == it->second.level; +} + +static bool mirrorLive(int32_t puzzleId) { + return mirrorAllowedFor(puzzleId, (int32_t)gsworld_getMap()); +} + +extern "C" int32_t port_puzzleStep_get(int32_t puzzleId) { + if (!mirrorLive(puzzleId)) { + return 0; + } + auto it = sPuzzleBits.find({ (int32_t)gsworld_getMap(), puzzleId }); + return it != sPuzzleBits.end() ? it->second : 0; +} + +extern "C" int32_t port_puzzleStep_getForMap(int32_t map, int32_t puzzleId) { + if (!mirrorAllowedFor(puzzleId, map)) { + return 0; + } + auto it = sPuzzleBits.find({ map, puzzleId }); + return it != sPuzzleBits.end() ? it->second : 0; +} + +// For level-homed puzzles: a relocated actor writes under the romhack's map +// key, which a map-keyed read can't know. ORs the puzzle's bits across the level. +extern "C" int32_t port_puzzleStep_getForLevel(int32_t levelId, int32_t puzzleId) { + int32_t bits = 0; + for (const auto& [key, val] : sPuzzleBits) { + if (key[1] == puzzleId && mirrorAllowedFor(puzzleId, key[0]) && + (int32_t)map_getLevel((enum map_e)key[0]) == levelId) { + bits |= val; + } + } + return bits; +} + +extern "C" void port_puzzleStep_orBits(int32_t puzzleId, int32_t bits) { + if (!mirrorLive(puzzleId)) { + return; + } + int32_t map = (int32_t)gsworld_getMap(); + std::array key = { map, puzzleId }; + int32_t before = sPuzzleBits.count(key) ? sPuzzleBits[key] : 0; + int32_t after = before | bits; + if (after == before) { + return; + } + sPuzzleBits[key] = after; + Anchor::GetInstance()->SendPacket_PuzzleStep(puzzleId, after, map); +} + +void Anchor::SendPacket_PuzzleStep(s32 puzzleId, s32 bits, s32 map, s32 phash) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = PUZZLE_STEP; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["puzzle"] = puzzleId; + payload["bits"] = bits; + payload["map"] = map; + // A positional puzzle ships its member's hash instead of a bit; 0 = an ordinary bitmask step. + if (phash != 0) { + payload["phash"] = phash; + } + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_PuzzleStep(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s32 puzzleId = payload.at("puzzle").get(); + s32 map = payload.at("map").get(); + if (!mirrorAllowedFor(puzzleId, map)) { + return; + } + s32 phash = payload.value("phash", (s32)0); + if (phash != 0) { + sPuzzlePos[{ map, puzzleId }].insert(phash); + return; + } + sPuzzleBits[{ map, puzzleId }] |= payload.at("bits").get(); +} + +std::vector port_puzzleStep_snapshot() { + std::vector flat; + flat.reserve(sPuzzleBits.size() * 3); + for (const auto& [key, bits] : sPuzzleBits) { + flat.push_back(key[0]); + flat.push_back(key[1]); + flat.push_back(bits); + } + return flat; +} + +void port_puzzleStep_restore(const std::vector& flat) { + sPuzzleBits.clear(); + for (size_t i = 0; i + 3 <= flat.size(); i += 3) { + if (!mirrorAllowedFor(flat[i + 1], flat[i])) { + continue; + } + sPuzzleBits[{ flat[i], flat[i + 1] }] = flat[i + 2]; + } +} + +void port_puzzleStep_clearForLevel(int32_t levelId) { + std::erase_if(sPuzzleBits, + [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); + std::erase_if(sPuzzleCounts, + [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); + std::erase_if(sPuzzlePos, + [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); +} + +/** + * PUZZLE_POS + * + * Positional companion to PUZZLE_STEP for steps keyed by spawn position instead of a bit index + * (FP's Sir Slushes). Rides the same PUZZLE_STEP packet via the phash field. + */ + +extern "C" int32_t port_puzzlePos_isMarked(int32_t puzzleId, int32_t x, int32_t y, int32_t z) { + if (!mirrorLive(puzzleId)) { + return 0; + } + auto it = sPuzzlePos.find({ (int32_t)gsworld_getMap(), puzzleId }); + return (it != sPuzzlePos.end() && it->second.count(puzzlePosHash(x, y, z))) ? 1 : 0; +} + +extern "C" void port_puzzlePos_mark(int32_t puzzleId, int32_t x, int32_t y, int32_t z) { + if (!mirrorLive(puzzleId)) { + return; + } + int32_t map = (int32_t)gsworld_getMap(); + int32_t hash = puzzlePosHash(x, y, z); + auto& set = sPuzzlePos[{ map, puzzleId }]; + if (!set.insert(hash).second) { + return; + } + Anchor::GetInstance()->SendPacket_PuzzleStep(puzzleId, 0, map, hash); +} + +// Flat [map, puzzleId, count, hashes...] runs. +std::vector port_puzzlePos_snapshot() { + std::vector flat; + for (const auto& [key, set] : sPuzzlePos) { + flat.push_back(key[0]); + flat.push_back(key[1]); + flat.push_back((int32_t)set.size()); + for (int32_t h : set) { + flat.push_back(h); + } + } + return flat; +} + +void port_puzzlePos_restore(const std::vector& flat) { + sPuzzlePos.clear(); + size_t i = 0; + while (i + 3 <= flat.size()) { + int32_t map = flat[i], puzzleId = flat[i + 1], count = flat[i + 2]; + i += 3; + // Still consume the run's hashes when filtered so the stream stays aligned. + const bool allowed = mirrorAllowedFor(puzzleId, map); + for (int32_t j = 0; j < count && i < flat.size(); j++, i++) { + if (allowed) { + sPuzzlePos[{ map, puzzleId }].insert(flat[i]); + } + } + } +} + +/** + * PUZZLE_COUNT + * + * Companion to PUZZLE_STEP for count-based progress (Eyrie's fed worms, Nabnut's acorns). + * Not home-scoped: counters never touch flag indices (keyed by the real map, applied only + * to actor state), and scoping them would brick a relocated Eyrie/Nabnut. + */ + +extern "C" int32_t port_puzzleCount_get(int32_t counterId) { + auto it = sPuzzleCounts.find({ (int32_t)gsworld_getMap(), counterId }); + return it != sPuzzleCounts.end() ? it->second : 0; +} + +extern "C" void port_puzzleCount_add(int32_t counterId, int32_t delta) { + int32_t map = (int32_t)gsworld_getMap(); + sPuzzleCounts[{ map, counterId }] += delta; + Anchor::GetInstance()->SendPacket_PuzzleCount(counterId, delta, map); +} + +void Anchor::SendPacket_PuzzleCount(s32 counterId, s32 delta, s32 map) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = PUZZLE_COUNT; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["counter"] = counterId; + payload["delta"] = delta; + payload["map"] = map; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_PuzzleCount(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s32 counterId = payload.at("counter").get(); + s32 delta = payload.at("delta").get(); + s32 map = payload.at("map").get(); + + sPuzzleCounts[{ map, counterId }] += delta; +} + +std::vector port_puzzleCount_snapshot() { + std::vector flat; + flat.reserve(sPuzzleCounts.size() * 3); + for (const auto& [key, count] : sPuzzleCounts) { + flat.push_back(key[0]); + flat.push_back(key[1]); + flat.push_back(count); + } + return flat; +} + +void port_puzzleCount_restore(const std::vector& flat) { + sPuzzleCounts.clear(); + for (size_t i = 0; i + 3 <= flat.size(); i += 3) { + sPuzzleCounts[{ flat[i], flat[i + 1] }] = flat[i + 2]; + } +} + +void RegisterPuzzleStep_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + sPuzzleBits.clear(); + sPuzzleCounts.clear(); + sPuzzlePos.clear(); + }); + // Treasure hunt has no actor to poll until the first X is busted. + REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + if (gsworld_getMap() == MAP_7_TTC_TREASURE_TROVE_COVE) { + chTreasurehunt_netTick(); + } + }); +} + +static RegisterShipInitFunc initPuzzleStep(RegisterPuzzleStep_Init, {}); diff --git a/src/port/Network/Anchor/Packets/RequestTeamState.cpp b/src/port/Network/Anchor/Packets/RequestTeamState.cpp index 220a16f80..7ebbfe2b0 100644 --- a/src/port/Network/Anchor/Packets/RequestTeamState.cpp +++ b/src/port/Network/Anchor/Packets/RequestTeamState.cpp @@ -1,7 +1,6 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/OTRGlobals.h" /** * REQUEST_TEAM_STATE @@ -16,8 +15,10 @@ * state */ -void Anchor::SendPacket_RequestTeamState() { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { +void Anchor::SendPacket_RequestTeamState(bool force) { + // `force` bypasses the IsSaveLoaded check: OnGameLoad fires from gameFile_load while the map is + // still FILE_SELECT, so the save is loading but IsSaveLoaded() is still false. + if ((!force && !IsSaveLoaded()) || !roomState.syncItemsAndFlags) { return; } diff --git a/src/port/Network/Anchor/Packets/RequestTeleport.cpp b/src/port/Network/Anchor/Packets/RequestTeleport.cpp index ab02cedea..17a0e8926 100644 --- a/src/port/Network/Anchor/Packets/RequestTeleport.cpp +++ b/src/port/Network/Anchor/Packets/RequestTeleport.cpp @@ -1,13 +1,11 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" /** * REQUEST_TELEPORT * - * Because we don't have all the necessary information to directly teleport to a player, we emit a request, - * in which they will respond with a TELEPORT_TO packet, with the necessary information. + * Asks a client for their location; they reply with TELEPORT_TO (map, position, yaw). */ void Anchor::SendPacket_RequestTeleport(uint32_t clientId) { @@ -31,61 +29,33 @@ void Anchor::HandlePacket_RequestTeleport(nlohmann::json& payload) { SendPacket_TeleportTo(clientId); } -// Reusable function to check if teleporting to a client is allowed bool Anchor::CanTeleportTo(uint32_t clientId) { - // Teleporting is disabled if (roomState.teleportMode == 0) { return false; } - // You're not loaded into a save if (!IsSaveLoaded()) { return false; } - // The client doesn't exist if (clients.find(clientId) == clients.end()) { return false; } AnchorClient& client = clients[clientId]; - // The client is yourself if (client.self) { return false; } - // The client isn't online or loaded into a save if (!client.online || !client.isSaveLoaded) { return false; } - // Teleporting to team only, but the client is not on your team std::string ownTeamId = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); if (roomState.teleportMode == 1 && client.teamId != ownTeamId) { return false; } - //// Problematic scenes for teleporting - // if (client.sceneNum == SCENE_ID_MAX || client.sceneNum == SCENE_GROTTOS || client.sceneNum == SCENE_MARKET_DAY || - // client.sceneNum == SCENE_MARKET_NIGHT || client.sceneNum == SCENE_MARKET_RUINS || - // client.sceneNum == SCENE_MARKET_ENTRANCE_DAY || client.sceneNum == SCENE_MARKET_ENTRANCE_NIGHT || - // client.sceneNum == SCENE_MARKET_ENTRANCE_RUINS || client.sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY || - // client.sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT || - // client.sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS || client.sceneNum == SCENE_BACK_ALLEY_DAY || - // client.sceneNum == SCENE_BACK_ALLEY_NIGHT) { - // return false; - // } - - //// Child can't teleport to Ganon's Castle exterior - // if (client.sceneNum == SCENE_OUTSIDE_GANONS_CASTLE && gSaveContext.linkAge == LINK_AGE_CHILD) { - // return false; - // } - - //// Adult can't teleport to Hyrule Castle exterior - // if (client.sceneNum == SCENE_HYRULE_CASTLE && gSaveContext.linkAge == LINK_AGE_ADULT) { - // return false; - // } - return true; } diff --git a/src/port/Network/Anchor/Packets/ScopedFlag.cpp b/src/port/Network/Anchor/Packets/ScopedFlag.cpp new file mode 100644 index 000000000..b6b6e938a --- /dev/null +++ b/src/port/Network/Anchor/Packets/ScopedFlag.cpp @@ -0,0 +1,79 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include "functions.h" + +static uint32_t sMapFlagSetRemotely = 0; + +extern "C" int32_t port_mapFlag_wasSetRemotely(int32_t index) { + return (index >= 0 && index < 32 && (sMapFlagSetRemotely & (1u << index))) ? 1 : 0; +} + +/** + * SCOPED_FLAG + * + * Realtime sync of a transient level-/map flag; ctx = sender's level/map id. + */ + +void Anchor::SendPacket_ScopedFlag(u8 space, s16 index, u8 value) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = SCOPED_FLAG; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["space"] = space; + payload["index"] = index; + payload["value"] = value; + + if (space == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC) { + payload["ctx"] = (s32)map_getLevel(gsworld_getMap()); + SendToCurrentLevelPlayers(payload); + } else { + payload["ctx"] = (s32)gsworld_getMap(); + SendToCurrentMapPlayers(payload); + } +} + +void Anchor::HandlePacket_ScopedFlag(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + u8 space = payload.at("space").get(); + s16 index = payload.at("index").get(); + u8 value = payload.at("value").get(); + s32 ctx = payload.at("ctx").get(); + + if (space == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC) { + if ((s32)map_getLevel(gsworld_getMap()) == ctx) { + levelSpecificFlags_setEx(index, value, 0); + } + } else if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC) { + if ((s32)gsworld_getMap() == ctx) { + mapSpecificFlags_setEx(index, value, 0); + if (value && index >= 0 && index < 32) { + sMapFlagSetRemotely |= (1u << index); + } + RevealSwitchHoneycomb(); + } + } +} + +void RegisterScopedFlag_Init() { + REGISTER_LISTENER(OnGameFlagSet, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + auto ev = reinterpret_cast(event); + if (ev->flagSpace == ANCHOR_FLAGSPACE_MAP_SPECIFIC && ev->index >= 0 && ev->index < 32) { + sMapFlagSetRemotely &= ~(1u << ev->index); + } + }); + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sMapFlagSetRemotely = 0; }); +} + +static RegisterShipInitFunc initScopedFlag(RegisterScopedFlag_Init, {}); diff --git a/src/port/Network/Anchor/Packets/ScopedState.cpp b/src/port/Network/Anchor/Packets/ScopedState.cpp new file mode 100644 index 000000000..ee0f7c1fb --- /dev/null +++ b/src/port/Network/Anchor/Packets/ScopedState.cpp @@ -0,0 +1,88 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include +#include +#include + +#include "functions.h" + +/** + * REQUEST_SCOPED_STATE / SCOPED_STATE + * + * On map load, a client asks the team for current level/map flag state; same-scope teammates reply. + */ + +void Anchor::SendPacket_RequestScopedState(GameMap map) { + nlohmann::json payload; + payload["type"] = REQUEST_SCOPED_STATE; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["level"] = (s32)map_getLevel((enum map_e)map); + payload["map"] = (s32)map; + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_RequestScopedState(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s32 reqLevel = payload.at("level").get(); + s32 reqMap = payload.at("map").get(); + + nlohmann::json response; + response["type"] = SCOPED_STATE; + response["targetClientId"] = payload.at("clientId").get(); + bool any = false; + + if ((s32)map_getLevel(gsworld_getMap()) == reqLevel) { + s32 size; + u8* addr; + levelSpecificFlags_getSizeAndPtr(&size, &addr); + std::vector levelFlags(addr, addr + size); + for (s32 idx = 0; idx < size * 8; idx++) { + if (Anchor_ScopedFlagExcluded(ANCHOR_FLAGSPACE_LEVEL_SPECIFIC, idx)) { + levelFlags[idx >> 3] &= ~(1 << (idx & 7)); + } + } + response["level"] = reqLevel; + response["levelFlags"] = levelFlags; + any = true; + } + if ((s32)gsworld_getMap() == reqMap) { + u32 mapFlags = (u32)mapSpecificFlags_getAll(); + for (s32 idx = 0; idx < 32; idx++) { + if (Anchor_ScopedFlagExcluded(ANCHOR_FLAGSPACE_MAP_SPECIFIC, idx)) { + mapFlags &= ~(1u << idx); + } + } + response["map"] = reqMap; + response["mapFlags"] = mapFlags; + any = true; + } + + if (any) { + SendJsonToRemote(response); + } +} + +void Anchor::HandlePacket_ScopedState(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + if (payload.contains("levelFlags") && (s32)map_getLevel(gsworld_getMap()) == payload.at("level").get()) { + auto bytes = payload["levelFlags"].get>(); + s32 size; + u8* addr; + levelSpecificFlags_getSizeAndPtr(&size, &addr); + s32 count = std::min(size, (s32)bytes.size()); + for (s32 i = 0; i < count; i++) { + addr[i] |= bytes[i]; + } + } + if (payload.contains("mapFlags") && (s32)gsworld_getMap() == payload.at("map").get()) { + u32 mapFlags = payload["mapFlags"].get(); + mapSpecificFlags_setAll(mapSpecificFlags_getAll() | mapFlags); + RevealSwitchHoneycomb(); + } +} diff --git a/src/port/Network/Anchor/Packets/ServerMessage.cpp b/src/port/Network/Anchor/Packets/ServerMessage.cpp index dfa3ece6b..ed1dab04d 100644 --- a/src/port/Network/Anchor/Packets/ServerMessage.cpp +++ b/src/port/Network/Anchor/Packets/ServerMessage.cpp @@ -1,7 +1,6 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "port/UI/Notification.h" /** diff --git a/src/port/Network/Anchor/Packets/SetAbility.cpp b/src/port/Network/Anchor/Packets/SetAbility.cpp new file mode 100644 index 000000000..903ba8c40 --- /dev/null +++ b/src/port/Network/Anchor/Packets/SetAbility.cpp @@ -0,0 +1,51 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "functions.h" +extern "C" { +void chSmBottles_netApplyTutorialComplete(void); +} + +/** + * SET_ABILITY + * + * Realtime sync of a learned move. Not queued. + */ + +void Anchor::SendPacket_SetAbility(s16 move, u8 value) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = SET_ABILITY; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["quiet"] = true; + payload["move"] = move; + payload["value"] = value; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_SetAbility(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s16 move = payload.at("move").get(); + u8 value = payload.at("value").get(); + + ability_setLearnedEx(move, value, 0); + if (value) { + ability_setHasUsed((enum ability_e)move); + } + + // A remote unlock just completed the SM tutorial set while we're standing in Spiral + // Mountain with a pre-completion world. Apply the completion state live. + if (value && (s32)gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN && + !mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED) && + chmole_learnedAllSpiralMountainAbilities()) { + chSmBottles_netApplyTutorialComplete(); + } +} diff --git a/src/port/Network/Anchor/Packets/SetCheckStatus.cpp b/src/port/Network/Anchor/Packets/SetCheckStatus.cpp index a0a4334fc..74e9a4698 100644 --- a/src/port/Network/Anchor/Packets/SetCheckStatus.cpp +++ b/src/port/Network/Anchor/Packets/SetCheckStatus.cpp @@ -1,57 +1,80 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -//#include "soh/OTRGlobals.h" -static bool isResultOfHandling = false; +#include "port/UI/cvar_prefixes.h" +#include "port/Rando/Rando.h" +#include "port/Rando/CustomObject/CustomObject.h" +#include "port/Rando/StaticData/StaticData.h" + +#include "functions.h" +extern "C" { +void marker_despawn(ActorMarker* marker); +} + +Actor* FindActorByRandoCheckId(RandoCheckId randoCheckId); /** * SET_CHECK_STATUS * - * Fired when a check status is updated or skipped + * Fired when a shuffled rando check is first obtained; teammates mark it obtained and + * despawn their copy if in the same map. */ -void Anchor::SendPacket_SetCheckStatus(/*RandomizerCheck rc*/) { - // if (!IsSaveLoaded() || isResultOfHandling) { - // return; - // } - // - // auto randoContext = Rando::Context::GetRawInstance(); - // - // nlohmann::json payload; - // payload["type"] = SET_CHECK_STATUS; - // payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - // payload["addToQueue"] = true; - // payload["rc"] = rc; - // payload["status"] = randoContext->GetItemLocation(rc)->GetCheckStatus(); - // payload["skipped"] = randoContext->GetItemLocation(rc)->GetIsSkipped(); - // payload["quiet"] = true; - // - // SendJsonToRemote(payload); +void Anchor::SendPacket_SetCheckStatus(s32 rc, s32 map) { + if (!IS_RANDO || !IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = SET_CHECK_STATUS; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["rc"] = rc; + payload["map"] = map; + + SendJsonToRemote(payload); +} + +// Adopt a check a teammate obtained: despawn our copy, mark obtained silently (no item grant, +// notification, or re-broadcast). +void Anchor::AdoptRemoteCheck(s32 rcRaw) { + RandoCheckId rc = (RandoCheckId)rcRaw; + if (rc <= RC_UNKNOWN || rc >= RC_MAX || RANDO_SAVE_CHECKS[rc].eligible) { + return; + } + if (CustomObject::CheckSpawnedIdList(rc)) { + Actor* actor = FindActorByRandoCheckId(rc); + if (actor != NULL && actor->marker != NULL) { + marker_despawn(actor->marker); + } + } + CustomObject::CheckObtainedEX(rc, true); } void Anchor::HandlePacket_SetCheckStatus(nlohmann::json& payload) { - // if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - // return; - // } - // - // auto randoContext = Rando::Context::GetRawInstance(); - // - // RandomizerCheck rc = payload.at("rc").get(); - // RandomizerCheckStatus status = payload.at("status").get(); - // bool skipped = payload.at("skipped").get(); - // - // isResultOfHandling = true; - // - // if (randoContext->GetItemLocation(rc)->GetCheckStatus() != status) { - // randoContext->GetItemLocation(rc)->SetCheckStatus(status); - // } - // if (randoContext->GetItemLocation(rc)->GetIsSkipped() != skipped) { - // randoContext->GetItemLocation(rc)->SetIsSkipped(skipped); - // } - // - // CheckTracker::RecalculateAllAreaTotals(); - // CheckTracker::RecalculateAvailableChecks(); - // isResultOfHandling = false; + if (!IS_RANDO || !IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + RandoCheckId rc = (RandoCheckId)payload.at("rc").get(); + s32 map = payload.at("map").get(); + + if (rc <= RC_UNKNOWN || rc >= RC_MAX) { + return; + } + if (RANDO_SAVE_CHECKS[rc].eligible) { + return; + } + + // BGS timed-switch checks cleanup + if ((s32)gsworld_getMap() == map && (rc == RC_BGS_JIGGY_ELEVATED_WALKWAY || rc == RC_BGS_JIGGY_MAZE)) { + func_802D6924(); + } + + AdoptRemoteCheck(rc); + + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RandoNotifications"), 0) && ShouldShowNotifications()) { + Rando::StaticData::SendRemoteCheckNotification(rc, GetClientName(payload.value("clientId", 0u))); + } } diff --git a/src/port/Network/Anchor/Packets/SetFlag.cpp b/src/port/Network/Anchor/Packets/SetFlag.cpp index 88e754f0f..91a57eb06 100644 --- a/src/port/Network/Anchor/Packets/SetFlag.cpp +++ b/src/port/Network/Anchor/Packets/SetFlag.cpp @@ -1,22 +1,47 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -//#include "soh/OTRGlobals.h" -extern "C" { #include "functions.h" -// extern PlayState* gPlayState; -} +#include "port/Patches/Patches.h" +#include "port/Rando/Rando.h" +#include "port/UI/Notification.h" /** * SET_FLAG * - * Fired when a flag is set in the save context + * Fired when a flag bit is set (raised) in either flag space. */ -void Anchor::SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag) { +static const char* LevelOpenSeenFlagName(s16 flag) { + switch (flag) { + case 0x28: + return "Mumbo's Mountain"; + case 0x29: + return "Treasure Trove Cove"; + case 0x2A: + return "Clanker's Cavern"; + case 0x2B: + return "Bubblegloop Swamp"; + case 0x2C: + return "Freezeezy Peak"; + case 0x2D: + return "Gobi's Valley"; + case 0x2E: + return "Mad Monster Mansion"; + case 0x2F: + return "Rusty Bucket Bay"; + case 0x30: + return "Click Clock Wood"; + case FILEPROG_E2_DOOR_OF_GRUNTY_OPEN: + return "the door to Gruntilda"; + default: + return nullptr; + } +} + +void Anchor::SendPacket_SetFlag(u8 flagSpace, s16 flag) { if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } @@ -25,8 +50,7 @@ void Anchor::SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag) { payload["type"] = SET_FLAG; payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); payload["addToQueue"] = true; - payload["sceneNum"] = sceneNum; - payload["flagType"] = flagType; + payload["flagSpace"] = flagSpace; payload["flag"] = flag; SendJsonToRemote(payload); @@ -37,37 +61,28 @@ void Anchor::HandlePacket_SetFlag(nlohmann::json& payload) { return; } - s16 sceneNum = payload.at("sceneNum").get(); - s16 flagType = payload.at("flagType").get(); + u8 flagSpace = payload.at("flagSpace").get(); s16 flag = payload.at("flag").get(); - // if (sceneNum == SCENE_ID_MAX) { - // auto effect = new GameInteractionEffect::SetFlag(); - // effect->parameters[0] = flagType; - // effect->parameters[1] = flag; - // effect->Apply(); - - // // Special case: If King Zora moved, and the player has Ruto's Letter, convert it to an empty bottle - // if (flagType == FLAG_EVENT_CHECK_INF && flag == EVENTCHKINF_KING_ZORA_MOVED && - // Inventory_HasSpecificBottle(ITEM_LETTER_RUTO)) { - // Inventory_ReplaceItem(gPlayState, ITEM_LETTER_RUTO, ITEM_BOTTLE); - // } - //} else { - // // Special case: Ignore water temple water level flags, stored at 0x1C, 0x1D, 0x1E. - // if (sceneNum == SCENE_WATER_TEMPLE && flagType == FLAG_SCENE_SWITCH && - // (flag == 0x1C || flag == 0x1D || flag == 0x1E)) { - // return; - // } - - // // Special case: Ignore forest temple elevator flag, stored at 0x1B. - // if (sceneNum == SCENE_FOREST_TEMPLE && flagType == FLAG_SCENE_SWITCH && flag == 0x1B) { - // return; - // } - - // auto effect = new GameInteractionEffect::SetSceneFlag(); - // effect->parameters[0] = sceneNum; - // effect->parameters[1] = flagType; - // effect->parameters[2] = flag; - // effect->Apply(); - //} + if (flagSpace == ANCHOR_FLAGSPACE_RANDO_INF) { + // Non-derived rando flag; set directly. + if (IS_RANDO && flag > RANDO_INF_UNKNOWN && flag < RANDO_INF_MAX) { + RANDO_SAVE_FLAGS[flag].flagState = 1; + } + } else if (flagSpace == ANCHOR_FLAGSPACE_VOLATILE) { + volatileFlag_setEx((enum volatile_flags_e)flag, 1, 0); + } else { + bool wasSet = fileProgressFlag_get((enum file_progress_e)flag) != 0; + fileProgressFlag_setEx((enum file_progress_e)flag, 1, 0); + port_progressFlag_remoteCue(flag); + // Vanilla only; rando reports world access via SET_CHECK_STATUS instead. + if (!wasSet && !IS_RANDO && ShouldShowNotifications()) { + if (const char* opened = LevelOpenSeenFlagName(flag)) { + Notification::Emit({ + .prefix = GetClientName(payload.value("clientId", 0u)), + .message = std::string("opened ") + opened, + }); + } + } + } } diff --git a/src/port/Network/Anchor/Packets/SetItemCount.cpp b/src/port/Network/Anchor/Packets/SetItemCount.cpp new file mode 100644 index 000000000..0ae95b34c --- /dev/null +++ b/src/port/Network/Anchor/Packets/SetItemCount.cpp @@ -0,0 +1,47 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "functions.h" +extern "C" { +s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent); +} + +/** + * ITEM_COUNT + * + * Realtime sync of a spendable item count (absolute value). Not queued. + */ + +void Anchor::SendPacket_SetItemCount(s16 item, s32 count) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = ITEM_COUNT; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["quiet"] = true; + payload["item"] = item; + payload["count"] = count; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_SetItemCount(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s16 item = payload.at("item").get(); + s32 count = payload.at("count").get(); + + // Jiggy-total increase is a teammate's collect: apply silently (paired COLLECT_ITEM pops the + // HUD counter). Decreases (pedestal spends) keep the vanilla total pop. + if (item == ITEM_26_JIGGY_TOTAL && count > item_getCount(ITEM_26_JIGGY_TOTAL)) { + item_adjustByDiff((enum item_e)item, count - item_getCount(ITEM_26_JIGGY_TOTAL), 1, 0); + return; + } + + item_setEx(item, count, 0); +} diff --git a/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp b/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp new file mode 100644 index 000000000..5441ecf81 --- /dev/null +++ b/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp @@ -0,0 +1,47 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "functions.h" +extern "C" { +void chHoneycomb_netSpawnDropAt(s32 uid, s32 bundleId, f32 x, f32 y, f32 z); +} + +void Anchor::SendPacket_SpawnHoneycomb(s16 honeycombId, s32 bundleId, f32 x, f32 y, f32 z) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + nlohmann::json payload; + payload["type"] = HONEYCOMB_SPAWN; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["honeycombId"] = honeycombId; + payload["bundle"] = bundleId; + payload["x"] = x; + payload["y"] = y; + payload["z"] = z; + payload["ctx"] = (s32)gsworld_getMap(); + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_SpawnHoneycomb(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s16 honeycombId = payload.at("honeycombId").get(); + if ((s32)gsworld_getMap() != payload.at("ctx").get()) { + return; + } + if (honeycombscore_get((enum honeycomb_e)honeycombId)) { + return; + } + // Already present locally, nothing to add. + if (actorArray_findHoneycombMarkerById((enum honeycomb_e)honeycombId) != nullptr) { + return; + } + + chHoneycomb_netSpawnDropAt(honeycombId, payload.at("bundle").get(), payload.at("x").get(), + payload.at("y").get(), payload.at("z").get()); +} diff --git a/src/port/Network/Anchor/Packets/SpawnJiggy.cpp b/src/port/Network/Anchor/Packets/SpawnJiggy.cpp new file mode 100644 index 000000000..54827734f --- /dev/null +++ b/src/port/Network/Anchor/Packets/SpawnJiggy.cpp @@ -0,0 +1,171 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include +#include + +#include "functions.h" + +/** + * JIGGY_SPAWN + * + * Sync of dynamically spawned jiggies (witch-switch puzzle, minigame reward, jinjo fifth, etc). + * Team-wide record (map -> jiggyId -> position) re-applied every map visit. + */ + +struct SpawnedJiggy { + int16_t jiggyId; + float x; + float y; + float z; + bool inFlight = false; +}; +std::map> sSpawnedJiggies; + +SpawnedJiggy& recordJiggySpawn(int32_t map, int16_t jiggyId, float x, float y, float z) { + auto& list = sSpawnedJiggies[map]; + for (auto& pj : list) { + if (pj.jiggyId == jiggyId) { + pj.x = x; + pj.y = y; + pj.z = z; + return pj; + } + } + list.push_back({ jiggyId, x, y, z }); + return list.back(); +} + +void trySpawnRecordedJiggy(SpawnedJiggy& pj) { + if (jiggyscore_isCollected((enum jiggy_e)pj.jiggyId)) { + return; + } + if (jiggylist_hasSpawnedObject((enum jiggy_e)pj.jiggyId)) { + pj.inFlight = false; + return; + } + if (pj.inFlight) { + return; + } + f32 pos[3] = { pj.x, pj.y, pj.z }; + codeABC00_spawnJiggyAtLocationEx((enum jiggy_e)pj.jiggyId, pos, 0); // silent, no re-broadcast + pj.inFlight = true; +} + +void Anchor::SendPacket_SpawnJiggy(s16 jiggyId, f32 x, f32 y, f32 z) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s32 map = (s32)gsworld_getMap(); + recordJiggySpawn(map, jiggyId, x, y, z); + + nlohmann::json payload; + payload["type"] = JIGGY_SPAWN; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["jiggyId"] = jiggyId; + payload["x"] = x; + payload["y"] = y; + payload["z"] = z; + payload["map"] = map; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_SpawnJiggy(nlohmann::json& payload) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + + s16 jiggyId = payload.at("jiggyId").get(); + s32 map = payload.at("map").get(); + f32 x = payload.at("x").get(); + f32 y = payload.at("y").get(); + f32 z = payload.at("z").get(); + + SpawnedJiggy& pj = recordJiggySpawn(map, jiggyId, x, y, z); + + if ((s32)gsworld_getMap() == map) { + trySpawnRecordedJiggy(pj); + } +} + +void Anchor::FlushPendingJiggySpawns() { + auto it = sSpawnedJiggies.find((s32)gsworld_getMap()); + if (it == sSpawnedJiggies.end()) { + return; + } + auto& list = it->second; + for (size_t i = 0; i < list.size();) { + auto& pj = list[i]; + if (jiggyscore_isCollected((enum jiggy_e)pj.jiggyId)) { + list.erase(list.begin() + i); + continue; + } + trySpawnRecordedJiggy(pj); + i++; + } +} + +// Team-state snapshot/restore (UpdateTeamState.cpp). Flat [map, jiggyId, x, y, z] tuples. +std::vector port_jiggySpawn_snapshot() { + std::vector flat; + for (const auto& [map, list] : sSpawnedJiggies) { + for (const auto& pj : list) { + flat.push_back(map); + flat.push_back(pj.jiggyId); + flat.push_back((int32_t)pj.x); + flat.push_back((int32_t)pj.y); + flat.push_back((int32_t)pj.z); + } + } + return flat; +} + +void port_jiggySpawn_restore(const std::vector& flat) { + sSpawnedJiggies.clear(); + for (size_t i = 0; i + 5 <= flat.size(); i += 5) { + sSpawnedJiggies[flat[i]].push_back( + { (int16_t)flat[i + 1], (float)flat[i + 2], (float)flat[i + 3], (float)flat[i + 4] }); + } +} + +extern "C" void port_jiggySpawn_remove(int32_t jiggyId) { + for (auto& [map, list] : sSpawnedJiggies) { + std::erase_if(list, [jiggyId](const SpawnedJiggy& pj) { return pj.jiggyId == jiggyId; }); + } +} + +extern "C" int32_t port_jiggySpawn_isRecorded(int32_t jiggyId) { + if (jiggyscore_isCollected((enum jiggy_e)jiggyId)) { + return 0; + } + for (const auto& [map, list] : sSpawnedJiggies) { + for (const auto& pj : list) { + if (pj.jiggyId == jiggyId) { + return 1; + } + } + } + return 0; +} + +void RegisterSpawnJiggy_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sSpawnedJiggies.clear(); }); + + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + for (auto& [map, list] : sSpawnedJiggies) { + for (auto& pj : list) { + pj.inFlight = false; + } + } + }); +} + +static RegisterShipInitFunc initSpawnJiggy(RegisterSpawnJiggy_Init, {}); diff --git a/src/port/Network/Anchor/Packets/TeleportTo.cpp b/src/port/Network/Anchor/Packets/TeleportTo.cpp index 31140ff70..ba66addf4 100644 --- a/src/port/Network/Anchor/Packets/TeleportTo.cpp +++ b/src/port/Network/Anchor/Packets/TeleportTo.cpp @@ -1,18 +1,16 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -#include "port/Network/Anchor/JsonConversions.hpp" -extern "C" { -#include "macros.h" -// extern PlayState* gPlayState; -} +#include "functions.h" + +// Exit id the game reserves for "spawn at an explicit position" (see func_8028E4B0). +#define EXIT_WARP_DESTINATION 0x63 /** * TELEPORT_TO * - * See REQUEST_TELEPORT for more information, this is the second part of the process. + * See REQUEST_TELEPORT; carries the sender's live map/position/yaw. */ void Anchor::SendPacket_TeleportTo(uint32_t clientId) { @@ -20,16 +18,18 @@ void Anchor::SendPacket_TeleportTo(uint32_t clientId) { return; } - /*Player* player = GET_PLAYER(gPlayState); + f32 pos[3]; + player_getPosition(pos); nlohmann::json payload; payload["type"] = TELEPORT_TO; payload["targetClientId"] = clientId; - payload["entranceIndex"] = gSaveContext.entranceIndex; - payload["roomIndex"] = gPlayState->roomCtx.curRoom.num; - payload["posRot"] = player->actor.world; + payload["map"] = gsworld_getMap(); + payload["exit"] = gsworld_getExit(); + payload["pos"] = pos; + payload["yaw"] = player_getYaw(); - SendJsonToRemote(payload);*/ + SendJsonToRemote(payload); } void Anchor::HandlePacket_TeleportTo(nlohmann::json& payload) { @@ -37,23 +37,18 @@ void Anchor::HandlePacket_TeleportTo(nlohmann::json& payload) { return; } - // s32 entranceIndex = payload.at("entranceIndex").get(); - // s8 roomIndex = payload.at("roomIndex").get(); - // PosRot posRot = payload.at("posRot").get(); - - // gPlayState->nextEntranceIndex = entranceIndex; - // gPlayState->transitionTrigger = TRANS_TRIGGER_START; - // gPlayState->transitionType = TRANS_TYPE_INSTANT; - // gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = entranceIndex; - // gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = roomIndex; - // gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = posRot.pos; - // gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = posRot.rot.y; - // gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0xDFF; - // gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST; - // gSaveContext.respawnFlag = 1; - // static HOOK_ID hookId = 0; - // hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, { - // *should = false; - // GameInteractor::Instance->UnregisterGameHookForID(hookId); - // }); + GameMap map = payload.at("map").get(); + std::vector pos = payload.at("pos").get>(); + f32 yaw = payload.at("yaw").get(); + + if (map == (GameMap)gsworld_getMap()) { + yaw_set(yaw); + yaw_setIdeal(yaw); + yaw_applyIdeal(); + func_8028F85C(pos.data()); + return; + } + + player_setWarpDestination(pos.data(), yaw, payload.value("exit", 0)); + func_8031D04C(map, EXIT_WARP_DESTINATION); } diff --git a/src/port/Network/Anchor/Packets/UnsetFlag.cpp b/src/port/Network/Anchor/Packets/UnsetFlag.cpp index e1b88908c..745e60f51 100644 --- a/src/port/Network/Anchor/Packets/UnsetFlag.cpp +++ b/src/port/Network/Anchor/Packets/UnsetFlag.cpp @@ -1,22 +1,16 @@ #include "port/Network/Anchor/Anchor.h" #include #include -//#include "soh/Enhancements/game-interactor/GameInteractor.h" -//#include "soh/OTRGlobals.h" -extern "C" { #include "functions.h" -//#include "soh/Enhancements/randomizer/ShuffleTradeItems.h" -// extern PlayState* gPlayState; -} /** * UNSET_FLAG * - * Fired when a flag is unset in the save context + * Fired when a flag bit is cleared (lowered) in either flag space. */ -void Anchor::SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag) { +void Anchor::SendPacket_UnsetFlag(u8 flagSpace, s16 flag) { if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } @@ -25,8 +19,7 @@ void Anchor::SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag) { payload["type"] = UNSET_FLAG; payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); payload["addToQueue"] = true; - payload["sceneNum"] = sceneNum; - payload["flagType"] = flagType; + payload["flagSpace"] = flagSpace; payload["flag"] = flag; SendJsonToRemote(payload); @@ -37,73 +30,12 @@ void Anchor::HandlePacket_UnsetFlag(nlohmann::json& payload) { return; } - s16 sceneNum = payload.at("sceneNum").get(); - s16 flagType = payload.at("flagType").get(); + u8 flagSpace = payload.at("flagSpace").get(); s16 flag = payload.at("flag").get(); - // if (sceneNum == SCENE_ID_MAX) { - // auto effect = new GameInteractionEffect::UnsetFlag(); - // effect->parameters[0] = flagType; - // effect->parameters[1] = flag; - // effect->Apply(); - - // // Special case: If an adult trade item flag is unset, replace the item if the player has it equipped - // if (flagType == FLAG_RANDOMIZER_INF && - // (flag >= RAND_INF_ADULT_TRADES_HAS_POCKET_EGG && flag <= RAND_INF_ADULT_TRADES_HAS_CLAIM_CHECK)) { - // u16 itemToReplace = ITEM_POCKET_EGG; - // switch (flag) { - // case RAND_INF_ADULT_TRADES_HAS_POCKET_EGG: - // itemToReplace = ITEM_POCKET_EGG; - // break; - // case RAND_INF_ADULT_TRADES_HAS_POCKET_CUCCO: - // itemToReplace = ITEM_POCKET_CUCCO; - // break; - // case RAND_INF_ADULT_TRADES_HAS_COJIRO: - // itemToReplace = ITEM_COJIRO; - // break; - // case RAND_INF_ADULT_TRADES_HAS_ODD_MUSHROOM: - // itemToReplace = ITEM_ODD_MUSHROOM; - // break; - // case RAND_INF_ADULT_TRADES_HAS_ODD_POTION: - // itemToReplace = ITEM_ODD_POTION; - // break; - // case RAND_INF_ADULT_TRADES_HAS_SAW: - // itemToReplace = ITEM_SAW; - // break; - // case RAND_INF_ADULT_TRADES_HAS_SWORD_BROKEN: - // itemToReplace = ITEM_SWORD_BROKEN; - // break; - // case RAND_INF_ADULT_TRADES_HAS_PRESCRIPTION: - // itemToReplace = ITEM_PRESCRIPTION; - // break; - // case RAND_INF_ADULT_TRADES_HAS_FROG: - // itemToReplace = ITEM_FROG; - // break; - // case RAND_INF_ADULT_TRADES_HAS_EYEDROPS: - // itemToReplace = ITEM_EYEDROPS; - // break; - // case RAND_INF_ADULT_TRADES_HAS_CLAIM_CHECK: - // itemToReplace = ITEM_CLAIM_CHECK; - // break; - // } - // Inventory_ReplaceItem(gPlayState, itemToReplace, Randomizer_GetNextAdultTradeItem()); - // } - //} else { - // // Special case: Ignore water temple water level flags, stored at 0x1C, 0x1D, 0x1E. - // if (sceneNum == SCENE_WATER_TEMPLE && flagType == FLAG_SCENE_SWITCH && - // (flag == 0x1C || flag == 0x1D || flag == 0x1E)) { - // return; - // } - - // // Special case: Ignore forest temple elevator flag, stored at 0x1B. - // if (sceneNum == SCENE_FOREST_TEMPLE && flagType == FLAG_SCENE_SWITCH && flag == 0x1B) { - // return; - // } - - // auto effect = new GameInteractionEffect::UnsetSceneFlag(); - // effect->parameters[0] = sceneNum; - // effect->parameters[1] = flagType; - // effect->parameters[2] = flag; - // effect->Apply(); - //} + if (flagSpace == ANCHOR_FLAGSPACE_VOLATILE) { + volatileFlag_setEx((enum volatile_flags_e)flag, 0, 0); + } else { + fileProgressFlag_setEx((enum file_progress_e)flag, 0, 0); + } } diff --git a/src/port/Network/Anchor/Packets/UpdateClientState.cpp b/src/port/Network/Anchor/Packets/UpdateClientState.cpp index 9482d448f..12ef0a91b 100644 --- a/src/port/Network/Anchor/Packets/UpdateClientState.cpp +++ b/src/port/Network/Anchor/Packets/UpdateClientState.cpp @@ -3,12 +3,10 @@ #include "port/Network/Anchor/JsonConversions.hpp" #include #include -//#include "soh/OTRGlobals.h" -extern "C" { +#include "port/Rando/Rando.h" + #include "variables.h" -// extern PlayState* gPlayState; -} /** * UPDATE_CLIENT_STATE @@ -28,8 +26,12 @@ nlohmann::json Anchor::PrepClientState() { payload["teamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); payload["online"] = true; + BKPlayerColorSet colors; + PlayerColors_getLocal(&colors); + to_json(payload["colors"], colors); + if (IsSaveLoaded()) { - payload["seed"] = /*IS_RANDO ? Rando::Context::GetRawInstance()->GetSeed() : */ 0; + payload["seed"] = (uint32_t)(IS_RANDO ? RANDO_SEED : 0); payload["isSaveLoaded"] = true; payload["isGameComplete"] = false; payload["map"] = gsworld_getMap(); @@ -60,7 +62,6 @@ void Anchor::HandlePacket_UpdateClientState(nlohmann::json& payload) { AnchorClient client = payload["state"].get(); clients[clientId].clientId = clientId; clients[clientId].name = client.name; - // clients[clientId].color = client.color; clients[clientId].clientVersion = client.clientVersion; clients[clientId].teamId = client.teamId; clients[clientId].online = client.online; @@ -69,8 +70,11 @@ void Anchor::HandlePacket_UpdateClientState(nlohmann::json& payload) { clients[clientId].isGameComplete = client.isGameComplete; clients[clientId].map = client.map; clients[clientId].exit = client.exit; + clients[clientId].colors = client.colors; + ApplyClientCosmetics(clientId); EvaluateDummyForClient(clientId); Authority_OnClientStateChanged(clientId, client.online, client.map); + SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); if (client.online) { // Covers clients (re)connecting while already in an activity's map: rebroadcast // any claim of ours so they don't briefly act as their own authority. diff --git a/src/port/Network/Anchor/Packets/UpdateRoomState.cpp b/src/port/Network/Anchor/Packets/UpdateRoomState.cpp index de1263a67..e8e98a539 100644 --- a/src/port/Network/Anchor/Packets/UpdateRoomState.cpp +++ b/src/port/Network/Anchor/Packets/UpdateRoomState.cpp @@ -4,14 +4,11 @@ #include #include "port/Romhack/RomhackConfig.h" #include "port/Romhack/RomhackCompat.h" +#include "port/Rando/Rando.h" #include "port/UI/LighthouseGui.hpp" #include "port/UI/LighthouseModals.h" -//#include "soh/OTRGlobals.h" -extern "C" { #include "variables.h" -// extern PlayState* gPlayState; -} /** * UPDATE_ROOM_STATE @@ -20,22 +17,29 @@ extern "C" { nlohmann::json Anchor::PrepRoomState() { nlohmann::json payload; payload["ownerClientId"] = ownClientId; - bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); - - // if (isGlobalRoom) { - // // Global room uses hardcoded settings - // payload["pvpMode"] = 0; - // payload["showLocationsMode"] = 0; - // payload["teleportMode"] = 0; - // payload["syncItemsAndFlags"] = 0; - // } else { + + if (IsGlobalRoom()) { + payload["pvpMode"] = 0; + payload["showLocationsMode"] = 0; + payload["teleportMode"] = 0; + payload["syncItemsAndFlags"] = 0; + payload["shareConsumables"] = 0; + payload["isRomHack"] = false; + payload["romhackName"] = ""; + payload["isRando"] = false; + payload["seed"] = 0; + return payload; + } + payload["pvpMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), 1); payload["showLocationsMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), 1); payload["teleportMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.TeleportMode"), 1); payload["syncItemsAndFlags"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.SyncItemsAndFlags"), 1); + payload["shareConsumables"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.ShareConsumables"), 0); payload["isRomHack"] = port_isRomhack(); payload["romhackName"] = Lighthouse::CurrentRomhackLabel(); - //} + payload["isRando"] = (bool)IS_RANDO; + payload["seed"] = (int32_t)(IS_RANDO ? RANDO_SEED : 0); return payload; } @@ -52,17 +56,35 @@ void Anchor::HandlePacket_UpdateRoomState(nlohmann::json& payload) { if (!payload.contains("state")) { return; } + + if (IsGlobalRoom()) { + roomState.ownerClientId = payload["state"].value("ownerClientId", (uint32_t)0); + roomState.pvpMode = 0; + roomState.showLocationsMode = 0; + roomState.teleportMode = 0; + roomState.syncItemsAndFlags = 0; + roomState.shareConsumables = 0; + roomState.isRomhack = false; + roomState.romhackName.clear(); + return; + } + roomState.isRomhack = payload["state"]["isRomHack"].get(); roomState.romhackName = payload["state"]["romhackName"].get(); const std::string localLabel = Lighthouse::CurrentRomhackLabel(); if (roomState.romhackName != localLabel) { - Disable(); - std::string msg = "There's a romhack mismatch between your client and the server:\n\n"; - msg += Lighthouse::DescribeRomhackMismatch(port_isRomhack(), localLabel, roomState.isRomhack, - roomState.romhackName); - msg += "\n\nAnchor has been disabled. Please enable or disable the appropriate\n" - "mod(s) in the Mod Menu and reconnect, or enter a new room name."; - LighthouseGui::RegisterPopup("Incompatible Romhack State", msg); + if (roomState.romhackName != lastWarnedRomhackLabel) { + lastWarnedRomhackLabel = roomState.romhackName; + std::string msg = "There's a romhack mismatch between your client and the server:\n\n"; + msg += Lighthouse::DescribeRomhackMismatch(port_isRomhack(), localLabel, roomState.isRomhack, + roomState.romhackName); + msg += "\n\nYou can still play together, but items, flags, and custom content\n" + "may not sync correctly. To avoid desyncs, enable or disable the\n" + "appropriate mod(s) in the Mod Menu so both sides match, then reconnect."; + LighthouseGui::RegisterPopup("Romhack Mismatch Warning", msg); + } + } else { + lastWarnedRomhackLabel.clear(); } roomState.ownerClientId = payload["state"]["ownerClientId"].get(); @@ -70,4 +92,49 @@ void Anchor::HandlePacket_UpdateRoomState(nlohmann::json& payload) { roomState.showLocationsMode = payload["state"]["showLocationsMode"].get(); roomState.teleportMode = payload["state"]["teleportMode"].get(); roomState.syncItemsAndFlags = payload["state"]["syncItemsAndFlags"].get(); + roomState.shareConsumables = payload["state"].value("shareConsumables", (u8)0); + roomState.isRando = payload["state"].value("isRando", false); + roomState.seed = payload["state"].value("seed", (int32_t)0); + + CheckRandoRoomCompatibility(); +} + +void Anchor::CheckRandoRoomCompatibility() { + if (IsGlobalRoom() || !isConnected || !IsSaveLoaded()) { + return; + } + + const bool localRando = IS_RANDO; + const int32_t localSeed = localRando ? (int32_t)RANDO_SEED : 0; + + std::string msg; + if (roomState.isRando && !localRando) { + msg = "This is a randomizer room, but the save you loaded is not a randomizer file.\n\n" + "Items, flags, and checks will not line up - you'll receive progress you can't use\n" + "and may corrupt the shared session. Load the matching randomizer file, or\n" + "disconnect before continuing."; + } else if (!roomState.isRando && localRando) { + msg = "You loaded a randomizer file, but this room is running a vanilla game.\n\n" + "Shuffled checks won't match what teammates send, so progress will desync.\n" + "Reconnect to a randomizer room, or load a vanilla file to match this one."; + } else if (roomState.isRando && localRando && roomState.seed != localSeed) { + msg = "Seed mismatch: your randomizer seed differs from the room's.\n\n" + "Checks are shuffled differently per seed, so syncing will scatter items to the\n" + "wrong locations. Everyone on a team must generate/load from the same seed.\n"; + msg += "\n Your seed: " + std::to_string(localSeed); + msg += "\n Room seed: " + std::to_string(roomState.seed); + } + + if (msg.empty()) { + lastWarnedRandoState.clear(); + return; + } + + std::string sig = std::to_string(roomState.isRando) + ":" + std::to_string(roomState.seed) + "|" + + std::to_string(localRando) + ":" + std::to_string(localSeed); + if (sig == lastWarnedRandoState) { + return; + } + lastWarnedRandoState = sig; + LighthouseGui::RegisterPopup("Randomizer Mismatch Warning", msg); } diff --git a/src/port/Network/Anchor/Packets/UpdateTeamState.cpp b/src/port/Network/Anchor/Packets/UpdateTeamState.cpp index a51b0046d..380097a40 100644 --- a/src/port/Network/Anchor/Packets/UpdateTeamState.cpp +++ b/src/port/Network/Anchor/Packets/UpdateTeamState.cpp @@ -2,110 +2,97 @@ #include "port/Network/Anchor/JsonConversions.hpp" #include #include -//#include "soh/OTRGlobals.h" #include "port/UI/Notification.h" +#include "port/Enhancements/Retention/Retention.h" +#include "port/Rando/Rando.h" +#include +#include -extern "C" { #include "variables.h" -// extern PlayState* gPlayState; -} +#include "functions.h" + +// In-memory session sets that aren't part of the save but still ride team state. Flat int +// tuples; defined in the respective port modules. +extern std::vector port_breakable_snapshotBroken(); +extern void port_breakable_restoreBroken(const std::vector& flat); +extern std::vector port_carriedSync_snapshotCollected(); +extern void port_carriedSync_restoreCollected(const std::vector& flat); +extern std::vector port_eggToll_snapshot(); +extern void port_eggToll_restore(const std::vector& flat); +extern std::vector port_puzzleStep_snapshot(); +extern void port_puzzleStep_restore(const std::vector& flat); +extern std::vector port_puzzleCount_snapshot(); +extern void port_puzzleCount_restore(const std::vector& flat); +extern std::vector port_puzzlePos_snapshot(); +extern void port_puzzlePos_restore(const std::vector& flat); +extern std::vector port_jiggySpawn_snapshot(); +extern void port_jiggySpawn_restore(const std::vector& flat); +extern std::vector port_hutSmash_snapshot(); +extern void port_hutSmash_restore(const std::vector& flat); /** * UPDATE_TEAM_STATE * - * Pushes the current save state to the server for other teammates to use. - * - * Fires when the server passes on a REQUEST_TEAM_STATE packet, or when this client saves the game - * - * When sending this packet we will assume that the team queue has been emptied for this client, so the queue - * stored in the server will be cleared. - * - * When receiving this packet, if there is items in the team queue, we will play them back in order. + * Pushes our full flag state to teammates on REQUEST_TEAM_STATE or on save. Sending clears + * the team queue (assumed drained); receiving replays any queued packets after applying state. */ +// Snapshot a decomp byte-array score/flag section into a JSON byte array. +static std::vector ScoreBytes(void (*getSizeAndPtr)(s32*, u8**)) { + s32 size; + u8* addr; + getSizeAndPtr(&size, &addr); + return std::vector(addr, addr + size); +} + void Anchor::SendPacket_UpdateTeamState() { if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } - // json payload; - // payload["type"] = UPDATE_TEAM_STATE; - // payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - - //// Assume the team queue has been emptied, so clear it - // payload["queue"] = json::array(); - - // payload["state"] = gSaveContext; - //// manually update current scene flags - // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4] = gPlayState->actorCtx.flags.chest; - // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 1] = gPlayState->actorCtx.flags.swch; - // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 2] = gPlayState->actorCtx.flags.clear; - // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 3] = gPlayState->actorCtx.flags.collect; - - //// The commented out code below is an attempt at sending the entire randomizer seed over, in hopes that a player - //// doesn't have to generate the seed themselves Currently it doesn't work :) - // if (IS_RANDO) { - // auto randoContext = Rando::Context::GetRawInstance(); - - // payload["state"]["rando"] = json::object(); - // payload["state"]["rando"]["itemLocations"] = json::array(); - // for (int i = 0; i < RC_MAX; i++) { - // payload["state"]["rando"]["itemLocations"][i] = json::array(); - // // payload["state"]["rando"]["itemLocations"][i]["rgID"] = - // // randoContext->GetItemLocation(i)->GetPlacedRandomizerGet(); - // payload["state"]["rando"]["itemLocations"][i][0] = randoContext->GetItemLocation(i)->GetCheckStatus(); - // payload["state"]["rando"]["itemLocations"][i][1] = (u8)randoContext->GetItemLocation(i)->GetIsSkipped(); - - // if (randoContext->GetItemLocation(i)->GetPlacedRandomizerGet() == RG_ICE_TRAP) { - // payload["state"]["rando"]["itemLocations"][i]["fakeRgID"] = - // randoContext->GetItemOverride(i).LooksLike(); - // payload["state"]["rando"]["itemLocations"][i]["trickName"] = json::object(); - // payload["state"]["rando"]["itemLocations"][i]["trickName"]["english"] = - // randoContext->GetItemOverride(i).GetTrickName().GetEnglish(); - // payload["state"]["rando"]["itemLocations"][i]["trickName"]["french"] = - // randoContext->GetItemOverride(i).GetTrickName().GetFrench(); - // } - // if (randoContext->GetItemLocation(i)->HasCustomPrice()) { - // payload["state"]["rando"]["itemLocations"][i]["price"] = - // randoContext->GetItemLocation(i)->GetPrice(); - // } - //} - - // auto entranceCtx = randoContext->GetEntranceShuffler(); - // for (int i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { - // payload["state"]["rando"]["entrances"][i] = json::object(); - // payload["state"]["rando"]["entrances"][i]["type"] = entranceCtx->entranceOverrides[i].type; - // payload["state"]["rando"]["entrances"][i]["index"] = entranceCtx->entranceOverrides[i].index; - // payload["state"]["rando"]["entrances"][i]["destination"] = entranceCtx->entranceOverrides[i].destination; - // payload["state"]["rando"]["entrances"][i]["override"] = entranceCtx->entranceOverrides[i].override; - // payload["state"]["rando"]["entrances"][i]["overrideDestination"] = - // entranceCtx->entranceOverrides[i].overrideDestination; - // } - - // payload["state"]["rando"]["seed"] = json::array(); - // for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) { - // payload["state"]["rando"]["seed"][i] = randoContext->hashIconIndexes[i]; - // } - // payload["state"]["rando"]["inputSeed"] = randoContext->GetSeedString(); - // payload["state"]["rando"]["finalSeed"] = randoContext->GetSeed(); - - // payload["state"]["rando"]["randoSettings"] = json::array(); - // for (int i = 0; i < RSK_MAX; i++) { - // payload["state"]["rando"]["randoSettings"][i] = - // randoContext->GetOption((RandomizerSettingKey(i))).GetSelectedOptionIndex(); - // } - - // payload["state"]["rando"]["masterQuestDungeonCount"] = randoContext->GetDungeons()->CountMQ(); - // payload["state"]["rando"]["masterQuestDungeons"] = json::array(); - // for (int i = 0; i < randoContext->GetDungeons()->GetDungeonListSize(); i++) { - // payload["state"]["rando"]["masterQuestDungeons"][i] = randoContext->GetDungeon(i)->IsMQ(); - // } - // for (int i = 0; i < randoContext->GetTrials()->GetTrialListSize(); i++) { - // payload["state"]["rando"]["requiredTrials"][i] = randoContext->GetTrial(i)->IsRequired(); - // } - /*} + json payload; + payload["type"] = UPDATE_TEAM_STATE; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["queue"] = json::array(); + payload["state"]["fileProgressFlags"] = ScoreBytes(fileProgressFlag_getSizeAndPtr); + payload["state"]["jiggies"] = ScoreBytes(jiggyscore_getSizeAndPtr); + payload["state"]["honeycombs"] = ScoreBytes(honeycombscore_getSizeAndPtr); + payload["state"]["mumboTokens"] = ScoreBytes(mumboscore_getSizeAndPtr); + payload["state"]["noteScores"] = ScoreBytes(itemscore_noteScores_getSizeAndPtr); + payload["state"]["savedItems"] = ScoreBytes(saveditem_getSizeAndPtr); + payload["state"]["abilities"] = ScoreBytes(ability_getSizeAndPtr); + // Time scores use a (s32*, void**) accessor, so packed inline. + s32 tsSize; + void* tsAddr; + timeScores_getSizeAndPtr(&tsSize, &tsAddr); + payload["state"]["timeScores"] = std::vector((u8*)tsAddr, (u8*)tsAddr + tsSize); + payload["state"]["volatileFlags"] = ScoreBytes(volatileFlag_getSizeAndPtr); + // In-memory session sets (never saved). + payload["state"]["brokenObjects"] = port_breakable_snapshotBroken(); + payload["state"]["carriedCollected"] = port_carriedSync_snapshotCollected(); + payload["state"]["eggTolls"] = port_eggToll_snapshot(); + payload["state"]["puzzleSteps"] = port_puzzleStep_snapshot(); + payload["state"]["puzzleCounts"] = port_puzzleCount_snapshot(); + payload["state"]["puzzlePos"] = port_puzzlePos_snapshot(); + payload["state"]["spawnedJiggies"] = port_jiggySpawn_snapshot(); + payload["state"]["huts"] = port_hutSmash_snapshot(); + + // Randomizer progress lives outside the vanilla score sections: obtained checks + RANDO_INF flags. + if (IS_RANDO) { + std::vector checks(RC_MAX, 0); + for (s32 rc = RC_UNKNOWN + 1; rc < RC_MAX; rc++) { + checks[rc] = RANDO_SAVE_CHECKS[rc].eligible ? 1 : 0; + } + payload["state"]["randoChecks"] = checks; + + std::vector randoFlags(RANDO_INF_MAX, 0); + for (s32 i = RANDO_INF_UNKNOWN + 1; i < RANDO_INF_MAX; i++) { + randoFlags[i] = RANDO_SAVE_FLAGS[i].flagState; + } + payload["state"]["randoFlags"] = randoFlags; + } - SendJsonToRemote(payload);*/ + SendJsonToRemote(payload); } void Anchor::SendPacket_ClearTeamState(std::string teamId) { @@ -117,188 +104,167 @@ void Anchor::SendPacket_ClearTeamState(std::string teamId) { SendJsonToRemote(payload); } +// Overwrites a local byte section with the authoritative team-state array (no additive merge). +static void ApplyTeamBytes(nlohmann::json& bytes, void (*getSizeAndPtr)(s32*, u8**)) { + s32 size; + u8* addr; + getSizeAndPtr(&size, &addr); + s32 count = std::min(size, (s32)bytes.size()); + for (s32 i = 0; i < count; i++) { + addr[i] = bytes[i].get(); + } +} + void Anchor::HandlePacket_UpdateTeamState(nlohmann::json& payload) { if (!roomState.syncItemsAndFlags) { return; } isHandlingUpdateTeamState = true; - // This can happen in between file select and the game starting, so we can't use this check, but we need to ensure - // we be careful to wrap PlayState usage in this check - // - // if (!IsSaveLoaded()) { - // return; - // } - - // if (payload.contains("state")) { - // SaveContext loadedData = payload["state"].get(); - // gSaveContext.healthCapacity = loadedData.healthCapacity; - // gSaveContext.magicLevel = loadedData.magicLevel; - // gSaveContext.magicCapacity = gSaveContext.magic = loadedData.magicCapacity; - // gSaveContext.isMagicAcquired = loadedData.isMagicAcquired; - // gSaveContext.isDoubleMagicAcquired = loadedData.isDoubleMagicAcquired; - // gSaveContext.isDoubleDefenseAcquired = loadedData.isDoubleDefenseAcquired; - // gSaveContext.bgsFlag = loadedData.bgsFlag; - // gSaveContext.swordHealth = loadedData.swordHealth; - // gSaveContext.ship.quest = loadedData.ship.quest; - - // for (int i = 0; i < 124; i++) { - // if (i == SCENE_WATER_TEMPLE) { - // // Keep water temple water level flags - // u32 mask = (1 << 0x1C) | (1 << 0x1D) | (1 << 0x1E); - // loadedData.sceneFlags[i].swch = - // (loadedData.sceneFlags[i].swch & ~mask) | (gSaveContext.sceneFlags[i].swch & mask); - // } - - // if (i == SCENE_FOREST_TEMPLE) { - // // Keep forest temple elevator flag - // u32 mask = (1 << 0x1B); - // loadedData.sceneFlags[i].swch = - // (loadedData.sceneFlags[i].swch & ~mask) | (gSaveContext.sceneFlags[i].swch & mask); - // } - - // gSaveContext.sceneFlags[i] = loadedData.sceneFlags[i]; - // if (IsSaveLoaded() && gPlayState->sceneNum == i) { - // gPlayState->actorCtx.flags.chest = loadedData.sceneFlags[i].chest; - // gPlayState->actorCtx.flags.swch = loadedData.sceneFlags[i].swch; - // gPlayState->actorCtx.flags.clear = loadedData.sceneFlags[i].clear; - // gPlayState->actorCtx.flags.collect = loadedData.sceneFlags[i].collect; - // } - // } - - // for (int i = 0; i < 14; i++) { - // gSaveContext.eventChkInf[i] = loadedData.eventChkInf[i]; - // } - - // for (int i = 0; i < 4; i++) { - // gSaveContext.itemGetInf[i] = loadedData.itemGetInf[i]; - // } - - // // Skip last row of infTable, don't want to sync swordless flag - // for (int i = 0; i < 29; i++) { - // gSaveContext.infTable[i] = loadedData.infTable[i]; - // } - - // for (int i = 0; i < ceil((RAND_INF_MAX + 15) / 16); i++) { - // gSaveContext.ship.randomizerInf[i] = loadedData.ship.randomizerInf[i]; - // } - - // for (int i = 0; i < 6; i++) { - // gSaveContext.gsFlags[i] = loadedData.gsFlags[i]; - // } - - // gSaveContext.ship.stats.firstInput = loadedData.ship.stats.firstInput; - // gSaveContext.ship.stats.fileCreatedAt = loadedData.ship.stats.fileCreatedAt; - - // // Restore master sword state - // // Disabling this for now, not really sure I understand why I did this in the past - // // u8 hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, 1); - // // if (hasMasterSword) { - // // loadedData.inventory.equipment |= 0x2; - // // } else { - // // loadedData.inventory.equipment &= ~0x2; - // // } - - // // Restore bottle contents (unless it's ruto's letter) - // for (int i = 0; i < 4; i++) { - // if (gSaveContext.inventory.items[SLOT_BOTTLE_1 + i] != ITEM_NONE && - // gSaveContext.inventory.items[SLOT_BOTTLE_1 + i] != ITEM_LETTER_RUTO) { - // loadedData.inventory.items[SLOT_BOTTLE_1 + i] = gSaveContext.inventory.items[SLOT_BOTTLE_1 + i]; - // } - // } - - // // Restore ammo if it's non-zero, unless it's beans - // for (int i = 0; i < ARRAY_COUNT(gSaveContext.inventory.ammo); i++) { - // if (gSaveContext.inventory.ammo[i] != 0 && i != SLOT(ITEM_BEAN) && i != SLOT(ITEM_BEAN + 1)) { - // loadedData.inventory.ammo[i] = gSaveContext.inventory.ammo[i]; - // } - // } - - // gSaveContext.inventory = loadedData.inventory; - - // // The commented out code below is an attempt at sending the entire randomizer seed over, in hopes that a - // player - // // doesn't have to generate the seed themselves Currently it doesn't work :) - // if (IS_RANDO && payload["state"].contains("rando")) { - // auto randoContext = Rando::Context::GetRawInstance(); - - // for (int i = 0; i < RC_MAX; i++) { - // auto itemLocation = payload["state"]["rando"].at("itemLocations").at(i); - // // randoContext->GetItemLocation(i)->RefPlacedItem() = - // // itemLocation.at("rgID").get(); - // OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetCheckStatus( - // itemLocation.at(0).get()); - // OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped(itemLocation.at(1).get()); - - // // if (itemLocation.contains("fakeRgID")) { - // // randoContext->overrides.emplace(static_cast(i), - // // Rando::ItemOverride(static_cast(i), - // // itemLocation.at("fakeRgID").get())); - // // randoContext->GetItemOverride(i).GetTrickName().english = - // // itemLocation.at("trickName").at("english").get(); - // // randoContext->GetItemOverride(i).GetTrickName().french = - // // itemLocation.at("trickName").at("french").get(); - // // } - // // if (itemLocation.contains("price")) { - // // u16 price = itemLocation.at("price"].get(); - // // if (price > 0) { - // // randoContext->GetItemLocation(i)->SetCustomPrice(price); - // // } - // // } - // } - - // // auto entranceCtx = randoContext->GetEntranceShuffler(); - // // for (int i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { - // // entranceCtx->entranceOverrides[i].type = - // // payload["state"]["rando"]["entrances"][i]["type"].get(); - // entranceCtx->entranceOverrides[i].index - // // = payload["state"]["rando"]["entrances"][i]["index"].get(); - // // entranceCtx->entranceOverrides[i].destination = - // // payload["state"]["rando"]["entrances"][i]["destination"].get(); - // // entranceCtx->entranceOverrides[i].override = - // // payload["state"]["rando"]["entrances"][i]["override"].get(); - // // entranceCtx->entranceOverrides[i].overrideDestination = - // // payload["state"]["rando"]["entrances"][i]["overrideDestination"].get(); - // // } - - // // for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) { - // // randoContext->hashIconIndexes[i] = payload["state"]["rando"]["seed"][i].get(); - // // } - // // randoContext->GetSettings()->SetSeedString(payload["state"]["rando"]["inputSeed"].get()); - // // randoContext->GetSettings()->SetSeed(payload["state"]["rando"]["finalSeed"].get()); - - // // for (int i = 0; i < RSK_MAX; i++) { - // // - // randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(payload["state"]["rando"]["randoSettings"][i].get()); - // // } - - // // randoContext->GetDungeons()->ClearAllMQ(); - // // for (int i = 0; i < randoContext->GetDungeons()->GetDungeonListSize(); i++) { - // // if (payload["state"]["rando"]["masterQuestDungeons"][i].get()) { - // // randoContext->GetDungeon(i)->SetMQ(); - // // } - // // } - - // // randoContext->GetTrials()->SkipAll(); - // // for (int i = 0; i < randoContext->GetTrials()->GetTrialListSize(); i++) { - // // if (payload["state"]["rando"]["requiredTrials"][i].get()) { - // // randoContext->GetTrial(i)->SetAsRequired(); - // // } - // // } - // } + if (payload.contains("state")) { + auto& state = payload["state"]; + // Direct byte copy bypasses the setters; no OnGameFlagSet / collectible events fire. + if (state.contains("fileProgressFlags")) { + ApplyTeamBytes(state["fileProgressFlags"], fileProgressFlag_getSizeAndPtr); + } + if (state.contains("volatileFlags")) { + ApplyTeamBytes(state["volatileFlags"], volatileFlag_getSizeAndPtr); + } + if (state.contains("jiggies")) { + ApplyTeamBytes(state["jiggies"], jiggyscore_getSizeAndPtr); + } + if (state.contains("honeycombs")) { + ApplyTeamBytes(state["honeycombs"], honeycombscore_getSizeAndPtr); + } + if (state.contains("mumboTokens")) { + ApplyTeamBytes(state["mumboTokens"], mumboscore_getSizeAndPtr); + } + if (state.contains("noteScores")) { + ApplyTeamBytes(state["noteScores"], itemscore_noteScores_getSizeAndPtr); + } + // Per-level retention sets; takes effect on next map load. + if (state.contains("noteRetention")) { + ApplyTeamBytes(state["noteRetention"], port_noteRetention_getSizeAndPtr); + } + if (state.contains("jinjoRetention")) { + ApplyTeamBytes(state["jinjoRetention"], port_jinjoRetention_getSizeAndPtr); + } + if (state.contains("abilities")) { + ApplyTeamBytes(state["abilities"], ability_getSizeAndPtr); + } + // In-memory session sets; takes effect on next map load. + if (state.contains("brokenObjects")) { + port_breakable_restoreBroken(state["brokenObjects"].get>()); + } + if (state.contains("carriedCollected")) { + port_carriedSync_restoreCollected(state["carriedCollected"].get>()); + } + if (state.contains("eggTolls")) { + port_eggToll_restore(state["eggTolls"].get>()); + } + if (state.contains("puzzleSteps")) { + port_puzzleStep_restore(state["puzzleSteps"].get>()); + } + if (state.contains("puzzlePos")) { + port_puzzlePos_restore(state["puzzlePos"].get>()); + } + if (state.contains("puzzleCounts")) { + port_puzzleCount_restore(state["puzzleCounts"].get>()); + } + if (state.contains("spawnedJiggies")) { + port_jiggySpawn_restore(state["spawnedJiggies"].get>()); + } + if (state.contains("huts")) { + port_hutSmash_restore(state["huts"].get>()); + } + + // Recompute cached HUD counts the overwrites above bypassed. + if (IsSaveLoaded()) { + if (state.contains("jiggies")) { + func_8034798C(); + } + if (state.contains("honeycombs")) { + func_80347958(); + } + if (state.contains("mumboTokens")) { + func_80347984(); + } + + // Saved item counts: mumbo tokens [0] and jiggy total [4] always sync; feathers + // [1-3] only when the room shares consumables. + if (state.contains("savedItems")) { + auto& incoming = state["savedItems"]; + s32 size; + u8* addr; + saveditem_getSizeAndPtr(&size, &addr); // rebuilds the array from live counts + u8 buf[5]; + for (s32 i = 0; i < 5; i++) { + buf[i] = (i < size) ? addr[i] : 0; + } + if (incoming.size() >= 5) { + buf[0] = incoming[0].get(); + buf[4] = incoming[4].get(); + if (roomState.shareConsumables) { + buf[1] = incoming[1].get(); + buf[2] = incoming[2].get(); + buf[3] = incoming[3].get(); + } + func_803479C0(buf); + } + } + + // Per-level best times (truncated u16 each). + if (state.contains("timeScores")) { + auto incoming = state["timeScores"].get>(); + u16 ts[0xB] = { 0 }; + size_t n = std::min(incoming.size(), sizeof(ts)); + for (size_t i = 0; i < n; i++) { + ((u8*)ts)[i] = incoming[i]; + } + itemscore_timeScores_fromSaveData(ts); + } + } + + // Randomizer catch-up: reconcile check records (obtain without re-granting, see + // AdoptRemoteCheck) and take RANDO_INF flags authoritatively. + if (IS_RANDO && IsSaveLoaded()) { + if (state.contains("randoChecks")) { + auto checks = state["randoChecks"].get>(); + s32 n = std::min((s32)checks.size(), (s32)RC_MAX); + for (s32 rc = RC_UNKNOWN + 1; rc < n; rc++) { + if (checks[rc]) { + AdoptRemoteCheck(rc); + } + } + } + if (state.contains("randoFlags")) { + auto flags = state["randoFlags"].get>(); + s32 n = std::min((s32)flags.size(), (s32)RANDO_INF_MAX); + for (s32 i = RANDO_INF_UNKNOWN + 1; i < n; i++) { + RANDO_SAVE_FLAGS[i].flagState = flags[i]; + } + } + } + + SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); + + Notification::Emit({ + .message = "Save updated from team", + }); + + if (reloadMapOnTeamState && IsSaveLoaded()) { + reloadMapOnTeamState = false; + transitionToMap(gsworld_getMap(), gsworld_getExit(), 1); + } + } - // Notification::Emit({ - // .message = "Save updated from team", - // }); - //} + if (payload.contains("queue")) { + std::lock_guard lock(incomingPacketQueueMutex); + for (auto& item : payload["queue"]) { + incomingPacketQueue.push(nlohmann::json::parse(item.get())); + } + } - // if (payload.contains("queue")) { - // std::lock_guard lock(incomingPacketQueueMutex); - // for (auto& item : payload["queue"]) { - // nlohmann::json itemPayload = nlohmann::json::parse(item.get()); - // incomingPacketQueue.push(itemPayload); - // } - // } - // isHandlingUpdateTeamState = false; + isHandlingUpdateTeamState = false; } diff --git a/src/port/Network/Anchor/Packets/VileEatRequest.cpp b/src/port/Network/Anchor/Packets/VileEatRequest.cpp index 536b061f1..7576365e7 100644 --- a/src/port/Network/Anchor/Packets/VileEatRequest.cpp +++ b/src/port/Network/Anchor/Packets/VileEatRequest.cpp @@ -3,10 +3,8 @@ #include #include -extern "C" { #include "functions.h" #include "variables.h" -} /** * VILE_EAT_REQUEST @@ -14,9 +12,6 @@ extern "C" { * Sent by a non-authority client when its local player chomps a piece. The minigame * authority validates the request against the live piece list and, on success, consumes * the piece and broadcasts the result as a VILE_HOLE_STATE (eaten) packet. - * - * No sequence number: this is a request toward the authority, not part of the - * authority's ordered state stream. */ void Anchor::SendPacket_VileEatRequest(u8 holeId) { @@ -41,14 +36,10 @@ void Anchor::HandlePacket_VileEatRequest(nlohmann::json& payload) { return; } - // Only the authority acts on eat requests; VileSync_HandleEatRequest returns false - // (touching nothing) on non-authority clients. uint32_t eaterClientId = payload.at("clientId").get(); s32 pieceType = 0; s32 correctType = 0; if (VileSync_HandleEatRequest(holeId, eaterClientId, &pieceType, &correctType)) { - // Confirm the successful eat back to the requester so it replays its croc's eat - // feedback (the piece removal already rides the eaten VILE_HOLE_STATE broadcast). SendPacket_VileEatResult(eaterClientId, (u8)pieceType, (u8)correctType); } } diff --git a/src/port/Network/Anchor/Packets/VileEatResult.cpp b/src/port/Network/Anchor/Packets/VileEatResult.cpp index 214943b6f..21d8b8142 100644 --- a/src/port/Network/Anchor/Packets/VileEatResult.cpp +++ b/src/port/Network/Anchor/Packets/VileEatResult.cpp @@ -3,22 +3,14 @@ #include #include -extern "C" { #include "functions.h" #include "variables.h" -} /** * VILE_EAT_RESULT * - * Sent by the minigame authority to confirm a successful VILE_EAT_REQUEST. The - * requester suppressed its local consume (so its croc never played the chomp), so on - * receipt it replays the eat feedback: the chomp animation/SFX, plus the wrong-type - * reaction when the eaten piece didn't match the required type. Score and piece removal - * are authority-driven and arrive via the snapshot / eaten VILE_HOLE_STATE separately. - * - * Broadcast to the chamber with the eater's id; only the eater acts on it. No sequence - * number: this is one-shot cosmetic feedback, not part of the ordered state stream. + * Sent by the minigame authority to confirm a successful VILE_EAT_REQUEST. + * Catches up on animations and sounds as necessary */ void Anchor::SendPacket_VileEatResult(u32 eaterClientId, u8 pieceType, u8 correctType) { diff --git a/src/port/Network/Anchor/Packets/VileGameState.cpp b/src/port/Network/Anchor/Packets/VileGameState.cpp index fba3bc9cb..c4f2da03e 100644 --- a/src/port/Network/Anchor/Packets/VileGameState.cpp +++ b/src/port/Network/Anchor/Packets/VileGameState.cpp @@ -3,21 +3,14 @@ #include #include -extern "C" { #include "functions.h" #include "variables.h" -} /** * VILE_GAME_STATE * * Periodic full snapshot of the Mr. Vile minigame, broadcast by the authority to other - * clients in the chamber every second or two while the game is running. Application is - * idempotent: it corrects any drift from lost packets and brings late joiners fully up - * to date (a late joiner is just a client whose drift is 100%). - * - * Events (VILE_HOLE_STATE / VILE_UPDATE) make the game feel synced; this packet makes - * it provably synced. + * clients in the chamber every second or two while the game is running. */ void Anchor::SendPacket_VileGameState() { diff --git a/src/port/Network/Anchor/Packets/VileHoleState.cpp b/src/port/Network/Anchor/Packets/VileHoleState.cpp index 379e1094c..f0078cd05 100644 --- a/src/port/Network/Anchor/Packets/VileHoleState.cpp +++ b/src/port/Network/Anchor/Packets/VileHoleState.cpp @@ -3,10 +3,8 @@ #include #include -extern "C" { #include "functions.h" #include "variables.h" -} /** * VILE_HOLE_STATE diff --git a/src/port/Network/Anchor/Packets/VileUpdate.cpp b/src/port/Network/Anchor/Packets/VileUpdate.cpp index 9d0c37d53..642375c9b 100644 --- a/src/port/Network/Anchor/Packets/VileUpdate.cpp +++ b/src/port/Network/Anchor/Packets/VileUpdate.cpp @@ -3,10 +3,8 @@ #include #include -extern "C" { #include "functions.h" #include "variables.h" -} /** * VILE_UPDATE @@ -15,7 +13,7 @@ extern "C" { * in the chamber at the player-update cadence. Remote clients skip Mr. Vile's AI and * apply this instead. * - * animMode is the BGS_func_8038BBA0 mode (101 idle / 102 walk / 103 munch / 104 burp). + * animMode is the chMrVile_setAction mode (101 idle / 102 walk / 103 munch / 104 burp). * * Note: sent every frame while the minigame runs, so keep this payload lean. */ diff --git a/src/port/Network/Anchor/Packets/WaterRise.cpp b/src/port/Network/Anchor/Packets/WaterRise.cpp new file mode 100644 index 000000000..63ff97663 --- /dev/null +++ b/src/port/Network/Anchor/Packets/WaterRise.cpp @@ -0,0 +1,121 @@ +#include "port/Network/Anchor/Anchor.h" +#include +#include + +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include + +#include "functions.h" +extern "C" { +#include "variables.h" +// func_8034C5AC: xform-3 water group. func_8034E78C: animate its dy. +} + +/** + * WATER_RISE + * + * A rising water level animates only on the client that triggered it (lair: switch cutscene in + * func_802D5628/func_802D5260; CC rings: func_8034E78C). Remotes otherwise only get the trailing + * fileprog flag / JIGGY_1C spawn at the end, snapping the water. This packet signals the rise start. + * + * kind 0 (lair): RBB-lobby water subaddie, driven every frame by func_802D5260. p1 = target level + * (1-3), stashed by a remote as a "pending level" until the real flag catches up. + * kind 1 (CC): rings water (xform-3 dy), no per-frame holder; remote replays func_8034E78C. + * p1 = mesh id, p2 = target dy, dur = seconds. + */ + +enum { WATERRISE_KIND_LAIR = 0, WATERRISE_KIND_CC = 1 }; + +// map -> pending target level for the lair water (remote only; cleared once the flag reaches it). +static std::map sLairPendingLevel; + +static int32_t lairLevelForFlag(int32_t levelFlag) { + switch (levelFlag) { + case FILEPROG_23_LAIR_WATER_LEVEL_1: + return 1; + case FILEPROG_25_LAIR_WATER_LEVEL_2: + return 2; + case FILEPROG_27_LAIR_WATER_LEVEL_3: + return 3; + default: + return 0; + } +} + +// Called from func_802D6264 (the lair switch/cutscene trigger). If the flag the cutscene will set is +// a water-level flag, broadcast the rise now. +extern "C" void port_lairWater_onRiseTrigger(int32_t waterMap, int32_t levelFlag) { + int32_t level = lairLevelForFlag(levelFlag); + if (level == 0) { + return; // not a water switch (doors, witch switches, etc. use this same trigger) + } + Anchor::GetInstance()->SendPacket_WaterRise(waterMap, WATERRISE_KIND_LAIR, level, 0, 0.0f); +} + +// func_802D5260 asks for the effective target level: max(flag-derived level, pending level from a +// teammate's in-flight rise). Clears the pending once the real flag catches up. +extern "C" int32_t port_lairWater_targetLevel(int32_t map, int32_t flagLevel) { + auto it = sLairPendingLevel.find(map); + if (it == sLairPendingLevel.end()) { + return flagLevel; + } + if (flagLevel >= it->second) { + sLairPendingLevel.erase(it); + return flagLevel; + } + return it->second; +} + +extern "C" void port_ccWater_broadcastRise(int32_t map, int32_t waterId, int32_t targetDy, f32 duration) { + Anchor::GetInstance()->SendPacket_WaterRise(map, WATERRISE_KIND_CC, waterId, targetDy, duration); +} + +void Anchor::SendPacket_WaterRise(s32 map, s32 kind, s32 p1, s32 p2, f32 duration) { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + return; + } + nlohmann::json payload; + payload["type"] = WATER_RISE; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["map"] = map; + payload["kind"] = kind; + payload["p1"] = p1; + payload["p2"] = p2; + payload["dur"] = duration; + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_WaterRise(nlohmann::json& payload) { + if (!roomState.syncItemsAndFlags) { + return; + } + s32 map = payload.at("map").get(); + s32 kind = payload.at("kind").get(); + s32 p1 = payload.at("p1").get(); + s32 p2 = payload.value("p2", (s32)0); + f32 dur = payload.value("dur", 0.0f); + + if (kind == WATERRISE_KIND_LAIR) { + int32_t cur = sLairPendingLevel.count(map) ? sLairPendingLevel[map] : 0; + if (p1 > cur) { + sLairPendingLevel[map] = p1; + } + } else if (kind == WATERRISE_KIND_CC) { + // Only replay while in the water's map; on later entry func_80388104 snaps it on its own. + if ((s32)gsworld_getMap() == map) { + Struct70s* water = func_8034C5AC(p1); + if (water != nullptr) { + func_8034E78C((Struct73s*)water, p2, dur); + } + } + } +} + +void RegisterWaterRise_Init() { + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sLairPendingLevel.clear(); }); +} + +static RegisterShipInitFunc initWaterRise(RegisterWaterRise_Init, {}); diff --git a/src/port/Network/Anchor/VileSync.c b/src/port/Network/Anchor/VileSync.c index 25f8d4264..096f768b9 100644 --- a/src/port/Network/Anchor/VileSync.c +++ b/src/port/Network/Anchor/VileSync.c @@ -9,8 +9,8 @@ // Implemented in src/BGS (see [port] Anchor sync entry points there). extern void chyumblie_netApplyState(Actor* actor, s32 state, s32 piece_type); extern s32 chyumblie_netGetState(Actor* actor, s32* piece_type); -extern void chvile_netApplyUpdate(Actor* actor, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode); -extern s32 chvile_netGetAnimMode(Actor* actor); +extern void chMrVile_netApplyUpdate(Actor* actor, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode); +extern s32 chMrVile_netGetAnimMode(Actor* actor); extern bool chvilegame_netGather(Actor* actor, VileGameSnapshot* dst); extern void chvilegame_netApply(Actor* actor, const VileGameSnapshot* src); extern bool chvilegame_netConsumeRemote(Actor* actor, f32 position[3], s32* out_piece_type, s32* out_correct_type); @@ -98,7 +98,7 @@ bool VileSync_HandleEatRequest(int32_t holeId, uint32_t eaterClientId, int32_t* return false; } pos[0] = holePos[0]; - pos[1] = 0.0f; // piece positions are stored with y = 0 (see chvilegame_new_piece) + pos[1] = 0.0f; // piece positions are stored with y = 0 (see chMrVileMinigame_newPiece) pos[2] = holePos[1]; // A successful consume broadcasts the eaten hole state itself (the state change // fires OnVileHoleStateChange on this authority client); the piece type / correctness @@ -117,7 +117,7 @@ void VileSync_ApplyVileUpdate(const float position[3], float pitch, float yaw, f Actor* vile = VileSync_FindActor(ACTOR_13A_MR_VILE); if (vile != NULL) { - chvile_netApplyUpdate(vile, position, pitch, yaw, roll, animMode); + chMrVile_netApplyUpdate(vile, position, pitch, yaw, roll, animMode); } } diff --git a/src/port/Network/Anchor/VileSync.h b/src/port/Network/Anchor/VileSync.h index 68c21e9fb..c6e6a83b0 100644 --- a/src/port/Network/Anchor/VileSync.h +++ b/src/port/Network/Anchor/VileSync.h @@ -69,7 +69,7 @@ bool VileSync_HandleEatRequest(int32_t holeId, uint32_t eaterClientId, int32_t* // plus the wrong-type reaction) once the authority confirms the eat succeeded. void VileSync_PlayLocalEatFeedback(int32_t pieceType, int32_t correctType); -// Apply a streamed Mr. Vile transform + anim mode (BGS_func_8038BBA0 modes 101-104). +// Apply a streamed Mr. Vile transform + anim mode (chMrVile_setAction modes 101-104). void VileSync_ApplyVileUpdate(const float position[3], float pitch, float yaw, float roll, uint8_t animMode); // Fill dst from the live minigame controller. Returns false if there is nothing to diff --git a/src/port/OS/OS.h b/src/port/OS/OS.h new file mode 100644 index 000000000..0321ca20c --- /dev/null +++ b/src/port/OS/OS.h @@ -0,0 +1,95 @@ +#ifndef PORT_OS_H +#define PORT_OS_H + +// N64 OS SDK +// +// libultraship already implements most of the libultra surface, and where its +// version is correct for a PC port we use it as-is. This layer exists only for +// the calls libultraship cannot serve, so that the decomp's own threading code +// can run instead of being replaced by port stand-ins. + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libultraship/libultra/message.h" +#include "libultraship/libultra/thread.h" +#include "libultraship/libultra/pfs.h" +#include "libultraship/libultra/sptask.h" +#include "libultraship/libultra/time.h" + +void OS_CreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p); +void OS_StartThread(OSThread* thread); +void OS_StopThread(OSThread* thread); +void OS_DestroyThread(OSThread* thread); +void OS_SetThreadPri(OSThread* thread, OSPri p); + +// Allowlist one decomp thread entry point. Until its entry is passed here, an +// osCreateThread/osStartThread pair is recorded but never launched, so threads +// are revived deliberately, one consumer at a time. +void OS_EnableThreadEntry(void* entry); + +// OS_MESG_BLOCK only blocks on queues opted in here. +void OS_SetQueueBlocking(OSMesgQueue* mq, int enabled); + +// Cooperative exit for threads. +void OS_RequestThreadExit(void); +int OS_ThreadShouldExit(void); +void OS_JoinDecompThreads(void); + +// Stop every queue blocking and wake all waiters, so the tick can unwind and be +// joined. Call once the window has closed and before joining it. +void OS_BeginShutdown(void); + +// Watchdog diagnostics: threads currently parked inside a blocking +// osSendMesg/osRecvMesg, so a stall dump can say where each one waits. +typedef struct OS_BlockedWait { + unsigned long tid; // SDL thread id + OSMesgQueue* mq; + int isSend; // 0 = recv, 1 = send/jam +} OS_BlockedWait; +int OS_MesgSnapshotBlockedWaits(OS_BlockedWait* out, int max); + +// Raise a registered hardware event (VI retrace, SI done, RDP done). +void OS_SendEventMesg(OSEvent event); + +// Raise an event ahead of whatever the recipient already has queued, the way +// an interrupt preempts. Used for completions that must not be reordered +// behind pending messages. +void OS_JamEventMesg(OSEvent event); + +// The VI ticker starts with osCreateViManager; this stops it at shutdown. +void OS_StopViTicker(void); + +// Complete one pending controller read: poll the pads and raise OS_EVENT_SI. +// Called by the thread that owns SDL input. +int OS_SiService(void); + +// Whether that thread has begun servicing SI at all. +int OS_SiPumpLive(void); + +// Cancel a pending timer. Both halves of the pair are ours (OS_Timer.cpp), but +// only osSetTimer has a prototype in LUS to be found through, so a decomp caller +// needs this one declared here. +int osStopTimer(OSTimer* t); + +// The timer worker starts with the first osSetTimer; this stops it at shutdown. +void OS_StopTimerWorker(void); + +s32 osPfsInit(OSMesgQueue* mq, OSPfs* pfs, s32 channel); + +// Whether osViBlack has the display blanked. The renderer blacks the presented +// frame while the world keeps rendering underneath. +int OS_ViBlackActive(void); + +// Take the task osSpTaskStartGo handed over, or NULL if none is pending. +OSTask* OS_SpTakePendingTask(void); + +// Same, but without consuming it; the watchdog reports what is in flight. +OSTask* OS_SpPeekPendingTask(void); + +#ifdef __cplusplus +} +#endif + +#endif // PORT_OS_H diff --git a/src/port/OS/OS_AI.cpp b/src/port/OS/OS_AI.cpp new file mode 100644 index 000000000..ac072f54e --- /dev/null +++ b/src/port/OS/OS_AI.cpp @@ -0,0 +1,61 @@ +// This file should eventually go to LUS as the AI api. +// +// The audio interface, backed by the libultraship audio player. The decomp's +// audio manager runs its original path and this is the DAC at the end of it. + +#include "OS.h" + +#include + +#include "port/UI/cvar_prefixes.h" + +extern "C" { +#include "libultraship/libultra/types.h" +#include "libultraship/libultra/os.h" +int32_t AudioPlayerBuffered(void); +int32_t AudioPlayerGetDesiredBuffered(void); +void AudioPlayerPlayFrame(const uint8_t* buf, size_t len); +} + +#include +#include + +extern "C" u32 osAiGetLength(void) { + int32_t excess = AudioPlayerBuffered() - AudioPlayerGetDesiredBuffered(); + return excess > 0 ? (u32)excess * 4 : 0; +} + +// How many extra synth frames the audio pump should queue this cycle to +// rebuild the playback cushion. +extern "C" int32_t port_audioCatchupFrames(void) { + constexpr int32_t kFrameSamples = 736; + constexpr int32_t kMaxCatchup = 3; + int32_t deficit = AudioPlayerGetDesiredBuffered() - AudioPlayerBuffered(); + if (deficit < kFrameSamples) { + return 0; + } + int32_t frames = deficit / kFrameSamples; + return frames > kMaxCatchup ? kMaxCatchup : frames; +} + +extern "C" s32 osAiSetNextBuffer(void* buff, size_t len) { + static bool sPrimed = false; + if (!sPrimed) { + sPrimed = true; + std::vector silence((size_t)AudioPlayerGetDesiredBuffered() * 4, 0); + AudioPlayerPlayFrame(silence.data(), silence.size()); + } + + float masterVol = CVarGetInteger(CVAR_SETTING("Volume.Master"), 40) / 100.0f; + if (masterVol >= 1.0f) { + AudioPlayerPlayFrame((const uint8_t*)buff, len); + return 0; + } + std::vector scaled(len / 2); + const int16_t* src = (const int16_t*)buff; + for (size_t i = 0; i < scaled.size(); i++) { + scaled[i] = (int16_t)(src[i] * masterVol); + } + AudioPlayerPlayFrame((const uint8_t*)scaled.data(), len); + return 0; +} diff --git a/src/port/OS/OS_Cont.cpp b/src/port/OS/OS_Cont.cpp new file mode 100644 index 000000000..b7369c77d --- /dev/null +++ b/src/port/OS/OS_Cont.cpp @@ -0,0 +1,103 @@ +// This file should eventually go to LUS as the SI api. The controller init and +// motor pieces are unchanged from libultra/os.cpp and only live here because +// taking osSetTimer port-side meant taking that whole object with it. + +#include "OS.h" + +#include + +#include +#include +#include + +extern "C" { + +uint8_t __osMaxControllers = MAXCONTROLLERS; + +int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) { + *controllerBits = 0; + status->status |= 1; + + // The SDL game-controller subsystem and mappings are brought up earlier, in + // Context::InitControlDeck, so controllers work in pre-game UI. ControlDeck::Init + // stays here as it needs the game's controllerBits. + Ship::Context::GetRawInstance()->GetControlDeck()->Init(controllerBits); + + return 0; +} + +// The SI, as a request and a completion rather than an inline poll. +// +// LUS's StartReadData does nothing and GetReadData polls the control deck on +// whichever thread asked, which cannot work once the tick is off the window +// thread: SDL input belongs to the thread pumping its events. A read is +// posted here, completed by that thread in OS_SiService, and answered with +// OS_EVENT_SI, which is what pfsManager_init already registered for and what +// its thread has been waiting on all along. +namespace { +std::atomic sReadPending{ false }; +std::mutex sLatchMutex; +OSContPad sLatch[MAXCONTROLLERS]; +std::atomic sLatchValid{ false }; +std::atomic sPumpLive{ false }; +} // namespace + +int32_t osContStartReadData(OSMesgQueue* mesg) { + (void)mesg; // completion goes to whoever registered for OS_EVENT_SI + sReadPending.store(true, std::memory_order_release); + return 0; +} + +extern "C" int OS_SiPumpLive(void) { + return sPumpLive.load(std::memory_order_acquire) ? 1 : 0; +} + +extern "C" int OS_SiService(void) { + sPumpLive.store(true, std::memory_order_release); + if (!sReadPending.exchange(false, std::memory_order_acq_rel)) { + return 0; + } + { + std::lock_guard lock(sLatchMutex); + memset(sLatch, 0, sizeof(sLatch)); + Ship::Context::GetRawInstance()->GetControlDeck()->WriteToPad(sLatch); + } + sLatchValid.store(true, std::memory_order_release); + OS_SendEventMesg(OS_EVENT_SI); + return 1; +} + +void osContGetReadData(OSContPad* pad) { + if (sLatchValid.load(std::memory_order_acquire)) { + std::lock_guard lock(sLatchMutex); + memcpy(pad, sLatch, sizeof(sLatch)); + return; + } + memset(pad, 0, sizeof(OSContPad) * __osMaxControllers); +} + +int32_t __osMotorAccess(OSPfs* pfs, uint32_t vibrate) { + auto io = Ship::Context::GetRawInstance()->GetControlDeck()->GetControllerByPort(pfs->channel)->GetRumble(); + if (vibrate) { + io->StartRumble(); + } else { + io->StopRumble(); + } + + return 0; +} + +int32_t osMotorInit(OSMesgQueue* ctrlrqueue, OSPfs* pfs, int32_t channel) { + pfs->channel = channel; + return 0; +} + +// Controller Pak gets probed first, the return kickstarts rumble +int32_t osPfsInit(OSMesgQueue* mq, OSPfs* pfs, int32_t channel) { + (void)mq; + (void)pfs; + (void)channel; + return PFS_ERR_DEVICE; +} + +} // extern "C" diff --git a/src/port/OS/OS_Mesg.cpp b/src/port/OS/OS_Mesg.cpp new file mode 100644 index 000000000..d0e2885a5 --- /dev/null +++ b/src/port/OS/OS_Mesg.cpp @@ -0,0 +1,239 @@ +// This file should eventually replace libultraship's os_mesg.cpp + +#include +#include +#include +#include + +#include + +#include "OS.h" + +extern "C" { +#include "libultraship/libultra/message.h" +#include "libultraship/libultra/internal.h" + +// Event -> (queue, message) routing table. +// Override from lus os_vi.cpp. +__OSEventState __osEventStateTab[OS_NUM_EVENTS] = { 0 }; +} + +// Message queues that can actually block. +// +// LUS's queues never do: osRecvMesg on an empty queue just returns -1. Every +// decomp thread is a loop parked on a queue, so they'd spin instead of sleeping +// and nobody would ever get woken. +// +// The queue fields themselves stay as they were, since decomp code reads them +// directly (pfsmanager watches validCount); only the waiting is ours, a +// condvar pair per queue where libultra used priority-ordered thread lists. +// Blocking is opt-in per queue. + +namespace { + +struct QueueSync { + std::condition_variable notEmpty; + std::condition_variable notFull; + bool blockingEnabled = false; +}; + +std::mutex sMesgMutex; +std::map sQueueSync; + +QueueSync& SyncFor(OSMesgQueue* mq) { + return sQueueSync[mq]; +} + +// Blocked-wait registry for the watchdog. Slots are atomics so a stall dump +// can read them without taking sMesgMutex (which a deadlocked thread may +// implicate); marking and clearing happen under sMesgMutex on the wait path. +constexpr int kMaxBlockedWaits = 16; +struct BlockedWaitSlot { + std::atomic tid{ 0 }; + std::atomic mq{ nullptr }; + std::atomic isSend{ 0 }; +}; +BlockedWaitSlot sBlockedWaits[kMaxBlockedWaits]; + +int MarkBlockedWait(OSMesgQueue* mq, int isSend) { + unsigned long tid = (unsigned long)SDL_ThreadID(); + for (int i = 0; i < kMaxBlockedWaits; i++) { + unsigned long expected = 0; + if (sBlockedWaits[i].tid.compare_exchange_strong(expected, tid, std::memory_order_acq_rel)) { + sBlockedWaits[i].mq.store(mq, std::memory_order_release); + sBlockedWaits[i].isSend.store(isSend, std::memory_order_release); + return i; + } + } + return -1; +} + +void ClearBlockedWait(int slot) { + if (slot >= 0) { + sBlockedWaits[slot].mq.store(nullptr, std::memory_order_release); + sBlockedWaits[slot].tid.store(0, std::memory_order_release); + } +} + +} // namespace + +extern "C" { + +void osCreateMesgQueue(OSMesgQueue* mq, OSMesg* msgBuf, int32_t count) { + std::lock_guard lock(sMesgMutex); + mq->mtqueue = nullptr; + mq->fullqueue = nullptr; + mq->validCount = 0; + mq->first = 0; + mq->msgCount = count; + mq->msg = msgBuf; + sQueueSync[mq]; +} + +int32_t osSendMesg(OSMesgQueue* mq, OSMesg msg, int32_t flag) { + std::unique_lock lock(sMesgMutex); + QueueSync& sync = SyncFor(mq); + int waitSlot = -1; + while (mq->validCount >= mq->msgCount) { + if (flag != OS_MESG_BLOCK || !sync.blockingEnabled) { + ClearBlockedWait(waitSlot); + return -1; + } + if (waitSlot < 0) { + waitSlot = MarkBlockedWait(mq, 1); + } + sync.notFull.wait(lock); + } + ClearBlockedWait(waitSlot); + s32 last = (mq->first + mq->validCount) % mq->msgCount; + mq->msg[last] = msg; + mq->validCount++; + sync.notEmpty.notify_one(); + return 0; +} + +// LUS bails when the queue is empty, which has it backwards. +// A jam should fail when there's no room, same as a send. +int32_t osJamMesg(OSMesgQueue* mq, OSMesg msg, int32_t flag) { + std::unique_lock lock(sMesgMutex); + QueueSync& sync = SyncFor(mq); + int waitSlot = -1; + while (mq->validCount >= mq->msgCount) { + if (flag != OS_MESG_BLOCK || !sync.blockingEnabled) { + ClearBlockedWait(waitSlot); + return -1; + } + if (waitSlot < 0) { + waitSlot = MarkBlockedWait(mq, 1); + } + sync.notFull.wait(lock); + } + ClearBlockedWait(waitSlot); + mq->first = (mq->first + mq->msgCount - 1) % mq->msgCount; + mq->msg[mq->first] = msg; + mq->validCount++; + sync.notEmpty.notify_one(); + return 0; +} + +int32_t osRecvMesg(OSMesgQueue* mq, OSMesg* msg, int32_t flag) { + std::unique_lock lock(sMesgMutex); + QueueSync& sync = SyncFor(mq); + int waitSlot = -1; + while (mq->validCount == 0) { + if (flag != OS_MESG_BLOCK || !sync.blockingEnabled) { + ClearBlockedWait(waitSlot); + return -1; + } + if (waitSlot < 0) { + waitSlot = MarkBlockedWait(mq, 0); + } + sync.notEmpty.wait(lock); + } + ClearBlockedWait(waitSlot); + if (msg != nullptr) { + *msg = mq->msg[mq->first]; + } + mq->first = (mq->first + 1) % mq->msgCount; + mq->validCount--; + sync.notFull.notify_one(); + return 0; +} + +void osSetEventMesg(OSEvent event, OSMesgQueue* mq, OSMesg msg) { + std::lock_guard lock(sMesgMutex); + if (event < OS_NUM_EVENTS) { + __osEventStateTab[event].queue = mq; + __osEventStateTab[event].msg = msg; + } +} + +void OS_SetQueueBlocking(OSMesgQueue* mq, int enabled) { + std::lock_guard lock(sMesgMutex); + SyncFor(mq).blockingEnabled = (enabled != 0); +} + +// Called once the window closes, before the tick is joined. +void OS_BeginShutdown(void) { + std::lock_guard lock(sMesgMutex); + for (auto& [mq, sync] : sQueueSync) { + (void)mq; + sync.blockingEnabled = false; + sync.notEmpty.notify_all(); + sync.notFull.notify_all(); + } +} + +// Lock-free on purpose: the caller is a watchdog inspecting a possible +// deadlock, so it must not touch sMesgMutex. Entries can be mid-update; +// they are diagnostics, not decisions. +int OS_MesgSnapshotBlockedWaits(OS_BlockedWait* out, int max) { + int n = 0; + for (int i = 0; i < kMaxBlockedWaits && n < max; i++) { + unsigned long tid = sBlockedWaits[i].tid.load(std::memory_order_acquire); + OSMesgQueue* mq = sBlockedWaits[i].mq.load(std::memory_order_acquire); + if (tid == 0 || mq == nullptr) { + continue; + } + out[n].tid = tid; + out[n].mq = mq; + out[n].isSend = sBlockedWaits[i].isSend.load(std::memory_order_acquire); + n++; + } + return n; +} + +// Raise a hardware event. Nothing interrupts on PC, so whoever stands in for a +// piece of hardware calls this when the real one would have fired. +void OS_SendEventMesg(OSEvent event) { + OSMesgQueue* mq = nullptr; + OSMesg msg = {}; + { + std::lock_guard lock(sMesgMutex); + if (event >= OS_NUM_EVENTS || __osEventStateTab[event].queue == nullptr) { + return; + } + mq = __osEventStateTab[event].queue; + msg = __osEventStateTab[event].msg; + } + osSendMesg(mq, msg, OS_MESG_NOBLOCK); +} + +// Same, but the message goes to the front of the queue. An interrupt landed +// ahead of whatever the recipient had queued; a hardware stand-in whose event +// must be seen before pending messages jams instead of sending. +void OS_JamEventMesg(OSEvent event) { + OSMesgQueue* mq = nullptr; + OSMesg msg = {}; + { + std::lock_guard lock(sMesgMutex); + if (event >= OS_NUM_EVENTS || __osEventStateTab[event].queue == nullptr) { + return; + } + mq = __osEventStateTab[event].queue; + msg = __osEventStateTab[event].msg; + } + osJamMesg(mq, msg, OS_MESG_NOBLOCK); +} + +} // extern "C" diff --git a/src/port/OS/OS_RCP.cpp b/src/port/OS/OS_RCP.cpp new file mode 100644 index 000000000..8a1c06e12 --- /dev/null +++ b/src/port/OS/OS_RCP.cpp @@ -0,0 +1,102 @@ +// This file should eventually go to LUS as the RCP api + +#include "OS.h" + +#include + +extern "C" { +#include +#include "libultraship/libultra/types.h" +#include "libultraship/libultra/sptask.h" +} + +// The RDP command unit's status register. +// +// Nothing on PC obeys FREEZE, since there is no RDP to stall, but thread5 runs +// its pipeline off that bit: it freezes after handing a frame over and clears +// it on the next retrace, which is what keeps one frame in flight. Holding the +// bit as real state lets that code run as written instead of being replaced. + +namespace { +std::atomic sStatus{ 0 }; +} + +extern "C" u32 osDpGetStatus(void) { + return sStatus.load(std::memory_order_acquire); +} + +// Writes are set/clear command pairs, mirrored into the bits reads return. +extern "C" void osDpSetStatus(u32 data) { + uint32_t set = 0; + uint32_t clr = 0; + if (data & DPC_SET_FREEZE) { + set |= DPC_STATUS_FREEZE; + } + if (data & DPC_CLR_FREEZE) { + clr |= DPC_STATUS_FREEZE; + } + if (data & DPC_SET_FLUSH) { + set |= DPC_STATUS_FLUSH; + } + if (data & DPC_CLR_FLUSH) { + clr |= DPC_STATUS_FLUSH; + } + if (set != 0) { + sStatus.fetch_or(set, std::memory_order_acq_rel); + } + if (clr != 0) { + sStatus.fetch_and(~clr, std::memory_order_acq_rel); + } +} + +// Task submission. +// +// There is no RSP, so this only hands the task over; whoever drains it decides +// what running one means. For the graphics task that has to be the window +// thread, since it ends up in the renderer. +// +// One slot is enough: the decomp starts a task and waits for its SP event +// before starting the next, so a second can never be pending. +namespace { +std::atomic sPendingTask{ nullptr }; +std::atomic sYieldPending{ false }; // yield requested, not yet observed +std::atomic sResumePending{ false }; // next gfx StartGo is the resume +} // namespace + +extern "C" void osSpTaskYield(void) { + sYieldPending.store(true, std::memory_order_release); + OS_JamEventMesg(OS_EVENT_SP); +} + +extern "C" OSYieldResult osSpTaskYielded(OSTask* task) { + (void)task; + if (sYieldPending.exchange(false, std::memory_order_acq_rel)) { + sResumePending.store(true, std::memory_order_release); + return 1; + } + return 0; +} + +extern "C" void osSpTaskLoad(OSTask* task) { + (void)task; // no DMEM to load; StartGo carries the pointer +} + +extern "C" void osSpTaskStartGo(OSTask* task) { + if (task->t.type == M_AUDTASK) { + OS_JamEventMesg(OS_EVENT_SP); + return; + } + + if (sResumePending.exchange(false, std::memory_order_acq_rel)) { + return; + } + sPendingTask.store(task, std::memory_order_release); +} + +extern "C" OSTask* OS_SpTakePendingTask(void) { + return sPendingTask.exchange(nullptr, std::memory_order_acq_rel); +} + +extern "C" OSTask* OS_SpPeekPendingTask(void) { + return sPendingTask.load(std::memory_order_acquire); +} diff --git a/src/port/OS/OS_Threads.cpp b/src/port/OS/OS_Threads.cpp new file mode 100644 index 000000000..250514944 --- /dev/null +++ b/src/port/OS/OS_Threads.cpp @@ -0,0 +1,155 @@ +// This file should eventually go to LUS as the threading api + +#include "OS.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +struct OsThreadState { + void (*entry)(void*) = nullptr; + void* arg = nullptr; + OSPri pri = 0; + OSId id = 0; + std::thread worker; + bool started = false; +}; + +std::mutex sTableMutex; +std::map sThreads; +std::set sEnabledEntries; + +bool ThreadEnabled(void* entry) { + return sEnabledEntries.count(entry) != 0; +} + +std::atomic sExitRequested{ false }; + +// Counted rather than joined blind: a thread stuck somewhere other than its queue +// wait would never see the request, and join() cannot time out. Waiting on the +// count lets us give up on a straggler instead of hanging the process on it. +std::mutex sExitMutex; +std::condition_variable sExitCv; +int sLiveThreads = 0; + +} // namespace + +extern "C" void OS_RequestThreadExit(void) { + sExitRequested.store(true, std::memory_order_release); +} + +extern "C" int OS_ThreadShouldExit(void) { + return sExitRequested.load(std::memory_order_acquire) ? 1 : 0; +} + +extern "C" void OS_JoinDecompThreads(void) { + bool allReturned; + { + std::unique_lock lock(sExitMutex); + allReturned = sExitCv.wait_for(lock, std::chrono::seconds(2), [] { return sLiveThreads == 0; }); + } + + std::lock_guard lock(sTableMutex); + for (auto& [thread, st] : sThreads) { + (void)thread; + if (!st.worker.joinable()) { + continue; + } + if (allReturned) { + st.worker.join(); + } else { + // Nothing safe left to do: it is still inside game code, so it cannot be + // joined without hanging and cannot be killed without leaving locks held. + // Detaching restores the pre-existing behaviour for that one thread. + st.worker.detach(); + } + } + if (!allReturned) { + SPDLOG_WARN("{} decomp thread(s) did not reach their exit check; detaching", sLiveThreads); + } +} + +extern "C" void OS_EnableThreadEntry(void* entry) { + std::lock_guard lock(sTableMutex); + sEnabledEntries.insert(entry); +} + +extern "C" void OS_CreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p) { + (void)sp; // N64 stack pointers are meaningless here + std::lock_guard lock(sTableMutex); + OsThreadState& st = sThreads[thread]; + st.entry = (void (*)(void*))entry; + st.arg = arg; + st.pri = p; + st.id = id; + st.started = false; +} + +extern "C" void OS_StartThread(OSThread* thread) { + std::lock_guard lock(sTableMutex); + auto it = sThreads.find(thread); + if (it == sThreads.end() || it->second.started || it->second.entry == nullptr) { + return; + } + if (!ThreadEnabled((void*)it->second.entry)) { + return; + } + it->second.started = true; + void (*entry)(void*) = it->second.entry; + void* arg = it->second.arg; + { + std::lock_guard exitLock(sExitMutex); + sLiveThreads++; + } + // Kept joinable: shutdown waits for these to leave their loops before the + // engine they draw and play audio through is destroyed. + it->second.worker = std::thread([entry, arg]() { + entry(arg); + { + std::lock_guard exitLock(sExitMutex); + sLiveThreads--; + } + sExitCv.notify_all(); + }); +} + +extern "C" void OS_StopThread(OSThread* thread) { + // N64 semantics are preemptive suspension, which std::thread cannot do. + // Revived consumers must exit cooperatively; Stop just joins if running. + OS_DestroyThread(thread); +} + +extern "C" void OS_DestroyThread(OSThread* thread) { + std::thread worker; + { + std::lock_guard lock(sTableMutex); + auto it = sThreads.find(thread); + if (it == sThreads.end()) { + return; + } + worker = std::move(it->second.worker); + sThreads.erase(it); + } + if (worker.joinable()) { + worker.join(); + } +} + +// Priority is recorded but not applied: the N64 scheduler was cooperative and +// priority-ordered, while these are preemptive OS threads. What the game needs +// from priority is queue ordering and blocking behavior, which the queues +// provide; mapping it onto OS thread priorities would only add scheduler noise. +extern "C" void OS_SetThreadPri(OSThread* thread, OSPri p) { + std::lock_guard lock(sTableMutex); + auto it = sThreads.find(thread); + if (it != sThreads.end()) { + it->second.pri = p; + } +} diff --git a/src/port/OS/OS_Time.cpp b/src/port/OS/OS_Time.cpp new file mode 100644 index 000000000..b068836d7 --- /dev/null +++ b/src/port/OS/OS_Time.cpp @@ -0,0 +1,39 @@ +// This file should eventually go back to LUS; it is unchanged from its +// libultra/os.cpp original, and only lives here because taking osSetTimer +// port-side means taking that whole object with it. + +#include +#include + +extern "C" { +#include "libultraship/libultra/types.h" +#include "libultraship/libultra/os.h" +} + +// A chrono duration matching the N64's 46.875MHz clock rate. +typedef std::ratio<3000, 64> n64ClockRatio; +typedef std::ratio_divide n64CycleRate; +typedef std::chrono::duration n64CycleRateDuration; + +extern "C" { + +uint64_t __osCurrentTime = 0; + +void osSetTime(OSTime time) { + __osCurrentTime = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count() + + time; +} + +uint64_t osGetTime() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count() - + __osCurrentTime; +} + +uint32_t osGetCount() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count(); +} + +} // extern "C" diff --git a/src/port/OS/OS_Timer.cpp b/src/port/OS/OS_Timer.cpp new file mode 100644 index 000000000..4a1c74361 --- /dev/null +++ b/src/port/OS/OS_Timer.cpp @@ -0,0 +1,121 @@ +// This file should eventually go to LUS as the timer api + +#include "OS.h" + +#include +#include +#include +#include +#include + +extern "C" { +#include "libultraship/libultra/time.h" +} + +// Deadline timers. LUS's osSetTimer returns 0 without arming anything and it +// has no osStopTimer at all, so a decomp timer never fired. Thread5 uses one +// to pace controller reads. +// +// Countdowns are in 46.875MHz ticks; 1e9/46875000 is exactly 64/3, so +// nanoseconds are ticks * 64 / 3 with no rounding. +namespace { + +struct Armed { + std::chrono::steady_clock::time_point deadline; + std::chrono::nanoseconds interval; + OSMesgQueue* mq = nullptr; + OSMesg msg = {}; +}; + +std::mutex sMutex; +std::map sTimers; +std::condition_variable sCv; +std::thread sWorker; +bool sWorkerStarted = false; +bool sStop = false; + +// One worker serves every timer, waking for whichever is due first and +// recomputing whenever the set changes under it. +void Worker() { + std::unique_lock lock(sMutex); + for (;;) { + if (sStop) { + return; + } + OSTimer* key = nullptr; + std::chrono::steady_clock::time_point deadline{}; + for (auto& [t, armed] : sTimers) { + if (key == nullptr || armed.deadline < deadline) { + key = t; + deadline = armed.deadline; + } + } + if (key == nullptr) { + sCv.wait(lock); + continue; + } + if (sCv.wait_until(lock, deadline) != std::cv_status::timeout) { + continue; // re-armed or stopped while waiting + } + if (sStop) { + return; + } + auto it = sTimers.find(key); + if (it == sTimers.end() || it->second.deadline != deadline) { + continue; // this one changed under the wait + } + OSMesgQueue* mq = it->second.mq; + OSMesg msg = it->second.msg; + if (it->second.interval.count() > 0) { + it->second.deadline += it->second.interval; + } else { + sTimers.erase(it); + } + lock.unlock(); + osSendMesg(mq, msg, OS_MESG_NOBLOCK); + lock.lock(); + } +} + +} // namespace + +extern "C" int osSetTimer(OSTimer* t, OSTime countdown, OSTime interval, OSMesgQueue* mq, OSMesg msg) { + std::lock_guard lock(sMutex); + if (sStop) { + return 0; + } + if (!sWorkerStarted) { + sWorkerStarted = true; + sWorker = std::thread(Worker); + } + Armed armed; + armed.deadline = std::chrono::steady_clock::now() + std::chrono::nanoseconds(countdown * 64 / 3); + armed.interval = std::chrono::nanoseconds(interval * 64 / 3); + armed.mq = mq; + armed.msg = msg; + sTimers[t] = armed; + sCv.notify_all(); + return 0; +} + +extern "C" int osStopTimer(OSTimer* t) { + std::lock_guard lock(sMutex); + sTimers.erase(t); + sCv.notify_all(); + return 0; +} + +extern "C" void OS_StopTimerWorker(void) { + { + std::lock_guard lock(sMutex); + if (!sWorkerStarted || sStop) { + return; + } + sStop = true; + sTimers.clear(); + } + sCv.notify_all(); + if (sWorker.joinable()) { + sWorker.join(); + } +} diff --git a/src/port/OS/OS_VI.cpp b/src/port/OS/OS_VI.cpp new file mode 100644 index 000000000..744eb1cf3 --- /dev/null +++ b/src/port/OS/OS_VI.cpp @@ -0,0 +1,111 @@ +// This file should eventually replace libultraship's os_vi.cpp + +#include "OS.h" + +#include +#include +#include + +#include "port/DevTools/ThreadWatchdog.h" + +extern "C" { +#include "libultraship/libultra/types.h" +#include "libultraship/libultra/vi.h" +} + +// The VI: retrace source and framebuffer registers. +// +// LUS drives retraces off an SDL timer at 16ms, which is 62.5Hz rather than 60, +// and only if SDL_INIT_TIMER were up. It never is, so retraces never fire at +// all. Game speed is meant to come off this cadence, so it needs to be a real +// 60Hz on an absolute schedule instead of an interval that drifts. +// +// The framebuffer registers are no-ops in LUS: swap does nothing and the +// getters return null. The decomp waits for a swap to latch and compares the +// current buffer against what it last saw, so they have to hold real values. + +namespace { + +std::thread sTicker; +std::atomic sTickerRun{ false }; + +std::atomic sNextFramebuffer{ nullptr }; +std::atomic sCurrentFramebuffer{ nullptr }; +std::atomic sBlack{ false }; + +} // namespace + +extern "C" void osCreateViManager(OSPri pri) { + (void)pri; + if (sTickerRun.exchange(true)) { + return; + } + sTicker = std::thread([] { + constexpr std::chrono::nanoseconds kVi(16666667); // NTSC 60Hz + auto next = std::chrono::steady_clock::now() + kVi; + while (sTickerRun.load(std::memory_order_relaxed)) { + std::this_thread::sleep_until(next); + next += kVi; + // If the process was suspended (debugger, sleep), resync rather + // than firing a burst of catch-up retraces. + auto now = std::chrono::steady_clock::now(); + if (now - next > std::chrono::milliseconds(100)) { + next = now + kVi; + } + // A retrace latches whatever swap armed, then raises VI. + sCurrentFramebuffer.store(sNextFramebuffer.load(std::memory_order_acquire), std::memory_order_release); + ThreadWatchdog_Beat(WATCHDOG_VI_TICKER); + OS_SendEventMesg(OS_EVENT_VI); + } + }); +} + +extern "C" void OS_StopViTicker(void) { + if (!sTickerRun.exchange(false)) { + return; + } + if (sTicker.joinable()) { + sTicker.join(); + } +} + +extern "C" void osViSetEvent(OSMesgQueue* queue, OSMesg mesg, u32 retraceCount) { + (void)retraceCount; + osSetEventMesg(OS_EVENT_VI, queue, mesg); +} + +extern "C" void osViSwapBuffer(void* framebuffer) { + sNextFramebuffer.store(framebuffer, std::memory_order_release); +} + +extern "C" void* osViGetNextFramebuffer(void) { + return sNextFramebuffer.load(std::memory_order_acquire); +} + +extern "C" void* osViGetCurrentFramebuffer(void) { + return sCurrentFramebuffer.load(std::memory_order_acquire); +} + +extern "C" void osViSetMode(OSViMode* mode) { + (void)mode; +} + +extern "C" void osViSetSpecialFeatures(u32 features) { + (void)features; +} + +extern "C" void osViBlack(u8 active) { + sBlack.store(active != 0, std::memory_order_release); +} + +extern "C" int OS_ViBlackActive(void) { + return sBlack.load(std::memory_order_acquire) ? 1 : 0; +} + +extern "C" void osViSetXScale(f32 scale) { + (void)scale; +} + +extern "C" void osViSetYScale(f32 scale) { + (void)scale; +} diff --git a/src/port/stub.c b/src/port/OS/libultra.c similarity index 62% rename from src/port/stub.c rename to src/port/OS/libultra.c index 20cf8c57f..b651a0bdc 100644 --- a/src/port/stub.c +++ b/src/port/OS/libultra.c @@ -1,7 +1,14 @@ +// BanjoDecomp: This file no longer exists upstream, +// but we do wrap its functions with our own. + +// Include the headers that declare what this file defines, so the compiler +// checks the definitions against them. #include "libultraship/libultra/types.h" #include "libultraship/libultra/interrupt.h" #include "libultraship/libultra/sptask.h" #include "libultraship/libultra/thread.h" +#include "libultraship/libultra/os.h" +#include "functions.h" #include "bk_string.h" #include @@ -16,29 +23,35 @@ s32 osViClock = VI_NTSC_CLOCK; u32 __osShutdown = 0; u32 __OSGlobalIntMask = OS_IM_ALL; s32 osCicId = 6103; -// [port] On N64 this was a fixed-address depth buffer at 0x8000E800 (naturally 0x40-aligned). +// On N64 this was a fixed-address depth buffer at 0x8000E800 (naturally 0x40-aligned). // On PC we need a properly sized and aligned buffer to avoid the alignment loop in func_80253428. _Alignas(0x40) u8 D_8000E800[DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIGHT * sizeof(u16)]; u16 gFramebuffers[2][DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIGHT]; +// Threads are in src/port/OS/OS.cpp. +void OS_CreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p); +void OS_StartThread(OSThread* thread); +void OS_StopThread(OSThread* thread); +void OS_DestroyThread(OSThread* thread); +void OS_SetThreadPri(OSThread* thread, OSPri p); + void osCreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p) { + OS_CreateThread(thread, id, entry, arg, sp, p); } void osStartThread(OSThread* thread) { + OS_StartThread(thread); } void osStopThread(OSThread* t) { + OS_StopThread(t); } void osDestroyThread(OSThread* thread) { -} -void osSpTaskYield(void) { -} -void osSpTaskLoad(OSTask* task) { -} -void osSpTaskStartGo(OSTask* task) { + OS_DestroyThread(thread); } void osViExtendVStart(u32 arg0) { } void osSetThreadPri(OSThread* thread, OSPri p) { + OS_SetThreadPri(thread, p); } s32 osContSetCh(u8 ch) { return 0; @@ -48,23 +61,12 @@ u32 __osGetSR(void) { } void __osSetSR(u32 value) { } +// All interrupt-enable bits set. thread5_checkAndExecutePreNMI reads SR_IBIT5 +// and treats a clear bit as "reset pressed"; with retraces running, returning +// 0 fires the PreNMI handler 60 times a second. u32 bkGetSR(void) { - return 0; -} -OSYieldResult osSpTaskYielded(OSTask* task) { - return 0; + return 0xFFFFFFFFu; } -// Lighthouse TODO these need to be implemented in LUS -int osStartTimer(void* t) { - return 0; -} -int osStopTimer(void* t) { - return 0; -} - -void osDpSetStatus(u32 data) { -} - void __osError(s16 error_code, s16 num_args, ...) { } diff --git a/src/port/Patches/AnimVertexPatches.cpp b/src/port/Patches/AnimVertexPatches.cpp new file mode 100644 index 000000000..87595b545 --- /dev/null +++ b/src/port/Patches/AnimVertexPatches.cpp @@ -0,0 +1,54 @@ +#include +#include +#include + +extern "C" { +#include +#include "functions.h" +#include "libultraship/libultra/gbi.h" +#include "port/Patches/Patches.h" +} + +#include "port/Interpolation/FrameInterpolation.h" + +namespace { + +// A single anim-vertex model runs 500-750 vertices. This covers roughly 20-25 +// of them on screen at once; past that a draw falls back to the shared buffer, +// which is exactly the behaviour that existed before this file. +constexpr size_t kVerticesPerSlot = 16384; +constexpr int kSlots = 2; + +Vtx* gArena[kSlots] = {}; +size_t gUsed = 0; +int gSlot = 0; +bool gWarnedExhausted = false; + +} // namespace + +extern "C" void port_animVtx_beginTick(void) { + gSlot = (gSlot + 1) % kSlots; + gUsed = 0; + if (gArena[gSlot] == nullptr) { + gArena[gSlot] = new (std::nothrow) Vtx[kVerticesPerSlot]; + } +} + +extern "C" void port_modelRender_snapshotAnimVertices(Gfx** gfx, void* vertices, int32_t count) { + if (gfx == nullptr || vertices == nullptr || count <= 0) { + return; + } + Vtx* arena = gArena[gSlot]; + if (arena == nullptr || gUsed + (size_t)count > kVerticesPerSlot) { + return; + } + + Vtx* copy = arena + gUsed; + gUsed += (size_t)count; + std::memcpy(copy, vertices, (size_t)count * sizeof(Vtx)); + + // Hand the pose to interpolation. It owns the blend from here: this buffer + // is private to this draw, so replay can rewrite it per sub-frame. + FrameInterpolation_RecordAnimVertices(copy, vertices, count); + gSPSegment((*gfx)++, 0x01, osVirtualToPhysical(copy)); +} diff --git a/src/port/Patches/CameraPatches.cpp b/src/port/Patches/CameraPatches.cpp index 733372f18..6770a57f3 100644 --- a/src/port/Patches/CameraPatches.cpp +++ b/src/port/Patches/CameraPatches.cpp @@ -13,13 +13,9 @@ #include "port/ShipInit.hpp" #include "port/ShipUtils.h" -extern "C" { #include "enums.h" #include "functions.h" #include "variables.h" -enum level_e map_getLevel(enum map_e map); -enum map_e gsworld_getMap(void); -} #include @@ -96,6 +92,7 @@ static void updateCutsceneAspect(int32_t mapId) { // Widescreen yaw fix — per-frame yaw adjustment for certain static cameras in widescreen mode #define CVAR_WS_CAMERA_FIX CVAR_ENHANCEMENT("Fix.WidescreenCamera") +#define CVAR_NO_SCREEN_SHAKE CVAR_SETTING("A11yDisableScreenShake") struct WsYawFix { int32_t map; @@ -176,5 +173,11 @@ void RegisterCameraPatches_Init() { }); } +void RegisterScreenShake_Init() { + COND_VB_SHOULD(VB_CAMERA_APPLY_SHAKE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_SCREEN_SHAKE, 0), + { *should = false; }); +} + static RegisterShipInitFunc cutsceneAspectInitFunc(RegisterCutsceneAspect, { CVAR_CUTSCENE_ASPECT }); static RegisterShipInitFunc staticCamInitFunc(RegisterCameraPatches_Init); +static RegisterShipInitFunc screenShakeInitFunc(RegisterScreenShake_Init, { CVAR_NO_SCREEN_SHAKE }); diff --git a/src/port/Patches/FramePacingPatches.cpp b/src/port/Patches/FramePacingPatches.cpp index 5ff05d6ee..4c7081372 100644 --- a/src/port/Patches/FramePacingPatches.cpp +++ b/src/port/Patches/FramePacingPatches.cpp @@ -20,33 +20,27 @@ enum map_e gsworld_getMap(void); // Demo Display Pacing static int sDemoViCount = 0; +static constexpr int kMaxDemoViCount = 0xF; int port_getDemoViCount(void) { return sDemoViCount; } void port_setDemoViCount(int viCount) { - sDemoViCount = viCount; + sDemoViCount = (viCount > kMaxDemoViCount) ? kMaxDemoViCount : viCount; } int port_getDemoDisplayViCount(int rawViCount) { - int displayViCount = rawViCount; - int game_mode = getGameMode(); - - if (game_mode == GAME_MODE_8_BOTTLES_BONUS) { - displayViCount = 3; - } else if (game_mode == GAME_MODE_A_SNS_PICTURE) { + if (getGameMode() == GAME_MODE_A_SNS_PICTURE) { switch (gsworld_getMap()) { case MAP_7F_FP_WOZZAS_CAVE: case MAP_92_GV_SNS_CHAMBER: - displayViCount = 3; - break; + return 3; default: break; } } - - return displayViCount; + return rawViCount; } // Cutscene Stutter Compensation @@ -62,6 +56,7 @@ static int sLairDingpotDurations[] = { 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, static int sCutsceneCounter = 0; static int sCutsceneNextStutter = 0; static int sCutsceneLagIndex = 0; +static int sCutsceneExtraVis = 0; static bool shouldLagCutscene(int* startFrames, int* durations, int count) { if (sCutsceneNextStutter == -1) { @@ -93,47 +88,40 @@ static void resetCutsceneTimings(void) { sCutsceneCounter = 0; sCutsceneNextStutter = 0; sCutsceneLagIndex = 0; + sCutsceneExtraVis = 0; } -int port_getCutsceneExtraVis(void) { - if (!CVarGetInteger(CVAR_CUTSCENE_SYNC, 1)) - return 0; +// Advances the stutter tables by one cutscene frame. Called from func_802E4384, +// the single point where a tick commits its time delta, so every consumer of +// port_getCutsceneExtraVis() sees the same answer for that tick. +void port_tickCutsceneStutter(void) { + sCutsceneExtraVis = 0; - int extra = 0; + if (!CVarGetInteger(CVAR_CUTSCENE_SYNC, 1)) + return; switch (gsworld_getMap()) { case MAP_1E_CS_START_NINTENDO: if (shouldLagCutscene(sConcertStartFrames, sConcertDurations, (int)(sizeof(sConcertStartFrames) / sizeof(sConcertStartFrames[0])))) { - extra = 1; + sCutsceneExtraVis = 1; } sCutsceneCounter++; break; case MAP_7B_CS_INTRO_GL_DINGPOT_1: if (shouldLagCutscene(sLairDingpotStartFrames, sLairDingpotDurations, (int)(sizeof(sLairDingpotStartFrames) / sizeof(sLairDingpotStartFrames[0])))) { - extra = 1; + sCutsceneExtraVis = 1; } sCutsceneCounter++; break; default: break; } - - return extra; } -int port_getInterpolationFpsCap(void) { - if (!CVarGetInteger(CVAR_CUTSCENE_SYNC, 1)) - return 0; - - switch (gsworld_getMap()) { - // [port] Cap concert to 30 fps - case MAP_1E_CS_START_NINTENDO: - return 30; - default: - return 0; - } +int port_getCutsceneExtraVis(void) { + return sCutsceneExtraVis; } } // extern "C" diff --git a/src/port/Patches/FramebufferPatches.cpp b/src/port/Patches/FramebufferPatches.cpp index 06d71ab31..15549e843 100644 --- a/src/port/Patches/FramebufferPatches.cpp +++ b/src/port/Patches/FramebufferPatches.cpp @@ -5,17 +5,22 @@ #include +#include "port/Engine.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/ShipInit.hpp" + +// From Patches.h; declared here because this file's definitions use concrete +// Gfx/model types where the header declares void*. +extern "C" void port_runOnRenderThread(void (*fn)(void*), void* arg); + extern "C" { #include "core1/core1.h" #include "model.h" -int gfx_create_framebuffer(unsigned int width, unsigned int height, unsigned int native_width, - unsigned int native_height, unsigned char resize, unsigned char force_fixed_aspect); void gfx_register_fb_texture(const void* cpuAddr, int fbId); BKGfxList* modelbin_getGfxList(BKModelBin* arg0); -unsigned int OTRGetGameRenderWidth(void); -unsigned int OTRGetGameRenderHeight(void); +s32 getGameMode(void); // During FADE_IN, the game disables scene drawing one frame before // capturing gFramebuffers. Without freezing, the readback would overwrite @@ -65,10 +70,17 @@ static void currentRenderSize(int* w, int* h) { } } +// Framebuffer creation talks to the renderer, so under thread5 mode it has to +// happen on the render thread rather than the game tick. +static void createPauseFb(void* arg) { + (void)arg; + s_pauseFbId = gfx_create_framebuffer(s_pauseFbW, s_pauseFbH, s_pauseFbW, s_pauseFbH, 0, 0); +} + int port_getPauseFramebufferId(void) { if (s_pauseFbId < 0) { currentRenderSize(&s_pauseFbW, &s_pauseFbH); - s_pauseFbId = gfx_create_framebuffer(s_pauseFbW, s_pauseFbH, s_pauseFbW, s_pauseFbH, 0, 0); + port_runOnRenderThread(createPauseFb, NULL); } return s_pauseFbId; } @@ -84,7 +96,7 @@ int port_capturePauseFramebuffer(void) { if (s_pauseFbId < 0 || w != s_pauseFbW || h != s_pauseFbH) { s_pauseFbW = w; s_pauseFbH = h; - s_pauseFbId = gfx_create_framebuffer(w, h, w, h, 0, 0); + port_runOnRenderThread(createPauseFb, NULL); } return s_pauseFbId; } @@ -179,28 +191,63 @@ static void patchModelDL(BKModelBin* model_bin, uintptr_t seg_start, uintptr_t s #define IMAGE_WIDTH (TILE_SIZE * 5) #define IMAGE_HEIGHT (TILE_SIZE * 4) -// Aux picture FB readback (Bottles Bonus / SNS pictures) +// Aux picture FB (Bottles Bonus / SNS pictures) -extern s16* D_80382450; // aux picture CPU buffer (picturebuffer.c) -extern s32 sAuxGpuFbId; // aux picture GPU FB id (picturebuffer.c) +// Scale the framebuffer from 160x128 based on the application width -s32 port_getAuxGpuFbId(void) { - return sAuxGpuFbId; +static u16 sAuxFbDummy[1]; + +#define AUX_FB_SCALE_MAX 2 +#define AUX_FB_SCALE_STEP_WIDTH 640 + +static s32 sAuxGpuFbId = -1; +static int s_auxFbRenderW = 0; +static int s_auxFbRenderH = 0; + +static int auxFbScale(void) { + int scale = s_auxFbRenderW / AUX_FB_SCALE_STEP_WIDTH; + + if (scale > AUX_FB_SCALE_MAX) { + scale = AUX_FB_SCALE_MAX; + } + if (scale < 1) { + scale = 1; + } + return scale; +} + +static void createAuxFb(void* arg) { + (void)arg; + int scale = auxFbScale(); + int nativeW = s_auxFbRenderW / scale; + int nativeH = s_auxFbRenderH / scale; + + if (nativeW < 1) { + nativeW = 1; + } + if (nativeH < 1) { + nativeH = 1; + } + sAuxGpuFbId = gfx_create_framebuffer(IMAGE_WIDTH, IMAGE_HEIGHT, nativeW, nativeH, 1, true); + if (sAuxGpuFbId >= 0) { + gfx_register_fb_texture(sAuxFbDummy, sAuxGpuFbId); + } } -void port_readAuxFbToCpu(Gfx** gfx) { - if (sAuxGpuFbId >= 0 && D_80382450 != NULL) { - gDPReadFB((*gfx)++, sAuxGpuFbId, (u16*)D_80382450, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1); - __gSPInvalidateTexCache((*gfx)++, 0); +static s32 auxGpuFbId(void) { + int w; + int h; + currentRenderSize(&w, &h); + if (sAuxGpuFbId < 0 || w != s_auxFbRenderW || h != s_auxFbRenderH) { + s_auxFbRenderW = w; + s_auxFbRenderH = h; + port_runOnRenderThread(createAuxFb, NULL); } + return sAuxGpuFbId; } // Picture model patching (Bottles Bonus / SNS pictures) -#define TILE_SIZE 32 -#define IMAGE_WIDTH (TILE_SIZE * 5) -#define IMAGE_HEIGHT (TILE_SIZE * 4) -#define SEG4_TAGGED ((uintptr_t)0x04000000 | 1) #define FROM_XZ 0 #define FROM_YZ 1 @@ -230,8 +277,8 @@ void port_patchPictureModel(BKModelBin* model_bin, s32 min_xy, s32 max_xy, s32 m sPicMaxXY = max_xy; sPicMinZ = min_z; sPicMaxZ = max_z; - patchModelDL(model_bin, 0x04000000, 0x04100000, (const void*)SEG4_TAGGED, IMAGE_WIDTH, IMAGE_HEIGHT, - setPictureVertexTexcoord, G_TF_BILERP, 1); + patchModelDL(model_bin, 0x04000000, 0x04100000, sAuxFbDummy, IMAGE_WIDTH, IMAGE_HEIGHT, setPictureVertexTexcoord, + G_TF_BILERP, 1); } // Transition model patching (falling jiggy pieces) @@ -241,11 +288,16 @@ void port_patchPictureModel(BKModelBin* model_bin, s32 min_xy, s32 max_xy, s32 m static u16 sTransitionFbDummy[1]; static s32 sTransitionGpuFbId = -1; +static void createTransitionFb(void* arg) { + (void)arg; + sTransitionGpuFbId = gfx_create_framebuffer(DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, + DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, 1, 0); + gfx_register_fb_texture(sTransitionFbDummy, sTransitionGpuFbId); +} + s32 port_getTransitionGpuFbId(void) { if (sTransitionGpuFbId < 0) { - sTransitionGpuFbId = gfx_create_framebuffer(DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, - DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, 1, 0); - gfx_register_fb_texture(sTransitionFbDummy, sTransitionGpuFbId); + port_runOnRenderThread(createTransitionFb, NULL); } return sTransitionGpuFbId; } @@ -281,3 +333,36 @@ void port_patchTransitionModel(BKModelBin* model_bin) { } } // extern "C" + +// Submitted picture-mode frames since the last map load. The first few frames a +// reloaded map composes are structurally normal DLs that draw nothing visible. +static s32 sPicFramesSinceMapLoad = 0; +static constexpr s32 kPicWarmupFrames = 3; + +void RegisterFramebufferPatches_Init() { + REGISTER_VB_SHOULD(VB_PICTUREBOX_TARGET_FB, EVENT_PRIORITY_NORMAL, { + Gfx** gdl = va_arg(args, Gfx**); + s32 auxFb = auxGpuFbId(); + if (gdl != nullptr && auxFb >= 0) { + gsSPSetFB((*gdl)++, auxFb); + } + (void)should; + }); + + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { sPicFramesSinceMapLoad = 0; }); + + REGISTER_VB_SHOULD(VB_PICTUREBOX_SUBMIT_FRAME, EVENT_PRIORITY_NORMAL, { + s32 gfxCount = va_arg(args, s32); + s32 mode = getGameMode(); + if (mode == GAME_MODE_8_BOTTLES_BONUS || mode == GAME_MODE_A_SNS_PICTURE) { + sPicFramesSinceMapLoad++; + if (sPicFramesSinceMapLoad <= kPicWarmupFrames || gfxCount < 100) { + SPDLOG_INFO("[pictureDiag] dropped frame (sinceLoad={}, gfxCount={})", sPicFramesSinceMapLoad, + gfxCount); + *should = false; + } + } + }); +} + +static RegisterShipInitFunc initFramebufferPatches(RegisterFramebufferPatches_Init); diff --git a/src/port/Patches/GeoCull.cpp b/src/port/Patches/GeoCull.cpp index 52d9e2f06..099e91a8c 100644 --- a/src/port/Patches/GeoCull.cpp +++ b/src/port/Patches/GeoCull.cpp @@ -2,6 +2,10 @@ #include "port/Enhancements/Events/Hooks/Events.h" +extern "C" { +#include "model.h" +} + static int sConsumerMask = 0; extern "C" void GeoCull_SetConsumer(int consumerBit, int active) { @@ -21,7 +25,13 @@ extern "C" int port_geoCullDraw(int type, const void* cmd, const void* modelBin, return drawnVanilla; } - int offset = (int)((const unsigned char*)cmd - (const unsigned char*)modelBin); + // Key commands by their offset within the geo command list. + const auto* bin = static_cast(modelBin); + const unsigned char* geoBase = (const unsigned char*)modelBin; + if (bin != nullptr) { + geoBase += bin->geo_list_offset; + } + int offset = (int)((const unsigned char*)cmd - geoBase); bool forceDraw = false; CALL_EVENT(OnGeoCull, type, offset, modelBin, areaIds, areaCount, detail0, detail1, drawnVanilla, &forceDraw); return (drawnVanilla || forceDraw) ? 1 : 0; diff --git a/src/port/Patches/GeoCull.h b/src/port/Patches/GeoCull.h index 93daa8cfb..f43303833 100644 --- a/src/port/Patches/GeoCull.h +++ b/src/port/Patches/GeoCull.h @@ -22,10 +22,6 @@ extern "C" { #define GEOCULL_CONSUMER_DEBUG 1 #define GEOCULL_CONSUMER_ENHANCEMENT 2 -// Called from each conditional cull command in render.c. `cmd`/`modelBin` give the command's -// stable byte offset; `drawnVanilla` is the unmodified recurse decision. areaIds/areaCount -// apply to CAMERA only (NULL/0 otherwise); detail0/detail1 are kind-specific extras (CAMERA: -// flags; LOD: min,max). Returns the final draw decision (1 = draw). int port_geoCullDraw(int type, const void* cmd, const void* modelBin, int drawnVanilla, const unsigned char* areaIds, int areaCount, int detail0, int detail1); diff --git a/src/port/Patches/GraphicsPatches.cpp b/src/port/Patches/GraphicsPatches.cpp index bf3d81e9f..d8082b1f4 100644 --- a/src/port/Patches/GraphicsPatches.cpp +++ b/src/port/Patches/GraphicsPatches.cpp @@ -1,5 +1,10 @@ +#include +#include +#include + #include #include "port/UI/cvar_prefixes.h" +#include "port/Engine.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" #include "port/ShipUtils.h" @@ -7,47 +12,60 @@ #define CVAR_DRAW_DISTANCE CVAR_ENHANCEMENT("Graphics.DrawDistance") #define CVAR_DISABLE_LOD CVAR_ENHANCEMENT("Graphics.DisableLOD") +#define CVAR_FP_LOBBY_DOOR_TILE CVAR_ENHANCEMENT("Fixes.FPLobbyDoorTile") static const int kMaxDrawDistanceMul = 6; static int sDrawDistanceCubeWidth(int mul) { return 4 * mul; } -static int sDrawDistanceLevel = 0; +static int sDrawDistanceLevel = 1; static int sDisableLOD = 0; extern "C" { +#include #include "enums.h" #include "functions.h" +#include "libultraship/libultra/gbi.h" +#include "port/Romhack/RomhackConfig.h" extern s32 gFramebufferWidth; extern s32 gFramebufferHeight; -float GameEngine_GetAspectRatio(void); + +// Romhack model display lists can leave a palette (TLUT) mode enabled and leak it +// into the next model's draw. +void port_modelRenderResetTLUT(Gfx** gfx) { + if (!port_isRomhack()) { + return; + } + gDPSetTextureLUT((*gfx)++, G_TT_NONE); +} // Widescreen HUD edge anchoring (centered-ortho HUD geometry). + +static const float kHudCenterBand = 32.0f; + float port_hudOrthoShift(float refX) { float halfW = (f32)gFramebufferWidth * 0.5f; float extraHalf = (f32)gFramebufferHeight * 0.5f * GameEngine_GetAspectRatio() - halfW; if (extraHalf < 0.0f) { extraHalf = 0.0f; // narrower than 4:3 (e.g. pillarboxed): never pull inward } - if (refX < halfW) { + if (refX < halfW - kHudCenterBand) { return -extraHalf; // left-anchored } - if (refX > halfW) { + if (refX > halfW + kHudCenterBand) { return extraHalf; // right-anchored } return 0.0f; // centered } +int port_getDrawDistanceSetting(void) { + return sDrawDistanceLevel; +} + int port_getDrawDistanceLevel(void) { - int mul = CVarGetInteger(CVAR_ENHANCEMENT("Graphics.DrawDistance"), 1); - if (mul < 1) { - mul = 1; - } - if (mul > kMaxDrawDistanceMul) { - mul = kMaxDrawDistanceMul; - } + int mul = port_getDrawDistanceSetting(); if (IsDemoMode() && getGameMode() != GAME_MODE_4_PAUSED) { mul = 1; } @@ -96,7 +114,9 @@ static void OnGeoCull_LevelOcclusion(IEvent* event) { if (ev->type != OCCLUSION_CMD_CAMERA) { return; } - if (gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN && ev->offset == 0x2CD0 && + // Offset into the opaque map model's geo command list (the "outside areas {1,2}" CAMERA + // command). Read it off the Occlusion Debugger, which reports the same geo-relative key. + if (gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN && ev->offset == 0x2C98 && ev->modelBin == (const void*)mapModel_getModelBin(0)) { *ev->forceDraw = true; } @@ -129,8 +149,155 @@ static void RegisterDrawDistanceGraphics_Init() { static RegisterShipInitFunc drawDistanceGraphicsInit(RegisterDrawDistanceGraphics_Init, { CVAR_DRAW_DISTANCE }); static void RefreshDrawDistanceCVars() { - sDrawDistanceLevel = CVarGetInteger(CVAR_DRAW_DISTANCE, 1); + int mul = CVarGetInteger(CVAR_DRAW_DISTANCE, 1); + if (mul < 1) { + mul = 1; + } + if (mul > kMaxDrawDistanceMul) { + mul = kMaxDrawDistanceMul; + } + sDrawDistanceLevel = mul; sDisableLOD = CVarGetInteger(CVAR_DISABLE_LOD, 0); } static RegisterShipInitFunc drawDistanceCVarCache(RefreshDrawDistanceCVars, { CVAR_DRAW_DISTANCE, CVAR_DISABLE_LOD }); + +// ============================================================================ +// STALE TILE DESCRIPTOR — Freezeezy Peak lobby door trim +// ============================================================================ + +// F3DEX opcodes as used by BK64. +static const uint8_t kOpVtx = 0x04; +static const uint8_t kOpTri2 = 0xB1; +static const uint8_t kOpTri1 = 0xBF; +static const uint8_t kOpSetTileSize = 0xF2; +static const uint8_t kOpSetTile = 0xF5; +static const uint8_t kOpSetTImg = 0xFD; + +static const uint32_t kTxClampBit = 0x2; // G_TX_CLAMP +static const uint8_t kRenderTile = 0; // G_TX_RENDERTILE + +// Torch tags a G_SETTIMG that references an extracted texture by putting 0xFF in +// the top byte of w1 and the texture index in the low 24 bits. +static const uint32_t kTexMarker = 0xFF; + +static const char kFPLobbySuffix[] = "GL_FP_LOBBY_OPA"; + +static bool sPathEndsWith(const char* path, const char* suffix) { + if (path == NULL) { + return false; + } + size_t plen = strlen(path); + size_t slen = strlen(suffix); + return plen >= slen && strcmp(path + plen - slen, suffix) == 0; +} + +static void OnModelDisplayListLoad_StaleTile(IEvent* event) { + auto* ev = reinterpret_cast(event); + if (ev->dlWords == NULL || ev->texSizes == NULL || !sPathEndsWith(ev->path, kFPLobbySuffix)) { + return; + } + + // Walk the list tracking live render-tile state, flagging any G_SETTILE whose + // clamp causes a larger texture to be drawn through a smaller tile. + std::vector toPatch; + int curTex = -1; + uint32_t liveTile = UINT32_MAX; + uint32_t tileW = 0, tileH = 0; + + for (uint32_t i = 0; i + 1 < ev->dlWordCount; i += 2) { + uint32_t w0 = ev->dlWords[i]; + uint32_t w1 = ev->dlWords[i + 1]; + uint8_t op = (uint8_t)(w0 >> 24); + + if (op == kOpSetTImg) { + if (((w1 >> 24) & 0xFF) == kTexMarker) { + curTex = (int)(w1 & 0x00FFFFFF); + } + } else if (op == kOpSetTile) { + if (((w1 >> 24) & 0x7) == kRenderTile) { + liveTile = i; + } + } else if (op == kOpSetTileSize) { + if (((w1 >> 24) & 0x7) == kRenderTile) { + uint32_t uls = (w0 >> 12) & 0xFFF; + uint32_t ult = w0 & 0xFFF; + uint32_t lrs = (w1 >> 12) & 0xFFF; + uint32_t lrt = w1 & 0xFFF; + tileW = ((lrs - uls) / 4) + 1; + tileH = ((lrt - ult) / 4) + 1; + } + } else if (op == kOpVtx || op == kOpTri1 || op == kOpTri2) { + if (curTex < 0 || liveTile == UINT32_MAX || tileW == 0 || tileH == 0) { + continue; + } + if ((uint32_t)curTex >= ev->texCount) { + continue; + } + uint32_t declW = ev->texSizes[curTex].width; + uint32_t declH = ev->texSizes[curTex].height; + if (declW <= tileW && declH <= tileH) { + continue; + } + uint32_t tileWord = ev->dlWords[liveTile + 1]; + uint32_t cms = (tileWord >> 8) & 0x3; + uint32_t cmt = (tileWord >> 18) & 0x3; + if (((cms & kTxClampBit) == 0) && ((cmt & kTxClampBit) == 0)) { + continue; + } + // Only safe to swap clamp for wrap when the mask makes the wrap period + // exactly the texture size. + uint32_t masks = (tileWord >> 4) & 0xF; + uint32_t maskt = (tileWord >> 14) & 0xF; + if (masks == 0 || maskt == 0 || (1u << masks) != declW || (1u << maskt) != declH) { + continue; + } + if (std::find(toPatch.begin(), toPatch.end(), liveTile) == toPatch.end()) { + toPatch.push_back(liveTile); + } + } + } + + for (size_t n = 0; n < toPatch.size(); n++) { + ev->dlWords[toPatch[n] + 1] &= ~((kTxClampBit << 18) | (kTxClampBit << 8)); + } +} + +static void RegisterStaleTileFix_Init() { + COND_HOOK(OnModelDisplayListLoad, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FP_LOBBY_DOOR_TILE, 0), + OnModelDisplayListLoad_StaleTile); +} + +static RegisterShipInitFunc staleTileFixInit(RegisterStaleTileFix_Init, { CVAR_FP_LOBBY_DOOR_TILE }); + +// ============================ +// INHERITED RENDER STATE +// ============================ + +static void ApplySnowRenderState(Gfx** gfx) { + gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | + G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); + gSPSetGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH); + gDPSetAlphaCompare((*gfx)++, G_AC_NONE); + gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF); + gDPSetEnvColor((*gfx)++, 0xFF, 0xFF, 0xFF, 0xFF); + gDPSetBlendColor((*gfx)++, 0x00, 0x00, 0x00, 0x80); +} + +static void RegisterSnowRenderState_Init() { + COND_VB_SHOULD(VB_SNOW_RENDER_STATE, EVENT_PRIORITY_NORMAL, true, { + ApplySnowRenderState(va_arg(args, Gfx**)); + *should = false; + }); +} + +static RegisterShipInitFunc sSnowRenderStateInit(RegisterSnowRenderState_Init); + +static void RegisterModelDrawDistFadeAlpha_Init() { + COND_VB_SHOULD(VB_MODEL_DRAWDIST_FADE_ALPHA, EVENT_PRIORITY_NORMAL, true, { + s32* alpha = va_arg(args, s32*); + *alpha = std::clamp(*alpha, 0, 0xFF); + }); +} + +static RegisterShipInitFunc sModelDrawDistFadeAlphaInit(RegisterModelDrawDistFadeAlpha_Init); diff --git a/src/port/Patches/MirrorPatches.cpp b/src/port/Patches/MirrorPatches.cpp index 9455105df..eb8264a25 100644 --- a/src/port/Patches/MirrorPatches.cpp +++ b/src/port/Patches/MirrorPatches.cpp @@ -5,10 +5,10 @@ #include #include +#include "functions.h" extern "C" { #include "model.h" #include "prop.h" -#include "functions.h" } static bool sMirrorSceneActive = false; @@ -25,12 +25,12 @@ static ActorDrawFunc sOrig_actor_draw = nullptr; extern "C" { // ActorInfo externs for text-bearing models (must be inside extern "C" for correct linkage) -extern ActorInfo D_80393354; // level entry signs (model 0x563) -extern ActorInfo D_80367530; // 5 mumbo token sign (0x301) -extern ActorInfo D_80367554; // 10 mumbo token sign (0x302) -extern ActorInfo D_80367578; // 15 mumbo token sign (0x303) -extern ActorInfo D_8036759C; // 20 mumbo token sign (0x304) -extern ActorInfo D_803675C0; // 25 mumbo token sign (0x305) +extern ActorInfo D_80393354; // level entry signs (model 0x563) +extern ActorInfo chMumboSign5; // 5 mumbo token sign (0x301) +extern ActorInfo chMumboSign10; // 10 mumbo token sign (0x302) +extern ActorInfo chMumboSign15; // 15 mumbo token sign (0x303) +extern ActorInfo chMumboSign20; // 20 mumbo token sign (0x304) +extern ActorInfo chMumboSign25; // 25 mumbo token sign (0x305) // Custom draw functions used by text-bearing actors (not in functions.h) extern Actor* lair_func_80387560(ActorMarker*, Gfx**, Mtx**, Vtx**); @@ -142,11 +142,11 @@ void port_mirror_patchTextActors(void) { // Mumbo token signs (5 variants: 5, 10, 15, 20, 25 tokens) sOrig_actor_draw = (ActorDrawFunc)actor_draw; - D_80367530.draw_func = mirror_excluded_actor_draw; - D_80367554.draw_func = mirror_excluded_actor_draw; - D_80367578.draw_func = mirror_excluded_actor_draw; - D_8036759C.draw_func = mirror_excluded_actor_draw; - D_803675C0.draw_func = mirror_excluded_actor_draw; + chMumboSign5.draw_func = mirror_excluded_actor_draw; + chMumboSign10.draw_func = mirror_excluded_actor_draw; + chMumboSign15.draw_func = mirror_excluded_actor_draw; + chMumboSign20.draw_func = mirror_excluded_actor_draw; + chMumboSign25.draw_func = mirror_excluded_actor_draw; } } // extern "C" diff --git a/src/port/Patches/Patches.h b/src/port/Patches/Patches.h index cf1c8a564..bb77404c1 100644 --- a/src/port/Patches/Patches.h +++ b/src/port/Patches/Patches.h @@ -7,13 +7,22 @@ extern "C" { #endif +// Threaded rendering (Game.cpp) + +// Carries the interpolation pair with a submitted display list. +void port_thread5_onSubmit(void* taskData); +// Runs fn on the window thread when the tick is on its own thread. +void port_runOnRenderThread(void (*fn)(void*), void* arg); +// Waits for in-flight display lists before freeing or reading what they use. +void port_pipelineSyncPoint(void); + // Frame Pacing (FramePacingPatches.cpp) int port_getDemoViCount(void); void port_setDemoViCount(int viCount); int port_getDemoDisplayViCount(int rawViCount); +void port_tickCutsceneStutter(void); int port_getCutsceneExtraVis(void); -int port_getInterpolationFpsCap(void); // Localization (Localization.cpp) @@ -21,10 +30,13 @@ int port_pauseMenuNeedsRefresh(void); // language or Return-to-Lair CVar changed void port_pauseMenuRebuild(void); // free + recreate + replay the main menu open void port_setPrintScale(float scale); +// Dialog font (AltDialogFont.cpp, SpritePatches.cpp) + +void port_dialogFontHd_rebuild(void); // rebuild the HD glyph textures for the current base +void port_refreshDialogFontGlyphCount(void); // re-read the reachable glyph count from the active font + // Framebuffer (FramebufferPatches.cpp) -void port_setViBlack(int active); -int port_isViBlack(void); void port_freezeReadback(int freeze); void port_requestReadback(void); int port_consumeReadbackRequest(void); @@ -34,8 +46,6 @@ void port_getPauseFramebufferSize(int* w, int* h); int port_pauseConsumeRecaptureRequest(void); int port_shouldCaptureTransition(void); -int32_t port_getAuxGpuFbId(void); -void port_readAuxFbToCpu(void* gfx_ptr); void port_patchPictureModel(void* model_bin, int32_t min_xy, int32_t max_xy, int32_t min_z, int32_t max_z, uint32_t from); int32_t port_getTransitionGpuFbId(void); @@ -64,12 +74,22 @@ int port_scalePlayerDamage(int damage); // Graphics (GraphicsPatches.cpp) -int port_getDrawDistanceLevel(void); +int port_getDrawDistanceSetting(void); // configured multiplier; safe during map load +int port_getDrawDistanceLevel(void); // render-time multiplier; clamped to 1x outside normal gameplay int port_shouldDisableLOD(void); float port_drawDistanceMul(void); void port_applyModelDrawDistanceCull(int* fadeFlag, float* cullMult, float* cullDist); int port_spriteSizeCulled(float depth, float size, float baseThreshold, int disableFlag); float port_hudOrthoShift(float refX); +void port_modelRenderResetTLUT(Gfx** gfx); + +// Vertex-animated models (AnimVertexPatches.cpp) + +// Recycles the per-draw vertex arena; once per tick, before the display list is built. +void port_animVtx_beginTick(void); +// Copies the just-posed vertices somewhere only this draw points at, and repoints +// segment 0x01 at the copy. +void port_modelRender_snapshotAnimVertices(Gfx** gfx, void* vertices, int32_t count); // Mirror (MirrorPatches.cpp) @@ -98,9 +118,105 @@ void port_unlockAudio(void); void port_audioIntMaskEnter(void); void port_audioIntMaskExit(void); +// Romhacks + +void* port_getRomhackResumeWarpFunc(void); +void romhack_RewriteActorSpawn(void* actorInfo, u32* flags); + // Attract-demo audio hold void port_beginDemoAudioHold(void); +void port_tickDemoAudioHold(void); +int port_audioHeld(void); +void port_noteMainLoopAlive(void); +int port_audioStallHold(void); +int32_t port_audioCatchupFrames(void); + +// One-shot cues when a teammate's file-progress flag arrives +void port_progressFlag_remoteCue(int32_t progressFlag); +void port_notedoor_remoteOpen(int32_t progressFlag); +void port_leveldoor_remoteOpen(int32_t progressFlag); + +void port_breakable_remoteBreak(int32_t progressFlag); + +void port_breakable_broadcastBreak(int32_t markerId, int32_t x, int32_t y, int32_t z); +void port_breakable_remoteBreakAt(int32_t markerId, int32_t x, int32_t y, int32_t z); + +void port_breakable_recordBreak(int32_t markerId, int32_t x, int32_t y, int32_t z); + +int32_t port_breakable_isBroken(int32_t map, int32_t markerId, int32_t x, int32_t y, int32_t z); + +int32_t port_cutsceneWarp_getReturnMap(void); + +void port_eggToll_onAdvance(int32_t map, int32_t secondaryId, int32_t stage); +int32_t port_eggToll_getStage(int32_t map, int32_t secondaryId); +void port_eggToll_remoteApply(int32_t map, int32_t secondaryId, int32_t stage); + +#define ANCHOR_PUZZLE_BGS_TANKTUP 1 +#define ANCHOR_PUZZLE_BGS_CROCTUS 2 +#define ANCHOR_PUZZLE_BGS_PINKEGG 3 +// CC clanker teeth: bits 0-2 = token tooth egg count, bits 3-5 = jiggy tooth. +#define ANCHOR_PUZZLE_CC_CLANKER_TEETH 4 +#define ANCHOR_PUZZLE_GV_JINXY_DOOR 5 +// MM Juju totem: bits 0-3, count of the 4 segments knocked off. +#define ANCHOR_PUZZLE_MM_JUJU 6 +// TTC Nipper: bits 0-2, count of hits taken (all 3 = dead, shell open). +#define ANCHOR_PUZZLE_TTC_NIPPER 7 +// TTC Blubber: bit 0 = first bullion delivered, bit 1 = second (jiggy spawned, Blubber leaves). +#define ANCHOR_PUZZLE_TTC_BLUBBER 8 +// TTC treasure hunt: bits 0-5, count of beak-busted X steps (bit 5 = treasure dug up). +#define ANCHOR_PUZZLE_TTC_XHUNT 9 +// FP xmas tree ice: 1 bit, set when the tree-top ice shatters. Recorded in the tree-interior +// map; the FP hub tree reads it via getForMap. +#define ANCHOR_PUZZLE_FP_TREE_ICE 10 +// FP bear cubs' presents: bit 0 = blue, bit 1 = green, bit 2 = red delivered. +#define ANCHOR_PUZZLE_FP_PRESENTS 11 +// FP snowman buttons: bit per button; all three spawns JIGGY_2D. +#define ANCHOR_PUZZLE_FP_SNOWBUTTONS 12 +#define ANCHOR_PUZZLE_FP_SLUSHES 13 +// RBB engine-room fans: 1 bit. Transient map flag 0 (enginefan.c reads it to slow the fans); persisted across reloads. +#define ANCHOR_PUZZLE_RBB_ENGINE_FANS 14 +// SM intro Bottles: bit 0 = the tutorial choice has been made. +#define ANCHOR_PUZZLE_SM_TUTORIAL 15 + +void port_remoteCarry_setCarried(uint32_t clientId, int32_t markerId, float offset[3], float yawOffset); +void port_remoteCarry_throw(uint32_t clientId, int32_t markerId, float start[3], float target[3]); +void port_remoteCarry_reset(void); +void port_anchorDummies_onActorsFreed(void); + +// Connected, in a real room, syncing world state. +int32_t port_anchor_isWorldSyncActive(void); + +// The puzzle mirrors below are home-scoped. +void port_puzzleStep_orBits(int32_t puzzleId, int32_t bits); +int32_t port_puzzleStep_get(int32_t puzzleId); +int32_t port_puzzleStep_getForMap(int32_t map, int32_t puzzleId); +int32_t port_puzzleStep_getForLevel(int32_t levelId, int32_t puzzleId); + +void port_puzzlePos_mark(int32_t puzzleId, int32_t x, int32_t y, int32_t z); +int32_t port_puzzlePos_isMarked(int32_t puzzleId, int32_t x, int32_t y, int32_t z); + +void port_fpTwinkly_release(void); + +int32_t port_mapFlag_wasSetRemotely(int32_t index); + +#define ANCHOR_COUNT_CCW_EYRIE_FED 0 +#define ANCHOR_COUNT_CCW_NABNUT_ACORNS 1 +void port_puzzleCount_add(int32_t counterId, int32_t delta); +int32_t port_puzzleCount_get(int32_t counterId); + +void port_hutSmash_record(int32_t x, int32_t y, int32_t z, int32_t loot); +int32_t port_hutSmash_get(int32_t x, int32_t y, int32_t z); +int32_t port_hutSmash_countForCurrentLevel(void); + +void port_jiggyCrane_broadcast(int32_t stage); +void port_jiggyCrane_remoteApply(int32_t stage); + +// Rate-limited: a marker reached cube_removeProp with a propPtr outside its cube. +void port_warnPropNotInCube(int32_t index, int32_t propCnt); + +// Rate-limited: a cube's node-prop split index passed 31, where the old :5 field wrapped. +void port_warnNodePropSplit(int32_t splitIndex, int32_t nodeCnt); #ifdef __cplusplus } diff --git a/src/port/Patches/PerfPatches.cpp b/src/port/Patches/PerfPatches.cpp new file mode 100644 index 000000000..037a48567 --- /dev/null +++ b/src/port/Patches/PerfPatches.cpp @@ -0,0 +1,252 @@ +#include +#include +#include + +#include + +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Patches/Patches.h" +#include "port/ShipInit.hpp" + +extern "C" { +#include +#include "functions.h" +#include "core2/lighting.h" + +extern s32 D_80383450[CUBE_SORT_SCRATCH_SIZE]; + +// core1 helpers not exposed through functions.h. +extern void func_80256E24(f32 dst[3], f32 theta, f32 phi, f32 x, f32 y, f32 z); +extern void ml_vec3f_normalize(f32 vec[3]); +extern void viewport_getPosition_vec3f(f32 dst[3]); +extern void viewport_getRotation_vec3f(f32 dst[3]); +} + +static const f32 kFrustumZX = 45.168514251708984f; // must match viewport.c +static const f32 kFrustumZY = 34.20201110839844f; +static constexpr float kDrawDistCullPadDeg = 25.0f; +static f32 sPadFrustumX = 89.21774f; +static f32 sPadFrustumY = 93.9692611694336f; +static f32 sPadPlanes[4][4]; +static bool sPadPlanesDirty = true; + +// TODO: Find better place for these two warn functions +// Capped so a bad frame can't flood the log; one print is enough to investigate. +extern "C" void port_warnPropNotInCube(int32_t index, int32_t propCnt) { + static int32_t sReported = 0; + if (sReported < 20) { + sReported++; + SPDLOG_WARN("cube_removeProp: prop not in cube (index {}, cnt {})", index, propCnt); + } +} + +// Fires only for a cube the old :5 unk0_4 would have silently corrupted, so if this +// never prints, no shipped map reaches the limit and the widening is forward-looking. +extern "C" void port_warnNodePropSplit(int32_t splitIndex, int32_t nodeCnt) { + static int32_t sReported = 0; + if (sReported < 20) { + sReported++; + SPDLOG_WARN("cube node-prop split {} of {} exceeds the old 31 limit", splitIndex, nodeCnt); + } +} + +// __cube_sort re-sorts every visible cube's props each tick, but only the camera +// moves, so the order rarely changes. A stable insertion sort skims an already +// sorted array in one pass and produces the same ordering as the vanilla sort. +static void RegisterCubeSort_Init() { + COND_VB_SHOULD(VB_CUBE_PROP_SORT, EVENT_PRIORITY_NORMAL, true, { + Cube* cube = va_arg(args, Cube*); + s32 n = cube->prop2Cnt; + for (s32 i = 1; i < n; i++) { + if (D_80383450[i] <= D_80383450[i - 1]) { + continue; + } + s32 key = D_80383450[i]; + Prop tmp; + std::memcpy(&tmp, &cube->prop2Ptr[i], sizeof(Prop)); + s32 j = i - 1; + while (j >= 0 && D_80383450[j] < key) { + D_80383450[j + 1] = D_80383450[j]; + std::memcpy(&cube->prop2Ptr[j + 1], &cube->prop2Ptr[j], sizeof(Prop)); + j--; + } + D_80383450[j + 1] = key; + std::memcpy(&cube->prop2Ptr[j + 1], &tmp, sizeof(Prop)); + } + *should = false; + }); +} + +// Same vertex recolor loop as gclights_recolor_vertices, but out-of-range lights +// are rejected with squared distances so only vertices inside a fade band pay a sqrt. +static void RegisterGcLights_Init() { + COND_VB_SHOULD(VB_GCLIGHTS_RECOLOR, EVENT_PRIORITY_NORMAL, true, { + Vtx* vtx = va_arg(args, Vtx*); + Vtx* vtxEnd = va_arg(args, Vtx*); + Vtx* refVtx = va_arg(args, Vtx*); + Lighting** lightsBegin = va_arg(args, Lighting**); + Lighting** lightsEnd = va_arg(args, Lighting**); + + // Active-light list caps at 16 entries (NUM_LIGHTING_ELEM). + f32 minSq[16]; + f32 maxSq[16]; + s32 nLights = (s32)(lightsEnd - lightsBegin); + for (s32 li = 0; li < nLights; li++) { + minSq[li] = lightsBegin[li]->fade_radius_min * lightsBegin[li]->fade_radius_min; + maxSq[li] = lightsBegin[li]->fade_radius_max * lightsBegin[li]->fade_radius_max; + } + + for (; vtx < vtxEnd; vtx++, refVtx++) { + f32 mod[3]; + mod[0] = mod[1] = mod[2] = 0.0f; + for (s32 li = 0; li < nLights; li++) { + const Lighting* light = lightsBegin[li]; + f32 dx = light->positionCopy[0] - (f32)refVtx->v.ob[0]; + f32 dy = light->positionCopy[1] - (f32)refVtx->v.ob[1]; + f32 dz = light->positionCopy[2] - (f32)refVtx->v.ob[2]; + f32 distSq = dx * dx + dy * dy + dz * dz; + if (maxSq[li] <= distSq) { + continue; + } + if (distSq <= minSq[li]) { + mod[0] += light->red; + mod[1] += light->green; + mod[2] += light->blue; + } else { + f32 dist = sqrtf(distSq); + f32 fade = + 1.0f - ((dist - light->fade_radius_min) / (light->fade_radius_max - light->fade_radius_min)); + mod[0] += fade * light->red; + mod[1] += fade * light->green; + mod[2] += fade * light->blue; + } + } + vtx->v.cn[0] = (s8)((refVtx->v.cn[0] * mod[0]) / 256.0) & 0xFF; + vtx->v.cn[1] = (s8)((refVtx->v.cn[1] * mod[1]) / 256.0) & 0xFF; + vtx->v.cn[2] = (s8)((refVtx->v.cn[2] * mod[2]) / 256.0) & 0xFF; + } + *should = false; + }); +} + +// Same rotations as mlMtx_rotate_yaw_deg/mlMtx_rotate_pitch_deg, but every +// snowflake shares one camera rotation, so cache the sin/cos instead of +// recomputing four of them per flake. +static void ApplySnowCameraRotation(const f32 camRot[3]) { + constexpr double kBadDtor = 3.141592654 / 180.0; + static f32 sYawDeg; + static f32 sPitchDeg; + static f32 sSinYaw, sCosYaw; + static f32 sSinPitch, sCosPitch; + static bool sHaveTrig = false; + + f32 pitchDeg = camRot[0]; + f32 yawDeg = camRot[1]; + if (!sHaveTrig || yawDeg != sYawDeg || pitchDeg != sPitchDeg) { + f32 yawRad = (f32)(yawDeg * kBadDtor); + f32 pitchRad = (f32)(pitchDeg * kBadDtor); + sSinYaw = sinf(yawRad); + sCosYaw = cosf(yawRad); + sSinPitch = sinf(pitchRad); + sCosPitch = cosf(pitchRad); + sYawDeg = yawDeg; + sPitchDeg = pitchDeg; + sHaveTrig = true; + } + + MtxF* m = mlMtx_get_stack_pointer(); + if (yawDeg != 0.0f) { + for (s32 i = 0; i < 3; i++) { + f32 r0 = m->mf[0][i]; + f32 r2 = m->mf[2][i]; + m->mf[0][i] = r0 * sCosYaw - r2 * sSinYaw; + m->mf[2][i] = r0 * sSinYaw + r2 * sCosYaw; + } + } + if (pitchDeg != 0.0f) { + for (s32 i = 0; i < 3; i++) { + f32 r1 = m->mf[1][i]; + f32 r2 = m->mf[2][i]; + m->mf[1][i] = r1 * sCosPitch + r2 * sSinPitch; + m->mf[2][i] = r1 * -sSinPitch + r2 * sCosPitch; + } + } +} + +static void RegisterSnowTrig_Init() { + COND_VB_SHOULD(VB_SNOW_CAMERA_ROTATION, EVENT_PRIORITY_NORMAL, true, { + ApplySnowCameraRotation(va_arg(args, f32*)); + *should = false; + }); +} + +static void RebuildPaddedPlanes() { + f32 rot[3]; + f32 pos[3]; + viewport_getRotation_vec3f(rot); + viewport_getPosition_vec3f(pos); + + // Components are cotangent-form (component/Z = cot(half angle)), so + // widening the frustum means shrinking the lateral component. + const f32 kDegToRad = 3.14159265f / 180.0f; + const f32 kMaxHalfAngle = 88.0f * kDegToRad; + f32 halfX = atanf(kFrustumZX / sPadFrustumX) + kDrawDistCullPadDeg * kDegToRad; + f32 halfY = atanf(kFrustumZY / sPadFrustumY) + kDrawDistCullPadDeg * kDegToRad; + halfX = std::min(halfX, kMaxHalfAngle); + halfY = std::min(halfY, kMaxHalfAngle); + f32 px = kFrustumZX / tanf(halfX); + f32 py = kFrustumZY / tanf(halfY); + + func_80256E24(sPadPlanes[0], rot[0], rot[1], -px, 0.0f, kFrustumZX); + func_80256E24(sPadPlanes[1], rot[0], rot[1], px, 0.0f, kFrustumZX); + func_80256E24(sPadPlanes[2], rot[0], rot[1], 0.0f, py, kFrustumZY); + func_80256E24(sPadPlanes[3], rot[0], rot[1], 0.0f, -py, kFrustumZY); + for (int i = 0; i < 4; i++) { + ml_vec3f_normalize(sPadPlanes[i]); + sPadPlanes[i][3] = -(pos[0] * sPadPlanes[i][0] + pos[1] * sPadPlanes[i][1] + pos[2] * sPadPlanes[i][2]); + } + sPadPlanesDirty = false; +} + +// Culled when all 8 corners are outside one plane. +static bool PaddedBoxCulled(const f32 boxMin[3], const f32 boxMax[3]) { + for (int p = 0; p < 4; p++) { + bool allOutside = true; + for (int c = 0; c < 8 && allOutside; c++) { + f32 x = (c & 1) ? boxMax[0] : boxMin[0]; + f32 y = (c & 2) ? boxMax[1] : boxMin[1]; + f32 z = (c & 4) ? boxMax[2] : boxMin[2]; + if (sPadPlanes[p][0] * x + sPadPlanes[p][1] * y + sPadPlanes[p][2] * z + sPadPlanes[p][3] < 0.0f) { + allOutside = false; + } + } + if (allOutside) { + return true; + } + } + return false; +} + +static void RegisterDrawDistCull_Init() { + COND_HOOK(ViewportFrustumUpdate, EVENT_PRIORITY_LOW, true, [](IEvent* event) { + auto* ev = (ViewportFrustumUpdate*)event; + sPadFrustumX = *ev->frustumX; + sPadFrustumY = *ev->frustumY; + sPadPlanesDirty = true; + }); + COND_VB_SHOULD(VB_DRAWDIST_BOX_CULL, EVENT_PRIORITY_NORMAL, true, { + f32* boxMin = va_arg(args, f32*); + f32* boxMax = va_arg(args, f32*); + if (sPadPlanesDirty) { + RebuildPaddedPlanes(); + } + if (PaddedBoxCulled(boxMin, boxMax)) { + *should = false; + } + }); +} + +static RegisterShipInitFunc sCubeSortInit(RegisterCubeSort_Init); +static RegisterShipInitFunc sGcLightsInit(RegisterGcLights_Init); +static RegisterShipInitFunc sSnowTrigInit(RegisterSnowTrig_Init); +static RegisterShipInitFunc sDrawDistCullInit(RegisterDrawDistCull_Init); \ No newline at end of file diff --git a/src/port/Patches/SpritePatches.cpp b/src/port/Patches/SpritePatches.cpp index 496e231d9..5f225d5d2 100644 --- a/src/port/Patches/SpritePatches.cpp +++ b/src/port/Patches/SpritePatches.cpp @@ -4,6 +4,10 @@ #include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Patches/Patches.h" +#include "port/ShipInit.hpp" + extern "C" { #include "structs.h" @@ -19,13 +23,12 @@ void assetcache_release(void* asset); enum asset_e print_getCurrentMapBoldFontTexture(void); char* ResourceMgr_ReloadByAssetId(uint32_t assetId); -int ResourceMgr_IsJapanese(void); enum level_e level_get(void); s32 gcpausemenu_levelToMenuPage(enum level_e level); extern s32 gFramebufferWidth; -extern BKSprite* D_80380AB8[]; // font alphamask sprites ([0] = dialog font) -extern s32 print_sDialogFontGlyphCount; // reachable glyph count: byte range 0x21 .. 0x21+count-1 +extern BKSprite* print_sFontSpriteAssets[]; // font alphamask sprites ([0] = dialog font) +extern s32 print_sDialogFontGlyphCount; // reachable glyph count: byte range 0x21 .. 0x21+count-1 #define SPRITE_DISPLAY_CACHE_SIZE 256 @@ -45,8 +48,8 @@ void port_spriteDisplayCache_clear(void) { // sets this once from the base font, but a language pack can swap in an extended dialog font // (more glyphs than the base 62) at runtime. void port_refreshDialogFontGlyphCount(void) { - if (D_80380AB8[0] != NULL) { - print_sDialogFontGlyphCount = sprite_getFramePtr(D_80380AB8[0], 0)->chunkCnt; + if (print_sFontSpriteAssets[0] != NULL) { + print_sDialogFontGlyphCount = sprite_getFramePtr(print_sFontSpriteAssets[0], 0)->chunkCnt; } } @@ -132,9 +135,11 @@ BKSprite* port_loadFilledBanner(s32 bannerAssetId, s32 fillId) { u8* maskPx = px + (x + y * cw) * 4; const s32 intensity = maskPx[2]; // mask byte[2] = intensity const u8 alpha = maskPx[3]; // mask byte[3] = alpha - r5 *= (intensity / 0x1F); - g5 *= (intensity / 0x1F); - b5 *= (intensity / 0x1F); + // 5-bit channel * 8-bit intensity / 31 expands to 8-bit exactly (31 * 255 / 31 == 255). + // Dividing first truncates to 0..8, blacking out any intensity below 0x1F. + r5 = (r5 * intensity) / 0x1F; + g5 = (g5 * intensity) / 0x1F; + b5 = (b5 * intensity) / 0x1F; maskPx[0] = (u8)r5; maskPx[1] = (u8)g5; maskPx[2] = (u8)b5; @@ -219,3 +224,9 @@ void port_pauseBannerFree(void) { } } // extern "C" + +static void RegisterSpriteRestoreAlphaCompare_Init() { + COND_VB_SHOULD(VB_SPRITE_RESTORE_ALPHA_COMPARE, EVENT_PRIORITY_NORMAL, true, { *should = true; }); +} + +static RegisterShipInitFunc sSpriteRestoreAlphaCompareInit(RegisterSpriteRestoreAlphaCompare_Init); diff --git a/src/port/Patches/TransitionPatches.cpp b/src/port/Patches/TransitionPatches.cpp index 7b4b82afe..041e9e44e 100644 --- a/src/port/Patches/TransitionPatches.cpp +++ b/src/port/Patches/TransitionPatches.cpp @@ -8,9 +8,7 @@ #include "port/ShipInit.hpp" #include "port/Patches/Patches.h" -extern "C" { #include "enums.h" -} // Falling-pieces transition uids. #define TRANSITION_FALLING_PIECES_IN 0x10 @@ -21,20 +19,6 @@ static int32_t sTransitionModelId = 0; static int32_t sTransitionUid = 0; static int32_t sTransitionSubstate = 0; -// Emulate N64's osViBlack on PC. On N64, osViBlack(1) blanked the TV output but -// the RDP still rendered to framebuffers. On PC we render normally (so the capture -// sees the world), then Engine.cpp clears the backbuffer to black before present -// while this flag is set. -static bool s_viBlack = false; - -extern "C" void port_setViBlack(int active) { - s_viBlack = (active != 0); -} - -extern "C" int port_isViBlack(void) { - return s_viBlack ? 1 : 0; -} - extern "C" int port_shouldCaptureTransition(void) { if (sTransitionModelId != ASSET_467_MODEL_TRANSITION_FALLING_JIGGIES) { return 0; @@ -54,7 +38,6 @@ void RegisterTransitionPatches_Init() { sTransitionModelId = ev->modelId; sTransitionUid = ev->uid; sTransitionSubstate = ev->substate; - port_setViBlack(ev->uid == TRANSITION_FALLING_PIECES_IN && ev->substate <= 4 ? 1 : 0); }); // Widescreen transition scaling. For the falling jiggy pieces, X-scale the diff --git a/src/port/Rando/CheckTracker/CheckTracker.cpp b/src/port/Rando/CheckTracker/CheckTracker.cpp index 1e231cc64..e650188ca 100644 --- a/src/port/Rando/CheckTracker/CheckTracker.cpp +++ b/src/port/Rando/CheckTracker/CheckTracker.cpp @@ -103,7 +103,7 @@ std::string GetTotalCheckCount() { uint32_t collected = 0; uint32_t totalShuffled = 0; for (auto& entry : Rando::Logic::shuffledPool) { - if (entry.obtained || entry.skipped) { + if (entry.eligible || entry.skipped) { collected++; } if (entry.isShuffled) { @@ -131,7 +131,7 @@ void UpdateWorldCheckCount(level_e world) { if (Rando::StaticData::Checks[entry.randoCheckId].worldId != world) { continue; } - if (entry.obtained || entry.skipped) { + if (entry.eligible || entry.skipped) { worldCollected++; } if (entry.isShuffled) { @@ -219,7 +219,7 @@ void DrawCheckTrackerList() { continue; } - if (CVAR_HIDE_COLLECTED && entry.obtained) { + if (CVAR_HIDE_COLLECTED && entry.eligible) { continue; } @@ -227,16 +227,16 @@ void DrawCheckTrackerList() { continue; } - ImVec4 checkTextColor = entry.obtained ? VecFromRGBA8(CVAR_COLLECTED_COLOR) + ImVec4 checkTextColor = entry.eligible ? VecFromRGBA8(CVAR_COLLECTED_COLOR) : UIWidgets::ColorValues.at(UIWidgets::Colors::White); - ImVec4 itemTextColor = entry.obtained ? VecFromRGBA8(CVAR_ITEM_COLOR) + ImVec4 itemTextColor = entry.eligible ? VecFromRGBA8(CVAR_ITEM_COLOR) : UIWidgets::ColorValues.at(UIWidgets::Colors::Indigo); if (entry.skipped) { checkTextColor = itemTextColor = VecFromRGBA8(CVAR_SKIPPED_COLOR); } - if (!entry.obtained && CVAR_SHOW_LOGIC) { + if (!entry.eligible && CVAR_SHOW_LOGIC) { checkTextColor = Rando::Logic::CanAccessCheck(entry.randoCheckId) ? UIWidgets::ColorValues.at(UIWidgets::Colors::White) : VecFromRGBA8(CVAR_LOGIC_COLOR); @@ -244,7 +244,7 @@ void DrawCheckTrackerList() { ImGui::BeginGroup(); ImGui::TextColored(checkTextColor, checkNames.at(entry.randoCheckId).c_str()); - if (entry.obtained) { + if (entry.eligible) { ImGui::SameLine(); RandoItemId randoItemId = Rando::Logic::GetShuffledObject(entry.randoCheckId).randoItemId; const std::string& randoItemName = diff --git a/src/port/Rando/CustomCollectible/CustomCollectible.cpp b/src/port/Rando/CustomCollectible/CustomCollectible.cpp new file mode 100644 index 000000000..5178333cc --- /dev/null +++ b/src/port/Rando/CustomCollectible/CustomCollectible.cpp @@ -0,0 +1,243 @@ +#include "CustomCollectible.h" +#include "CustomCollectibleDrawCustom.h" +#include + +#include +#include "port/ShipInit.hpp" +#include + +extern "C" { +#include "functions.h" +#include "actor.h" +void __chJinjo_802CDC9C(Actor* thisx, s16 arg1); +Actor* func_802D94B4(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); +Actor* chSnsEgg_draw(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); +} + +static std::queue propQueue; + +std::unordered_map customCollectibleDrawInfo = { + { ACTOR_52_BLUE_EGG, { ASSET_36D_SPRITE_BLUE_EGG, CCT_GENERIC_SPRITE } }, + { ACTOR_47_EMPTY_HONEYCOMB, { ASSET_361_MODEL_EMPTY_HONEYCOMB, CCT_GENERIC_MODEL } }, + { ACTOR_49_EXTRA_LIFE, { ASSET_36E_MODEL_EXTRA_LIFE, CCT_GENERIC_SPRITE } }, + { ACTOR_50_HONEYCOMB, { ASSET_363_MODEL_HONEYCOMB, CCT_GENERIC_MODEL } }, + { ACTOR_46_JIGGY, { ASSET_35F_MODEL_JIGGY, CCT_GENERIC_MODEL } }, + { ACTOR_60_JINJO_BLUE, { ASSET_3C0_MODEL_JINJO_BLUE, CCT_JINJO } }, + { ACTOR_62_JINJO_GREEN, { ASSET_3C2_MODEL_JINJO_GREEN, CCT_JINJO } }, + { ACTOR_5F_JINJO_ORANGE, { ASSET_3BC_MODEL_JINJO_ORANGE, CCT_JINJO } }, + { ACTOR_61_JINJO_PINK, { ASSET_3C1_MODEL_JINJO_PINK, CCT_JINJO } }, + { ACTOR_5E_JINJO_YELLOW, { ASSET_3BB_MODEL_JINJO_YELLOW, CCT_JINJO } }, + { ACTOR_12C_MOLEHILL, { ASSET_387_MODEL_BOTTLES, CCT_MOLEHILL } }, + { ACTOR_2D_MUMBO_TOKEN, { ASSET_41A_SPRITE_MUMBO_TOKEN, CCT_GENERIC_SPRITE } }, + { ACTOR_51_MUSIC_NOTE, { ASSET_6D6_SPRITE_MUSIC_NOTE, CCT_GENERIC_SPRITE } }, + { ACTOR_25E_SNS_EGG, { ASSET_50D_MODEL_SNS_EGG, CCT_VANILLA_SNS_EGG } }, + { ACTOR_25D_ICE_KEY, { ASSET_50C_MODEL_ICE_KEY, CCT_GENERIC_MODEL } }, + { ACTOR_3CD_CUSTOM_COLLECTIBLE, { ASSET_35F_MODEL_JIGGY, CCT_CUSTOM_MODEL } }, +}; + +ActorAnimationInfo moleAnimation[] = { + { ASSET_13B_ANIM_BOTTLES_IDLE, 7.0f }, +}; + +ActorAnimationInfo chJinjoAnimation[] = { + { ASSET_2F_ANIM_JINJO_HELP, 1.5f }, +}; + +ActorInfo customActorInfo = { MARKER_300_CUSTOM_COLLECTIBLE, + ACTOR_3CD_CUSTOM_COLLECTIBLE, + ASSET_0_NONE, + 0, + NULL, + CustomCollectible_Update, + NULL, + NULL, + 0, + 0, + 0.8f, + 0 }; + +void CustomCollectible_Update(Actor* actor) { + ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&actor->local; + + if (!actor->initialized) { + actor->initialized = true; + actor->marker->collidable = true; + + actor->scale = CustomCollectible::GetScale(customLocal->itemType); + } + + if (customLocal->itemType == RITYPE_MOLEHILL || customLocal->itemType == RITYPE_JINJO) { + CustomCollectible::FacePlayer(actor); + } else { + actor->yaw += 5.0f; + } + + // Sparkles + if (customCollectibleDrawInfo[customLocal->actorId].drawType != CCT_GENERIC_SPRITE) { + for (int i = 0; i < 4; i++) { + if (randf() < 0.03) { + commonParticle_add(actor->marker, i + 5, func_80329904); + commonParticle_new((common_particle_e)8, actor->marker->unk14_21); + } + } + } + + // Allows shadows + if (customLocal->itemType == RITYPE_AP_ITEM) { + actor->unk124_6 = 1; + actor->marker->unk14_21 = 1; + } +} + +f32 CustomCollectible::GetScale(RandoItemType itemType) { + switch (itemType) { + case RITYPE_MUSIC_NOTE: + case RITYPE_SNS_EGG: + return 0.42857143f; + case RITYPE_EMPTY_HONEYCOMB: + case RITYPE_MOLEHILL: + return 0.8f; + default: + return 1.0f; + } +} + +void CustomCollectible::FacePlayer(Actor* actor) { + // Copied from source code inside jinjo.c + f32 sp7C[3]; + f32 sp6C; + f32* sp30 = actor->position; + func_8028E964(sp7C); + func_80257F18(sp30, sp7C, &sp6C); + s16 sp64 = (actor->yaw * 182.04444); + s16 sp66 = (s32)(sp6C * 182.04444); + sp66 = sp64 - sp66; + s32 sp60 = func_8028AED4(sp30, 55.0f); + __chJinjo_802CDC9C(actor, sp66); +} + +Actor* CustomCollectible::AttachCustomVariables(RandoCheckId randoCheckId, Actor* customCollectible) { + ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&customCollectible->local; + + RandoItemId randoItemId = RANDO_SAVE_CHECKS[randoCheckId].randoItemId; + + customLocal->randoCheckId = randoCheckId; + customLocal->randoItemId = randoItemId; + customLocal->actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; + customLocal->itemType = Rando::StaticData::Items[randoItemId].randoItemType; + + return customCollectible; +} + +Actor* CustomCollectible::Spawn(int32_t position[3], RandoCheckId randoCheckId) { + int32_t spawnPosition[3] = { position[0], position[1], position[2] }; + + int32_t flags = ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21; + + RandoItemId randoItemId = RANDO_SAVE_CHECKS[randoCheckId].randoItemId; + RandoItemType itemType = Rando::StaticData::Items[randoItemId].randoItemType; + + // actor_new stores the ActorInfo* permanently, so it must outlive Spawn() + static std::unordered_map sActorInfoCache; + ActorInfo& collectibleInfo = sActorInfoCache[randoItemId]; + collectibleInfo = CustomCollectible::GetActorAndDrawInfo(randoItemId); + + // Spawn actor + Actor* customCollectible = actor_new(spawnPosition, 0, &collectibleInfo, flags); + if (itemType == RITYPE_SNS_EGG) { + customCollectible->actorTypeSpecificField = CustomCollectible::GetSNSEggColor(randoItemId); + } + customCollectible->marker->collisionFunc = CustomCollectible::OnCollect; + customCollectible = CustomCollectible::AttachCustomVariables(randoCheckId, customCollectible); + + return customCollectible; +} + +uint32_t CustomCollectible::GetSNSEggColor(RandoItemId randoItemId) { + switch (randoItemId) { + case RI_STOP_N_SWOP_EGG_BLUE: + return (uint32_t)SNS_ITEM_EGG_BLUE; + case RI_STOP_N_SWOP_EGG_CYAN: + return (uint32_t)SNS_ITEM_EGG_CYAN; + case RI_STOP_N_SWOP_EGG_GREEN: + return (uint32_t)SNS_ITEM_EGG_GREEN; + case RI_STOP_N_SWOP_EGG_PINK: + return (uint32_t)SNS_ITEM_EGG_PINK; + case RI_STOP_N_SWOP_EGG_RED: + return (uint32_t)SNS_ITEM_EGG_RED; + case RI_STOP_N_SWOP_EGG_YELLOW: + return (uint32_t)SNS_ITEM_EGG_YELLOW; + default: + return (uint32_t)SNS_ITEM_EGG_CYAN; + } +} + +ActorInfo CustomCollectible::GetActorAndDrawInfo(RandoItemId randoItemId) { + ActorInfo collectibleInfo = customActorInfo; + + actor_e actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; + auto drawInfo = customCollectibleDrawInfo[actorId]; + + collectibleInfo.modelId = drawInfo.drawModel; + + switch (drawInfo.drawType) { + case CCT_GENERIC_MODEL: + collectibleInfo.draw_func = actor_draw; + break; + case CCT_GENERIC_SPRITE: + collectibleInfo.draw_func = fxTouchSparkle_draw; + collectibleInfo.shadow_scale = 0.0f; + break; + case CCT_JINJO: + collectibleInfo.draw_func = actor_draw; + collectibleInfo.animations = chJinjoAnimation; + break; + case CCT_MOLEHILL: + collectibleInfo.draw_func = func_802D94B4; + collectibleInfo.animations = moleAnimation; + break; + case CCT_VANILLA_SNS_EGG: + collectibleInfo.draw_func = chSnsEgg_draw; + break; + case CCT_CUSTOM_MODEL: + collectibleInfo.draw_func = CustomCollectible_DrawCustomModel; + break; + default: + break; + } + return collectibleInfo; +} + +void CustomCollectible::OnCollect(struct actorMarker_s* self, struct actorMarker_s* other) { + Actor* actor = marker_getActor(self); + ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&actor->local; + fxSparkle_honeycomb(&self->propPtr->x); + ItemQueue::AddCheck(customLocal->randoCheckId); + marker_despawn(self); +} + +// When regular props are spawned in BK, the game isn't fully set up yet to spawn +// actors. So we delay prop spawns until the game's ready to spawn actors. +void CustomCollectible::QueueProp(int32_t position[3], RandoCheckId randoCheckId) { + QueuedProp queuedProp; + queuedProp.position[0] = position[0]; + queuedProp.position[1] = position[1]; + queuedProp.position[2] = position[2]; + queuedProp.randoCheckId = randoCheckId; + propQueue.push(queuedProp); +} + +void CustomCollectible::ProcessPropQueue() { + while (propQueue.size() > 0) { + QueuedProp prop = propQueue.front(); + Actor* actor = CustomCollectible::Spawn(prop.position, prop.randoCheckId); + propQueue.pop(); + } +} + +void RegisterCustomCollectible() { + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO, + [](IEvent* event) { CustomCollectible::ProcessPropQueue(); }); +} + +static RegisterShipInitFunc initFunc(RegisterCustomCollectible, { "IS_RANDO" }); diff --git a/src/port/Rando/CustomCollectible/CustomCollectible.h b/src/port/Rando/CustomCollectible/CustomCollectible.h new file mode 100644 index 000000000..8b2f06bdb --- /dev/null +++ b/src/port/Rando/CustomCollectible/CustomCollectible.h @@ -0,0 +1,46 @@ +#pragma once +#include "port/Rando/ItemQueue.h" +#include "prop.h" + +typedef struct { + RandoCheckId randoCheckId; + RandoItemId randoItemId; + actor_e actorId; + RandoItemType itemType; +} ActorLocal_CustomCollectible; + +enum CustomCollectibleDrawTypes { + CCT_GENERIC_MODEL, + CCT_GENERIC_SPRITE, + CCT_JINJO, + CCT_MOLEHILL, + CCT_VANILLA_SNS_EGG, + CCT_CUSTOM_MODEL, +}; + +typedef struct { + asset_e drawModel; + CustomCollectibleDrawTypes drawType; +} CustomCollectibleDrawInfo; + +typedef struct { + s32 position[3]; + RandoCheckId randoCheckId; +} QueuedProp; + +void CustomCollectible_Update(Actor* actor); + +class CustomCollectible { +private: + static Actor* AttachCustomVariables(RandoCheckId randoItemId, Actor* customCollectible); + static void OnCollect(struct actorMarker_s* self, struct actorMarker_s* other); + static ActorInfo GetActorAndDrawInfo(RandoItemId randoItemId); + static uint32_t GetSNSEggColor(RandoItemId randoItemId); + +public: + static Actor* Spawn(int32_t position[3], RandoCheckId randoCheckId); + static f32 GetScale(RandoItemType itemType); + static void FacePlayer(Actor* actor); + static void QueueProp(int32_t position[3], RandoCheckId randoCheckId); + static void ProcessPropQueue(); +}; diff --git a/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp b/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp new file mode 100644 index 000000000..80ae1ed27 --- /dev/null +++ b/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp @@ -0,0 +1,108 @@ +// Custom item model rendering. +// +// The models live in lighthouse.o2r as XML libultraship resources under +// objects/object_X_item. +// They are untextured prim-color geometry, so they draw with a single matrix +// push and no material setup beyond what the display lists carry. + +// Include order matters here. +// 1. ResourceHelpers.h (via ship/Context.h -> spdlog) parses the Windows headers, +// which must happen before any decomp header: Events.h drags in prop.h -> +// structs.h -> bool.h, whose function-like BOOL(x) macro corrupts the +// `typedef BOOL (CALLBACK* ...)` declarations in the Windows SDK. +// 2. bridge.h/Events.h bring in the events bridge/json templates, which must be +// seen with C++ linkage before functions.h re-includes them inside the +// extern "C" block below. +#include +#include "port/ResourceHelpers.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Interpolation/FrameInterpolation.h" + +#include "CustomCollectibleDrawCustom.h" +#include "CustomCollectible.h" + +extern "C" { +#include +#include "macros.h" +#include "prop.h" +#include "functions.h" +#include "variables.h" +#include "core1/viewport.h" +#include "core1/mlmtx.h" +} + +static const char* sCustomModelPaths[] = { + "objects/object_archipelago_item/gArchipelagoItemDL", + "objects/object_archipelago_item/gArchipelagoJunkDL", + "objects/object_archipelago_item/gArchipelagoProgressiveDL", +}; + +// The models are authored at OoT world scale, which is roughly 10x too large +// for BK. Baked into every draw so callers treat scale 1.0 as "natural size". +static const f32 sCustomModelBaseScale = 0.04f; + +// BK never uploads RSP lights (its models bake shading into vertex colors), but +// these materials enable G_LIGHTING, so without our own light setup the shade +// input is garbage and the model renders black. Neutral white key light from +// the upper-front-right plus a mid ambient. +static Lights1 sCustomModelLights = gdSPDefLights1(110, 110, 110, 255, 255, 255, 40, 40, 40); + +// Pin the resources so the cached Gfx pointers stay valid across frames. +static std::shared_ptr sModelResources[ARRAY_COUNT(sCustomModelPaths)]; +static Gfx* sModelDLs[ARRAY_COUNT(sCustomModelPaths)]; + +static Gfx* CustomCollectible_GetDL(CustomItemModel model) { + if (model < 0 || model >= (s32)ARRAY_COUNT(sCustomModelPaths)) { + return nullptr; + } + if (sModelDLs[model] == nullptr) { + sModelResources[model] = GetResourceByName(sCustomModelPaths[model]); + if (sModelResources[model] == nullptr) { + return nullptr; + } + sModelDLs[model] = ResourceMgr_LoadGfxByName(sCustomModelPaths[model]); + } + return sModelDLs[model]; +} + +Actor* CustomCollectible_DrawCustomModel(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { + Actor* actor = marker_getActor(marker); + ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&actor->local; + CustomItemModel model; + + switch (customLocal->randoItemId) { + case RI_AP_ITEM_PROGRESSION: + model = ARCHIPELAGO_MODEL_PROGRESSIVE; + break; + default: + break; + } + + Gfx* dl = CustomCollectible_GetDL(model); + if (dl == nullptr) { + return actor; + } + + f32 camera_position[3]; + viewport_getPosition_vec3f(camera_position); + + // The mlMtx calls below are recorded for frame interpolation; the scope key + // pairs this draw's matrix across ticks. Keyed by model, so two instances + // of the same model drawn in the same frame would need instance-keyed + // scopes instead. + FrameInterpolation_RecordOpenChild("custom_item", (uintptr_t)model); + f32 rotation[3] = { actor->pitch, actor->yaw, actor->roll }; + f32 position[3] = { actor->position[0], actor->position[1] + 50, actor->position[2] }; + // The modelview translation is camera-relative, matching modelRender_draw. + mlMtxIdent(); + func_80252AF0(camera_position, position, rotation, actor->scale * sCustomModelBaseScale, NULL); + mlMtxApply(*mtx); + gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSetLights1((*gfx)++, sCustomModelLights); + gSPDisplayList((*gfx)++, dl); + gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW); + + FrameInterpolation_RecordCloseChild(); + + return actor; +} diff --git a/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h b/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h new file mode 100644 index 000000000..ce87b41bf --- /dev/null +++ b/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h @@ -0,0 +1,36 @@ +#ifndef PORT_ARCHIPELAGO_ITEM_H +#define PORT_ARCHIPELAGO_ITEM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Forward declarations (tag structs from prop.h) so this header stays free of +// the decomp includes including prop.h here would drag in bool.h, whose +// function-like BOOL() macro corrupts the Windows SDK headers in C++ TUs. +struct actorMarker_s; +struct actor_s; + +typedef enum CustomItemModel { + ARCHIPELAGO_MODEL_NONE = -1, // resolver sentinel: keep the vanilla model + ARCHIPELAGO_MODEL_ITEM, + ARCHIPELAGO_MODEL_JUNK, + ARCHIPELAGO_MODEL_PROGRESSIVE, +} CustomItemModel; + +// Draws an Archipelago item model at a world position. Must be called from a +// draw context that owns the display list and matrix pools (an actor draw +// callback, a world/player draw event hook, cutscene draw code, etc.). +// rotation is pitch/yaw/roll in degrees and may be NULL; scale is a relative +// multiplier where 1.0 = natural in-world size (the OoT-scale source models are +// shrunk to BK proportions internally). +Actor* CustomCollectible_DrawCustomModel(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/port/Rando/CustomObject/CustomObject.cpp b/src/port/Rando/CustomObject/CustomObject.cpp index aa30f92d3..beeaa989a 100644 --- a/src/port/Rando/CustomObject/CustomObject.cpp +++ b/src/port/Rando/CustomObject/CustomObject.cpp @@ -2,6 +2,7 @@ #include #include "port/UI/cvar_prefixes.h" #include "port/Rando/Logic/Logic.h" +#include "port/Rando/ObjectBehavior/ObjectBehavior.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "actor.h" @@ -34,7 +35,6 @@ void ml_vec3f_to_vec3h(s16 dst[3], f32 src[3]); void gcparade_beginFinalParade(void); void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume); -Actor* marker_getActor(ActorMarker* thisx); void marker_despawn(ActorMarker* marker); Actor* actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags); extern ActorInfo chJinjoBlue; @@ -43,18 +43,18 @@ extern ActorInfo chJinjoYellow; extern ActorInfo chJinjoPink; extern ActorInfo chJinjoOrange; extern ActorInfo chJiggy; -extern ActorInfo D_80366C80; -extern ActorInfo D_803685A0; +extern ActorInfo chEmptyHoneycomb; +extern ActorInfo chMumboToken; extern ActorInfo sumusicNote; extern ActorInfo chExtraLife; -extern ActorInfo D_80366CA4; -extern ActorInfo D_80367D00; -extern ActorInfo D_80367D24; -extern ActorInfo D_80367D48; +extern ActorInfo chHoneycomb; +extern ActorInfo chBlueEgg; +extern ActorInfo chRedFeather; +extern ActorInfo chGoldFeather; -extern ActorInfo D_80367814; -extern ActorInfo D_803677A8; +extern ActorInfo chSnsEgg; +extern ActorInfo chIceKey; } typedef struct { @@ -69,9 +69,9 @@ bool shouldRemoveEX = false; // clang-format off std::map> actorInfoMap = { - { ACTOR_2D_MUMBO_TOKEN, { D_803685A0, ACTOR_FLAG_UNKNOWN_6 } }, + { ACTOR_2D_MUMBO_TOKEN, { chMumboToken, ACTOR_FLAG_UNKNOWN_6 } }, { ACTOR_46_JIGGY, { chJiggy, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_47_EMPTY_HONEYCOMB, { D_80366C80, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_47_EMPTY_HONEYCOMB, { chEmptyHoneycomb, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_49_EXTRA_LIFE, { chExtraLife, ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_51_MUSIC_NOTE, { sumusicNote, ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_5E_JINJO_YELLOW, { chJinjoYellow, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, @@ -79,16 +79,15 @@ std::map> actorInfoMap = { { ACTOR_60_JINJO_BLUE, { chJinjoBlue, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, { ACTOR_61_JINJO_PINK, { chJinjoPink, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, { ACTOR_62_JINJO_GREEN, { chJinjoGreen, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, - { ACTOR_50_HONEYCOMB, { D_80366CA4, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_52_BLUE_EGG, { D_80367D00, ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_129_RED_FEATHER, { D_80367D24, ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_370_GOLD_FEATHER, { D_80367D48, ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_25E_SNS_EGG, { D_80367814, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, - { ACTOR_25D_ICE_KEY, { D_803677A8, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, + { ACTOR_50_HONEYCOMB, { chHoneycomb, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_52_BLUE_EGG, { chBlueEgg, ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_129_RED_FEATHER, { chRedFeather, ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_370_GOLD_FEATHER, { chGoldFeather, ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_25E_SNS_EGG, { chSnsEgg, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, + { ACTOR_25D_ICE_KEY, { chIceKey, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, }; // clang-format on -extern int32_t GetJinjoActorMarkerId(actor_e actorId); int32_t currentMap = -1; void CustomObject::ResetRandoSpawnQueue() { @@ -172,6 +171,10 @@ Actor* CustomObject::SpawnCustomActorEX(RandoCheckId randoCheckId, int32_t posit Actor* customActor = actor_new(position, 0, actorInfo, flags); if (customActor != NULL) { + // Music notes don't cast shadows, custom or otherwise. + if (actorInfo->actorId == ACTOR_51_MUSIC_NOTE) { + customActor->unk124_6 = 0; + } customActor = SetCustomActorParametersEX(randoCheckId, customActor); randoSpawnedCheckIds.push_back(randoCheckId); } @@ -204,7 +207,7 @@ void CustomObject::FlushRandoSpawnQueue() { } actor_e randoActorId = Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId); - if (randoSaveCheck.obtained) { + if (randoSaveCheck.eligible) { randoActorId = GetRandomJunkActorId(randoSaveCheck); } @@ -217,7 +220,8 @@ void CustomObject::FlushRandoSpawnQueue() { &actorInfoMap.at(randoActorId).first, actorInfoMap.at(randoActorId).second); - if (randoSaveCheck.obtained && RANDO_SAVE_OPTIONS[RO_SPAWN_JUNK].optionValue == RO_GENERIC_ON) { + if (customActor != NULL && randoSaveCheck.eligible && + RANDO_SAVE_OPTIONS[RO_SPAWN_JUNK].optionValue == RO_GENERIC_ON) { customActor->marker->unk14_21 = true; customActor->scale = 1.0f; } @@ -250,7 +254,7 @@ Actor* CustomObject::ShouldCreateCustomActorEX(RandoCheckId randoCheckId, int32_ return NULL; } - if (randoSaveCheck.obtained) { + if (randoSaveCheck.eligible) { if (refActor != nullptr) { randoActorId = (actor_e)refActor->modelCacheIndex; } else { @@ -335,16 +339,22 @@ void CustomObject::ResolveCustomActorCollisionEX(RandoCheckId randoCheckId) { void CustomObject::CheckObtainedEX(RandoCheckId randoCheckId, bool isInit) { for (auto& pool : Rando::Logic::shuffledPool) { - if (pool.randoCheckId == randoCheckId && !pool.obtained) { - pool.obtained = true; + if (pool.randoCheckId == randoCheckId && !pool.eligible) { + pool.eligible = true; shouldRemoveEX = true; - RANDO_SAVE_CHECKS[pool.randoCheckId].obtained = true; + RANDO_SAVE_CHECKS[pool.randoCheckId].eligible = true; CustomObject::RemoveSpawnedIdFromList(randoCheckId); - if (!isInit) { + if (isInit) { + CustomObject::ResolveCustomActorCollisionEX(randoCheckId); + } else { Rando::StaticData::SendCollisionNotification(pool.randoCheckId); } Rando::StaticData::ModifyRandoInfFlagState(randoCheckId); Rando::Logic::RefreshReachableRegions(); + // Broadcast real collects only (not save-load/remote apply, both isInit). + if (!isInit) { + CALL_EVENT(OnRandoCheckObtained, (int32_t)randoCheckId, (int32_t)gsworld_getMap()); + } break; } } diff --git a/src/port/Rando/ItemQueue.cpp b/src/port/Rando/ItemQueue.cpp new file mode 100644 index 000000000..8b2571fe7 --- /dev/null +++ b/src/port/Rando/ItemQueue.cpp @@ -0,0 +1,344 @@ +#include "ItemQueue.h" + +#include +#include +#include + +#include "port/UI/Notification.h" +#include "port/UI/UIWidgets.hpp" +#include +#include "port/ShipInit.hpp" +#include "port/Rando/Logic/Logic.h" +#include "actor.h" +#include "port/Enhancements/Retention/Retention.h" + +extern "C" { +#include "functions.h" +extern u8 sHoneycombScore[3]; +extern struct { + u8 D_803832C0[0xD]; + u8 D_803832CD[0xD]; +} jiggyscore; +#define MUMBO_TOKEN_COUNT 126 +#define MUMBOSCORE_SIZE (((MUMBO_TOKEN_COUNT - 1 + 7) & ~7) / 8) +extern u8 sMumboTokenScore[MUMBOSCORE_SIZE]; +extern u8 D_80385FF0[0xE]; + +extern ActorInfo chJinjoBlue; +extern ActorInfo chJinjoGreen; +extern ActorInfo chJinjoYellow; +extern ActorInfo chJinjoPink; +extern ActorInfo chJinjoOrange; +extern void spawnOrbit(); +} + +constexpr u8 kAllJinjos = 0x1F; // all five color bits collected + +#define CVAR_NAME_SHOW_COLLISION_NOTIFICATIONS "gRandoSettings.RandoNotifications" +#define CVAR_SHOW_COLLISION_NOTIFICATIONS CVarGetInteger(CVAR_NAME_SHOW_COLLISION_NOTIFICATIONS, 0) + +#define JIGGY_ID_MULTIPLIER(levelId) (1 + (10 * (levelId - 1))) +#define HONEYCOMB_ID_MULTIPLIER(levelId) (1 + (2 * (levelId - 1))) + +static std::queue itemQueue; + +std::unordered_map itemColors = { + { ACTOR_1_UNKNOWN, UIWidgets::Colors::Brown }, { ACTOR_52_BLUE_EGG, UIWidgets::Colors::Cyan }, + { ACTOR_47_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_49_EXTRA_LIFE, UIWidgets::Colors::Yellow }, + { ACTOR_50_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_46_JIGGY, UIWidgets::Colors::Yellow }, + { ACTOR_60_JINJO_BLUE, UIWidgets::Colors::SkyBlue }, { ACTOR_62_JINJO_GREEN, UIWidgets::Colors::Green }, + { ACTOR_5F_JINJO_ORANGE, UIWidgets::Colors::Orange }, { ACTOR_61_JINJO_PINK, UIWidgets::Colors::Pink }, + { ACTOR_5E_JINJO_YELLOW, UIWidgets::Colors::Yellow }, { ACTOR_12C_MOLEHILL, UIWidgets::Colors::Cyan }, + { ACTOR_2D_MUMBO_TOKEN, UIWidgets::Colors::Gray }, { ACTOR_51_MUSIC_NOTE, UIWidgets::Colors::Yellow }, + { ACTOR_25E_SNS_EGG, UIWidgets::Colors::Pink }, { ACTOR_25D_ICE_KEY, UIWidgets::Colors::White }, +}; + +std::unordered_map snsColors = { + { RI_STOP_N_SWOP_EGG_YELLOW, UIWidgets::Colors::Yellow }, { RI_STOP_N_SWOP_EGG_RED, UIWidgets::Colors::Red }, + { RI_STOP_N_SWOP_EGG_GREEN, UIWidgets::Colors::Green }, { RI_STOP_N_SWOP_EGG_BLUE, UIWidgets::Colors::Blue }, + { RI_STOP_N_SWOP_EGG_PINK, UIWidgets::Colors::Pink }, { RI_STOP_N_SWOP_EGG_CYAN, UIWidgets::Colors::Cyan }, + { RI_STOP_N_SWOP_ICE_KEY, UIWidgets::Colors::White }, +}; + +std::unordered_map jinjoJiggyChecks = { + { LEVEL_1_MUMBOS_MOUNTAIN, RC_MM_JIGGY_JINJO }, { LEVEL_2_TREASURE_TROVE_COVE, RC_TTC_JIGGY_JINJO }, + { LEVEL_3_CLANKERS_CAVERN, RC_CC_JIGGY_JINJO }, { LEVEL_4_BUBBLEGLOOP_SWAMP, RC_BGS_JIGGY_JINJO }, + { LEVEL_5_FREEZEEZY_PEAK, RC_FP_JIGGY_JINJO }, { LEVEL_7_GOBIS_VALLEY, RC_GV_JIGGY_JINJO }, + { LEVEL_8_CLICK_CLOCK_WOOD, RC_CCW_JIGGY_JINJO }, { LEVEL_9_RUSTY_BUCKET_BAY, RC_RBB_JIGGY_JINJO }, + { LEVEL_A_MAD_MONSTER_MANSION, RC_MMM_JIGGY_JINJO }, +}; + +void ItemQueue::Process() { + if (itemQueue.size() < 1) { + return; + } + + RandoCheckId randoCheckId = itemQueue.front(); + + // Grant item + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; + if (!randoSaveCheck.received) { + ItemQueue::GiveItem(randoSaveCheck.randoItemId); + ItemQueue::SendNotification(randoSaveCheck.randoItemId); + Rando::StaticData::ModifyRandoInfFlagState(randoCheckId); + // RANDO_SAVE_CHECKS[randoCheckId].received = true; + } + + itemQueue.pop(); +} + +void ItemQueue::GiveItem(RandoItemId randoItemId) { + RandoItemType itemType = Rando::StaticData::Items[randoItemId].randoItemType; + actor_e actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; + int16_t worldId = Rando::StaticData::Items[randoItemId].worldId; + uint16_t combId; + uint16_t maxHoneycombs; + uint32_t jiggyId; + ActorInfo* actorInfo; + int32_t playerPosition[3]; + Actor* customActor; + uint8_t collectedJinjos; + + switch (itemType) { + case RITYPE_BLUE_EGG: + coMusicPlayer_playMusic(COMUSIC_C_EGG_COLLECTED, 32000); + item_inc(ITEM_D_EGGS); + break; + case RITYPE_EMPTY_HONEYCOMB: + combId = HONEYCOMB_ID_MULTIPLIER(worldId); + maxHoneycombs = worldId == LEVEL_B_SPIRAL_MOUNTAIN ? 6 : 2; + if (worldId > LEVEL_6_LAIR) { + combId = HONEYCOMB_ID_MULTIPLIER(worldId - 1); + } + for (int i = 0; i < (maxHoneycombs); i++) { + if ((sHoneycombScore[((combId + i) - 1) / 8] & (1 << ((combId + i) & 7))) == 0) { + honeycombscore_set((honeycomb_e)(combId + i), 1); + break; + } + } + coMusicPlayer_playMusic(COMUSIC_17_EMPTY_HONEYCOMB_COLLECTED, 28000); + item_inc(ITEM_13_EMPTY_HONEYCOMB); + if (!(item_getCount(ITEM_13_EMPTY_HONEYCOMB) < 6)) { + gcpausemenu_80314AC8(0); + } + break; + case RITYPE_EXTRA_LIFE: + coMusicPlayer_playMusic(COMUSIC_15_EXTRA_LIFE_COLLECTED, 0x7FFF); + item_inc(ITEM_16_LIFE); + break; + case RITYPE_HONEYCOMB: + coMusicPlayer_playMusic(COMUSIC_16_HONEYCOMB_COLLECTED, 28000); + item_inc(ITEM_14_HEALTH); + break; + case RITYPE_JIGGY: + jiggyId = JIGGY_ID_MULTIPLIER(worldId); + for (int32_t i = jiggyId; i <= (jiggyId + 9); i++) { + if ((jiggyscore.D_803832C0[(i - 1) / 8] & (1 << (i & 7))) == 0) { + jiggyscore_setCollected(i, 1); + break; + } + } + coMusicPlayer_playMusic(COMUSIC_D_JINGLE_JIGGY_COLLECTED, -1); + item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, 1); + item_inc(ITEM_E_JIGGY); + spawnOrbit(); + break; + case RITYPE_JINJO: + if (worldId == map_getLevel(gsworld_getMap())) { + item_adjustByDiffWithHud(ITEM_12_JINJOS, jinjoBitFromActor(actorId)); + } + collectedJinjos = collectedBits(worldId); + collectedJinjos |= jinjoBitFromActor(actorId); + if (collectedJinjos == kAllJinjos) { + ItemQueue::AddCheck(jinjoJiggyChecks[worldId]); + } + setCollectedBits(worldId, collectedJinjos); + // Spawn vanilla jinjo on top of the player because the animation is too complex to handle without doing + // this. Collection behaviour is canceled in Jinjo.cpp so that part can all be handled here in the + // ItemQueue. + switch (actorId) { + case ACTOR_5E_JINJO_YELLOW: + actorInfo = &chJinjoYellow; + break; + case ACTOR_5F_JINJO_ORANGE: + actorInfo = &chJinjoOrange; + break; + case ACTOR_60_JINJO_BLUE: + actorInfo = &chJinjoBlue; + break; + case ACTOR_61_JINJO_PINK: + actorInfo = &chJinjoPink; + break; + case ACTOR_62_JINJO_GREEN: + actorInfo = &chJinjoGreen; + break; + } + player_getPosition_s32(playerPosition); + customActor = actor_new(playerPosition, 0, actorInfo, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); + break; + case RITYPE_MOLEHILL: + coMusicPlayer_playMusic(COMUSIC_D_JINGLE_JIGGY_COLLECTED, -1); + switch (randoItemId) { + case RI_MOLEHILL_BARGE: + ability_unlock(ABILITY_0_BARGE); + break; + case RI_MOLEHILL_BEAK_BOMB: + ability_unlock(ABILITY_1_BEAK_BOMB); + break; + case RI_MOLEHILL_BEAK_BUSTER: + ability_unlock(ABILITY_2_BEAK_BUSTER); + break; + case RI_MOLEHILL_CAMERA_CONTROL: + ability_unlock(ABILITY_3_CAMERA_CONTROL); + break; + case RI_MOLEHILL_CLAW_SWIPE: + ability_unlock(ABILITY_4_CLAW_SWIPE); + ability_unlock(ABILITY_C_ROLL); + ability_unlock(ABILITY_B_RATATAT_RAP); + break; + case RI_MOLEHILL_CLIMB: + ability_unlock(ABILITY_5_CLIMB); + break; + case RI_MOLEHILL_DIVE: + ability_unlock(ABILITY_F_DIVE); + break; + case RI_MOLEHILL_EGGS: + ability_unlock(ABILITY_6_EGGS); + item_adjustByDiffWithHud(ITEM_D_EGGS, 50); + break; + case RI_MOLEHILL_FLAP_FLIP: + ability_unlock(ABILITY_A_HOLD_A_JUMP_HIGHER); + ability_unlock(ABILITY_7_FEATHERY_FLAP); + ability_unlock(ABILITY_8_FLAP_FLIP); + break; + case RI_MOLEHILL_FLIGHT: + ability_unlock(ABILITY_9_FLIGHT); + item_adjustByDiffWithHud(ITEM_F_RED_FEATHER, 25); + break; + case RI_MOLEHILL_SHOCK_JUMP: + ability_unlock(ABILITY_D_SHOCK_JUMP); + break; + case RI_MOLEHILL_TALON_TROT: + ability_unlock(ABILITY_10_TALON_TROT); + break; + case RI_MOLEHILL_TURBO_TALON: + ability_unlock(ABILITY_11_TURBO_TALON); + break; + case RI_MOLEHILL_WADING_BOOTS: + ability_unlock(ABILITY_E_WADING_BOOTS); + break; + case RI_MOLEHILL_WONDERWING: + ability_unlock(ABILITY_12_WONDERWING); + item_adjustByDiffWithHud(ITEM_10_GOLD_FEATHER, 5); + break; + default: + break; + } + break; + case RITYPE_MUMBO_TOKEN: + func_8030E760((sfx_e)0x401, 1.0f, 0x7fff); + for (uint32_t i = MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA; + i <= MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL; i++) { + if ((sMumboTokenScore[(i - 1) / 8] & (1 << (i & 7))) == 0) { + mumboscore_set((mumbotoken_e)i, true); + break; + } + } + item_inc(ITEM_1C_MUMBO_TOKEN); + break; + case RITYPE_MUSIC_NOTE: + coMusicPlayer_playMusic(COMUSIC_9_NOTE_COLLECTED, 16000); + D_80385FF0[worldId]++; + if (worldId == map_getLevel(gsworld_getMap())) { + item_set(ITEM_C_NOTE, D_80385FF0[map_getLevel(gsworld_getMap())]); + } + break; + case RITYPE_SNS_EGG: + comusic_playTrack(COMUSIC_88_BIG_SNS_FANFARE); + FUNC_8030E624(SFX_114_BRICKWALL_BREAKING, 0.8f, 15000); + switch (randoItemId) { + case RI_STOP_N_SWOP_EGG_BLUE: + sns_set_item_and_update_payload(SNS_ITEM_EGG_BLUE, 0, 1); + break; + case RI_STOP_N_SWOP_EGG_CYAN: + sns_set_item_and_update_payload(SNS_ITEM_EGG_CYAN, 0, 1); + break; + case RI_STOP_N_SWOP_EGG_GREEN: + sns_set_item_and_update_payload(SNS_ITEM_EGG_GREEN, 0, 1); + break; + case RI_STOP_N_SWOP_EGG_PINK: + sns_set_item_and_update_payload(SNS_ITEM_EGG_PINK, 0, 1); + break; + case RI_STOP_N_SWOP_EGG_RED: + sns_set_item_and_update_payload(SNS_ITEM_EGG_RED, 0, 1); + break; + case RI_STOP_N_SWOP_EGG_YELLOW: + sns_set_item_and_update_payload(SNS_ITEM_EGG_YELLOW, 0, 1); + break; + } + break; + case RITYPE_SNS_KEY: + sns_set_item_and_update_payload(SNS_ITEM_ICE_KEY, 0, 1); + comusic_playTrack(COMUSIC_88_BIG_SNS_FANFARE); + break; + case RITYPE_AP_ITEM: + break; + default: + break; + } +} + +void ItemQueue::SendNotification(RandoItemId randoItemId) { + if (CVAR_SHOW_COLLISION_NOTIFICATIONS) { + RandoItemType itemType = Rando::StaticData::Items[randoItemId].randoItemType; + actor_e actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; + std::string prefix = ""; + std::string message = Rando::StaticData::Items[randoItemId].name; + std::string suffix = ""; + ImVec4 itemColor = UIWidgets::ColorValues.at(itemColors[actorId]); + + if (itemType == RITYPE_MOLEHILL) { + prefix = "You learned"; + } else if (itemType == RITYPE_SNS_EGG || itemType == RITYPE_SNS_KEY) { + int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); + prefix = "You collected "; + prefix += Rando::StaticData::Items[randoItemId].article; + suffix = "("; + suffix += std::to_string(totalsnsItems); + suffix += " / 7)"; + + itemColor = UIWidgets::ColorValues.at(snsColors[randoItemId]); + } else { + prefix = "You collected "; + prefix += Rando::StaticData::Items[randoItemId].article; + } + + Notification::Emit({ + .prefix = prefix, + .prefixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), + .message = message, + .messageColor = itemColor, + .suffix = suffix, + .suffixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), + }); + } +} + +void ItemQueue::Clear() { + while (!itemQueue.empty()) { + itemQueue.pop(); + } +} + +void ItemQueue::AddCheck(RandoCheckId randoCheckId) { + RANDO_SAVE_CHECKS[randoCheckId].eligible = true; + itemQueue.push(randoCheckId); +} + +void RegisterItemQueue() { + COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { ItemQueue::Process(); }); + + COND_HOOK(OnSaveFileLoad, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { ItemQueue::Clear(); }); +} + +static RegisterShipInitFunc initFunc(RegisterItemQueue, { "IS_RANDO" }); diff --git a/src/port/Rando/ItemQueue.h b/src/port/Rando/ItemQueue.h new file mode 100644 index 000000000..0e526b04d --- /dev/null +++ b/src/port/Rando/ItemQueue.h @@ -0,0 +1,10 @@ +#include "port/Rando/Rando.h" + +class ItemQueue { +public: + static void Process(); + static void Clear(); + static void GiveItem(RandoItemId randoItemId); + static void SendNotification(RandoItemId randoItemId); + static void AddCheck(RandoCheckId randoCheckId); +}; diff --git a/src/port/Rando/LighthouseMenuRando.cpp b/src/port/Rando/LighthouseMenuRando.cpp index 0a5a8117a..8c654a44d 100644 --- a/src/port/Rando/LighthouseMenuRando.cpp +++ b/src/port/Rando/LighthouseMenuRando.cpp @@ -7,12 +7,11 @@ #include "port/Rando/CustomObject/CustomObject.h" #include "port/Rando/Logic/Logic.h" +#include "port/Rando/Spoiler/Spoiler.h" #include -extern "C" { #include "variables.h" -} const char* logicModes[2] = { "Glitchless", @@ -61,6 +60,38 @@ void LighthouseMenu::AddMenuRando() { } UIWidgets::PopStyleCombobox(); }); + AddWidget(path, "Load Existing Spoiler Log", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_RANDOMIZER_SETTING("UseExistingLog")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Uses a Spoiler Log in the randomizer folder.")); + AddWidget(path, "Available Spoiler Logs", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { + std::vector spoilerLogPtrs; + spoilerLogPtrs.reserve(Rando::Spoiler::spoilerLogs.size()); + for (const auto& log : Rando::Spoiler::spoilerLogs) { + spoilerLogPtrs.push_back(log.c_str()); + } + + ImGui::BeginDisabled(!CVarGetInteger(CVAR_RANDOMIZER_SETTING("UseExistingLog"), 0)); + if (UIWidgets::CVarCombobox("Seed", CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), spoilerLogPtrs, + { .labelPosition = UIWidgets::LabelPositions::None, .color = WIDGET_COLOR })) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), 0) == 0) { + CVarSetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), ""); + } else { + std::string spoilerName = + Rando::Spoiler::spoilerLogs[CVarGetInteger(CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), 0)]; + CVarSetString("gRandoSettings.SpoilerFile", spoilerName.c_str()); + } + } + ImGui::SameLine(); + if (UIWidgets::Button(ICON_FA_REFRESH, UIWidgets::ButtonOptions() + .Color(WIDGET_COLOR) + .Size(ImVec2(32.0f, 32.0f)) + .Tooltip("Refreshes the list of Spoiler Logs."))) { + Rando::Spoiler::RefreshSpoilerLogs(); + } + ImGui::EndDisabled(); + }); + AddWidget(path, "Send Collection Notifications", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_RANDOMIZER_SETTING("RandoNotifications")) .Options(CheckboxOptions().Tooltip("Sends notifications when you collect a Rando Item.")); @@ -237,36 +268,6 @@ void LighthouseMenu::AddMenuRando() { } }); - // Rando - Junk Options - AddSidebarEntry("Rando", "Junk Options", 1); - path = { "Rando", "Junk Options", SECTION_COLUMN_1 }; - - AddWidget(path, "Enable Junk", WIDGET_SEPARATOR_TEXT); - - AddWidget(path, "Spawn Junk For Obtained Checks", WIDGET_CVAR_CHECKBOX) - .CVar(Rando::StaticData::Options[RO_SPAWN_JUNK].cvar) - .Options(CheckboxOptions().Tooltip("Spawns a junk item in place of an object that has already been collected.")) - .Callback([](WidgetInfo& info) { UpdateJunkList(); }); - - AddWidget(path, "Junk Selection", WIDGET_SEPARATOR_TEXT); - - AddWidget(path, "Honeycomb Refills", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_RANDOMIZER_SETTING("Junk.HealthRefill")) - .Options(CheckboxOptions().Tooltip("Adds Health Refills to the Junk List.")) - .Callback([](WidgetInfo& info) { UpdateJunkList(); }); - AddWidget(path, "Blue Eggs", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_RANDOMIZER_SETTING("Junk.BlueEggs")) - .Options(CheckboxOptions().Tooltip("Adds Blue Eggs to the Junk List.")) - .Callback([](WidgetInfo& info) { UpdateJunkList(); }); - AddWidget(path, "Red Feathers", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_RANDOMIZER_SETTING("Junk.RedFeathers")) - .Options(CheckboxOptions().Tooltip("Adds Red Feathers to the Junk List.")) - .Callback([](WidgetInfo& info) { UpdateJunkList(); }); - AddWidget(path, "Gold Feathers", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_RANDOMIZER_SETTING("Junk.GoldFeathers")) - .Options(CheckboxOptions().Tooltip("Adds Gold Feathers to the Junk List.")) - .Callback([](WidgetInfo& info) { UpdateJunkList(); }); - // Rando - Check Tracker path.sidebarName = "Check Tracker"; AddSidebarEntry("Rando", path.sidebarName, 1); diff --git a/src/port/Rando/Logic/GeneratePools.cpp b/src/port/Rando/Logic/GeneratePools.cpp index 64aca987e..f6eace65e 100644 --- a/src/port/Rando/Logic/GeneratePools.cpp +++ b/src/port/Rando/Logic/GeneratePools.cpp @@ -130,7 +130,7 @@ void GenerateShufflePool(SaveData* saveData) { .randoItemId = Rando::StaticData::Checks[std::get<2>(itemPool[i])].randoItemId, .randoCollectionId = std::get<1>(itemPool[i]), .isShuffled = checkPool[i] == RC_UNKNOWN ? false : true, - .obtained = false, + .eligible = false, .skipped = false, }; @@ -146,7 +146,7 @@ void GenerateShufflePool(SaveData* saveData) { .randoItemId = Rando::StaticData::Checks[std::get<2>(abilityItemPool[a])].randoItemId, .randoCollectionId = std::get<1>(abilityItemPool[a]), .isShuffled = true, - .obtained = false, + .eligible = false, .skipped = false, }; @@ -177,7 +177,8 @@ void GeneratePoolFromSaveData(SaveData* saveData) { .randoItemId = randoSaveCheck.randoItemId, .randoCollectionId = randoSaveCheck.randoCollectionId, .isShuffled = randoSaveCheck.isShuffled, - .obtained = randoSaveCheck.obtained, + .eligible = randoSaveCheck.eligible, + .received = randoSaveCheck.received, .skipped = randoSaveCheck.skipped, }; diff --git a/src/port/Rando/Logic/GenerateSaveData.cpp b/src/port/Rando/Logic/GenerateSaveData.cpp index 3361ce00a..2106f2302 100644 --- a/src/port/Rando/Logic/GenerateSaveData.cpp +++ b/src/port/Rando/Logic/GenerateSaveData.cpp @@ -8,11 +8,9 @@ #include "port/Save/Types.h" extern "C" { -void ability_setLearned(s32 move, s32 val); void ability_setHasUsed(enum ability_e move); void item_setMaxCount(s32 item); -void fileProgressFlag_set(enum file_progress_e index, s32 set); } // clang-format off @@ -128,7 +126,7 @@ void Rando::Logic::InitializeSaveData(SaveData* saveData) { // .randoItemId = Rando::StaticData::GetRandoItemByActorId((actor_e)randoStaticCheck.actorId), .randoCollectionId = randoStaticCheck.collectionId, .isShuffled = false, - .obtained = false, + .eligible = false, .skipped = false, }; @@ -150,7 +148,7 @@ void Rando::Logic::InitializeSaveData(SaveData* saveData) { } void Rando::Logic::GenerateSaveData(SaveData* saveData) { - for (auto& object : Rando::Logic::shuffledPool) { + for (auto& object : RANDO_SAVE_CHECKS) { saveData->shipSaveData.randoSaveData.randoSaveCheck[object.randoCheckId] = object; } @@ -172,21 +170,30 @@ void Rando::Logic::GrantStartingLoadout() { item_setMaxCount(item); } } +} - // Set progress flag for tutorial dialogue, skipping them +void Rando::Logic::GrantFileProgressFlags() { for (auto& fileprog : progressLoadout) { fileProgressFlag_set(fileprog, 1); } +} - if (CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.SkipSMTutorial"), 0)) { - for (auto& smCheckId : smRandoCheckIdList) { - RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[smCheckId]; +void Rando::Logic::GrantSpiralMountainChecks() { + if (!CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.SkipSMTutorial"), 0)) { + return; + } - if (!randoSaveCheck.isShuffled) { - continue; - } + for (auto& smCheckId : smRandoCheckIdList) { + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[smCheckId]; + + if (!randoSaveCheck.isShuffled) { + continue; + } - CustomObject::CheckObtainedEX(smCheckId, true); + CustomObject::CheckObtainedEX(smCheckId, true); + if (Rando::StaticData::Items[randoSaveCheck.randoItemId].randoItemType == RITYPE_MOLEHILL) { + ability_setLearned((ability_e)randoSaveCheck.randoCollectionId, true); + ability_setHasUsed((ability_e)randoSaveCheck.randoCollectionId); } } } \ No newline at end of file diff --git a/src/port/Rando/Logic/GlitchlessLogic.cpp b/src/port/Rando/Logic/GlitchlessLogic.cpp index 495a9df96..75390a401 100644 --- a/src/port/Rando/Logic/GlitchlessLogic.cpp +++ b/src/port/Rando/Logic/GlitchlessLogic.cpp @@ -241,7 +241,9 @@ void PopulateJinjoCheckIds() { } void ResetSaveData() { - for (int s = 0; s < sizeof(SaveData); s++) { + // [port] `data` is the 112-byte vanilla payload, not the whole SaveData, which is + // ~43 KB once shipSaveData (rando checks, note/jinjo retention) is counted. + for (size_t s = 0; s < sizeof(gameFile_saveData[selectedFileNum].data); s++) { gameFile_saveData[selectedFileNum].data[s] = 0; } @@ -381,13 +383,6 @@ void GenerateGlitchlessLogicPool(std::vector& checkPool, PlacedItemCounts placedItems = { .noteCount = 0, .jiggyCount = 0, .mumboTokenCount = 0 }; PlacedCheckObject placedCheckItems[RC_MAX] = {}; - for (auto& shuffledCheck : checkPool) { - reachableChecks[shuffledCheck].isShuffled = true; - } - for (auto& shuffledAbiity : abilityCheckPool) { - reachableChecks[shuffledAbiity].isShuffled = true; - } - if (CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_JINJOS].cvar, 0) == RO_GENERIC_ON) { PopulateJinjoCheckIds(); } @@ -403,23 +398,46 @@ void GenerateGlitchlessLogicPool(std::vector& checkPool, reachableChecks[checkId].name = checkData.name; reachableChecks[checkId].canAccess = false; reachableChecks[checkId].isFilled = false; + reachableChecks[checkId].isShuffled = false; + } + + for (auto& shuffledCheck : checkPool) { + reachableChecks[shuffledCheck].isShuffled = true; + } + for (auto& shuffledAbiity : abilityCheckPool) { + reachableChecks[shuffledAbiity].isShuffled = true; } // Starting Initialization reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess = true; Rando::Logic::GrantStartingLoadout(); for (auto& [ability, abilityInfo] : abilityLoadoutMap) { - if (CVarGetInteger(abilityInfo.second, 0)) { - RandoCheckId abilityCheck = Rando::StaticData::GetCheckByAbilityId(ability); - - auto it = std::find(abilityCheckPool.begin(), abilityCheckPool.end(), abilityCheck); - if (it != abilityCheckPool.end()) { - abilityCheckPool.erase(it); - UpdateAccessibility(RR_SPIRAL_MOUNTAIN_ENTRANCE, - reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess); - continue; - } + if (!CVarGetInteger(abilityInfo.second, 0)) { + continue; } + + RandoCheckId abilityCheck = Rando::StaticData::GetCheckByAbilityId(ability); + + auto it = std::find(abilityCheckPool.begin(), abilityCheckPool.end(), abilityCheck); + if (it == abilityCheckPool.end()) { + continue; + } + + abilityCheckPool.erase(it); + + // The molehill left the pool, so it has to stop being a valid placement target as well. + reachableChecks[abilityCheck].isShuffled = false; + + // The player already owns this ability, so its item leaves the pool alongside the molehill. + auto item = std::find_if(abilityItemPool.begin(), abilityItemPool.end(), + [&](const std::tuple& abilityItem) { + return std::get<1>(abilityItem) == (int32_t)ability; + }); + if (item != abilityItemPool.end()) { + abilityItemPool.erase(item); + } + + UpdateAccessibility(RR_SPIRAL_MOUNTAIN_ENTRANCE, reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess); } UpdateAccessibility(RR_SPIRAL_MOUNTAIN_ENTRANCE, reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess); diff --git a/src/port/Rando/Logic/Logic.h b/src/port/Rando/Logic/Logic.h index 964235b66..bed9f239a 100644 --- a/src/port/Rando/Logic/Logic.h +++ b/src/port/Rando/Logic/Logic.h @@ -6,32 +6,21 @@ #include +#include "functions.h" extern "C" { -void item_set(s32 item, s32 val); -void item_adjustByDiffWithoutHud(enum item_e item, s32 diff); -s32 item_getCount(enum item_e item); -void itemscore_noteScores_clear(void); - -void ability_unlock(enum ability_e); -int ability_isUnlocked(enum ability_e uid); -void ability_setLearned(s32 move, s32 val); +// Decomp functions that functions.h does not declare (defined in smbottles.c, +// mumbo_transforms.c and jigsawpicture.c respectively). void __chSmBottles_skipIntroTutorial(void); - -void fileProgressFlag_set(enum file_progress_e index, s32 set); -bool fileProgressFlag_get(enum file_progress_e index); s32 __transformation_getCost(enum transformation_e trans_id); s32 _puzzleCost(s32 index); - -u32 player_getTransformation(void); - -enum level_e map_getLevel(enum map_e map); -enum map_e gsworld_getMap(void); } extern int32_t randoFinalSeed; extern std::map> abilityLoadoutMap; extern std::map> itemLoadoutMap; +extern std::vector progressLoadout; +extern std::vector smRandoCheckIdList; extern Rando::StaticData::RandoLogicData reachableRegions[RR_MAX]; extern Rando::StaticData::RandoLogicData reachableEvents[RA_MAX]; @@ -67,20 +56,17 @@ void GeneratePoolFromSaveData(SaveData* saveData); void InitializeSaveData(SaveData* saveData); void GenerateSaveData(SaveData* saveData); void GrantStartingLoadout(); +void GrantFileProgressFlags(); +void GrantSpiralMountainChecks(); void RefreshReachableRegions(); inline bool IsCheckShuffled(RandoCheckId randoCheckId) { - bool isShuffled = false; - - for (auto& object : shuffledPool) { - if (object.randoCheckId == randoCheckId) { - isShuffled = object.isShuffled; - break; - } - } + return RANDO_SAVE_CHECKS[randoCheckId].isShuffled; +} - return isShuffled; +inline bool IsCheckObtained(RandoCheckId randoCheckId) { + return RANDO_SAVE_CHECKS[randoCheckId].eligible; } inline RandoSaveCheck GetShuffledObject(RandoCheckId randoCheckId) { @@ -101,25 +87,12 @@ inline RandoSaveCheck GetShuffledObject(RandoCheckId randoCheckId) { return shuffledObject; } -inline bool IsCheckObtained(RandoCheckId randoCheckId) { - bool isObtained = false; - - for (auto& object : shuffledPool) { - if (object.randoCheckId == randoCheckId) { - isObtained = object.obtained; - break; - } - } - - return isObtained; -} - inline bool ShouldSpawnJinjoJiggy(int16_t levelId) { bool shouldSpawn = false; int16_t jinjoCount = 0; for (auto& location : Rando::Logic::shuffledPool) { - if (!location.obtained) { + if (!location.eligible) { continue; } @@ -145,7 +118,7 @@ inline int32_t GetTotalSnsItemsCollected() { int32_t snsCount = 0; for (auto& location : Rando::Logic::shuffledPool) { - if (!location.obtained) { + if (!location.eligible) { continue; } @@ -251,7 +224,9 @@ inline bool CanOpenWorld(level_e levelId) { return true; } - int32_t puzzleCost = levelId == LEVEL_6_LAIR ? 25 : _puzzleCost(levelNum - 1); + // [port] index 9 is the Door of Grunty picture; 25 is only its vanilla cost, and a + // romhack can change it like any other. + int32_t puzzleCost = levelId == LEVEL_6_LAIR ? _puzzleCost(9) : _puzzleCost(levelNum - 1); int32_t jiggyCount = item_getCount(ITEM_E_JIGGY); if (jiggyCount >= puzzleCost) { @@ -364,6 +339,8 @@ inline bool CanKillEnemy(actor_e enemyType) { canKillEnemy = true; } break; + default: + break; } return canKillEnemy; diff --git a/src/port/Rando/MiscBehavior/OnFileLoad.cpp b/src/port/Rando/MiscBehavior/OnFileLoad.cpp index e8d8161f9..12100a6d0 100644 --- a/src/port/Rando/MiscBehavior/OnFileLoad.cpp +++ b/src/port/Rando/MiscBehavior/OnFileLoad.cpp @@ -1,5 +1,7 @@ #include "MiscBehavior.h" #include +#include "src/port/ShipInit.hpp" +#include "ship/Context.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/UI/Notification.h" @@ -7,8 +9,8 @@ #include "port/UI/cvar_prefixes.h" #include "port/Rando/Logic/Logic.h" +#include "port/Rando/Spoiler/Spoiler.h" #include "port/Rando/CheckTracker/CheckTracker.h" -// #include "port/Rando/Spoiler/Spoiler.h" extern "C" { enum map_e gsworld_getMap(void); @@ -21,6 +23,8 @@ void Rando::MiscBehavior::OnFileLoad() { Rando::Logic::shuffledPool.clear(); }); + REGISTER_LISTENER(OnGameStart, EVENT_PRIORITY_NORMAL, [](IEvent* event) { ShipInit::Init("IS_RANDO"); }); + REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnSaveLoad* ev = (OnSaveLoad*)event; SaveData* saveData = (SaveData*)ev->saveData; @@ -30,21 +34,34 @@ void Rando::MiscBehavior::OnFileLoad() { if (saveData->magic != 0) { if (saveData->shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { Rando::Logic::GeneratePoolFromSaveData(saveData); - CALL_EVENT(InitRandoEvents); } return; } if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Enable"), 0)) { Rando::Logic::InitializeSaveData(saveData); - Rando::Logic::GenerateShufflePool(saveData); - Rando::Logic::GrantStartingLoadout(); + std::string spoilerPath = CVarGetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), ""); + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("UseExistingLog"), 0) && !spoilerPath.empty()) { + // std::string spoilerPath = CVarGetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), ""); + Rando::Spoiler::GenerateFromSpoiler(Rando::Spoiler::LoadFromFile(spoilerPath.c_str())); + } else { + Rando::Logic::GenerateShufflePool(saveData); + Rando::Logic::GrantStartingLoadout(); + Rando::Logic::GrantFileProgressFlags(); + Rando::Logic::GrantSpiralMountainChecks(); + std::string spoilerName = std::to_string(saveData->shipSaveData.randoSaveData.seedId).c_str(); + std::erase(spoilerName, '-'); + spoilerName += ".json"; + Rando::Spoiler::SaveToFile(spoilerName, Rando::Spoiler::GenerateFromPoolGeneration()); + } + saveData->shipSaveData.fileType = FILE_TYPE_SAVE_RANDO; saveData->shipSaveData.fileCreatedAt = GetUnixTimestamp(); - CALL_EVENT(InitRandoEvents); } }); + REGISTER_LISTENER(OnGameStart, EVENT_PRIORITY_NORMAL, [](IEvent* event) { CALL_EVENT(InitRandoEvents); }); + REGISTER_LISTENER(OnLoadFileSelect, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnLoadFileSelect* ev = (OnLoadFileSelect*)event; diff --git a/src/port/Rando/MiscBehavior/WorldState.cpp b/src/port/Rando/MiscBehavior/WorldState.cpp index ab26bea2a..e42d8c144 100644 --- a/src/port/Rando/MiscBehavior/WorldState.cpp +++ b/src/port/Rando/MiscBehavior/WorldState.cpp @@ -5,17 +5,7 @@ #include "spdlog/spdlog.h" #include "enums.h" -extern "C" { -s32 getGameMode(void); -void mapSpecificFlags_set(s32 i, s32 val); -s32 mapSpecificFlags_get(s32 i); - -enum map_e gsworld_getMap(void); -enum level_e map_getLevel(enum map_e map); - -Struct70s* func_8034C5AC(s32 arg0); -void func_8034E71C(Struct73s* arg0, s32 arg1, f32 arg2); -} +#include "functions.h" // These read per-file save data, so they must not be evaluated before a file is selected. #define EMPTY_HONEYCOMB_OPTION_ENABLED \ @@ -41,8 +31,8 @@ void Rando::StaticData::ModifyRandoInfFlagState(RandoCheckId randoCheckId) { break; case RC_GV_JIGGY_WATER_PYRAMID: case RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_WATER_PYRAMID].obtained && - RANDO_SAVE_CHECKS[RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID].obtained) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_WATER_PYRAMID].eligible && + RANDO_SAVE_CHECKS[RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID].eligible) { randoInfFlag = RANDO_INF_WATER_PYRAMID_DRAINED; } break; @@ -106,18 +96,18 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { switch (currentLevel) { case LEVEL_1_MUMBOS_MOUNTAIN: - if (RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained) { + if (RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible) { if (ev->actorId == ACTOR_F_CHIMPY) { event->Cancelled = true; ev->result = NULL; } } mapSpecificFlags_set(MM_SPECIFIC_FLAG_0_CHIMPY_STUMP_RAISED, - RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained); + RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible); mapSpecificFlags_set(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED, - RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained); + RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible); mapSpecificFlags_set(MM_SPECIFIC_FLAG_3_CHIMPY_HAS_LEFT, - RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained); + RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible); break; case LEVEL_3_CLANKERS_CAVERN: if (currentMap == MAP_22_CC_INSIDE_CLANKER && @@ -127,11 +117,11 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { break; case LEVEL_9_RUSTY_BUCKET_BAY: if (ev->actorId == 0x18F) { - mapSpecificFlags_set(0, RANDO_SAVE_CHECKS[RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE].obtained); + mapSpecificFlags_set(0, RANDO_SAVE_CHECKS[RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE].eligible); } break; case LEVEL_A_MAD_MONSTER_MANSION: - if (ev->actorId == ACTOR_39_NAPPER && RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].obtained) { + if (ev->actorId == ACTOR_39_NAPPER && RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].eligible) { event->Cancelled = true; ev->result = NULL; } @@ -165,7 +155,7 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (currentMap == MAP_26_MMM_NAPPERS_ROOM && randoSaveCheck.randoCheckId != RC_MMM_JIGGY_MANSION_TABLE) { event->Cancelled = true; - ev->result = RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].obtained; + ev->result = RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].eligible; break; } } @@ -179,13 +169,20 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (ev->jiggyId == JIGGY_2E_FP_PRESENTS) { if (currenLevel == LEVEL_5_FREEZEEZY_PEAK) { event->Cancelled = true; - ev->result = RANDO_SAVE_CHECKS[RC_FP_JIGGY_IGLOO].obtained; + ev->result = RANDO_SAVE_CHECKS[RC_FP_JIGGY_IGLOO].eligible; + break; + } + } + if (ev->jiggyId == JIGGY_37_LAIR_BGS_WITCH_SWITCH) { + if (currenLevel == LEVEL_6_LAIR) { + event->Cancelled = true; + ev->result = RANDO_SAVE_CHECKS[RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP].eligible; break; } } event->Cancelled = true; - ev->result = randoSaveCheck.obtained; + ev->result = randoSaveCheck.eligible; break; } } @@ -205,13 +202,29 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (randoCheckId == RC_MMM_JIGGY_TUMBLARS_PUZZLE) { ev->result = mapSpecificFlags_get(MMM_SPECIFIC_FLAG_TUMBLAR_BROKEN); } else if (randoCheckId == RC_CC_JIGGY_CLANKER_RAISED) { - ev->result = RANDO_SAVE_FLAGS[RANDO_INF_CLANKER_RAISED].flagState; + // Clanker's height and his rings' water level are both recalled from + // this query, so it has to answer for the world event and not just + // for a reward still sitting in the level. + ev->result = RANDO_SAVE_FLAGS[RANDO_INF_CLANKER_RAISED].flagState || + CustomObject::CheckSpawnedIdList(randoCheckId); + } else if (randoCheckId == RC_CC_JIGGY_RINGS) { + ev->result = RANDO_SAVE_FLAGS[RANDO_INF_MINIGAME_RINGS_COMPLETED].flagState || + CustomObject::CheckSpawnedIdList(randoCheckId); } else { - ev->result = CustomObject::CheckSpawnedIdList(randoCheckId); + ev->result = CustomObject::CheckSpawnedIdList(randoCheckId) || RANDO_SAVE_CHECKS[randoCheckId].eligible; } } }) + // Drop the id-keyed requirement for the MMM floorboard honeycomb (marker.c) + COND_VB_SHOULD(VB_HONEYCOMB_PUMPKIN_REQUIREMENT, EVENT_PRIORITY_NORMAL, true, { + (void)args; + if (!IS_RANDO || !EMPTY_HONEYCOMB_OPTION_ENABLED) { + return; + } + *should = false; + }) + REGISTER_LISTENER(OnIsHoneycombScoreCollected, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnIsHoneycombScoreCollected* ev = (OnIsHoneycombScoreCollected*)event; @@ -236,7 +249,7 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (ev->honeycombId == HONEYCOMB_17_SM_COLLIWOBBLE) { ev->result = false; } else { - ev->result = saveCheck.obtained; + ev->result = saveCheck.eligible; } break; @@ -264,7 +277,7 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (saveCheck.randoCollectionId == ev->tokenId) { event->Cancelled = true; - ev->result = saveCheck.obtained; + ev->result = saveCheck.eligible; break; } } diff --git a/src/port/Rando/ObjectBehavior/BlueEgg.cpp b/src/port/Rando/ObjectBehavior/BlueEgg.cpp new file mode 100644 index 000000000..7d55692d7 --- /dev/null +++ b/src/port/Rando/ObjectBehavior/BlueEgg.cpp @@ -0,0 +1,40 @@ +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" + +#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_BLUE_EGGS].optionValue + +bool OverrideBlueEggSpawn(s16 spawnPosition[3], int32_t propAsset) { + if (propAsset != ASSET_6D7_SPRITE_BLUE_EGGS) { + return false; + } + + s32 position[3] = { spawnPosition[0], spawnPosition[1], spawnPosition[2] }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); + + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } + + // Let vanilla blue eggs spawn after check has been obtained. + if (Rando::Logic::IsCheckObtained(randoCheckId)) { + return false; + } + + CustomCollectible::QueueProp(position, randoCheckId); + return true; +} + +void RegisterRandoBlueEggs() { + COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { + s16* spawnPosition = va_arg(args, s16*); + int32_t propAsset = va_arg(args, int32_t); + bool replaceEgg = OverrideBlueEggSpawn(spawnPosition, propAsset); + if (replaceEgg) { + *should = true; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterRandoBlueEggs, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Boggy.cpp b/src/port/Rando/ObjectBehavior/Boggy.cpp index 8634b420b..613d96c15 100644 --- a/src/port/Rando/ObjectBehavior/Boggy.cpp +++ b/src/port/Rando/ObjectBehavior/Boggy.cpp @@ -20,7 +20,7 @@ void Rando::ObjectBehavior::ModifyBoggyBehavior(void* boggyActor) { switch (actor->actor_info->actorId) { case ACTOR_160_BOGGY_1: case ACTOR_181_SCARF_SLED: - if (RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].obtained) { + if (RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].eligible) { marker_despawn(actor->marker); if (actor->actor_info->actorId == ACTOR_160_BOGGY_1) { func_80387760(actor->marker); @@ -28,12 +28,12 @@ void Rando::ObjectBehavior::ModifyBoggyBehavior(void* boggyActor) { } break; case ACTOR_C8_BOGGY_2: - if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].obtained) { + if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].eligible) { marker_despawn(actor->marker); } break; case 0x33D: - if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_BOGGY_RACE_2].obtained) { + if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_BOGGY_RACE_2].eligible) { marker_despawn(actor->marker); } break; diff --git a/src/port/Rando/ObjectBehavior/Bundle.cpp b/src/port/Rando/ObjectBehavior/Bundle.cpp index 6f7806343..739359c51 100644 --- a/src/port/Rando/ObjectBehavior/Bundle.cpp +++ b/src/port/Rando/ObjectBehavior/Bundle.cpp @@ -1,572 +1,551 @@ #include "ObjectBehavior.h" #include "port/Rando/Logic/Logic.h" #include "port/Rando/CustomObject/CustomObject.h" - -#include -#include "port/UI/cvar_prefixes.h" -#include -#include "port/Enhancements/Events/PortEnhancements.h" #include "port/Enhancements/Events/Hooks/Events.h" -#include "spdlog/spdlog.h" + +#include "port/ShipInit.hpp" +#include "port/Rando/CustomCollectible/CustomCollectible.h" extern "C" { extern f32 gBundle_yaw; - bool fileProgressFlag_get(enum file_progress_e index); -void marker_despawn(ActorMarker* marker); } -bool applyCustomPhysics = false; -std::vector bundleDespawnQueue; +typedef struct { + RandoCheckId randoCheckId; + bool customPhysics; +} RandoBundleInfo; + int32_t vileCount = 0; -void Rando::ObjectBehavior::DespawnCollectedBundles() { - if (bundleDespawnQueue.empty()) { - return; - } +RandoBundleInfo IdentifyBundle(bundle_e bundleId, BundleInfo* bundleInfo, s32 bundleCount, f32 spawnPosition[3]) { + map_e currentMap = gsworld_getMap(); + level_e currentLevel = map_getLevel(currentMap); + s32 position[3] = { (int32_t)spawnPosition[0], (int32_t)spawnPosition[1], (int32_t)spawnPosition[2] }; + RandoBundleInfo randoBundleInfo; + randoBundleInfo.randoCheckId = RC_UNKNOWN; + randoBundleInfo.customPhysics = false; - for (auto& bundle : bundleDespawnQueue) { - marker_despawn(bundle); + switch (currentLevel) { + case LEVEL_1_MUMBOS_MOUNTAIN: + switch (bundleId) { + case BUNDLE_0_MM_HUT_MUSIC_NOTE: + randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_MM_NOTE_HUT_BUNDLE_1 + bundleCount); + randoBundleInfo.customPhysics = true; + break; + case BUNDLE_1_MM_HUT_BLUE_EGG: + randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_MM_BLUE_EGG_HUT_BUNDLE_1 + bundleCount); + randoBundleInfo.customPhysics = true; + break; + case BUNDLE_3_MM_HUT_JINJO_GREEN: + randoBundleInfo.randoCheckId = RC_MM_JINJO_GREEN; + randoBundleInfo.customPhysics = true; + break; + case BUNDLE_4_MM_HUT_JIGGY: + if (position[1] < 2000) { + randoBundleInfo.randoCheckId = RC_MM_JIGGY_ORANGE_PADS; + } else { + randoBundleInfo.randoCheckId = RC_MM_JIGGY_HUTS; + randoBundleInfo.customPhysics = true; + } + break; + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoBundleInfo.randoCheckId = RC_MM_EXTRA_LIFE_HUT; + randoBundleInfo.customPhysics = true; + break; + case BUNDLE_7__JIGGY: + randoBundleInfo.randoCheckId = RC_MM_JIGGY_CHIMPY; + break; + case BUNDLE_10__JIGGY: + randoBundleInfo.randoCheckId = RC_MM_JIGGY_JUJU; + break; + case BUNDLE_15__JIGGY: + randoBundleInfo.randoCheckId = RC_MM_JIGGY_CONGA; + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 400) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1 + bundleCount); + } else { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_2_TREASURE_TROVE_COVE: + switch (bundleId) { + case BUNDLE_4_MM_HUT_JIGGY: + randoBundleInfo.randoCheckId = RC_TTC_JIGGY_RED_X; + break; + case BUNDLE_7__JIGGY: + randoBundleInfo.randoCheckId = RC_TTC_JIGGY_BLUBBER; + break; + default: + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 900 && position[1] > 890) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1 + bundleCount); + } else if (position[1] < 1770 && position[1] > 1765) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1 + bundleCount); + } else if (position[1] < 1910 && position[1] > 1905) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1 + bundleCount); + } else if (position[1] < 875 && position[1] > 870) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1 + bundleCount); + } + break; + } + break; + case LEVEL_3_CLANKERS_CAVERN: + switch (bundleId) { + case BUNDLE_10__JIGGY: + switch (position[1]) { + case 1536: + randoBundleInfo.randoCheckId = RC_CC_JIGGY_TOOTH; + break; + default: + randoBundleInfo.randoCheckId = RC_CC_JIGGY_RINGS; + break; + } + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 1405 && position[1] > 1395) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1 + bundleCount); + } else if (position[1] < 5495 && position[1] > 5490) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1 + bundleCount); + } else if (position[1] < 3820 && position[1] > 3810) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_4_BUBBLEGLOOP_SWAMP: + switch (bundleId) { + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_BGS_EXTRA_LIFE_MR_VILE_1 + vileCount); + vileCount++; + randoBundleInfo.customPhysics = true; + if (vileCount >= 3) { + vileCount = 0; + } + break; + case BUNDLE_7__JIGGY: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_CROCTUS; + break; + case BUNDLE_8__JIGGY: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_MR_VILE; + break; + case BUNDLE_9__JIGGY: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_TANKTUP; + break; + case BUNDLE_B_BGS_HUT_MUSIC_NOTE: + randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_BGS_NOTE_HUT_BUNDLE_1 + bundleCount); + break; + case BUNDLE_C_BGS_HUT_JIGGY: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_HUTS; + break; + case BUNDLE_10__JIGGY: + switch (position[2]) { + case 49: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_ELEVATED_WALKWAY; + break; + case -1386: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_FLIBBITS; + break; + case 2799: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_PINKEGG; + break; + case -1020: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_TIPTUP; + break; + case -6148: + randoBundleInfo.randoCheckId = RC_BGS_JIGGY_MAZE; + break; + default: + break; + } + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 1260 && position[1] > 1250) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1 + bundleCount); + } else if (position[1] < 1160 && position[1] > 1150) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1 + bundleCount); + } else if (position[0] < 4390 && position[0] > 4385) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1 + bundleCount); + } else if (position[0] < 2565 && position[0] > 2560) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_5_FREEZEEZY_PEAK: + switch (bundleId) { + case BUNDLE_9__JIGGY: + randoBundleInfo.randoCheckId = RC_FP_JIGGY_SLED_TO_BOGGY; + break; + case BUNDLE_10__JIGGY: + if (position[1] > 1900) { + randoBundleInfo.randoCheckId = RC_FP_JIGGY_BOGGY_RACE_1; + } else if (position[1] < 850) { + randoBundleInfo.randoCheckId = RC_FP_JIGGY_WOZZA; + } + break; + case BUNDLE_7__JIGGY: + randoBundleInfo.randoCheckId = RC_FP_JIGGY_BOGGY_RACE_2; + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 820 && position[1] > 810) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1 + bundleCount); + } else if (position[1] < 590 && position[1] > 580) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1 + bundleCount); + } else if (position[1] < 1755 && position[1] > 1745) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1 + bundleCount); + } else if (position[1] < 5760 && position[1] > 5750) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_6_LAIR: + switch (bundleId) { + case BUNDLE_C_BGS_HUT_JIGGY: + if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN].posY) { + randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN; + break; + } + if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY].posY) { + randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY; + break; + } + if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD].posY) { + randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD; + break; + } + if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN].posY) { + randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN; + break; + } + break; + case BUNDLE_10__JIGGY: + if (fileProgressFlag_get(FILEPROG_1A_TTC_WITCH_SWITCH_JIGGY_PRESSED) && + gsworld_getMap() == MAP_6D_GL_TTC_LOBBY) { + randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE; + auto spawnTuple = Rando::StaticData::multiSpawnCheckMap.at(randoBundleInfo.randoCheckId); + position[0] = std::get<0>(spawnTuple); + position[1] = std::get<1>(spawnTuple); + position[2] = std::get<2>(spawnTuple); + } else { + randoBundleInfo.customPhysics = true; + randoBundleInfo.randoCheckId = + Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); + } + break; + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_69_GL_MM_LOBBY: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1 + bundleCount); + break; + case MAP_6D_GL_TTC_LOBBY: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1 + bundleCount); + break; + case MAP_6F_GL_FP_LOBBY: + if (position[1] < 295 && position[1] > 285) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1 + + bundleCount); + } else if (position[1] < 255 && position[1] > 245) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1 + + bundleCount); + } + break; + case MAP_70_GL_CC_LOBBY: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1 + bundleCount); + break; + case MAP_71_GL_STATUE_ROOM: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1 + + bundleCount); + break; + case MAP_72_GL_BGS_LOBBY: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1 + bundleCount); + break; + case MAP_75_GL_MMM_LOBBY: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1 + bundleCount); + break; + case MAP_78_GL_RBB_AND_MMM_PUZZLE: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1 + bundleCount); + break; + case MAP_79_GL_CCW_LOBBY: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1 + bundleCount); + break; + } + break; + default: + break; + } + break; + case LEVEL_7_GOBIS_VALLEY: + switch (bundleId) { + case BUNDLE_10__JIGGY: + randoBundleInfo.randoCheckId = + Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); + break; + case BUNDLE_D__EMPTY_HONEYCOMB: + randoBundleInfo.randoCheckId = RC_GV_EMPTY_HONEYCOMB_GOBI; + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 2990 && position[1] > 2980) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1 + bundleCount); + } else if (position[1] < 1990 && position[1] > 1980) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1 + bundleCount); + } else if (position[1] < 610 && position[1] > 600) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_8_CLICK_CLOCK_WOOD: + switch (bundleId) { + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_40_CCW_HUB: + if (position[1] < 150 && position[1] > 140) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1 + + bundleCount); + } + break; + case MAP_43_CCW_SPRING: + if (position[0] < 5 && position[0] > -5) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1 + + bundleCount); + } else if (position[0] < -1545 && position[0] > -1555) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[0] < 4345 && position[0] > 4340) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_44_CCW_SUMMER: + if (position[1] < -440 && position[1] > -450) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[1] < 4580 && position[1] > 4570) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1 + + bundleCount); + } + break; + case MAP_45_CCW_AUTUMN: + if (position[1] < 1435 && position[1] > 1425) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[1] < 4405 && position[1] > 4395) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_46_CCW_WINTER: + if (position[1] < 1060 && position[1] > 1050) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1 + + bundleCount); + } else if (position[1] < 4405 && position[1] > 4395) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_4D_CCW_WINTER_MUMBOS_SKULL: + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1 + + bundleCount); + break; + } + default: + break; + } + break; + case LEVEL_9_RUSTY_BUCKET_BAY: + switch (bundleId) { + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoBundleInfo.randoCheckId = RC_RBB_EXTRA_LIFE_BOOM_BOXES; + randoBundleInfo.customPhysics = true; + break; + case BUNDLE_18__HONEYCOMB: + if (position[0] == 0 && position[1] == 156 && position[2] == 4800) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1 + bundleCount); + } else if (position[0] == 0 && position[1] == 156 && position[2] == -178) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1 + bundleCount); + } else if (position[0] == 7850 && position[1] == -1019 && position[2] == 3550) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1 + bundleCount); + } + break; + default: + break; + } + case LEVEL_A_MAD_MONSTER_MANSION: + switch (bundleId) { + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_1C_MMM_CHURCH: + if (position[0] < 1880 && position[0] > 1870) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1 + + bundleCount); + } else if (position[0] < -1870 && position[0] > -1880) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1 + bundleCount); + } + break; + case MAP_1B_MMM_MAD_MONSTER_MANSION: + if (position[1] < 160 && position[1] > 150) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1 + bundleCount); + } else if (position[1] < 335 && position[1] > 325) { + randoBundleInfo.randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1 + bundleCount); + } + break; + default: + break; + } + break; + default: + break; + } + break; + case LEVEL_B_SPIRAL_MOUNTAIN: + switch (bundleId) { + case BUNDLE_1F_SM_EMPTY_HONEYCOMB: + if (position[1] >= 500 && position[1] <= 800) { + randoBundleInfo.randoCheckId = RC_SM_EMPTY_HONEYCOMB_COLLIWOBBLE; + } else { + randoBundleInfo.randoCheckId = RC_SM_EMPTY_HONEYCOMB_QUARRIES; + } + break; + case BUNDLE_18__HONEYCOMB: + break; + default: + break; + } + break; + default: + return randoBundleInfo; } - bundleDespawnQueue.clear(); + return randoBundleInfo; } -void Rando::ObjectBehavior::InitBundleBehavior() { - COND_HOOK(ClearBundleDespawnQueue, EVENT_PRIORITY_NORMAL, IS_RANDO, - [](IEvent* event) { bundleDespawnQueue.clear(); }) +bool OverrideBundleSpawn(bundle_e bundleId, BundleInfo* bundleInfo, s32 bundleCount, f32 spawnPosition[3]) { + + s32 position[3] = { (int32_t)spawnPosition[0], (int32_t)spawnPosition[1], (int32_t)spawnPosition[2] }; + + if (bundleId == BUNDLE_16__HONEYCOMB && + (gsworld_getMap() == MAP_43_CCW_SPRING || gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN)) { + if (CheckEnemyOverlapPosition(position)) { + return false; + } + } + + RandoBundleInfo randoBundleInfo = IdentifyBundle(bundleId, bundleInfo, bundleCount, spawnPosition); + if (randoBundleInfo.randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoBundleInfo.randoCheckId)) { + return false; + } + + if (Rando::Logic::IsCheckObtained(randoBundleInfo.randoCheckId)) { + bool isConsumable = bundleInfo->actor_id == ACTOR_52_BLUE_EGG || bundleInfo->actor_id == ACTOR_50_HONEYCOMB; + return !isConsumable; + } + + Actor* actor = CustomCollectible::Spawn(position, randoBundleInfo.randoCheckId); + if (randoBundleInfo.customPhysics) { + ApplyCustomActorPhysics(randoBundleInfo.randoCheckId, actor, false); + } else { + ApplyBundleActorPhysics(actor, bundleId, (BundleInfo*)bundleInfo, gBundle_yaw); + } + + return true; +} + +void RegisterRandoBundles() { COND_VB_SHOULD(VB_BUNDLE_SPAWN_SET_ACTOR_DATA, EVENT_PRIORITY_NORMAL, IS_RANDO, { Actor* refActor = va_arg(args, Actor*); - if (refActor == NULL) { *should = true; } - }) + }); COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO, { bundle_e bundleId = (bundle_e)va_arg(args, int); BundleInfo* bundleInfo = va_arg(args, BundleInfo*); s32 bundleCount = va_arg(args, s32); f32* position = va_arg(args, f32*); - Actor** actor = va_arg(args, Actor**); - map_e currentMap = gsworld_getMap(); - level_e currentLevel = map_getLevel(currentMap); - - int32_t spawnPosition[3]; - spawnPosition[0] = (int32_t)position[0]; - spawnPosition[1] = (int32_t)position[1]; - spawnPosition[2] = (int32_t)position[2]; - - SPDLOG_INFO("Bundle ID: {} :: {}, {}, {}", (int32_t)bundleId, spawnPosition[0], spawnPosition[1], spawnPosition[2]); - - if (bundleId == BUNDLE_16__HONEYCOMB && - (currentMap == MAP_43_CCW_SPRING || currentMap == MAP_B_CC_CLANKERS_CAVERN)) { - if (CheckEnemyOverlapPosition(spawnPosition)) { - *should = false; - return; - } - } - - RandoCheckId randoCheckId = RC_UNKNOWN; - applyCustomPhysics = false; - - switch (currentLevel) { - case LEVEL_1_MUMBOS_MOUNTAIN: - switch (bundleId) { - case BUNDLE_0_MM_HUT_MUSIC_NOTE: - randoCheckId = (RandoCheckId)((int32_t)RC_MM_NOTE_HUT_BUNDLE_1 + bundleCount); - applyCustomPhysics = true; - break; - case BUNDLE_1_MM_HUT_BLUE_EGG: - randoCheckId = (RandoCheckId)((int32_t)RC_MM_BLUE_EGG_HUT_BUNDLE_1 + bundleCount); - applyCustomPhysics = true; - break; - case BUNDLE_3_MM_HUT_JINJO_GREEN: - randoCheckId = RC_MM_JINJO_GREEN; - applyCustomPhysics = true; - break; - case BUNDLE_4_MM_HUT_JIGGY: - if (spawnPosition[1] < 2000) { - randoCheckId = RC_MM_JIGGY_ORANGE_PADS; - } else { - randoCheckId = RC_MM_JIGGY_HUTS; - applyCustomPhysics = true; - } - break; - case BUNDLE_6_MM_HUT_EXTRA_LIFE: - randoCheckId = RC_MM_EXTRA_LIFE_HUT; - applyCustomPhysics = true; - break; - case BUNDLE_7__JIGGY: - randoCheckId = RC_MM_JIGGY_CHIMPY; - break; - case BUNDLE_10__JIGGY: - randoCheckId = RC_MM_JIGGY_JUJU; - break; - case BUNDLE_15__JIGGY: - randoCheckId = RC_MM_JIGGY_CONGA; - break; - case BUNDLE_18__HONEYCOMB: - if (spawnPosition[1] < 400) { - randoCheckId = - (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1 + bundleCount); - } else { - randoCheckId = - (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_2_TREASURE_TROVE_COVE: - switch (bundleId) { - case BUNDLE_4_MM_HUT_JIGGY: - randoCheckId = RC_TTC_JIGGY_RED_X; - break; - case BUNDLE_7__JIGGY: - randoCheckId = RC_TTC_JIGGY_BLUBBER; - break; - default: - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 900 && position[1] > 890) { - randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1 + bundleCount); - } else if (position[1] < 1770 && position[1] > 1765) { - randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1 + bundleCount); - } else if (position[1] < 1910 && position[1] > 1905) { - randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1 + bundleCount); - } else if (position[1] < 875 && position[1] > 870) { - randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1 + bundleCount); - } - break; - } - break; - case LEVEL_3_CLANKERS_CAVERN: - switch (bundleId) { - case BUNDLE_10__JIGGY: - switch (spawnPosition[1]) { - case 1536: - randoCheckId = RC_CC_JIGGY_TOOTH; - break; - default: - randoCheckId = RC_CC_JIGGY_RINGS; - break; - } - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 1405 && position[1] > 1395) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1 + bundleCount); - } else if (position[1] < 5495 && position[1] > 5490) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1 + bundleCount); - } else if (position[1] < 3820 && position[1] > 3810) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_4_BUBBLEGLOOP_SWAMP: - switch (bundleId) { - case BUNDLE_6_MM_HUT_EXTRA_LIFE: - randoCheckId = (RandoCheckId)((int32_t)RC_BGS_EXTRA_LIFE_MR_VILE_1 + vileCount); - vileCount++; - applyCustomPhysics = true; - if (vileCount >= 3) { - vileCount = 0; - } - break; - case BUNDLE_7__JIGGY: - randoCheckId = RC_BGS_JIGGY_CROCTUS; - break; - case BUNDLE_8__JIGGY: - randoCheckId = RC_BGS_JIGGY_MR_VILE; - break; - case BUNDLE_9__JIGGY: - randoCheckId = RC_BGS_JIGGY_TANKTUP; - break; - case BUNDLE_B_BGS_HUT_MUSIC_NOTE: - randoCheckId = (RandoCheckId)((int32_t)RC_BGS_NOTE_HUT_BUNDLE_1 + bundleCount); - break; - case BUNDLE_C_BGS_HUT_JIGGY: - randoCheckId = RC_BGS_JIGGY_HUTS; - break; - case BUNDLE_10__JIGGY: - switch (spawnPosition[2]) { - case 49: - randoCheckId = RC_BGS_JIGGY_ELEVATED_WALKWAY; - break; - case -1386: - randoCheckId = RC_BGS_JIGGY_FLIBBITS; - break; - case 2799: - randoCheckId = RC_BGS_JIGGY_PINKEGG; - break; - case -1020: - randoCheckId = RC_BGS_JIGGY_TIPTUP; - break; - case -6148: - randoCheckId = RC_BGS_JIGGY_MAZE; - break; - default: - break; - } - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 1260 && position[1] > 1250) { - randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1 + bundleCount); - } else if (position[1] < 1160 && position[1] > 1150) { - randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1 + bundleCount); - } else if (position[0] < 4390 && position[0] > 4385) { - randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1 + bundleCount); - } else if (position[0] < 2565 && position[0] > 2560) { - randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_5_FREEZEEZY_PEAK: - switch (bundleId) { - case BUNDLE_9__JIGGY: - randoCheckId = RC_FP_JIGGY_SLED_TO_BOGGY; - break; - case BUNDLE_10__JIGGY: - if (spawnPosition[1] > 1900) { - randoCheckId = RC_FP_JIGGY_BOGGY_RACE_1; - } else if (spawnPosition[1] < 850) { - randoCheckId = RC_FP_JIGGY_WOZZA; - } - break; - case BUNDLE_7__JIGGY: - randoCheckId = RC_FP_JIGGY_BOGGY_RACE_2; - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 820 && position[1] > 810) { - randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1 + bundleCount); - } else if (position[1] < 590 && position[1] > 580) { - randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1 + bundleCount); - } else if (position[1] < 1755 && position[1] > 1745) { - randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1 + bundleCount); - } else if (position[1] < 5760 && position[1] > 5750) { - randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1 + bundleCount); - } - break; - } - break; - case LEVEL_6_LAIR: - switch (bundleId) { - case BUNDLE_C_BGS_HUT_JIGGY: - if (spawnPosition[1] == - Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN].posY) { - randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN; - break; - } - if (spawnPosition[1] == - Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY].posY) { - randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY; - break; - } - if (spawnPosition[1] == - Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD].posY) { - randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD; - break; - } - if (spawnPosition[1] == - Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN].posY) { - randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN; - break; - } - break; - case BUNDLE_10__JIGGY: - if (fileProgressFlag_get(FILEPROG_1A_TTC_WITCH_SWITCH_JIGGY_PRESSED) && - gsworld_getMap() == MAP_6D_GL_TTC_LOBBY) { - randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE; - auto spawnTuple = Rando::StaticData::multiSpawnCheckMap.at(randoCheckId); - spawnPosition[0] = std::get<0>(spawnTuple); - spawnPosition[1] = std::get<1>(spawnTuple); - spawnPosition[2] = std::get<2>(spawnTuple); - } else { - applyCustomPhysics = true; - randoCheckId = Rando::StaticData::GetCheckByPosition(spawnPosition[0], spawnPosition[1], - spawnPosition[2]); - } - break; - case BUNDLE_18__HONEYCOMB: - switch (currentMap) { - case MAP_69_GL_MM_LOBBY: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1 + bundleCount); - break; - case MAP_6D_GL_TTC_LOBBY: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1 + bundleCount); - break; - case MAP_6F_GL_FP_LOBBY: - if (position[1] < 295 && position[1] > 285) { - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1 + bundleCount); - } else if (position[1] < 255 && position[1] > 245) { - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1 + bundleCount); - } - break; - case MAP_70_GL_CC_LOBBY: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1 + bundleCount); - break; - case MAP_71_GL_STATUE_ROOM: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1 + bundleCount); - break; - case MAP_72_GL_BGS_LOBBY: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1 + bundleCount); - break; - case MAP_75_GL_MMM_LOBBY: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1 + bundleCount); - break; - case MAP_78_GL_RBB_AND_MMM_PUZZLE: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1 + bundleCount); - break; - case MAP_79_GL_CCW_LOBBY: - randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1 + bundleCount); - break; - } - break; - default: - break; - } - break; - case LEVEL_7_GOBIS_VALLEY: - switch (bundleId) { - case BUNDLE_10__JIGGY: - randoCheckId = - Rando::StaticData::GetCheckByPosition(spawnPosition[0], spawnPosition[1], spawnPosition[2]); - break; - case BUNDLE_D__EMPTY_HONEYCOMB: - randoCheckId = RC_GV_EMPTY_HONEYCOMB_GOBI; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 2990 && position[1] > 2980) { - randoCheckId = - (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1 + bundleCount); - } else if (position[1] < 1990 && position[1] > 1980) { - randoCheckId = - (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1 + bundleCount); - } else if (position[1] < 610 && position[1] > 600) { - randoCheckId = - (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_8_CLICK_CLOCK_WOOD: - switch (bundleId) { - case BUNDLE_18__HONEYCOMB: - switch (currentMap) { - case MAP_40_CCW_HUB: - if (position[1] < 150 && position[1] > 140) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1 + - bundleCount); - } else if (position[1] < 160 && position[1] > 150) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1 + - bundleCount); - } - break; - case MAP_43_CCW_SPRING: - if (position[0] < 5 && position[0] > -5) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1 + - bundleCount); - } else if (position[0] < -1545 && position[0] > -1555) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1 + - bundleCount); - } else if (position[0] < 4345 && position[0] > 4340) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1 + - bundleCount); - } - break; - case MAP_44_CCW_SUMMER: - if (position[1] < -440 && position[1] > -450) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1 + - bundleCount); - } else if (position[1] < 160 && position[1] > 150) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1 + - bundleCount); - } else if (position[1] < 4580 && position[1] > 4570) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1 + - bundleCount); - } - break; - case MAP_45_CCW_AUTUMN: - if (position[1] < 1435 && position[1] > 1425) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1 + - bundleCount); - } else if (position[1] < 160 && position[1] > 150) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1 + - bundleCount); - } else if (position[1] < 4405 && position[1] > 4395) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1 + - bundleCount); - } - break; - case MAP_46_CCW_WINTER: - if (position[1] < 1060 && position[1] > 1050) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1 + - bundleCount); - } else if (position[1] < 4405 && position[1] > 4395) { - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1 + - bundleCount); - } - break; - case MAP_4D_CCW_WINTER_MUMBOS_SKULL: - randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1 + - bundleCount); - break; - } - default: - break; - } - break; - case LEVEL_9_RUSTY_BUCKET_BAY: - switch (bundleId) { - case BUNDLE_6_MM_HUT_EXTRA_LIFE: - randoCheckId = RC_RBB_EXTRA_LIFE_BOOM_BOXES; - applyCustomPhysics = true; - break; - case BUNDLE_18__HONEYCOMB: - if (position[0] == 0 && position[1] == 156 && position[2] == 4800) { - randoCheckId = - (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1 + bundleCount); - } else if (position[0] == 0 && position[1] == 156 && position[2] == -178) { - randoCheckId = - (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1 + bundleCount); - } else if (position[0] == 7850 && position[1] == -1019 && position[2] == 3550) { - randoCheckId = - (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1 + bundleCount); - } - break; - default: - break; - } - case LEVEL_A_MAD_MONSTER_MANSION: - switch (bundleId) { - case BUNDLE_18__HONEYCOMB: - switch (currentMap) { - case MAP_1C_MMM_CHURCH: - if (position[0] < 1880 && position[0] > 1870) { - randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1 + bundleCount); - } else if (position[0] < -1870 && position[0] > -1880) { - randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1 + bundleCount); - } - break; - case MAP_1B_MMM_MAD_MONSTER_MANSION: - if (position[1] < 160 && position[1] > 150) { - randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1 + bundleCount); - } else if (position[1] < 335 && position[1] > 325) { - randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1 + - bundleCount); - } - break; - default: - break; - } - break; - default: - break; - } - break; - case LEVEL_B_SPIRAL_MOUNTAIN: - switch (bundleId) { - case BUNDLE_1F_SM_EMPTY_HONEYCOMB: - if (spawnPosition[1] >= 500 && spawnPosition[1] <= 800) { - randoCheckId = RC_SM_EMPTY_HONEYCOMB_COLLIWOBBLE; - } else { - randoCheckId = RC_SM_EMPTY_HONEYCOMB_QUARRIES; - } - break; - case BUNDLE_18__HONEYCOMB: - break; - default: - break; - } - break; - default: - return; - } - - if (randoCheckId == RC_UNKNOWN) { - return; - } - - if (!Rando::Logic::IsCheckShuffled(randoCheckId)) { - return; - } - - RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; - if (randoSaveCheck.obtained) { - actor_e actorId = (actor_e)Rando::StaticData::Items[randoSaveCheck.randoItemId].actorId; - *actor = - CustomObject::SpawnCustomActorEX(randoCheckId, spawnPosition, &actorInfoMap.at((actor_e)actorId).first, - actorInfoMap.at((actor_e)actorId).second); - - bundleDespawnQueue.push_back((*actor)->marker); - } else { - *actor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, spawnPosition, false); - - if (*actor == NULL) { - *should = true; - return; - } - - if (applyCustomPhysics) { - ApplyCustomActorPhysics(randoCheckId, *actor, false); - } else { - ApplyBundleActorPhysics(*actor, bundleId, (BundleInfo*)bundleInfo, gBundle_yaw); - } + bool replaceBundle = OverrideBundleSpawn(bundleId, bundleInfo, bundleCount, position); + if (replaceBundle) { + *should = true; } - - *should = true; - }) + }); } + +static RegisterShipInitFunc initFunc(RegisterRandoBundles, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp b/src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp new file mode 100644 index 000000000..90a744a80 --- /dev/null +++ b/src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp @@ -0,0 +1,38 @@ +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" + +#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_EMPTY_HONEYCOMBS].optionValue + +bool OverrideEmptyHoneyCombSpawn(OnActorSpawn* ev) { + if (ev->actorId != ACTOR_47_EMPTY_HONEYCOMB) { + return false; + } + + int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); + + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } + + if (!Rando::Logic::IsCheckObtained(randoCheckId)) { + CustomCollectible::Spawn(spawnPosition, randoCheckId); + } + + return true; +} + +void RegisterRandoEmptyHoneyCombs() { + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + + bool replaceEmptyHoneyComb = OverrideEmptyHoneyCombSpawn(ev); + if (replaceEmptyHoneyComb) { + event->Cancelled = true; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterRandoEmptyHoneyCombs, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/ExtraLife.cpp b/src/port/Rando/ObjectBehavior/ExtraLife.cpp new file mode 100644 index 000000000..875e68355 --- /dev/null +++ b/src/port/Rando/ObjectBehavior/ExtraLife.cpp @@ -0,0 +1,38 @@ +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" + +#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUMBO_TOKENS].optionValue + +bool OverrideExtraLifeSpawn(OnActorSpawn* ev) { + if (ev->actorId != ACTOR_49_EXTRA_LIFE) { + return false; + } + + int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); + + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } + + if (!Rando::Logic::IsCheckObtained(randoCheckId)) { + CustomCollectible::Spawn(spawnPosition, randoCheckId); + } + + return true; +} + +void RegisterRandoExtraLifes() { + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + + bool replaceExtraLife = OverrideExtraLifeSpawn(ev); + if (replaceExtraLife) { + event->Cancelled = true; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterRandoExtraLifes, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Gobi.cpp b/src/port/Rando/ObjectBehavior/Gobi.cpp index abf0f6ef1..1ac60ec89 100644 --- a/src/port/Rando/ObjectBehavior/Gobi.cpp +++ b/src/port/Rando/ObjectBehavior/Gobi.cpp @@ -22,12 +22,12 @@ void Rando::ObjectBehavior::ModifyGobiBehavior(void* gobiActor) { case ACTOR_12E_GOBI_1: case ACTOR_12F_GOBI_ROPE: case ACTOR_130_GOBI_ROCK: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].obtained) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].eligible) { marker_despawn(actor->marker); } break; case ACTOR_131_GOBI_2: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].obtained && !RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].obtained) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].eligible && !RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].eligible) { if (actor->state == 1) { chGobi2_setState(actor, 2); actor->marker->collidable = true; @@ -41,7 +41,7 @@ void Rando::ObjectBehavior::ModifyGobiBehavior(void* gobiActor) { } break; case ACTOR_135_GOBI_3: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].obtained) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].eligible) { if (actor->state == 0) { chGobi3_setState(actor, 2); actor->marker->collidable = true; diff --git a/src/port/Rando/ObjectBehavior/Jiggy.cpp b/src/port/Rando/ObjectBehavior/Jiggy.cpp index cc4fc67f8..f473113af 100644 --- a/src/port/Rando/ObjectBehavior/Jiggy.cpp +++ b/src/port/Rando/ObjectBehavior/Jiggy.cpp @@ -1,56 +1,81 @@ #include "ObjectBehavior.h" +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/Hooks/Events.h" #include "port/Rando/Logic/Logic.h" #include "port/Rando/CustomObject/CustomObject.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include "spdlog/spdlog.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue -void Rando::ObjectBehavior::InitJiggyBehavior() { - COND_VB_SHOULD(VB_NAPPER_SET_JIGGY_POSITION, EVENT_PRIORITY_NORMAL, true, { - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } +bool OverrideJiggySpawn(f32 position[3], jiggy_e jiggyId) { + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByJiggyId(jiggyId); - if (RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].obtained) { - *should = false; - } - }) + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } - COND_VB_SHOULD(VB_OVERRIDE_JIGGY_SPAWN, EVENT_PRIORITY_NORMAL, true, { - jiggy_e jiggyId = (jiggy_e)va_arg(args, int); - f32* position = va_arg(args, f32*); + int32_t spawnPosition[3] = { (int32_t)position[0], (int32_t)position[1], (int32_t)position[2] }; - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } + if (jiggyId == JIGGY_26_BGS_TANKTUP) { + spawnPosition[0] -= 300; + spawnPosition[1] += 100; + spawnPosition[2] -= 300; + } - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByJiggyId(jiggyId); + Actor* actor = CustomCollectible::Spawn(spawnPosition, randoCheckId); + if (jiggyId != JIGGY_17_CC_CLANKER_RAISED && jiggyId != JIGGY_1B_CC_TOOTH) { + ApplyCustomActorPhysics(randoCheckId, actor, false); + } + return true; +} - if (randoCheckId == RC_UNKNOWN) { - return; - } +bool OverrideJiggyActorSpawn(OnActorSpawn* ev) { + if (ev->actorId != ACTOR_46_JIGGY) { + return false; + } - if (!Rando::Logic::IsCheckShuffled(randoCheckId)) { - return; + int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); + + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } + + if (Rando::Logic::IsCheckObtained(randoCheckId)) { + return true; + } + + CustomCollectible::Spawn(spawnPosition, randoCheckId); + return true; +} + +void RegisterRandoJiggies() { + COND_VB_SHOULD(VB_NAPPER_SET_JIGGY_POSITION, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { + if (RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].eligible) { + *should = false; } + }); - int32_t spawnPosition[3]; - spawnPosition[0] = (int32_t)position[0]; - spawnPosition[1] = (int32_t)position[1]; - spawnPosition[2] = (int32_t)position[2]; + // Jiggies can be spawned through 2 separate code paths, that's why there's 2 hooks with slight + // variations on how it identifies the jiggy. + COND_VB_SHOULD(VB_OVERRIDE_JIGGY_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { + jiggy_e jiggyId = (jiggy_e)va_arg(args, int); + f32* position = va_arg(args, f32*); - if (jiggyId == JIGGY_26_BGS_TANKTUP) { - spawnPosition[0] -= 300; - spawnPosition[1] += 100; - spawnPosition[2] -= 300; + bool replaceJiggy = OverrideJiggySpawn(position, jiggyId); + if (replaceJiggy) { + *should = true; } + }); - Actor* randoCustomActor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, spawnPosition, false); - if (jiggyId != JIGGY_17_CC_CLANKER_RAISED && jiggyId != JIGGY_1B_CC_TOOTH) { - ApplyCustomActorPhysics(randoCheckId, randoCustomActor, false); + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + + bool replaceJiggy = OverrideJiggyActorSpawn(ev); + if (replaceJiggy) { + event->Cancelled = true; } - *should = true; - }) + }); } + +static RegisterShipInitFunc initFunc(RegisterRandoJiggies, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Jinjo.cpp b/src/port/Rando/ObjectBehavior/Jinjo.cpp index 61764a6bd..3df071888 100644 --- a/src/port/Rando/ObjectBehavior/Jinjo.cpp +++ b/src/port/Rando/ObjectBehavior/Jinjo.cpp @@ -1,12 +1,8 @@ -#include "ObjectBehavior.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomObject/CustomObject.h" - -#include -#include "port/UI/cvar_prefixes.h" -#include -#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/ShipInit.hpp" #include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" +#include "port/Enhancements/Retention/Retention.h" extern "C" { s32 item_adjustByDiffWithHud(enum item_e item, s32 diff); @@ -14,29 +10,48 @@ s32 item_adjustByDiffWithHud(enum item_e item, s32 diff); #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JINJOS].optionValue -void Rando::ObjectBehavior::InitJinjoBehavior() { - COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnSetJiggyList* ev = (OnSetJiggyList*)event; +bool OverrideJinjoSpawn(OnActorSpawn* ev) { + if (ev->actorId != ACTOR_5E_JINJO_YELLOW && ev->actorId != ACTOR_5F_JINJO_ORANGE && + ev->actorId != ACTOR_60_JINJO_BLUE && ev->actorId != ACTOR_61_JINJO_PINK && + ev->actorId != ACTOR_62_JINJO_GREEN) { + return false; + } - for (auto& location : Rando::Logic::shuffledPool) { - if (!location.obtained) { - continue; - } + int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); - Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } - if (randoItem.worldId != ev->levelId) { - continue; - } + if (!Rando::Logic::IsCheckObtained(randoCheckId)) { + CustomCollectible::Spawn(spawnPosition, randoCheckId); + } - if (randoItem.randoItemType == RITYPE_JINJO) { - int32_t jinjoMarkerId = GetJinjoActorMarkerId((actor_e)randoItem.actorId); - item_adjustByDiffWithHud(ITEM_12_JINJOS, (1 << ((jinjoMarkerId + 6) & 0x1F))); - } - } - }) + return true; +} +void RegisterRandoJinjos() { COND_VB_SHOULD(VB_UPDATE_JINJO_HUD, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { *should = true; }) COND_VB_SHOULD(VB_SET_JINJO_COUNT, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { *should = true; }) + + COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnSetJiggyList* ev = (OnSetJiggyList*)event; + u8 bits = collectedBits(ev->levelId); + if (bits != 0) { + item_adjustByDiffWithoutHud(ITEM_12_JINJOS, bits - item_getCount(ITEM_12_JINJOS)); + } + }); + + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + + bool replaceJinjo = OverrideJinjoSpawn(ev); + if (replaceJinjo) { + event->Cancelled = true; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterRandoJinjos, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Molehill.cpp b/src/port/Rando/ObjectBehavior/Molehill.cpp index e7e640f73..cdcea42f4 100644 --- a/src/port/Rando/ObjectBehavior/Molehill.cpp +++ b/src/port/Rando/ObjectBehavior/Molehill.cpp @@ -1,53 +1,17 @@ -#include "ObjectBehavior.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomObject/CustomObject.h" - #include -#include "port/UI/cvar_prefixes.h" -#include -#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/ShipInit.hpp" #include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" -#define MOLETABLE_SIZE 16 #define BRIDGE_REQUIREMENT 6 -typedef struct { - s16 teach_text_id; - s16 refresher_text_id; - s8 camera_node; - s8 ability; -} ChMoleDescription; - extern "C" { -void func_80347A14(s32 arg0); -s32 item_adjustByDiffWithHud(enum item_e item, s32 diff); -void ability_unlock(enum ability_e); s32 mapSpecificFlags_get(s32 i); void mapSpecificFlags_set(s32 i, s32 val); } // clang-format off -ChMoleDescription moleDialogTable[MOLETABLE_SIZE] = { - //{ ASSET_DF3_DIALOG_BOTTLES_INTRODUCTION, ASSET_E08_DIALOG_BOTTLES_FIND_ANOTHER_MOLEHILL, 0x1, -1 }, - { ASSET_DF4_DIALOG_BOTTLES_CAMERA_CONTROL_LEARN, ASSET_DF5_DIALOG_BOTTLES_CAMERA_CONTROL_REFRESHER, 0x3, ABILITY_3_CAMERA_CONTROL }, - { ASSET_DFB_DIALOG_BOTTLES_DIVE_LEARN, ASSET_DFE_DIALOG_BOTTLES_DIVE_REFRESHER, 0x5, ABILITY_F_DIVE }, - { -1, ASSET_E00_DIALOG_BOTTLES_ATTACK_REFRESHER, 0x6, ABILITY_4_CLAW_SWIPE }, - { ASSET_E04_DIALOG_BOTTLES_BEAK_BARGE_LEARN, ASSET_E06_DIALOG_BOTTLES_BEAK_BARGE_REFRESHER, 0x8, ABILITY_0_BARGE }, - { -1, ASSET_DFA_DIALOG_BOTTLES_JUMP_REFRESHER, 0x4, ABILITY_8_FLAP_FLIP }, - { ASSET_E01_DIALOG_BOTTLES_CLIMB_LEARN, ASSET_E03_DIALOG_BOTTLES_CLIMB_REFRESHER, 0x7, ABILITY_5_CLIMB }, - //{ ASSET_E10_DIALOG_BOTTLES_BRIDGE_BROKEN, ASSET_E11_DIALOG_BOTTLES_BRIDGE_STILL_BROKEN, 0x11, -1 }, - { ASSET_C23_DIALOG_BEAKBOMB_LEARN, ASSET_C24_DIALOG_BEAKBOMB_REFRESHER, 0x0F, ABILITY_1_BEAK_BOMB }, - { ASSET_B47_DIALOG_EGGS_LEARN, ASSET_B4B_DIALOG_EGGS_REFRESHER, 0x16, ABILITY_6_EGGS }, - { ASSET_B48_DIALOG_BEAKBUSTER_LEARN, ASSET_B4C_DIALOG_BEAKBUSTER_REFRESHER, 0x17, ABILITY_2_BEAK_BUSTER }, - { ASSET_B49_DIALOG_TALON_TROT_LEARN, ASSET_B4A_DIALOG_TALON_TROT_REFRESHER, 0x18, ABILITY_10_TALON_TROT }, - { ASSET_A1F_DIALOG_SHOCKJUMP_LEARN, ASSET_A23_DIALOG_SHOCKJUMP_REFRESHER, 0x0C, ABILITY_D_SHOCK_JUMP }, - { ASSET_A20_DIALOG_FLY_LEARN, ASSET_A22_DIALOG_FLY_REFRESHER, 0x0D, ABILITY_9_FLIGHT }, - { ASSET_D35_DIALOG_WONDERWING_LEARN, ASSET_D36_DIALOG_WONDERWING_REFRESHER, 0x01, ABILITY_12_WONDERWING }, - { ASSET_C88_DIALOG_WADING_BOOTS_LEARN, ASSET_C89_DIALOG_WADING_BOOTS_REFRESHER, 0x10, ABILITY_E_WADING_BOOTS }, - { ASSET_A84_DIALOG_TURBOTRAINERS_LEARN, ASSET_A85_DIALOG_TURBOTRAINERS_REFRESHER, 0x19, ABILITY_11_TURBO_TALON }, - { ASSET_F64_DIALOG_NOTEDOORS_LEARN, ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, 0x0E, ABILITY_13_1ST_NOTEDOOR }, -}; - std::vector spiralMountainBridge = { RC_SM_MOLEHILL_JUMP, RC_SM_MOLEHILL_CAMERA_CONTROL, @@ -58,27 +22,13 @@ std::vector spiralMountainBridge = { }; // clang-format on -ChMoleDescription result; - #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MOLEHILLS].optionValue -ChMoleDescription GetMoleDescriptionByAbility(int16_t abilityId) { - result.ability = -1; - for (int i = 0; i < MOLETABLE_SIZE; i++) { - if (moleDialogTable[i].ability == abilityId) { - result = moleDialogTable[i]; - break; - } - } - - return result; -} - bool CheckBridgeState() { int32_t smBridgeCheck = 0; if (!mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED)) { for (auto& check : spiralMountainBridge) { - if (Rando::Logic::GetShuffledObject(check).obtained) { + if (RANDO_SAVE_CHECKS[check].eligible) { smBridgeCheck++; } } @@ -87,117 +37,49 @@ bool CheckBridgeState() { return smBridgeCheck == BRIDGE_REQUIREMENT ? true : false; } -void SetSpiralMountainFlags() { - mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); -} - -static void MarkBridgeRepairedDialogComplete() { - CALL_EVENT(SetRandoInfFlag, RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, true); -} - -void Rando::ObjectBehavior::InitMolehillBehavior() { - COND_VB_SHOULD(VB_OVERRIDE_MOLEHILL_ABILITY, EVENT_PRIORITY_NORMAL, true, { - Actor* molehillActor = va_arg(args, Actor*); - s32* textId = va_arg(args, s32*); - s32* isLearned = va_arg(args, s32*); - - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } - - if (molehillActor->actorTypeSpecificField == 8) { - return; - } - - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition( - molehillActor->position_x, molehillActor->position_y, molehillActor->position_z); - - if (randoCheckId == RC_UNKNOWN) { - return; - } - - RandoSaveCheck shuffledMolehill = Rando::Logic::GetShuffledObject(randoCheckId); - ChMoleDescription moleInfo = GetMoleDescriptionByAbility(shuffledMolehill.randoCollectionId); - - if (moleInfo.ability >= ABILITY_0_BARGE) { - *should = true; - - func_80347A14(0); - molehillActor->has_met_before = true; - - switch (moleInfo.ability) { - case ABILITY_4_CLAW_SWIPE: - *textId = (s32)moleInfo.refresher_text_id; - ability_unlock(ABILITY_4_CLAW_SWIPE); - ability_unlock(ABILITY_C_ROLL); - ability_unlock(ABILITY_B_RATATAT_RAP); - break; - case ABILITY_6_EGGS: - *textId = (s32)moleInfo.refresher_text_id; - ability_unlock((ability_e)moleInfo.ability); - item_adjustByDiffWithHud(ITEM_D_EGGS, 50); - break; - case ABILITY_8_FLAP_FLIP: - *textId = (s32)moleInfo.refresher_text_id; - ability_unlock(ABILITY_A_HOLD_A_JUMP_HIGHER); - ability_unlock(ABILITY_7_FEATHERY_FLAP); - ability_unlock(ABILITY_8_FLAP_FLIP); - break; - case ABILITY_9_FLIGHT: - *textId = (s32)moleInfo.refresher_text_id; - ability_unlock((ability_e)moleInfo.ability); - item_adjustByDiffWithHud(ITEM_F_RED_FEATHER, 25); - break; - case ABILITY_12_WONDERWING: - *textId = (s32)moleInfo.refresher_text_id; - ability_unlock((ability_e)moleInfo.ability); - item_adjustByDiffWithHud(ITEM_10_GOLD_FEATHER, 5); - break; - default: - *textId = (s32)moleInfo.refresher_text_id; - ability_unlock((ability_e)moleInfo.ability); - break; - } +bool OverrideMoleSpawn(OnActorSpawn* ev) { + if (ev->actorId != ACTOR_12B_TUTORIAL_BOTTLES && ev->actorId != ACTOR_37A_BOTTLES) { + return false; + } - CustomObject::CheckObtainedEX(shuffledMolehill.randoCheckId); + int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); - if (map_getLevel(gsworld_getMap()) == LEVEL_B_SPIRAL_MOUNTAIN) { - if (CheckBridgeState()) { - SetSpiralMountainFlags(); - } - } - } - }) - - COND_VB_SHOULD(VB_OVERRIDE_BOTTLES_TEXT_CALLBACK, EVENT_PRIORITY_NORMAL, true, { - Actor* molehillActor = va_arg(args, Actor*); + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } + if (Rando::Logic::IsCheckObtained(randoCheckId)) { + return true; + } - if (CheckBridgeState() && !RANDO_SAVE_FLAGS[RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE].flagState) { - *should = true; - } - }) + CustomCollectible::Spawn(spawnPosition, randoCheckId); + return true; +} - COND_HOOK(OnCheckSpiralMountainAbilities, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { +void RegisterRandoMolehills() { + COND_HOOK(OnCheckSpiralMountainAbilities, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { OnCheckSpiralMountainAbilities* ev = (OnCheckSpiralMountainAbilities*)event; - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } - if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED)) { mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, false); } if (CheckBridgeState()) { mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, true); - if (!RANDO_SAVE_FLAGS[RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE].flagState) { - MarkBridgeRepairedDialogComplete(); - } + mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); event->Cancelled = true; ev->result = true; } - }) + }); + + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + + bool replaceMole = OverrideMoleSpawn(ev); + if (replaceMole) { + event->Cancelled = true; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterRandoMolehills, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/MumboToken.cpp b/src/port/Rando/ObjectBehavior/MumboToken.cpp new file mode 100644 index 000000000..1ecbc7a12 --- /dev/null +++ b/src/port/Rando/ObjectBehavior/MumboToken.cpp @@ -0,0 +1,38 @@ +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" + +#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUMBO_TOKENS].optionValue + +bool OverrideMumboTokenSpawn(OnActorSpawn* ev) { + if (ev->actorId != ACTOR_2D_MUMBO_TOKEN) { + return false; + } + + int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); + + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } + + if (!Rando::Logic::IsCheckObtained(randoCheckId)) { + CustomCollectible::Spawn(spawnPosition, randoCheckId); + } + + return true; +} + +void RegisterRandoMumboTokens() { + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + + bool replaceMumboToken = OverrideMumboTokenSpawn(ev); + if (replaceMumboToken) { + event->Cancelled = true; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterRandoMumboTokens, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/MusicNote.cpp b/src/port/Rando/ObjectBehavior/MusicNote.cpp index 24d32b6ee..ec2ec0595 100644 --- a/src/port/Rando/ObjectBehavior/MusicNote.cpp +++ b/src/port/Rando/ObjectBehavior/MusicNote.cpp @@ -1,38 +1,49 @@ -#include "ObjectBehavior.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomObject/CustomObject.h" - -#include -#include "port/UI/cvar_prefixes.h" -#include -#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/ShipInit.hpp" #include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" extern "C" { void item_inc(enum item_e item); +extern u8 D_80385FF0[0xE]; } #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue -void Rando::ObjectBehavior::InitMusicNoteBehavior() { +bool OverrideMusicNoteSpawn(s16 spawnPosition[3], int32_t propAsset) { + if (propAsset != ASSET_6D6_SPRITE_MUSIC_NOTE) { + return false; + } + + s32 position[3] = { spawnPosition[0], spawnPosition[1], spawnPosition[2] }; + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); + + if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { + return false; + } + + if (!Rando::Logic::IsCheckObtained(randoCheckId)) { + CustomCollectible::QueueProp(position, randoCheckId); + } + + return true; +} + +void RegisterRandoMusicNotes() { COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { OnSetJiggyList* ev = (OnSetJiggyList*)event; - int32_t currentNotes = 0; - for (auto& location : Rando::Logic::shuffledPool) { - Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; + item_set(ITEM_C_NOTE, D_80385FF0[ev->levelId]); + }); - if (randoItem.worldId != ev->levelId) { - continue; - } - - if (randoItem.randoItemType == RITYPE_MUSIC_NOTE) { - if (location.obtained) { - currentNotes++; - } - } + COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { + s16* spawnPosition = va_arg(args, s16*); + int32_t propAsset = va_arg(args, int32_t); + bool replaceNote = OverrideMusicNoteSpawn(spawnPosition, propAsset); + if (replaceNote) { + *should = true; } - - item_set(ITEM_C_NOTE, currentNotes); - }) + }); } + +static RegisterShipInitFunc initFunc(RegisterRandoMusicNotes, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index 68f158eaf..2fbb1d0d7 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -13,33 +13,16 @@ #define CVAR_SHOW_COLLISION_NOTIFICATIONS CVarGetInteger(CVAR_NAME_SHOW_COLLISION_NOTIFICATIONS, 0) extern "C" { -void player_getPosition(f32 dst[3]); -Actor* marker_getActor(ActorMarker* thisx); -bool func_802C9C14(Actor* actor); - -s32 mapSpecificFlags_get(s32 i); - -void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume); extern ActorArray* suBaddieActorArray; } -bool isSaveState = false; std::map> randoSaveState; // clang-format off std::vector actorSpawnWhitelist = { - ACTOR_2D_MUMBO_TOKEN, - ACTOR_46_JIGGY, ACTOR_47_EMPTY_HONEYCOMB, ACTOR_49_EXTRA_LIFE, ACTOR_50_HONEYCOMB, - ACTOR_51_MUSIC_NOTE, - ACTOR_52_BLUE_EGG, - ACTOR_5E_JINJO_YELLOW, - ACTOR_5F_JINJO_ORANGE, - ACTOR_60_JINJO_BLUE, - ACTOR_61_JINJO_PINK, - ACTOR_62_JINJO_GREEN, ACTOR_25E_SNS_EGG, ACTOR_25D_ICE_KEY, //ACTOR_12C_MOLEHILL, @@ -96,21 +79,19 @@ std::vector enemyKillOverlapList = { bool nextActorSaveState = false; bool IsActorWhitelisted(int32_t actorId) { - for (auto& entry : actorSpawnWhitelist) { + /*for (auto& entry : actorSpawnWhitelist) { if (entry == actorId) { return true; } } - if (!isSaveState) { - if (CVarGetInteger(Rando::StaticData::Options[RO_SPAWN_JUNK].cvar, 0) == RO_GENERIC_ON) { - for (auto& junk : junkItemList) { - if (junk == actorId) { - return true; - } + if (CVarGetInteger(Rando::StaticData::Options[RO_SPAWN_JUNK].cvar, 0) == RO_GENERIC_ON) { + for (auto& junk : junkItemList) { + if (junk == actorId) { + return true; } } - } + }*/ return false; } @@ -168,47 +149,64 @@ Actor* FindActorByRandoCheckId(RandoCheckId randoCheckId) { return NULL; } +// subject is "You" or a teammate's name for Anchor remote collects. +static void EmitCheckNotification(RandoCheckId randoCheckId, const std::string& subject) { + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; + std::string prefix; + std::string message; + std::string suffix = ""; + ImVec4 itemColor = + WIDGET_TEXT_COLOR(randoItemColors.at((actor_e)Rando::StaticData::Items[randoSaveCheck.randoItemId].actorId)); + RandoItemType itemType = Rando::StaticData::Items[randoSaveCheck.randoItemId].randoItemType; + + if (itemType == RITYPE_MOLEHILL) { + prefix = subject + " learned"; + message = abilityNameList[randoSaveCheck.randoCollectionId].c_str(); + } else if (itemType == RITYPE_SNS_EGG || itemType == RITYPE_SNS_KEY) { + int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); + prefix = subject + " collected "; + prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; + + message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; + suffix = "("; + suffix += std::to_string(totalsnsItems); + suffix += " / 7)"; + + itemColor = WIDGET_TEXT_COLOR(snsItemColors.at(randoSaveCheck.randoCollectionId)); + } else { + prefix = subject + " collected "; + prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; + message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; + } + + Notification::Emit({ + .prefix = prefix, + .prefixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), + .message = message, + .messageColor = itemColor, + .suffix = suffix, + .suffixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), + }); +} + void Rando::StaticData::SendCollisionNotification(RandoCheckId randoCheckId) { if (CVAR_SHOW_COLLISION_NOTIFICATIONS) { - RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; - actor_e actorId = Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId); - std::string prefix; - std::string message; - std::string suffix = ""; - ImVec4 itemColor = WIDGET_TEXT_COLOR(randoItemColors.at(actorId)); - - if (actorId == ACTOR_12C_MOLEHILL) { - prefix = "You learned"; - message = abilityNameList[randoSaveCheck.randoCollectionId].c_str(); - } else if (randoSaveCheck.randoItemId >= RI_STOP_N_SWOP_EGG_BLUE && - randoSaveCheck.randoItemId <= RI_STOP_N_SWOP_ICE_KEY) { - int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); - prefix = "You collected "; - prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; - - message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; - suffix = "("; - suffix += std::to_string(totalsnsItems); - suffix += " / 7)"; - - itemColor = WIDGET_TEXT_COLOR(snsItemColors.at(randoSaveCheck.randoCollectionId)); - } else { - prefix = "You collected "; - prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; - message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; - } - - Notification::Emit({ - .prefix = prefix, - .prefixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), - .message = message, - .messageColor = itemColor, - .suffix = suffix, - .suffixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), - }); + EmitCheckNotification(randoCheckId, "You"); } }; +void Rando::StaticData::SendRemoteCheckNotification(RandoCheckId randoCheckId, const std::string& collectorName) { + EmitCheckNotification(randoCheckId, collectorName); +}; + +bool ShouldOverrideSpawn(RandoCheckId randoCheckId) { + if (Rando::Logic::IsCheckShuffled(randoCheckId)) { + return true; + } + + return false; +} + bool CheckEnemyOverlapPosition(int32_t pos[3]) { level_e levelId = map_getLevel(gsworld_getMap()); bool enemyOverlap = false; @@ -243,12 +241,6 @@ static void FireClearBundleDespawnQueue() { // Entry point for the module, run once on game boot void Rando::ObjectBehavior::Init() { - InitBundleBehavior(); - InitJiggyBehavior(); - InitJinjoBehavior(); - InitMolehillBehavior(); - InitMusicNoteBehavior(); - InitPropBehavior(); InitStopNSwopBehavior(); UpdateJunkList(); @@ -258,7 +250,6 @@ void Rando::ObjectBehavior::Init() { map_e currentMap = gsworld_getMap(); CustomObject::FlushRandoSpawnQueue(); - DespawnCollectedBundles(); if (ev->actorId == ACTOR_12_BEEHIVE) { SPDLOG_INFO("Actor ID: {} {}, {}, {}", ev->actorId, ev->posX, ev->posY, ev->posZ); @@ -266,7 +257,7 @@ void Rando::ObjectBehavior::Init() { if (currentMap == MAP_12_GV_GOBIS_VALLEY) { if (ev->actorId == ACTOR_118_GRABBA) { - event->Cancelled = RANDO_SAVE_CHECKS[RC_GV_JIGGY_GRABBA].obtained; + event->Cancelled = RANDO_SAVE_CHECKS[RC_GV_JIGGY_GRABBA].eligible; ev->result = NULL; } } @@ -316,12 +307,12 @@ void Rando::ObjectBehavior::Init() { COND_HOOK(OnLoadActorSaveState, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { OnLoadActorSaveState* ev = (OnLoadActorSaveState*)event; - isSaveState = true; + // Decide up front whether this restore is ours: anything we don't manage falls + // through to the vanilla restore untouched. The predicate has to be the same one + // the save side recorded under, junk included. if (!IsActorWhitelisted((actor_e)ev->actor->modelCacheIndex)) { - event->Cancelled = true; return; } - isSaveState = false; if (randoSaveState.empty()) { return; @@ -345,12 +336,16 @@ void Rando::ObjectBehavior::Init() { return; } + // The check already has a live actor. Restoring would stack a second one on + // top of it, so drop the restore entirely. if (CustomObject::CheckSpawnedIdList(randoCheckId)) { event->Cancelled = true; return; } - Actor* randoCustomActor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, position, false, ev->actor); + // refActor keeps an obtained check restoring the junk actor it was saved as + // instead of rolling a fresh one. + CustomObject::ShouldCreateCustomActorEX(randoCheckId, position, false, ev->actor); randoSaveState.erase(randoCheckId); event->Cancelled = true; }) diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.h b/src/port/Rando/ObjectBehavior/ObjectBehavior.h index 25221fd9e..c620a504c 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.h +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.h @@ -13,12 +13,6 @@ namespace Rando { namespace ObjectBehavior { void Init(); -void InitBundleBehavior(); -void InitJiggyBehavior(); -void InitJinjoBehavior(); -void InitMolehillBehavior(); -void InitMusicNoteBehavior(); -void InitPropBehavior(); void InitStopNSwopBehavior(); void ModifySwitchBehavior(int32_t switchActorId); @@ -26,7 +20,6 @@ void ModifyGobiBehavior(void* gobiActor); void ModifyBoggyBehavior(void* boggyActor); void ModifyPresentBehavior(void* presentActor); void ModifyStopNSwopWorldBehavior(void* snsActor); -void DespawnCollectedBundles(); } // namespace ObjectBehavior diff --git a/src/port/Rando/ObjectBehavior/Present.cpp b/src/port/Rando/ObjectBehavior/Present.cpp index d8be0600e..da91e939c 100644 --- a/src/port/Rando/ObjectBehavior/Present.cpp +++ b/src/port/Rando/ObjectBehavior/Present.cpp @@ -10,12 +10,25 @@ s32 levelSpecificFlags_get(s32 i); #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue +std::map presentLevelFlagMap = { + { ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE, LEVEL_FLAG_11_FP_UNKNOWN }, + { ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE, LEVEL_FLAG_12_FP_UNKNOWN }, + { ACTOR_1F1_RED_PRESENT_COLLECTIBLE, LEVEL_FLAG_13_FP_UNKNOWN }, +}; + +void GetPresentLevelFlag(Actor* actor, level_flags_e levelFlag) { + if (levelSpecificFlags_get(levelFlag)) { + marker_despawn(actor->marker); + } +} + void Rando::ObjectBehavior::ModifyPresentBehavior(void* presentActor) { if (!IS_RANDO && !OPTION_ENABLED) { return; } Actor* actor = (Actor*)presentActor; + int32_t actorAdjustment = 0; int32_t levelFlag = 0; switch (actor->actor_info->actorId) { @@ -30,10 +43,7 @@ void Rando::ObjectBehavior::ModifyPresentBehavior(void* presentActor) { case ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE: case ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE: case ACTOR_1F1_RED_PRESENT_COLLECTIBLE: - levelFlag = (LEVEL_FLAG_11_FP_UNKNOWN + (actor->actor_info->actorId - ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE)); - if (levelSpecificFlags_get(levelFlag)) { - marker_despawn(actor->marker); - } + GetPresentLevelFlag(actor, presentLevelFlagMap.at((actor_e)actor->actor_info->actorId)); break; default: break; diff --git a/src/port/Rando/ObjectBehavior/Prop.cpp b/src/port/Rando/ObjectBehavior/Prop.cpp deleted file mode 100644 index db6b416b9..000000000 --- a/src/port/Rando/ObjectBehavior/Prop.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "ObjectBehavior.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomObject/CustomObject.h" - -#include -#include "port/UI/cvar_prefixes.h" -#include -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include "spdlog/spdlog.h" - -#define BLUE_EGG_OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_BLUE_EGGS].optionValue -#define MUSIC_NOTE_OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue - -void Rando::ObjectBehavior::InitPropBehavior() { - COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { - s16* spawnPosition = va_arg(args, s16*); - int32_t propAsset = va_arg(args, int32_t); - - if (!IS_RANDO) { - return; - } - - if (!BLUE_EGG_OPTION_ENABLED && propAsset == ASSET_6D7_SPRITE_BLUE_EGGS) { - return; - } - - if (!MUSIC_NOTE_OPTION_ENABLED && propAsset == ASSET_6D6_SPRITE_MUSIC_NOTE) { - return; - } - - int32_t position[3]; - position[0] = spawnPosition[0]; - position[1] = spawnPosition[1]; - position[2] = spawnPosition[2]; - - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); - if (randoCheckId == RC_UNKNOWN) { - *should = false; - return; - } - - if (!Rando::Logic::IsCheckShuffled(randoCheckId)) { - *should = false; - return; - } - - Actor* randoCustomActor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, position, true); - *should = true; - }) -} diff --git a/src/port/Rando/ObjectBehavior/StopNSwop.cpp b/src/port/Rando/ObjectBehavior/StopNSwop.cpp index df6b232d4..335f5cdec 100644 --- a/src/port/Rando/ObjectBehavior/StopNSwop.cpp +++ b/src/port/Rando/ObjectBehavior/StopNSwop.cpp @@ -40,7 +40,7 @@ void Rando::ObjectBehavior::ModifyStopNSwopWorldBehavior(void* snsActor) { void Rando::ObjectBehavior::InitStopNSwopBehavior() { COND_VB_SHOULD(VB_OVERRIDE_SNS_MAP_CHECK, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { *should = true; }) COND_VB_SHOULD(VB_OVERRIDE_TIMED_DIALOGUE, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { - asset_e textId = va_arg(args, asset_e); + asset_e textId = (asset_e)va_arg(args, int); if (textId == ASSET_DB3_DIALOG_SNS_EGG_1_TEXT || textId == ASSET_DB5_DIALOG_ICE_KEY_TEXT || textId == ASSET_DB2_DIALOG_MUMBO_MISTAKE_2) { diff --git a/src/port/Rando/ObjectBehavior/Switch.cpp b/src/port/Rando/ObjectBehavior/Switch.cpp index 619f4979b..c26be158c 100644 --- a/src/port/Rando/ObjectBehavior/Switch.cpp +++ b/src/port/Rando/ObjectBehavior/Switch.cpp @@ -6,13 +6,7 @@ #include "spdlog/spdlog.h" extern "C" { -Actor* actorArray_findActorFromActorId(enum actor_e actor_id); void destroyJiggy(Actor* thisx, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, enum volatile_flags_e arg6); - -s32 mapSpecificFlags_get(s32 i); -void mapSpecificFlags_set(s32 i, s32 val); - -void actor_collisionOff(Actor*); } #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue diff --git a/src/port/Rando/Rando.cpp b/src/port/Rando/Rando.cpp index cee6eb6b4..6dd76de7a 100644 --- a/src/port/Rando/Rando.cpp +++ b/src/port/Rando/Rando.cpp @@ -5,7 +5,7 @@ #include "MiscBehavior/MiscBehavior.h" #include "port/Rando/CheckTracker/CheckTracker.h" // #include "port/Rando/EntranceTracker/EntranceTracker.h" -// #include "port/Rando/Spoiler/Spoiler.h" +#include "port/Rando/Spoiler/Spoiler.h" #include "port/ShipInit.hpp" #include "spdlog/spdlog.h" @@ -23,7 +23,7 @@ void Rando::Init() { fs::create_directory(randomizerFolderPath); } - // Rando::Spoiler::RefreshSpoilerLogs(); + Rando::Spoiler::RefreshSpoilerLogs(); Rando::MiscBehavior::Init(); // Rando::EntranceTracker::Init(); // Ship::Context::GetInstance()->GetFileDropMgr()->RegisterDropHandler(Rando::Spoiler::HandleFileDropped); diff --git a/src/port/Rando/Rando.h b/src/port/Rando/Rando.h index f2897cc38..7d5f7ecb4 100644 --- a/src/port/Rando/Rando.h +++ b/src/port/Rando/Rando.h @@ -22,6 +22,10 @@ extern int16_t selectedFileNum; #define RANDO_SAVE_OPTIONS gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.randoSaveOption #define RANDO_SAVE_FLAGS gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.randoSaveFlag +// Loaded rando file's seed id, or 0 if none. +#define RANDO_SEED \ + (selectedFileNum == DEFAULT_FILE_NUM ? 0 : gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.seedId) + // #define RANDO_SAVE_ENTRANCES(fileNum) gSaveBuffer.files[fileNum]->shipSaveData.randoSaveData.randoSaveEntrances // #define RANDO_EVENTS gSaveContext.save.shipSaveInfo.rando.randoEvents // #define RANDO_STARTING_ITEMS gSaveContext.save.shipSaveInfo.rando.randoStartingItems diff --git a/src/port/Rando/Spoiler/File.cpp b/src/port/Rando/Spoiler/File.cpp new file mode 100644 index 000000000..67bf5f119 --- /dev/null +++ b/src/port/Rando/Spoiler/File.cpp @@ -0,0 +1,72 @@ +#include "Spoiler.h" +#include "port/UI/Notification.h" +#include "ship/Context.h" +#include + +extern std::string CollapsedJSONArray(const nlohmann::ordered_json& jsonFile); + +namespace fs = std::filesystem; + +namespace Rando { + +namespace Spoiler { + +void SaveToFile(const std::string& fileName, nlohmann::ordered_json spoiler) { + std::string testDirectory = Ship::Context::GetPathRelativeToAppDirectory("randomizer/", "bk64"); + std::string filePath = Ship::Context::GetPathRelativeToAppDirectory("randomizer/" + fileName, "bk64"); + + if (!fs::exists(testDirectory)) { + fs::create_directories(testDirectory); + } + + std::ofstream fileStream(filePath); + if (!fileStream.is_open()) { + Notification::Emit( + { .message = "Error: Failed to open spoiler file.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); + return; + } + + std::string collapsedString = CollapsedJSONArray(spoiler); + if (fileStream.is_open()) { + fileStream << collapsedString; + fileStream.close(); + } else { + Notification::Emit( + { .message = "Error: Failed to open save file.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); + } + + fileStream << spoiler.dump(4); + RefreshSpoilerLogs(); +} + +nlohmann::json LoadFromFile(const std::string& fileName) { + nlohmann::json spoiler; + std::string spoilerFilePath = Ship::Context::GetPathRelativeToAppDirectory("randomizer/" + fileName, "bk64"); + std::ifstream fileStream(spoilerFilePath); + + if (!fs::exists(spoilerFilePath)) { + return spoiler; + } + + if (!fileStream.is_open()) { + Notification::Emit( + { .message = "Error: Failed to open spoiler file.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); + return spoiler; + } + + try { + fileStream >> spoiler; + } catch (nlohmann::json::exception& e) { + throw std::runtime_error("Failed to parse spoiler file: " + std::string(e.what())); + } + + if (!spoiler.contains("type") || spoiler["type"] != "LIGHTHOUSE_RANDO_SPOILER") { + throw std::runtime_error("Spoiler file is not a valid spoiler file"); + } + + return spoiler; +} + +} // namespace Spoiler + +} // namespace Rando diff --git a/src/port/Rando/Spoiler/Generate.cpp b/src/port/Rando/Spoiler/Generate.cpp new file mode 100644 index 000000000..c98ce18a8 --- /dev/null +++ b/src/port/Rando/Spoiler/Generate.cpp @@ -0,0 +1,111 @@ +#include "Spoiler.h" +#include +#include "port/Rando/Logic/Logic.h" +#include "port/UI/Notification.h" + +extern void RandoSaveCheck_to_json(nlohmann::json& j, const RandoSaveCheck& randoSaveCheck); +extern RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& randoSaveCheck); + +namespace Rando { + +namespace Spoiler { +nlohmann::ordered_json GenerateFromPoolGeneration() { + nlohmann::ordered_json orderedSpoiler = nlohmann::ordered_json::object(); + + orderedSpoiler["type"] = "LIGHTHOUSE_RANDO_SPOILER"; + orderedSpoiler["seed"] = randoFinalSeed; // TODO: Add once Manual Seed Input is finished. + + orderedSpoiler["options"] = nlohmann::json::object(); + for (auto& optionEntry : RANDO_SAVE_OPTIONS) { + orderedSpoiler["options"][optionEntry.name] = optionEntry.optionValue; + } + + orderedSpoiler["checks"] = nlohmann::json::object(); + + for (auto& checkEntry : RANDO_SAVE_CHECKS) { + nlohmann::json check = nlohmann::json::object(); + RandoSaveCheck_to_json(check, checkEntry); + + if (checkEntry.randoCheckId == RC_UNKNOWN) { + checkEntry.name = "RC_UNKNOWN"; + } + + orderedSpoiler["checks"][checkEntry.name] = check; + } + + orderedSpoiler["loadout"] = nlohmann::json::object(); + + orderedSpoiler["loadout"]["abilities"] = nlohmann::json::array(); + orderedSpoiler["loadout"]["abilities"].push_back(ABILITY_A_HOLD_A_JUMP_HIGHER); + orderedSpoiler["loadout"]["abilities"].push_back(ABILITY_13_1ST_NOTEDOOR); + for (auto& [abilityId, abilityInfo] : abilityLoadoutMap) { + if (CVarGetInteger(abilityInfo.second, 0)) { + orderedSpoiler["loadout"]["abilities"].push_back(abilityId); + } + } + + orderedSpoiler["loadout"]["items"] = nlohmann::json::array(); + for (auto& [item, itemInfo] : itemLoadoutMap) { + if (CVarGetInteger(itemInfo.second, 0)) { + orderedSpoiler["loadout"]["items"].push_back(item); + } + } + + return orderedSpoiler; +} + +void GenerateFromSpoiler(nlohmann::json spoiler) { + Rando::Logic::shuffledPool.clear(); + + if (!spoiler.contains("type") || spoiler["type"] != "LIGHTHOUSE_RANDO_SPOILER") { + Notification::Emit({ .message = "Error: Invalid Spoiler Log.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); + return; + } + + gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.seedId = spoiler["seed"]; + + if (spoiler.contains("checks") && !spoiler["checks"].empty()) { + for (auto& data : spoiler["checks"].items()) { + RandoSaveCheck checkEntry = RandoSaveCheck_from_json(data.value(), checkEntry); + checkEntry.name = Rando::StaticData::Checks[checkEntry.randoCheckId].name; + RANDO_SAVE_CHECKS[checkEntry.randoCheckId] = checkEntry; + + Rando::Logic::shuffledPool.push_back(checkEntry); + } + } + + if (spoiler.contains("options") && !spoiler["options"].empty()) { + for (auto& data : spoiler["options"].items()) { + for (auto& [optionId, staticOption] : Rando::StaticData::Options) { + if (staticOption.name == data.key()) { + RANDO_SAVE_OPTIONS[optionId].optionValue = data.value().get(); + break; + } + } + } + } + + if (spoiler.contains("loadout") && !spoiler["loadout"].empty()) { + if (spoiler["loadout"].contains("abilities") && !spoiler["loadout"]["abilities"].empty()) { + for (auto& data : spoiler["loadout"]["abilities"].items()) { + ability_setLearned(data.value(), true); + ability_setHasUsed(data.value()); + } + } + + if (spoiler["loadout"].contains("items") && !spoiler["loadout"]["items"].empty()) { + for (auto& data : spoiler["loadout"]["items"].items()) { + item_setMaxCount(data.value()); + } + } + } + + Rando::Logic::GrantFileProgressFlags(); + Rando::Logic::GrantSpiralMountainChecks(); + + Notification::Emit({ .message = "Loaded from Spoiler Log.", .messageColor = ImVec4(0, 0.85f, 0, 1) }); +} + +} // namespace Spoiler + +} // namespace Rando diff --git a/src/port/Rando/Spoiler/RefreshOptions.cpp b/src/port/Rando/Spoiler/RefreshOptions.cpp new file mode 100644 index 000000000..6568f9ed0 --- /dev/null +++ b/src/port/Rando/Spoiler/RefreshOptions.cpp @@ -0,0 +1,40 @@ +#include "Spoiler.h" +#include +#include "ship/Context.h" +#include + +#include + +std::vector Rando::Spoiler::spoilerLogs; +const std::filesystem::path randomizerFolderPath(Ship::Context::GetPathRelativeToAppDirectory("randomizer", "bk64")); + +void Rando::Spoiler::RefreshSpoilerLogs() { + Rando::Spoiler::spoilerLogs.clear(); + + Rando::Spoiler::spoilerLogs.push_back("Generate New Seed"); + s32 spoilerFileIndex = -1; + + if (!std::filesystem::exists(randomizerFolderPath)) { + std::filesystem::create_directory(randomizerFolderPath); + } + + for (const auto& entry : std::filesystem::directory_iterator(randomizerFolderPath)) { + if (entry.is_regular_file()) { + std::string fileName = entry.path().filename().string(); + + Rando::Spoiler::spoilerLogs.push_back(fileName); + + // Check if the current file is the one set in the cvar + if (fileName == CVarGetString("gRandoSettings.SpoilerFile", "")) { + spoilerFileIndex = Rando::Spoiler::spoilerLogs.size() - 1; + } + } + } + + if (spoilerFileIndex == -1) { + CVarSetInteger("gRandoSettings.SpoilerFileIndex", 0); + CVarSetString("gRandoSettings.SpoilerFile", ""); + } else { + CVarSetInteger("gRandoSettings.SpoilerFileIndex", spoilerFileIndex); + } +} \ No newline at end of file diff --git a/src/port/Rando/Spoiler/Spoiler.h b/src/port/Rando/Spoiler/Spoiler.h new file mode 100644 index 000000000..272e70f6a --- /dev/null +++ b/src/port/Rando/Spoiler/Spoiler.h @@ -0,0 +1,26 @@ +#ifndef RANDO_SPOILER_H +#define RANDO_SPOILER_H + +#include +#include +#include "port/Rando/Logic/Logic.h" +#include + +namespace Rando { + +namespace Spoiler { +extern std::vector spoilerLogs; + +nlohmann::ordered_json GenerateFromPoolGeneration(); + +void GenerateFromSpoiler(nlohmann::json spoiler); +void SaveToFile(const std::string& fileName, nlohmann::ordered_json spoiler); +nlohmann::json LoadFromFile(const std::string& filePath); + +void RefreshSpoilerLogs(); + +} // namespace Spoiler + +} // namespace Rando + +#endif \ No newline at end of file diff --git a/src/port/Rando/StaticData/Checks.cpp b/src/port/Rando/StaticData/Checks.cpp index 8a23c19b4..9ac508693 100644 --- a/src/port/Rando/StaticData/Checks.cpp +++ b/src/port/Rando/StaticData/Checks.cpp @@ -4,11 +4,6 @@ #include "prop.h" #include "include/core1/sns.h" -extern "C" { -enum map_e gsworld_getMap(void); -enum level_e map_getLevel(enum map_e map); -} - namespace Rando { namespace StaticData { @@ -24,75 +19,75 @@ std::array CheckNames = std::array(); // clang-format off std::map Checks = { RC(RC_UNKNOWN, RCTYPE_UNKNOWN, LEVEL_D_CUTSCENE, RI_UNKNOWN, NULL, 0, 0, 0), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4309, 100, 6025), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4368, 100, 6106), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4428, 100, 6198), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4484, 100, 6296), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4541, 100, 6389), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4133, 1400, -1304), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4208, 1400, -1422), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4343, 1400, -1422), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4412, 1400, -1304), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4342, 1400, -1184), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4207, 1400, -1184), - RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1185, 0, 0), - RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -1189, 0, 0), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 300, 0, -1830), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 150, 0, -1829), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -150, 0, -1832), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -300, 0, -1831), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7873, 1000, -6525), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7591, 1000, -6568), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7309, 1000, -6610), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7017, 1000, -6552), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -6729, 1000, -6507), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1250, -7549), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1350, -7549), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1450, -7549), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1250, 2740), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1350, 2740), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1450, 2740), - RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3209, 150, -253), - RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3403, 150, -761), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5917, 0, 2497), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5705, 0, 2672), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5283, 0, 3047), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5087, 0, 3251), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1813, 0, -2967), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1857, 0, -3096), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1889, 0, -3228), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -404, 0, -1715), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -518, 0, -1728), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -628, 0, -1744), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1497, 0, -3242), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1501, 0, -3121), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1506, 0, -3005), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -635, 0, -1361), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -528, 0, -1380), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -427, 0, -1398), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4592, 0, -3489), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4586, 0, -3710), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4809, 0, -3711), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4814, 0, -3490), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4309, 100, 6025), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4368, 100, 6106), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4428, 100, 6198), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4484, 100, 6296), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4541, 100, 6389), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4133, 1400, -1304), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4208, 1400, -1422), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4343, 1400, -1422), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4412, 1400, -1304), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4342, 1400, -1184), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4207, 1400, -1184), + RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1185, 0, 0), + RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -1189, 0, 0), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 300, 0, -1830), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 150, 0, -1829), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -150, 0, -1832), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -300, 0, -1831), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7873, 1000, -6525), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7591, 1000, -6568), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7309, 1000, -6610), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7017, 1000, -6552), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -6729, 1000, -6507), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3920, 1250, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3920, 1350, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3920, 1450, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 839, 1250, 2740), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 839, 1350, 2740), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 839, 1450, 2740), + RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3209, 150, -253), + RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3403, 150, -761), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5917, 0, 2497), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5705, 0, 2672), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5283, 0, 3047), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5087, 0, 3251), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1813, 0, -2967), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1857, 0, -3096), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1889, 0, -3228), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -404, 0, -1715), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -518, 0, -1728), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -628, 0, -1744), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1497, 0, -3242), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1501, 0, -3121), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1506, 0, -3005), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -635, 0, -1361), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -528, 0, -1380), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -427, 0, -1398), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4592, 0, -3489), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4586, 0, -3710), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4809, 0, -3711), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4814, 0, -3490), RC(RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_7_BGS_MUMBOS, 0, 600, 0), RC(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_8_BGS_TANKTUP, 0, 537, -1157), - RC(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, -4382, 985, 2799), - RC(RC_BGS_EXTRA_LIFE_MR_VILE_1, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_EXTRA_LIFE_MR_VILE_2, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_EXTRA_LIFE_MR_VILE_3, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 7149, 0, -4353), - RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, -4382, 985, 2799), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_1, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_2, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_3, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 7149, 0, -4353), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_BGS_JIGGY_CROCTUS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_22_CROCTUS, 0, 0, 0), RC(RC_BGS_JIGGY_ELEVATED_WALKWAY, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_20_BGS_ELEVATED_WALKWAY, 0, 0, 0), RC(RC_BGS_JIGGY_FLIBBITS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_24_BGS_FLIBBITS, 0, 0, 0), @@ -109,16 +104,16 @@ std::map Checks = { RC(RC_BGS_JINJO_PINK, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, NULL, 5670, 0, -4158), RC(RC_BGS_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, NULL, -1606, 500, 2797), RC(RC_BGS_MOLEHILL_WADING_BOOTS, RCTYPE_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MOLEHILL_WADING_BOOTS, ABILITY_E_WADING_BOOTS, 4297, 100, 6286), - RC(RC_BGS_MUMBO_TOKEN_ALCOVE_ABOVE_YELLOW_FLIBBITS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1B_BGS_ALCOVE_ABOVE_YELLOW_FLIBBITS, 4278, 1400, -1302), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1A_BGS_BEHIND_MUMBOS_SKULL, -6940, 1000, -5838), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1C_BGS_BEHIND_TIPTUP, 0, 0, -1829), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_YELLOW_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_18_BGS_BEHIND_YELLOW_JINJO, -1855, 0, 2835), - RC(RC_BGS_MUMBO_TOKEN_FLOATING_BETWEEN_HUT_AND_CROCTUS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_19_BGS_FLOATING_BETWEEN_HUT_AND_CROCTUS, 6546, 2992, -4697), - RC(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1D_BGS_INSIDE_MR_VILES, 0, 300, -1754), - RC(RC_BGS_MUMBO_TOKEN_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1E_BGS_INSIDE_MUMBOS_SKULL, 0, 0, -450), - RC(RC_BGS_MUMBO_TOKEN_TOP_OF_POLE_NEXT_TO_BIG_EGG, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_17_BGS_TOP_OF_POLE_NEXT_TO_BIG_EGG, -3993, 1055, 1295), - RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_1, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_15_BGS_UNDER_HUT_1, 5049, 0, -5142), - RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_2, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_16_BGS_UNDER_HUT_2, 5347, 0, -5055), + RC(RC_BGS_MUMBO_TOKEN_ALCOVE_ABOVE_YELLOW_FLIBBITS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1B_BGS_ALCOVE_ABOVE_YELLOW_FLIBBITS, 4278, 1400, -1302), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1A_BGS_BEHIND_MUMBOS_SKULL, -6940, 1000, -5838), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1C_BGS_BEHIND_TIPTUP, 0, 0, -1829), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_YELLOW_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_18_BGS_BEHIND_YELLOW_JINJO, -1855, 0, 2835), + RC(RC_BGS_MUMBO_TOKEN_FLOATING_BETWEEN_HUT_AND_CROCTUS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_19_BGS_FLOATING_BETWEEN_HUT_AND_CROCTUS, 6546, 2992, -4697), + RC(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1D_BGS_INSIDE_MR_VILES, 0, 300, -1754), + RC(RC_BGS_MUMBO_TOKEN_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1E_BGS_INSIDE_MUMBOS_SKULL, 0, 0, -450), + RC(RC_BGS_MUMBO_TOKEN_TOP_OF_POLE_NEXT_TO_BIG_EGG, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_17_BGS_TOP_OF_POLE_NEXT_TO_BIG_EGG, -3993, 1055, 1295), + RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_1, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_15_BGS_UNDER_HUT_1, 5049, 0, -5142), + RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_2, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_16_BGS_UNDER_HUT_2, 5347, 0, -5055), RC(RC_BGS_NOTE_ABOVE_MR_VILES_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -912, 347, -3385), RC(RC_BGS_NOTE_ABOVE_MR_VILES_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1073, 318, -3495), RC(RC_BGS_NOTE_ABOVE_MR_VILES_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1247, 405, -3608), @@ -219,64 +214,64 @@ std::map Checks = { RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2921, 93, -513), RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3020, 93, -304), RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3114, 93, -86), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6379, 5087, 2586), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6582, 5047, 2536), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6785, 4876, 2454), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6989, 4703, 2388), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 7194, 4526, 2321), - RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2588, 5456, 2596), - RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2494, 5456, 2556), - RC(RC_CC_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -5274, 3269, -270), - RC(RC_CC_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4937, 3221, -597), - RC(RC_CC_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4492, 3113, -449), - RC(RC_CC_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4392, 3051, -27), - RC(RC_CC_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4722, 3104, 299), - RC(RC_CC_BLUE_EGG_ENTRANCE_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -5159, 3232, 178), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2293, 3662, 2354), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2360, 3662, 2231), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2329, 3662, 2107), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2216, 3662, 2018), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2094, 3662, 1968), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 1970, 3662, 1998), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 1895, 3662, 2117), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -390, -116, 1316), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -476, -192, 480), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -433, -214, -453), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -390, -160, -1300), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 391, -160, -1300), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 434, -214, -453), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 476, -192, 480), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_8, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 389, -116, 1316), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 15075, 3648, -20), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14862, 3649, -17), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14651, 3649, -20), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14437, 3649, -20), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14225, 3649, -20), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2392, 5200), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2293, 5276), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2197, 5350), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2099, 5425), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3854, 1202, -532), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3692, 1202, -356), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3529, 1202, -182), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3369, 1207, -10), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3206, 1202, 165), - RC(RC_CC_BLUE_EGG_YELLOW_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 4271, 5261, -2936), - RC(RC_CC_BLUE_EGG_YELLOW_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3247, 5262, -2842), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6379, 5087, 2586), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6582, 5047, 2536), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6785, 4876, 2454), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6989, 4703, 2388), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 7194, 4526, 2321), + RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2588, 5456, 2596), + RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2494, 5456, 2556), + RC(RC_CC_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -5274, 3269, -270), + RC(RC_CC_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4937, 3221, -597), + RC(RC_CC_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4492, 3113, -449), + RC(RC_CC_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4392, 3051, -27), + RC(RC_CC_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4722, 3104, 299), + RC(RC_CC_BLUE_EGG_ENTRANCE_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -5159, 3232, 178), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2293, 3662, 2354), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2360, 3662, 2231), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2329, 3662, 2107), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2216, 3662, 2018), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2094, 3662, 1968), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 1970, 3662, 1998), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 1895, 3662, 2117), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -390, -116, 1316), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -476, -192, 480), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -433, -214, -453), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -390, -160, -1300), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 391, -160, -1300), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 434, -214, -453), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 476, -192, 480), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_8, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 389, -116, 1316), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 15075, 3648, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14862, 3649, -17), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14651, 3649, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14437, 3649, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14225, 3649, -20), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2392, 5200), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2293, 5276), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2197, 5350), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2099, 5425), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3854, 1202, -532), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3692, 1202, -356), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3529, 1202, -182), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3369, 1207, -10), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3206, 1202, 165), + RC(RC_CC_BLUE_EGG_YELLOW_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 4271, 5261, -2936), + RC(RC_CC_BLUE_EGG_YELLOW_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3247, 5262, -2842), RC(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_6_CC_ABOVE_WATER, 7886, 4272, 1969), RC(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_5_CC_UNDERWATER, 3718, 3311, 2519), - RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 4570, 3727, 2783), - RC(RC_CC_EXTRA_LIFE_JINJO_PIPE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 7309, 4267, 2286), - RC(RC_CC_EXTRA_LIFE_YELLOW_GRATE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 1752, 5270, -2214), - RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE, NULL, 4570, 3727, 2783), + RC(RC_CC_EXTRA_LIFE_JINJO_PIPE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE, NULL, 7309, 4267, 2286), + RC(RC_CC_EXTRA_LIFE_YELLOW_GRATE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE, NULL, 1752, 5270, -2214), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_CC_JIGGY_BOLT, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_18_CC_BOLT, 90, 5962, -12), RC(RC_CC_JIGGY_CLANKER_RAISED, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_17_CC_CLANKER_RAISED, 0, 0, 0), RC(RC_CC_JIGGY_FAST_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1E_CC_FAST_SAWBLADES, 0, -340, -1604), @@ -293,11 +288,11 @@ std::map Checks = { RC(RC_CC_JINJO_PINK, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_PINK_CLANKERS_CAVERN, NULL, 3644, -474, 48), RC(RC_CC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_YELLOW_CLANKERS_CAVERN, NULL, -4726, 5337, -110), RC(RC_CC_MOLEHILL_WONDERWING, RCTYPE_MOLEHILL, LEVEL_3_CLANKERS_CAVERN, RI_MOLEHILL_WONDERWING, ABILITY_12_WONDERWING, -259, -500, 1413), - RC(RC_CC_MUMBO_TOKEN_CHOMPA_BEHIND_CLANKERS_TAIL, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_10_CC_CHOMPA_BEHIND_CLANKERS_TAIL, 9823, 4225, -19), - RC(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE, -9694, 5272, 1607), - RC(RC_CC_MUMBO_TOKEN_TUNNEL_RIGHT_OF_CLANKER, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, 870, 2146, -3148), - RC(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_13_CC_ALCOVE_WITH_OPEN_GRATE, 2028, 5456, 2344), - RC(RC_CC_MUMBO_TOKEN_CLANKERS_LEFT_TOOTH, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_14_CC_CLANKERS_LEFT_TOOTH, 532, 1424, 6632), + RC(RC_CC_MUMBO_TOKEN_CHOMPA_BEHIND_CLANKERS_TAIL, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_10_CC_CHOMPA_BEHIND_CLANKERS_TAIL, 9823, 4225, -19), + RC(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE, -9694, 5272, 1607), + RC(RC_CC_MUMBO_TOKEN_TUNNEL_RIGHT_OF_CLANKER, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, 870, 2146, -3148), + RC(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_13_CC_ALCOVE_WITH_OPEN_GRATE, 2028, 5456, 2344), + RC(RC_CC_MUMBO_TOKEN_CLANKERS_LEFT_TOOTH, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_14_CC_CLANKERS_LEFT_TOOTH, 532, 1424, 6632), RC(RC_CC_NOTE_ABOVE_BOLT_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2036, 5693, -15), RC(RC_CC_NOTE_ABOVE_BOLT_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1533, 5693, 381), RC(RC_CC_NOTE_ABOVE_BOLT_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1043, 5693, 377), @@ -398,164 +393,164 @@ std::map Checks = { RC(RC_CC_NOTE_UNDERWATER_PIPE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6804, 1184, 2361), RC(RC_CC_NOTE_YELLOW_GRATE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2240, 5262, -2473), RC(RC_CC_NOTE_YELLOW_GRATE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5270, 5261, -2937), - RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 825, 758, 531), - RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 682, 758, 583), - RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 536, 758, 628), - RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -113, 304, 3001), - RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 115, 605, 3001), - RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -170, 0, -700), - RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, -20, -630), - RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 170, 0, -699), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1362, 4419, 2014), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1860, 4469, 1580), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2181, 4519, 1118), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5700, 40, -1000), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5500, 40, -500), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5350, 40, 0), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3513, 4102, -541), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3595, 4104, 478), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3615, 2773, 1411), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4356, 2821, 356), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4920, 2778, 1222), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3735, 2828, -787), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4431, 2830, -882), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5370, 2882, -787), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3270, 103, -815), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3483, 109, -341), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3483, 99, 342), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3270, 121, 815), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3930, 4900, 316), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4378, 4900, 764), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5018, 4900, 773), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5468, 4900, 314), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5468, 4900, -315), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5018, 4900, -773), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4378, 4900, -764), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3930, 4900, -315), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 510, 387, 0), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, 398, 520), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, 398, -520), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 472, 413, -237), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 383, 413, -295), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 287, 413, -357), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 975, 900, 2573), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2566, 900, 968), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2568, 900, -968), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1950, 900, -1949), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 975, 900, -2574), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -50, 1050, -2750), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -975, 900, -2575), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2579, 1100, -980), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2579, 900, 980), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -977, 900, 2573), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2140, 2938, -1157), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1696, 3050, -1731), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1072, 3157, -2180), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 790, 3300, -2345), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1427, 3300, -1995), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1873, 3899, -1580), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2267, 3963, -1018), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2450, 4019, -394), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4366, -599, -311), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 5404, -593, -734), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 5831, -589, 301), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4769, -600, 726), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4302, 3719, 583), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4214, 3719, 1076), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3653, 3719, 1587), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3080, 3719, 2063), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -633, 5, -4826), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -727, 5, -5426), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -635, 5, -6006), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 9, 5, -6099), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 634, 5, -6008), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 726, 5, -5426), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 636, 5, -4834), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 9, 5, -4734), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4815, 125, 200), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4930, 125, 0), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4815, 125, -201), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4585, 125, -200), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4470, 125, 0), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4585, 125, 200), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1153, 4019, 4293), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1284, 4019, 4611), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1599, 4019, 4747), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2047, 4019, 4303), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1920, 4019, 3996), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1603, 4019, 3851), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -285, 513, -354), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -395, 513, -280), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -504, 513, -205), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -577, 513, -110), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -646, 513, -5), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 253, -500, -621), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 617, -499, -263), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 621, -499, 254), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 258, -500, 624), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -254, -500, 621), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -622, -499, 259), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -624, -499, -254), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -262, -500, -619), - RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 244, 150, -509), - RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 88, 250, 682), - RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -531, 450, -430), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 825, 758, 531), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 682, 758, 583), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 536, 758, 628), + RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -113, 304, 3001), + RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 115, 605, 3001), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -170, 0, -700), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 0, -20, -630), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 170, 0, -699), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1362, 4419, 2014), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1860, 4469, 1580), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2181, 4519, 1118), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5700, 40, -1000), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5500, 40, -500), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5350, 40, 0), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3513, 4102, -541), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3595, 4104, 478), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3615, 2773, 1411), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4356, 2821, 356), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4920, 2778, 1222), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3735, 2828, -787), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4431, 2830, -882), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5370, 2882, -787), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3270, 103, -815), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3483, 109, -341), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3483, 99, 342), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3270, 121, 815), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3930, 4900, 316), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4378, 4900, 764), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5018, 4900, 773), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5468, 4900, 314), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5468, 4900, -315), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5018, 4900, -773), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4378, 4900, -764), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3930, 4900, -315), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 510, 387, 0), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 0, 398, 520), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 0, 398, -520), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 472, 413, -237), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 383, 413, -295), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 287, 413, -357), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 975, 900, 2573), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2566, 900, 968), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2568, 900, -968), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 1950, 900, -1949), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 975, 900, -2574), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -50, 1050, -2750), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -975, 900, -2575), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2579, 1100, -980), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2579, 900, 980), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -977, 900, 2573), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2140, 2938, -1157), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1696, 3050, -1731), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1072, 3157, -2180), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 790, 3300, -2345), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 1427, 3300, -1995), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 1873, 3899, -1580), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2267, 3963, -1018), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2450, 4019, -394), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4366, -599, -311), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 5404, -593, -734), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 5831, -589, 301), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4769, -600, 726), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4302, 3719, 583), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4214, 3719, 1076), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3653, 3719, 1587), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3080, 3719, 2063), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -633, 5, -4826), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -727, 5, -5426), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -635, 5, -6006), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 9, 5, -6099), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 634, 5, -6008), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 726, 5, -5426), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 636, 5, -4834), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 9, 5, -4734), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4815, 125, 200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4930, 125, 0), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4815, 125, -201), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4585, 125, -200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4470, 125, 0), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4585, 125, 200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1153, 4019, 4293), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1284, 4019, 4611), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1599, 4019, 4747), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2047, 4019, 4303), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1920, 4019, 3996), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1603, 4019, 3851), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -285, 513, -354), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -395, 513, -280), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -504, 513, -205), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -577, 513, -110), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -646, 513, -5), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 253, -500, -621), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 617, -499, -263), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 621, -499, 254), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 258, -500, 624), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -254, -500, 621), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -622, -499, 259), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -624, -499, -254), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -262, -500, -619), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 244, 150, -509), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 88, 250, 682), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -531, 450, -430), RC(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_D_CCW_GNAWTYS, 694, 998, 632), RC(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_E_CCW_NABNUTS, 640, 513, -202), - RC(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -225, 640, 506), - RC(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 4050, 4284, 1010), - RC(RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -310, 730, -856), - RC(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -4993, 2896, -944), - RC(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 5100, 425, 0), - RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -693, 2, 528), - RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -310, 730, -855), - RC(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3604, 22, -4012), - RC(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 5848, 4244, 612), - RC(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 833, 441, 133), - RC(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -3157, 300, -3149), - RC(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3078, -338, 3076), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -225, 640, 506), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 4050, 4284, 1010), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -310, 730, -856), + RC(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -4993, 2896, -944), + RC(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 5100, 425, 0), + RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -693, 2, 528), + RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -310, 730, -855), + RC(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 3604, 22, -4012), + RC(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 5848, 4244, 612), + RC(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 833, 441, 133), + RC(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -3157, 300, -3149), + RC(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 3078, -338, 3076), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_CCW_JIGGY_EYRIE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_49_CCW_EYRIE, 0, 0, 0), RC(RC_CCW_JIGGY_FLOWER, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4D_CCW_FLOWER, 0, 0, 0), RC(RC_CCW_JIGGY_GNAWTY, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4B_CCW_GNAWTY, 240, 600, 75), @@ -571,31 +566,31 @@ std::map Checks = { RC(RC_CCW_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, NULL, -1592, 900, -6073), RC(RC_CCW_JINJO_PINK, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_PINK_CLICK_CLOCK_WOOD, NULL, -225, 1039, -1100), RC(RC_CCW_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, NULL, -3602, 0, 4266), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6A_CCW_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, 153, 1857, 2677), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6D_CCW_AUTUMN_LEAF_NEAR_TREEHOUSE, 3405, 4107, 1003), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6B_CCW_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, 500, 166, 5125), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6C_CCW_AUTUMN_SNAREBEAR_TOP_OF_TREE, 0, 5830, -3325), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6E_CCW_AUTUMN_TOP_OF_BRANCH, -5929, 2586, 61), - RC(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5D_CCW_SPRING_FRONT_OF_EYRIE, -2750, 4586, -513), - RC(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_62_CCW_SPRING_NABNUTS_HOUSE, -575, 300, -139), - RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5F_CCW_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, 1904, 105, -2706), - RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_60_CCW_SPRING_SNAREBEAR_NEAR_ENTRANCE, 1000, 105, 5300), - RC(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5E_CCW_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, -2649, 0, -395), - RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_61_CCW_SPRING_TOP_OF_BEEHIVE, 0, 3513, -5240), - RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5C_CCW_SPRING_TOP_OF_BRANCH, -4053, 2894, 587), - RC(RC_CCW_MUMBO_TOKEN_SPRING_UNFINISHED_WOOD_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5B_CCW_SPRING_UNFINISHED_WOOD_TREEHOUSE, 6134, 4244, 306), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_64_CCW_SUMMER_BIG_FLOWER_FIELD, -3578, 40, -4259), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_67_CCW_SUMMER_ENTRANCE_GNAWTYS_HOUSE, 2700, -600, 0), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_68_CCW_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, 2043, 3534, 1799), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_69_CCW_SUMMER_INSIDE_MUMBOS_SKULL, 0, 416, 500), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_63_CCW_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, -1861, 4469, 1583), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_65_CCW_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, -3855, 1428, 3840), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_66_CCW_SUMMER_TOP_OF_BRANCH, -4661, 2800, -1248), - RC(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6F_CCW_WINTER_BIG_FLOWER, 0, 105, -5400), - RC(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_71_CCW_WINTER_BROKEN_BEEHIVE, 0, 3138, -3696), - RC(RC_CCW_MUMBO_TOKEN_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_70_CCW_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, 5950, -46, 0), - RC(RC_CCW_MUMBO_TOKEN_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, -3157, 300, -3149), - RC(RC_CCW_MUMBO_TOKEN_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_72_CCW_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, 40, 3969, 5000), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6A_CCW_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, 153, 1857, 2677), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6D_CCW_AUTUMN_LEAF_NEAR_TREEHOUSE, 3405, 4107, 1003), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6B_CCW_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, 500, 166, 5125), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6C_CCW_AUTUMN_SNAREBEAR_TOP_OF_TREE, 0, 5830, -3325), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6E_CCW_AUTUMN_TOP_OF_BRANCH, -5929, 2586, 61), + RC(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5D_CCW_SPRING_FRONT_OF_EYRIE, -2750, 4586, -513), + RC(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_62_CCW_SPRING_NABNUTS_HOUSE, -575, 300, -139), + RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5F_CCW_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, 1904, 105, -2706), + RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_60_CCW_SPRING_SNAREBEAR_NEAR_ENTRANCE, 1000, 105, 5300), + RC(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5E_CCW_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, -2649, 0, -395), + RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_61_CCW_SPRING_TOP_OF_BEEHIVE, 0, 3513, -5240), + RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5C_CCW_SPRING_TOP_OF_BRANCH, -4053, 2894, 587), + RC(RC_CCW_MUMBO_TOKEN_SPRING_UNFINISHED_WOOD_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5B_CCW_SPRING_UNFINISHED_WOOD_TREEHOUSE, 6134, 4244, 306), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_64_CCW_SUMMER_BIG_FLOWER_FIELD, -3578, 40, -4259), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_67_CCW_SUMMER_ENTRANCE_GNAWTYS_HOUSE, 2700, -600, 0), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_68_CCW_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, 2043, 3534, 1799), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_69_CCW_SUMMER_INSIDE_MUMBOS_SKULL, 0, 416, 500), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_63_CCW_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, -1861, 4469, 1583), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_65_CCW_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, -3855, 1428, 3840), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_66_CCW_SUMMER_TOP_OF_BRANCH, -4661, 2800, -1248), + RC(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6F_CCW_WINTER_BIG_FLOWER, 0, 105, -5400), + RC(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_71_CCW_WINTER_BROKEN_BEEHIVE, 0, 3138, -3696), + RC(RC_CCW_MUMBO_TOKEN_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_70_CCW_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, 5950, -46, 0), + RC(RC_CCW_MUMBO_TOKEN_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, -3157, 300, -3149), + RC(RC_CCW_MUMBO_TOKEN_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_72_CCW_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, 40, 3969, 5000), RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -674, -1, 925), RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -674, 0, -900), RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 675, -2, 925), @@ -697,73 +692,73 @@ std::map Checks = { RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1691, 5210, -2199), RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -764, 5590, -2634), RC(RC_CCW_SNS_YELLOW_EGG, RCTYPE_STOP_N_SWOP, LEVEL_8_CLICK_CLOCK_WOOD, RI_STOP_N_SWOP_EGG_YELLOW, SNS_ITEM_EGG_YELLOW, 556, 150, 47), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1536, 3505, 9857), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1606, 3505, 9635), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1674, 3505, 9422), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1610, 3505, 9197), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1545, 3505, 8981), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 404, 18, -2625), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 654, 18, -3169), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1410, 17, -2859), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1185, 18, -2295), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -344, 2110, -200), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -195, 2110, -343), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1, 2110, -399), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 199, 2110, -346), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 345, 2110, -199), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 395, 2110, 1), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 341, 2110, 196), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 199, 2110, 340), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 0, 2110, 393), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -198, 2110, 347), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -344, 2110, 198), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -396, 2110, 0), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1465, 7354, 1066), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1961, 7227, 248), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1734, 7166, -667), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -948, 7201, -1175), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -33, 7313, -984), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 496, 7442, -179), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 278, 7505, 757), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3128, -168, -4645), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2939, -168, -4791), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2759, -168, -4928), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2552, -168, -5061), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2367, -168, -5166), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2165, -168, -5146), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1979, -168, -5120), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1897, -168, -4931), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1824, -168, -4732), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1758, -168, -4514), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4112, -168, 5604), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3753, -168, 6126), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3887, -168, 6767), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4440, -168, 7130), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5069, -168, 6990), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5424, -168, 6438), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5280, -168, 5810), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4753, -168, 5455), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -6559, 0, -291), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -7119, 0, -113), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -7166, 0, 926), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -6599, 0, 1184), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1536, 3505, 9857), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1606, 3505, 9635), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1674, 3505, 9422), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1610, 3505, 9197), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1545, 3505, 8981), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 404, 18, -2625), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 654, 18, -3169), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1410, 17, -2859), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1185, 18, -2295), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -344, 2110, -200), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -195, 2110, -343), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1, 2110, -399), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 199, 2110, -346), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 345, 2110, -199), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 395, 2110, 1), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 341, 2110, 196), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 199, 2110, 340), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 0, 2110, 393), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -198, 2110, 347), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -344, 2110, 198), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -396, 2110, 0), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1465, 7354, 1066), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1961, 7227, 248), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1734, 7166, -667), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -948, 7201, -1175), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -33, 7313, -984), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 496, 7442, -179), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 278, 7505, 757), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -3128, -168, -4645), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2939, -168, -4791), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2759, -168, -4928), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2552, -168, -5061), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2367, -168, -5166), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2165, -168, -5146), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1979, -168, -5120), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1897, -168, -4931), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1824, -168, -4732), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1758, -168, -4514), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -4112, -168, 5604), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -3753, -168, 6126), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -3887, -168, 6767), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -4440, -168, 7130), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -5069, -168, 6990), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -5424, -168, 6438), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -5280, -168, 5810), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -4753, -168, 5455), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -6559, 0, -291), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -7119, 0, -113), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -7166, 0, 926), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -6599, 0, 1184), RC(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_A_FP_SIR_SLUSH, 4295, 441, 1268), RC(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_9_FP_WOZZAS_CAVE, -6531, 135, 422), - RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, 6992, 1390, -3159), - RC(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -4450, 1591, -7407), - RC(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -7322, 0, 391), - RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE, NULL, 6992, 1390, -3159), + RC(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE, NULL, -4450, 1591, -7407), + RC(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE, NULL, -7322, 0, 391), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_31_FP_SIR_SLUSH, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_1, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_30_FP_BOGGY_2, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_2, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2C_FP_BOGGY_3, 0, 0 ,0), @@ -780,16 +775,16 @@ std::map Checks = { RC(RC_FP_JINJO_PINK, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_PINK_FREEZEEZY_PEAK, NULL, -6851, 1193, 930), RC(RC_FP_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_YELLOW_FREEZEEZY_PEAK, NULL, 0, 406, -511), RC(RC_FP_MOLEHILL_BEAK_BOMB, RCTYPE_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK, RI_MOLEHILL_BEAK_BOMB, ABILITY_1_BEAK_BOMB, -7462, 250, 1324), - RC(RC_FP_MUMBO_TOKEN_INSIDE_BOGGYS_IGLOO, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_28_FP_INSIDE_BOGGYS_IGLOO, 0, 10, -215), - RC(RC_FP_MUMBO_TOKEN_PRESENT_STACK, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_21_FP_BEHIND_PILE_PRESENT_BOXES, -5904, 260, 794), - RC(RC_FP_MUMBO_TOKEN_POTTED_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_25_FP_CHRISTMAS_TREE_POT, -4590, 350, 6344), - RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_START, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_23_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_LEFT_FOOT, 1413, 18, 2802), - RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_FINISH, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_24_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_RIGHT_FOOT, -4527, 211, -803), - RC(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_26_FP_TIP_OF_SCARF, -793, 3020, 4389), - RC(RC_FP_MUMBO_TOKEN_SNOWMAN_LEFT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_1F_FP_SNOWMAN_LEFT_FOOT, -1815, 4, -1019), - RC(RC_FP_MUMBO_TOKEN_SNOWMAN_RIGHT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_20_FP_SNOWMAN_RIGHT_FOOT, 634, 5, 769), - RC(RC_FP_MUMBO_TOKEN_VILLAGE_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_22_FP_ABOVE_CHIMNEY_FLIGHT_PAD, 5296, 2013, 2729), - RC(RC_FP_MUMBO_TOKEN_WATER_BEHIND_SNOWMAN, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_27_FP_WATER_BEHIND_SNOWMAN, -2424, -168, -4235), + RC(RC_FP_MUMBO_TOKEN_INSIDE_BOGGYS_IGLOO, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_28_FP_INSIDE_BOGGYS_IGLOO, 0, 10, -215), + RC(RC_FP_MUMBO_TOKEN_PRESENT_STACK, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_21_FP_BEHIND_PILE_PRESENT_BOXES, -5904, 260, 794), + RC(RC_FP_MUMBO_TOKEN_POTTED_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_25_FP_CHRISTMAS_TREE_POT, -4590, 350, 6344), + RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_START, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_23_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_LEFT_FOOT, 1413, 18, 2802), + RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_FINISH, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_24_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_RIGHT_FOOT, -4527, 211, -803), + RC(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_26_FP_TIP_OF_SCARF, -793, 3020, 4389), + RC(RC_FP_MUMBO_TOKEN_SNOWMAN_LEFT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_1F_FP_SNOWMAN_LEFT_FOOT, -1815, 4, -1019), + RC(RC_FP_MUMBO_TOKEN_SNOWMAN_RIGHT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_20_FP_SNOWMAN_RIGHT_FOOT, 634, 5, 769), + RC(RC_FP_MUMBO_TOKEN_VILLAGE_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_22_FP_ABOVE_CHIMNEY_FLIGHT_PAD, 5296, 2013, 2729), + RC(RC_FP_MUMBO_TOKEN_WATER_BEHIND_SNOWMAN, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_27_FP_WATER_BEHIND_SNOWMAN, -2424, -168, -4235), RC(RC_FP_NOTE_FIRST_SLOPE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -790, 3505, 8345), RC(RC_FP_NOTE_FIRST_SLOPE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -820, 3149, 7926), RC(RC_FP_NOTE_FIRST_SLOPE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -843, 2725, 7475), @@ -891,109 +886,109 @@ std::map Checks = { RC(RC_FP_NOTE_SNOWMAN_SCARF_18, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -941, 5605, 844), RC(RC_FP_NOTE_SNOWMAN_SCARF_19, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 17, 5605, 266), RC(RC_FP_SNS_ICE_KEY, RCTYPE_STOP_N_SWOP, LEVEL_5_FREEZEEZY_PEAK, RI_STOP_N_SWOP_ICE_KEY, SNS_ITEM_ICE_KEY, 1567, 583, 2416), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -1065), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -605), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -145), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 315), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 775), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 1235), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2799, 0, -2071), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2911, 0, -1907), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3016, 0, -1764), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3120, 0, -1616), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -9, -1395, 1178), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 382, -1395, 1090), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 820, -1395, 1183), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 820, -1395, 1692), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 445, -1395, 1832), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 27, -1395, 1781), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -185, -1395, 1477), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 3600), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4001), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4400), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4800), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6392, 122, 744), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6732, 277, 765), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7018, 426, 641), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7264, 495, 389), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7264, 496, -1392), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7018, 426, -1640), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6732, 277, -1767), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6392, 122, -1749), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2726, -176, -6393), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2986, -176, -6339), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3277, -176, -6332), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3552, -176, -6394), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1004, -800, 6827), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 888, -802, 6826), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -300, -792, 6800), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -458, -768, 6764), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1335, -1482, 1349), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1835, -1486, 485), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1832, -1486, -499), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1344, -1492, -1346), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -499, -1492, -1836), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 491, -1490, -1832), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1342, -1486, -1349), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1833, -1492, -491), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1846, -1492, 503), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1341, -1492, 1361), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -885, -749, 3037), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -98, -749, 3041), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 418, -750, 3577), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 422, -750, 4333), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -114, -750, 4871), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -864, -750, 4881), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1412, -750, 4335), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1410, -749, 3551), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1499, 0, 310), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1630, 0, 310), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1630, 0, 180), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1499, 0, 180), - RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 7900, 1750, -1445), - RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 7900, 1750, -1358), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -898, 0, -630), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -126, 0, -637), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 671, 0, -637), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 671, 0, 631), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -112, 0, 630), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -899, 0, 630), - RC(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 0, 1600, -3700), - RC(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -1992, 878, -3052), - RC(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 2954, 1247, 100), - RC(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -8689, -1781, -3192), - RC(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 3599, -478, 2424), - RC(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -838, 1950, 835), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, -1065), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, -605), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, -145), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, 315), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, 775), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, 1235), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2799, 0, -2071), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2911, 0, -1907), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3016, 0, -1764), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3120, 0, -1616), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -9, -1395, 1178), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 382, -1395, 1090), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 820, -1395, 1183), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 820, -1395, 1692), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 445, -1395, 1832), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 27, -1395, 1781), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -185, -1395, 1477), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 3600), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 4001), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 4400), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 4800), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6392, 122, 744), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6732, 277, 765), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7018, 426, 641), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7264, 495, 389), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7264, 496, -1392), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7018, 426, -1640), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6732, 277, -1767), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6392, 122, -1749), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2726, -176, -6393), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2986, -176, -6339), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3277, -176, -6332), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3552, -176, -6394), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1004, -800, 6827), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 888, -802, 6826), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -300, -792, 6800), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -458, -768, 6764), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1335, -1482, 1349), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1835, -1486, 485), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1832, -1486, -499), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1344, -1492, -1346), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -499, -1492, -1836), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 491, -1490, -1832), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1342, -1486, -1349), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1833, -1492, -491), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1846, -1492, 503), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1341, -1492, 1361), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -885, -749, 3037), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -98, -749, 3041), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 418, -750, 3577), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 422, -750, 4333), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -114, -750, 4871), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -864, -750, 4881), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1412, -750, 4335), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1410, -749, 3551), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1499, 0, 310), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1630, 0, 310), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1630, 0, 180), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1499, 0, 180), + RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 7900, 1750, -1445), + RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 7900, 1750, -1358), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -898, 0, -630), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -126, 0, -637), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 671, 0, -637), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 671, 0, 631), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -112, 0, 630), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -899, 0, 630), + RC(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, 0, 1600, -3700), + RC(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, -1992, 878, -3052), + RC(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, 2954, 1247, 100), + RC(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, -8689, -1781, -3192), + RC(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, 3599, -478, 2424), + RC(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, -838, 1950, 835), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_GL_JIGGY_LOBBY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_33_LAIR_1ST_JIGGY, -1505, 600, 123), RC(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_37_LAIR_BGS_WITCH_SWITCH, 0, 0, -20), RC(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_35_LAIR_CC_WITCH_SWITCH, 0, 75, 156), @@ -1004,85 +999,85 @@ std::map Checks = { RC(RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_34_LAIR_MM_WITCH_SWITCH, 4165, 1000, -2363), RC(RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_3B_LAIR_RBB_WITCH_SWITCH, 0, 1200, 1650), RC(RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_36_LAIR_TTC_WITCH_SWITCH, 998, 783, 368), - RC(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_51_LAIR_BEHIND_PURPLE_CAULDRON, 162, -750, 4611), - RC(RC_GL_MUMBO_TOKEN_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_53_LAIR_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, -180, 351, -750), - RC(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_54_LAIR_ABOVE_CC_ENTRANCE, 0, 850, -2450), - RC(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_52_LAIR_CCW_JIGGY_PODIUM, 4936, -478, 286), - RC(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_55_LAIR_BEHIND_SARCOPHAGUS, -1486, 0, -922), - RC(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_56_LAIR_ADVENT_TOP_WINDOW, 4155, 1485, 6270), - RC(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_59_LAIR_UNDERWATER_RBB_ENTRANCE_AREA, 1764, -1400, -1136), - RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), - RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), - RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), - RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 387, 2730, -6645), - RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 17, 2730, -6645), - RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -342, 2730, -6645), - RC(RC_GV_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1325, -59, 9447), - RC(RC_GV_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 845, -55, 9275), - RC(RC_GV_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 781, -51, 8805), - RC(RC_GV_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1214, -51, 8493), - RC(RC_GV_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1647, -56, 8820), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 712, 20, -1636), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 612, 20, -1636), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 511, 20, -1636), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 517, 22, -1502), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 612, 22, -1502), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 712, 22, -1502), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -856, 25, -1243), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -775, 25, -1243), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -775, 25, -1140), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -855, 25, -1140), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1139, 25, 880), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1139, 25, 961), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1240, 25, 964), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1240, 24, 884), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -985, 2432, 994), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1056, 2432, 466), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1137, 2432, -58), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -814, 2431, -394), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -472, 2432, -752), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 129, 2432, -740), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 740, 2432, -729), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 945, 2432, -392), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1151, 2431, -43), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1099, 2432, 473), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1039, 2432, 970), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2251, 0, -50), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2347, 0, 159), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2550, 0, 251), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2757, 0, 137), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2850, 0, -50), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2756, 0, -272), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2550, 0, -349), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2359, 0, -293), - RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4379, 1623, 6824), - RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4674, 1659, 6885), - RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4530, 1665, 6538), - RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4402, 1618, 5076), - RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4551, 1663, 5336), - RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4689, 1662, 5017), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -671, 13, -369), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -390, 13, 655), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 354, 13, -645), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 645, 13, 384), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1168, 3325, -5619), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 861, 3821, -5292), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 526, 4316, -3580), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 523, 4316, -4952), + RC(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_51_LAIR_BEHIND_PURPLE_CAULDRON, 162, -750, 4611), + RC(RC_GL_MUMBO_TOKEN_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_53_LAIR_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, -180, 351, -750), + RC(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_54_LAIR_ABOVE_CC_ENTRANCE, 0, 850, -2450), + RC(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_52_LAIR_CCW_JIGGY_PODIUM, 4936, -478, 286), + RC(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_55_LAIR_BEHIND_SARCOPHAGUS, -1486, 0, -922), + RC(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_56_LAIR_ADVENT_TOP_WINDOW, 4155, 1485, 6270), + RC(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_59_LAIR_UNDERWATER_RBB_ENTRANCE_AREA, 1764, -1400, -1136), + RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), + RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), + RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 387, 2730, -6645), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 17, 2730, -6645), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -342, 2730, -6645), + RC(RC_GV_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1325, -59, 9447), + RC(RC_GV_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 845, -55, 9275), + RC(RC_GV_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 781, -51, 8805), + RC(RC_GV_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1214, -51, 8493), + RC(RC_GV_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1647, -56, 8820), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 712, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 612, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 511, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 517, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 612, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 712, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -856, 25, -1243), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -775, 25, -1243), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -775, 25, -1140), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -855, 25, -1140), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1139, 25, 880), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1139, 25, 961), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1240, 25, 964), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1240, 24, 884), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -985, 2432, 994), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1056, 2432, 466), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1137, 2432, -58), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -814, 2431, -394), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -472, 2432, -752), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 129, 2432, -740), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 740, 2432, -729), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 945, 2432, -392), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1151, 2431, -43), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1099, 2432, 473), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1039, 2432, 970), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2251, 0, -50), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2347, 0, 159), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2550, 0, 251), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2757, 0, 137), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2850, 0, -50), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2756, 0, -272), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2550, 0, -349), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2359, 0, -293), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4379, 1623, 6824), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4674, 1659, 6885), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4530, 1665, 6538), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4402, 1618, 5076), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4551, 1663, 5336), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4689, 1662, 5017), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -671, 13, -369), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -390, 13, 655), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 354, 13, -645), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 645, 13, 384), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1168, 3325, -5619), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 861, 3821, -5292), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 526, 4316, -3580), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 523, 4316, -4952), RC(RC_GV_EMPTY_HONEYCOMB_CACTUS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_B_GV_CACTUS, 2911, 3292, -3307), RC(RC_GV_EMPTY_HONEYCOMB_GOBI, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_C_GV_GOBI_3, -6885, 2383, 1335), - RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -8948, 1332, 5500), - RC(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, 1282, 18, 1971), - RC(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -230, 4820, -4421), - RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE, NULL, -8948, 1332, 5500), + RC(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE, NULL, 1282, 18, 1971), + RC(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE, NULL, -230, 4820, -4421), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_GV_JIGGY_ANCIENT_ONES, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_46_GV_ANCIENT_ONES, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_1, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_44_GV_GOBI_1, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_2, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_45_GV_GOBI_2, 0, 0, 0), @@ -1099,16 +1094,16 @@ std::map Checks = { RC(RC_GV_JINJO_PINK, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_PINK_GOBIS_VALLEY, NULL, -4964, 0, 700), RC(RC_GV_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_YELLOW_GOBIS_VALLEY, NULL, 3067, 447, 10270), RC(RC_GV_MOLEHILL_TURBO_TALON, RCTYPE_MOLEHILL, LEVEL_7_GOBIS_VALLEY, RI_MOLEHILL_TURBO_TALON, ABILITY_11_TURBO_TALON, -6445, 2831, -822), - RC(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2F_GV_BEHIND_SANDYBUTTS_SARCOPHAGUS, -5514, 0, 138), - RC(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2B_GV_BOTTOM_OF_MOAT, 91, 535, -860), - RC(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2D_GV_FRONT_OF_STAR_DOOR, -230, 2843, -3091), - RC(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_32_GV_INSIDE_JINXY, -2550, 0, -51), - RC(RC_GV_MUMBO_TOKEN_INSIDE_MEMORY_GAME_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2E_GV_INSIDE_MEMORY_GAME_ROOM, 715, 248, 0), - RC(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_30_GV_INSIDE_WATER_PYRAMID, -300, 1439, -1194), - RC(RC_GV_MUMBO_TOKEN_NEXT_TO_RUBEE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_31_GV_NEXT_TO_RUBEE, 0, 107, -602), - RC(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2A_GV_SAND_RIGHT_OF_JINXY, -5386, 1420, 10034), - RC(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_29_GV_TOP_OF_JINXYS_NOSE, -2149, 3340, 5867), - RC(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2C_GV_TOP_OF_WATER_PYRAMID, 64, 3484, 400), + RC(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2F_GV_BEHIND_SANDYBUTTS_SARCOPHAGUS, -5514, 0, 138), + RC(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2B_GV_BOTTOM_OF_MOAT, 91, 535, -860), + RC(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2D_GV_FRONT_OF_STAR_DOOR, -230, 2843, -3091), + RC(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_32_GV_INSIDE_JINXY, -2550, 0, -51), + RC(RC_GV_MUMBO_TOKEN_INSIDE_MEMORY_GAME_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2E_GV_INSIDE_MEMORY_GAME_ROOM, 715, 248, 0), + RC(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_30_GV_INSIDE_WATER_PYRAMID, -300, 1439, -1194), + RC(RC_GV_MUMBO_TOKEN_NEXT_TO_RUBEE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_31_GV_NEXT_TO_RUBEE, 0, 107, -602), + RC(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2A_GV_SAND_RIGHT_OF_JINXY, -5386, 1420, 10034), + RC(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_29_GV_TOP_OF_JINXYS_NOSE, -2149, 3340, 5867), + RC(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2C_GV_TOP_OF_WATER_PYRAMID, 64, 3484, 400), RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7178, 2372, 1754), RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7148, 2371, 1568), RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7123, 2371, 1404), @@ -1210,56 +1205,56 @@ std::map Checks = { RC(RC_GV_NOTE_WATER_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -828, 3821, -3580), RC(RC_GV_NOTE_WATER_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -489, 4316, -4946), RC(RC_GV_SNS_BLUE_EGG, RCTYPE_STOP_N_SWOP, LEVEL_7_GOBIS_VALLEY, RI_STOP_N_SWOP_EGG_BLUE, SNS_ITEM_EGG_BLUE, 8, 470, -4141), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -131, 398, -496), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -362, 378, -362), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -487, 398, -146), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -493, 398, 101), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -352, 398, 371), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -131, 398, 496), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 136, 398, -499), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 361, 379, -363), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 498, 394, -129), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 495, 398, 133), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 359, 398, 362), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 134, 379, 497), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -10, 1507, -125), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -80, 1503, -71), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -74, 1521, 19), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3, 1510, 52), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 60, 1510, -87), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 67, 1510, 0), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5548, 200, 5984), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5706, 200, 5962), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5835, 201, 5896), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5911, 200, 5764), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5967, 200, 5615), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5927, 200, 5471), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5858, 200, 5343), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5732, 200, 5272), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5061, 298, 6090), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -4881, 299, 6135), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3958, 600, 6084), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3827, 600, 5997), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2840, 2355, -2408), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2811, 2355, -2445), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2776, 2355, -2494), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2743, 2355, -2538), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2713, 2355, -2576), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -131, 398, -496), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -362, 378, -362), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -487, 398, -146), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -493, 398, 101), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -352, 398, 371), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -131, 398, 496), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 136, 398, -499), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 361, 379, -363), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 498, 394, -129), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 495, 398, 133), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 359, 398, 362), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 134, 379, 497), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -10, 1507, -125), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -80, 1503, -71), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -74, 1521, 19), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -3, 1510, 52), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 60, 1510, -87), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 67, 1510, 0), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5548, 200, 5984), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5706, 200, 5962), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5835, 201, 5896), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5911, 200, 5764), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5967, 200, 5615), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5927, 200, 5471), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5858, 200, 5343), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5732, 200, 5272), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5061, 298, 6090), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -4881, 299, 6135), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -3958, 600, 6084), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -3827, 600, 5997), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2840, 2355, -2408), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2811, 2355, -2445), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2776, 2355, -2494), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2743, 2355, -2538), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2713, 2355, -2576), RC(RC_MM_EMPTY_HONEYCOMB_HILL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_1_MM_HILL, 985, 484, 1681), RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), - RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_EXTRA_LIFE_TICKERS_TOWER, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 223, 3563, -382), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE, NULL, 0, 0, 0), + RC(RC_MM_EXTRA_LIFE_TICKERS_TOWER, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE, NULL, 223, 3563, -382), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_MM_JIGGY_CHIMPY, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_9_MM_CHIMPY, 0, 0, 0), RC(RC_MM_JIGGY_CONGA, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_A_MM_CONGA, 0, 0, 0), RC(RC_MM_JIGGY_HILL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_07_MM_HILL, 4335, 1485, 794), @@ -1278,11 +1273,11 @@ std::map Checks = { RC(RC_MM_MOLEHILL_BEAK_BUSTER, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_BEAK_BUSTER, ABILITY_2_BEAK_BUSTER, 3943, 2155, -3422), RC(RC_MM_MOLEHILL_TALON_TROT, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_TALON_TROT, ABILITY_10_TALON_TROT, -2550, 2255, -1217), RC(RC_MM_MOLEHILL_USE_EGGS, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_EGGS, ABILITY_6_EGGS, -5926, 200, 6213), - RC(RC_MM_MUMBO_TOKEN_BEHIND_PINK_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_04_MM_BEHIND_PINK_JINJO, 5855, 0, 2169), - RC(RC_MM_MUMBO_TOKEN_BEHIND_RUINS, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_02_MM_BEHIND_RUINS, -4869, 2255, -2506), - RC(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_05_MM_INSIDE_TICKERS_TOWER, -343, 345, -518), - RC(RC_MM_MUMBO_TOKEN_STUMP_NEAR_CONGA, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA, -4431, 475, 6183), - RC(RC_MM_MUMBO_TOKEN_UNDER_RAMP_TO_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_03_MM_UNDER_RAMP_TO_MUMBOS_SKULL, 5150, 2168, -2447), + RC(RC_MM_MUMBO_TOKEN_BEHIND_PINK_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_04_MM_BEHIND_PINK_JINJO, 5855, 0, 2169), + RC(RC_MM_MUMBO_TOKEN_BEHIND_RUINS, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_02_MM_BEHIND_RUINS, -4869, 2255, -2506), + RC(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_05_MM_INSIDE_TICKERS_TOWER, -343, 345, -518), + RC(RC_MM_MUMBO_TOKEN_STUMP_NEAR_CONGA, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA, -4431, 475, 6183), + RC(RC_MM_MUMBO_TOKEN_UNDER_RAMP_TO_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_03_MM_UNDER_RAMP_TO_MUMBOS_SKULL, 5150, 2168, -2447), RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4867, 297, 1766), RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4782, 298, 1892), RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4971, 299, 1887), @@ -1383,100 +1378,100 @@ std::map Checks = { RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 60, 817, -87), RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -10, 817, -125), RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -80, 817, -71), - RC(RC_MMM_BLUE_EGG_BEDROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 450), - RC(RC_MMM_BLUE_EGG_BEDROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 300), - RC(RC_MMM_BLUE_EGG_BEDROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 150), - RC(RC_MMM_BLUE_EGG_CELLAR_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -464, 40, -473), - RC(RC_MMM_BLUE_EGG_CELLAR_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -495, 40, -474), - RC(RC_MMM_BLUE_EGG_CELLAR_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -524, 40, -473), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 950, 588, 819), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2300, 588, 819), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2299, 588, 820), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -949, 588, 820), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2300, 588, 2369), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 950, 588, 2369), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -949, 588, 2370), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2299, 588, 2370), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4885, -2065), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2069, 4885, -1765), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2069, 4885, -1464), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4839, -2065), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4838, -1764), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4839, -1465), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2730), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2430), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2129), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2720), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2420), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2119), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, -480), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, -280), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -701, 0, -80), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 121), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 320), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 520), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -600, 0, 619), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -400, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -199, 0, 621), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 200, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 401, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 600, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 519), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 320), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 120), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -78), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -279), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -481), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -350, 550, -2499), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -176, 550, -2499), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 0, 550, -2500), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 174, 550, -2500), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 349, 550, -2500), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 446, 135, -339), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 450, 0, -35), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 450, 0, 36), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 35, 0, 351), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -36, 0, 350), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -442, 160, 331), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -437, 150, -336), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -302, 150, -336), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 225, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 61, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -103, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -268, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -442, -135, -390), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 50, 1100, -760), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 50, 1100, 1255), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 1942, 1100, 1255), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 1950, 1099, -758), - RC(RC_MMM_BLUE_EGG_MAZE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -1750, 0, 2410), - RC(RC_MMM_BLUE_EGG_MAZE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -1951, 0, 2655), - RC(RC_MMM_BLUE_EGG_MAZE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2446, 0, 760), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, -103), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, 452), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, 1008), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7174, -175, 1564), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 4200, -275, -2324), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 4200, -275, -2474), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7150, -273, -2383), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7149, -273, -2233), + RC(RC_MMM_BLUE_EGG_BEDROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -650, 175, 450), + RC(RC_MMM_BLUE_EGG_BEDROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -650, 175, 300), + RC(RC_MMM_BLUE_EGG_BEDROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -650, 175, 150), + RC(RC_MMM_BLUE_EGG_CELLAR_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -464, 40, -473), + RC(RC_MMM_BLUE_EGG_CELLAR_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -495, 40, -474), + RC(RC_MMM_BLUE_EGG_CELLAR_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -524, 40, -473), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 950, 588, 819), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2300, 588, 819), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2299, 588, 820), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -949, 588, 820), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2300, 588, 2369), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 950, 588, 2369), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -949, 588, 2370), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2299, 588, 2370), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4885, -2065), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2069, 4885, -1765), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2069, 4885, -1464), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4839, -2065), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4838, -1764), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4839, -1465), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4813, 2730), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4813, 2430), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4813, 2129), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4768, 2720), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4768, 2420), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4768, 2119), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, -480), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, -280), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -701, 0, -80), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, 121), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, 320), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, 520), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -600, 0, 619), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -400, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -199, 0, 621), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 200, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 401, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 600, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, 519), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, 320), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, 120), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, -78), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, -279), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, -481), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -350, 550, -2499), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -176, 550, -2499), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 0, 550, -2500), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 174, 550, -2500), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 349, 550, -2500), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 446, 135, -339), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 450, 0, -35), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 450, 0, 36), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 35, 0, 351), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -36, 0, 350), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -442, 160, 331), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -437, 150, -336), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -302, 150, -336), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 225, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 61, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -103, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -268, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -442, -135, -390), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 50, 1100, -760), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 50, 1100, 1255), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 1942, 1100, 1255), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 1950, 1099, -758), + RC(RC_MMM_BLUE_EGG_MAZE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -1750, 0, 2410), + RC(RC_MMM_BLUE_EGG_MAZE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -1951, 0, 2655), + RC(RC_MMM_BLUE_EGG_MAZE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2446, 0, 760), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7173, -175, -103), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7173, -175, 452), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7173, -175, 1008), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7174, -175, 1564), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 4200, -275, -2324), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 4200, -275, -2474), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7150, -273, -2383), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7149, -273, -2233), RC(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_12_MMM_FLOORBOARD, -51, -135, 52), RC(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_11_MMM_CHURCH_RAFTERS, 0, 5163, 2400), - RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, -1, 2263, -3465), - RC(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 13, 6), - RC(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 1326, 145), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE, NULL, -1, 2263, -3465), + RC(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE, NULL, 0, 13, 6), + RC(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE, NULL, 0, 1326, 145), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_MMM_JIGGY_BARREL_INTERIOR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_61_MMM_RAIN_BARREL, 2, 288, -4), RC(RC_MMM_JIGGY_CELLAR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5E_MMM_CELLAR, -516, 30, 477), RC(RC_MMM_JIGGY_CEMETARY_POTS, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_63_MMM_FLOWER_POTS, 0, 0, 0), @@ -1492,22 +1487,22 @@ std::map Checks = { RC(RC_MMM_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_ORANGE_MAD_MONSTER_MANSION, NULL, -4265, 0, 2668), RC(RC_MMM_JINJO_PINK, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_PINK_MAD_MONSTER_MANSION, NULL, 511, 38, 203), RC(RC_MMM_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_YELLOW_MAD_MONSTER_MANSION, NULL, -250, 540, 300), - RC(RC_MMM_MUMBO_TOKEN_ALCOVE_CLOCK_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_35_MMM_ALCOVE_CLOCK_TOWER, -2800, 1475, -1363), - RC(RC_MMM_MUMBO_TOKEN_BEHIND_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_38_MMM_BEHIND_CHURCH, -4700, 175, -5149), - RC(RC_MMM_MUMBO_TOKEN_HIDDEN_NEAR_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_33_MMM_HIDDEN_NEAR_FOUNTAIN, 3950, -175, 325), - RC(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3E_MMM_IN_CHIMNEY_INSIDE_DINNING_ROOM, -160, 190, -2599), - RC(RC_MMM_MUMBO_TOKEN_IN_THE_MAZE, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_37_MMM_IN_THE_MAZE, -4250, 0, 352), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_40_MMM_INSIDE_BEDROOM, 696, 0, -397), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_LOGGO, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, RP_MUMBO_TOKEN_INSIDE_LOGGO, 424, 170, 304), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3D_MMM_INSIDE_LOGGO_AND_INSIDE_BARREL_IN_CELLAR, -507, 30, 199), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_WELL, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3F_MMM_INSIDE_WELL, -732, 0, -109), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_WHIPCRACK_IN_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_39_MMM_INSIDE_WHIPCRACK_IN_FOUNTAIN, 5900, -275, 798), - RC(RC_MMM_MUMBO_TOKEN_NEAR_FRONT_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_34_MMM_NEAR_FRONT_TUMBLARS_SHED, 173, 350, -3610), - RC(RC_MMM_MUMBO_TOKEN_NEXT_TO_MAZE_HEDGE_RAMP, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_36_MMM_NEXT_TO_MAZE_HEDGE_RAMP, -1643, 25, -1026), - RC(RC_MMM_MUMBO_TOKEN_IN_LOGGOS_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_41_MMM_SINK_IN_LOGGOS_ROOM, 52, 104, 512), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3A_MMM_TOP_OF_RAFTER_INSIDE_CHURCH, 0, 4806, 341), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3B_MMM_TOP_OF_STOOL_INSIDE_CHURCH, 0, 583, -1300), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3C_MMM_TOP_OF_TUMBLARS_SHED, 1796, 857, -4243), + RC(RC_MMM_MUMBO_TOKEN_ALCOVE_CLOCK_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_35_MMM_ALCOVE_CLOCK_TOWER, -2800, 1475, -1363), + RC(RC_MMM_MUMBO_TOKEN_BEHIND_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_38_MMM_BEHIND_CHURCH, -4700, 175, -5149), + RC(RC_MMM_MUMBO_TOKEN_HIDDEN_NEAR_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_33_MMM_HIDDEN_NEAR_FOUNTAIN, 3950, -175, 325), + RC(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3E_MMM_IN_CHIMNEY_INSIDE_DINNING_ROOM, -160, 190, -2599), + RC(RC_MMM_MUMBO_TOKEN_IN_THE_MAZE, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_37_MMM_IN_THE_MAZE, -4250, 0, 352), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_40_MMM_INSIDE_BEDROOM, 696, 0, -397), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_LOGGO, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, RP_MUMBO_TOKEN_INSIDE_LOGGO, 424, 170, 304), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3D_MMM_INSIDE_LOGGO_AND_INSIDE_BARREL_IN_CELLAR, -507, 30, 199), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_WELL, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3F_MMM_INSIDE_WELL, -732, 0, -109), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_WHIPCRACK_IN_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_39_MMM_INSIDE_WHIPCRACK_IN_FOUNTAIN, 5900, -275, 798), + RC(RC_MMM_MUMBO_TOKEN_NEAR_FRONT_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_34_MMM_NEAR_FRONT_TUMBLARS_SHED, 173, 350, -3610), + RC(RC_MMM_MUMBO_TOKEN_NEXT_TO_MAZE_HEDGE_RAMP, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_36_MMM_NEXT_TO_MAZE_HEDGE_RAMP, -1643, 25, -1026), + RC(RC_MMM_MUMBO_TOKEN_IN_LOGGOS_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_41_MMM_SINK_IN_LOGGOS_ROOM, 52, 104, 512), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3A_MMM_TOP_OF_RAFTER_INSIDE_CHURCH, 0, 4806, 341), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3B_MMM_TOP_OF_STOOL_INSIDE_CHURCH, 0, 583, -1300), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3C_MMM_TOP_OF_TUMBLARS_SHED, 1796, 857, -4243), RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 7150, -275, -3474), RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 7150, -275, -3325), RC(RC_MMM_NOTE_AROUND_THE_WELL_EAST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 4200, -275, -3325), @@ -1610,79 +1605,79 @@ std::map Checks = { RC(RC_MMM_NOTE_WELL_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 681, 0, 182), RC(RC_MMM_SNS_CYAN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_CYAN, SNS_ITEM_EGG_CYAN, 1995, 100, -476), RC(RC_MMM_SNS_GREEN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_GREEN, SNS_ITEM_EGG_GREEN, 517, 350, -241), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -450, 0, -750), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 450, 0, -751), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 450, 0, 750), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -450, 0, 750), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -750, -800, -3651), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -750, -800, -3726), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -50, -800, -3651), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -49, -800, -3726), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -3001), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2300), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2475), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2825), - RC(RC_RRB_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -550, -650, 3549), - RC(RC_RRB_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -1200, -450, 3899), - RC(RC_RRB_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -1750, -650, 3300), - RC(RC_RRB_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 1549, -500, 3250), - RC(RC_RRB_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 1900, -200, 3800), - RC(RC_RBB_BLUE_EGG_KITCHEN_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 702, 213, -596), - RC(RC_RBB_BLUE_EGG_KITCHEN_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 758, 213, -600), - RC(RC_RBB_BLUE_EGG_KITCHEN_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 647, 213, -601), - RC(RC_RBB_BLUE_EGG_KITCHEN_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 645, 213, -501), - RC(RC_RBB_BLUE_EGG_KITCHEN_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 705, 213, -503), - RC(RC_RBB_BLUE_EGG_KITCHEN_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 758, 213, -503), - RC(RC_RBB_BLUE_EGG_KITCHEN_7, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 760, 213, -408), - RC(RC_RBB_BLUE_EGG_KITCHEN_8, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 700, 213, -407), - RC(RC_RBB_BLUE_EGG_KITCHEN_9, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 646, 213, -404), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 590), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 409), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 230), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 50), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 3075), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 3550), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 4025), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6976, -2613, 3075), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6976, -2613, 3550), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6975, -2613, 4025), - RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -3721, -185, -1677), - RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -3953, -185, -1677), - RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -4185, -185, -1678), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -651, 140, -959), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -651, 140, -1064), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -520, 140, -1064), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -390, 140, -1064), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -389, 140, -959), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -520, 140, -959), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 450), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 324), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 199), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -399, 400, 74), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, -49), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4500, -250, -1150), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 5050, 50, -1050), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4100, -250, 1150), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4650, 150, 1050), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -726, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -537, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -350, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -163, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 25, 575, 124), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -450, 0, -750), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 450, 0, -751), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 450, 0, 750), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -450, 0, 750), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -750, -800, -3651), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -750, -800, -3726), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -50, -800, -3651), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -49, -800, -3726), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -3001), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -2300), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -2475), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -2825), + RC(RC_RRB_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -550, -650, 3549), + RC(RC_RRB_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -1200, -450, 3899), + RC(RC_RRB_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -1750, -650, 3300), + RC(RC_RRB_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 1549, -500, 3250), + RC(RC_RRB_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 1900, -200, 3800), + RC(RC_RBB_BLUE_EGG_KITCHEN_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 702, 213, -596), + RC(RC_RBB_BLUE_EGG_KITCHEN_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 758, 213, -600), + RC(RC_RBB_BLUE_EGG_KITCHEN_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 647, 213, -601), + RC(RC_RBB_BLUE_EGG_KITCHEN_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 645, 213, -501), + RC(RC_RBB_BLUE_EGG_KITCHEN_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 705, 213, -503), + RC(RC_RBB_BLUE_EGG_KITCHEN_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 758, 213, -503), + RC(RC_RBB_BLUE_EGG_KITCHEN_7, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 760, 213, -408), + RC(RC_RBB_BLUE_EGG_KITCHEN_8, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 700, 213, -407), + RC(RC_RBB_BLUE_EGG_KITCHEN_9, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 646, 213, -404), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 590), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 409), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 230), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 50), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 8726, -2613, 3075), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 8726, -2613, 3550), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 8726, -2613, 4025), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 6976, -2613, 3075), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 6976, -2613, 3550), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 6975, -2613, 4025), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -3721, -185, -1677), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -3953, -185, -1677), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -4185, -185, -1678), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -651, 140, -959), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -651, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -520, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -390, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -389, 140, -959), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -520, 140, -959), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, 450), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, 324), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, 199), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -399, 400, 74), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, -49), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 4500, -250, -1150), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 5050, 50, -1050), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 4100, -250, 1150), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 4650, 150, 1050), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -726, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -537, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -350, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -163, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 25, 575, 124), RC(RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_F_RBB_BOAT_HOUSE, 0, 1000, 0), RC(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_10_RBB_ENGINE_ROOM, 0, 360, 3541), - RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -626, 140, -351), - RC(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -2551, 1065, -2650), - RC(RC_RBB_EXTRA_LIFE_WAREHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -950, 1045, -50), - RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE, NULL, -626, 140, -351), + RC(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE, NULL, -2551, 1065, -2650), + RC(RC_RBB_EXTRA_LIFE_WAREHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE, NULL, -950, 1045, -50), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_RBB_JIGGY_BOSS_BOOM_BOX, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_56_RBB_BOSS_BOOM_BOX, 0, 0, 0), RC(RC_RBB_JIGGY_CAPTAINS_CABIN, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_58_RBB_CAPTAINS_CABIN, -997, 273, 355), RC(RC_RBB_JIGGY_CRANE_CAGE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_59_RBB_CRANE_CAGE, -4900, 0, 0), @@ -1698,21 +1693,21 @@ std::map Checks = { RC(RC_RBB_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, NULL, -193, 0, -979), RC(RC_RBB_JINJO_PINK, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_PINK_RUSTY_BUCKET_BAY, NULL, 7850, -2613, 4026), RC(RC_RBB_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, NULL, -8615, -1000, -3555), - RC(RC_RBB_MUMBO_TOKEN_TOXIC_WASTE_POND, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_46_RBB_TOXIC_WASTE_POND, -7401, -1000, -3425), - RC(RC_RBB_MUMBO_TOKEN_ON_LIFE_BOAT, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_44_RBB_ON_LIFE_BOAT, 7053, -985, -1672), - RC(RC_RBB_MUMBO_TOKEN_SHIPS_PROW, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_43_RBB_SHIPS_PROW, -6200, 150, 0), - RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_47_RBB_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, 6200, 400, 0), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_SHIPS_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_42_RBB_TOP_OF_SHIPS_CHIMNEY, 1000, 2750, 0), - RC(RC_RBB_MUMBO_TOKEN_FRONT_OF_CHOMPA_LEFT_OF_SHIP, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_45_RBB_FRONT_OF_CHOMPA_LEFT_OF_SHIP, -3299, -457, 3800), - RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_48_RBB_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, -650, 562, -35), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_49_RBB_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, -278, 710, -557), - RC(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4C_RBB_INSIDE_KITCHEN, -771, 238, -293), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BUNK_IN_CABIN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4A_RBB_TOP_OF_BUNK_IN_CABIN, 583, 323, -70), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_50_RBB_TOP_OF_BOX_INSIDE_TNT_ROOM, -435, 300, -435), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4D_RBB_ENGINE_ROOM_LEFT_PIPE, -2450, 1100, -400), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4E_RBB_ENGINE_ROOM_RIGHT_PIPE, 2450, 1100, -400), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_SPINNING_PLATFORM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4F_RBB_ENGINE_ROOM_SPINNING_PLATFORM, -319, 12, 1899), - RC(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4B_RBB_INSIDE_NAVIGATION_ROOM, -656, 0, -222), + RC(RC_RBB_MUMBO_TOKEN_TOXIC_WASTE_POND, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_46_RBB_TOXIC_WASTE_POND, -7401, -1000, -3425), + RC(RC_RBB_MUMBO_TOKEN_ON_LIFE_BOAT, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_44_RBB_ON_LIFE_BOAT, 7053, -985, -1672), + RC(RC_RBB_MUMBO_TOKEN_SHIPS_PROW, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_43_RBB_SHIPS_PROW, -6200, 150, 0), + RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_47_RBB_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, 6200, 400, 0), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_SHIPS_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_42_RBB_TOP_OF_SHIPS_CHIMNEY, 1000, 2750, 0), + RC(RC_RBB_MUMBO_TOKEN_FRONT_OF_CHOMPA_LEFT_OF_SHIP, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_45_RBB_FRONT_OF_CHOMPA_LEFT_OF_SHIP, -3299, -457, 3800), + RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_48_RBB_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, -650, 562, -35), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_49_RBB_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, -278, 710, -557), + RC(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4C_RBB_INSIDE_KITCHEN, -771, 238, -293), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BUNK_IN_CABIN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4A_RBB_TOP_OF_BUNK_IN_CABIN, 583, 323, -70), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_50_RBB_TOP_OF_BOX_INSIDE_TNT_ROOM, -435, 300, -435), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4D_RBB_ENGINE_ROOM_LEFT_PIPE, -2450, 1100, -400), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4E_RBB_ENGINE_ROOM_RIGHT_PIPE, 2450, 1100, -400), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_SPINNING_PLATFORM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4F_RBB_ENGINE_ROOM_SPINNING_PLATFORM, -319, 12, 1899), + RC(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4B_RBB_INSIDE_NAVIGATION_ROOM, -656, 0, -222), RC(RC_RBB_NOTE_ANCHOR_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3500, 449, -501), RC(RC_RBB_NOTE_ANCHOR_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3499, 449, 499), RC(RC_RBB_NOTE_ANCHOR_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 4499, 449, -500), @@ -1820,81 +1815,81 @@ std::map Checks = { RC(RC_SM_EMPTY_HONEYCOMB_TREE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_16_SM_TREE, -2752, 1299, 37), RC(RC_SM_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_15_SM_UNDERWATER, -264, -442, -651), RC(RC_SM_EMPTY_HONEYCOMB_WATERFALL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_14_SM_WATERFALL, -6725, 1300, -1803), - RC(RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, NULL, 3656, 339, 6552), - RC(RC_SM_EXTRA_LIFE_WATERFALL, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, NULL, -7108, 1200, -3079), + RC(RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE, NULL, 3656, 339, 6552), + RC(RC_SM_EXTRA_LIFE_WATERFALL, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE, NULL, -7108, 1200, -3079), RC(RC_SM_MOLEHILL_ATTACK, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLAW_SWIPE, ABILITY_4_CLAW_SWIPE, 4675, 400, 511), RC(RC_SM_MOLEHILL_BEAK_BARGE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_BARGE, ABILITY_0_BARGE, 3271, -110, -2673), RC(RC_SM_MOLEHILL_CAMERA_CONTROL, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CAMERA_CONTROL, ABILITY_3_CAMERA_CONTROL, 2250, -34, 2774 ), RC(RC_SM_MOLEHILL_CLIMB, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLIMB, ABILITY_5_CLIMB, -1999, 342, -2545), RC(RC_SM_MOLEHILL_DIVE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_DIVE, ABILITY_F_DIVE, -2336, 302, 973), RC(RC_SM_MOLEHILL_JUMP, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_FLAP_FLIP, ABILITY_8_FLAP_FLIP, -164, -190, 3313), - RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1667, 1639), - RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1792, 1639), - RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1917, 1639), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -2906, 1012, -6249), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -2941, 1011, -6045), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3580, 1062, -5526), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3808, 1062, -5389), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3978, 1312, -5163), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3995, 1312, -4990), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4215, 1411, -4547), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4413, 1412, -4482), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -106, -23, 186), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -142, -23, 315), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -267, -23, 318), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -306, -23, 212), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -215, -23, 117), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 1012, 5782, -2017), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 864, 5826, -1874), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 648, 5857, -1874), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 743, 6580, -3494), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 944, 6625, -3436), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 1077, 6667, -3226), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2475, 5793, -2303), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2357, 5791, -2182), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2351, 5822, -2417), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2241, 5819, -2305), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 720, 5819, -4297), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 869, 5820, -4332), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 750, 5791, -4131), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 918, 5793, -4172), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1269, 5795, -2811), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1147, 5822, -2700), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1145, 5792, -2928), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1037, 5818, -2802), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 687, 5822, -1177), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 843, 5819, -1172), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 857, 5793, -1336), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 689, 5794, -1347), - RC(RC_TTC_BLUE_EGG_LOCKUP_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3966, 1190, 1747), - RC(RC_TTC_BLUE_EGG_LOCKUP_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4051, 1190, 1793), - RC(RC_TTC_BLUE_EGG_LOCKUP_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4051, 1190, 1706), - RC(RC_TTC_BLUE_EGG_LOCKUP_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3882, 1190, 1795), - RC(RC_TTC_BLUE_EGG_LOCKUP_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3882, 1190, 1707), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -5319, 2470, -2929), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -5154, 2470, -3256), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4975, 2470, -3543), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4749, 2470, -3780), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4410, 2470, -3814), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4092, 2470, -3826), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3957, 2470, -3586), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 4539, 1667, 1639), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 4539, 1792, 1639), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 4539, 1917, 1639), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -2906, 1012, -6249), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -2941, 1011, -6045), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3580, 1062, -5526), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3808, 1062, -5389), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3978, 1312, -5163), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3995, 1312, -4990), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4215, 1411, -4547), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4413, 1412, -4482), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -106, -23, 186), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -142, -23, 315), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -267, -23, 318), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -306, -23, 212), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -215, -23, 117), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 1012, 5782, -2017), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 864, 5826, -1874), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 648, 5857, -1874), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 743, 6580, -3494), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 944, 6625, -3436), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 1077, 6667, -3226), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2475, 5793, -2303), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2357, 5791, -2182), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2351, 5822, -2417), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2241, 5819, -2305), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 720, 5819, -4297), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 869, 5820, -4332), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 750, 5791, -4131), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 918, 5793, -4172), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1269, 5795, -2811), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1147, 5822, -2700), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1145, 5792, -2928), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1037, 5818, -2802), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 687, 5822, -1177), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 843, 5819, -1172), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 857, 5793, -1336), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 689, 5794, -1347), + RC(RC_TTC_BLUE_EGG_LOCKUP_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3966, 1190, 1747), + RC(RC_TTC_BLUE_EGG_LOCKUP_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4051, 1190, 1793), + RC(RC_TTC_BLUE_EGG_LOCKUP_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4051, 1190, 1706), + RC(RC_TTC_BLUE_EGG_LOCKUP_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3882, 1190, 1795), + RC(RC_TTC_BLUE_EGG_LOCKUP_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3882, 1190, 1707), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -5319, 2470, -2929), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -5154, 2470, -3256), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4975, 2470, -3543), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4749, 2470, -3780), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4410, 2470, -3814), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4092, 2470, -3826), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3957, 2470, -3586), RC(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_4_TTC_FLOATING_BOX, 8473, 844, -2684), RC(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_3_TTC_UNDERWATER, -4303, 46, 115), - RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, -2442, 3158, -1706), - RC(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 5864, 677, 7898), - RC(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 4710, 323, -6007), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE, NULL, -2442, 3158, -1706), + RC(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE, NULL, 5864, 677, 7898), + RC(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE, NULL, 4710, 323, -6007), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), RC(RC_TTC_JIGGY_ALCOVE1, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0D_TTC_ALCOVE_1, 2832, 2152, -1797), RC(RC_TTC_JIGGY_ALCOVE2, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0E_TTC_ALCOVE_2, -5116, 1417, -3915), RC(RC_TTC_JIGGY_BLUBBER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_14_TTC_BLUBBER, 0, 0, 0), @@ -1912,16 +1907,16 @@ std::map Checks = { RC(RC_TTC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_YELLOW_TREASURE_TROVE_COVE, NULL, -968, 5358, -776), RC(RC_TTC_MOLEHILL_FLIGHT, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, RI_MOLEHILL_FLIGHT, ABILITY_9_FLIGHT, -288, 2161, 1314), RC(RC_TTC_MOLEHILL_SHOCK_JUMP, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, RI_MOLEHILL_SHOCK_JUMP, ABILITY_D_SHOCK_JUMP, 2698, 1517, 3338), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_PILLAR_UNDERWATER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0C_TTC_BEHIND_PILLAR_UNDERWATER, 6480, 597, -258), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0A_TTC_BEHIND_LIGHTHOUSE_DOOR, 565, 6917, -2776), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_NIPPER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0F_TTC_BEHIND_NIPPER, -6620, 510, 4621), - RC(RC_TTC_MUMBO_TOKEN_FLOATING_ABOVE_SHOCKJUMP_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0E_TTC_FLOATING_ABOVE_SHOCKJUMP_PAD, 2462, 2217, 2957), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_1, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_07_TTC_INSIDE_LOCKUP_1, -2660, 2447, -6079), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_2, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_08_TTC_INSIDE_LOCKUP_2, -2646, 2447, -6223), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_SALTY_HIPPO, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_06_TTC_INSIDE_SALTY_HIPPO, 610, -412, 31), - RC(RC_TTC_MUMBO_TOKEN_ON_FLOATING_BOX, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0B_TTC_ON_FLOATING_BOX, -783, 745, -3872), - RC(RC_TTC_MUMBO_TOKEN_POND_BOTTOM, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0D_TTC_POND_BOTTOM, -4932, 1122, -1063), - RC(RC_TTC_MUMBO_TOKEN_SALTY_HIPPO_MAST, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_09_TTC_SALTY_HIPPO_MAST, -221, 2029, 929), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_PILLAR_UNDERWATER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0C_TTC_BEHIND_PILLAR_UNDERWATER, 6480, 597, -258), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0A_TTC_BEHIND_LIGHTHOUSE_DOOR, 565, 6917, -2776), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_NIPPER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0F_TTC_BEHIND_NIPPER, -6620, 510, 4621), + RC(RC_TTC_MUMBO_TOKEN_FLOATING_ABOVE_SHOCKJUMP_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0E_TTC_FLOATING_ABOVE_SHOCKJUMP_PAD, 2462, 2217, 2957), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_1, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_07_TTC_INSIDE_LOCKUP_1, -2660, 2447, -6079), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_2, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_08_TTC_INSIDE_LOCKUP_2, -2646, 2447, -6223), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_SALTY_HIPPO, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_06_TTC_INSIDE_SALTY_HIPPO, 610, -412, 31), + RC(RC_TTC_MUMBO_TOKEN_ON_FLOATING_BOX, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0B_TTC_ON_FLOATING_BOX, -783, 745, -3872), + RC(RC_TTC_MUMBO_TOKEN_POND_BOTTOM, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0D_TTC_POND_BOTTOM, -4932, 1122, -1063), + RC(RC_TTC_MUMBO_TOKEN_SALTY_HIPPO_MAST, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_09_TTC_SALTY_HIPPO_MAST, -221, 2029, 929), RC(RC_TTC_NOTE_BEACH_LOCKUP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4802, 737, -2351), RC(RC_TTC_NOTE_BEACH_LOCKUP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4730, 737, -2420), RC(RC_TTC_NOTE_BEACH_LOCKUP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4803, 736, -2444), diff --git a/src/port/Rando/StaticData/Flags.cpp b/src/port/Rando/StaticData/Flags.cpp index 4f807dd28..0fad9ae3d 100644 --- a/src/port/Rando/StaticData/Flags.cpp +++ b/src/port/Rando/StaticData/Flags.cpp @@ -17,7 +17,6 @@ namespace StaticData { std::map Flags = { RF(RANDO_INF_UNKNOWN, RO_GENERIC_OFF), RF(RANDO_INF_ANCHOR_RAISED, RO_GENERIC_OFF), - RF(RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, RO_GENERIC_OFF), RF(RANDO_INF_CLANKER_RAISED, RO_GENERIC_OFF), RF(RANDO_INF_MINIGAME_RINGS_COMPLETED, RO_GENERIC_OFF), RF(RANDO_INF_WATER_PYRAMID_DRAINED, RO_GENERIC_OFF), diff --git a/src/port/Rando/StaticData/Items.cpp b/src/port/Rando/StaticData/Items.cpp index 415740927..65591bdeb 100644 --- a/src/port/Rando/StaticData/Items.cpp +++ b/src/port/Rando/StaticData/Items.cpp @@ -10,59 +10,29 @@ namespace Rando { namespace StaticData { -#define RI(id, article, name, type, actorId) \ - { \ - id, { \ - id, #id, article, name, type, actorId \ - } \ +#define RI(id, article, name, type, actorId, worldId) \ + { \ + id, { \ + id, #id, article, name, type, actorId, worldId \ + } \ } // clang-format off std::map Items = { RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN, LEVEL_D_CUTSCENE), - RI(RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, "a", "Blue Egg - BGS", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_BLUE_EGG_CLANKERS_CAVERN, "a", "Blue Egg - CC", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN), - RI(RI_BLUE_EGG_CLICK_CLOCK_WOOD, "a", "Blue Egg - CCW", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_BLUE_EGG_FREEZEEZY_PEAK, "a", "Blue Egg - FP", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_BLUE_EGG_GOBIS_VALLEY, "a", "Blue Egg - GV", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_7_GOBIS_VALLEY), - RI(RI_BLUE_EGG_GRUNTILDAS_LAIR, "a", "Blue Egg - Gl", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_6_LAIR), - RI(RI_BLUE_EGG_MAD_MONSTER_MANSION, "a", "Blue Egg - MMM", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_BLUE_EGG_MUMBOS_MOUNTAIN, "a", "Blue Egg - MM", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_BLUE_EGG_RUSTY_BUCKET_BAY, "a", "Blue Egg - RBB", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_BLUE_EGG_TREASURE_TROVE_COVE, "a", "Blue Egg - TTC", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_BLUE_EGG, "a", "Blue Egg", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_D_CUTSCENE), RI(RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Empty Honeycomb - BGS", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, "a", "Empty Honeycomb - CC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), RI(RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Empty Honeycomb - CCW", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), RI(RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, "a", "Empty Honeycomb - FP", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), RI(RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, "a", "Empty Honeycomb - GV", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), - RI(RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Empty Honeycomb - GL", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_6_LAIR), RI(RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Empty Honeycomb - MMM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), RI(RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Empty Honeycomb - MM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), RI(RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Empty Honeycomb - RBB", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), RI(RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Empty Honeycomb - SM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN), RI(RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Empty Honeycomb - TTC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, "an", "Extra Life - BGS", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_EXTRA_LIFE_CLANKERS_CAVERN, "an", "Extra Life - CC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN), - RI(RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, "an", "Extra Life - CCW", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_EXTRA_LIFE_FREEZEEZY_PEAK, "an", "Extra Life - FP", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_EXTRA_LIFE_GOBIS_VALLEY, "an", "Extra Life - GV", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY), - RI(RI_EXTRA_LIFE_GRUNTILDAS_LAIR, "an", "Extra Life - GL", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_6_LAIR), - RI(RI_EXTRA_LIFE_MAD_MONSTER_MANSION, "an", "Extra Life - MMM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, "an", "Extra Life - MM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, "an", "Extra Life - RBB", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, "an", "Extra Life - SM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_EXTRA_LIFE_TREASURE_TROVE_COVE, "an", "Extra Life - TTC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Honeycomb - BGS", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_HONEYCOMB_CLANKERS_CAVERN, "a", "Honeycomb - CC", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), - RI(RI_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Honeycomb - CCW", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_HONEYCOMB_FREEZEEZY_PEAK, "a", "Honeycomb - FP", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_HONEYCOMB_GOBIS_VALLEY, "a", "Honeycomb - GV", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), - RI(RI_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Honeycomb - GL", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_6_LAIR), - RI(RI_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Honeycomb - MMM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Honeycomb - MM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Honeycomb - RBB", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Honeycomb - SM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN), - RI(RI_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Honeycomb - TTC", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_EXTRA_LIFE, "an", "Extra Life", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_D_CUTSCENE), + RI(RI_HONEYCOMB, "a", "Honeycomb", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_D_CUTSCENE), RI(RI_JIGGY_BUBBLEGLOOP_SWAMP, "a", "Jiggy - BGS", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_JIGGY_CLANKERS_CAVERN, "a", "Jiggy - CC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_3_CLANKERS_CAVERN), RI(RI_JIGGY_CLICK_CLOCK_WOOD, "a", "Jiggy - CCW", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD), @@ -133,16 +103,7 @@ std::map Items = { RI(RI_MOLEHILL_TURBO_TALON, "", "Turbo Talon", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_7_GOBIS_VALLEY), RI(RI_MOLEHILL_WADING_BOOTS, "", "Wading Boots", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_MOLEHILL_WONDERWING, "", "Wonderwing", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_3_CLANKERS_CAVERN), - RI(RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, "a", "Mumbo Token - BGS", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP), - RI(RI_MUMBO_TOKEN_CLANKERS_CAVERN, "a", "Mumbo Token - CC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN), - RI(RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, "a", "Mumbo Token - CCW", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD), - RI(RI_MUMBO_TOKEN_FREEZEEZY_PEAK, "a", "Mumbo Token - FP", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_MUMBO_TOKEN_GOBIS_VALLEY, "a", "Mumbo Token - GV", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY), - RI(RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, "a", "Mumbo Token - GL", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_6_LAIR), - RI(RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, "a", "Mumbo Token - MMM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION), - RI(RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, "a", "Mumbo Token - MM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN), - RI(RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, "a", "Mumbo Token - RBB", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY), - RI(RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, "a", "Mumbo Token - TTC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_MUMBO_TOKEN, "a", "Mumbo Token", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_D_CUTSCENE), RI(RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, "a", "Note - BGS", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_MUSIC_NOTE_CLANKERS_CAVERN, "a", "Note - CC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN), RI(RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, "a", "Note - CCW", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD), @@ -159,6 +120,7 @@ std::map Items = { RI(RI_STOP_N_SWOP_EGG_RED, "a", "Red Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_9_RUSTY_BUCKET_BAY), RI(RI_STOP_N_SWOP_EGG_YELLOW, "a", "Yellow Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_8_CLICK_CLOCK_WOOD), RI(RI_STOP_N_SWOP_ICE_KEY, "an", "Ice Key", RITYPE_SNS_KEY, ACTOR_25D_ICE_KEY, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_AP_ITEM_PROGRESSION, "a", "AP Progression Item", RITYPE_AP_ITEM, ACTOR_3CD_CUSTOM_COLLECTIBLE, LEVEL_D_CUTSCENE), }; // clang-format on diff --git a/src/port/Rando/StaticData/StaticData.h b/src/port/Rando/StaticData/StaticData.h index bfb3cb9ff..030f55954 100644 --- a/src/port/Rando/StaticData/StaticData.h +++ b/src/port/Rando/StaticData/StaticData.h @@ -13,6 +13,7 @@ namespace Rando { namespace StaticData { void SendCollisionNotification(RandoCheckId randoCheckId); +void SendRemoteCheckNotification(RandoCheckId randoCheckId, const std::string& collectorName); struct RandoLogicData { const char* name; diff --git a/src/port/Rando/Types.h b/src/port/Rando/Types.h index ba6b63e3f..146d7c8cc 100644 --- a/src/port/Rando/Types.h +++ b/src/port/Rando/Types.h @@ -2040,54 +2040,25 @@ typedef enum { RITYPE_MUSIC_NOTE, RITYPE_SNS_EGG, RITYPE_SNS_KEY, + RITYPE_AP_ITEM, RITYPE_MAX, } RandoItemType; typedef enum { RI_UNKNOWN, - RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, - RI_BLUE_EGG_CLANKERS_CAVERN, - RI_BLUE_EGG_CLICK_CLOCK_WOOD, - RI_BLUE_EGG_FREEZEEZY_PEAK, - RI_BLUE_EGG_GOBIS_VALLEY, - RI_BLUE_EGG_GRUNTILDAS_LAIR, - RI_BLUE_EGG_MAD_MONSTER_MANSION, - RI_BLUE_EGG_MUMBOS_MOUNTAIN, - RI_BLUE_EGG_RUSTY_BUCKET_BAY, - RI_BLUE_EGG_TREASURE_TROVE_COVE, + RI_BLUE_EGG, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, - RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, - RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, - RI_EXTRA_LIFE_CLANKERS_CAVERN, - RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, - RI_EXTRA_LIFE_FREEZEEZY_PEAK, - RI_EXTRA_LIFE_GOBIS_VALLEY, - RI_EXTRA_LIFE_GRUNTILDAS_LAIR, - RI_EXTRA_LIFE_MAD_MONSTER_MANSION, - RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, - RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, - RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, - RI_EXTRA_LIFE_TREASURE_TROVE_COVE, - RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, - RI_HONEYCOMB_CLANKERS_CAVERN, - RI_HONEYCOMB_CLICK_CLOCK_WOOD, - RI_HONEYCOMB_FREEZEEZY_PEAK, - RI_HONEYCOMB_GOBIS_VALLEY, - RI_HONEYCOMB_GRUNTILDAS_LAIR, - RI_HONEYCOMB_MAD_MONSTER_MANSION, - RI_HONEYCOMB_MUMBOS_MOUNTAIN, - RI_HONEYCOMB_RUSTY_BUCKET_BAY, - RI_HONEYCOMB_SPIRAL_MOUNTAIN, - RI_HONEYCOMB_TREASURE_TROVE_COVE, + RI_EXTRA_LIFE, + RI_HONEYCOMB, RI_JIGGY_BUBBLEGLOOP_SWAMP, RI_JIGGY_CLANKERS_CAVERN, RI_JIGGY_CLICK_CLOCK_WOOD, @@ -2158,16 +2129,7 @@ typedef enum { RI_MOLEHILL_TURBO_TALON, RI_MOLEHILL_WADING_BOOTS, RI_MOLEHILL_WONDERWING, - RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, - RI_MUMBO_TOKEN_CLANKERS_CAVERN, - RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, - RI_MUMBO_TOKEN_FREEZEEZY_PEAK, - RI_MUMBO_TOKEN_GOBIS_VALLEY, - RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, - RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, - RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, - RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, - RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, + RI_MUMBO_TOKEN, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, @@ -2184,6 +2146,7 @@ typedef enum { RI_STOP_N_SWOP_EGG_RED, RI_STOP_N_SWOP_EGG_YELLOW, RI_STOP_N_SWOP_ICE_KEY, + RI_AP_ITEM_PROGRESSION, RI_MAX, } RandoItemId; @@ -2419,7 +2382,6 @@ typedef enum { typedef enum { RANDO_INF_UNKNOWN, RANDO_INF_ANCHOR_RAISED, - RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, RANDO_INF_CLANKER_RAISED, RANDO_INF_MINIGAME_RINGS_COMPLETED, RANDO_INF_WATER_PYRAMID_DRAINED, @@ -2432,7 +2394,8 @@ typedef struct RandoSaveCheck { RandoItemId randoItemId; int32_t randoCollectionId; bool isShuffled; - bool obtained; + bool eligible; + bool received; bool skipped; } RandoSaveCheck; diff --git a/src/port/Resource/Alt/AltBoldFont.cpp b/src/port/Resource/Alt/AltBoldFont.cpp index df9c8524e..c5ec43030 100644 --- a/src/port/Resource/Alt/AltBoldFont.cpp +++ b/src/port/Resource/Alt/AltBoldFont.cpp @@ -23,6 +23,7 @@ #include #include +#include "AltPathPool.h" #include "AltSprites.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" @@ -41,7 +42,11 @@ struct ChunkHeader { int16_t x, y, w, h; }; -std::unordered_map sByOutput; +// resolveHd hands these strings' addresses into display lists, and texture +// binds may be memoized on that address downstream: the strings must be +// immutable and immortal, so they live in the shared alt-path pool. +// reset() clears the output mapping, never the pool. +std::unordered_map sByOutput; std::unordered_set sBuilt; std::mutex sMutex; @@ -135,7 +140,7 @@ void buildHd(const void* output, const void* maskChunk, const void* sphereChunk) std::unique_lock lock(sMutex); if (sBuilt.count(cachePath)) { - sByOutput[output] = "__OTR__" + cachePath; + sByOutput[output] = InternAltPath("__OTR__" + cachePath); return; } @@ -143,7 +148,7 @@ void buildHd(const void* output, const void* maskChunk, const void* sphereChunk) // the identity path. Serve it directly and skip compositing. if (Ship::Context::GetRawInstance()->GetResourceManager()->GetArchiveManager()->HasFile("alt/" + cachePath)) { sBuilt.insert(cachePath); - sByOutput[output] = "__OTR__" + cachePath; + sByOutput[output] = InternAltPath("__OTR__" + cachePath); return; } lock.unlock(); @@ -211,7 +216,7 @@ void buildHd(const void* output, const void* maskChunk, const void* sphereChunk) lock.lock(); sBuilt.insert(cachePath); - sByOutput[output] = "__OTR__" + cachePath; + sByOutput[output] = InternAltPath("__OTR__" + cachePath); } void resolveHd(const void* output, const char** path) { @@ -221,7 +226,7 @@ void resolveHd(const void* output, const char** path) { std::lock_guard lock(sMutex); auto it = sByOutput.find(output); if (it != sByOutput.end()) { - *path = it->second.c_str(); + *path = it->second; } } diff --git a/src/port/Resource/Alt/AltDialogFont.cpp b/src/port/Resource/Alt/AltDialogFont.cpp new file mode 100644 index 000000000..76c2782c6 --- /dev/null +++ b/src/port/Resource/Alt/AltDialogFont.cpp @@ -0,0 +1,160 @@ +// Cross-revision HD dialog font. +// +// The dialog font changed between ROM revisions: US v1.0 has 62 glyphs at native 8x12; v1.1/PAL/JP +// extended it to 75 glyphs at 8x13 (the extra 13 are the PAL accents; every glyph also grew one row). +// A LOAD_AS_RAW alt bakes its h/v scale factors against the native dims of the ROM the pack was built +// from, so a v1.0-built pack's glyph carries a scale computed for 12 rows. +// +// The pixels are fine; only the baked scale is wrong, and it is wrong purely because native dims +// differ between revisions. Calculate and re-scale port-side so hd packs don't need per-revision art. + +#include +#include +#include +#include + +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Patches/Patches.h" +#include "port/ResourceHelpers.h" +#include "port/ShipInit.hpp" + +#include +#include +#include +#include +#include +#include + +namespace { + +constexpr uint32_t kDialogFontAssetId = 0x6EB; +constexpr const char* kFontBaseFallback = "assets/sprite/ASSET_6EB_DIALOG_FONT_ALPHAMASK"; +std::unordered_set sBuiltSheets; +std::string fontSheetPath(std::string resolved) { + return resolved.empty() ? kFontBaseFallback : resolved; +} + +std::shared_ptr loadTex(const std::string& path, bool loadExact) { + return std::static_pointer_cast( + Ship::Context::GetRawInstance()->GetResourceManager()->LoadResourceProcess(path, loadExact)); +} + +// HD art for one chunk: the active sheet's own alt when the pack ships one, else the base game's +// alt for the same slot. Null when neither has art for it. +std::shared_ptr loadHdChunk(const std::string& activePath, const std::string& basePath, + const Fast::Texture* nativeCell, bool& fromBaseSheet) { + fromBaseSheet = false; + auto alt = loadTex(activePath, false); + if (alt != nullptr && alt.get() != nativeCell) { + return alt; + } + if (basePath == activePath) { + return nullptr; + } + fromBaseSheet = true; + return loadTex(Ship::IResource::gAltAssetPrefix + basePath, true); +} + +// Build a corrected alt for one chunk and cache it under "alt/". Returns false when +// there is nothing to do: no alt shipped, the dims already reconcile, or it isn't an HD raw texture. +bool correctChunk(const std::string& activePath, const std::string& basePath) { + auto base = loadTex(activePath, true); // live native cell + if (base == nullptr || base->Width <= 0 || base->Height <= 0) { + return false; + } + bool fromBaseSheet = false; + auto alt = loadHdChunk(activePath, basePath, base.get(), fromBaseSheet); + if (alt == nullptr || alt->ImageData == nullptr) { + return false; + } + if (alt->Type != Fast::TextureType::RGBA32bpp || (alt->Flags & TEX_FLAG_LOAD_AS_RAW) == 0) { + return false; + } + + const int nativeW = base->Width; + const int nativeH = base->Height; + + // Width is revision-stable (drift is height-only), so the integer scale comes cleanly off it. + // Bail if the alt isn't an integer multiple of the native width, or is degenerate. + if (nativeW <= 0 || alt->Width % nativeW != 0) { + return false; + } + const int k = alt->Width / nativeW; + if (k < 1) { + return false; + } + + const int dstW = nativeW * k; + const int dstH = nativeH * k; + // Matching heights mean no drift to correct. Art borrowed from the base sheet still has to be + // re-cached, though: nothing is reachable at the active path until we put it there. + if (dstH == (int)alt->Height && !fromBaseSheet) { + return false; + } + + // Top-align the HD rows into the k-scaled native cell; the zero-filled remainder stays transparent. + const int copyRows = (int)alt->Height < dstH ? (int)alt->Height : dstH; + const int rowBytes = dstW * 4; + + auto pixels = std::make_shared>((size_t)dstW * dstH * 4, 0); + for (int r = 0; r < copyRows; r++) { + std::memcpy(pixels->data() + (size_t)r * rowBytes, alt->ImageData + (size_t)r * rowBytes, (size_t)rowBytes); + } + + // Same HD pixels, but VPixelScale re-derived against the live native rows (native_rows * k == dstH). + // Cache under the alt path so the resource layer returns this in place of the raw archive alt. + const std::string altPath = Ship::IResource::gAltAssetPrefix + activePath; + auto initData = std::make_shared(); + initData->Path = altPath; + auto tex = std::make_shared(initData); + tex->Type = Fast::TextureType::RGBA32bpp; + tex->Width = (uint16_t)dstW; + tex->Height = (uint16_t)dstH; + tex->Flags = TEX_FLAG_LOAD_AS_RAW; + tex->HByteScale = alt->HByteScale; + tex->VPixelScale = (float)k; + tex->ImageDataSize = (uint32_t)pixels->size(); + tex->mImageBuffer = pixels; + tex->ImageData = (uint8_t*)pixels->data(); + + Ship::Context::GetRawInstance()->GetResourceManager()->CacheExternalResource(altPath, tex); + return true; +} + +} // namespace + +// Called when the dialog font is (re)loaded, boot and language switch alike. Scans every chunk of +// the sheet now in play and corrects each. +extern "C" void port_dialogFontHd_rebuild(void) { + if (!Ship::Context::GetRawInstance()->GetResourceManager()->IsAltAssetsEnabled()) { + return; + } + + const std::string activeFont = fontSheetPath(ResourceHelpers_GetActiveAssetPath(kDialogFontAssetId)); + if (sBuiltSheets.count(activeFont) != 0) { + return; + } + const std::string baseFont = fontSheetPath(ResourceHelpers_GetBaseAssetPath(kDialogFontAssetId)); + + bool built = false; + for (int frame = 0; frame < 64; frame++) { + bool anyInFrame = false; + for (int chunk = 0; chunk < 256; chunk++) { + const std::string suffix = "_" + std::to_string(frame) + "_" + std::to_string(chunk); + const std::string activePath = activeFont + suffix; + if (loadTex(activePath, true) == nullptr) { + break; + } + anyInFrame = true; + built = true; + correctChunk(activePath, baseFont + suffix); + } + if (!anyInFrame) { + break; + } + } + + if (built) { + sBuiltSheets.insert(activeFont); + } +} diff --git a/src/port/Resource/GfxBridge.c b/src/port/Resource/GfxBridge.c index 30c28c9a5..cf62f287f 100644 --- a/src/port/Resource/GfxBridge.c +++ b/src/port/Resource/GfxBridge.c @@ -5,6 +5,8 @@ // __OTR__ asset paths instead of raw RAM; these wrappers detect that, swap in the // loaded resource via the ResourceManager, then forward to the real __gSP* GBI ops. +#include + #include "libultraship/libultra/gbi.h" #include "libultraship/bridge/resourcebridge.h" #include "src/port/ResourceHelpers.h" @@ -12,12 +14,9 @@ int ResourceMgr_OTRSigCheck(char* imgData) { uintptr_t i = (uintptr_t)(imgData); - // [port] Reject N64 segmented addresses and special sentinels. - // Segmented addresses fit in 32 bits with a non-zero segment byte (bits 24-31). - // Bit 0 set = already-tagged segmented address from stub GBI functions. - if ((i & 1) == 1) - return 0; - if (i != 0 && i <= 0xFFFFFFFF && (i >> 24) != 0) + // [port] Guard against small integers masquerading as pointers, which arise when + // N64 code computes an address from a NULL-based buffer. + if (i < 0x10000) return 0; // if ((i & 0xFF000000) != 0xAB000000 && (i & 0xFF000000) != 0xCD000000 && i != 0) { @@ -52,20 +51,25 @@ void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset) { __gSPDisplayList(pkt, dl + offset); } +// [port] `v` is a host pointer or an __OTR__ path. It is never a segmented address: +// callers that mean "segment N, offset off" use gSPVertexSeg. void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0) { if (ResourceMgr_OTRSigCheck((char*)v) == 1) v = (uintptr_t)ResourceMgr_LoadVtxByName((char*)v); - // [port] Mark N64 segmented addresses with bit 0 so the interpreter's SegAddr resolves them. - // SEGMENT_ADDR(num, off) produces values like 0x01000000 without bit 0 set. - // Segmented addresses fit in 32 bits with a non-zero segment byte (bits 24-31). - if (v != 0 && v <= 0xFFFFFFFF && (v >> 24) != 0) { - v |= 1; - } - __gSPVertex(pkt, v, n, v0); } +// [port] Emit a vertex command that references segment `seg` at byte offset `off`. +// Bit 0 is the tag Fast::Interpreter::SegAddr keys on to resolve against its segment +// table; host pointers are always even, so the two can never be confused. +void gSPVertexSeg(Gfx* pkt, u32 seg, uintptr_t off, int n, int v0) { + assert(seg < 16); + assert(off <= 0x00FFFFFE); + + __gSPVertex(pkt, ((uintptr_t)(seg & 0xF) << 24) | (off & 0x00FFFFFEu) | 1u, n, v0); +} + void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr) { char* imgData = (char*)texAddr; diff --git a/src/port/Resource/Importers/MapFactory.cpp b/src/port/Resource/Importers/MapFactory.cpp index 68f90b4de..d7a19d22a 100644 --- a/src/port/Resource/Importers/MapFactory.cpp +++ b/src/port/Resource/Importers/MapFactory.cpp @@ -128,19 +128,24 @@ void SerializeLegacyMapData(std::vector& out, const std::vector(cube.nodeProps.size(), 0xFF); out.push_back(0x0A); - out.push_back(static_cast(std::min(cube.nodeProps.size(), 0xFF))); + out.push_back(static_cast(nodeCnt)); out.push_back(0x0B); - for (const auto& node : cube.nodeProps) { - WriteNodeProp(out, node); + for (size_t n = 0; n < nodeCnt; n++) { + WriteNodeProp(out, cube.nodeProps[n]); } } if (!cube.props.empty()) { + const size_t propCnt = std::min(cube.props.size(), 0xFF); out.push_back(0x08); - out.push_back(static_cast(std::min(cube.props.size(), 0xFF))); + out.push_back(static_cast(propCnt)); out.push_back(0x09); - for (const auto& prop : cube.props) { + for (size_t pi = 0; pi < propCnt; pi++) { + const auto& prop = cube.props[pi]; // [port] Props are raw 12-byte N64 big-endian structs from the ROM. // Layout: u32(4) + s16(2) + s16(2) + s16(2) + u16(2) = 12 bytes. // Byte-swap each multi-byte field to native (little-endian) order diff --git a/src/port/Resource/Importers/ModelFactory.cpp b/src/port/Resource/Importers/ModelFactory.cpp index c1c4ebc41..409d3ccf3 100644 --- a/src/port/Resource/Importers/ModelFactory.cpp +++ b/src/port/Resource/Importers/ModelFactory.cpp @@ -6,12 +6,12 @@ #include #include "port/Resource/Alt/AltPathPool.h" +#include "port/Enhancements/Events/Hooks/Events.h" #include +#include -extern "C" { #include "model.h" -} namespace Factories { namespace { @@ -132,6 +132,18 @@ ResourceFactoryBinaryModelV0::ReadResource(std::shared_ptr file, tm.type, tm.width, tm.height, tm.tlutColors, tm.textureDataOffset); } + // Let enhancements patch the raw display list before it is widened. + // Command indices must be preserved; the geo layout references them by position. + if (!rawDLWords.empty() && texCount > 0) { + std::vector texSizes; + texSizes.reserve(texMetas.size()); + for (const auto& tm : texMetas) { + texSizes.push_back(ModelTexSize{ tm.width, tm.height }); + } + CALL_EVENT(OnModelDisplayListLoad, initData->Path.c_str(), rawDLWords.data(), + static_cast(rawDLWords.size()), texSizes.data(), texCount); + } + // Raw texture data blob — full contiguous pixel area from the ROM. // Preserves animated texture frames and unlisted data between textures. uint32_t rawTexDataSize = reader->ReadUInt32(); @@ -386,29 +398,22 @@ ResourceFactoryBinaryModelV0::ReadResource(std::shared_ptr file, // // Layout (each section padded to 8-byte alignment): // [ 0 ] BKModelBin header (zero-init, geo_type set) - // [ GL ] GeoLayout command tree → geo_list_offset - // [ T ] BKTextureList + BKTextureInfo[] + pixel data → texture_list_offset - // [ A ] BKAnimationList + BKAnimation[] → animation_list_offset - // [ B ] BKCollisionList + ColGeo[] + ColTri[] → collision_list_offset - // [ 14 ] BKModelUnk14List + entries → unk14 - // [ 20 ] BKCameraAreaList + entries → unk20 - // [ E ] effect count (s16) + effects → mesh_list_offset - // [ 28 ] BKAnimVerticesList + entries → unk28 - // [ AT ] AnimTexture[4] → animated_texture_list_offset - // [ V ] BKVertexList header + Vtx[] → vtx_list_offset - // [ G ] BKGfxList header + Gfx[] → gfx_list_offset + // [ T ] BKTextureList + BKTextureInfo[] + pixel data -> texture_list_offset + // [ GL ] GeoLayout command tree -> geo_list_offset + // [ A ] BKAnimationList + BKAnimation[] -> animation_list_offset + // [ B ] BKCollisionList + ColGeo[] + ColTri[] -> collision_list_offset + // [ 14 ] BKModelUnk14List + entries -> unk14 + // [ 20 ] BKCameraAreaList + entries -> unk20 + // [ E ] effect count (s16) + effects -> mesh_list_offset + // [ 28 ] BKAnimVerticesList + entries -> unk28 + // [ AT ] AnimTexture[4] -> animated_texture_list_offset + // [ V ] BKVertexList header + Vtx[] -> vtx_list_offset + // [ G ] BKGfxList header + Gfx[] -> gfx_list_offset auto out = std::vector(sizeof(BKModelBin), 0); auto hdr = [&]() -> BKModelBin* { return reinterpret_cast(out.data()); }; hdr()->geo_type = static_cast(geoType); - // GeoLayout section - if (geoBlob && !geoBlob->Data.empty()) { - PadTo8(out); - hdr()->geo_list_offset = static_cast(out.size()); - AppendBytes(out, geoBlob->Data.data(), geoBlob->Data.size()); - } - // Texture section if (texCount > 0) { PadTo8(out); @@ -441,13 +446,16 @@ ResourceFactoryBinaryModelV0::ReadResource(std::shared_ptr file, // Write pixel data area (raw blob from Torch) if (blobPtr) { AppendBytes(out, blobPtr, rawTexDataSize); - } else { - // Fallback: zero-filled if blob was missing - for (uint32_t i = 0; i < rawTexDataSize; i++) - out.push_back(0); } } + // GeoLayout section + if (geoBlob && !geoBlob->Data.empty()) { + PadTo8(out); + hdr()->geo_list_offset = static_cast(out.size()); + AppendBytes(out, geoBlob->Data.data(), geoBlob->Data.size()); + } + // Animation section if (hasAnim) { PadTo8(out); diff --git a/src/port/Resource/Type/Sprite.cpp b/src/port/Resource/Type/Sprite.cpp index 38c8c0e7e..72c12daef 100644 --- a/src/port/Resource/Type/Sprite.cpp +++ b/src/port/Resource/Type/Sprite.cpp @@ -125,27 +125,6 @@ void Sprite::BuildSpriteStructure() { // SPDLOG_DEBUG(" Frame buffer size: {} bytes, pointer: {}", // frameSizes[frameIdx], static_cast(sprite->frames[frameIdx])); } - - // SPDLOG_INFO("=== Sprite structure complete (total {} bytes) ===", totalSize); - - // Verify - // SPDLOG_INFO("Verification: frameCnt={}, type=0x{:X}", sprite->frameCnt, sprite->type); - if (frameCount > 0) { - BKSpriteFrame* verifyFrame = sprite->frames[0]; - // SPDLOG_INFO("Frame 0: w={}, h={}, chunkCnt={}, frame pointer={}", - // verifyFrame->w, verifyFrame->h, verifyFrame->chunkCnt, - // static_cast(verifyFrame)); - - if (verifyFrame->chunkCnt > 0) { - BKSpriteTextureBlock* verifyChunk = reinterpret_cast(verifyFrame + 1); - // SPDLOG_INFO("First chunk at frame+1: pointer={}, pos=({}, {}), size={}x{}", - // static_cast(verifyChunk), - // verifyChunk->x, verifyChunk->y, verifyChunk->w, verifyChunk->h); - // SPDLOG_INFO("Expected offset from frame: {} bytes, actual: {} bytes", - // sizeof(BKSpriteFrame), - // reinterpret_cast(verifyChunk) - reinterpret_cast(verifyFrame)); - } - } } BKSprite* Sprite::GetPointer() { diff --git a/src/port/ResourceHelpers.cpp b/src/port/ResourceHelpers.cpp index 933b692ac..a350a0f86 100644 --- a/src/port/ResourceHelpers.cpp +++ b/src/port/ResourceHelpers.cpp @@ -27,14 +27,19 @@ #include "GameVersion/AssetVersionRemap.h" #include "GameVersion/BaseGameVersion.h" -extern "C" { #include "enums.h" -} -extern "C" uint16_t ResourceMgr_LoadTexWidthByName(char* texPath); -extern "C" uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); extern "C" void func_8031B5C4(int32_t lang); // decomp: set dialog language index +extern "C" { +// SNS picture demo table (core2/map/exit.c, Struct_core2_C4320_0). unk2 is both +// the demo file slot and the map exit/entry-point id used for the warp. +typedef struct { + uint8_t map, unk1, exit, unk3, unk4, unk5; +} BKSnsDemoEntry; +extern BKSnsDemoEntry D_80371F78[3]; +} + // Dialog language state — detected at boot from o2r version static int sDialogLanguageCount = 1; // 1 for US/JP, 3 for PAL (EN/FR/DE) static int sDialogLanguage = 0; // 0=English, 1=French, 2=German @@ -107,7 +112,7 @@ const std::unordered_map& GetAssetSymbolMap() { switch (Lighthouse::GetBaseVersion()) { case BK_VER_US_11: remapTable = &sV10toV11Remap; - SPDLOG_INFO("Loaded v1.1 o2r with {} entries", symbolMap.size()); + SPDLOG_INFO("Loaded US v1.1 o2r with {} entries", symbolMap.size()); break; case BK_VER_PAL: remapTable = &sV10toPALRemap; @@ -119,10 +124,22 @@ const std::unordered_map& GetAssetSymbolMap() { break; case BK_VER_US_10: default: + SPDLOG_INFO("Loaded US v1.0 o2r"); // v1.0 or a v1.0-based romhack: decomp IDs are already correct. break; } + // Non-v1.0 ROMs keep the SNS picture demos one slot lower (0x5E, matching + // the PAL VER_SELECT in the decomp) and their map setups place the demo + // entry points at that exit id too. The compiled v1.0 value (0x5F) would + // load the right demo file via the alias but warp to a nonexistent exit, + // so retarget the table; the 2508/2511/2513 aliases cover the asset side. + if (remapTable) { + for (auto& entry : D_80371F78) { + entry.exit = 0x5E; + } + } + // Relocate the JP world-name banners to their 0x1600 aliases for a JP // base (a JP pack does this re-point at language-select time instead). if (Lighthouse::GetBaseVersion() == BK_VER_JP) { @@ -171,6 +188,11 @@ extern "C" int ResourceMgr_GetDialogLanguageCount(void) { return sDialogLanguageCount; } +// PAL is the only base that carries more than one dialog language (EN/FR/DE). +extern "C" int ResourceMgr_IsPal(void) { + return sDialogLanguageCount > 1 ? 1 : 0; +} + extern "C" int ResourceMgr_IsJapanese(void) { return sIsJapanese ? 1 : 0; } @@ -220,12 +242,8 @@ extern "C" int ResourceMgr_IsAssetRepointed(uint32_t assetId) { return sDialogOverride.find(assetId) != sDialogOverride.end() ? 1 : 0; } -// Resolve an asset id to its o2r path: the active language override wins for -// re-pointed dialog ids, otherwise the base manifest. -static std::string ResolveAssetPath(uint32_t assetId) { - if (auto ov = sDialogOverride.find(assetId); ov != sDialogOverride.end()) { - return ov->second; - } +// The base game's own o2r path for an asset id, ignoring any active language re-point. +std::string ResourceHelpers_GetBaseAssetPath(uint32_t assetId) { const auto& symbolMap = GetAssetSymbolMap(); if (auto entry = symbolMap.find(assetId); entry != symbolMap.end()) { return entry->second; @@ -233,6 +251,14 @@ static std::string ResolveAssetPath(uint32_t assetId) { return std::string(); } +// The o2r path an asset id resolves to right now. +std::string ResourceHelpers_GetActiveAssetPath(uint32_t assetId) { + if (auto ov = sDialogOverride.find(assetId); ov != sDialogOverride.end()) { + return ov->second; + } + return ResourceHelpers_GetBaseAssetPath(assetId); +} + static char* LoadAndRetainResource(const std::string& path, uint32_t assetId) { auto res = GetResourceByName(path.c_str()); if (res && res->GetRawPointer() != nullptr) { @@ -251,7 +277,7 @@ extern "C" char* ResourceMgr_ReloadByAssetId(uint32_t assetId) { sResourceRefCache.erase(it); } - std::string mappedPath = ResolveAssetPath(assetId); + std::string mappedPath = ResourceHelpers_GetActiveAssetPath(assetId); if (!mappedPath.empty()) { std::replace(mappedPath.begin(), mappedPath.end(), '\\', '/'); @@ -276,7 +302,7 @@ extern "C" char* ResourceMgr_LoadByAssetId(uint32_t assetId) { sResourceRefCache.erase(it); } - std::string mappedPath = ResolveAssetPath(assetId); + std::string mappedPath = ResourceHelpers_GetActiveAssetPath(assetId); if (mappedPath.empty()) { // A reserved-but-empty ROM slot resolves to nothing by design (the game // tolerates it, as on N64); only a genuinely-missing asset is worth tracing. @@ -303,14 +329,20 @@ extern "C" size_t ResourceMgr_GetResourceSize(uint32_t assetId) { return 0; } -// On N64, sprites and models were raw binary blobs that could be type-punned. -// On PC, they're separate resource types from different importers. Actors with sprite -// assets can be spawned as "model" props (unk8_1=1), causing collision code to call -// marker_loadModelBin which reinterprets sprite data as BKModelBin. This helper lets -// decomp code detect and skip the model path for sprite assets. +// Force an asset id to resolve to a custom resource shipped at `customPath`. +extern "C" void ResourceMgr_RegisterAssetOverride(uint32_t assetId, const char* customPath) { + auto res = GetResourceByName(customPath); + if (res != nullptr && res->GetRawPointer() != nullptr) { + sResourceRefCache[assetId] = res; + } +} + +// Actors with sprite assets can be spawned as "model" props (unk8_1=1), causing collision +// code to call marker_loadModelBin which reinterprets sprite data as BKModelBin. This helper +// lets decomp code detect and skip the model path for sprite assets. extern "C" int ResourceMgr_IsModelAsset(uint32_t assetId) { if (auto it = sResourceRefCache.find(assetId); it != sResourceRefCache.end()) { - return it->second->GetInitData()->Type == 0x424B4D4F; // Torch::ResourceType::BKModel + return it->second->GetInitData()->Type == 0x424B4D4F; } return 0; } @@ -363,7 +395,12 @@ void ResourceHelpers_ApplyLanguage(std::unordered_map dia } ++sLanguageGeneration; // invalidates re-pointed models on their next draw sIsJapanese = isJapanese; - sDialogLanguageCount = dialogCount; + sDialogLanguageCount = (dialogCount > 0) ? dialogCount : 1; + if (dialogIndex < 0 || dialogIndex >= sDialogLanguageCount) { + SPDLOG_WARN("[ResourceHelpers] Dialog language index {} out of range for a {}-language source; using 0", + dialogIndex, sDialogLanguageCount); + dialogIndex = 0; + } sDialogLanguage = dialogIndex; // keep ResourceMgr_GetDialogLanguage() in sync - func_8031B5C4(dialogIndex); // clamps against sDialogLanguageCount + func_8031B5C4(dialogIndex); } diff --git a/src/port/ResourceHelpers.h b/src/port/ResourceHelpers.h index 1fb9957a8..e1223cd95 100644 --- a/src/port/ResourceHelpers.h +++ b/src/port/ResourceHelpers.h @@ -6,6 +6,7 @@ #include //#include "ResourceManager.h" #include "ship/Context.h" +#include "ship/resource/ResourceManager.h" std::shared_ptr GetResourceByName(const char* path); @@ -14,9 +15,11 @@ extern "C" { #include char* ResourceMgr_LoadByAssetId(uint32_t assetId); +void ResourceMgr_RegisterAssetOverride(uint32_t assetId, const char* customPath); size_t ResourceMgr_GetResourceSize(uint32_t assetId); int ResourceMgr_IsModelAsset(uint32_t assetId); int ResourceMgr_GetDialogLanguageCount(void); +int ResourceMgr_IsPal(void); int ResourceMgr_IsJapanese(void); int ResourceMgr_GetDialogLanguage(void); void ResourceMgr_SetDialogLanguage(int lang); @@ -35,6 +38,8 @@ Mtx* ResourceMgr_LoadMtxByName(char* path); void ResourceHelpers_ApplyLanguage(std::unordered_map dialogOverride, bool isJapanese, int dialogCount, int dialogIndex); +std::string ResourceHelpers_GetBaseAssetPath(uint32_t assetId); +std::string ResourceHelpers_GetActiveAssetPath(uint32_t assetId); #endif #endif diff --git a/src/port/Romhack/RomhackCompat.cpp b/src/port/Romhack/RomhackCompat.cpp index 0bd322e5f..904facd27 100644 --- a/src/port/Romhack/RomhackCompat.cpp +++ b/src/port/Romhack/RomhackCompat.cpp @@ -7,7 +7,13 @@ namespace Lighthouse { static constexpr const char* kVanillaLabel = "Vanilla"; std::string CurrentRomhackLabel() { - return port_isRomhack() ? port_getRomhackName() : kVanillaLabel; + if (!port_isRomhack()) { + return kVanillaLabel; + } + if (const char* id = port_getRomhackIdentifier()) { + return id; + } + return port_getRomhackName(); } std::string DescribeRomhackMismatch(bool localIsRomhack, const std::string& localLabel, bool remoteIsRomhack, diff --git a/src/port/Romhack/RomhackConfig.cpp b/src/port/Romhack/RomhackConfig.cpp index e989cca8c..303dd86a9 100644 --- a/src/port/Romhack/RomhackConfig.cpp +++ b/src/port/Romhack/RomhackConfig.cpp @@ -62,6 +62,8 @@ static int sHideJiggiesLevel = -1; static int sHideCollectiblesLevel = -1; static int sNoteDoors[12] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; static int sJiggyCosts[11] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +static int sJiggySizes[11] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +static int sJiggyFlags[11] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; static char* sLevelNames[13] = {}; static std::unordered_map sWarpDests; static std::string sRomName; @@ -70,6 +72,7 @@ static std::string sRomName; // loaded romhack has no detectable injected MIPS code. static std::string sCustomCodeHashHex; static uint32_t sCustomCodeRamBase = 0; +static int sCustomCodeKind = -1; // ROM SHA1 — populated by the ROM_HASH section. Always emitted by Torch for // any romhack; serves as the fallback identifier when no custom-code blob is @@ -351,12 +354,16 @@ static void LoadGameConfig() { break; case 8: // JIGGY_PUZZLES - for (uint16_t e = 0; e < entryCount && pos + 2 <= size; e++) { + for (uint16_t e = 0; e < entryCount && pos + 6 <= size; e++) { int idx = data[pos]; int cost = data[pos + 1]; - pos += 2; + int sizeBits = data[pos + 2]; + int flag = readLE16(data + pos + 4); + pos += 6; if (idx >= 0 && idx < 11) { sJiggyCosts[idx] = cost; + sJiggySizes[idx] = sizeBits; + sJiggyFlags[idx] = flag; } } break; @@ -390,7 +397,7 @@ static void LoadGameConfig() { } break; - case 11: // CUSTOM_CODE — single entry: u32 ramBase + u8 hash[20] + case 11: // CUSTOM_CODE if (entryCount >= 1 && pos + 24 <= size) { sCustomCodeRamBase = readLE32(data + pos); char hex[41]; @@ -398,17 +405,6 @@ static void LoadGameConfig() { std::snprintf(hex + i * 2, 3, "%02x", data[pos + 4 + i]); } sCustomCodeHashHex.assign(hex, 40); - if (Lighthouse::LookupRomhackIdentifier(sCustomCodeHashHex.c_str()) == nullptr) { - // Hash isn't in RomhackTable.h yet — Lighthouse can detect - // this hack ships custom code but doesn't know which one. - // Log the SHA1 so a hand-port author can pick it up. - SPDLOG_WARN("[GameConfig] Custom-code SHA1 {} is not identified! This romhack's " - "scripted behavior will be absent until a hand-port is added " - "(ramBase=0x{:08X}).", - sCustomCodeHashHex, sCustomCodeRamBase); - } - // Known identifiers are surfaced in the summary log line below. - pos += 24; // Skip any additional entries (forward-compat). for (uint16_t e = 1; e < entryCount && pos + 24 <= size; e++) { @@ -420,6 +416,13 @@ static void LoadGameConfig() { } break; + case 13: // CUSTOM_CODE_INFO + if (entryCount >= 1 && pos + 4 <= size) { + sCustomCodeKind = readLE16(data + pos); + } + pos += entryCount * 4; + break; + case 12: // ROM_HASH — single entry: u8 hash[20] if (entryCount >= 1 && pos + 20 <= size) { char hex[41]; @@ -444,48 +447,31 @@ static void LoadGameConfig() { } } - int codeConstCount = 0; - for (int i = 0; i < 24; i++) { - // Check each static against its default (-1) - const int* vals[] = { &sNewGameMap, &sStartLevel1, &sStartLevel2, - &sKnowAllMoves, &sMumboCostTermite, &sMumboCostCroc, - &sMumboCostWalrus, &sMumboCostPumpkin, &sMumboCostBee, - &sEggsNormalMax, &sRedFeathersNormalMax, &sGoldFeathersNormalMax, - &sEggsCheatomax, &sRedFeathersCheatomax, &sGoldFeathersCheatomax, - &sNotesMax, &sJiggiesPerWorld, &sHoneycombsPerWorld, - &sExtraHcStart, &sWarpExitBanjosHouse, &sWarpEnterLair, - &sSpecialLevel, &sHideJiggiesLevel, &sHideCollectiblesLevel }; - if (*vals[i] != -1) { - codeConstCount++; - } - } - int levelNameCount = 0; - for (int i = 0; i < 13; i++) { - if (sLevelNames[i]) { - levelNameCount++; - } - } - int noteDoorCount = 0; - for (int i = 0; i < 12; i++) { - if (sNoteDoors[i] != -1) { - noteDoorCount++; - } - } - int jiggyCostCount = 0; - for (int i = 0; i < 11; i++) { - if (sJiggyCosts[i] != -1) { - jiggyCostCount++; - } - } if (sCustomCodeHashHex.empty()) { // Data-only romhack — BB patches only, no injected MIPS to identify. // Fall back to the o2r-derived name for visibility. SPDLOG_INFO("[GameConfig] Loaded romhack: {}", sRomName.empty() ? "" : sRomName); - } else if (const char* id = Lighthouse::LookupRomhackIdentifier(sCustomCodeHashHex.c_str())) { - SPDLOG_INFO("[GameConfig] Loaded romhack: {}", id); + } else if (const auto* entry = Lighthouse::LookupRomhackEntry(sCustomCodeHashHex.c_str())) { + SPDLOG_INFO("[GameConfig] Loaded romhack: {}", entry->identifier); + // No warning when the custom code is just the BB globalized-overlay + // framework or is already ported. Only injected, not-yet-ported code merits one. + // isPorted=false means analysis confirmed real un-ported custom code, + // regardless of how the blob is shipped (Nostalgia 64's lives inside a + // globalization-kind blob). + if (!entry->isPorted) { + SPDLOG_WARN("[GameConfig] {} ships injected custom code that is not ported yet; " + "scripted behavior driven by it will be absent.", + entry->identifier); + } + } else if (sCustomCodeKind == 1 /* BB_GLOBALIZATION */) { + const char* romId = sRomHashHex.empty() ? nullptr : Lighthouse::LookupRomhackIdentifier(sRomHashHex.c_str()); + SPDLOG_INFO("[GameConfig] Loaded romhack: {}", + romId ? romId : (sRomName.empty() ? "" : sRomName.c_str())); } else { - // Custom code present but the SHA1 is not in RomhackTable.h. The - // separate warn earlier in this function already surfaced the hash. + // Custom code present but the SHA1 is not in RomhackTable.h. + SPDLOG_WARN("[GameConfig] Custom-code SHA1 {} is not identified! This romhack's scripted " + "behavior will be absent until a port is added (ramBase=0x{:08X}).", + sCustomCodeHashHex, sCustomCodeRamBase); SPDLOG_INFO("[GameConfig] Loaded romhack: unidentified custom-code"); } } @@ -521,6 +507,14 @@ extern "C" const char* port_getRomhackName(void) { return sRomName.empty() ? "" : sRomName.c_str(); } +extern "C" int port_getRomhackCustomCodeKind(void) { + LoadGameConfig(); + if (!sIsRomhack || sCustomCodeHashHex.empty() || sCustomCodeKind < 0) { + return 0; // none + } + return sCustomCodeKind; +} + extern "C" bool port_getRomhackCustomCodeHash(char out_hex[41]) { LoadGameConfig(); if (sCustomCodeHashHex.empty()) { @@ -746,6 +740,22 @@ extern "C" int port_getRomhackJiggyPuzzleCost(int puzzle_index) { return -1; } +extern "C" int port_getRomhackJiggyPuzzleSize(int puzzle_index) { + ROMHACK_GUARD_INT; + if (puzzle_index >= 0 && puzzle_index < 11) { + return sJiggySizes[puzzle_index]; + } + return -1; +} + +extern "C" int port_getRomhackJiggyPuzzleFlag(int puzzle_index) { + ROMHACK_GUARD_INT; + if (puzzle_index >= 0 && puzzle_index < 11) { + return sJiggyFlags[puzzle_index]; + } + return -1; +} + extern "C" const char* port_getRomhackLevelName(int level_index) { ROMHACK_GUARD_NULL; if (level_index >= 0 && level_index < 13) { @@ -759,3 +769,8 @@ extern "C" int port_getRomhackWarpDest(int warp_index) { auto it = sWarpDests.find(warp_index); return (it != sWarpDests.end()) ? it->second : -1; } + +extern "C" void port_clearRomhackWarpDest(int warp_index) { + LoadGameConfig(); + sWarpDests.erase(warp_index); +} diff --git a/src/port/Romhack/RomhackConfig.h b/src/port/Romhack/RomhackConfig.h index 4d704ecb7..2dc678181 100644 --- a/src/port/Romhack/RomhackConfig.h +++ b/src/port/Romhack/RomhackConfig.h @@ -4,10 +4,7 @@ extern "C" { #endif -// BB romhack game config — loaded from aGameConfig blob in the o2r. -// Returns -1 (or 0/NULL) for vanilla default when no override exists. -// All functions are fast after first call: vanilla ROMs hit one branch. - +// Config building bool port_isRomhack(void); const char* port_getRomhackName(void); @@ -41,12 +38,21 @@ int port_getRomhackHoneycombsPerWorld(void); int port_getRomhackExtraHcStart(void); int port_getRomhackNoteDoor(int door_index); int port_getRomhackJiggyPuzzleCost(int puzzle_index); +int port_getRomhackJiggyPuzzleSize(int puzzle_index); +int port_getRomhackJiggyPuzzleFlag(int puzzle_index); const char* port_getRomhackLevelName(int level_index); int port_getRomhackWarpDest(int warp_index); +void port_clearRomhackWarpDest(int warp_index); bool port_getRomhackCustomCodeHash(char out_hex[41]); +int port_getRomhackCustomCodeKind(void); bool port_getRomhackRomHash(char out_hex[41]); const char* port_getRomhackIdentifier(void); +// Hack specific functions +int romhack_mumboTransform(int transformId); +int romhack_mumboWishwashyId(void); +int romhack_mumboRandomEventsAllowed(void); + #ifdef __cplusplus } #endif diff --git a/src/port/Romhack/RomhackQuirks.cpp b/src/port/Romhack/RomhackQuirks.cpp deleted file mode 100644 index 7df269857..000000000 --- a/src/port/Romhack/RomhackQuirks.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Per-romhack quirk handlers. Each block here is a port-side listener that -// adjusts engine behavior for a specific romhack identified via the -// RomhackTable.h SHA1 -> name mapping. Listeners run only when the loaded -// romhack matches the relevant identifier; vanilla and unrelated romhacks -// see no behavior change. -// -// To add a new quirk: -// 1. Make sure the romhack has an entry in RomhackTable.h. -// 2. Find the engine event the quirk should hook (or define a new one in -// src/port/enhancements/events/hooks/list/). -// 3. Add a REGISTER_LISTENER block below, gated on -// port_getRomhackIdentifier() returning the matching name. -// 4. Wire the registration into RegisterRomhackQuirks_Init(). - -#include - -#include -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" -#include "port/Romhack/RomhackConfig.h" - -namespace { - -bool IsRomhack(const char* identifier) { - const char* id = port_getRomhackIdentifier(); - return id != nullptr && std::strcmp(id, identifier) == 0; -} - -// --- Banjo-Dreamie -// -// Pre-BB romhack whose BB-patched warp constants live in the relocated overlay -// copy. Dreamie's boot loader doesn't actually load that copy on N64. -// -// On every OnWarpResolveDest fire, restore the dispatcher's vanilla default, -// ignoring whatever the BKCF claims. - -void RegisterDreamiePatches() { - REGISTER_LISTENER(OnWarpResolveDest, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - if (!IsRomhack("Dreamie")) { - return; - } - auto* ev = reinterpret_cast(event); - if (ev->warpId == WARP_ID_SM_EXIT_BANJOS_HOUSE || ev->warpId == WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL) { - *ev->dest = ev->defaultDest; - } - }); -} - -void RegisterRomhackQuirks_Init() { - RegisterDreamiePatches(); -} - -RegisterShipInitFunc initFunc(RegisterRomhackQuirks_Init); - -} // namespace diff --git a/src/port/Romhack/RomhackRegistration.cpp b/src/port/Romhack/RomhackRegistration.cpp new file mode 100644 index 000000000..0cf49a7fb --- /dev/null +++ b/src/port/Romhack/RomhackRegistration.cpp @@ -0,0 +1,61 @@ +// Registration hub for per-romhack ports. +// +// Each supported romhack lives in its own file under Romhack/Specific/ and +// exposes a RegisterPatches() that installs its listeners. Registration +// itself is gated on the loaded romhack's RomhackTable.h identifier. +// +// To add a new port: +// 1. Add an entry in RomhackTable.h by hash. +// 2. Add Romhack/Specific/.cpp exposing RegisterPatches(). +// 3. Add one PORT() line to the list below. The identifier must match the +// RomhackTable.h identifier and the RegisterPatches() name. + +#include + +#include "port/Romhack/RomhackConfig.h" +#include "port/ShipInit.hpp" + +#define ROMHACK_PORT_LIST(PORT) \ + PORT(Dreamie) \ + PORT(JiggiesOfTime) \ + PORT(NewHorizons) \ + PORT(Nostalgia64) \ + PORT(CutThroatCoast) \ + PORT(BubblingBog) \ + PORT(Gruntch) + +#define ROMHACK_PORT_DECL(name) void Register##name##Patches(); +ROMHACK_PORT_LIST(ROMHACK_PORT_DECL) +#undef ROMHACK_PORT_DECL + +namespace { + +struct RomhackPort { + const char* identifier; + void (*install)(); +}; + +constexpr RomhackPort kRomhackPorts[] = { +#define ROMHACK_PORT_ENTRY(name) { #name, &Register##name##Patches }, + ROMHACK_PORT_LIST(ROMHACK_PORT_ENTRY) +#undef ROMHACK_PORT_ENTRY +}; + +void RegisterRomhackPatches_Init() { + const char* id = port_getRomhackIdentifier(); + if (id == nullptr) { + return; + } + for (const RomhackPort& port : kRomhackPorts) { + if (std::strcmp(id, port.identifier) == 0) { + port.install(); + return; + } + } +} + +RegisterShipInitFunc initFunc(RegisterRomhackPatches_Init, { "BOOT" }); + +} // namespace + +#undef ROMHACK_PORT_LIST diff --git a/src/port/Romhack/RomhackTable.h b/src/port/Romhack/RomhackTable.h index db90a0618..a12e19fc0 100644 --- a/src/port/Romhack/RomhackTable.h +++ b/src/port/Romhack/RomhackTable.h @@ -7,46 +7,77 @@ namespace Lighthouse { struct RomhackTableEntry { const char* sha1; const char* identifier; + bool isPorted; }; /* - This romhack table contains the sha1 hashes for custom code - blobs injected into romhacks. Torch inserts these hashes into - aGameConfig per romhack generated into an o2r. Having a table - of such hashes allows Lighthouse to eventually port custom code - that allows these romhacks to function properly, and gate custom - code paths behind matching hashes per o2r. + This romhack table contains the sha1 hashes for detected code changes + injected into romhacks. Torch inserts these hashes into aGameConfig + per romhack generated into an o2r. Having a table of such hashes allows + Lighthouse to eventually port the code modifications that allow these + romhacks to function properly, and gate such changes behind matching + hashes per o2r. + + Known romhacks hashed against the latest at patch.wedarobi.com + as of July 2026. */ static constexpr RomhackTableEntry kRomhackTable[] = { + // These hacks ship a separate code blob; the hash covers its decompressed + // payload. + // Cut-Throat Coast - { "13f4fa8a180fe5775a606486effbafeb58862d26", "CutThroatCoast" }, + { "13f4fa8a180fe5775a606486effbafeb58862d26", "CutThroatCoast", true }, - // How the Gruntch Stole Christmas — also shipped, byte-identical, in - // Santa's Village. Single hand-port covers both. - { "bed22dd8ef931228fbc94f006dfc718a4d4f6f8c", "Gruntch" }, + // The Gruntch, Santa's Village + { "bed22dd8ef931228fbc94f006dfc718a4d4f6f8c", "Gruntch", true }, - // Snow Glow Village — derivative of Gruntch's blob with diverged code. - { "23596c2858283b847e9e0ff44785e35110002fc7", "SnowGlowVillage" }, + // Snow Glow Village + { "23596c2858283b847e9e0ff44785e35110002fc7", "SnowGlowVillage", false }, // The Corrupted Jiggies - { "9e20be78496d66f2e5f7930022a0fee769753488", "CorruptedJiggies" }, + { "9e20be78496d66f2e5f7930022a0fee769753488", "CorruptedJiggies", false }, + + // Bubbling Bog Brewery Redone + { "af7c71b034b2d7af867cd0aec8751c49aca1f0bc", "BubblingBog", false }, + + // Cheatos Challenges + { "017bf33d80b22d7926a9839f09fd1c52f83d3b97", "CheatosChallenges", true }, + + // These hacks ship no blob of their own; they edit the globalized overlay + // in place, which aGameConfig has no schema for. Mostly actor table + // rebinds, though Nostalgia 64 also fills spare overlay space with its own + // functions and repoints update funcs at them. // Banjo-Dreamie - { "3972b2a3aca230dde1cbf66ffa6f052327b7d3fa", "Dreamie" }, + { "3972b2a3aca230dde1cbf66ffa6f052327b7d3fa", "Dreamie", true }, + + // Jiggies of Time + { "ad7ef5ba9051c6a360c1d60546d5ca8cf61f0d92", "JiggiesOfTime", true }, - { nullptr, nullptr }, // terminator — keep last + // New Horizons + { "663dd77a9e3a1ed1f25399380665511a04b91a54", "NewHorizons", true }, + + // Nostalgia 64 + { "7a7a07c26d77530dc45caf8ab96e9056ea2877e1", "Nostalgia64", true }, + + { nullptr, nullptr, false }, // terminator }; -inline const char* LookupRomhackIdentifier(const char* sha1Hex) { +inline const RomhackTableEntry* LookupRomhackEntry(const char* sha1Hex) { if (sha1Hex == nullptr || sha1Hex[0] == '\0') { return nullptr; } for (const auto* entry = kRomhackTable; entry->sha1 != nullptr; entry++) { if (std::strcmp(entry->sha1, sha1Hex) == 0) { - return entry->identifier; + return entry; } } return nullptr; } +inline const char* LookupRomhackIdentifier(const char* sha1Hex) { + const RomhackTableEntry* entry = LookupRomhackEntry(sha1Hex); + return entry ? entry->identifier : nullptr; +} + } // namespace Lighthouse diff --git a/src/port/Romhack/Shared/HackShared.cpp b/src/port/Romhack/Shared/HackShared.cpp new file mode 100644 index 000000000..f431a00f3 --- /dev/null +++ b/src/port/Romhack/Shared/HackShared.cpp @@ -0,0 +1,147 @@ +#include +#include "port/UI/cvar_prefixes.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/RomhackConfig.h" +#include "port/ShipInit.hpp" +#include "HackShared.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "actor.h" +#include "core2/abilityprogress.h" + +extern ActorArray* suBaddieActorArray; + +extern s32 print_sCurrentFont; +extern s32 print_sMonospacedModeEnabled; +extern char print_sPreviousBoldLetter; +f32 print_calculateLetterXPos(u8 letter, f32* xPtr, f32* yPtr, f32 arg3); +} + +#define CVAR_NOTE_RETENTION CVAR_ENHANCEMENT("Gameplay.NoteRetention") + +namespace { + +void ApplyNoteSignHooks(); +f32 MeasureBoldNameWidth(const char* s); +void ApplyPauseNameCentering(); +void ApplyDialogSuppression(); +void ApplyForceAbilitiesUsed(); + +int sNoteSignActorId = -1; +const int* sSuppressedDialogs = nullptr; +int sSuppressedDialogCount = 0; +s32 sForcedUsedAbilities = 0; + +// Romhacks that have note signs and Bottles explainers don't need them when +// note saving is turned on. Suppress them. +void ApplyNoteSignHooks() { + const bool active = sNoteSignActorId >= 0 && CVarGetInteger(CVAR_NOTE_RETENTION, 0); + + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, active, [](IEvent* event) { + auto* ev = reinterpret_cast(event); + if (ev->actorId == sNoteSignActorId) { + ev->result = nullptr; + event->Cancelled = true; + } + }); + + COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, active, [](IEvent*) { + if (suBaddieActorArray == nullptr) { + return; + } + Actor* start = suBaddieActorArray->data; + Actor* end = start + suBaddieActorArray->cnt; + for (Actor* actor = start; actor < end; actor++) { + if (actor->marker == nullptr || actor->marker->id != MARKER_B7_TUTORIAL_BOTTLES || + actor->actorTypeSpecificField != 8) { + continue; + } + if (actor->partnerActor != nullptr) { + marker_despawn(actor->partnerActor); + } + marker_despawn(actor->marker); + } + }); +} + +// Center bold font in pause menu +f32 MeasureBoldNameWidth(const char* s) { + const s32 savedSlot = print_sCurrentFont; + const s32 savedMono = print_sMonospacedModeEnabled; + const char savedPrev = print_sPreviousBoldLetter; + print_sCurrentFont = 1; + print_sMonospacedModeEnabled = 0; + print_sPreviousBoldLetter = 0; + f32 x = 0.0f; + f32 y = 0.0f; + for (const char* p = s; *p != '\0'; ++p) { + print_calculateLetterXPos((u8)(unsigned char)*p, &x, &y, 1.05f); + } + print_sCurrentFont = savedSlot; + print_sMonospacedModeEnabled = savedMono; + print_sPreviousBoldLetter = savedPrev; + return x; +} + +void ApplyPauseNameCentering() { + COND_VB_SHOULD(VB_PAUSEMENU_LEVEL_NAME_X, EVENT_PRIORITY_NORMAL, port_getRomhackIdentifier() != nullptr, { + s32* x = va_arg(args, s32*); + va_arg(args, s32); + const char* vanillaName = va_arg(args, const char*); + const char* romhackName = va_arg(args, const char*); + if (romhackName != nullptr && vanillaName != nullptr) { + const f32 shift = (MeasureBoldNameWidth(vanillaName) - MeasureBoldNameWidth(romhackName)) * 0.5f; + *x += (s32)(shift >= 0.0f ? shift + 0.5f : shift - 0.5f); + } + (void)should; + }); +} + +// Suppress a caller-supplied set of dialogs +void ApplyDialogSuppression() { + COND_VB_SHOULD(VB_OVERRIDE_DIALOG_SHOW, EVENT_PRIORITY_NORMAL, sSuppressedDialogCount > 0, { + const s32 textId = va_arg(args, s32); + for (int i = 0; i < sSuppressedDialogCount; i++) { + if (sSuppressedDialogs[i] == textId) { + *should = true; + break; + } + } + }); +} + +// Mark moves as already used +void ApplyForceAbilitiesUsed() { + COND_HOOK(OnSaveLoad, EVENT_PRIORITY_NORMAL, sForcedUsedAbilities != 0, [](IEvent*) { + for (int move = 0; move < 32; move++) { + if (sForcedUsedAbilities & (1 << move)) { + ability_setHasUsed(static_cast(move)); + } + } + }); +} + +RegisterShipInitFunc noteSignInitFunc(ApplyNoteSignHooks, { CVAR_NOTE_RETENTION }); +RegisterShipInitFunc pauseNameCenterInit(ApplyPauseNameCentering, { "BOOT" }); + +} // namespace + +void HackShared_EnableNoteSignSuppression(int signActorId) { + sNoteSignActorId = signActorId; + ApplyNoteSignHooks(); +} + +void HackShared_EnableDialogSuppression(const int* dialogIds, int count) { + sSuppressedDialogs = dialogIds; + sSuppressedDialogCount = count; + ApplyDialogSuppression(); +} + +void HackShared_EnableForceAbilitiesUsed(const ability_used* moves, int count) { + for (int i = 0; i < count; i++) { + sForcedUsedAbilities |= (1 << moves[i]); + } + ApplyForceAbilitiesUsed(); +} diff --git a/src/port/Romhack/Shared/HackShared.h b/src/port/Romhack/Shared/HackShared.h new file mode 100644 index 000000000..37d8cb578 --- /dev/null +++ b/src/port/Romhack/Shared/HackShared.h @@ -0,0 +1,23 @@ +#pragma once + +extern "C" { +#include "core2/abilityprogress.h" +} + +constexpr ability_used kAllUsedAbilities[] = { + ABILITY_USED_JUMP, ABILITY_USED_FLAP, ABILITY_USED_FLIP, ABILITY_USED_SWIM, ABILITY_USED_CLIMB, + ABILITY_USED_BEAK_BARGE, ABILITY_USED_SLIDE, ABILITY_USED_EGG, ABILITY_USED_FLY, ABILITY_USED_SHOCK, + ABILITY_USED_PECK, ABILITY_USED_CLAW, ABILITY_USED_TWIRL, +}; + +void HackShared_EnableNoteSignSuppression(int signActorId); +void HackShared_EnableDialogSuppression(const int* dialogIds, int count); +void HackShared_EnableForceAbilitiesUsed(const ability_used* moves, int count); + +template inline void HackShared_EnableDialogSuppression(const int (&dialogIds)[N]) { + HackShared_EnableDialogSuppression(dialogIds, N); +} + +template inline void HackShared_EnableForceAbilitiesUsed(const ability_used (&moves)[N]) { + HackShared_EnableForceAbilitiesUsed(moves, N); +} diff --git a/src/port/Romhack/Shared/ProximityDialogs.cpp b/src/port/Romhack/Shared/ProximityDialogs.cpp new file mode 100644 index 000000000..1388630dc --- /dev/null +++ b/src/port/Romhack/Shared/ProximityDialogs.cpp @@ -0,0 +1,83 @@ +#include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "ProximityDialogs.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "core1/ml.h" + +extern f32 D_8037C5B0[3]; +} + +namespace { +constexpr s32 kDialogFlagSkippable = 0x1; + +u16 sDialogShown[2] = { 0, 0 }; +const ProximityDialogMap* sWorldMaps = nullptr; +s32 sWorldMapCount = 0; +} // namespace + +void ProximityDialogs_Run(const ProximityDialogMap* maps, int count) { + if (getGameMode() != GAME_MODE_3_NORMAL || gcdialog_hasCurrentTextId()) { + return; + } + + const ProximityDialogMap* entry = nullptr; + const s32 map = gsworld_getMap(); + for (s32 i = 0; i < count; i++) { + if (maps[i].map == map) { + entry = &maps[i]; + break; + } + } + if (entry == nullptr) { + return; + } + if (entry->gate != nullptr && !entry->gate()) { + return; + } + + for (s32 i = 0; i < entry->pageCount; i++) { + const ProximityDialogPage& page = entry->pages[i]; + const bool tokenIsGuard = page.doneBit == 0; + if (tokenIsGuard ? mumboscore_get((enum mumbotoken_e)page.token) + : (sDialogShown[page.word] & page.doneBit) != 0) { + continue; + } + if (page.skipIfJiggy > 0 && jiggyscore_isCollected((enum jiggy_e)page.skipIfJiggy)) { + continue; + } + if (page.needFlag > 0 && !fileProgressFlag_get((enum file_progress_e)page.needFlag)) { + continue; + } + if (page.needFlagClear > 0 && fileProgressFlag_get((enum file_progress_e)page.needFlagClear)) { + continue; + } + f32 anchor[3] = { page.anchor[0], page.anchor[1], page.anchor[2] }; + if (!(ml_vec3f_distance(anchor, D_8037C5B0) < page.radius)) { + return; + } + gcdialog_showDialog(page.textId, page.dialogFlags | kDialogFlagSkippable, (f32*)page.dialogPos, NULL, NULL, + NULL); + sDialogShown[page.word] |= page.doneBit; + if (page.token >= 0) { + mumboscore_set((enum mumbotoken_e)page.token, true); + } + } +} + +void ProximityDialogs_Enable(const ProximityDialogMap* maps, int count) { + sWorldMaps = maps; + sWorldMapCount = count; + COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, sWorldMapCount > 0, + [](IEvent*) { ProximityDialogs_Run(sWorldMaps, sWorldMapCount); }); +} + +bool ProximityDialogs_IsShown(int word, unsigned bits) { + return (sDialogShown[word] & bits) != 0; +} + +void ProximityDialogs_ClearShown(int word, unsigned bits) { + sDialogShown[word] &= ~(u16)bits; +} diff --git a/src/port/Romhack/Shared/ProximityDialogs.h b/src/port/Romhack/Shared/ProximityDialogs.h new file mode 100644 index 000000000..aac61acc8 --- /dev/null +++ b/src/port/Romhack/Shared/ProximityDialogs.h @@ -0,0 +1,39 @@ +#pragma once + +struct ProximityDialogPage { + float anchor[3]; + float radius; + int textId; + int dialogFlags; + unsigned char word; // which sDialogShown word tracks this page + unsigned short doneBit; // bit within that word; 0 means "guarded by token instead" + int token; // mumbotoken to guard on / bank (-1 = none) + const float* dialogPos; + int skipIfJiggy; // skip if this jiggy is collected (>0) + int needFlag; // skip unless this FILEPROG flag is set (>0) + int needFlagClear; // skip if this FILEPROG flag is set (>0) +}; + +struct ProximityDialogMap { + int map; + const ProximityDialogPage* pages; + int pageCount; + // Optional per-map hook run before the page loop. Return false to skip this + // map's pages this frame; may also perform side effects. nullptr = always run. + bool (*gate)(); +}; + +// Run one frame of checks against a caller-owned table (used by the storybook). +void ProximityDialogs_Run(const ProximityDialogMap* maps, int count); + +// Register a GameFrameUpdate that runs the given world table every frame. +void ProximityDialogs_Enable(const ProximityDialogMap* maps, int count); + +// Deduce the count from a fixed table so callers pass just the table. +template inline void ProximityDialogs_Enable(const ProximityDialogMap (&maps)[N]) { + ProximityDialogs_Enable(maps, N); +} + +// Shown-bit access for gate() callbacks that re-arm a page. +bool ProximityDialogs_IsShown(int word, unsigned bits); +void ProximityDialogs_ClearShown(int word, unsigned bits); diff --git a/src/port/Romhack/Shared/StealthNoise.cpp b/src/port/Romhack/Shared/StealthNoise.cpp new file mode 100644 index 000000000..98147c193 --- /dev/null +++ b/src/port/Romhack/Shared/StealthNoise.cpp @@ -0,0 +1,362 @@ +#include +#include + +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/RomhackConfig.h" +#include "StealthNoise.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "bk_time.h" +#include "core1/core1.h" +#include "core2/timedfunc.h" +#include "core1/pfsmanager.h" + +extern f32 D_8037C5B0[3]; +extern PfsManagerControllerData D_80281138[4]; +extern Gfx D_80369238[]; +f32 randf(void); +s32 getGameMode(void); + +typedef struct { + s16 x, y, topVertexAlpha, bottomVertexAlpha; + u8 fmtString[8]; + f32 scale; + u8* string; + u8 rgba[4]; +} StealthPrintBuffer; +extern StealthPrintBuffer* print_sCurrentPtr; +} + +namespace { + +// Constants +constexpr f32 kHudLerp = 0.25f; +constexpr f32 kAlphaLerp = 0.2f; +constexpr f32 kAlphaEpsilon = 0.01f; +constexpr f32 kHudShownX = 20.0f; +constexpr f32 kHudHiddenX = -70.0f; +constexpr f32 kHudYDialog = 137.0f; +constexpr f32 kHudYPlain = 177.0f; +constexpr f32 kAlphaNear = 1.0f; +constexpr f32 kAlphaFar = 0.6f; +constexpr f32 kStickDeadzone = 0.1f; +constexpr f32 kGainScaleInner = 0.4f; +constexpr f32 kGainScaleOuter = 0.46f; +constexpr f32 kGainJitter = 0.05f; +constexpr f32 kDecay = 0.55f; +constexpr f32 kDecayFloor = 0.1f; +constexpr f32 kEggPeriodHead = 0.4f; +constexpr f32 kEggPeriodAss = 0.6f; +constexpr f32 kEggJitter = 0.07f; +constexpr f32 kLoudAirborne = 0.85f; +constexpr f32 kLoudAirJitter = 0.1f; +constexpr f32 kCatchCamDelay = 0.72f; +constexpr f32 kLabelScale = 0.75f; +constexpr s32 kAirborneForLanding = 3; +constexpr u32 kCatchSfxPacked = 0xB31FF86B; +constexpr s32 kCatchSfxA = 0x142; +constexpr s32 kCatchSfxB = 0x14B; + +// HUD geometry +constexpr s16 kLabelOffX = 8, kLabelOffY = 8; +constexpr s16 kFrameX = 0, kFrameY = 0, kFrameW = 85, kFrameH = 20; +constexpr s16 kBarX = 4, kBarY = 12, kBarW = 77, kBarH = 5; +constexpr f32 kFrameAlphaScale = 160.0f; +constexpr f32 kBarAlphaScale = 136.0f; + +// Quiet-states table +constexpr s32 kQuietStates[] = { + BS_0_NONE, + BS_1_IDLE, + BS_2_WALK_SLOW, + BS_1F_WALK_CREEP, + BS_5A_LOADZONE, + BS_7_CROUCH, + BS_7A_WALK_MUD, + BS_98_WALK_DRONE, + BS_9_EGG_HEAD, + BS_A_EGG_ASS, + BS_14_BTROT_ENTER, + BS_15_BTROT_IDLE, + BS_17_BTROT_EXIT, + BS_1A_WONDERWING_ENTER, + BS_1B_WONDERWING_IDLE, + BS_1E_WONDERWING_EXIT, +}; + +struct NoiseState { + s32 airborneFrames; + bool loudLanding; + f32 noise; + f32 gain; + f32 burstTimer; + f32 burstAmount; + f32 eggTimer; + bool hudRetracted; + f32 hudX, hudY, hudAlpha; + f32 targetX, targetY, targetAlpha; + bool hudOffscreen; +}; + +NoiseState sState{}; +const StealthNoiseConfig* sCfg = nullptr; +bool sCaughtBefore = false; +bool sSuspended = false; +bool sCatchPending = false; + +f32 Clamp01(f32 value) { + return value < 0.0f ? 0.0f : (value > 1.0f ? 1.0f : value); +} + +void Approach(f32& current, f32 target, f32 rate, f32 epsilon) { + const f32 delta = target - current; + if (fabsf(delta) > epsilon) { + current += delta * rate; + } +} + +bool IsQuiet(s32 state) { + for (s32 quietState : kQuietStates) { + if (quietState == state) { + return true; + } + } + return false; +} + +void ResetMeter() { + sState.airborneFrames = 0; + sState.loudLanding = false; + sState.noise = 0.0f; + sState.eggTimer = 0.0f; + sState.burstTimer = 0.0f; + sState.targetX = kHudHiddenX; + sState.targetY = kHudYPlain; + sState.targetAlpha = kAlphaFar; + sState.hudOffscreen = true; +} + +void RetractHud() { + sState.hudRetracted = true; +} + +void TriggerCatch() { + sState.noise = 1.0f; + func_8030E624(kCatchSfxPacked); + gcdialog_showDialog(sCfg->caughtTextId, sCaughtBefore ? 0x02 : 0x82, NULL, NULL, NULL, NULL); + func_80324E38(0.0f, 1); + timed_setStaticCameraToNode(kCatchCamDelay, 1); + timedFunc_set_0(kCatchCamDelay, RetractHud); + sCaughtBefore = true; + sCatchPending = true; +} + +void ResolveCatch() { + gcsfx_play((enum sfx_e)(sfx_randi2(0, 2) != 0 ? kCatchSfxA : kCatchSfxB)); + if (!mumboscore_get((enum mumbotoken_e)sCfg->firstCatchToken)) { + const s32 warpDestination = port_getRomhackWarpDest(sCfg->escapeWarpIndex); + if (warpDestination >= 0) { + func_8031CC8C(NULL, warpDestination); + } else if (sCfg->escapeWarpFallback != nullptr) { + sCfg->escapeWarpFallback(NULL, NULL); + } + mumboscore_set((enum mumbotoken_e)sCfg->firstCatchToken, 1); + } else { + transitionToMap((enum map_e)gsworld_getMap(), gsworld_getExit(), 1); + } + sSuspended = true; + sCatchPending = false; +} + +void Update() { + if (sCfg == nullptr || gsworld_getMap() != sCfg->map) { + return; + } + NoiseState& meter = sState; + + Approach(meter.hudX, meter.targetX, kHudLerp, 1.0f); + Approach(meter.hudY, meter.targetY, kHudLerp, 1.0f); + Approach(meter.hudAlpha, meter.targetAlpha, kAlphaLerp, kAlphaEpsilon); + meter.hudAlpha = Clamp01(meter.hudAlpha); + + if (meter.burstTimer > 0.0f) { + meter.burstTimer -= time_getDelta(); + if (meter.burstTimer < 0.0f) { + meter.burstTimer = 0.0f; + } + } else { + meter.burstAmount = 0.0f; + } + + const bool dialogUp = gcdialog_hasCurrentTextId() != 0; + if (!dialogUp && sCatchPending) { + ResolveCatch(); + } + + const f32 playerX = D_8037C5B0[0]; + const bool inRoom = playerX >= sCfg->zoneMin && playerX <= sCfg->zoneMax; + if (inRoom && !meter.hudRetracted) { + meter.hudOffscreen = false; + } else if (!inRoom) { + meter.hudOffscreen = true; + } + + print_dialog((s32)(kLabelOffX + meter.hudX), (s32)(kLabelOffY + meter.hudY), (u8*)"NOISE"); + if (print_sCurrentPtr != nullptr) { + print_sCurrentPtr->scale = kLabelScale; + if (inRoom && !meter.hudOffscreen) { + meter.targetAlpha = (playerX >= sCfg->innerMin && playerX <= sCfg->innerMax) ? kAlphaNear : kAlphaFar; + } else { + meter.targetAlpha = 0.0f; + } + print_sCurrentPtr->rgba[0] = 0xFF; + print_sCurrentPtr->rgba[1] = 0xFF; + print_sCurrentPtr->rgba[2] = 0xFF; + print_sCurrentPtr->rgba[3] = (u8)(meter.hudAlpha * 255.0f); + } + + meter.targetY = dialogUp ? kHudYDialog : kHudYPlain; + meter.targetX = meter.hudRetracted ? kHudHiddenX : kHudShownX; + meter.hudOffscreen = meter.hudRetracted; + + if (sSuspended || sCatchPending) { + return; + } + + const s32 state = bs_getState(); + const bool quiet = IsQuiet(state); + const bool stable = player_isStable() != 0; + + const bool inner = playerX >= sCfg->innerMin && playerX <= sCfg->innerMax; + if (!inRoom) { + ResetMeter(); + return; + } + + const bool muted = !stable || D_80281138[0].side_button2.button_z != 0 || state == BS_73_UNKNOWN || + state == BS_79_BTROT_LOCKED || state == BS_98_WALK_DRONE || state == BS_1E_WONDERWING_EXIT || + (state & ~0x10) == BS_7_CROUCH; + f32 gain = 0.0f; + if (!muted) { + gain = Clamp01((bastick_distance() - kStickDeadzone) / (inner ? kGainScaleInner : kGainScaleOuter)); + } + meter.gain = Clamp01(gain + randf() * kGainJitter); + + if (state == BS_9_EGG_HEAD || state == BS_A_EGG_ASS) { + meter.eggTimer += time_getDelta(); + const f32 period = (state == BS_9_EGG_HEAD) ? kEggPeriodHead : kEggPeriodAss; + meter.noise = (meter.eggTimer > period ? kStickDeadzone : 0.0f) + meter.burstAmount + randf() * kEggJitter; + } else { + meter.noise = (inner && stable) ? meter.gain : meter.noise + meter.gain; + meter.eggTimer = 0.0f; + if (!stable) { + meter.airborneFrames++; + if (!inner) { + meter.loudLanding = false; + } + } else { + if (meter.airborneFrames >= kAirborneForLanding) { + meter.loudLanding = true; + meter.noise = 1.0f; + } + if (!inner) { + meter.loudLanding = false; + const f32 decayed = meter.noise * kDecay; + if (decayed < kDecayFloor) { + meter.airborneFrames = 0; + meter.noise = 0.0f; + } else { + meter.noise = decayed; + } + meter.noise += randf() * kGainJitter; + } + } + } + + if (state != BS_73_UNKNOWN && state != BS_79_BTROT_LOCKED && !quiet) { + meter.noise = stable ? 1.0f : kLoudAirborne + randf() * kLoudAirJitter; + } + meter.noise = Clamp01(meter.noise); + + if (inner && stable && (!quiet || meter.loudLanding)) { + TriggerCatch(); + } +} + +void FillRect(Gfx** gfx, s32 left, s32 top, s32 width, s32 height, u8 red, u8 green, u8 blue, u8 alpha) { + if (width <= 0 || height <= 0 || alpha == 0) { + return; + } + gDPPipeSync((*gfx)++); + gDPSetPrimColor((*gfx)++, 0, 0, red, green, blue, alpha); + gDPSetCombineMode((*gfx)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + gDPScisFillRectangle((*gfx)++, left, top, left + width - 1, top + height - 1); + gDPPipeSync((*gfx)++); +} + +void BarColour(s32 percent, u8* red, u8* green) { + const s32 remaining = 100 - percent; + if (percent >= 100) { + *red = 0xFF; + *green = 0x00; + } else if (remaining >= 100) { + *red = 0x00; + *green = 0xFF; + } else if (remaining < 40) { + *red = 0xFF; + *green = (u8)((255 * remaining) / 40); + } else { + *red = (u8)((255 * percent) / 60); + *green = 0xFF; + } +} + +void Draw(Gfx** gfx) { + if (sCfg == nullptr || gsworld_getMap() != sCfg->map || getGameMode() == GAME_MODE_4_PAUSED) { + return; + } + const NoiseState& meter = sState; + const u8 frameAlpha = (u8)(meter.hudAlpha * kFrameAlphaScale); + if (frameAlpha == 0) { + return; + } + + gSPDisplayList((*gfx)++, D_80369238); + FillRect(gfx, (s32)(kFrameX + meter.hudX), (s32)(kFrameY + meter.hudY), kFrameW, kFrameH, 0x00, 0x00, 0x00, + frameAlpha); + + s32 percent = (s32)(meter.noise * 100.0f); + percent = percent < 0 ? 0 : (percent > 100 ? 100 : percent); + u8 red, green; + BarColour(percent, &red, &green); + FillRect(gfx, (s32)(kBarX + meter.hudX), (s32)(kBarY + meter.hudY), (s32)(kBarW * meter.noise), kBarH, red, green, + 0x00, (u8)(meter.hudAlpha * kBarAlphaScale)); +} + +} // namespace + +void StealthNoise_AddBurst(float amount, float seconds) { + sState.burstAmount = amount; + sState.burstTimer = seconds; +} + +void StealthNoise_Enable(const StealthNoiseConfig& cfg) { + sCfg = &cfg; + ResetMeter(); + + REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent*) { Update(); }); + + REGISTER_LISTENER(OnHudDraw, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + auto* hudEvent = reinterpret_cast(event); + Draw(hudEvent->gfx); + }); + + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { + sSuspended = false; + sCatchPending = false; + sState.hudRetracted = false; + ResetMeter(); + }); +} diff --git a/src/port/Romhack/Shared/StealthNoise.h b/src/port/Romhack/Shared/StealthNoise.h new file mode 100644 index 000000000..5d25e698c --- /dev/null +++ b/src/port/Romhack/Shared/StealthNoise.h @@ -0,0 +1,20 @@ +#pragma once + +extern "C" { +#include "prop.h" +} + +struct StealthNoiseConfig { + int map; + float zoneMin; + float zoneMax; + float innerMin; + float innerMax; + int caughtTextId; + int escapeWarpIndex; + void (*escapeWarpFallback)(NodeProp*, ActorMarker*); + int firstCatchToken; +}; + +void StealthNoise_Enable(const StealthNoiseConfig& cfg); +void StealthNoise_AddBurst(float amount, float seconds); diff --git a/src/port/Romhack/Shared/Storybook.cpp b/src/port/Romhack/Shared/Storybook.cpp new file mode 100644 index 000000000..d461cb546 --- /dev/null +++ b/src/port/Romhack/Shared/Storybook.cpp @@ -0,0 +1,134 @@ +#include +#include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "Storybook.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "macros.h" +#include "actor.h" +#include "core1/ml.h" + +extern OSContPad pfsManagerContPadData[4]; +extern PfsManagerControllerData D_80281138[4]; +extern Struct_core1_10A00_1 D_80281250[4]; +extern f32 D_8037C5B0[3]; +extern f32 player_position[3]; +} + +namespace { + +bool IsStorybookMap(enum map_e map); +f32 StoryStickAxis(s32 raw); +void StorybookInputCapture(); +void StorybookPageUpdate(); +void ApplyStorybookIntroHooks(); + +// Engine tuning +constexpr f32 kPageStep = 2500.0f; +constexpr f32 kStickClamp = 80.0f; +constexpr f32 kPushThreshold = 0.5f; +constexpr f32 kCenterThreshold = 0.3f; +constexpr s32 kDebounceTicks = 50; + +// Per-hack data +const ProximityDialogMap* sPages = nullptr; +s32 sPageCount = 0; +s32 sResumeDest = 0; +s32 sSeenToken = -1; + +bool sStorybookEnabled = false; +s32 sStoryTick = 0; +s32 sStoryLastStep = -kDebounceTicks - 1; +s32 sStoryStickX = 0; +s32 sStoryStickY = 0; + +bool IsStorybookMap(enum map_e map) { + for (s32 i = 0; i < sPageCount; i++) { + if ((enum map_e)sPages[i].map == map) { + return true; + } + } + return false; +} + +f32 StoryStickAxis(s32 raw) { + f32 v = (f32)raw; + if (v > kStickClamp) { + v = kStickClamp; + } else if (v < -kStickClamp) { + v = -kStickClamp; + } + return v / kStickClamp; +} + +void StorybookInputCapture() { + if (!IsStorybookMap(gsworld_getMap())) { + return; + } + sStoryStickX = pfsManagerContPadData[0].stick_x; + sStoryStickY = pfsManagerContPadData[0].stick_y; + memset(&D_80281138[0], 0, sizeof(D_80281138[0])); + memset(&D_80281250[0], 0, sizeof(D_80281250[0])); + pfsManagerContPadData[0].stick_x = 0; + pfsManagerContPadData[0].stick_y = 0; + pfsManagerContPadData[0].button = 0; +} + +void StorybookPageUpdate() { + sStoryTick++; + if (!IsStorybookMap(gsworld_getMap())) { + return; + } + D_8037C5B0[1] = 0.0f; + D_8037C5B0[2] = 0.0f; + + if (!gcdialog_hasCurrentTextId()) { + const f32 x = StoryStickAxis(sStoryStickX); + const f32 y = StoryStickAxis(sStoryStickY); + if (y > -kCenterThreshold && y < kCenterThreshold && x > kPushThreshold && + sStoryLastStep + kDebounceTicks < sStoryTick) { + sStoryLastStep = sStoryTick; + D_8037C5B0[0] += kPageStep; + } + } + player_position[0] = D_8037C5B0[0]; +} + +void ApplyStorybookIntroHooks() { + // First storybook writes a mumbo token to indicate that it's been seen + COND_VB_SHOULD(VB_GAMESELECT_START_NEW_GAME, EVENT_PRIORITY_NORMAL, sStorybookEnabled, { + (void)args; // gamenum is passed but unused + const bool seen = sSeenToken >= 0 && mumboscore_get((enum mumbotoken_e)sSeenToken); + *should = !seen; + }); + + // Storybook mode freezes all input except the left stick's right movement + COND_HOOK(OnControllerUpdate, EVENT_PRIORITY_NORMAL, sStorybookEnabled, [](IEvent*) { StorybookInputCapture(); }); + + COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, sStorybookEnabled, [](IEvent*) { + ProximityDialogs_Run(sPages, sPageCount); + StorybookPageUpdate(); + }); +} + +} // namespace + +extern "C" void Storybook_ResumeWarp(NodeProp* node, ActorMarker* marker) { + (void)marker; + func_8031CC8C(node, sResumeDest); +} + +extern "C" void* port_getRomhackResumeWarpFunc(void) { + return sStorybookEnabled ? (void*)&Storybook_ResumeWarp : nullptr; +} + +void Storybook_Enable(const StorybookConfig& cfg) { + sPages = cfg.pages; + sPageCount = cfg.pageCount; + sResumeDest = cfg.resumeDest; + sSeenToken = cfg.newGameSeenToken; + sStorybookEnabled = true; + ApplyStorybookIntroHooks(); +} diff --git a/src/port/Romhack/Shared/Storybook.h b/src/port/Romhack/Shared/Storybook.h new file mode 100644 index 000000000..554ec22d3 --- /dev/null +++ b/src/port/Romhack/Shared/Storybook.h @@ -0,0 +1,12 @@ +#pragma once + +#include "ProximityDialogs.h" + +struct StorybookConfig { + const ProximityDialogMap* pages; // book pages, one entry per book map + int pageCount; // number of book maps + int resumeDest; // MAP<<8 | ENTRY warp used when resuming a save + int newGameSeenToken; // mumbotoken the first book banks (-1 = none) +}; + +void Storybook_Enable(const StorybookConfig& cfg); diff --git a/src/port/Romhack/Specific/BubblingBog.cpp b/src/port/Romhack/Specific/BubblingBog.cpp new file mode 100644 index 000000000..9762bbe5d --- /dev/null +++ b/src/port/Romhack/Specific/BubblingBog.cpp @@ -0,0 +1,24 @@ +#include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/Shared/HackShared.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +} + +// The Tooie jiggy animation exists in this hack +void TooieJiggyDance_ForceEnable(); + +void RegisterBubblingBogPatches() { + TooieJiggyDance_ForceEnable(); + HackShared_EnableForceAbilitiesUsed(kAllUsedAbilities); + + // Bubbling Bog Brewery's swapy water is hazardous + REGISTER_VB_SHOULD(VB_GROUND_HAZARD_ACTIVE, EVENT_PRIORITY_NORMAL, { + s32 map = va_arg(args, s32); + if (map == MAP_D_BGS_BUBBLEGLOOP_SWAMP && func_80294554()) { + *should = true; + } + }); +} diff --git a/src/port/Romhack/Specific/CutThroatCoast.cpp b/src/port/Romhack/Specific/CutThroatCoast.cpp new file mode 100644 index 000000000..4ef92627e --- /dev/null +++ b/src/port/Romhack/Specific/CutThroatCoast.cpp @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/RomhackConfig.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "model.h" + +extern struct1Cs_1 D_8036C58C[0xD]; + +// Acorn replaced with collectible doubloon +extern ActorInfo chCarriedAcorn; +void chCarriedAcorn_update(Actor* thisx); + +typedef struct { + u8 map_id; + u8 rgb[3]; + u8 alpha; +} CameraFogEntry; +extern CameraFogEntry D_80365D60[]; + +typedef struct { + u8 uid; + u8 state; + u8 next_state; + f32 duration; + s32 model_index; + s32 anim_index; + f32 scale; +} TransitionInfoEntry; +extern TransitionInfoEntry D_8036C150[0x16]; +} + +namespace { + +// Custom transition pair +constexpr s32 kPairMapA = MAP_2_MM_MUMBOS_MOUNTAIN; +constexpr s32 kPairMapB = MAP_31_RBB_RUSTY_BUCKET_BAY; +constexpr s32 kPairInIndex = 0xD; + +GameMap sPrevMap = (GameMap)0; +GameMap sCurMap = (GameMap)0; + +struct PauseRemap { + int src; + s16 level_id; + s16 x; +}; +constexpr PauseRemap kRemap[0xD] = { + { 0, 0, 80 }, { 1, 0, 64 }, { 3, 0, 37 }, { 4, 0, 27 }, { 5, 0, 52 }, { 6, 0, 35 }, { 7, 0, 72 }, + { 8, 0, 78 }, { 9, 0xA, 43 }, { 10, 0, 50 }, { 11, 0, 48 }, { 2, 0, 60 }, { 12, 0, 72 }, +}; + +void RebuildPauseMenuTable() { + u8* names[0xD]; + for (int i = 0; i < 0xD; i++) { + names[i] = D_8036C58C[i].string; + } + for (int page = 0; page < 0xD; page++) { + D_8036C58C[page].string = names[kRemap[page].src]; + D_8036C58C[page].level_id = kRemap[page].level_id; + D_8036C58C[page].x = kRemap[page].x; + } + D_8036C58C[8].string = (u8*)"CUT-THROAT COAST"; +} + +void ApplyDataPatches() { + D_80365D60[3] = { 0, { 0x34, 0x6E, 0xEF }, 0x5A }; + D_8036C150[3].state = 7; // TRANSITION_STATE_7_WHITE_IN + D_8036C150[3].next_state = 0; // TRANSITION_STATE_0_NONE + D_8036C150[3].duration = 0.7f; + D_8036C150[3].model_index = 0; + D_8036C150[3].anim_index = 0; + D_8036C150[12].duration = 0.4f; + D_8036C150[13].state = 3; // TRANSITION_STATE_3_BLACK_OUT + D_8036C150[13].next_state = 1; // TRANSITION_STATE_1_LOADING + D_8036C150[13].duration = 0.4f; + D_8036C150[13].model_index = 0; + D_8036C150[13].scale = 0.0f; +} + +// Lighthouse beam sweep +constexpr s32 kBeamFirstVtx = 423; +constexpr s32 kBeamLastVtx = 454; +constexpr f32 kBeamDegPerTick = 2.0f; + +struct BeamVert { + Vtx* v; + f32 dx, dz; +}; +BKModelBin* sBeamModelBin = nullptr; +std::vector sBeamVerts; +f32 sBeamAngle = 0.0f; +f32 sBeamPivotX, sBeamPivotZ; + +void UpdateLighthouseBeam() { + if (gsworld_getMap() != MAP_1B_MMM_MAD_MONSTER_MANSION) { + return; + } + BKModelBin* bin = mapModel_getModelBin(1); + if (bin == nullptr) { + sBeamModelBin = nullptr; + return; + } + if (bin != sBeamModelBin) { + sBeamModelBin = bin; + sBeamVerts.clear(); + BKVertexList* vl = modelbin_getVtxList(bin); + if (vl == nullptr) { + sBeamModelBin = nullptr; + return; + } + s32 cnt = vtxList_getVtxCount(vl); + if (cnt <= kBeamLastVtx) { + return; + } + for (s32 i = kBeamFirstVtx; i <= kBeamLastVtx; i++) { + sBeamVerts.push_back({ &vl->vertices[i], 0.0f, 0.0f }); + } + sBeamPivotX = 3563.0f; + sBeamPivotZ = 8751.0f; + for (auto& bv : sBeamVerts) { + bv.dx = bv.v->v.ob[0] - sBeamPivotX; + bv.dz = bv.v->v.ob[2] - sBeamPivotZ; + } + } + sBeamAngle = mlNormalizeAngle(sBeamAngle + kBeamDegPerTick); + f32 rad = sBeamAngle * (f32)(BAD_PI / 180.0); + f32 c = cosf(rad), s = sinf(rad); + for (auto& bv : sBeamVerts) { + bv.v->v.ob[0] = (s16)(sBeamPivotX + bv.dx * c - bv.dz * s); + bv.v->v.ob[2] = (s16)(sBeamPivotZ + bv.dx * s + bv.dz * c); + } +} + +} // namespace + +extern "C" void CutThroatCoast_DoubloonUpdate(Actor* thisx) { + thisx->yaw = mlNormalizeAngle(thisx->yaw + 12.0f); + chCarriedAcorn_update(thisx); +} + +void RegisterCutThroatCoastPatches() { + RebuildPauseMenuTable(); + ApplyDataPatches(); + chCarriedAcorn.update_func = CutThroatCoast_DoubloonUpdate; + + // Sweep the lighthouse beam + REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + (void)event; + UpdateLighthouseBeam(); + }); + + // Track map changes for the custom MM <-> RBB transition below. + REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_HIGH, [](IEvent* event) { + auto* ev = reinterpret_cast(event); + sPrevMap = ev->prevMap; + sCurMap = ev->nextMap; + }); + + // Pause menu pins below + REGISTER_VB_SHOULD(VB_JIGGYSCORE_LEVEL_TOTAL, EVENT_PRIORITY_NORMAL, { + s32 lvl = va_arg(args, s32); + s32* result = va_arg(args, s32*); + s32 cnt = 0; + if (lvl == 0xA) { + for (s32 i = 1; i < 0x65; i++) { + if (jiggyscore_isCollected((enum jiggy_e)i)) { + cnt++; + } + } + if (cnt > 0xA) { + cnt = 0xA; + } + } + *result = cnt; + *should = false; + }); + + REGISTER_VB_SHOULD(VB_PAUSEMENU_LEVEL_TO_PAGE, EVENT_PRIORITY_NORMAL, { + va_arg(args, s32); + s32* page = va_arg(args, s32*); + *page = 8; + *should = false; + }); + + REGISTER_VB_SHOULD(VB_PAUSEMENU_SET_NEXT_PAGE, EVENT_PRIORITY_NORMAL, { + s8* page = va_arg(args, s8*); + *page = 8; + *should = false; + }); + + REGISTER_VB_SHOULD(VB_PAUSEMENU_DRAW_JOYSTICKS, EVENT_PRIORITY_NORMAL, { + (void)args; + *should = false; + }); + + REGISTER_VB_SHOULD(VB_PAUSEMENU_BOLD_FONT_TEXTURE, EVENT_PRIORITY_NORMAL, { + s32* fontId = va_arg(args, s32*); + *fontId = 0x6E4; + (void)should; + }); + + // TODO: CTC has an extra data blob separate from the asset table + // where a custom gravestone and note door (100) are. Torch should not + // need to do per-romhack extraction, so these will need to either be skipped + // or rebuilt a different way. For now, blank the digits on the note door. + REGISTER_VB_SHOULD(VB_NOTEDOOR_DRAW_NUMBER, EVENT_PRIORITY_NORMAL, { + s32 noteDoorIdx = va_arg(args, s32); + if (noteDoorIdx >= 1 && port_getRomhackNoteDoor(noteDoorIdx - 1) >= 0) { + *should = false; + } + }); + + // Exiting via the exit pad should go back to the CTC lobby map + REGISTER_VB_SHOULD(VB_MAP_CHANGE_REQUEST, EVENT_PRIORITY_NORMAL, { + s32* map = va_arg(args, s32*); + s32* exit = va_arg(args, s32*); + if (*map == MAP_75_GL_MMM_LOBBY) { + *map = MAP_1_SM_SPIRAL_MOUNTAIN; + *exit = 2; + } + (void)should; + }); + + REGISTER_VB_SHOULD(VB_VOID_OUT_RESPAWN_TRANSITION, EVENT_PRIORITY_NORMAL, { + s32 map = va_arg(args, s32); + s32 exit = va_arg(args, s32); + transitionToMap((enum map_e)map, exit, 1); + *should = false; + }); + + REGISTER_VB_SHOULD(VB_MAP_TRANSITION_IN_INDEX, EVENT_PRIORITY_NORMAL, { + s32 map = va_arg(args, s32); + s32* inIndex = va_arg(args, s32*); + s32 other = (map == sCurMap) ? sPrevMap : sCurMap; + if ((map == kPairMapA && other == kPairMapB) || (map == kPairMapB && other == kPairMapA)) { + *inIndex = kPairInIndex; + } + (void)should; + }); + + // The repurposed season switches are hidden below the ground when hit + REGISTER_VB_SHOULD(VB_CCW_SEASON_SWITCH_PRESSED_INIT, EVENT_PRIORITY_NORMAL, { + Actor* switchActor = va_arg(args, Actor*); + switchActor->position[1] = -420.0f; + subaddie_set_state(switchActor, 4); + *should = false; + }); + + // Suppress the jiggy tutorial dialog + REGISTER_VB_SHOULD(VB_JIGGY_COLLECT_TUTORIAL, EVENT_PRIORITY_NORMAL, { + (void)args; + *should = false; + }); + + // This MMM empty honeycomb doesn't require the pumpkin + REGISTER_VB_SHOULD(VB_HONEYCOMB_PUMPKIN_REQUIREMENT, EVENT_PRIORITY_NORMAL, { + (void)args; + *should = false; + }); + + // The sky timer never advances, so skybox layers hold their initial rotation + REGISTER_VB_SHOULD(VB_SKY_UPDATE, EVENT_PRIORITY_NORMAL, { + (void)args; + *should = false; + }); + + // No fullscreen clear behind the skybox when sky models are present + REGISTER_VB_SHOULD(VB_SKY_DRAW_BACKDROP_RECT, EVENT_PRIORITY_NORMAL, { + (void)args; + *should = false; + }); + + // Suppress Brentilda's heal dialog + REGISTER_VB_SHOULD(VB_BRENTILDA_HEAL_DIALOG, EVENT_PRIORITY_NORMAL, { + (void)args; + *should = false; + }); +} diff --git a/src/port/Romhack/Specific/Dreamie.cpp b/src/port/Romhack/Specific/Dreamie.cpp new file mode 100644 index 000000000..2a1dbae0c --- /dev/null +++ b/src/port/Romhack/Specific/Dreamie.cpp @@ -0,0 +1,37 @@ +/* + * Banjo-Dreamie + * + * Dreamie ships no custom code at all - it rewires the world purely through BB + * globalized-overlay data, so the BKCF carries everything. Spiral Mountain becomes + * the hub, and two of the ~86 warp edits retarget the Spiral Mountain transitions: + * + * warp_smExitBanjosHouse 0x0112 -> 0x0105 + * warp_lairEnterLairFromSMLevel 0x6912 -> 0x0112 + * + * Both resolve to map 0x01, which is also Dreamie's new-game map (START_MAP = 1, + * START_LEVEL_2 = 1, down from vanilla 0x69). Honoring them verbatim drops every hub + * transition back into the starting room instead of moving between areas. + * + * On every OnWarpResolveDest fire, restore the dispatcher's vanilla default for these + * two warps, ignoring what the BKCF claims. The other BKCF warp remaps are genuine and + * pass through untouched. + * + */ + +#include + +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/RomhackConfig.h" + +static constexpr int kWarpIdxSmExitBanjosHouse = 281; + +void RegisterDreamiePatches() { + port_clearRomhackWarpDest(kWarpIdxSmExitBanjosHouse); + + REGISTER_LISTENER(OnWarpResolveDest, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + auto* ev = reinterpret_cast(event); + if (ev->warpId == WARP_ID_SM_EXIT_BANJOS_HOUSE || ev->warpId == WARP_ID_LAIR_ENTER_LAIR_FROM_SM_LEVEL) { + *ev->dest = ev->defaultDest; + } + }); +} diff --git a/src/port/Romhack/Specific/JiggiesOfTime.cpp b/src/port/Romhack/Specific/JiggiesOfTime.cpp new file mode 100644 index 000000000..614288a40 --- /dev/null +++ b/src/port/Romhack/Specific/JiggiesOfTime.cpp @@ -0,0 +1,31 @@ +/* + * Jiggies of Time Fun Facts + * + * The Collywobble actor is marker-swapped to prevent a spawn. This is rarely seen anyway, since BB enforces + * file select as the default boot. With vanilla, if you were to view the intro sequence after a game over, + * you'd see a stray Collywobble spawned during the concert when it shouldn't be there at all. + * + * An unused vanilla marker 0x54 spawns ASSET_50B_MODEL_X_BARREL_TOP, which in Jiggies of Time is model-swapped + * with a random honeycomb drop. + * + */ + +#include +#include "port/Romhack/Shared/HackShared.h" + +extern "C" { +#include "enums.h" +#include "functions.h" + +extern ActorInfo chXBarrelTop; +extern ActorInfo gChVegetablesCollywobbleB; +} + +void RegisterJiggiesOfTimePatches() { + chXBarrelTop.markerId = 0x54; + gChVegetablesCollywobbleB.markerId = MARKER_1F1_GRUNTLING_BLACK; + + // JoT's note signs are repurposed Red Question Marks. + // Source: https://github.com/Mr-Wiseguy/JiggiesOfTimeRecomp/blob/main/src/note_signs.c + HackShared_EnableNoteSignSuppression(ACTOR_54_RED_QUESTION_MARK); +} diff --git a/src/port/Romhack/Specific/NewHorizons.cpp b/src/port/Romhack/Specific/NewHorizons.cpp new file mode 100644 index 000000000..67d671680 --- /dev/null +++ b/src/port/Romhack/Specific/NewHorizons.cpp @@ -0,0 +1,25 @@ +/* + * New Horizons Fun Facts + * + * Beyond the BKCF-covered data tables, New Horizons patches two ActorInfo + * marker bindings inside its copy of the globalized-overlay blob. + * + */ + +#include +#include "port/Enhancements/Events/Hooks/Events.h" + +extern "C" { +#include "enums.h" +#include "functions.h" + +// { MARKER_235_CRACKED_SKYLIGHT, ACTOR_23F_CRACKED_SKYLIGHT, ... } +extern ActorInfo chCrackedSkylight; +// { 0x220, 0x22C, ... } +extern ActorInfo D_80392994; +} + +void RegisterNewHorizonsPatches() { + chCrackedSkylight.markerId = MARKER_60_BLUE_EGG_COLLECTIBLE; + D_80392994.markerId = MARKER_60_BLUE_EGG_COLLECTIBLE; +} diff --git a/src/port/Romhack/Specific/Nostalgia64.cpp b/src/port/Romhack/Specific/Nostalgia64.cpp new file mode 100644 index 000000000..faf6b5de0 --- /dev/null +++ b/src/port/Romhack/Specific/Nostalgia64.cpp @@ -0,0 +1,90 @@ +#include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/Shared/HackShared.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "actor.h" + +extern ActorInfo D_80393378; +extern ActorInfo chGruntlingBlack; +extern ActorInfo chCellarHatch; +extern ActorInfo chMMMWideWindow; + +void chGruntling_initialize(Actor* thisx); +void func_802D3CE8(Actor* thisx); +} + +struct HitboxRow { + u16 markerId; + u16 flags; + u16 vals[11]; +}; +extern "C" HitboxRow collision_table[]; + +namespace { + +// Black Gruntling is recycled to use the Beta Vent enemy +bool sBlackGruntlingAttack = false; + +extern "C" void Nostalgia64_VentUpdate(Actor* thisx) { + Humanoid_Baddies_Actor* local = (Humanoid_Baddies_Actor*)&thisx->local; + if (!thisx->volatile_initialized) { + local->baddieSpecific = (thisx->modelCacheIndex == ACTOR_367_GRUNTLING_RED) ? 2 + : (thisx->modelCacheIndex == ACTOR_3BF_GRUNTLING_BLUE) ? 1 + : 0; + chGruntling_initialize(thisx); + } + humanoidBaddie_update(thisx); + if (thisx->state == 5) { + bool swipeFrame = actor_animationIsAt(thisx, 0.18f); + if (swipeFrame) { + sfx_playFadeShorthandDefault(SFX_2_CLAW_SWIPE, 1.0f, 28000, thisx->position, 1250, 2500); + } + sBlackGruntlingAttack = true; + if (swipeFrame) { + sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.0f, 28000, thisx->position, 1250, 2500); + } + } +} + +// Banjo takes damage while the vent is open +extern "C" void Nostalgia64_VentSmokeUpdate(Actor* thisx) { + func_802D3CE8(thisx); + for (int i = 0; i < 0xBB; i++) { + if (collision_table[i].markerId == MARKER_1F1_GRUNTLING_BLACK) { + collision_table[i].vals[10] = 0x7000; + break; + } + } + if (sBlackGruntlingAttack) { + item_adjustByDiffWithHud(ITEM_14_HEALTH, -item_getCount(ITEM_14_HEALTH)); + bs_setState(BS_41_DIE); + sBlackGruntlingAttack = false; + } +} + +// The 1881 Barrel Top was swapped for a breakable door +extern "C" void Nostalgia64_BreakableDoorUpdate(Actor* thisx) { + func_802D3CE8(thisx); + for (int i = 0; i < 0xBB; i++) { + if (collision_table[i].markerId == MARKER_9A_1881_BARREL_TOP) { + collision_table[i].flags = 0x0804; + break; + } + } +} + +} // namespace + +void RegisterNostalgia64Patches() { + D_80393378.markerId = MARKER_65_SHRAPNEL; + + chGruntlingBlack.update_func = Nostalgia64_VentUpdate; + chCellarHatch.update_func = Nostalgia64_VentSmokeUpdate; + chMMMWideWindow.update_func = Nostalgia64_BreakableDoorUpdate; + + // The N64 cube stands in for the note signs + HackShared_EnableNoteSignSuppression(ACTOR_93_INTRO_N64_CUBE); +} diff --git a/src/port/Romhack/Specific/TheGruntch.cpp b/src/port/Romhack/Specific/TheGruntch.cpp new file mode 100644 index 000000000..497d139ab --- /dev/null +++ b/src/port/Romhack/Specific/TheGruntch.cpp @@ -0,0 +1,540 @@ +/* + * All hack-specific code here is shared + between Gruntch and Santa's Village. + */ + +#include +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Romhack/Shared/HackShared.h" +#include "port/Romhack/Shared/Storybook.h" +#include "port/Romhack/Shared/ProximityDialogs.h" +#include "port/Romhack/Shared/StealthNoise.h" + +extern "C" { +#include "enums.h" +#include "functions.h" +#include "macros.h" +#include "actor.h" +#include "core1/ml.h" +#include "core2/timedfunc.h" +#include "bk_time.h" + +extern f32 D_8037C5B0[3]; +extern PfsManagerControllerData D_80281138[4]; +extern f32 cameraPosition[3]; +extern f32 cameraRotation[3]; +extern f32 D_8037D948[3]; +extern f32 D_8037D9C8[3]; +extern f32 D_8037D9E0[3]; +extern f32 D_8037D9D4, D_8037D9D8, D_8037D9EC, D_8037D9F0; +extern struct { + u8 unk0; + u8 level; +} D_80383300; + +typedef struct struct_1A_s { + f32 delay; + f32 unk4; + u8* str; + s16 y; + u8 portrait; + u8 unkF; +} PauseTotalsRow; +extern PauseTotalsRow D_8036C520[4]; +extern s8 D_8036C5F4[]; +} + +void TooieJiggyDance_ForceEnable(); + +// Suppressed dialogs +constexpr int kGruntchSuppressedDialogs[] = { + ASSET_A6F_DIALOG_RUBEE_MEET, + ASSET_C8B_DIALOG_GRUNTY_LONG_SWITCH_MISS, + ASSET_CCF_DIALOG_GNAWTY_MEET_SUMMER, + ASSET_DA3_DIALOG_EXTRA_LIFE_MEET, + 0xF78, + ASSET_D9C_DIALOG_MUSIC_NOTE_MEET, + ASSET_D9D_DIALOG_MUMBO_TOKEN_MEET, + ASSET_D9E_DIALOG_BLUE_EGG_MEET, + ASSET_D9F_DIALOG_RED_FEATHER_MEET, + ASSET_DA0_DIALOG_GOLD_FEATHER_MEET, + ASSET_DA1_DIALOG_HONEYCOMB_MEET, +}; + +// ---------------------------------------------------------- Proximity dialogs +constexpr s32 kDialogFlags8A = 0x8A; +constexpr s32 kDialogFlags82 = 0x82; +constexpr s32 kDialogFlagsA = 0x0A; +constexpr f32 kDialogRadius = 300.0f; + +// Storybook page dialogs +constexpr ProximityDialogPage kPages37[] = { + { { -7500.0f, 0.0f, 0.0f }, + kDialogRadius, + 0xA1D, + kDialogFlags8A, + 0, + 0x8000, + MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER }, + { { -5000.0f, 0.0f, 0.0f }, kDialogRadius, 0xA1E, kDialogFlags8A, 0, 0x4000, -1 }, + { { -2500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA29, kDialogFlags8A, 0, 0x2000, -1 }, +}; + +constexpr ProximityDialogPage kPages38[] = { + { { -7500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA77, kDialogFlags8A, 0, 0x0040, -1 }, +}; + +constexpr ProximityDialogPage kPages3E[] = { + { { -7500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA70, kDialogFlags8A, 0, 0x1000, -1 }, + { { -5000.0f, 0.0f, 0.0f }, kDialogRadius, 0xA72, kDialogFlags8A, 0, 0x0800, -1 }, + { { -2500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA73, kDialogFlags8A, 0, 0x0400, -1 }, + { { 0.0f, 0.0f, 0.0f }, kDialogRadius, 0xA74, kDialogFlags8A, 0, 0x0200, -1 }, + { { 2500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA75, kDialogFlags8A, 0, 0x0100, -1 }, + { { 5000.0f, 0.0f, 0.0f }, kDialogRadius, 0xA76, kDialogFlags8A, 0, 0x0080, -1 }, +}; + +constexpr ProximityDialogPage kPages3C[] = { + { { -140.0f, 100.0f, -30.0f }, kDialogRadius, 0xA83, kDialogFlags8A, 1, 0x0080, -1 }, +}; + +constexpr ProximityDialogPage kPages72[] = { + { { 315.0f, 95.0f, -2085.0f }, 200.0f, 0xA7C, kDialogFlags8A, 1, 0x0200, -1 }, +}; + +constexpr ProximityDialogPage kPages28[] = { + { { 280.0f, 0.0f, -230.0f }, + kDialogRadius, + 0xA12, + kDialogFlags8A, + 0, + 0x0000, + MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE }, +}; + +// Gameplay proximity dialogs +constexpr f32 kDialog15Pos[3] = { -568.0f, 128.0f, -180.0f }; +constexpr ProximityDialogPage kPages15[] = { + { { -200.0f, 130.0f, -100.0f }, 220.0f, 0xA82, kDialogFlags8A, 1, 0x0100, -1, kDialog15Pos }, +}; + +constexpr ProximityDialogPage kPages22[] = { + { { -2800.0f, 590.0f, 800.0f }, + 300.0f, + 0xA19, + kDialogFlags8A, + 1, + 0x1000, + -1, + NULL, + JIGGY_8_MM_ORANGE_PADS, + -1, + -1 }, + { { -180.0f, 235.0f, 370.0f }, 700.0f, 0xA1B, kDialogFlags82, 1, 0x0800, -1, NULL, JIGGY_5_MM_HUTS, 0, 0 }, +}; + +constexpr f32 kDialog1BPos[3] = { -15.0f, 798.0f, -360.0f }; +constexpr ProximityDialogPage kPages1B[] = { + { { 0.0f, 720.0f, -360.0f }, + 270.0f, + 0xA13, + kDialogFlagsA, + 1, + 0x8000, + -1, + kDialog1BPos, + -1, + -1, + FILEPROG_38_RBB_OPEN }, + { { 0.0f, 720.0f, -360.0f }, + 270.0f, + 0xA7D, + kDialogFlagsA, + 1, + 0x4000, + -1, + kDialog1BPos, + -1, + FILEPROG_38_RBB_OPEN, + -1 }, +}; + +constexpr ProximityDialogPage kPages29[] = { + { { 230.0f, 660.0f, 100.0f }, 200.0f, 0xA1C, kDialogFlags82, 1, 0x2000, -1, NULL }, +}; + +static bool GruntchDialogGate15() { + if (jiggyscore_isCollected(JIGGY_34_LAIR_MM_WITCH_SWITCH) || + !fileProgressFlag_get(FILEPROG_18_MM_WITCH_SWITCH_JIGGY_PRESSED)) { + return false; + } + fileProgressFlag_set(FILEPROG_88_TRIED_LOGGO_AS_BEAR, 1); + return true; +} + +static bool GruntchDialogGate1B() { + if (ProximityDialogs_IsShown(1, 0xC000) && player_isStable()) { + f32 reArm[3] = { 0.0f, 720.0f, -360.0f }; + if (ml_vec3f_distance(reArm, D_8037C5B0) < 170.0f && D_80281138[0].face_button[1] == 1) { + ProximityDialogs_ClearShown(1, 0xC000); + } + } + return true; +} + +// Storybook pages +constexpr ProximityDialogMap kGruntchStorybookPages[] = { + { MAP_37_RBB_CONTAINER_1, kPages37, ARRAY_COUNT(kPages37), nullptr }, + { MAP_38_RBB_CONTAINER_3, kPages38, ARRAY_COUNT(kPages38), nullptr }, + { MAP_3E_RBB_CONTAINER_2, kPages3E, ARRAY_COUNT(kPages3E), nullptr }, +}; + +// Map the player warps to when resuming save +constexpr StorybookConfig kGruntchStorybook = { + kGruntchStorybookPages, + ARRAY_COUNT(kGruntchStorybookPages), + 0x2802, + MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, +}; + +// Gameplay dialogs +constexpr ProximityDialogMap kGruntchGameplayDialogs[] = { + { MAP_3C_RBB_KITCHEN, kPages3C, ARRAY_COUNT(kPages3C), nullptr }, + { MAP_28_MMM_EGG_ROOM, kPages28, ARRAY_COUNT(kPages28), nullptr }, + { MAP_72_GL_BGS_LOBBY, kPages72, ARRAY_COUNT(kPages72), nullptr }, + { MAP_15_GV_WATER_PYRAMID, kPages15, ARRAY_COUNT(kPages15), GruntchDialogGate15 }, + { MAP_1B_MMM_MAD_MONSTER_MANSION, kPages1B, ARRAY_COUNT(kPages1B), GruntchDialogGate1B }, + { MAP_22_CC_INSIDE_CLANKER, kPages22, ARRAY_COUNT(kPages22), nullptr }, + { MAP_29_MMM_NOTE_ROOM, kPages29, ARRAY_COUNT(kPages29), nullptr }, +}; + +// ---------------------------------------------------------- Conditional actors +static bool sConditionalActorsEnabled = false; + +extern "C" void romhack_RewriteActorSpawn(void* actorInfo, u32* flags) { + if (!sConditionalActorsEnabled || actorInfo == NULL || flags == NULL) { + return; + } + ActorInfo* info = (ActorInfo*)actorInfo; + switch (info->actorId) { + case 0x131: + *flags = (*flags & ~0x02u) | 0x40u; + break; + case 0xF: + case 0xF1: + case ACTOR_340_XMAS_TREE_ICE: + *flags |= 0x400u; + info->draw_distance = 0x8000; + break; + default: + break; + } +} + +// Draw the Giant Christmas Tree only if it's been "purchased" +static void Gruntch_EnableConditionalActors() { + sConditionalActorsEnabled = true; + COND_VB_SHOULD(VB_XMAS_TREE_ICE_UPDATE, EVENT_PRIORITY_NORMAL, sConditionalActorsEnabled, { + Actor* self = va_arg(args, Actor*); + if (gsworld_getMap() == MAP_1B_MMM_MAD_MONSTER_MANSION && self != NULL && self->marker != NULL && + self->marker->propPtr != NULL) { + bool open = fileProgressFlag_get(FILEPROG_38_RBB_OPEN) != 0; + self->marker->propPtr->unk8_3 = open; + self->unk38_31 = !open; + *should = false; + } + }); + + // Force Boggy to be visible + COND_VB_SHOULD(VB_BOGGY_HOME_VISIBLE, EVENT_PRIORITY_NORMAL, sConditionalActorsEnabled, { *should = true; }); +} + +// --------------------------------------------------------------- Mumbo reward +namespace { +constexpr f32 kJiggyDelay = 4.15f; +constexpr f32 kStateDelay = 3.85f; +constexpr f32 kStateValue = 1.1f; +constexpr f32 kCameraReleaseDelay = 0.5f; +constexpr s32 kRewardJiggy = 3; +constexpr s32 kCameraMotor = 1; +constexpr s32 kLeaveHutText = 0xA7E; +constexpr s32 kLeaveHutFlags = 0x02; + +f32 sJiggyPos[3] = { 0.0f, 500.0f, -95.0f }; +f32 sMumboState = 0.0f; +bool sMumboRewardEnabled = false; +bool sLeaveHutPending = false; + +void MumboReward_spawnJiggy() { + jiggy_spawn((enum jiggy_e)kRewardJiggy, sJiggyPos); + func_802BB3DC(kCameraMotor, 3.0f, 1.0f); + timedFunc_set_1(kCameraReleaseDelay, (GenFunction_1)func_802BB41C, kCameraMotor); +} + +void MumboReward_setState() { + sMumboState = kStateValue; +} +} // namespace + +extern "C" s32 romhack_mumboTransform(s32 transformId) { + if (!sMumboRewardEnabled || gsworld_getMap() != MAP_48_FP_MUMBOS_SKULL) { + return player_transform((enum transformation_e)transformId); + } + timedFunc_set_0(kJiggyDelay, MumboReward_spawnJiggy); + timedFunc_set_0(kStateDelay, MumboReward_setState); + sLeaveHutPending = true; + return 1; +} + +extern "C" s32 romhack_mumboWishwashyId(void) { + return sMumboRewardEnabled ? 9 : TRANSFORM_7_WISHWASHY; +} + +extern "C" s32 romhack_mumboRandomEventsAllowed(void) { + return sMumboRewardEnabled ? 0 : 1; +} + +// Mumbo's reward shows a static camera +namespace { +constexpr f32 kPanPosition[3] = { -250.0f, 194.0f, 147.0f }; +constexpr f32 kPanRotation[3] = { 35.0f, 315.0f, 0.0f }; + +bool sPanSaved = false; +f32 sPanSavedPosition[3]; +f32 sPanSavedRotation[3]; + +void MumboReward_updatePendingDialog() { + if (!sLeaveHutPending) { + return; + } + const s32 state = bs_getState(); + if (state == BS_74_UNKNOWN || state == BS_20_LANDING || state == BS_44_JIG_JIGGY) { + return; + } + gcdialog_showDialog(kLeaveHutText, kLeaveHutFlags, NULL, NULL, NULL, NULL); + sLeaveHutPending = false; +} + +void MumboReward_updateCamera() { + if (!sMumboRewardEnabled) { + return; + } + MumboReward_updatePendingDialog(); + if (sMumboState > 0.0f) { + if (!sPanSaved) { + sPanSaved = true; + for (int i = 0; i < 3; i++) { + sPanSavedPosition[i] = cameraPosition[i]; + sPanSavedRotation[i] = cameraRotation[i]; + } + } + for (int i = 0; i < 3; i++) { + cameraPosition[i] = kPanPosition[i]; + cameraRotation[i] = kPanRotation[i]; + D_8037D948[i] = kPanPosition[i]; + D_8037D9C8[i] = 0.0f; + D_8037D9E0[i] = 0.0f; + } + D_8037D9D4 = 0.0f; + D_8037D9D8 = 0.0f; + D_8037D9EC = 0.0f; + D_8037D9F0 = 0.0f; + + sMumboState -= time_getDelta(); + if (sMumboState == 0.0f) { + sMumboState = -1.0f; // sentinel: expired, restore next frame + } + } else if (sMumboState < 0.0f && sPanSaved) { + for (int i = 0; i < 3; i++) { + cameraPosition[i] = sPanSavedPosition[i]; + cameraRotation[i] = sPanSavedRotation[i]; + } + sPanSaved = false; + sMumboState = 0.0f; + } +} +} // namespace + +static void Gruntch_EnableMumboReward() { + sMumboRewardEnabled = true; + REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent*) { MumboReward_updateCamera(); }); +} + +// Game-Over respawns +static void Gruntch_EnableVoidOutRespawn() { + REGISTER_VB_SHOULD(VB_VOID_OUT_RESPAWN_TRANSITION, EVENT_PRIORITY_NORMAL, { + s32 map = va_arg(args, s32); + s32 exit = va_arg(args, s32); + if (D_80383300.level == 1) { + map = MAP_28_MMM_EGG_ROOM; + exit = 2; + } else if (D_80383300.level == 0xA) { + map = MAP_6C_GL_RED_CAULDRON_ROOM; + exit = 5; + } + transitionToMap((enum map_e)map, exit, 1); + *should = false; + }); +} + +// Firing an egg spikes the stealth meter +static void Gruntch_EnableEggNoise() { + REGISTER_VB_SHOULD(VB_EGG_FIRE_SFX, EVENT_PRIORITY_NORMAL, { + s32 slot = va_arg(args, s32); + s32* rate = va_arg(args, s32*); + switch (slot) { + case 0: + StealthNoise_AddBurst(0.3f, 0.2f); + break; + case 1: + StealthNoise_AddBurst(0.65f, 0.3f); + *rate = 0x6D60; + break; + case 2: + StealthNoise_AddBurst(0.65f, 0.4f); + break; + default: + break; + } + (void)should; + }); +} + +// Lair music persists through various maps +constexpr s32 kMusicGroupLair[] = { 0x6A, 0x6C, 0x6F, 0x71, 0x6B, 0x15 }; +constexpr s32 kMusicGroupVillage[] = { 0x1B, 0x22, 0x0C }; + +static bool SameMusicGroup(const s32* group, int count, s32 a, s32 b) { + bool hasA = false, hasB = false; + for (int i = 0; i < count; i++) { + hasA = hasA || group[i] == a; + hasB = hasB || group[i] == b; + } + return hasA && hasB; +} + +// Banjo & Kazooie don't rebound when hitting windows with Rat-A-Tap Rap +static void Gruntch_EnableWindowRapNoRebound() { + REGISTER_VB_SHOULD(VB_BUMP_REBOUNDS_PLAYER, EVENT_PRIORITY_NORMAL, { + ActorMarker* marker = va_arg(args, ActorMarker*); + if (marker != NULL && marker->id == MARKER_107_ENGINE_ROOM_DOOR) { + *should = false; + } + }); +} + +static void Gruntch_EnableWarpMusic() { + REGISTER_VB_SHOULD(VB_WARP_KEEPS_MUSIC, EVENT_PRIORITY_NORMAL, { + const s32 dest = va_arg(args, s32); + const s32 cur = gsworld_getMap(); + if (SameMusicGroup(kMusicGroupVillage, ARRAY_COUNT(kMusicGroupVillage), cur, dest) || + SameMusicGroup(kMusicGroupLair, ARRAY_COUNT(kMusicGroupLair), cur, dest)) { + musicKeepsPlaying(); + } + (void)should; + }); +} + +// ------------------------------------------------------- Jiggy consolidation +constexpr s32 kJiggyToMM[] = { 0x14, 0x20, 0x2E, 0x4A }; +constexpr s32 kJiggyToMMM[] = { 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3E }; + +static bool JiggyMovedFromVanillaLevel(s32 id) { + for (s32 m : kJiggyToMM) { + if (m == id) { + return true; + } + } + for (s32 m : kJiggyToMMM) { + if (m == id) { + return true; + } + } + return false; +} + +// Pause-menu totals layout for Gruntch and Santa's Village +static void Gruntch_EnablePauseTotalsLayout() { + static const s16 kRowY[4] = { 46, 85, -100, 122 }; + static const s8 kScrollStep[4] = { 2, 2, 3, 3 }; + for (int i = 0; i < 4; i++) { + D_8036C520[i].y = kRowY[i]; + D_8036C5F4[i] = kScrollStep[i]; + } +} + +static void Gruntch_EnableJiggyTally() { + REGISTER_VB_SHOULD(VB_JIGGYSCORE_LEVEL_TOTAL, EVENT_PRIORITY_NORMAL, { + s32 lvl = va_arg(args, s32); + s32* result = va_arg(args, s32*); + s32 cnt = 0; + if (lvl >= 1 && lvl <= 0xA) { + for (s32 id = (lvl - 1) * 10 + 1; id <= lvl * 10; id++) { + if (!JiggyMovedFromVanillaLevel(id) && jiggyscore_isCollected((enum jiggy_e)id)) { + cnt++; + } + } + if (lvl == 1) { + for (s32 id : kJiggyToMM) { + if (jiggyscore_isCollected((enum jiggy_e)id)) { + cnt++; + } + } + } else if (lvl == 0xA) { + for (s32 id : kJiggyToMMM) { + if (jiggyscore_isCollected((enum jiggy_e)id)) { + cnt++; + } + } + } + } + *result = cnt; + *should = false; + }); + + // Hide Mt Grumpit's notes and jiggies + REGISTER_VB_SHOULD(VB_PAUSEMENU_ROW_VISIBLE, EVENT_PRIORITY_NORMAL, { + s32 lvl = va_arg(args, s32); + s32 row = va_arg(args, s32); + if (lvl == LEVEL_2_TREASURE_TROVE_COVE) { + *should = (row != 0 && row != 1); + } + }); +} + +// The second act stays locked until the RBB level-open flag is set +static void Gruntch_EnableActGate() { + REGISTER_VB_SHOULD(VB_WARP_DISPATCH, EVENT_PRIORITY_NORMAL, { + if (va_arg(args, int) == 0xAA && !fileProgressFlag_get(FILEPROG_38_RBB_OPEN)) { + *should = false; + } + }); +} + +// ------------------------------------------------------------ Stealth section +extern "C" void warp_rbbExitBoomBoxContainer(NodeProp*, ActorMarker*); + +constexpr s32 kWarpRbbExitBoomBoxContainer = 182; + +constexpr StealthNoiseConfig kGruntchStealth = { + MAP_3C_RBB_KITCHEN, -500.0f, 3600.0f, 0.0f, 3100.0f, 0xA7B, kWarpRbbExitBoomBoxContainer, + warp_rbbExitBoomBoxContainer, 0x13, +}; + +// ------------------------------------------------------- Patch registration +void RegisterGruntchPatches() { + TooieJiggyDance_ForceEnable(); + Storybook_Enable(kGruntchStorybook); + ProximityDialogs_Enable(kGruntchGameplayDialogs); + StealthNoise_Enable(kGruntchStealth); + Gruntch_EnableActGate(); + Gruntch_EnableConditionalActors(); + Gruntch_EnableMumboReward(); + Gruntch_EnableVoidOutRespawn(); + Gruntch_EnableEggNoise(); + Gruntch_EnableWarpMusic(); + Gruntch_EnableWindowRapNoRebound(); + Gruntch_EnablePauseTotalsLayout(); + Gruntch_EnableJiggyTally(); + HackShared_EnableDialogSuppression(kGruntchSuppressedDialogs); + HackShared_EnableForceAbilitiesUsed(kAllUsedAbilities); +} diff --git a/src/port/Save/SaveConverter.cpp b/src/port/Save/SaveConverter.cpp index 116ab6077..6860a878a 100644 --- a/src/port/Save/SaveConverter.cpp +++ b/src/port/Save/SaveConverter.cpp @@ -6,7 +6,7 @@ #include #include -#include "portable-file-dialogs.h" +#include "port/FilePicker.h" #include #include #include @@ -227,23 +227,44 @@ Result ExportToRecompBin(const std::string& dstPath, int slot) { return res; } -Result PickAndImport(int slot) { - // We can't predict the file extension a save will come in, and we already validate later in the chain - // Trust the user to pick the correct file - auto selection = pfd::open_file("Select a save to import", ".", { "All Files", "*" }).result(); - if (selection.empty()) { - return {}; - } - return ImportFromRawEeprom(selection[0], slot); +void PickAndImport(int slot, std::function onComplete) { + // We can't predict the file extension a save will come in, and we already validate later in the + // chain, so trust the user to pick the correct file. + Ship::FileBrowserRequest req; + req.Title = "Select a save to import"; + req.Filters = { { "All Files", { "*" } } }; + Lighthouse::PickFile(std::move(req), [slot, onComplete](std::optional path) { + if (!path) { + if (onComplete) { + onComplete({}); // cancelled + } + return; + } + Result r = ImportFromRawEeprom(path->string(), slot); + if (onComplete) { + onComplete(r); + } + }); } -Result PickAndExport(int slot) { - auto dest = pfd::save_file("Export save", "bk.n64.us.1.0.bin", { "Save files (*.bin)", "*.bin", "All Files", "*" }) - .result(); - if (dest.empty()) { - return {}; - } - return ExportToRecompBin(dest, slot); +void PickAndExport(int slot, std::function onComplete) { + Ship::FileBrowserRequest req; + req.Title = "Export save"; + req.Save = true; + req.DefaultName = "bk.n64.us.1.0.bin"; + req.Filters = { { "Save files (*.bin)", { "*.bin" } }, { "All Files", { "*" } } }; + Lighthouse::PickFile(std::move(req), [slot, onComplete](std::optional path) { + if (!path) { + if (onComplete) { + onComplete({}); // cancelled + } + return; + } + Result r = ExportToRecompBin(path->string(), slot); + if (onComplete) { + onComplete(r); + } + }); } } // namespace SaveConverter diff --git a/src/port/Save/SaveConverter.h b/src/port/Save/SaveConverter.h index 073458320..e51b78d7e 100644 --- a/src/port/Save/SaveConverter.h +++ b/src/port/Save/SaveConverter.h @@ -1,6 +1,7 @@ #ifndef SAVE_CONVERTER_H #define SAVE_CONVERTER_H +#include #include namespace SaveConverter { @@ -15,8 +16,11 @@ struct Result { Result ImportFromRawEeprom(const std::string& srcPath, int slot = kSlotAll); Result ExportToRecompBin(const std::string& dstPath, int slot = kSlotAll); -Result PickAndImport(int slot = kSlotAll); -Result PickAndExport(int slot = kSlotAll); + +// Open the file picker, then import/export on the chosen path. onComplete runs when done; an empty +// Result.message means the user cancelled. +void PickAndImport(int slot, std::function onComplete); +void PickAndExport(int slot, std::function onComplete); } // namespace SaveConverter diff --git a/src/port/Save/SaveManager.cpp b/src/port/Save/SaveManager.cpp index 9adfc1394..219c2cf69 100644 --- a/src/port/Save/SaveManager.cpp +++ b/src/port/Save/SaveManager.cpp @@ -16,13 +16,13 @@ #include "Types.h" #include "port/Rando/Logic/Logic.h" +#include "port/Romhack/RomhackConfig.h" extern "C" { #include "core1/sns.h" extern SaveData gameFile_saveData[4]; -void savedata_update_crc(void* buffer, s32 size); -s32 item_getCount(enum item_e item); +extern s8 gameFile_GameIdToFileIdMap[4]; extern u8 gCompletedBottlesBonusGames[7]; } @@ -73,10 +73,75 @@ static void BitfieldSetNBits(uint8_t* array, int startIndex, int numBits, int va } } +struct ResolvedFlag { + int index; + int width; + int puzzle; +}; + +static int PuzzleIndexForFlag(const FlagDef& f) { + static const char* const kPuzzleFlagNames[] = { + "MM_PUZZLE_PIECES_PLACED", + "TTC_PUZZLE_PIECES_PLACED", + "CC_PUZZLE_PIECES_PLACED", + "BGS_PUZZLE_PIECES_PLACED", + "FP_PUZZLE_PIECES_PLACED", + "GV_PUZZLE_PIECES_PLACED", + "MMM_PUZZLE_PIECES_PLACED", + "RBB_PUZZLE_PIECES_PLACED", + "CCW_PUZZLE_PIECES_PLACED", + "DOG_PUZZLE_PIECES_PLACED", + "DOUBLE_HEALTH_PUZZLE_PIECES_PLACED", + }; + if (f.name != nullptr) { + for (int i = 0; i < 11; i++) { + if (strcmp(f.name, kPuzzleFlagNames[i]) == 0) { + return i; + } + } + } + return -1; +} + +static ResolvedFlag ResolveFlag(const FlagDef& f) { + const int puzzle = PuzzleIndexForFlag(f); + if (puzzle < 0) { + return { f.bitIndex, f.bitWidth, -1 }; + } + + const int index = port_getRomhackJiggyPuzzleFlag(puzzle); + const int width = port_getRomhackJiggyPuzzleSize(puzzle); + if (index < 0 || width < 0) { + return { f.bitIndex, f.bitWidth, puzzle }; // no override, vanilla placement + } + // A malformed override would put the counter on top of unrelated progress flags. + // The vanilla counters tile 0x5D-0x81 exactly, and 0x82 is the next flag along. + if (width == 0 || index < 0x5D || index + width - 1 > 0x81) { + SPDLOG_WARN("[SaveManager] {} declares an out-of-range puzzle layout (offset {:#x}, {} bits); " + "falling back to the vanilla placement", + f.name, index, width); + return { f.bitIndex, f.bitWidth, puzzle }; + } + return { index, width, puzzle }; +} + +// A picture's cost can shrink when a romhack ships a revised aGameConfig, which leaves an +// existing save reporting more pieces placed than the picture now has slots. The podium +// picks its occupied slots by rejection sampling, which never terminates once every slot +// is taken, so pin the counter to what the current table can represent on the way in. +static uint32_t ClampPuzzleCount(int puzzle, uint32_t value, const char* name) { + const int cost = _puzzleCost(puzzle); + if (cost >= 0 && value > static_cast(cost)) { + SPDLOG_WARN("[SaveManager] {} is {} but the picture only has {} slots; clamping", name, value, cost); + return static_cast(cost); + } + return value; +} + void RandoSaveCheck_to_json(nlohmann::json& j, const RandoSaveCheck& randoSaveCheck) { j = nlohmann::json::array({ randoSaveCheck.randoCheckId, randoSaveCheck.randoItemId, - randoSaveCheck.randoCollectionId, randoSaveCheck.isShuffled, randoSaveCheck.obtained, - randoSaveCheck.skipped }); + randoSaveCheck.randoCollectionId, randoSaveCheck.isShuffled, randoSaveCheck.eligible, + randoSaveCheck.received, randoSaveCheck.skipped }); } RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& randoSaveCheck) { @@ -84,8 +149,9 @@ RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& j.at(1).get_to(randoSaveCheck.randoItemId); j.at(2).get_to(randoSaveCheck.randoCollectionId); j.at(3).get_to(randoSaveCheck.isShuffled); - j.at(4).get_to(randoSaveCheck.obtained); - j.at(5).get_to(randoSaveCheck.skipped); + j.at(4).get_to(randoSaveCheck.eligible); + j.at(5).get_to(randoSaveCheck.received); + j.at(6).get_to(randoSaveCheck.skipped); return randoSaveCheck; } @@ -161,10 +227,11 @@ ordered_json Convert_SaveDataToJSON(SaveData* saveData, int32_t fileNum) { if (f.world != nullptr) { continue; } - if (f.bitWidth == 1) { - general[f.name] = BitfieldGetBit(progressFlags, f.bitIndex); + const ResolvedFlag r = ResolveFlag(f); + if (r.width == 1) { + general[f.name] = BitfieldGetBit(progressFlags, r.index); } else { - general[f.name] = BitfieldGetNBits(progressFlags, f.bitIndex, f.bitWidth); + general[f.name] = BitfieldGetNBits(progressFlags, r.index, r.width); } } j["progress"] = general; @@ -176,10 +243,11 @@ ordered_json Convert_SaveDataToJSON(SaveData* saveData, int32_t fileNum) { if (f.world == nullptr || strcmp(f.world, "CHEATS") != 0) { continue; } - if (f.bitWidth == 1) { - cheats[f.name] = BitfieldGetBit(progressFlags, f.bitIndex); + const ResolvedFlag r = ResolveFlag(f); + if (r.width == 1) { + cheats[f.name] = BitfieldGetBit(progressFlags, r.index); } else { - cheats[f.name] = BitfieldGetNBits(progressFlags, f.bitIndex, f.bitWidth); + cheats[f.name] = BitfieldGetNBits(progressFlags, r.index, r.width); } } j["cheats"] = cheats; @@ -264,10 +332,11 @@ ordered_json Convert_SaveDataToJSON(SaveData* saveData, int32_t fileNum) { if (f.world == nullptr || strcmp(f.world, wd.name) != 0) { continue; } - if (f.bitWidth == 1) { - worldProgress[f.name] = BitfieldGetBit(progressFlags, f.bitIndex); + const ResolvedFlag r = ResolveFlag(f); + if (r.width == 1) { + worldProgress[f.name] = BitfieldGetBit(progressFlags, r.index); } else { - worldProgress[f.name] = BitfieldGetNBits(progressFlags, f.bitIndex, f.bitWidth); + worldProgress[f.name] = BitfieldGetNBits(progressFlags, r.index, r.width); } } if (!worldProgress.empty()) { @@ -418,11 +487,15 @@ SaveData* Convert_JSONToSaveData(int32_t fileNum) { if (generalProgress.contains(f.name)) { uint32_t value = generalProgress[f.name].get(); + const ResolvedFlag r = ResolveFlag(f); + if (r.puzzle >= 0) { + value = ClampPuzzleCount(r.puzzle, value, f.name); + } - if (f.bitWidth == 1) { - BitfieldSetBit(progressFlags, f.bitIndex, value != 0); + if (r.width == 1) { + BitfieldSetBit(progressFlags, r.index, value != 0); } else { - BitfieldSetNBits(progressFlags, f.bitIndex, f.bitWidth, value); + BitfieldSetNBits(progressFlags, r.index, r.width, value); } } } @@ -439,13 +512,14 @@ SaveData* Convert_JSONToSaveData(int32_t fileNum) { if (cheats.contains(f.name)) { uint32_t value = cheats[f.name].get(); + const ResolvedFlag r = ResolveFlag(f); - if (f.bitWidth == 1) { + if (r.width == 1) { // Set single bit (0 or 1) - BitfieldSetBit(progressFlags, f.bitIndex, value != 0); + BitfieldSetBit(progressFlags, r.index, value != 0); } else { // Set multiple bits for specific cheat values - BitfieldSetNBits(progressFlags, f.bitIndex, f.bitWidth, value); + BitfieldSetNBits(progressFlags, r.index, r.width, value); } } } @@ -533,10 +607,14 @@ SaveData* Convert_JSONToSaveData(int32_t fileNum) { if (f.world != nullptr && strcmp(f.world, wd.name) == 0) { if (src.contains(f.name)) { uint32_t val = src[f.name].get(); - if (f.bitWidth == 1) - BitfieldSetBit(progressFlags, f.bitIndex, val != 0); + const ResolvedFlag r = ResolveFlag(f); + if (r.puzzle >= 0) { + val = ClampPuzzleCount(r.puzzle, val, f.name); + } + if (r.width == 1) + BitfieldSetBit(progressFlags, r.index, val != 0); else - BitfieldSetNBits(progressFlags, f.bitIndex, f.bitWidth, val); + BitfieldSetNBits(progressFlags, r.index, r.width, val); } } } @@ -666,6 +744,34 @@ static void LoadGlobalData() { } } +static bool WriteFileAtomically(const std::filesystem::path& path, const std::string& contents) { + const std::filesystem::path tempPath = path.parent_path() / (path.filename().string() + ".tmp"); + std::error_code ec; + { + std::ofstream ofs(tempPath, std::ios::binary | std::ios::trunc); + if (!ofs.is_open()) { + SPDLOG_ERROR("SaveManager: failed to open \"{}\" for writing", tempPath.string()); + return false; + } + ofs << contents; + ofs.flush(); + if (!ofs.good()) { + SPDLOG_ERROR("SaveManager: failed writing \"{}\"; leaving the existing file alone", tempPath.string()); + ofs.close(); + std::filesystem::remove(tempPath, ec); + return false; + } + } + std::filesystem::rename(tempPath, path, ec); + if (ec) { + SPDLOG_ERROR("SaveManager: failed to replace \"{}\": {}", path.string(), ec.message()); + std::error_code removeEc; + std::filesystem::remove(tempPath, removeEc); + return false; + } + return true; +} + static void SaveGlobalData() { ordered_json j = ordered_json::object(); @@ -687,13 +793,7 @@ static void SaveGlobalData() { j["bottlesBonusCompleted"] = bb; std::string globalPath = SaveManager_GetSavePath("global.json"); - std::ofstream ofs(globalPath); - if (ofs.is_open()) { - ofs << CollapsedJSONArray(j); - ofs.close(); - } else { - SPDLOG_ERROR("SaveManager: failed to open global save file \"{}\" for writing", globalPath); - } + WriteFileAtomically(globalPath, CollapsedJSONArray(j)); } void SaveManager_MoveInvalidSaveFile(const std::filesystem::path& fileName, const std::string& message) { @@ -748,26 +848,44 @@ void SaveManager_Init() { REGISTER_LISTENER(OnSaveFileSave, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnSaveFileSave* ev = (OnSaveFileSave*)event; - ordered_json saveFile = Convert_SaveDataToJSON((SaveData*)ev->saveBuffer, ev->fileNum); - if (!saveFile.empty()) { - std::string collapsedString = CollapsedJSONArray(saveFile); - - std::string fileName = createFileName(ev->fileNum); - std::string filePath = SaveManager_GetSavePath(fileName); + std::string fileName = createFileName(ev->fileNum); + std::string filePath = SaveManager_GetSavePath(fileName); - std::ofstream outputFile(filePath); - if (outputFile.is_open()) { - outputFile << collapsedString; - outputFile.close(); - } else { - SPDLOG_ERROR("SaveManager: failed to open save file \"{}\" for writing", filePath); + if (((SaveData*)ev->saveBuffer)->magic == 0) { + std::error_code ec; + fs::remove(filePath, ec); + if (ec) { + SPDLOG_ERROR("SaveManager: failed to remove erased save file \"{}\": {}", filePath, ec.message()); } + SaveGlobalData(); + event->Cancelled = true; + return; + } + + ordered_json saveFile = Convert_SaveDataToJSON((SaveData*)ev->saveBuffer, ev->fileNum); + if (!saveFile.empty()) { + WriteFileAtomically(filePath, CollapsedJSONArray(saveFile)); } SaveGlobalData(); event->Cancelled = true; }); + REGISTER_LISTENER(OnGameErase, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnGameErase* ev = (OnGameErase*)event; + std::string fileName = createFileName(ev->gameNum); + std::error_code ec; + if (fs::remove(SaveManager_GetSavePath(fileName), ec)) { + SPDLOG_INFO("SaveManager: deleted erased save file \"{}\"", fileName); + } else if (ec) { + SPDLOG_ERROR("SaveManager: failed to delete erased save file \"{}\": {}", fileName, ec.message()); + } + // Drop retention data too. + if (ev->gameNum >= 0 && ev->gameNum < 4) { + gameFile_saveData[gameFile_GameIdToFileIdMap[ev->gameNum]].shipSaveData = {}; + } + }); + REGISTER_LISTENER(OnSaveClear, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnSaveClear* ev = (OnSaveClear*)event; SaveData* saveData = (SaveData*)ev->result; @@ -786,6 +904,11 @@ void SaveManager_Init() { event->Cancelled = true; }); + REGISTER_LISTENER(OnGameFileErase, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnGameFileErase* ev = (OnGameFileErase*)event; + gameFile_8033CFD4(ev->gamenum); + }); + REGISTER_LISTENER(OnGameLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnGameLoad* ev = (OnGameLoad*)event; gSelectedFileNum = ev->fileNum; diff --git a/src/port/Save/Types.h b/src/port/Save/Types.h index 49a1aa2f9..d5bede421 100644 --- a/src/port/Save/Types.h +++ b/src/port/Save/Types.h @@ -417,6 +417,9 @@ static constexpr int kSnsItemCount = sizeof(kSnsUnlocked) / sizeof(kSnsUnlocked[ // so internal gamenum 0/1/2 corresponds to displayed Game 1/3/2. static int SlotToFileIndex(int gameNum) { static const int fileMap[3] = { 1, 3, 2 }; + if (gameNum < 0 || gameNum >= 3) { + return 0; + } return fileMap[gameNum]; } diff --git a/src/port/ShipUtils.cpp b/src/port/ShipUtils.cpp index 087f900dd..8381950f8 100644 --- a/src/port/ShipUtils.cpp +++ b/src/port/ShipUtils.cpp @@ -10,6 +10,7 @@ #include #include #include "UI/cvar_prefixes.h" +#include "UI/enhancementTypes.h" #include "fast/Fast3dGui.h" #ifdef _WIN32 #include @@ -61,7 +62,7 @@ extern uint32_t Ship_Hash(std::string str) { return hval; } -extern std::string port_FormatTimeDisplay(uint32_t value) { +extern std::string port_FormatTimeDisplay(uint64_t value) { uint32_t sec = value / 10; uint32_t hh = sec / 3600; uint32_t mm = (sec - hh * 3600) / 60; @@ -74,7 +75,6 @@ extern "C" { #include "enums.h" // game_mode_e // Furnace Fun active flag -s32 volatileFlag_get(s32); s32 getGameMode(void); int gPortResetPending = 0; @@ -95,10 +95,6 @@ bool Ship_IsCStringEmpty(const char* str) { return str == NULL || str[0] == '\0'; } -void port_audioStartThread(void) { - GameEngine::AudioStartThread(); -} - int port_checkHeap(const char* label) { #if defined(_DEBUG) && defined(_MSC_VER) if (!_CrtCheckMemory()) { @@ -296,8 +292,8 @@ int port_getBootSequence(void) { // Romhacks always boot to file select; their intros aren't compatible with the // vanilla cutscene/demo path. if (port_isRomhack()) - return 2; // BOOTSEQUENCE_FILESELECT - return CVarGetInteger(CVAR_SETTING("BootSequence"), 0); + return BOOTSEQUENCE_FILESELECT; + return CVarGetInteger(CVAR_SETTING("BootSequence"), BOOTSEQUENCE_DEFAULT); } float port_getRumbleScale(void) { @@ -323,9 +319,8 @@ float port_getRumbleScale(void) { } // extern "C" std::vector worldOpenFlags = { - FILEPROG_5D_MM_PUZZLE_PIECES_PLACED, FILEPROG_5E_TTC_PUZZLE_PIECES_PLACED, FILEPROG_60_CC_PUZZLE_PIECES_PLACED, - FILEPROG_63_BGS_PUZZLE_PIECES_PLACED, FILEPROG_66_FP_PUZZLE_PIECES_PLACED, FILEPROG_6A_GV_PUZZLE_PIECES_PLACED, - FILEPROG_6E_MMM_PUZZLE_PIECES_PLACED, FILEPROG_72_RBB_PUZZLE_PIECES_PLACED, FILEPROG_76_CCW_PUZZLE_PIECES_PLACED, + FILEPROG_31_MM_OPEN, FILEPROG_32_TTC_OPEN, FILEPROG_33_CC_OPEN, FILEPROG_34_BGS_OPEN, FILEPROG_35_FP_OPEN, + FILEPROG_36_GV_OPEN, FILEPROG_37_MMM_OPEN, FILEPROG_38_RBB_OPEN, FILEPROG_39_CCW_OPEN, }; std::unordered_map levelAbbreviations = { diff --git a/src/port/ShipUtils.h b/src/port/ShipUtils.h index f4a2f2fe3..90766d680 100644 --- a/src/port/ShipUtils.h +++ b/src/port/ShipUtils.h @@ -20,7 +20,7 @@ extern std::vector abilityNameList; void TableCellCenteredText(const char* text); uint32_t Ship_Hash(std::string str); -std::string port_FormatTimeDisplay(uint32_t value); +std::string port_FormatTimeDisplay(uint64_t value); extern "C" { #endif @@ -34,9 +34,6 @@ void BK_LOG_INFO(const char* fmt, ...); void BK_LOG_WARN(const char* fmt, ...); void BK_LOG_ERROR(const char* fmt, ...); -// Start the audio processing thread (called from audioManager_startThread after soundfont patching) -void port_audioStartThread(void); - // Flag: when true, audio spin-waits should force-stop immediately. extern int gPortResetPending; diff --git a/src/port/UI/DeveloperTools/GameplayTools.cpp b/src/port/UI/DeveloperTools/GameplayTools.cpp index 11f703de2..427eedbb0 100644 --- a/src/port/UI/DeveloperTools/GameplayTools.cpp +++ b/src/port/UI/DeveloperTools/GameplayTools.cpp @@ -2,6 +2,7 @@ #include "port/Rando/Rando.h" #include "port/Rando/Logic/Logic.h" #include "port/Rando/CustomObject/CustomObject.h" +#include "port/Rando/CustomCollectible/CustomCollectible.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/UI/UIWidgets.hpp" @@ -20,23 +21,6 @@ #include "include/core1/sns.h" extern "C" { -void sns_set_item_state(enum StopNSwop_Item item, s32 set, s32 state); -void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]); -void player_getPosition(f32 dst[3]); -void player_getPosition_s32(s32 arg0[3]); -enum map_e gsworld_getMap(void); -Actor* actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags); -void func_8031D04C(enum map_e arg0, s32 exit_id); - -void item_set(s32 item, s32 val); -void ability_setAllLearned(s32 val); -void ability_setAllUsed(s32 val); - -s32 mapSpecificFlags_get(s32 i); -void mapSpecificFlags_set(s32 i, s32 val); -enum map_e gsworld_getMap(void); -enum level_e map_getLevel(enum map_e map); - typedef struct { enum honeycomb_e uid; s32 unk4; @@ -69,6 +53,7 @@ int32_t selectedSnsItem = SNS_ITEM_EGG_YELLOW; int32_t selectedJiggy = JIGGY_01_MM_JINJO; int32_t selectedHoneycomb = HONEYCOMB_1_MM_HILL; int32_t selectedToken = MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA; +int32_t selectedCustomCollectible = RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1; const char* mapNames[] = { "Mumbo's Mountain", "Treasure Trove Cove", "Clanker's Cavern", "Bubblegloop Swamp", "Freezeezy Peak", @@ -164,17 +149,17 @@ std::vector mapSpecificFlagList = { { TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN, "TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN", LEVEL_2_TREASURE_TROVE_COVE }, { TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN, "TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN", LEVEL_2_TREASURE_TROVE_COVE }, { BGS_SPECIFIC_FLAG_1, "BGS_SPECIFIC_FLAG_1", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_RESET, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET, "BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY, "BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, { BGS_SPECIFIC_FLAG_7, "BGS_SPECIFIC_FLAG_7", LEVEL_4_BUBBLEGLOOP_SWAMP }, { BGS_SPECIFIC_FLAG_8, "BGS_SPECIFIC_FLAG_8", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_MAZE_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_MAZE_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, { BGS_SPECIFIC_FLAG_A, "BGS_SPECIFIC_FLAG_A", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_MAZE_JIGGY_RESET, "BGS_SPECIFIC_FLAG_MAZE_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_MAZE_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_MAZE_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_MAZE_JIGGY, "BGS_SPECIFIC_FLAG_MAZE_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET, "BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_D_MAZE_JIGGY, "BGS_SPECIFIC_FLAG_D_MAZE_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, { FP_SPECIFIC_FLAG_0_XMAS_TREE_LIGHTS_ON, "FP_SPECIFIC_FLAG_0_XMAS_TREE_LIGHTS_ON", LEVEL_5_FREEZEEZY_PEAK }, { FP_SPECIFIC_FLAG_1_UNKNOWN, "FP_SPECIFIC_FLAG_1_UNKNOWN", LEVEL_5_FREEZEEZY_PEAK }, { FP_SPECIFIC_FLAG_2_XMAS_TREE_SWITCH, "FP_SPECIFIC_FLAG_2_XMAS_TREE_SWITCH", LEVEL_5_FREEZEEZY_PEAK }, @@ -238,7 +223,7 @@ void GameplayTools_UpdateSnsCheckboxes(StopNSwop_Item selectedSnsId) { } void GameplayTools_SpawnPosition() { - for (int i = 0; i < 2; i++) { + for (int i = 0; i <= 2; i++) { spawnPosition[i] = playerPosition[i] + spawnOffset[i]; } } @@ -420,6 +405,27 @@ void GameplayTools_ObjectSpawner() { ImGui::EndTable(); } + + ImGui::SeparatorText("Custom Collectible Testing"); + if (ImGui::BeginTable("ObjectSpawner", 2, ImGuiTableFlags_SizingStretchSame)) { + ImGui::TableNextColumn(); + if (UIWidgets::Button("Spawn Custom Collectible", { .color = THEME_COLOR })) { + Actor* newActor = CustomCollectible::Spawn(spawnPosition, (RandoCheckId)selectedCustomCollectible); + } + ImGui::TableNextColumn(); + std::string customCollectibleText = std::to_string(selectedCustomCollectible) + ": " + + Rando::StaticData::Checks[(RandoCheckId)selectedCustomCollectible].name; + + UIWidgets::SliderInt("##customCollectibleIndex", &selectedCustomCollectible, + UIWidgets::IntSliderOptions() + .Color(THEME_COLOR) + .Min(RC_UNKNOWN + 1) + .Max(RC_MAX - 1) + .DefaultValue(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1) + .Format(customCollectibleText.c_str()) + .LabelPosition(UIWidgets::LabelPositions::None)); + ImGui::EndTable(); + } } void DrawGameplayToolsWarpList() { @@ -470,10 +476,42 @@ void DrawGrantUnlocks() { } } +// Index 0 traces every space; the rest are ANCHOR_FLAGSPACE_* ids offset by one. +static const std::unordered_map flagTraceSpaces = { + { 0, "All" }, { 1, "File Progress" }, { 2, "Volatile" }, { 3, "Level Specific" }, + { 4, "Map Specific" }, { 5, "Rando Inf" }, +}; + +void DrawFlagTracer() { + ImGui::SeparatorText("Flag Tracer"); + ImGui::TextWrapped("Logs every flag write to the console and log file, with the flag's enum name and a marker on " + "each map load."); + + UIWidgets::CVarCheckbox("Trace Flag Writes", CVAR_DEVELOPER_TOOLS("FlagTrace"), + UIWidgets::CheckboxOptions().Color(THEME_COLOR).DefaultValue(false)); + + if (!CVarGetInteger(CVAR_DEVELOPER_TOOLS("FlagTrace"), 0)) { + return; + } + + UIWidgets::CVarCombobox("Flag Space", CVAR_DEVELOPER_TOOLS("FlagTraceSpace"), flagTraceSpaces, + UIWidgets::ComboboxOptions() + .Color(THEME_COLOR) + .Tooltip("Limit tracing to a single flag space.") + .DefaultIndex(0)); + UIWidgets::CVarCheckbox("Include Call Stacks", CVAR_DEVELOPER_TOOLS("FlagTraceStacks"), + UIWidgets::CheckboxOptions() + .Color(THEME_COLOR) + .DefaultValue(false) + .Tooltip("Name the function and line that set each flag.")); +} + void DrawMonitoringTools() { level_e currentLevel = map_getLevel(gsworld_getMap()); int32_t mapIndex = 0; + DrawFlagTracer(); + ImGui::SeparatorText("Map Specific Flags"); if (ImGui::BeginChild("MapFlagChild")) { if (ImGui::BeginTable("MapFlagTable", 2, ImGuiTableFlags_SizingFixedFit)) { diff --git a/src/port/UI/DeveloperTools/SaveEditor.cpp b/src/port/UI/DeveloperTools/SaveEditor.cpp index d93c46eba..3b079579f 100644 --- a/src/port/UI/DeveloperTools/SaveEditor.cpp +++ b/src/port/UI/DeveloperTools/SaveEditor.cpp @@ -13,10 +13,8 @@ #include "port/UI/LighthouseGui.hpp" #include "port/UI/cvar_prefixes.h" -extern "C" { #include "enums.h" #include "prop.h" -} #define DEFAULT_MAX_HEALTH 8 #define DEFAULT_MAX_EGGS 100 @@ -27,16 +25,8 @@ extern "C" { #define HONEYCOMB_ID_MULTIPLIER(levelId) (1 + (2 * (levelId - 1))) extern "C" { -bool player_is_present(void); -s32 item_getCount(enum item_e item); -void item_set(s32 item, s32 val); -bool fileProgressFlag_get(enum file_progress_e index); -void fileProgressFlag_set(enum file_progress_e index, s32 set); -int ability_isUnlocked(enum ability_e uid); -void ability_setLearned(s32 move, s32 val); -u32 jiggyscore_isCollected(enum jiggy_e jiggy_id); +bool ability_isUnlocked(enum ability_e uid); void jiggyscore_setCollected(s32 indx, s32 val); -bool honeycombscore_get(enum honeycomb_e indx); void honeycombscore_set(enum honeycomb_e indx, bool val); void mumboscore_set(enum mumbotoken_e indx, bool val); @@ -93,39 +83,39 @@ bool SaveEditor_IsHoneycombCollected(honeycomb_e honeycombId) { } void SaveEditor_UpdateCheckTracker(RandoSaveCheck randoSaveCheck) { - if (randoSaveCheck.obtained) { + if (randoSaveCheck.eligible) { CustomObject::CheckObtainedEX(randoSaveCheck.randoCheckId); } for (auto& pool : Rando::Logic::shuffledPool) { if (pool.randoCheckId == randoSaveCheck.randoCheckId) { pool.isShuffled = randoSaveCheck.isShuffled; - pool.obtained = randoSaveCheck.obtained; + pool.eligible = randoSaveCheck.eligible; pool.skipped = randoSaveCheck.skipped; break; } } - int32_t itemIncr = randoSaveCheck.obtained ? 1 : -1; + int32_t itemIncr = randoSaveCheck.eligible ? 1 : -1; Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[randoSaveCheck.randoItemId]; switch (randoItem.randoItemType) { case RITYPE_JIGGY: - jiggyscore_setCollected(randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); + jiggyscore_setCollected(randoSaveCheck.randoCollectionId, randoSaveCheck.eligible); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, itemIncr); break; case RITYPE_EMPTY_HONEYCOMB: - honeycombscore_set((honeycomb_e)randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); + honeycombscore_set((honeycomb_e)randoSaveCheck.randoCollectionId, randoSaveCheck.eligible); break; case RITYPE_MOLEHILL: - if (randoSaveCheck.obtained) { + if (randoSaveCheck.eligible) { ability_unlock((ability_e)randoSaveCheck.randoCollectionId); } else { ability_setLearned((ability_e)randoSaveCheck.randoCollectionId, 0); } break; case RITYPE_MUMBO_TOKEN: - mumboscore_set((mumbotoken_e)randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); + mumboscore_set((mumbotoken_e)randoSaveCheck.randoCollectionId, randoSaveCheck.eligible); item_adjustByDiffWithoutHud(ITEM_1C_MUMBO_TOKEN, itemIncr); break; default: @@ -367,6 +357,10 @@ void SaveEditor_DrawProgressTab() { void DrawRandoFlagEditor() { ImGui::SeparatorText("Rando INF Flags"); + if (selectedFileNum == DEFAULT_FILE_NUM) { + ImGui::Text("No Save File Loaded"); + return; + } if (ImGui::BeginChild("RandoFlagChild")) { for (int f = RANDO_INF_UNKNOWN; f < RANDO_INF_MAX; f++) { ImGui::PushID(f); @@ -381,7 +375,7 @@ void DrawRandoFlagEditor() { } void DrawRandoCheckEditor() { - if (Rando::Logic::shuffledPool.empty()) { + if (selectedFileNum == DEFAULT_FILE_NUM || Rando::Logic::shuffledPool.empty()) { ImGui::Text("No Rando Save Data"); } else { static ImGuiTextFilter rcFilter; @@ -394,9 +388,10 @@ void DrawRandoCheckEditor() { } if (ImGui::BeginChild("RandoToolsChild", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { - if (ImGui::BeginTable("RandoSaveEditorTable", 6)) { + if (ImGui::BeginTable("RandoSaveEditorTable", 7)) { ImGui::TableSetupColumn("shuffled", ImGuiTableColumnFlags_WidthFixed, 34.0f); - ImGui::TableSetupColumn("obtained", ImGuiTableColumnFlags_WidthFixed, 34.0f); + ImGui::TableSetupColumn("eligible", ImGuiTableColumnFlags_WidthFixed, 34.0f); + ImGui::TableSetupColumn("received", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("skipped", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("checkName", ImGuiTableColumnFlags_WidthFixed, (ImGui::GetContentRegionAvail().x - 34.0f) * 0.60f); @@ -406,33 +401,52 @@ void DrawRandoCheckEditor() { ImGui::TableNextColumn(); for (auto& check : RANDO_SAVE_CHECKS) { - if (!rcFilter.PassFilter(check.name) && - !rcFilter.PassFilter(Rando::StaticData::Items[check.randoItemId].name)) { + auto checkEntry = Rando::StaticData::Checks.find(check.randoCheckId); + if (checkEntry == Rando::StaticData::Checks.end()) { + continue; + } + const char* checkName = checkEntry->second.name; + + auto itemEntry = Rando::StaticData::Items.find(check.randoItemId); + const char* itemName = + (itemEntry != Rando::StaticData::Items.end()) ? itemEntry->second.name : nullptr; + + if (!rcFilter.PassFilter(checkName) && !rcFilter.PassFilter(itemName)) { continue; } ImGui::PushID(check.randoCheckId); bool isChanged = false; bool isShuffled = check.isShuffled; - bool obtained = check.obtained; + bool eligible = check.eligible; + bool received = check.received; bool skipped = check.skipped; + std::string checkId = std::to_string((uint32_t)check.randoCheckId); + if (UIWidgets::Checkbox( - "isShuffled", &isShuffled, + ("isShuffled##" + checkId).c_str(), &isShuffled, UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { RANDO_SAVE_CHECKS[check.randoCheckId].isShuffled = !check.isShuffled; isChanged = true; } ImGui::TableNextColumn(); if (UIWidgets::Checkbox( - "obtained", &obtained, + ("eligible##" + checkId).c_str(), &eligible, + UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { + RANDO_SAVE_CHECKS[check.randoCheckId].eligible = !check.eligible; + isChanged = true; + } + ImGui::TableNextColumn(); + if (UIWidgets::Checkbox( + ("received##" + checkId).c_str(), &received, UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { - RANDO_SAVE_CHECKS[check.randoCheckId].obtained = !check.obtained; + RANDO_SAVE_CHECKS[check.randoCheckId].received = !check.received; isChanged = true; } ImGui::TableNextColumn(); if (UIWidgets::Checkbox( - "skipped", &skipped, + ("skipped##" + checkId).c_str(), &skipped, UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { RANDO_SAVE_CHECKS[check.randoCheckId].skipped = !check.skipped; isChanged = true; @@ -443,8 +457,7 @@ void DrawRandoCheckEditor() { } ImGui::TableNextColumn(); - std::string checkName = Rando::StaticData::Checks[check.randoCheckId].name; - ImGui::TextWrapped(checkName.c_str()); + ImGui::TextWrapped("%s", checkName); ImGui::TableNextColumn(); ImGui::TextWrapped(Rando::StaticData::Items[check.randoItemId].name); diff --git a/src/port/UI/InputViewer.cpp b/src/port/UI/InputViewer.cpp index 692de976c..3920b287c 100644 --- a/src/port/UI/InputViewer.cpp +++ b/src/port/UI/InputViewer.cpp @@ -73,339 +73,335 @@ void InputViewer::Draw() { } void InputViewer::DrawElement() { - if (CVarGetInteger(CVAR_WINDOW("InputViewer"), 0)) { - static bool sButtonTexturesLoaded = false; - if (!sButtonTexturesLoaded) { - GetFast3dGui()->LoadTextureFromRawImage("Input-Viewer-Background", - "textures/buttons/InputViewerBackground.png"); - GetFast3dGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/StartBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); - GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick", "textures/buttons/AnalogStick.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/DPadLeft.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/DPadRight.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); - GetFast3dGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); - GetFast3dGui()->LoadTextureFromRawImage("A-Btn Outline", "textures/buttons/ABtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("B-Btn Outline", "textures/buttons/BBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("L-Btn Outline", "textures/buttons/LBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("R-Btn Outline", "textures/buttons/RBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Z-Btn Outline", "textures/buttons/ZBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Start-Btn Outline", "textures/buttons/StartBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Left Outline", "textures/buttons/CLeftOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Right Outline", "textures/buttons/CRightOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Up Outline", "textures/buttons/CUpOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Down Outline", "textures/buttons/CDownOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right Outline", "textures/buttons/DPadRightOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up Outline", "textures/buttons/DPadUpOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-1 Outline", "textures/buttons/Mod1Outline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-2 Outline", "textures/buttons/Mod2Outline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); - sButtonTexturesLoaded = true; - } + static bool sButtonTexturesLoaded = false; + if (!sButtonTexturesLoaded) { + GetFast3dGui()->LoadTextureFromRawImage("Input-Viewer-Background", + "textures/buttons/InputViewerBackground.png"); + GetFast3dGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/StartBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); + GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick", "textures/buttons/AnalogStick.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/DPadLeft.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/DPadRight.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); + GetFast3dGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); + GetFast3dGui()->LoadTextureFromRawImage("A-Btn Outline", "textures/buttons/ABtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("B-Btn Outline", "textures/buttons/BBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("L-Btn Outline", "textures/buttons/LBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("R-Btn Outline", "textures/buttons/RBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Z-Btn Outline", "textures/buttons/ZBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Start-Btn Outline", "textures/buttons/StartBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Left Outline", "textures/buttons/CLeftOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Right Outline", "textures/buttons/CRightOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Up Outline", "textures/buttons/CUpOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Down Outline", "textures/buttons/CDownOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right Outline", "textures/buttons/DPadRightOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up Outline", "textures/buttons/DPadUpOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-1 Outline", "textures/buttons/Mod1Outline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-2 Outline", "textures/buttons/Mod2Outline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); + sButtonTexturesLoaded = true; + } - ImVec2 mainPos = ImGui::GetWindowPos(); - ImVec2 size = ImGui::GetMainViewport()->WorkSize; + ImVec2 mainPos = ImGui::GetWindowPos(); + ImVec2 size = ImGui::GetMainViewport()->WorkSize; #ifdef __WIIU__ - const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.0f; + const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.0f; #else - const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); + const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); #endif - const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); - const int buttonOutlineMode = - CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); - const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); - - ImVec2 bgSize = GetFast3dGui()->GetTextureSize("Input-Viewer-Background"); - ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); - - ImGui::SetNextWindowSize( - ImVec2(scaledBGSize.x + 20, scaledBGSize.y + - (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * - CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + - 20)); - ImGui::SetNextWindowContentSize( - ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * - CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); - ImGui::SetNextWindowPos( - ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), - ImGuiCond_FirstUseEver); - - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); - - OSContPad* pads = - std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetControlDeck())->GetPads(); - - ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | - ImGuiWindowFlags_NoFocusOnAppearing; - - if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) { - windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; - } + const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); + const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); + const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); + + ImVec2 bgSize = GetFast3dGui()->GetTextureSize("Input-Viewer-Background"); + ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); + + ImGui::SetNextWindowSize( + ImVec2(scaledBGSize.x + 20, scaledBGSize.y + + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + + 20)); + ImGui::SetNextWindowContentSize( + ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); + ImGui::SetNextWindowPos(ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), + ImGuiCond_FirstUseEver); + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + + OSContPad* pads = + std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetControlDeck())->GetPads(); + + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoFocusOnAppearing; + + if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) { + windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; + } - if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) { - ImGui::SetCursorPos(ImVec2(10, 10)); - const ImVec2 aPos = ImGui::GetCursorPos(); + if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) { + ImGui::SetCursorPos(ImVec2(10, 10)); + const ImVec2 aPos = ImGui::GetCursorPos(); - if (CVarGetInteger(CVAR_INPUT_VIEWER("ShowBackground"), 1)) { - ImGui::SetNextItemAllowOverlap(); - // Background - ImGui::Image(GetFast3dGui()->GetTextureByName("Input-Viewer-Background"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } + if (CVarGetInteger(CVAR_INPUT_VIEWER("ShowBackground"), 1)) { + ImGui::SetNextItemAllowOverlap(); + // Background + ImGui::Image(GetFast3dGui()->GetTextureByName("Input-Viewer-Background"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } - // A/B - if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // A/B + if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // C buttons - if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // C buttons + if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // L/R/Z - if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // L/R/Z + if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // Start - if (CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, - useGlobalOutlineMode ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), - BUTTON_OUTLINE_NOT_PRESSED)); - } + // Start + if (CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // Dpad - if (CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - // Lighthouse Unused - // Modifier 1 - // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { - // ImGui::SetNextItemAllowOverlap(); - // ImGui::SetCursorPos(aPos); - // RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize, - // useGlobalOutlineMode - // ? buttonOutlineMode - // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - //} - // Modifier 2 - // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { - // ImGui::SetNextItemAllowOverlap(); - // ImGui::SetCursorPos(aPos); - // RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize, - // useGlobalOutlineMode - // ? buttonOutlineMode - // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - //} - - const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; - const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y; - - // Analog Stick - const int analogOutlineMode = - CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN); - const int32_t maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12); - if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || - (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick Outline"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } - const int analogStickMode = - CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN); - if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || - (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos( - ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, - aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); - ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } + // Dpad + if (CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + // Lighthouse Unused + // Modifier 1 + // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { + // ImGui::SetNextItemAllowOverlap(); + // ImGui::SetCursorPos(aPos); + // RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize, + // useGlobalOutlineMode + // ? buttonOutlineMode + // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + //} + // Modifier 2 + // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { + // ImGui::SetNextItemAllowOverlap(); + // ImGui::SetCursorPos(aPos); + // RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize, + // useGlobalOutlineMode + // ? buttonOutlineMode + // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + //} + + const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; + const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y; + + // Analog Stick + const int analogOutlineMode = + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN); + const int32_t maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12); + if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick Outline"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } + const int analogStickMode = + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN); + if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || + (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } - // Right Stick - const int32_t maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7); - const int rightOutlineMode = - CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN); - if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || - (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick Outline"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } - const int rightStickMode = - CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN); - if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || - (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos( - ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, - aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); - ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } + // Right Stick + const int32_t maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7); + const int rightOutlineMode = + CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN); + if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick Outline"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } + const int rightStickMode = + CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN); + if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || + (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } - // Analog stick angle text - if (showAnalogAngles) { - ImGui::SetCursorPos( - ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, - scaledBGSize.y + aPos.y + 10)); - // Scale font with input viewer scale - float oldFontScale = ImGui::GetFont()->Scale; - ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f); - ImGui::PushFont(ImGui::GetFont()); - - // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt - const int32_t rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; - - // ESS range - const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8); - const int range1Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Max"), 27); - // Walking speed range - const int range2Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Min"), 27); - const int range2Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Max"), 62); - - // Push color based on angle ranges - if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && - (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { - ImGui::PushStyleColor( - ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), - range1ColorDefault))); - } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) && - (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { - ImGui::PushStyleColor( - ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), - range2ColorDefault))); - } else { - ImGui::PushStyleColor(ImGuiCol_Text, - VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"), - textColorDefault))); - } - - // Render text - ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y); - // Restore original color - ImGui::PopStyleColor(); - // Restore original font scale - ImGui::GetFont()->Scale = oldFontScale; - ImGui::PopFont(); + // Analog stick angle text + if (showAnalogAngles) { + ImGui::SetCursorPos( + ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, + scaledBGSize.y + aPos.y + 10)); + // Scale font with input viewer scale + float oldFontScale = ImGui::GetFont()->Scale; + ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f); + ImGui::PushFont(ImGui::GetFont()); + + // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt + const int32_t rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; + + // ESS range + const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8); + const int range1Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Max"), 27); + // Walking speed range + const int range2Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Min"), 27); + const int range2Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Max"), 62); + + // Push color based on angle ranges + if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && + (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { + ImGui::PushStyleColor(ImGuiCol_Text, + VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), + range1ColorDefault))); + } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) && + (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { + ImGui::PushStyleColor(ImGuiCol_Text, + VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), + range2ColorDefault))); + } else { + ImGui::PushStyleColor( + ImGuiCol_Text, + VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"), textColorDefault))); } - ImGui::End(); + // Render text + ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y); + // Restore original color + ImGui::PopStyleColor(); + // Restore original font scale + ImGui::GetFont()->Scale = oldFontScale; + ImGui::PopFont(); } - ImGui::PopStyleVar(); - ImGui::PopStyleColor(); + ImGui::End(); } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); } InputViewerSettingsWindow::~InputViewerSettingsWindow() { diff --git a/src/port/UI/LighthouseGui.cpp b/src/port/UI/LighthouseGui.cpp index 2e5d70095..7885ff7af 100644 --- a/src/port/UI/LighthouseGui.cpp +++ b/src/port/UI/LighthouseGui.cpp @@ -23,6 +23,8 @@ #include "port/Rando/CheckTracker/CheckTracker.h" #include "Notification.h" +#include "port/Controller/Mapper.h" +#include "port/Network/Anchor/Anchor.h" #include "port/Enhancements/Backports/EggAim.h" #include "LighthouseMenu.h" #include "LighthouseInputEditorWindow.h" @@ -43,6 +45,7 @@ std::shared_ptr mConsoleWindow; std::shared_ptr mStatsWindow; std::shared_ptr mGfxDebuggerWindow; std::shared_ptr mInputEditorWindow; +std::shared_ptr mGamepadMapperWindow; std::shared_ptr mModMenuWindow; std::shared_ptr mRomhackMenuWindow; @@ -72,6 +75,7 @@ std::shared_ptr mEggAimCrosshair; std::shared_ptr mModalWindow; std::shared_ptr mEventDebuggerWindow; std::shared_ptr mOcclusionDebugWindow; +std::shared_ptr mAnchorRoomWindow; UIWidgets::Colors GetMenuThemeColor() { return mLighthouseMenu->GetMenuThemeColor(); @@ -105,15 +109,19 @@ void SetupGuiElements() { SPDLOG_ERROR("Could not find console window"); } - mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow"); - if (mGfxDebuggerWindow == nullptr) { - SPDLOG_ERROR("Could not find input GfxDebuggerWindow"); - } + // mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow"); + // if (mGfxDebuggerWindow == nullptr) { + // SPDLOG_ERROR("Could not find input GfxDebuggerWindow"); + // } mInputEditorWindow = std::make_shared(CVAR_WINDOW("ControllerConfiguration"), "Configure Controller"); gui->AddGuiWindow(mInputEditorWindow); + mGamepadMapperWindow = + std::make_shared(CVAR_WINDOW("GamepadMapper"), "Gamepad Mapper", ImVec2(1280, 820)); + gui->AddGuiWindow(mGamepadMapperWindow); + mModMenuWindow = std::make_shared(CVAR_WINDOW("ModMenu"), "Mod Menu"); gui->AddGuiWindow(mModMenuWindow); @@ -190,10 +198,10 @@ void SetupGuiElements() { "gWindows.CheckTrackerSettings", "Check Tracker Settings"); gui->AddGuiWindow(mRandoCheckTrackerSettingsWindow); - mInputViewer = std::make_shared("gWindows.InputViewer", "Input Viewer"); + mInputViewer = std::make_shared(CVAR_WINDOW("InputViewer"), "Input Viewer"); gui->AddGuiWindow(mInputViewer); - mInputViewerSettings = std::make_shared("gWindows.InputViewerSettings", + mInputViewerSettings = std::make_shared(CVAR_WINDOW("InputViewerSettings"), "Input Viewer Settings", ImVec2(500, 525)); gui->AddGuiWindow(mInputViewerSettings); @@ -202,6 +210,9 @@ void SetupGuiElements() { mOcclusionDebugWindow = std::make_shared(CVAR_WINDOW("OcclusionDebug"), "Occlusion Debugger"); gui->AddGuiWindow(mOcclusionDebugWindow); + + mAnchorRoomWindow = std::make_shared(CVAR_WINDOW("AnchorRoom"), "Anchor Room"); + gui->AddGuiWindow(mAnchorRoomWindow); } void Destroy() { @@ -214,6 +225,7 @@ void Destroy() { mConsoleWindow = nullptr; mGfxDebuggerWindow = nullptr; mInputEditorWindow = nullptr; + mGamepadMapperWindow = nullptr; // mCollisionViewerWindow = nullptr; // mEventLogWindow = nullptr; mNotificationWindow = nullptr; @@ -237,6 +249,7 @@ void Destroy() { mEggAimCrosshair = nullptr; mEventDebuggerWindow = nullptr; mOcclusionDebugWindow = nullptr; + mAnchorRoomWindow = nullptr; } void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, diff --git a/src/port/UI/LighthouseInputEditorWindow.cpp b/src/port/UI/LighthouseInputEditorWindow.cpp index e762f7be1..e577e199f 100644 --- a/src/port/UI/LighthouseInputEditorWindow.cpp +++ b/src/port/UI/LighthouseInputEditorWindow.cpp @@ -4,6 +4,7 @@ #include #include #include +#include "cvar_prefixes.h" #ifndef __WIIU__ #include #endif @@ -13,6 +14,15 @@ #define SCALE_IMGUI_SIZE(value) ((value / 13.0f) * ImGui::GetFontSize()) LighthouseInputEditorWindow::~LighthouseInputEditorWindow() { + auto ignored = Ship::Context::GetRawInstance() + ->GetControlDeck() + ->GetConnectedPhysicalDeviceManager() + ->GetIgnoredInstanceIdsForPort(0); + if (!ignored.empty()) { + Ship::Context::GetRawInstance()->GetConfig()->SetBlock("CVars.gSettings.IgnoredControllers", ignored); + } else { + Ship::Context::GetRawInstance()->GetConfig()->EraseBlock("CVars.gSettings.IgnoredControllers"); + } } void LighthouseInputEditorWindow::InitElement() { @@ -40,6 +50,19 @@ void LighthouseInputEditorWindow::InitElement() { addButtonName(BTN_DLEFT, "D-pad left"); addButtonName(BTN_DRIGHT, "D-pad right"); addButtonName(0, "None"); + if (Ship::Context::GetRawInstance()->GetConfig()->GetNestedJson()["CVars"]["gSettings"].contains( + "IgnoredControllers")) { + std::vector ignored = + Ship::Context::GetRawInstance()->GetConfig()->GetNestedJson()["CVars"]["gSettings"]["IgnoredControllers"]; + if (!ignored.empty()) { + for (int id : ignored) { + Ship::Context::GetRawInstance() + ->GetControlDeck() + ->GetConnectedPhysicalDeviceManager() + ->IgnoreInstanceIdForPort(0, id); + } + } + } } #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 diff --git a/src/port/UI/LighthouseMenu.cpp b/src/port/UI/LighthouseMenu.cpp index 63769245f..db16a7c99 100644 --- a/src/port/UI/LighthouseMenu.cpp +++ b/src/port/UI/LighthouseMenu.cpp @@ -5,6 +5,7 @@ #include "port/Localization/Language.h" #include "port/Romhack/RomhackConfig.h" #include "port/Patches/Patches.h" +#include "port/Network/Anchor/Anchor.h" #include #include #include @@ -213,6 +214,12 @@ void LighthouseMenu::InitElement() { "Not available during the character parade." } }, { DISABLE_FOR_ROMHACK, { [](disabledInfo& info) -> bool { return port_isRomhack(); }, "Not available with romhacks" } }, + { FORCED_ON_FOR_ANCHOR_CONNECTED, + { [](disabledInfo& info) -> bool { + Anchor* anchor = Anchor::GetInstance(); + return anchor != nullptr && anchor->isConnected && !anchor->IsGlobalRoom(); + }, + "Forced on while connected to Anchor" } }, }; } diff --git a/src/port/UI/LighthouseMenuDevTools.cpp b/src/port/UI/LighthouseMenuDevTools.cpp index 38a337350..6ce8a96f8 100644 --- a/src/port/UI/LighthouseMenuDevTools.cpp +++ b/src/port/UI/LighthouseMenuDevTools.cpp @@ -6,12 +6,11 @@ //#include #include "port/ResourceHelpers.h" #include "port/DevTools/DevSequences.h" +#include "port/DevTools/ThreadWatchdog.h" #include "UIWidgets.hpp" #include -extern "C" { #include "variables.h" -} namespace LighthouseGui { @@ -73,9 +72,14 @@ void LighthouseMenu::AddMenuDevTools() { .Options(CheckboxOptions().Tooltip( "Enables the Gfx trace mode, which will output information about the Gfx commands being run.")); #endif - AddWidget(path, "Nametag Distance", WIDGET_CVAR_SLIDER_FLOAT) - .CVar(CVAR_DEVELOPER_TOOLS("NametagDist")) - .Options(FloatSliderOptions().DefaultValue(3000.0f).Min(1000.0f).Max(10000.0f).Step(10.0f)); + AddWidget(path, "Dump Thread State", WIDGET_BUTTON) + .Callback([](WidgetInfo&) { ThreadWatchdog_DumpNow(); }) + .Options( + ButtonOptions() + .Size(Sizes::Inline) + .Tooltip( + "Log a snapshot of the decomp thread heartbeats and pipeline queue state. The watchdog also logs " + "this automatically when a thread stops beating.")); /*AddWidget(path, "Debug Mode", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_DEVELOPER_TOOLS("DebugMode")) .Options(CheckboxOptions().Tooltip("Various debug features, including a level selector from the main menu."));*/ @@ -97,6 +101,11 @@ void LighthouseMenu::AddMenuDevTools() { AddWidget(path, "Spiral Mountain Ending Sequence", WIDGET_BUTTON) .Callback([](WidgetInfo&) { RequestSequence(SEQ_MODE9_BK); }) .Options(ButtonOptions().Size(Sizes::Inline).Tooltip("Jump to the post-parade demo.")); + AddWidget(path, "All 100 Ending Scene", WIDGET_BUTTON) + .Callback([](WidgetInfo&) { RequestSequence(SEQ_ENDING_ALL_100); }) + .Options(ButtonOptions() + .Size(Sizes::Inline) + .Tooltip("Jump to the 100-jiggy ending cutscene (normally shown after the final parade).")); AddWidget(path, "Attract Demos", WIDGET_SEPARATOR_TEXT); // Demo index = slot in the decomp attract table (D_80371F00); 4 and 9 are the @@ -141,14 +150,6 @@ void LighthouseMenu::AddMenuDevTools() { .HideInSearch(true) .Options(WindowButtonOptions().Tooltip( "Shows the stats window, with your FPS and frametimes, and the OS you're playing on.")); - AddWidget(path, "Adaptive FPS", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_SETTING("AdaptiveFPS")) - .RaceDisable(false) - .Options(CheckboxOptions() - .Tooltip("Automatically lowers interpolation FPS in demanding scenes so the game logic never " - "stalls, then restores it when the scene clears. Disable to always target your " - "requested FPS, which may stutter on heavy scenes or weaker hardware.") - .DefaultValue(true)); // Console // path.sidebarName = "Console"; diff --git a/src/port/UI/LighthouseMenuEnhancements.cpp b/src/port/UI/LighthouseMenuEnhancements.cpp index a9be7a36c..ee18db3a6 100644 --- a/src/port/UI/LighthouseMenuEnhancements.cpp +++ b/src/port/UI/LighthouseMenuEnhancements.cpp @@ -1,5 +1,12 @@ #include "LighthouseMenu.h" #include "port/Enhancements/Trackers/DisplayOverlay.h" +#include "port/Network/Anchor/Anchor.h" + +#include "functions.h" +extern "C" { +#include "variables.h" +extern u8 gCompletedBottlesBonusGames[7]; +} #define CVAR_INT_SHIP_INIT(cvar, val) \ CVarSetInteger(cvar, val); \ @@ -7,6 +14,54 @@ namespace LighthouseGui { +// Live toggle state for the Bottles' Bonus gags (non-cvar checkboxes). Order matches +// D_803635EC in ba_anim.c and gCompletedBottlesBonusGames. +static bool sBottlesBonusState[7] = { false }; + +static const char* kBottlesBonusNames[7] = { + "Big Head", + "Big Hands & Feet", + "Big Kazooie", + "Tall Body & Small Head", + "Tall Body, Small Head, Big Hands & Feet", + "Big Everything", + "Wishy-Washy Banjo", +}; + +static const char* kBottlesBonusTooltips[7] = { + "Bottles' Bonus: enlarges Banjo's head.", + "Bottles' Bonus: enlarges Banjo's hands and feet.", + "Bottles' Bonus: enlarges Kazooie's head and wings.", + "Bottles' Bonus: stretches Banjo's body and shrinks his head.", + "Bottles' Bonus: stretched body, shrunken head, and big hands and feet.", + "The 'Big Bottles Bonus': big head, big hands and feet, and big Kazooie.", + "Bottles' Bonus: turns Banjo into Wishy-Washy.", +}; + +static const char* kBottlesBonusLockedTooltip = + "Complete this Bottles' Bonus puzzle to unlock it. (Always available while connected to Anchor.)"; + +static bool IsBottlesBonusUnlocked(int i) { + Anchor* anchor = Anchor::GetInstance(); + if (anchor != nullptr && anchor->isConnected && !anchor->IsGlobalRoom()) { + return true; + } + return gCompletedBottlesBonusGames[i] != 0; +} + +static void ApplyBottlesBonusState() { + bool any = false; + for (int i = 0; i < 7; i++) { + volatileFlag_setEx((enum volatile_flags_e)(VOLATILE_FLAG_97_SANDCASTLE_BOTTLES_BONUS_1 + i), + sBottlesBonusState[i] ? 1 : 0, 0); + if (sBottlesBonusState[i]) { + any = true; + } + } + // Master gate read by __baanim_applyBottlesBonus / baanim_getActiveBottlesBonusMask. + volatileFlag_setEx(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS, any ? 1 : 0, 0); +} + extern std::shared_ptr mLighthouseMenu; using namespace UIWidgets; @@ -22,16 +77,31 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Allow Start to Skip Boot Logos", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cutscenes.SkipBootLogos")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Press Start to skip the Rareware and Nintendo logos on boot.")); AddWidget(path, "Allow Start to Skip Intro Cutscenes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cutscenes.StartSkipIntro")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Press Start to Skip Intro Cutscenes.")); AddWidget(path, "Allow Start to Skip Misc Cutscenes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cutscenes.SkipMiscCutscenes")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Press Start to skip the Gruntilda's Lair and Game Over cutscenes.")); AddWidget(path, "Skip Jiggy Dance", WIDGET_CVAR_CHECKBOX) @@ -45,6 +115,11 @@ void LighthouseMenu::AddMenuEnhancements() { .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Skips the cutscene that plays when first defeating a Clucker.")); + AddWidget(path, "Skip Note Door Dance", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("Cutscenes.SkipNoteDoorDance")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Skips Banjo's dance when a note door opens, opening it immediately.")); + // Enhancements -> Graphics path = { "Enhancements", "Graphics", SECTION_COLUMN_1 }; AddSidebarEntry("Enhancements", path.sidebarName, 2); @@ -60,10 +135,29 @@ void LighthouseMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip("Forces game to show original aspect ratio during cutscenes to avoid seeing " "unfinished edges of scene geometry.")); - AddWidget(path, "Extended Draw Distance: %dx", WIDGET_CVAR_SLIDER_INT) + path.column = SECTION_COLUMN_2; + + AddWidget(path, "Bottles' Bonuses", WIDGET_SEPARATOR_TEXT); + + for (int i = 0; i < 7; i++) { + AddWidget(path, kBottlesBonusNames[i], WIDGET_CHECKBOX) + .ValuePointer(&sBottlesBonusState[i]) + .Callback([](WidgetInfo& info) { ApplyBottlesBonusState(); }) + .PreFunc([i](WidgetInfo& info) { + if (!IsBottlesBonusUnlocked(i)) { + info.options->disabled = true; + info.options->disabledTooltip = kBottlesBonusLockedTooltip; + } + }) + .Options(CheckboxOptions().Tooltip(kBottlesBonusTooltips[i])); + } + + path.column = SECTION_COLUMN_1; + + AddWidget(path, "Extended Draw Distance", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_ENHANCEMENT("Graphics.DrawDistance")) .RaceDisable(false) - .Options(IntSliderOptions().Min(1).Max(6).DefaultValue(1).ShowButtons(true).Format("").Tooltip( + .Options(IntSliderOptions().Min(1).Max(6).DefaultValue(1).ShowButtons(true).Format("%dx").Tooltip( "Multiplies the draw distance for objects.\n" "Higher values render more but cost performance.")); @@ -218,11 +312,21 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Fix CCW Gnawty Rock (Spring)", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fixes.GnawtySpringRock")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Makes Gnawty's rock indestructible in CCW Spring.")); AddWidget(path, "Fix Termite Mound Slopes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fixes.TermiteMoundSlopes")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Makes slopes in the Mumbo's Mountain termite mound slide instantly.")); AddWidget(path, "Fix Early Claw Swipe During Slide", WIDGET_CVAR_CHECKBOX) @@ -250,6 +354,13 @@ void LighthouseMenu::AddMenuEnhancements() { .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Stops the Jinjo charge-up sound the instant it hits Grunty.")); + AddWidget(path, "Mute Chimpy Replay", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("Fixes.ChimpyStumpRumble")) + .RaceDisable(false) + .Options(CheckboxOptions().DefaultValue(true).Tooltip( + "Mutes Chimpy and the rumbling sound his stump makes on every return trip to " + "Mumbo's Mountain. The first rise keeps its sound.")); + AddWidget(path, "Fix Cutscene Audio Sync", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fix.CutsceneSync")) .RaceDisable(false) @@ -268,8 +379,24 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Fix Conga's Name", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fixes.CongaText")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Corrects a spelling error when meeting Conga as a termite.")); + AddWidget(path, "Fix Freezeezy Peak Lobby", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("Fixes.FPLobbyDoorTile")) + .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) + .Options(CheckboxOptions().Tooltip("Fixes the smeared snow trim around the Freezeezy Peak entrance in " + "Gruntilda's Lair. Requires a map reload to take effect.")); + // Enhancements -> Restorations path = { "Enhancements", "Restorations", SECTION_COLUMN_1 }; AddSidebarEntry("Enhancements", path.sidebarName, 2); @@ -302,6 +429,16 @@ void LighthouseMenu::AddMenuEnhancements() { }) .DefaultIndex(1)); + AddWidget(path, "Permadeath", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("Gameplay.Permadeath")) + .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) + .Options(CheckboxOptions().Tooltip("Your save file is deleted on death. Lives are ignored.")); + AddWidget(path, "Skip Spiral Mountain Tutorial", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Gameplay.SkipSMTutorial")) .RaceDisable(false) @@ -360,7 +497,8 @@ void LighthouseMenu::AddMenuEnhancements() { info.activeDisables.push_back(DISABLE_FOR_ROMHACK); } }) - .Options(CheckboxOptions().Tooltip("Reduces Boggy's max speed during both sled races in Freezeezy Peak.")); + .Options(CheckboxOptions().Tooltip("Reduces Boggy's max speed during both sled races in Freezeezy Peak.\n" + "Requires a map reload to take effect.")); AddWidget(path, "Easier Mr Vile", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("EasierMrVile")) @@ -422,6 +560,11 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Note Collection Retention", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Gameplay.NoteRetention")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(FORCED_ON_FOR_ANCHOR_CONNECTED).active) { + info.activeDisables.push_back(FORCED_ON_FOR_ANCHOR_CONNECTED); + } + }) .Options(CheckboxOptions().Tooltip( "Notes you've already collected stay collected and don't respawn when you revisit a level. " "Collection is always tracked; this toggle controls whether collected notes are skipped on " @@ -430,6 +573,11 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Jinjo Collection Retention", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Gameplay.JinjoRetention")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(FORCED_ON_FOR_ANCHOR_CONNECTED).active) { + info.activeDisables.push_back(FORCED_ON_FOR_ANCHOR_CONNECTED); + } + }) .Options(CheckboxOptions().Tooltip( "Jinjos you've already collected stay collected across visits instead of resetting each time " "you enter a level, so you no longer need all five in one go. Collection is always tracked; " @@ -499,7 +647,7 @@ void LighthouseMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("Cheats.TalonTrotCycle")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip( - "While in Talon Trot: D-pad Right cycles forward (Normal→Boots→Sneakers), D-pad Left cycles backward.")); + "While in Talon Trot: D-pad Right cycles forward (Normal->Boots->Sneakers), D-pad Left cycles backward.")); // Transformations Section AddWidget(path, "Transformations", WIDGET_SEPARATOR_TEXT); @@ -507,22 +655,32 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Fast Transformation", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cheats.FastTransform")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip("Speeds up Mumbo transformation animation by 3x.")); AddWidget(path, "D-pad Cycle Transform", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cheats.CycleTransform")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Press D-pad Up/Down to cycle through transformation forms.\nUp: Forward " - "(Banjo→Mumbo→...→Wishy→Banjo), Down: Backward.")); + "(Banjo->Termite->...->Bee->Banjo), Down: Backward.")); AddWidget(path, "No Mumbo Untransform", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cheats.NoMumboUntransform")) .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { + info.activeDisables.push_back(DISABLE_FOR_ROMHACK); + } + }) .Options(CheckboxOptions().Tooltip( "Disables Mumbo untransforming you when going too far and skips his warning dialog.")); path = { "Enhancements", "Trackers", SECTION_COLUMN_1 }; - AddSidebarEntry("Enhancements", path.sidebarName, 1); + AddSidebarEntry("Enhancements", path.sidebarName, 2); path.column = SECTION_COLUMN_1; AddWidget(path, "Gameplay Timer", WIDGET_SEPARATOR_TEXT); @@ -551,7 +709,7 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Hide Window Background", WIDGET_CVAR_CHECKBOX) .CVar("gDisplayOverlay.Background") .Options(CheckboxOptions().Tooltip("Hides the background of the Display Overlay window.")); - AddWidget(path, "Scale: %.1fx", WIDGET_CVAR_SLIDER_FLOAT) + AddWidget(path, "Timer Scale", WIDGET_CVAR_SLIDER_FLOAT) .CVar("gDisplayOverlay.Scale") .Options(FloatSliderOptions() .Tooltip("Adjust the Scale for the Display Overlay window.") diff --git a/src/port/UI/LighthouseMenuNetwork.cpp b/src/port/UI/LighthouseMenuNetwork.cpp index 42310a6a7..5759914bc 100644 --- a/src/port/UI/LighthouseMenuNetwork.cpp +++ b/src/port/UI/LighthouseMenuNetwork.cpp @@ -7,9 +7,7 @@ #include "UIWidgets.hpp" #include -extern "C" { #include "variables.h" -} namespace LighthouseGui { diff --git a/src/port/UI/LighthouseMenuSettings.cpp b/src/port/UI/LighthouseMenuSettings.cpp index f70c67990..b463c570a 100644 --- a/src/port/UI/LighthouseMenuSettings.cpp +++ b/src/port/UI/LighthouseMenuSettings.cpp @@ -13,9 +13,7 @@ #include "UIWidgets.hpp" #include -extern "C" { #include "variables.h" -} namespace LighthouseGui { @@ -156,8 +154,8 @@ void LighthouseMenu::AddMenuSettings() { .ComponentAlignment(ComponentAlignments::Right) .ComboMap(bootSequenceLabels) .Tooltip("Configure what happens when starting or resetting the game.\n\n" - "Default: LUS logo -> N64 logo\n" - "Authentic: N64 logo only\n" + "Default: Replace the N64 branding with LUS branding\n" + "Authentic: Keep the authentic N64 branding\n" "File Select: Skip to file select menu")); path.column = SECTION_COLUMN_2; @@ -183,12 +181,13 @@ void LighthouseMenu::AddMenuSettings() { "Make sure you're playing the same game or romhack as the save you're importing.", "Select Save", "Cancel", [slot]() { - SaveConverter::Result r = SaveConverter::PickAndImport(slot); - if (r.message.empty()) { - return; // cancelled - } - LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Import Complete" : "Save Import Failed", - r.message, "OK", "", nullptr, nullptr); + SaveConverter::PickAndImport(slot, [](SaveConverter::Result r) { + if (r.message.empty()) { + return; // cancelled + } + LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Import Complete" : "Save Import Failed", + r.message, "OK", "", nullptr, nullptr); + }); }, nullptr); }) @@ -200,12 +199,13 @@ void LighthouseMenu::AddMenuSettings() { .RaceDisable(false) .Callback([](WidgetInfo& info) { int slot = CVarGetInteger(CVAR_SETTING("SaveConvertSlot"), SaveConverter::kSlotAll); - SaveConverter::Result r = SaveConverter::PickAndExport(slot); - if (r.message.empty()) { - return; // cancelled - } - LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Export Complete" : "Save Export Failed", r.message, - "OK", "", nullptr, nullptr); + SaveConverter::PickAndExport(slot, [](SaveConverter::Result r) { + if (r.message.empty()) { + return; // cancelled + } + LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Export Complete" : "Save Export Failed", + r.message, "OK", "", nullptr, nullptr); + }); }) .Options(ButtonOptions().Tooltip( "Export the save for the game you're playing to a Banjo: Recompiled file. Use the slot above " @@ -261,21 +261,17 @@ void LighthouseMenu::AddMenuSettings() { .Options(ButtonOptions() .Size(Sizes::Inline) .Tooltip("Pick a Banjo-Kazooie ROM and extract only its dialog into a slim language pack.")); + + // Accessibility Options AddWidget(path, "Accessibility", WIDGET_SEPARATOR_TEXT); -#if defined(_WIN32) || defined(__APPLE__) || defined(ESPEAK) - AddWidget(path, "Text to Speech", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_SETTING("A11yTTS")) - .RaceDisable(false) - .Options(CheckboxOptions().Tooltip("Enables text to speech for in game dialog")); -#endif - AddWidget(path, "Disable Idle Camera Re-Centering", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_SETTING("A11yDisableIdleCam")) - .RaceDisable(false) - .Options(CheckboxOptions().Tooltip("Disables the automatic re-centering of the camera when idle.")); - AddWidget(path, "Disable Screen Flash for Finishing Blow", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_SETTING("A11yNoScreenFlashForFinishingBlow")) + AddWidget(path, "Disable Screen Shake", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("A11yDisableScreenShake")) .RaceDisable(false) - .Options(CheckboxOptions().Tooltip("Disables the white screen flash on enemy kill.")); + .Options(CheckboxOptions().Tooltip( + "Stops the camera shaking on impacts such as Beak Buster landings, boulders and boss attacks. " + "Controller rumble is unaffected.")); + + // Experimental Options AddWidget(path, "EXPERIMENTAL", WIDGET_SEPARATOR_TEXT).Options(TextOptions().Color(Colors::Orange)); AddWidget(path, "ImGui Menu Scaling", WIDGET_CVAR_COMBOBOX) .CVar(CVAR_SETTING("ImGuiScale")) @@ -293,41 +289,41 @@ void LighthouseMenu::AddMenuSettings() { path.column = SECTION_COLUMN_1; AddSidebarEntry("Settings", "Audio", 3); - AddWidget(path, "Master Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + AddWidget(path, "Master Volume", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_SETTING("Volume.Master")) .RaceDisable(false) - .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(40).ShowButtons(true).Format("")); - AddWidget(path, "Main Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - .CVar(CVAR_SETTING("Volume.MainMusic")) - .RaceDisable(false) - .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(40).ShowButtons(true).Format("%d%%")); + // AddWidget(path, "Main Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + // .CVar(CVAR_SETTING("Volume.MainMusic")) + // .RaceDisable(false) + // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, - // ((float)CVarGetInteger(CVAR_SETTING("Volume.MainMusic"), 100) / 100.0f)); - //}); - AddWidget(path, "Sub Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - .CVar(CVAR_SETTING("Volume.SubMusic")) - .RaceDisable(false) - .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + // Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, + // ((float)CVarGetInteger(CVAR_SETTING("Volume.MainMusic"), 100) / 100.0f)); + // }); + // AddWidget(path, "Sub Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + // .CVar(CVAR_SETTING("Volume.SubMusic")) + // .RaceDisable(false) + // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, - // ((float)CVarGetInteger(CVAR_SETTING("Volume.SubMusic"), 100) / 100.0f)); - //}); - AddWidget(path, "Fanfare Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - .CVar(CVAR_SETTING("Volume.Fanfare")) - .RaceDisable(false) - .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + // Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, + // ((float)CVarGetInteger(CVAR_SETTING("Volume.SubMusic"), 100) / 100.0f)); + // }); + // AddWidget(path, "Fanfare Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + // .CVar(CVAR_SETTING("Volume.Fanfare")) + // .RaceDisable(false) + // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_FANFARE, - // ((float)CVarGetInteger(CVAR_SETTING("Volume.Fanfare"), 100) / 100.0f)); - //}); - AddWidget(path, "Sound Effects Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - .CVar(CVAR_SETTING("Volume.SFX")) - .RaceDisable(false) - .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + // Audio_SetGameVolume(SEQ_PLAYER_FANFARE, + // ((float)CVarGetInteger(CVAR_SETTING("Volume.Fanfare"), 100) / 100.0f)); + // }); + // AddWidget(path, "Sound Effects Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + // .CVar(CVAR_SETTING("Volume.SFX")) + // .RaceDisable(false) + // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_SFX, ((float)CVarGetInteger(CVAR_SETTING("Volume.SFX"), 100) / 100.0f)); - //}); + // Audio_SetGameVolume(SEQ_PLAYER_SFX, ((float)CVarGetInteger(CVAR_SETTING("Volume.SFX"), 100) / 100.0f)); + // }); AddWidget(path, "Audio API (Needs reload)", WIDGET_AUDIO_BACKEND).RaceDisable(false); // Graphics Settings @@ -514,7 +510,8 @@ void LighthouseMenu::AddMenuSettings() { // Input Viewer path.sidebarName = "Input Viewer"; - AddSidebarEntry("Settings", path.sidebarName, 3); + path.column = SECTION_COLUMN_1; + AddSidebarEntry("Settings", path.sidebarName, 2); AddWidget(path, "Input Viewer", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Toggle Input Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("InputViewer")) diff --git a/src/port/UI/LighthouseModMenuWindow.cpp b/src/port/UI/LighthouseModMenuWindow.cpp index 90018371b..49b15e3e6 100644 --- a/src/port/UI/LighthouseModMenuWindow.cpp +++ b/src/port/UI/LighthouseModMenuWindow.cpp @@ -84,8 +84,8 @@ static std::vector sRomhackBaseMismatch; // Romhacks and universally shared mods get special folders // The lang folder is skipped in scans #define ROMHACKS_DIR "~romhacks" -#define SHARED_DIR "shared" -#define LANG_DIR "lang" +#define SHARED_DIR "~shared" +#define LANG_DIR "~lang" static std::string JoinModList(const std::vector& list) { std::string s; @@ -313,7 +313,7 @@ void UpdateModFiles(bool init, bool reset) { if (!IsValidExtension(p.path().extension().generic_string())) { continue; } - // Skip reserved folders (e.g. mods/lang/ language packs) — they + // Skip reserved folders (e.g. mods/~lang/ language packs) — they // aren't user-toggleable mods and must not appear in either menu. if (IsReservedModPath(modsPath, p.path())) { continue; @@ -466,7 +466,7 @@ static void DrawModInfo(std::string file) { using ModFilter = std::function; -static void DrawMods(bool enabled, const ModFilter& shown) { +static void DrawMods(bool enabled, const ModFilter& shown, bool alphabetical) { std::vector& selectedModFiles = GetModFiles(enabled); std::vector visible; @@ -482,10 +482,10 @@ static void DrawMods(bool enabled, const ModFilter& shown) { bool madeAnyChange = false; size_t switchFromIndex = 0; size_t switchToIndex = 0; + std::string pendingMoveFile; - // Highest priority (largest real index) draws at the top, matching the - // "top overrides bottom" rule. - for (size_t vpos = visible.size() - 1; vpos != SIZE_MAX; vpos--) { + for (size_t k = 0; k < visible.size(); k++) { + size_t vpos = alphabetical ? k : (visible.size() - 1 - k); size_t i = visible[vpos]; std::string file = selectedModFiles[i]; if (enabled) { @@ -496,14 +496,10 @@ static void DrawMods(bool enabled, const ModFilter& shown) { // (to the disabled list), disabled mods get an arrow pointing left. if (UIWidgets::StateButton((file + "_left_right").c_str(), enabled ? ICON_FA_ARROW_RIGHT : ICON_FA_ARROW_LEFT, ImVec2(25, 25), UIWidgets::ButtonOptions().Color(THEME_COLOR))) { - if (enabled) { - DisableMod(file); - } else { - EnableMod(file); - } + pendingMoveFile = file; } - if (enabled) { + if (enabled && !alphabetical) { const bool atTop = (vpos == visible.size() - 1); const bool atBottom = (vpos == 0); @@ -551,11 +547,19 @@ static void DrawMods(bool enabled, const ModFilter& shown) { std::iter_swap(selectedModFiles.begin() + switchFromIndex, selectedModFiles.begin() + switchToIndex); AfterModChange(); } + + if (!pendingMoveFile.empty()) { + if (enabled) { + DisableMod(pendingMoveFile); + } else { + EnableMod(pendingMoveFile); + } + } } static bool editing = false; -static void DrawModManager(const char* tableId, const ModFilter& shown) { +static void DrawModManager(const char* tableId, const ModFilter& shown, bool alphabetical = false) { auto editOpts = UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR); editOpts.Disabled(editing); editOpts.DisabledTooltip("Already editing..."); @@ -610,7 +614,7 @@ static void DrawModManager(const char* tableId, const ModFilter& shown) { ImGui::TableNextColumn(); if (ImGui::BeginChild("Enabled Mods", ImVec2(0, -8))) { - DrawMods(true, shown); + DrawMods(true, shown, alphabetical); ImGui::EndChild(); } @@ -618,7 +622,7 @@ static void DrawModManager(const char* tableId, const ModFilter& shown) { ImGui::TableNextColumn(); if (ImGui::BeginChild("Disabled Mods", ImVec2(0, -8))) { - DrawMods(false, shown); + DrawMods(false, shown, alphabetical); ImGui::EndChild(); } @@ -662,7 +666,10 @@ void LighthouseRomhackMenuWindow::DrawElement() { "Romhack overlays live in mods/~romhacks/. Changes require a restart, and only one\n" "romhack can be active at a time."); - DrawModManager("tableRomhacks", [](const std::string& name) { return IsRomhackOverlay(name); }); + // Romhacks are one-at-a-time, so there's no load order to preserve: list them + // alphabetically instead of by priority. + DrawModManager( + "tableRomhacks", [](const std::string& name) { return IsRomhackOverlay(name); }, true); } void LighthouseModMenuWindow::InitElement() { @@ -829,19 +836,13 @@ bool IsInlineModExtractionBusy() { return sInlineExtracting.load(); } -void RequestInlineModExtraction() { - if (sInlineExtracting.load()) { - return; - } - auto extractor = std::make_unique(); - if (!extractor->SelectGameFromUI()) { - return; - } +// Kick off the (detached) extraction worker for a ROM the user already picked + loaded. +static void BeginInlineExtraction(std::shared_ptr extractor, bool langPack) { sInlineFile = extractor->GetRomPath(); sInlineCount = 0; sInlineTotal = 0; sInlineResult = 0; - sInlineLangPack = false; + sInlineLangPack = langPack; sInlineExtracting = true; std::thread([ex = std::move(extractor)]() mutable { const bool ok = ex->GenerateOTR(sInlineCount, sInlineTotal, "bk"); @@ -850,49 +851,51 @@ void RequestInlineModExtraction() { }).detach(); } -void RequestInlineLanguagePackExtraction() { +// Shared body of the two public requests: pick a ROM, load it, and start extraction. Language packs +// add a couple of region gates before the common kickoff. The extractor is a shared_ptr so it stays +// alive across the async pick (captured in the callback) and the detached extraction thread. +static void StartInlineRomExtraction(bool langPack) { if (sInlineExtracting.load()) { return; } - auto extractor = std::make_unique(); - if (!extractor->SelectGameFromUI()) { - return; - } + auto extractor = std::make_shared(); + extractor->SelectGameFromUI([extractor, langPack](bool ok) { + if (!ok) { + return; // cancelled or failed to load + } + if (langPack) { + // Refuse a pack when we already have it as bk.o2r. + const std::string region = extractor->GetRegionSlug(); + if (region.empty()) { + LighthouseGui::RegisterPopup("Unrecognized ROM", + "That file isn't a recognized Banjo-Kazooie ROM, so no\n" + "language pack could be made from it.", + "OK", "", nullptr, nullptr); + return; + } + if (region == Lighthouse::BaseRegionSlug()) { + LighthouseGui::RegisterPopup("Already Have This Language", + "Your base game data (bk.o2r) already provides this region's\n" + "dialog, so there's no need to add it as a language pack.", + "OK", "", nullptr, nullptr); + return; + } + // Re-extracting a region overwrites its existing pack (e.g. to refresh it after an + // update), so a pre-existing mods/lang/bk.o2r is fine. + std::error_code ec; + std::filesystem::create_directories(Ship::Context::GetPathRelativeToAppDirectory("mods/lang"), ec); + extractor->SetDialogPack(true); + } + BeginInlineExtraction(extractor, langPack); + }); +} - // Refuse a pack when we already have it as bk.o2r. - const std::string region = extractor->GetRegionSlug(); - if (region.empty()) { - LighthouseGui::RegisterPopup("Unrecognized ROM", - "That file isn't a recognized Banjo-Kazooie ROM, so no\n" - "language pack could be made from it.", - "OK", "", nullptr, nullptr); - return; - } - if (region == Lighthouse::BaseRegionSlug()) { - LighthouseGui::RegisterPopup("Already Have This Language", - "Your base game data (bk.o2r) already provides this region's\n" - "dialog, so there's no need to add it as a language pack.", - "OK", "", nullptr, nullptr); - return; - } - // Re-extracting a region overwrites its existing pack (e.g. to refresh it - // after an update), so a pre-existing mods/lang/bk.o2r is fine. - const std::string langDir = Ship::Context::GetPathRelativeToAppDirectory("mods/lang"); - std::error_code ec; - std::filesystem::create_directories(langDir, ec); +void RequestInlineModExtraction() { + StartInlineRomExtraction(false); +} - extractor->SetDialogPack(true); - sInlineFile = extractor->GetRomPath(); - sInlineCount = 0; - sInlineTotal = 0; - sInlineResult = 0; - sInlineLangPack = true; - sInlineExtracting = true; - std::thread([ex = std::move(extractor)]() mutable { - const bool ok = ex->GenerateOTR(sInlineCount, sInlineTotal, "bk"); - sInlineResult = ok ? 1 : 2; - sInlineExtracting = false; - }).detach(); +void RequestInlineLanguagePackExtraction() { + StartInlineRomExtraction(true); } void DrawInlineModExtraction() { @@ -924,7 +927,7 @@ void DrawInlineModExtraction() { const std::string packPath = GameExtractor::sLastOutputPath; if (!packPath.empty() && GetArchiveManager()->AddArchive(packPath) == nullptr) { // Shouldn't happen for an o2r we just wrote; if it does, the pack is - // still in mods/lang and loads on the next launch. + // still in mods/~lang and loads on the next launch. SPDLOG_WARN("[Lang] Pack '{}' didn't register live; it will load on the next launch.", packPath); } Lighthouse::RescanLanguages(); diff --git a/src/port/UI/LighthouseModals.cpp b/src/port/UI/LighthouseModals.cpp index 05696e112..d3db2586b 100644 --- a/src/port/UI/LighthouseModals.cpp +++ b/src/port/UI/LighthouseModals.cpp @@ -33,7 +33,7 @@ void LighthouseModalWindow::DrawElement() { if (modals.size() > 0) { LighthouseModal curModal = modals.at(0); if (!ImGui::IsPopupOpen(curModal.title_.c_str())) { - ImVec2 center = ImGui::GetMainViewport()->GetCenter(); + ImVec2 center = ImGui::GetMainViewport()->GetWorkCenter(); ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGui::OpenPopup(curModal.title_.c_str()); } @@ -46,6 +46,11 @@ void LighthouseModalWindow::DrawElement() { ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) { + // Show the nav highlight on the default button (button1) the moment the popup opens, so a + // gamepad/keyboard user sees the selection immediately rather than after a first input. + if (ImGui::IsWindowAppearing()) { + ImGui::SetNavCursorVisible(true); + } ImGui::Text("%s", curModal.message_.c_str()); UIWidgets::PushStyleButton(THEME_COLOR); if (ImGui::Button(curModal.button1_.c_str())) { diff --git a/src/port/UI/Menu.cpp b/src/port/UI/Menu.cpp index a79fef5f0..778aff569 100644 --- a/src/port/UI/Menu.cpp +++ b/src/port/UI/Menu.cpp @@ -15,7 +15,6 @@ std::vector windowTypeSizes = { {} }; extern std::unordered_map warpPointSceneList; -extern void Warp(); namespace LighthouseGui { extern std::shared_ptr mModalWindow; @@ -114,6 +113,13 @@ void Menu::UpdateWindowBackendObjects() { } } +void Menu::UpdateAudioBackendObjects() { + availableAudioBackends = Ship::Context::GetRawInstance()->GetAudio()->GetAvailableAudioBackends(); + for (auto& backend : *availableAudioBackends) { + availableAudioBackendsMap[backend] = audioBackendsMap.at(backend); + } +} + bool Menu::IsMenuPopped() { return popped; } @@ -136,6 +142,7 @@ void Menu::InitElement() { menuThemeIndex = static_cast(CVarGetInteger(CVAR_SETTING("Menu.Theme"), defaultThemeIndex)); UpdateWindowBackendObjects(); + UpdateAudioBackendObjects(); } void Menu::UpdateElement() { @@ -249,8 +256,9 @@ uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { entry.info.type == WIDGET_SEPARATOR_TEXT || entry.info.isHidden || entry.info.hideInSearch) { continue; } - std::string widgetStr = - entry.info.name + entry.info.options->tooltip + entry.extraTerms + entry.sidebarName; + const char* extraTooltip = entry.info.options->tooltip; + std::string widgetStr = entry.info.name + std::string(extraTooltip != nullptr ? extraTooltip : "") + + entry.extraTerms + entry.sidebarName; std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); if (widgetStr.find(menuSearchText) != std::string::npos) { @@ -342,10 +350,9 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me UIWidgets::ComboboxOptions options = {}; options.color = menuThemeIndex; options.tooltip = "Sets the audio API used by the game. Requires a relaunch to take effect."; - options.disabled = - Ship::Context::GetRawInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1; + options.disabled = availableAudioBackends->size() <= 1; options.disabledTooltip = "Only one audio API is available on this platform."; - if (UIWidgets::Combobox("Audio API", ¤tAudioBackend, audioBackendsMap, options)) { + if (UIWidgets::Combobox("Audio API", ¤tAudioBackend, availableAudioBackendsMap, options)) { Ship::Context::GetRawInstance()->GetAudio()->SetCurrentAudioBackend(currentAudioBackend); } } break; diff --git a/src/port/UI/Menu.h b/src/port/UI/Menu.h index f32c349d6..b1b8378e3 100644 --- a/src/port/UI/Menu.h +++ b/src/port/UI/Menu.h @@ -20,6 +20,7 @@ class Menu : public GuiWindow { void InsertSidebarSearch(); void RemoveSidebarSearch(); void UpdateWindowBackendObjects(); + void UpdateAudioBackendObjects(); bool IsMenuPopped(); UIWidgets::Colors GetMenuThemeColor(); @@ -41,6 +42,8 @@ class Menu : public GuiWindow { std::shared_ptr> availableWindowBackends; std::unordered_map availableWindowBackendsMap; Fast::WindowBackend configWindowBackend; + std::shared_ptr> availableAudioBackends; + std::unordered_map availableAudioBackendsMap; std::unordered_map disabledMap; std::vector disabledVector; diff --git a/src/port/UI/MenuTypes.h b/src/port/UI/MenuTypes.h index b0ef5b269..f86cf363b 100644 --- a/src/port/UI/MenuTypes.h +++ b/src/port/UI/MenuTypes.h @@ -23,6 +23,7 @@ typedef enum { DISABLE_FOR_SINGLE_LANGUAGE, DISABLE_DURING_PARADE, DISABLE_FOR_ROMHACK, + FORCED_ON_FOR_ANCHOR_CONNECTED, } DisableOption; struct WidgetInfo; @@ -265,6 +266,7 @@ struct MainMenuEntry { static const std::unordered_map audioBackendsMap = { { Ship::AudioBackend::WASAPI, "Windows Audio Session API" }, + { Ship::AudioBackend::COREAUDIO, "Core Audio" }, { Ship::AudioBackend::SDL, "SDL" }, { Ship::AudioBackend::NUL, "Null" }, }; diff --git a/src/port/UI/Notification.cpp b/src/port/UI/Notification.cpp index e7380efb0..cb89c0311 100644 --- a/src/port/UI/Notification.cpp +++ b/src/port/UI/Notification.cpp @@ -2,11 +2,15 @@ #include "port/UI/cvar_prefixes.h" #include #include +#include +#include namespace Notification { static uint32_t nextId = 0; static std::vector notifications = {}; +// Emit() runs on the game thread; Draw()/UpdateElement() run on the render thread. +static std::mutex notificationsMutex; #define ABS(x) ((x) >= 0 ? (x) : -(x)) @@ -46,9 +50,17 @@ void Window::Draw() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f * CVarGetFloat(CVAR_SETTING("Notifications.Size"), 1.8f), 8.0f)); - for (size_t index = 0; index < notifications.size(); ++index) { - auto& notification = notifications[index]; - int inverseIndex = -ABS((int)index - (int)(notifications.size() - 1)); + // Render from a snapshot rather than the live vector, so a concurrent Emit() can + // reallocate without invalidating anything this loop is reading. + std::vector snapshot; + { + std::lock_guard lock(notificationsMutex); + snapshot = notifications; + } + + for (size_t index = 0; index < snapshot.size(); ++index) { + auto& notification = snapshot[index]; + int inverseIndex = -ABS((int)index - (int)(snapshot.size() - 1)); ImGui::SetNextWindowViewport(vp->ID); if (notification.remainingTime < 4.0f) { @@ -114,6 +126,7 @@ void Window::Draw() { } void Window::UpdateElement() { + std::lock_guard lock(notificationsMutex); for (int index = 0; index < notifications.size(); ++index) { auto& notification = notifications[index]; @@ -129,11 +142,14 @@ void Window::UpdateElement() { } void Emit(Options notification) { - notification.id = nextId++; if (notification.remainingTime == 0.0f) { notification.remainingTime = CVarGetFloat(CVAR_SETTING("Notifications.Duration"), 10.0f); } - notifications.push_back(notification); + { + std::lock_guard lock(notificationsMutex); + notification.id = nextId++; + notifications.push_back(notification); + } if (!notification.mute) { // TODO: play game notification sound } diff --git a/src/port/UI/ResolutionEditor.cpp b/src/port/UI/ResolutionEditor.cpp index 433f8cc41..305131005 100644 --- a/src/port/UI/ResolutionEditor.cpp +++ b/src/port/UI/ResolutionEditor.cpp @@ -404,13 +404,13 @@ void RegisterResolutionWidgets() { .CVar(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled") .RaceDisable(false); // Error/Warning display - mLighthouseMenu - ->AddWidget(path, ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring.", - WIDGET_TEXT) - .RaceDisable(false) - .PreFunc( - [](WidgetInfo& info) { info.isHidden = !(!CVarGetInteger(CVAR_LOW_RES_MODE, 0) && IsDroppingFrames()); }) - .Options(TextOptions().Color(Colors::Orange)); + // LighthouseMenu + // ->AddWidget(path, ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring.", + // WIDGET_TEXT) + // .RaceDisable(false) + // .PreFunc( + // [](WidgetInfo& info) { info.isHidden = !(!CVarGetInteger(CVAR_LOW_RES_MODE, 0) && IsDroppingFrames()); }) + // .Options(TextOptions().Color(Colors::Orange)); mLighthouseMenu->AddWidget(path, ICON_FA_QUESTION_CIRCLE " \"N64 Mode\" is overriding these settings.", WIDGET_TEXT) .RaceDisable(false) .PreFunc([](WidgetInfo& info) { info.isHidden = !CVarGetInteger(CVAR_LOW_RES_MODE, 0); }) @@ -589,13 +589,13 @@ void UpdateResolutionVars() { disabled_pixelCount = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0); } -bool IsDroppingFrames() { - // a rather imprecise way of checking for frame drops. - // but it's mostly there to inform the player of large drops. - const short targetFPS = GameEngine::Instance->GetInterpolationFPS(); - const float threshold = targetFPS / 20.0f + 4.1f; - return ImGui::GetIO().Framerate < targetFPS - threshold; -} +// bool IsDroppingFrames() { +// // a rather imprecise way of checking for frame drops. +// // but it's mostly there to inform the player of large drops. +// const short targetFPS = GameEngine::Instance->GetInterpolationFPS(); +// const float threshold = targetFPS / 20.0f + 4.1f; +// return ImGui::GetIO().Framerate < targetFPS - threshold; +// } static RegisterMenuUpdateFunc updateFunc(UpdateResolutionVars, "Settings", "Graphics"); static RegisterMenuInitFunc menuInitFunc(RegisterResolutionWidgets); diff --git a/src/port/UI/ResolutionEditor.h b/src/port/UI/ResolutionEditor.h index a640b1e2c..316680534 100644 --- a/src/port/UI/ResolutionEditor.h +++ b/src/port/UI/ResolutionEditor.h @@ -2,7 +2,7 @@ #define RESOLUTIONEDITOR_H namespace LighthouseGui { -bool IsDroppingFrames(); +// bool IsDroppingFrames(); void RegisterResolutionWidgets(); void UpdateResolutionVars(); } // namespace LighthouseGui diff --git a/src/port/UI/UIWidgets.cpp b/src/port/UI/UIWidgets.cpp index e2b670a1f..e41ab88db 100644 --- a/src/port/UI/UIWidgets.cpp +++ b/src/port/UI/UIWidgets.cpp @@ -529,7 +529,7 @@ bool SliderInt(const char* label, int32_t* value, const IntSliderOptions& option } ImGui::AlignTextToFramePadding(); if (options.alignment == ComponentAlignments::Right && options.labelPosition != LabelPositions::None) { - ImGui::Text(label, *value); + ImGui::Text("%s", label); if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(ImGui::GetContentRegionAvail().x - width); @@ -540,7 +540,7 @@ bool SliderInt(const char* label, int32_t* value, const IntSliderOptions& option } } else if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text(label, *value); + ImGui::Text("%s", label); } } if (options.showButtons) { @@ -585,11 +585,11 @@ bool SliderInt(const char* label, int32_t* value, const IntSliderOptions& option if (options.alignment == ComponentAlignments::Left && options.labelPosition != LabelPositions::None) { if (options.labelPosition == LabelPositions::Near) { ImGui::SameLine(); - ImGui::Text(label, *value); + ImGui::Text("%s", label); } else if (options.labelPosition == LabelPositions::Far) { ImGui::SameLine(ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize(label).x + ImGui::GetStyle().ItemSpacing.x); - ImGui::Text(label, *value); + ImGui::Text("%s", label); } } PopStyleSlider(); @@ -665,7 +665,7 @@ bool SliderFloat(const char* label, float* value, const FloatSliderOptions& opti } ImGui::AlignTextToFramePadding(); if (options.alignment == ComponentAlignments::Right) { - ImGui::Text(label, *value); + ImGui::Text("%s", label); if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(ImGui::GetContentRegionAvail().x - width); @@ -678,7 +678,7 @@ bool SliderFloat(const char* label, float* value, const FloatSliderOptions& opti } } else if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text(label, *value); + ImGui::Text("%s", label); } } if (options.showButtons) { @@ -717,10 +717,10 @@ bool SliderFloat(const char* label, float* value, const FloatSliderOptions& opti if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Near) { ImGui::SameLine(); - ImGui::Text(label, *value); + ImGui::Text("%s", label); } else if (options.labelPosition == LabelPositions::Far || options.labelPosition == LabelPositions::None) { ImGui::SameLine(ImGui::GetContentRegionAvail().x - labelSpacing); - ImGui::Text(label, *value); + ImGui::Text("%s", label); } } PopStyleSlider(); @@ -771,13 +771,13 @@ bool InputString(const char* label, std::string* value, const InputOptions& opti if (labelSize.x != 0) { if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text(label, *value->c_str()); + ImGui::Text("%s", label); } } else if (options.alignment == ComponentAlignments::Right) { if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(width - ImGui::CalcTextSize(label).x); - ImGui::Text(label, *value->c_str()); + ImGui::Text("%s", label); } } } @@ -834,13 +834,13 @@ bool InputInt(const char* label, int32_t* value, const InputOptions& options) { float width = (options.size == ImVec2(0, 0)) ? ImGui::GetContentRegionAvail().x : options.size.x; if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text(label, *value); + ImGui::Text("%s", label); } } else if (options.alignment == ComponentAlignments::Right) { if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(width - ImGui::CalcTextSize(label).x); - ImGui::Text(label, *value); + ImGui::Text("%s", label); } } ImGui::SetNextItemWidth(width); @@ -903,7 +903,8 @@ bool CVarColorPicker(const char* label, const char* cvarName, Color_RGBA8 defaul ImGui::AlignTextToFramePadding(); if (showReset) { ImGui::SameLine(); - std::string uniqueTag = "Reset##" + std::string(label); + // Tag off the CVar, not the label. + std::string uniqueTag = "Reset##" + std::string(cvarName) + ".Reset"; if (UIWidgets::Button(uniqueTag.c_str(), UIWidgets::ButtonOptions({ { .tooltip = "Resets this color to its default value" } }) .Color(themeColor) @@ -920,7 +921,7 @@ bool CVarColorPicker(const char* label, const char* cvarName, Color_RGBA8 defaul } if (showRandom) { ImGui::SameLine(); - std::string uniqueTag = "Random##" + std::string(label); + std::string uniqueTag = "Random##" + std::string(cvarName) + ".Random"; if (UIWidgets::Button(uniqueTag.c_str(), UIWidgets::ButtonOptions({ { .tooltip = "Generates a random color value to use" } }) .Color(themeColor) diff --git a/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp b/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp index aad0f5b07..5d2c7c7a4 100644 --- a/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp +++ b/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp @@ -7,9 +7,7 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -extern "C" { #include "enums.h" -} #define CVAR_DISABLE_SNACKER CVAR_ENHANCEMENT("Gameplay.DisableSnackerSpawn") #define CVAR CVarGetInteger(CVAR_DISABLE_SNACKER, 0) diff --git a/src/port/enhancements/Gameplay/EasierMrVile.cpp b/src/port/enhancements/Gameplay/EasierMrVile.cpp index 9e3b89d18..94ce8d771 100644 --- a/src/port/enhancements/Gameplay/EasierMrVile.cpp +++ b/src/port/enhancements/Gameplay/EasierMrVile.cpp @@ -7,9 +7,7 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -extern "C" { #include "enums.h" -} #define CVAR_EASIER_MR_VILE CVAR_ENHANCEMENT("EasierMrVile") #define CVAR CVarGetInteger(CVAR_EASIER_MR_VILE, 0) diff --git a/src/unused/datalookup.c b/src/unused/datalookup.c index 6da37f5f2..c3033cebc 100644 --- a/src/unused/datalookup.c +++ b/src/unused/datalookup.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (unknown decomp origin - data lookup) +// BanjoDecomp: core2/code_5FD80.c #include #include "functions.h" #include "variables.h" diff --git a/src/unused/debug_assert.c b/src/unused/debug_assert.c index 4a0de56a5..4bba81053 100644 --- a/src/unused/debug_assert.c +++ b/src/unused/debug_assert.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/ultra/debug/assert.c +// BanjoDecomp: core2/ultra/debug/assert.c (kept in unused/, not built on PC) #include #include "functions.h" #include "variables.h" diff --git a/src/unused/debug_boxdraw.c b/src/unused/debug_boxdraw.c index c49e57865..8dec67ea0 100644 --- a/src/unused/debug_boxdraw.c +++ b/src/unused/debug_boxdraw.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (unknown decomp origin - unused debug drawing) +// BanjoDecomp: core1/stub_3A70.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/unused/unused_block.c b/src/unused/unused_block.c index 9f2f5b6a0..a71bdf874 100644 --- a/src/unused/unused_block.c +++ b/src/unused/unused_block.c @@ -1,4 +1,4 @@ -// BanjoDecomp: (unknown decomp origin - unused block) +// BanjoDecomp: core2/code_B7F40.c #include #include "functions.h" #include "variables.h" From 78a46da69c123d997762f0c7497c114e45c8410e Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 7 Aug 2026 22:18:26 +0200 Subject: [PATCH 8/8] Revert "Custom collectible (#439)" This reverts commit 127a2824f16d279009af353c87045e118994b833. --- .github/macports.yml | 2 - .github/workflows/linux.yml | 48 + .github/workflows/mac.yml | 23 + .github/workflows/main.yml | 47 +- .github/workflows/switch.yml | 38 + .github/workflows/windows.yml | 20 + .gitmodules | 2 +- CMakeLists.txt | 24 +- README.md | 81 +- Torch | 2 +- assets/yaml/jp/rev0/soundfont.yaml | 4 +- assets/yaml/pal/rev0/soundfont.yaml | 4 +- assets/yaml/us/rev0/soundfont.yaml | 4 +- assets/yaml/us/rev1/soundfont.yaml | 4 +- cmake/GenerateFlagNames.cmake | 123 -- config.yml | 6 +- docs/BUILDING.md | 12 +- docs/modding/LANGUAGE PACKS.md | 71 +- docs/poweredbylus.darkmode.png | Bin 213165 -> 0 bytes docs/poweredbylus.lightmode.png | Bin 210989 -> 0 bytes include/actor.h | 4 - include/bk_math.h | 2 - include/bool.h | 11 - include/bs_funcs.h | 278 ++- include/checksums.h | 115 -- include/core1/core1.h | 59 +- include/core1/main.h | 12 +- include/core1/ml.h | 10 +- include/core1/sns.h | 8 - include/core1/sprite.h | 8 - include/core1/viewport.h | 10 +- include/core2/ba/carry.h | 2 +- include/core2/ba/model.h | 8 - include/core2/ba/physics.h | 10 - include/core2/ba/timer.h | 2 +- include/core2/bonetransform.h | 8 - include/core2/commonParticle.h | 8 - include/core2/modelRender.h | 2 +- include/core2/particle.h | 8 - .../storage.h => include/core2/quiz_storage.h | 14 +- include/core2/statetimer.h | 8 - include/core2/timedfunc.h | 2 - include/enums.h | 743 +++---- include/file_and_line.h | 19 +- include/functions.h | 956 ++++----- include/gc/gctransition.h | 10 +- include/model.h | 8 - include/prop.h | 17 +- include/structs.h | 9 - include/variables.h | 8 - include/version.h | 3 - lib/ultralib/include/PR/gbi.h | 2 +- .../include/{ultra_assert.h => assert.h} | 0 libultraship | 2 +- port/anim/lighthouse_shrug | Bin 408 -> 0 bytes port/anim/lighthouse_walk | Bin 288 -> 0 bytes port/models/lighthouse | Bin 5688 -> 0 bytes port/models/lighthouse_GEO | Bin 212 -> 0 bytes port/models/lighthouse_VTX | Bin 7684 -> 0 bytes port/models/lighthouse_tex_0 | Bin 1104 -> 0 bytes port/models/lighthouse_tex_1 | Bin 1104 -> 0 bytes port/models/lighthouse_tex_2 | Bin 1104 -> 0 bytes .../gArchipelagoItemDL | 16 - .../gArchipelagoItemDL_tri_0 | 56 - .../gArchipelagoItemDL_tri_1 | 57 - .../gArchipelagoItemDL_tri_2 | 57 - .../gArchipelagoItemDL_tri_3 | 57 - .../gArchipelagoItemDL_tri_4 | 57 - .../gArchipelagoItemDL_tri_5 | 56 - .../gArchipelagoItemDL_tri_6 | 56 - .../gArchipelagoItemDL_vtx_0 | 64 - .../gArchipelagoItemDL_vtx_1 | 77 - .../gArchipelagoItemDL_vtx_2 | 70 - .../gArchipelagoItemDL_vtx_3 | 68 - .../gArchipelagoItemDL_vtx_4 | 69 - .../gArchipelagoItemDL_vtx_5 | 64 - .../gArchipelagoItemDL_vtx_6 | 64 - .../gArchipelagoJunkDL | 16 - .../gArchipelagoJunkDL_tri_0 | 56 - .../gArchipelagoJunkDL_tri_1 | 57 - .../gArchipelagoJunkDL_tri_2 | 57 - .../gArchipelagoJunkDL_tri_3 | 57 - .../gArchipelagoJunkDL_tri_4 | 57 - .../gArchipelagoJunkDL_tri_5 | 56 - .../gArchipelagoJunkDL_tri_6 | 56 - .../gArchipelagoJunkDL_vtx_0 | 64 - .../gArchipelagoJunkDL_vtx_1 | 77 - .../gArchipelagoJunkDL_vtx_2 | 70 - .../gArchipelagoJunkDL_vtx_3 | 68 - .../gArchipelagoJunkDL_vtx_4 | 69 - .../gArchipelagoJunkDL_vtx_5 | 64 - .../gArchipelagoJunkDL_vtx_6 | 64 - .../gArchipelagoProgressiveDL | 18 - .../gArchipelagoProgressiveDL_tri_0 | 56 - .../gArchipelagoProgressiveDL_tri_1 | 57 - .../gArchipelagoProgressiveDL_tri_2 | 57 - .../gArchipelagoProgressiveDL_tri_3 | 57 - .../gArchipelagoProgressiveDL_tri_4 | 57 - .../gArchipelagoProgressiveDL_tri_5 | 56 - .../gArchipelagoProgressiveDL_tri_6 | 41 - .../gArchipelagoProgressiveDL_tri_7 | 41 - .../gArchipelagoProgressiveDL_vtx_0 | 64 - .../gArchipelagoProgressiveDL_vtx_1 | 77 - .../gArchipelagoProgressiveDL_vtx_2 | 70 - .../gArchipelagoProgressiveDL_vtx_3 | 68 - .../gArchipelagoProgressiveDL_vtx_4 | 69 - .../gArchipelagoProgressiveDL_vtx_5 | 64 - .../gArchipelagoProgressiveDL_vtx_6 | 39 - .../gArchipelagoProgressiveDL_vtx_7 | 39 - .../mat_gArchipelagoItemDL_black | 12 - .../mat_gArchipelagoItemDL_blue | 12 - .../mat_gArchipelagoItemDL_green | 12 - .../mat_gArchipelagoItemDL_orange | 12 - .../mat_gArchipelagoItemDL_outline | 12 - .../mat_gArchipelagoItemDL_pink | 12 - .../mat_gArchipelagoItemDL_purple | 12 - .../mat_gArchipelagoItemDL_red | 12 - .../mat_gArchipelagoItemDL_yellow | 12 - .../mat_gArchipelagoJunkDL_black_junk | 12 - .../mat_gArchipelagoJunkDL_blue_junk | 12 - .../mat_gArchipelagoJunkDL_green_junk | 12 - .../mat_gArchipelagoJunkDL_grey_blue | 12 - .../mat_gArchipelagoJunkDL_grey_green | 12 - .../mat_gArchipelagoJunkDL_grey_orange | 12 - .../mat_gArchipelagoJunkDL_grey_outline | 12 - .../mat_gArchipelagoJunkDL_grey_pink | 12 - .../mat_gArchipelagoJunkDL_grey_red | 12 - .../mat_gArchipelagoJunkDL_grey_yellow | 12 - .../mat_gArchipelagoJunkDL_orange_junk | 12 - .../mat_gArchipelagoJunkDL_purple_junk | 12 - .../mat_gArchipelagoJunkDL_red_junk | 12 - .../mat_gArchipelagoJunkDL_yellow_junk | 12 - ...pelagoProgressiveDL_arrow_gold_progressive | 12 - ...ArchipelagoProgressiveDL_black_progressive | 12 - ...gArchipelagoProgressiveDL_blue_progressive | 12 - ...ArchipelagoProgressiveDL_green_progressive | 12 - ...rchipelagoProgressiveDL_orange_progressive | 12 - ...ArchipelagoProgressiveDL_progressive_arrow | 12 - ...gArchipelagoProgressiveDL_progressive_blue | 12 - ...ArchipelagoProgressiveDL_progressive_green | 12 - ...rchipelagoProgressiveDL_progressive_orange | 12 - ...chipelagoProgressiveDL_progressive_outline | 12 - ...gArchipelagoProgressiveDL_progressive_pink | 12 - ..._gArchipelagoProgressiveDL_progressive_red | 12 - ...rchipelagoProgressiveDL_progressive_yellow | 12 - ...rchipelagoProgressiveDL_purple_progressive | 12 - ..._gArchipelagoProgressiveDL_red_progressive | 12 - ...rchipelagoProgressiveDL_yellow_progressive | 12 - .../objects/object_archipelago_item/model.xml | 0 port/textures/icons/g2ShipIcon.png | Bin 0 -> 13286 bytes port/textures/intro/xylophone | Bin 131164 -> 0 bytes port/textures/mapping-xbox.png | Bin 79348 -> 0 bytes .../{bgsspawnqueue.c => actor_spawninit.c} | 12 +- src/BGS/bss_pad.c | 2 + src/BGS/ch/{choirturtle.c => choir_turtle.c} | 6 +- src/BGS/ch/croctus.c | 211 +- src/BGS/ch/frogminigame.c | 31 +- src/BGS/ch/leafboat.c | 4 +- src/BGS/ch/mrvile.c | 106 +- src/BGS/ch/mudhut.c | 53 +- src/BGS/ch/pinkegg.c | 27 +- src/BGS/ch/swampswitch.c | 8 +- src/BGS/ch/tanktup.c | 291 ++- src/BGS/ch/{tanktuplegs.c => tanktup_legs.c} | 19 +- src/BGS/ch/tiptup.c | 328 +-- src/BGS/ch/yellowflibbit.c | 1 - src/BGS/ch/yumblie.c | 6 +- src/BGS/checksums.c | 7 - src/BGS/crc.c | 9 +- src/BGS/{mrvileminigame.c => minigame_vile.c} | 476 ++--- src/CC/{ccspawnqueue.c => actor_spawninit.c} | 2 +- src/CC/bss_pad.c | 2 + src/CC/ch/{ccgrates.c => clanker.c} | 16 +- src/CC/ch/clankertoothext.c | 48 +- src/CC/ch/{clankerkey.c => key.c} | 18 +- src/CC/ch/{clankerscrew.c => screw.c} | 18 +- src/CC/ch/tooth.c | 3 - src/CC/checksums.c | 7 - src/CC/crc.c | 10 +- src/CC/ma/clanker.c | 451 ---- src/CC/ma/clankerrings.c | 130 -- src/CC/minigame_rings.c | 115 ++ src/CC/model_renderstate.c | 24 +- src/CC/platform_physics.c | 441 ++++ src/CCW/actor_spawninit.c | 157 ++ src/CCW/bss_pad.c | 2 + src/CCW/ccwspawnqueue.c | 229 --- src/CCW/ch/acorn.c | 140 +- src/CCW/ch/adulteyrie.c | 129 -- src/CCW/ch/beanstalk.c | 239 --- src/CCW/ch/caterpillar.c | 152 +- src/CCW/ch/cutsceneadulteyrie.c | 114 -- src/CCW/ch/deadbeanstalk.c | 14 +- src/CCW/ch/deadsnarebear.c | 25 - src/CCW/ch/eyrie_baby.c | 301 +++ src/CCW/ch/eyrie_egg.c | 70 + src/CCW/ch/eyrie_summer.c | 120 ++ src/CCW/ch/eyrie_winter.c | 105 + src/CCW/ch/eyrieegg.c | 94 - src/CCW/ch/fairy.c | 129 ++ src/CCW/ch/gnawty.c | 143 ++ src/CCW/ch/gnawtyboulder.c | 55 +- src/CCW/ch/{ccwgobi.c => gobi_ccw.c} | 143 +- src/CCW/ch/grublinhood.c | 45 +- src/CCW/ch/indoorsgnawty.c | 98 - src/CCW/ch/nabnut_autumn.c | 172 ++ src/CCW/ch/nabnut_dialog.c | 85 + src/CCW/ch/nabnut_spring.c | 97 + .../ch/{bellyfullnabnut.c => nabnut_summer.c} | 52 +- src/CCW/ch/nabnut_winter.c | 124 ++ src/CCW/ch/outsideautumnnabnut.c | 226 -- src/CCW/ch/seasonswitchdoors.c | 245 --- src/CCW/ch/snarebear.c | 138 +- src/CCW/ch/snore.c | 28 +- src/CCW/ch/springnabnut.c | 110 - src/CCW/ch/summeroutsidegnawty.c | 160 -- src/CCW/ch/swimminggnawty.c | 140 -- src/CCW/ch/vacationtexttrigger.c | 2 +- src/CCW/ch/zubba.c | 216 ++ src/CCW/ch/zubba_hive_npc.c | 133 ++ src/CCW/ch/zubbadoor.c | 37 +- src/CCW/ch/zubbahoneylump.c | 244 --- src/CCW/checksums.c | 7 - src/CCW/eyrie_baby.c | 382 ---- src/CCW/flower.c | 170 ++ src/CCW/minigame_zubba.c | 221 ++ src/CCW/nabnut_winter.c | 174 -- src/CCW/seasonal_switch.c | 171 ++ src/CCW/snarebear_proximity.c | 122 ++ src/CCW/zubba.c | 240 --- src/CCW/zubba_hive_npc.c | 157 -- src/{fight => FINALE/ch}/chbossjinjo.c | 2 +- src/{fight => FINALE/ch}/chbossjinjobase.c | 10 +- src/{fight => FINALE/ch}/chbossshadow.c | 2 +- src/{fight => FINALE/ch}/chfinalboss.c | 111 +- src/{fight => FINALE/ch}/chjinjonator.c | 2 +- src/{fight => FINALE/ch}/chjinjonatorbase.c | 52 +- src/{fight => FINALE}/chgreenblast.c | 0 src/{fight => FINALE}/chspellbarrier.c | 0 src/{fight => FINALE}/chspellfireball.c | 0 src/{fight => FINALE}/chstonejinjo.c | 0 src/{fight => FINALE}/fight.c | 2 + src/{fight => FINALE}/fight.h | 36 +- src/FP/{fpspawnqueue.c => actor_spawninit.c} | 4 +- src/FP/bss_pad.c | 2 + src/FP/ch/bearcub.c | 68 +- src/FP/ch/boggy1.c | 12 +- src/FP/ch/boggy2.c | 52 +- src/FP/ch/boggy3.c | 18 +- src/FP/ch/cavewozza.c | 10 +- src/FP/ch/racesled.c | 2 +- src/FP/ch/snowmanbutton.c | 18 +- src/FP/ch/twinkly.c | 10 +- src/FP/ch/twinklybox.c | 16 +- src/FP/ch/twinklymuncher.c | 6 +- src/FP/ch/wozza.c | 14 +- src/FP/{ => ch}/wozza_fire.c | 0 src/FP/ch/xmastree.c | 82 +- src/FP/ch/xmastreeice.c | 28 - src/FP/ch/xmastreestar.c | 4 +- src/FP/ch/xmastreeswitch.c | 4 +- src/FP/checksums.c | 7 - src/FP/{ma => mapstate}/slalom.c | 26 +- .../slalom2ctrl.c} | 8 +- .../slalomctrl.c} | 8 +- src/FP/{ma => mapstate}/snowbutton.c | 0 src/FP/{ma => mapstate}/snowy.c | 0 src/GV/{gvspawnqueue.c => actor_spawninit.c} | 80 +- src/GV/bss_pad.c | 2 + src/GV/ch/ancientone.c | 65 +- src/GV/ch/buriedpyramid.c | 9 +- src/GV/{ => ch}/cactus.c | 0 src/GV/{ => ch}/carpet1.c | 0 src/GV/{ => ch}/carpet2.c | 12 +- .../carpet_shadow.c} | 19 +- src/GV/ch/{eggpot.c => egg_pot.c} | 2 +- src/GV/ch/gobi1.c | 6 +- src/GV/ch/gobi2.c | 8 +- src/GV/ch/gobi3.c | 5 +- src/GV/ch/gobirock.c | 2 +- src/GV/ch/gobirope.c | 2 +- src/GV/ch/grabba.c | 12 +- src/GV/{ => ch}/handshadow.c | 0 src/GV/ch/histup.c | 20 +- src/GV/ch/jinxy.c | 158 ++ src/GV/{ => ch}/jinxy_head.c | 0 src/GV/ch/mummum.c | 2 +- src/GV/{ => ch}/rubee.c | 64 +- src/GV/ch/sarcophagus.c | 2 +- src/GV/ch/slappa.c | 2 +- src/GV/ch/toots.c | 2 +- src/GV/ch/trunker.c | 6 +- src/GV/checksums.c | 7 - src/GV/crc.c | 10 +- src/GV/gv_helpers.c | 14 +- src/GV/magiccarpet2.c | 171 -- src/GV/matchinggame.c | 6 +- src/GV/{ch => }/mazectrl.c | 16 +- src/GV/pyramid_raise.c | 164 +- .../{sandybutteggtoll.c => pyramid_trigger.c} | 13 +- src/GV/smoke_particle.c | 4 +- src/GV/water_pyramidrot.c | 20 +- .../actor_spawninit.c} | 649 +----- src/LAIR/bss_pad.c | 2 + src/{lair => LAIR}/ch/brentilda.c | 9 +- src/{lair => LAIR}/ch/cauldron.c | 8 +- src/{lair => LAIR}/ch/cheato.c | 8 +- src/{lair => LAIR/ch}/fall_damagedetect.c | 0 src/{lair => LAIR/ch}/ff_lava_fireball.c | 0 .../ch}/ff_lava_fireball_actor.c | 0 src/{lair => LAIR}/ch/gruntling.c | 2 +- .../ch/grunty_final.c} | 8 +- .../refillpillow.c => LAIR/ch/item_pillows.c} | 6 +- .../ch/minigame_ffprize.c} | 6 +- src/{lair => LAIR/ch}/tooty_parade.c | 0 src/{lair => LAIR}/ff_manager.c | 42 +- src/{lair => LAIR}/jigsawpicture.c | 121 +- src/MM/{mmspawnqueue.c => actor_spawninit.c} | 2 +- src/MM/ch/chimpystump.c | 14 +- src/MM/ch/conga.c | 198 +- src/MM/ch/conga.h | 11 - src/MM/ch/hut.c | 69 +- src/MM/ch/juju.c | 3 +- src/MM/ch/jujuhitbox.c | 21 +- src/MM/ch/lmonkey.c | 14 +- src/MM/ch/orange.c | 2 +- src/MM/ch/orangepad.c | 159 +- src/MM/ch/orangepad.h | 14 - src/MM/checksums.c | 7 - src/MM/crc.c | 8 +- .../{mmmspawnqueue.c => actor_spawninit.c} | 229 +-- src/MMM/bathroom_particles.c | 6 +- src/MMM/bss_pad.c | 2 + src/MMM/ch/{cemetarypot.c => flowerpot.c} | 18 +- src/MMM/ch/{skeleton.c => limbo.c} | 6 +- src/MMM/ch/loggo.c | 10 +- src/MMM/ch/napper.c | 16 +- src/MMM/ch/portrait.c | 4 +- .../{portraitchompa.c => portrait_chompa.c} | 6 +- src/MMM/ch/tumblar.c | 8 +- src/MMM/checksums.c | 7 - src/MMM/crc.c | 9 +- src/MMM/minigame_organ.c | 10 +- src/MMM/minigame_shed.c | 2 +- src/MMM/napper_room.c | 8 +- src/RBB/actor_spawninit.c | 231 +++ src/RBB/bss_pad.c | 2 + src/RBB/ch/anchor.c | 33 +- src/RBB/ch/anchorctrl.c | 45 +- src/RBB/ch/anchorswitch.c | 27 +- src/RBB/ch/axle.c | 138 +- src/RBB/ch/bellbuoy.c | 153 +- src/RBB/ch/boombox.c | 253 ++- src/RBB/ch/bossboombox.c | 450 ++-- src/RBB/ch/bossboomboxctrl.c | 18 +- src/RBB/ch/cog.c | 67 +- src/RBB/ch/dolphin.c | 76 +- src/RBB/ch/eggtoll1.c | 173 +- src/RBB/ch/enginefan.c | 142 +- src/RBB/ch/enginefanswitch.c | 40 +- src/RBB/ch/engineparts.c | 104 +- src/RBB/ch/grimlet.c | 113 +- src/RBB/ch/propellor.c | 43 +- src/RBB/ch/propellorswitch.c | 35 +- src/RBB/ch/rarewareflag.c | 13 +- src/RBB/ch/rowboat.c | 137 +- .../ch/{seamangrublin.c => seaman_grublin.c} | 2 +- src/RBB/ch/siren.c | 61 + src/RBB/ch/whistle.c | 109 +- src/RBB/ch/whistlectrl.c | 39 +- src/RBB/ch/whistleswitch.c | 172 +- src/RBB/checksums.c | 7 - src/RBB/crane_boombox.c | 84 +- src/RBB/crane_jiggycage.c | 140 +- src/RBB/miniboombox_container.c | 54 +- src/RBB/propellorctrl.c | 4 +- src/RBB/rbbspawnqueue.c | 241 --- src/RBB/siren.c | 81 - src/SM/ch/ambient_fish.c | 2 +- src/SM/ch/attacktutorial.c | 24 +- src/SM/{ => ch}/bottles_movecheck.c | 0 src/SM/{ => ch}/furniture.c | 0 src/SM/ch/jumptutorial.c | 14 +- src/SM/{ => ch}/quarrie.c | 5 +- src/SM/ch/smbottles.c | 42 +- src/SM/ch/vegetables.c | 12 +- src/SM/checksums.c | 7 - src/SM/{smspawnqueue.c => crc.c} | 45 +- src/SM/version_compat.c | 168 +- src/TTC/actor_spawninit.c | 8 +- src/TTC/{ma => }/castle.c | 16 +- src/TTC/ch/blubber.c | 53 +- src/TTC/ch/clam.c | 8 +- src/TTC/ch/leaky.c | 24 +- src/TTC/ch/lockup.c | 10 +- src/TTC/ch/lockup.h | 23 - src/TTC/ch/nipper.c | 56 +- src/TTC/ch/treasure.c | 2 +- src/TTC/ch/treasurehunt.c | 72 +- src/TTC/checksums.c | 7 - src/TTC/crc.c | 23 +- src/boot/bk_boot_1050.c | 10 +- src/core1/audio_instruments.c | 14 +- src/core1/audio_manager.c | 721 +++---- src/core1/debugtext.c | 2 +- src/core1/defragmanager.c | 4 +- src/core1/depthbuffer.c | 54 +- src/core1/display_list.c | 111 +- src/core1/graphics_thread.c | 144 +- src/core1/init.c | 23 +- src/core1/{ => io}/bamotor.c | 59 +- src/core1/{ => io}/pfsmanager.c | 46 +- src/core1/math/longlong_arith.c | 63 + src/core1/math/longlong_convert.c | 40 + src/core1/{mlmtx.c => math/matrix_stack.c} | 21 +- src/core1/{gu_matrix.c => math/ml.c} | 2 +- src/core1/{gu_perspective.c => math/mlmtx.c} | 13 +- src/core1/{ml.c => math/vector.c} | 136 +- src/core1/musicplayer.c | 47 +- src/core1/musicplayer.h | 7 - src/core1/n_audio/n_csplayer.c | 2 +- src/core1/n_audio/n_env.c | 2 +- src/core1/n_audio/n_seqplayer.c | 2 +- src/core1/overlay.c | 15 +- src/core1/stopnswop.c | 4 +- src/core1/{sns.c => stopnswop_payload.c} | 2 +- src/core1/syncprintf.c | 17 + src/core1/viewport.c | 20 +- src/core1/vimgr.c | 52 +- src/core2/abilityprogress.c | 28 +- src/core2/actor_array.c | 137 +- src/core2/actor_cleanup.c | 5 +- src/core2/{gccube.c => actor_cubebounds.c} | 32 +- src/core2/actor_cubepropsystem.c | 147 +- src/core2/actor_motioncurve.c | 34 +- src/core2/actor_updatestub.c | 15 +- src/core2/anim/anim_bonetransform.c | 6 - src/core2/anim/anim_buffer.c | 2 - src/core2/anim/{animcache.c => anim_cache.c} | 1 - src/core2/anim/anim_defrag.c | 4 +- src/core2/anim/anim_driver.c | 82 +- src/core2/anim/anim_sequencehandler.c | 1 - .../{betavent.c => anim_sequencestruct.c} | 17 +- .../anim/{chumpfish.c => anim_spriteframe.c} | 3 +- ...animtexturecache.c => anim_texturecache.c} | 1 - src/core2/anim/bonetransformlist.c | 1 - src/core2/anim/{anctrl.c => controller.c} | 1 - src/core2/anim/{anseq.c => sequence.c} | 1 - src/core2/anim/{skeletalanim.c => skeletal.c} | 1 - src/core2/anim/sprite.c | 2 +- src/core2/ba/{anim.c => ba_anim.c} | 81 +- src/core2/ba/ba_animcache.c | 1 - src/core2/ba/ba_animstate.c | 197 ++ src/core2/ba/{babounds.c => ba_bounds.c} | 3 +- src/core2/ba/{babuzz.c => ba_buzz.c} | 1 - src/core2/ba/ba_camera.c | 3 +- .../ba/{carriedobj.c => ba_carriedobj.c} | 7 +- src/core2/ba/{carry.c => ba_carry.c} | 3 +- src/core2/ba/{iFrame.c => ba_eyeblink.c} | 2 - src/core2/ba/ba_eyeblink_data.c | 1 - src/core2/ba/ba_eyemouth_data.c | 9 +- src/core2/ba/{baeyes.c => ba_eyes.c} | 11 +- .../ba/{falldamage.c => ba_falldamage.c} | 5 +- src/core2/ba/ba_falling.c | 4 +- src/core2/ba/{baflag.c => ba_flag.c} | 1 - src/core2/ba/{flap.c => ba_flap.c} | 1 - .../ba/{hazards.c => ba_groundsurface.c} | 9 +- src/core2/ba/ba_health.c | 5 +- src/core2/ba/ba_hitbox.c | 17 +- src/core2/ba/{bainput.c => ba_input.c} | 1 - src/core2/ba/ba_intensity.c | 1 - src/core2/ba/{bakey.c => ba_key.c} | 1 - src/core2/ba/{balookat.c => ba_lookat.c} | 1 - src/core2/ba/ba_lookdir.c | 75 +- src/core2/ba/{marker.c => ba_marker.c} | 50 +- src/core2/ba/{model.c => ba_model.c} | 19 +- .../ba/{playermodel.c => ba_modelselect.c} | 24 +- src/core2/ba/ba_momentum.c | 1 - src/core2/ba/ba_musicstate.c | 1 - src/core2/ba/{physics.c => ba_physics.c} | 17 +- .../ba/{playerposition.c => ba_position.c} | 9 +- src/core2/ba/ba_recoil.c | 9 +- src/core2/ba/{drone.c => ba_scripted.c} | 1 - src/core2/ba/{basfx.c => ba_sfx.c} | 1 - src/core2/ba/ba_state.c | 331 +++ src/core2/ba/ba_statusflags.c | 3 +- src/core2/ba/{bastick.c => ba_stick.c} | 3 +- src/core2/ba/ba_stickinterp.c | 1 - src/core2/ba/{batimer.c => ba_timer.c} | 5 +- src/core2/ba/ba_underwater.c | 1 - src/core2/ba/ba_yaw.c | 1 - src/core2/ba/bsmethods.c | 335 --- src/core2/ba/iFrame.h | 10 - src/core2/ba/modelappendages.c | 209 -- src/core2/bs/ant.c | 60 +- src/core2/bs/{bFlip.c => backflip.c} | 10 +- src/core2/bs/{bBarge.c => beak_barge.c} | 10 +- src/core2/bs/{bFly.c => beak_bomb.c} | 132 +- src/core2/bs/{bbuster.c => beak_buster.c} | 12 +- src/core2/bs/{bEggHead.c => beak_egg_aim.c} | 28 +- src/core2/bs/{bEggAss.c => beak_egg_fire.c} | 17 +- src/core2/bs/{bPeck.c => beak_peck.c} | 9 +- src/core2/bs/{bSwim.c => beak_swim.c} | 72 +- src/core2/bs/bee.c | 4 +- src/core2/bs/{beeFly.c => bee_fly.c} | 24 +- src/core2/bs/{beeMain.c => bee_main.c} | 98 +- src/core2/bs/{bsList.c => bs_list.c} | 1 - src/core2/bs/bs_statemachine.c | 1 - .../bs/{bsStoredState.c => bs_storedstate.c} | 1 - src/core2/bs/carry.c | 11 +- src/core2/bs/claw.c | 5 +- src/core2/bs/climb.c | 16 +- src/core2/bs/croc.c | 67 +- src/core2/bs/crouch.c | 10 +- src/core2/bs/die.c | 10 +- src/core2/bs/{bFlap.c => flap_flip.c} | 10 +- src/core2/bs/{ow.c => hurt.c} | 1 - src/core2/bs/{jig.c => jiggy_dance.c} | 14 +- src/core2/bs/jump.c | 33 +- src/core2/bs/player_spawn.c | 257 ++- src/core2/bs/pumpkin.c | 39 +- src/core2/bs/rebound.c | 21 +- src/core2/bs/rest.c | 29 +- src/core2/bs/{drone.c => scripted.c} | 1 - .../bs/{droneenter.c => scripted_enter.c} | 4 +- src/core2/bs/{dronegoto.c => scripted_goto.c} | 4 +- src/core2/bs/{dronelook.c => scripted_look.c} | 16 +- .../bs/{dronexform.c => scripted_transform.c} | 44 +- .../bs/{dronevanish.c => scripted_vanish.c} | 4 +- src/core2/bs/{bShock.c => shock_spring.c} | 28 +- src/core2/bs/sled.c | 3 +- src/core2/bs/slide.c | 5 +- src/core2/bs/splat.c | 7 +- src/core2/bs/stand.c | 49 +- src/core2/bs/{bLongLeg.c => stilt_stride.c} | 68 +- src/core2/bs/surf.c | 11 +- src/core2/bs/swim.c | 25 +- src/core2/bs/talk.c | 2 +- src/core2/bs/{bTrot.c => talon_trot.c} | 52 +- src/core2/bs/throw.c | 6 +- src/core2/bs/timeout.c | 39 +- src/core2/bs/turn.c | 4 +- src/core2/bs/walk.c | 55 +- src/core2/bs/walrus.c | 77 +- src/core2/bs/{washy.c => washing_machine.c} | 12 +- src/core2/bs/{bWhirl.c => wonderwing.c} | 28 +- src/core2/bundle.c | 1 - .../{nc => camera}/camera_debug_freecam.c | 1 - src/core2/{nc => camera}/camera_ease.c | 3 +- src/core2/{nc => camera}/camera_focus.c | 1 - src/core2/{nc => camera}/camera_focustarget.c | 1 - src/core2/{nc => camera}/camera_fog.c | 1 - src/core2/{nc => camera}/camera_motor1.c | 13 - src/core2/{nc => camera}/camera_motor2.c | 1 - src/core2/{nc => camera}/camera_nodemanager.c | 18 +- src/core2/{nc => camera}/camera_position.c | 1 - src/core2/{nc => camera}/camera_set.c | 1 - src/core2/{nc => camera}/cameranode_type1.c | 1 - src/core2/{nc => camera}/cameranode_type2.c | 1 - src/core2/{nc => camera}/cameranode_type3.c | 1 - src/core2/{nc => camera}/cameranode_type4.c | 1 - src/core2/{nc => camera}/cameranodelist.c | 1 - src/core2/camera/dynamicCam1.c | 46 + src/core2/{nc => camera}/dynamicCam10.c | 1 - src/core2/{nc => camera}/dynamicCam11.c | 1 - src/core2/{nc => camera}/dynamicCam12.c | 1 - src/core2/{nc => camera}/dynamicCam13.c | 1 - src/core2/{nc => camera}/dynamicCam3.c | 9 +- src/core2/{nc/fly.c => camera/dynamicCam4.c} | 31 +- src/core2/{nc => camera}/dynamicCam5.c | 3 +- src/core2/{nc => camera}/dynamicCam8.c | 1 - src/core2/{nc => camera}/dynamicCam9.c | 11 +- src/core2/{nc => camera}/dynamicCamA.c | 1 - src/core2/{nc => camera}/dynamicCamB.c | 1 - src/core2/{nc => camera}/dynamicCamC.c | 3 +- src/core2/{nc/die.c => camera/dynamicCamD.c} | 11 +- src/core2/{nc => camera}/dynamicCamF.c | 1 - src/core2/{nc => camera}/dynamicCamera.c | 161 +- .../{nc/1p.c => camera/firstpersoncamera.c} | 39 +- src/core2/{nc => camera}/randomCamera.c | 1 - src/core2/{nc => camera}/staticCamera.c | 3 +- src/core2/ch/beehive.c | 6 +- src/core2/ch/beeswarm.c | 8 +- src/core2/ch/bottlesbonus.c | 25 +- src/core2/ch/bottlesbonuscursor.c | 30 +- src/core2/ch/{climbBase.c => climb_base.c} | 5 +- src/core2/ch/clucker.c | 6 +- src/core2/ch/collectible.c | 12 +- src/core2/ch/crab.c | 169 +- src/core2/ch/extralife.c | 1 - src/core2/ch/feather.c | 1 - src/core2/ch/gameSelect.h | 14 - src/core2/ch/ghost.c | 188 +- src/core2/ch/gloop.c | 2 +- src/core2/ch/goldfeather.c | 5 +- src/core2/ch/gravestone.c | 4 +- .../ch/{grillechompa.c => grill_chompa.c} | 3 +- src/core2/ch/honeycomb.c | 23 +- src/core2/ch/icecube.c | 2 +- src/core2/ch/jiggy.c | 224 +- src/core2/ch/jiggy.h | 20 - src/core2/ch/jinjo.c | 187 +- src/core2/ch/level_collectible.c | 378 ++++ src/core2/ch/levelcollectible.c | 692 ------- src/core2/ch/mole.c | 204 +- src/core2/ch/molehill.c | 12 +- src/core2/ch/mumbo_sign.c | 26 + src/core2/ch/mumbosign.c | 27 - src/core2/ch/mumbotoken.c | 11 +- src/core2/ch/shock_jumppad.c | 1 - src/core2/ch/snacker.c | 6 +- src/core2/ch/snowball.c | 2 +- src/core2/ch/snowman.c | 23 +- src/core2/ch/trainers.c | 4 +- src/core2/ch/wadingboots.c | 10 +- src/core2/checksums.c | 7 - src/core2/climb.c | 41 +- src/core2/collision/climbsurface.c | 23 +- src/core2/collision/dispatch.c | 1 - src/core2/collision/enemy.c | 5 +- src/core2/collision/filter.c | 1 - src/core2/collision/geometrybounds.c | 1 - src/core2/collision/hitboxdata.c | 452 ++-- src/core2/collision/polydetect.c | 1 - src/core2/collision/raycast.c | 1 - .../{scarabbeetle.c => raycastmap.c} | 15 +- src/core2/collision/spherecast.c | 1 - src/core2/collision/tricheck.c | 1 - src/core2/{gc => context}/bound.c | 1 - src/core2/{gc => context}/dialog.c | 48 +- .../{gc => context}/enter_text_trigger.c | 21 +- .../{gc/gameoversign.c => context/gameover.c} | 20 +- .../{gc/section.c => context/map_info.c} | 1 - .../overlay_copyright.c} | 1 - .../overlay_nocontroller.c} | 5 +- .../overlay_pressstart.c} | 7 +- src/core2/{gc => context}/parade.c | 1 - .../{gc/pauseMenu.c => context/pause_menu.c} | 56 +- src/core2/{gc => context}/pictureframe.c | 14 +- src/core2/{gc => context}/sky.c | 27 +- src/core2/{gc => context}/transition.c | 47 +- src/core2/{gc => context}/zoombox.c | 26 +- src/core2/crc_bootvalidation.c | 138 +- .../{mumboshandwithpicture.c => demo_ctrl.c} | 71 +- src/core2/{demo.c => demo_input.c} | 8 +- src/core2/dialog/binload.c | 5 +- src/core2/dialog/progressDialog.c | 135 -- src/core2/dialog/progress_dialogs.c | 134 ++ src/core2/displaylist_init.c | 7 +- src/core2/fileselect.c | 2 - src/core2/flags_bitfield.c | 64 +- src/core2/font/print.c | 439 ++-- src/core2/font/render.c | 39 +- src/core2/frame/auxbuffer.c | 77 +- src/core2/frame/rendermem.c | 18 +- src/core2/frame/texture_capture.c | 15 +- src/core2/{fla.c => freelist.c} | 1 - .../{cutscene_actors.c => background_decor.c} | 47 +- src/core2/fx/drips.c | 1 - .../fx/{piranhaWaterParticles.c => droplet.c} | 3 +- src/core2/fx/effect_colordata.c | 1 - src/core2/fx/effect_debris.c | 138 +- .../fx/{eggshatter.c => effect_eggshatter.c} | 1 - .../{explosionripple.c => effect_generic.c} | 1 - src/core2/fx/effect_ice.c | 4 +- src/core2/fx/effect_jiggy.c | 1 - src/core2/fx/effect_jiggy_list.c | 19 +- src/core2/fx/effect_jiggy_spawn.c | 1 - src/core2/fx/effect_modelparticle.c | 1 - src/core2/fx/effect_playerspray.c | 9 +- src/core2/fx/effect_ripple.c | 3 +- .../fx/{ripple.c => effect_ripple_spawn.c} | 1 - src/core2/fx/effect_simplesprite.c | 1 - src/core2/fx/effect_soundemit.c | 132 ++ .../fx/{shoesparkle.c => effect_sparkle.c} | 34 +- .../fx/{sparkle.c => effect_sparkle_spawn.c} | 1 - src/core2/fx/effect_sparkleemit.c | 5 +- ...banjokazooiesign.c => effect_spriteanim.c} | 38 +- src/core2/fx/{badShad.c => enemy_shadow.c} | 11 +- src/core2/fx/firefx.c | 1 - src/core2/fx/projectile_anim.c | 1 - src/core2/fx/projectile_blueegg.c | 11 +- ...{commonParticle.c => projectile_manager.c} | 13 +- src/core2/fx/projectile_render.c | 1 - src/core2/fx/projectile_smoke.c | 1 - src/core2/fx/projectile_sparkle.c | 1 - src/core2/fx/projectile_spawnfx.c | 1 - src/core2/fx/projectile_system.c | 1 - src/core2/fx/shrapnel.c | 3 +- src/core2/fx/weather_emitter.c | 188 -- src/core2/fx/whipcrack.c | 1 - src/core2/gameSelect.c | 125 +- src/core2/gameloop.c | 144 +- src/core2/gamestate.c | 64 +- src/core2/gc/dialog.h | 22 - src/core2/inventory_slots.c | 3 +- src/core2/level/lightconfig.c | 2 +- src/core2/level/metadata.c | 1 - .../{levelspecificflags.c => specificflags.c} | 25 +- src/core2/map/audioconfig.c | 1 - src/core2/map/cutscene_skip.c | 29 +- src/core2/map/cutscene_triggers.c | 1 - src/core2/map/envcolor.c | 1 - src/core2/map/exit.c | 11 +- src/core2/map/gsworld.c | 125 +- src/core2/map/list.c | 3 +- src/core2/map/loadzone.c | 1 - src/core2/map/{mapModel.c => model.c} | 85 +- src/core2/map/overlay.c | 19 +- src/core2/map/{mapsavestate.c => savestate.c} | 1 - .../{mapspecificflags.c => specificflags.c} | 13 +- src/core2/map/warp_dispatch.c | 20 +- src/core2/map/world_reset.c | 1 - src/core2/matrix_interp.c | 1 - src/core2/model/lighting.c | 1 - src/core2/model/mesh_dataaccess.c | 1 - src/core2/model/meshbounds.c | 1 - src/core2/model/{modelRender.c => render.c} | 32 +- src/core2/model/rendernormal.c | 1 - src/core2/model/skinning.c | 1 - src/core2/model/vertex_brightness.c | 1 - src/core2/{mumbo.c => mumbo_transforms.c} | 141 +- src/core2/nc/dynamicCam1.c | 50 - .../{particleemittermanager.c => accel.c} | 1 - .../{dustemitter.c => colordefault.c} | 1 - src/core2/particle/emitter1.c | 1 - src/core2/particle/emitter2.c | 1 - src/core2/particle/emitterstruct.c | 3 +- .../{commonParticleTypeMap.c => factory.c} | 1 - src/core2/particle/initcallback.c | 1 - src/core2/particle/lifescale.c | 1 - src/core2/particle/particle.c | 27 +- src/core2/particle/positionset.c | 1 - src/core2/particle/samplerate.c | 1 - src/core2/particle/scale1.c | 1 - src/core2/particle/scale2.c | 1 - src/core2/particle/spawn.c | 1 - src/core2/particle/typeindex.c | 1 - src/core2/particle/velocityrange.c | 1 - src/core2/particle/velocityset.c | 1 - src/core2/playerutils.c | 82 +- .../{propModelList.c => prop_assetcache.c} | 1 - ...quizquestionaskedbitfield.c => bitfield.c} | 5 +- src/core2/quiz/game.c | 626 ++---- .../quiz/{minigame.c => minigamemanager.c} | 3 +- src/core2/quiz/questionmanager.c | 1 - src/core2/quiz/storage.c | 3 +- src/core2/savedata.c | 5 +- .../{honeycombscore.c => score_honeycomb.c} | 1 - src/core2/{jiggyscore.c => score_jiggy.c} | 7 - src/core2/{mumboscore.c => score_mumbo.c} | 1 - src/core2/scorequeue/dispatch.c | 1 - .../scorequeue/{airscore.c => drawui_air.c} | 1 - .../{healthscore.c => drawui_health.c} | 1 - ...eycarrierscore.c => drawui_honeycarrier.c} | 1 - .../{jinjoscore.c => drawui_jinjo.c} | 1 - .../{lifescore.c => drawui_lives.c} | 1 - .../{common3score.c => drawui_models.c} | 13 +- .../{common2score.c => drawui_sprites.c} | 11 +- .../{common1score.c => drawui_stub.c} | 1 - src/core2/scorequeue/manager.c | 5 +- src/core2/scorequeue/queue_collectibles.c | 1 - src/core2/scorequeue/queue_honeycombs.c | 1 - src/core2/scorequeue/queue_lives.c | 1 - src/core2/scorequeue/queue_major_items.c | 1 - src/core2/scorequeue/queue_notes.c | 1 - src/core2/scorequeue/queue_timers.c | 1 - src/core2/scorequeue/queue_totals.c | 1 - .../{fx/weather_snow.c => sfx/filedata.c} | 58 +- src/core2/{fx/weather.c => sfx/init.c} | 1 - src/core2/sfx/instruments.c | 6 +- src/core2/sfx/pitched.c | 1 - .../{fx/weather_leaves.c => sfx/playstate.c} | 5 +- src/core2/sfx/randompitch.c | 1 - src/core2/sfx/sequenceindex.c | 1 - src/core2/sfx/soundsource.c | 1 - src/core2/sfx/source.c | 12 +- .../{fx/weather_rain.c => sfx/streamctrl.c} | 5 +- src/core2/sfx/trackmanager.c | 1 - src/core2/sfx/volume.c | 1 - src/core2/{snackerctl.c => snacker_ctl.c} | 9 +- src/core2/{spawnqueue.c => spawn_queue.c} | 356 ++-- src/core2/spline_bezier.c | 1 - src/core2/spline_pathfollow.c | 10 +- src/core2/sprite/render.c | 7 +- src/core2/sprite/rendertex.c | 1 - src/core2/sprite/screenoverlay.c | 13 +- src/core2/sprite/texblock.c | 1 - src/core2/{statetimer.c => state_timer.c} | 1 - src/core2/texture_dataaccess.c | 7 +- src/core2/time.c | 9 +- src/core2/time_framedelta.c | 20 +- .../{timedfuncqueue.c => timed_funcqueue.c} | 1 - src/core2/{vla.c => vector.c} | 5 +- src/core2/vtx/alphablend.c | 1 - src/core2/vtx/colorapply.c | 1 - src/core2/vtx/colorintensity.c | 1 - src/core2/vtx/colorset.c | 1 - src/core2/vtx/convert.c | 1 - src/core2/vtx/{gclights.c => lighting.c} | 11 +- src/core2/vtx/list.c | 7 +- src/core2/vtx/listutils.c | 6 +- src/core2/vtx/meshcount.c | 1 - src/core2/vtx/normalset.c | 1 - src/core2/vtx/positionset.c | 11 +- src/core2/vtx/renderstart.c | 3 +- src/core2/vtx/scale.c | 1 - src/core2/vtx/transform.c | 2 - src/core2/vtx/uvset.c | 1 - ...utscenesspawnqueue.c => actor_spawninit.c} | 2 +- src/cutscenes/bss_pad.c | 2 + .../{theendsign.c => character_parade.c} | 15 +- src/cutscenes/checksums.c | 7 - src/cutscenes/cutscene_trigger.c | 2 +- src/cutscenes/{ => fx}/glow_sparkle.c | 0 src/cutscenes/{ => fx}/smoke.c | 0 src/cutscenes/{ => fx}/sparkle.c | 0 src/emptyLvl/checksums.c | 7 - src/fight/checksums.c | 7 - src/lair/checksums.c | 7 - src/lair/jigsawpicture.h | 11 - src/{emptyLvl => overlay_stub}/empty_level.c | 2 +- src/port/Audio/AudioSync.cpp | 23 - src/port/Audio/mixer.h | 30 +- src/port/Controller/ControlSchemes.cpp | 255 +-- src/port/Controller/Mapper.cpp | 1709 ---------------- src/port/Controller/Mapper.h | 182 -- src/port/Controller/ModernCamera.cpp | 179 +- src/port/DevTools/DevSequences.cpp | 4 - src/port/DevTools/DevSequences.h | 1 - src/port/DevTools/FlagTracer.cpp | 243 --- src/port/DevTools/OcclusionDebug.cpp | 7 +- src/port/DevTools/ThreadWatchdog.cpp | 580 ------ src/port/DevTools/ThreadWatchdog.h | 94 - src/port/Engine.cpp | 329 ++- src/port/Engine.h | 5 + src/port/Enhancements/Backports/EggAim.cpp | 14 +- src/port/Enhancements/Backports/FastSwim.cpp | 2 + src/port/Enhancements/Backports/Honeyback.cpp | 2 + .../Backports/TooieJiggyDance.cpp | 23 +- .../Enhancements/Camera/FreeLookCamera.cpp | 201 +- .../Enhancements/Camera/OrbitCameraCore.cpp | 157 ++ .../Enhancements/Camera/OrbitCameraCore.h | 59 + src/port/Enhancements/Cheats/Cheats.cpp | 129 +- .../Enhancements/Cosmetics/PlayerColors.cpp | 480 ----- .../Enhancements/Cosmetics/PlayerColors.h | 43 - .../Enhancements/Cutscenes/CutsceneSkips.cpp | 14 - .../Enhancements/Cutscenes/IntroLogos.cpp | 59 - src/port/Enhancements/Events/Hooks/Events.h | 99 +- .../Events/Hooks/List/BehaviorEvent.h | 1 - .../Events/Hooks/List/EngineEvent.h | 11 - .../Events/Hooks/List/GameEvent.h | 20 - .../Events/Hooks/List/RandoEvent.h | 2 - .../Enhancements/Events/PortEnhancements.cpp | 16 - src/port/Enhancements/Fixes/GameFixes.cpp | 44 +- .../Fixes/TransientLevelState.cpp | 62 - .../Enhancements/Gameplay/DamageScale.cpp | 13 + src/port/Enhancements/Gameplay/Difficulty.cpp | 53 - .../Gameplay/EasierBoggyRaces.cpp | 2 + .../Enhancements/Gameplay/FurnaceFunMoves.cpp | 7 +- .../Enhancements/Gameplay/SkipSMTutorial.cpp | 30 +- .../Gameplay/WaterPyramidTimer.cpp | 2 + .../JinjoRetention/JinjoRetention.cpp | 195 ++ .../JinjoRetention/JinjoRetention.h | 8 + .../NoteRetention/NoteRetention.cpp | 425 ++++ .../NoteRetention/NoteRetention.h | 17 + .../Restorations/ReturnToLair.cpp | 6 +- .../Enhancements/Retention/JinjoRetention.cpp | 271 --- .../Enhancements/Retention/NoteRetention.cpp | 495 ----- src/port/Enhancements/Retention/Retention.cpp | 31 - src/port/Enhancements/Retention/Retention.h | 80 - src/port/Enhancements/Retention/WormSync.cpp | 199 -- .../Enhancements/Trackers/DisplayOverlay.cpp | 12 +- src/port/Extractor/GameExtractor.cpp | 126 +- src/port/Extractor/GameExtractor.h | 8 +- src/port/FilePicker.cpp | 66 - src/port/FilePicker.h | 34 - src/port/Game.cpp | 297 +-- src/port/GameStatus.cpp | 78 +- src/port/GameVersion/AssetVersionRemap.h | 1111 +++++----- src/port/GameVersion/BaseGameVersion.cpp | 70 +- src/port/GameVersion/BaseGameVersion.h | 6 - src/port/Interpolation/AdaptiveFps.cpp | 185 ++ src/port/Interpolation/AdaptiveFps.h | 46 + src/port/Interpolation/FrameInterpolation.cpp | 836 +++----- src/port/Interpolation/FrameInterpolation.h | 26 +- src/port/LaunchArgs.cpp | 148 -- src/port/LaunchArgs.h | 13 - src/port/Localization/Language.cpp | 84 +- src/port/Localization/Localization.cpp | 44 +- src/port/Nametag/Nametag.cpp | 172 +- src/port/Nametag/Nametag.h | 11 +- src/port/Nametag/NametagBindings.cpp | 48 +- src/port/Network/Anchor/Anchor.cpp | 285 +-- src/port/Network/Anchor/Anchor.h | 137 +- src/port/Network/Anchor/AnchorRoomWindow.cpp | 15 +- src/port/Network/Anchor/Authority.cpp | 35 +- src/port/Network/Anchor/Authority.h | 6 +- src/port/Network/Anchor/DummyPlayer.cpp | 222 +- src/port/Network/Anchor/DummyPlayer.h | 39 +- src/port/Network/Anchor/FightSync.c | 554 ----- src/port/Network/Anchor/FightSync.h | 98 - src/port/Network/Anchor/HookHandlers.cpp | 429 +--- src/port/Network/Anchor/JigsawPedestal.cpp | 93 - src/port/Network/Anchor/JigsawPedestal.h | 23 - src/port/Network/Anchor/JsonConversions.hpp | 34 - src/port/Network/Anchor/Menu.cpp | 194 +- .../Network/Anchor/Packets/AllClientState.cpp | 11 +- .../Network/Anchor/Packets/BreakObject.cpp | 114 -- .../Network/Anchor/Packets/CarryThrow.cpp | 64 - .../Network/Anchor/Packets/CollectItem.cpp | 152 -- .../Network/Anchor/Packets/DamagePlayer.cpp | 36 +- .../Network/Anchor/Packets/DisableAnchor.cpp | 1 + src/port/Network/Anchor/Packets/EggToll.cpp | 108 - .../Anchor/Packets/EntranceDiscovered.cpp | 6 +- .../Network/Anchor/Packets/FightEvent.cpp | 72 - .../Network/Anchor/Packets/FightState.cpp | 70 - .../Network/Anchor/Packets/FightUpdate.cpp | 75 - .../Network/Anchor/Packets/GameComplete.cpp | 7 +- src/port/Network/Anchor/Packets/GiveItem.cpp | 9 +- src/port/Network/Anchor/Packets/Handshake.cpp | 2 + src/port/Network/Anchor/Packets/HutSmash.cpp | 108 - .../Network/Anchor/Packets/JiggyCrane.cpp | 35 - src/port/Network/Anchor/Packets/MapLoad.cpp | 6 +- .../Network/Anchor/Packets/PedestalOwner.cpp | 27 - src/port/Network/Anchor/Packets/PlayerSfx.cpp | 18 + .../Network/Anchor/Packets/PlayerUpdate.cpp | 70 +- .../Network/Anchor/Packets/PuzzleStep.cpp | 340 --- .../Anchor/Packets/RequestTeamState.cpp | 7 +- .../Anchor/Packets/RequestTeleport.cpp | 32 +- .../Network/Anchor/Packets/ScopedFlag.cpp | 79 - .../Network/Anchor/Packets/ScopedState.cpp | 88 - .../Network/Anchor/Packets/ServerMessage.cpp | 1 + .../Network/Anchor/Packets/SetAbility.cpp | 51 - .../Network/Anchor/Packets/SetCheckStatus.cpp | 109 +- src/port/Network/Anchor/Packets/SetFlag.cpp | 95 +- .../Network/Anchor/Packets/SetItemCount.cpp | 47 - .../Network/Anchor/Packets/SpawnHoneycomb.cpp | 47 - .../Network/Anchor/Packets/SpawnJiggy.cpp | 171 -- .../Network/Anchor/Packets/TeleportTo.cpp | 57 +- src/port/Network/Anchor/Packets/UnsetFlag.cpp | 86 +- .../Anchor/Packets/UpdateClientState.cpp | 16 +- .../Anchor/Packets/UpdateRoomState.cpp | 109 +- .../Anchor/Packets/UpdateTeamState.cpp | 494 ++--- .../Network/Anchor/Packets/VileEatRequest.cpp | 9 + .../Network/Anchor/Packets/VileEatResult.cpp | 12 +- .../Network/Anchor/Packets/VileGameState.cpp | 9 +- .../Network/Anchor/Packets/VileHoleState.cpp | 2 + .../Network/Anchor/Packets/VileUpdate.cpp | 4 +- src/port/Network/Anchor/Packets/WaterRise.cpp | 121 -- src/port/Network/Anchor/VileSync.c | 8 +- src/port/Network/Anchor/VileSync.h | 2 +- src/port/OS/OS.h | 95 - src/port/OS/OS_AI.cpp | 61 - src/port/OS/OS_Cont.cpp | 103 - src/port/OS/OS_Mesg.cpp | 239 --- src/port/OS/OS_RCP.cpp | 102 - src/port/OS/OS_Threads.cpp | 155 -- src/port/OS/OS_Time.cpp | 39 - src/port/OS/OS_Timer.cpp | 121 -- src/port/OS/OS_VI.cpp | 111 - src/port/Patches/AnimVertexPatches.cpp | 54 - src/port/Patches/CameraPatches.cpp | 11 +- src/port/Patches/FramePacingPatches.cpp | 48 +- src/port/Patches/FramebufferPatches.cpp | 133 +- src/port/Patches/GeoCull.cpp | 12 +- src/port/Patches/GeoCull.h | 4 + src/port/Patches/GraphicsPatches.cpp | 193 +- src/port/Patches/MirrorPatches.cpp | 24 +- src/port/Patches/Patches.h | 128 +- src/port/Patches/PerfPatches.cpp | 252 --- src/port/Patches/SpritePatches.cpp | 27 +- src/port/Patches/TransitionPatches.cpp | 17 + src/port/Rando/CheckTracker/CheckTracker.cpp | 14 +- .../CustomCollectible/CustomCollectible.cpp | 243 --- .../CustomCollectible/CustomCollectible.h | 46 - .../CustomCollectibleDrawCustom.cpp | 108 - .../CustomCollectibleDrawCustom.h | 36 - src/port/Rando/CustomObject/CustomObject.cpp | 60 +- src/port/Rando/ItemQueue.cpp | 344 ---- src/port/Rando/ItemQueue.h | 10 - src/port/Rando/LighthouseMenuRando.cpp | 65 +- src/port/Rando/Logic/GeneratePools.cpp | 7 +- src/port/Rando/Logic/GenerateSaveData.cpp | 31 +- src/port/Rando/Logic/GlitchlessLogic.cpp | 54 +- src/port/Rando/Logic/Logic.h | 59 +- src/port/Rando/MiscBehavior/OnFileLoad.cpp | 27 +- src/port/Rando/MiscBehavior/WorldState.cpp | 65 +- src/port/Rando/ObjectBehavior/BlueEgg.cpp | 40 - src/port/Rando/ObjectBehavior/Boggy.cpp | 6 +- src/port/Rando/ObjectBehavior/Bundle.cpp | 1059 +++++----- .../Rando/ObjectBehavior/EmptyHoneyComb.cpp | 38 - src/port/Rando/ObjectBehavior/ExtraLife.cpp | 38 - src/port/Rando/ObjectBehavior/Gobi.cpp | 6 +- src/port/Rando/ObjectBehavior/Jiggy.cpp | 99 +- src/port/Rando/ObjectBehavior/Jinjo.cpp | 65 +- src/port/Rando/ObjectBehavior/Molehill.cpp | 186 +- src/port/Rando/ObjectBehavior/MumboToken.cpp | 38 - src/port/Rando/ObjectBehavior/MusicNote.cpp | 59 +- .../Rando/ObjectBehavior/ObjectBehavior.cpp | 141 +- .../Rando/ObjectBehavior/ObjectBehavior.h | 7 + src/port/Rando/ObjectBehavior/Present.cpp | 18 +- src/port/Rando/ObjectBehavior/Prop.cpp | 52 + src/port/Rando/ObjectBehavior/StopNSwop.cpp | 2 +- src/port/Rando/ObjectBehavior/Switch.cpp | 6 + src/port/Rando/Rando.cpp | 4 +- src/port/Rando/Rando.h | 4 - src/port/Rando/Spoiler/File.cpp | 72 - src/port/Rando/Spoiler/Generate.cpp | 111 - src/port/Rando/Spoiler/RefreshOptions.cpp | 40 - src/port/Rando/Spoiler/Spoiler.h | 26 - src/port/Rando/StaticData/Checks.cpp | 1821 +++++++++-------- src/port/Rando/StaticData/Flags.cpp | 1 + src/port/Rando/StaticData/Items.cpp | 58 +- src/port/Rando/StaticData/StaticData.h | 1 - src/port/Rando/Types.h | 53 +- src/port/Resource/Alt/AltBoldFont.cpp | 15 +- src/port/Resource/Alt/AltDialogFont.cpp | 160 -- src/port/Resource/GfxBridge.c | 30 +- src/port/Resource/Importers/MapFactory.cpp | 15 +- src/port/Resource/Importers/ModelFactory.cpp | 56 +- src/port/Resource/Type/Sprite.cpp | 21 + src/port/ResourceHelpers.cpp | 79 +- src/port/ResourceHelpers.h | 5 - src/port/Romhack/RomhackCompat.cpp | 8 +- src/port/Romhack/RomhackConfig.cpp | 117 +- src/port/Romhack/RomhackConfig.h | 14 +- src/port/Romhack/RomhackQuirks.cpp | 56 + src/port/Romhack/RomhackRegistration.cpp | 61 - src/port/Romhack/RomhackTable.h | 65 +- src/port/Romhack/Shared/HackShared.cpp | 147 -- src/port/Romhack/Shared/HackShared.h | 23 - src/port/Romhack/Shared/ProximityDialogs.cpp | 83 - src/port/Romhack/Shared/ProximityDialogs.h | 39 - src/port/Romhack/Shared/StealthNoise.cpp | 362 ---- src/port/Romhack/Shared/StealthNoise.h | 20 - src/port/Romhack/Shared/Storybook.cpp | 134 -- src/port/Romhack/Shared/Storybook.h | 12 - src/port/Romhack/Specific/BubblingBog.cpp | 24 - src/port/Romhack/Specific/CutThroatCoast.cpp | 284 --- src/port/Romhack/Specific/Dreamie.cpp | 37 - src/port/Romhack/Specific/JiggiesOfTime.cpp | 31 - src/port/Romhack/Specific/NewHorizons.cpp | 25 - src/port/Romhack/Specific/Nostalgia64.cpp | 90 - src/port/Romhack/Specific/TheGruntch.cpp | 540 ----- src/port/Save/SaveConverter.cpp | 53 +- src/port/Save/SaveConverter.h | 8 +- src/port/Save/SaveManager.cpp | 209 +- src/port/Save/Types.h | 3 - src/port/ShipUtils.cpp | 17 +- src/port/ShipUtils.h | 5 +- src/port/UI/DeveloperTools/GameplayTools.cpp | 90 +- src/port/UI/DeveloperTools/SaveEditor.cpp | 73 +- src/port/UI/InputViewer.cpp | 624 +++--- src/port/UI/LighthouseGui.cpp | 25 +- src/port/UI/LighthouseInputEditorWindow.cpp | 23 - src/port/UI/LighthouseMenu.cpp | 7 - src/port/UI/LighthouseMenuDevTools.cpp | 27 +- src/port/UI/LighthouseMenuEnhancements.cpp | 172 +- src/port/UI/LighthouseMenuNetwork.cpp | 2 + src/port/UI/LighthouseMenuSettings.cpp | 115 +- src/port/UI/LighthouseModMenuWindow.cpp | 133 +- src/port/UI/LighthouseModals.cpp | 7 +- src/port/UI/Menu.cpp | 19 +- src/port/UI/Menu.h | 3 - src/port/UI/MenuTypes.h | 2 - src/port/UI/Notification.cpp | 26 +- src/port/UI/ResolutionEditor.cpp | 28 +- src/port/UI/ResolutionEditor.h | 2 +- src/port/UI/UIWidgets.cpp | 29 +- .../Gameplay/DisableSnackerSpawn.cpp | 2 + .../enhancements/Gameplay/EasierMrVile.cpp | 2 + src/port/{OS/libultra.c => stub.c} | 46 +- src/unused/datalookup.c | 2 +- src/unused/debug_assert.c | 2 +- src/unused/debug_boxdraw.c | 2 +- src/unused/unused_block.c | 2 +- 1077 files changed, 20243 insertions(+), 42075 deletions(-) create mode 100644 .github/workflows/linux.yml create mode 100644 .github/workflows/mac.yml create mode 100644 .github/workflows/switch.yml create mode 100644 .github/workflows/windows.yml delete mode 100644 cmake/GenerateFlagNames.cmake delete mode 100644 docs/poweredbylus.darkmode.png delete mode 100644 docs/poweredbylus.lightmode.png delete mode 100644 include/checksums.h rename src/core2/quiz/storage.h => include/core2/quiz_storage.h (85%) rename lib/ultralib/include/{ultra_assert.h => assert.h} (100%) delete mode 100644 port/anim/lighthouse_shrug delete mode 100644 port/anim/lighthouse_walk delete mode 100644 port/models/lighthouse delete mode 100644 port/models/lighthouse_GEO delete mode 100644 port/models/lighthouse_VTX delete mode 100644 port/models/lighthouse_tex_0 delete mode 100644 port/models/lighthouse_tex_1 delete mode 100644 port/models/lighthouse_tex_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 delete mode 100644 port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive delete mode 100644 port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive delete mode 100644 port/objects/object_archipelago_item/model.xml create mode 100644 port/textures/icons/g2ShipIcon.png delete mode 100644 port/textures/intro/xylophone delete mode 100644 port/textures/mapping-xbox.png rename src/BGS/{bgsspawnqueue.c => actor_spawninit.c} (91%) create mode 100644 src/BGS/bss_pad.c rename src/BGS/ch/{choirturtle.c => choir_turtle.c} (95%) rename src/BGS/ch/{tanktuplegs.c => tanktup_legs.c} (75%) delete mode 100644 src/BGS/checksums.c rename src/BGS/{mrvileminigame.c => minigame_vile.c} (58%) rename src/CC/{ccspawnqueue.c => actor_spawninit.c} (98%) create mode 100644 src/CC/bss_pad.c rename src/CC/ch/{ccgrates.c => clanker.c} (73%) rename src/CC/ch/{clankerkey.c => key.c} (91%) rename src/CC/ch/{clankerscrew.c => screw.c} (88%) delete mode 100644 src/CC/checksums.c delete mode 100644 src/CC/ma/clanker.c delete mode 100644 src/CC/ma/clankerrings.c create mode 100644 src/CC/minigame_rings.c create mode 100644 src/CC/platform_physics.c create mode 100644 src/CCW/actor_spawninit.c create mode 100644 src/CCW/bss_pad.c delete mode 100644 src/CCW/ccwspawnqueue.c delete mode 100644 src/CCW/ch/adulteyrie.c delete mode 100644 src/CCW/ch/beanstalk.c delete mode 100644 src/CCW/ch/cutsceneadulteyrie.c delete mode 100644 src/CCW/ch/deadsnarebear.c create mode 100644 src/CCW/ch/eyrie_baby.c create mode 100644 src/CCW/ch/eyrie_egg.c create mode 100644 src/CCW/ch/eyrie_summer.c create mode 100644 src/CCW/ch/eyrie_winter.c delete mode 100644 src/CCW/ch/eyrieegg.c create mode 100644 src/CCW/ch/fairy.c create mode 100644 src/CCW/ch/gnawty.c rename src/CCW/ch/{ccwgobi.c => gobi_ccw.c} (55%) delete mode 100644 src/CCW/ch/indoorsgnawty.c create mode 100644 src/CCW/ch/nabnut_autumn.c create mode 100644 src/CCW/ch/nabnut_dialog.c create mode 100644 src/CCW/ch/nabnut_spring.c rename src/CCW/ch/{bellyfullnabnut.c => nabnut_summer.c} (61%) create mode 100644 src/CCW/ch/nabnut_winter.c delete mode 100644 src/CCW/ch/outsideautumnnabnut.c delete mode 100644 src/CCW/ch/seasonswitchdoors.c delete mode 100644 src/CCW/ch/springnabnut.c delete mode 100644 src/CCW/ch/summeroutsidegnawty.c delete mode 100644 src/CCW/ch/swimminggnawty.c create mode 100644 src/CCW/ch/zubba.c create mode 100644 src/CCW/ch/zubba_hive_npc.c delete mode 100644 src/CCW/ch/zubbahoneylump.c delete mode 100644 src/CCW/checksums.c delete mode 100644 src/CCW/eyrie_baby.c create mode 100644 src/CCW/flower.c create mode 100644 src/CCW/minigame_zubba.c delete mode 100644 src/CCW/nabnut_winter.c create mode 100644 src/CCW/seasonal_switch.c create mode 100644 src/CCW/snarebear_proximity.c delete mode 100644 src/CCW/zubba.c delete mode 100644 src/CCW/zubba_hive_npc.c rename src/{fight => FINALE/ch}/chbossjinjo.c (99%) rename src/{fight => FINALE/ch}/chbossjinjobase.c (95%) rename src/{fight => FINALE/ch}/chbossshadow.c (97%) rename src/{fight => FINALE/ch}/chfinalboss.c (95%) rename src/{fight => FINALE/ch}/chjinjonator.c (99%) rename src/{fight => FINALE/ch}/chjinjonatorbase.c (85%) rename src/{fight => FINALE}/chgreenblast.c (100%) rename src/{fight => FINALE}/chspellbarrier.c (100%) rename src/{fight => FINALE}/chspellfireball.c (100%) rename src/{fight => FINALE}/chstonejinjo.c (100%) rename src/{fight => FINALE}/fight.c (99%) rename src/{fight => FINALE}/fight.h (94%) rename src/FP/{fpspawnqueue.c => actor_spawninit.c} (99%) create mode 100644 src/FP/bss_pad.c rename src/FP/{ => ch}/wozza_fire.c (100%) delete mode 100644 src/FP/checksums.c rename src/FP/{ma => mapstate}/slalom.c (91%) rename src/FP/{ch/boggyraceflag2.c => mapstate/slalom2ctrl.c} (89%) rename src/FP/{ch/boggyraceflag1.c => mapstate/slalomctrl.c} (94%) rename src/FP/{ma => mapstate}/snowbutton.c (100%) rename src/FP/{ma => mapstate}/snowy.c (100%) rename src/GV/{gvspawnqueue.c => actor_spawninit.c} (84%) create mode 100644 src/GV/bss_pad.c rename src/GV/{ => ch}/cactus.c (100%) rename src/GV/{ => ch}/carpet1.c (100%) rename src/GV/{ => ch}/carpet2.c (90%) rename src/GV/{magiccarpetshadow.c => ch/carpet_shadow.c} (61%) rename src/GV/ch/{eggpot.c => egg_pot.c} (95%) rename src/GV/{ => ch}/handshadow.c (100%) create mode 100644 src/GV/ch/jinxy.c rename src/GV/{ => ch}/jinxy_head.c (100%) rename src/GV/{ => ch}/rubee.c (56%) delete mode 100644 src/GV/checksums.c delete mode 100644 src/GV/magiccarpet2.c rename src/GV/{ch => }/mazectrl.c (90%) rename src/GV/{sandybutteggtoll.c => pyramid_trigger.c} (69%) rename src/{lair/lairspawnqueue.c => LAIR/actor_spawninit.c} (73%) create mode 100644 src/LAIR/bss_pad.c rename src/{lair => LAIR}/ch/brentilda.c (95%) rename src/{lair => LAIR}/ch/cauldron.c (98%) rename src/{lair => LAIR}/ch/cheato.c (96%) rename src/{lair => LAIR/ch}/fall_damagedetect.c (100%) rename src/{lair => LAIR/ch}/ff_lava_fireball.c (100%) rename src/{lair => LAIR/ch}/ff_lava_fireball_actor.c (100%) rename src/{lair => LAIR}/ch/gruntling.c (99%) rename src/{lair/ch/lairgruntilda.c => LAIR/ch/grunty_final.c} (95%) rename src/{lair/ch/refillpillow.c => LAIR/ch/item_pillows.c} (94%) rename src/{lair/ch/furnacefunprizes.c => LAIR/ch/minigame_ffprize.c} (97%) rename src/{lair => LAIR/ch}/tooty_parade.c (100%) rename src/{lair => LAIR}/ff_manager.c (97%) rename src/{lair => LAIR}/jigsawpicture.c (79%) rename src/MM/{mmspawnqueue.c => actor_spawninit.c} (97%) delete mode 100644 src/MM/ch/conga.h delete mode 100644 src/MM/ch/orangepad.h delete mode 100644 src/MM/checksums.c rename src/MMM/{mmmspawnqueue.c => actor_spawninit.c} (55%) create mode 100644 src/MMM/bss_pad.c rename src/MMM/ch/{cemetarypot.c => flowerpot.c} (73%) rename src/MMM/ch/{skeleton.c => limbo.c} (95%) rename src/MMM/ch/{portraitchompa.c => portrait_chompa.c} (98%) delete mode 100644 src/MMM/checksums.c create mode 100644 src/RBB/actor_spawninit.c create mode 100644 src/RBB/bss_pad.c rename src/RBB/ch/{seamangrublin.c => seaman_grublin.c} (97%) create mode 100644 src/RBB/ch/siren.c delete mode 100644 src/RBB/checksums.c delete mode 100644 src/RBB/rbbspawnqueue.c delete mode 100644 src/RBB/siren.c rename src/SM/{ => ch}/bottles_movecheck.c (100%) rename src/SM/{ => ch}/furniture.c (100%) rename src/SM/{ => ch}/quarrie.c (94%) delete mode 100644 src/SM/checksums.c rename src/SM/{smspawnqueue.c => crc.c} (80%) rename src/TTC/{ma => }/castle.c (98%) delete mode 100644 src/TTC/ch/lockup.h delete mode 100644 src/TTC/checksums.c rename src/core1/{ => io}/bamotor.c (78%) rename src/core1/{ => io}/pfsmanager.c (93%) create mode 100644 src/core1/math/longlong_arith.c create mode 100644 src/core1/math/longlong_convert.c rename src/core1/{mlmtx.c => math/matrix_stack.c} (95%) rename src/core1/{gu_matrix.c => math/ml.c} (99%) rename src/core1/{gu_perspective.c => math/mlmtx.c} (93%) rename src/core1/{ml.c => math/vector.c} (88%) delete mode 100644 src/core1/musicplayer.h rename src/core1/{sns.c => stopnswop_payload.c} (99%) create mode 100644 src/core1/syncprintf.c rename src/core2/{gccube.c => actor_cubebounds.c} (99%) rename src/core2/anim/{animcache.c => anim_cache.c} (98%) rename src/core2/anim/{betavent.c => anim_sequencestruct.c} (88%) rename src/core2/anim/{chumpfish.c => anim_spriteframe.c} (99%) rename src/core2/anim/{animtexturecache.c => anim_texturecache.c} (98%) rename src/core2/anim/{anctrl.c => controller.c} (99%) rename src/core2/anim/{anseq.c => sequence.c} (99%) rename src/core2/anim/{skeletalanim.c => skeletal.c} (99%) rename src/core2/ba/{anim.c => ba_anim.c} (88%) create mode 100644 src/core2/ba/ba_animstate.c rename src/core2/ba/{babounds.c => ba_bounds.c} (93%) rename src/core2/ba/{babuzz.c => ba_buzz.c} (98%) rename src/core2/ba/{carriedobj.c => ba_carriedobj.c} (93%) rename src/core2/ba/{carry.c => ba_carry.c} (95%) rename src/core2/ba/{iFrame.c => ba_eyeblink.c} (92%) rename src/core2/ba/{baeyes.c => ba_eyes.c} (88%) rename src/core2/ba/{falldamage.c => ba_falldamage.c} (96%) rename src/core2/ba/{baflag.c => ba_flag.c} (95%) rename src/core2/ba/{flap.c => ba_flap.c} (98%) rename src/core2/ba/{hazards.c => ba_groundsurface.c} (96%) rename src/core2/ba/{bainput.c => ba_input.c} (98%) rename src/core2/ba/{bakey.c => ba_key.c} (98%) rename src/core2/ba/{balookat.c => ba_lookat.c} (98%) rename src/core2/ba/{marker.c => ba_marker.c} (95%) rename src/core2/ba/{model.c => ba_model.c} (94%) rename src/core2/ba/{playermodel.c => ba_modelselect.c} (87%) rename src/core2/ba/{physics.c => ba_physics.c} (96%) rename src/core2/ba/{playerposition.c => ba_position.c} (87%) rename src/core2/ba/{drone.c => ba_scripted.c} (98%) rename src/core2/ba/{basfx.c => ba_sfx.c} (99%) create mode 100644 src/core2/ba/ba_state.c rename src/core2/ba/{bastick.c => ba_stick.c} (98%) rename src/core2/ba/{batimer.c => ba_timer.c} (93%) delete mode 100644 src/core2/ba/bsmethods.c delete mode 100644 src/core2/ba/iFrame.h delete mode 100644 src/core2/ba/modelappendages.c rename src/core2/bs/{bFlip.c => backflip.c} (94%) rename src/core2/bs/{bBarge.c => beak_barge.c} (94%) rename src/core2/bs/{bFly.c => beak_bomb.c} (85%) rename src/core2/bs/{bbuster.c => beak_buster.c} (94%) rename src/core2/bs/{bEggHead.c => beak_egg_aim.c} (63%) rename src/core2/bs/{bEggAss.c => beak_egg_fire.c} (72%) rename src/core2/bs/{bPeck.c => beak_peck.c} (92%) rename src/core2/bs/{bSwim.c => beak_swim.c} (89%) rename src/core2/bs/{beeFly.c => bee_fly.c} (91%) rename src/core2/bs/{beeMain.c => bee_main.c} (85%) rename src/core2/bs/{bsList.c => bs_list.c} (97%) rename src/core2/bs/{bsStoredState.c => bs_storedstate.c} (97%) rename src/core2/bs/{bFlap.c => flap_flip.c} (94%) rename src/core2/bs/{ow.c => hurt.c} (98%) rename src/core2/bs/{jig.c => jiggy_dance.c} (92%) rename src/core2/bs/{drone.c => scripted.c} (97%) rename src/core2/bs/{droneenter.c => scripted_enter.c} (97%) rename src/core2/bs/{dronegoto.c => scripted_goto.c} (94%) rename src/core2/bs/{dronelook.c => scripted_look.c} (84%) rename src/core2/bs/{dronexform.c => scripted_transform.c} (91%) rename src/core2/bs/{dronevanish.c => scripted_vanish.c} (96%) rename src/core2/bs/{bShock.c => shock_spring.c} (86%) rename src/core2/bs/{bLongLeg.c => stilt_stride.c} (88%) rename src/core2/bs/{bTrot.c => talon_trot.c} (92%) rename src/core2/bs/{washy.c => washing_machine.c} (90%) rename src/core2/bs/{bWhirl.c => wonderwing.c} (90%) rename src/core2/{nc => camera}/camera_debug_freecam.c (98%) rename src/core2/{nc => camera}/camera_ease.c (96%) rename src/core2/{nc => camera}/camera_focus.c (96%) rename src/core2/{nc => camera}/camera_focustarget.c (97%) rename src/core2/{nc => camera}/camera_fog.c (98%) rename src/core2/{nc => camera}/camera_motor1.c (94%) rename src/core2/{nc => camera}/camera_motor2.c (99%) rename src/core2/{nc => camera}/camera_nodemanager.c (94%) rename src/core2/{nc => camera}/camera_position.c (98%) rename src/core2/{nc => camera}/camera_set.c (98%) rename src/core2/{nc => camera}/cameranode_type1.c (99%) rename src/core2/{nc => camera}/cameranode_type2.c (98%) rename src/core2/{nc => camera}/cameranode_type3.c (99%) rename src/core2/{nc => camera}/cameranode_type4.c (96%) rename src/core2/{nc => camera}/cameranodelist.c (99%) create mode 100644 src/core2/camera/dynamicCam1.c rename src/core2/{nc => camera}/dynamicCam10.c (96%) rename src/core2/{nc => camera}/dynamicCam11.c (98%) rename src/core2/{nc => camera}/dynamicCam12.c (99%) rename src/core2/{nc => camera}/dynamicCam13.c (98%) rename src/core2/{nc => camera}/dynamicCam3.c (81%) rename src/core2/{nc/fly.c => camera/dynamicCam4.c} (70%) rename src/core2/{nc => camera}/dynamicCam5.c (87%) rename src/core2/{nc => camera}/dynamicCam8.c (97%) rename src/core2/{nc => camera}/dynamicCam9.c (86%) rename src/core2/{nc => camera}/dynamicCamA.c (98%) rename src/core2/{nc => camera}/dynamicCamB.c (98%) rename src/core2/{nc => camera}/dynamicCamC.c (91%) rename src/core2/{nc/die.c => camera/dynamicCamD.c} (73%) rename src/core2/{nc => camera}/dynamicCamF.c (95%) rename src/core2/{nc => camera}/dynamicCamera.c (85%) rename src/core2/{nc/1p.c => camera/firstpersoncamera.c} (74%) rename src/core2/{nc => camera}/randomCamera.c (97%) rename src/core2/{nc => camera}/staticCamera.c (96%) rename src/core2/ch/{climbBase.c => climb_base.c} (95%) delete mode 100644 src/core2/ch/gameSelect.h rename src/core2/ch/{grillechompa.c => grill_chompa.c} (97%) delete mode 100644 src/core2/ch/jiggy.h create mode 100644 src/core2/ch/level_collectible.c delete mode 100644 src/core2/ch/levelcollectible.c create mode 100644 src/core2/ch/mumbo_sign.c delete mode 100644 src/core2/ch/mumbosign.c delete mode 100644 src/core2/checksums.c rename src/core2/collision/{scarabbeetle.c => raycastmap.c} (97%) rename src/core2/{gc => context}/bound.c (98%) rename src/core2/{gc => context}/dialog.c (97%) rename src/core2/{gc => context}/enter_text_trigger.c (78%) rename src/core2/{gc/gameoversign.c => context/gameover.c} (85%) rename src/core2/{gc/section.c => context/map_info.c} (99%) rename src/core2/{gc/overlaycopyright.c => context/overlay_copyright.c} (97%) rename src/core2/{gc/overlaynocontroller.c => context/overlay_nocontroller.c} (97%) rename src/core2/{gc/overlaypressstart.c => context/overlay_pressstart.c} (94%) rename src/core2/{gc => context}/parade.c (99%) rename src/core2/{gc/pauseMenu.c => context/pause_menu.c} (95%) rename src/core2/{gc => context}/pictureframe.c (89%) rename src/core2/{gc => context}/sky.c (88%) rename src/core2/{gc => context}/transition.c (94%) rename src/core2/{gc => context}/zoombox.c (98%) rename src/core2/{mumboshandwithpicture.c => demo_ctrl.c} (68%) rename src/core2/{demo.c => demo_input.c} (91%) delete mode 100644 src/core2/dialog/progressDialog.c create mode 100644 src/core2/dialog/progress_dialogs.c rename src/core2/{fla.c => freelist.c} (99%) rename src/core2/fx/{cutscene_actors.c => background_decor.c} (69%) rename src/core2/fx/{piranhaWaterParticles.c => droplet.c} (94%) rename src/core2/fx/{eggshatter.c => effect_eggshatter.c} (98%) rename src/core2/fx/{explosionripple.c => effect_generic.c} (94%) rename src/core2/fx/{ripple.c => effect_ripple_spawn.c} (99%) create mode 100644 src/core2/fx/effect_soundemit.c rename src/core2/fx/{shoesparkle.c => effect_sparkle.c} (50%) rename src/core2/fx/{sparkle.c => effect_sparkle_spawn.c} (99%) rename src/core2/fx/{banjokazooiesign.c => effect_spriteanim.c} (61%) rename src/core2/fx/{badShad.c => enemy_shadow.c} (93%) rename src/core2/fx/{commonParticle.c => projectile_manager.c} (96%) delete mode 100644 src/core2/fx/weather_emitter.c delete mode 100644 src/core2/gc/dialog.h rename src/core2/level/{levelspecificflags.c => specificflags.c} (82%) rename src/core2/map/{mapModel.c => model.c} (93%) rename src/core2/map/{mapsavestate.c => savestate.c} (99%) rename src/core2/map/{mapspecificflags.c => specificflags.c} (85%) rename src/core2/model/{modelRender.c => render.c} (97%) rename src/core2/{mumbo.c => mumbo_transforms.c} (74%) delete mode 100644 src/core2/nc/dynamicCam1.c rename src/core2/particle/{particleemittermanager.c => accel.c} (98%) rename src/core2/particle/{dustemitter.c => colordefault.c} (98%) rename src/core2/particle/{commonParticleTypeMap.c => factory.c} (98%) rename src/core2/{propModelList.c => prop_assetcache.c} (99%) rename src/core2/quiz/{quizquestionaskedbitfield.c => bitfield.c} (81%) rename src/core2/quiz/{minigame.c => minigamemanager.c} (98%) rename src/core2/{honeycombscore.c => score_honeycomb.c} (97%) rename src/core2/{jiggyscore.c => score_jiggy.c} (90%) rename src/core2/{mumboscore.c => score_mumbo.c} (97%) rename src/core2/scorequeue/{airscore.c => drawui_air.c} (99%) rename src/core2/scorequeue/{healthscore.c => drawui_health.c} (99%) rename src/core2/scorequeue/{honeycarrierscore.c => drawui_honeycarrier.c} (99%) rename src/core2/scorequeue/{jinjoscore.c => drawui_jinjo.c} (99%) rename src/core2/scorequeue/{lifescore.c => drawui_lives.c} (99%) rename src/core2/scorequeue/{common3score.c => drawui_models.c} (89%) rename src/core2/scorequeue/{common2score.c => drawui_sprites.c} (97%) rename src/core2/scorequeue/{common1score.c => drawui_stub.c} (91%) rename src/core2/{fx/weather_snow.c => sfx/filedata.c} (78%) rename src/core2/{fx/weather.c => sfx/init.c} (98%) rename src/core2/{fx/weather_leaves.c => sfx/playstate.c} (97%) rename src/core2/{fx/weather_rain.c => sfx/streamctrl.c} (97%) rename src/core2/{snackerctl.c => snacker_ctl.c} (95%) rename src/core2/{spawnqueue.c => spawn_queue.c} (61%) rename src/core2/{statetimer.c => state_timer.c} (97%) rename src/core2/{timedfuncqueue.c => timed_funcqueue.c} (99%) rename src/core2/{vla.c => vector.c} (92%) rename src/core2/vtx/{gclights.c => lighting.c} (94%) rename src/cutscenes/{cutscenesspawnqueue.c => actor_spawninit.c} (99%) create mode 100644 src/cutscenes/bss_pad.c rename src/cutscenes/{theendsign.c => character_parade.c} (79%) delete mode 100644 src/cutscenes/checksums.c rename src/cutscenes/{ => fx}/glow_sparkle.c (100%) rename src/cutscenes/{ => fx}/smoke.c (100%) rename src/cutscenes/{ => fx}/sparkle.c (100%) delete mode 100644 src/emptyLvl/checksums.c delete mode 100644 src/fight/checksums.c delete mode 100644 src/lair/checksums.c delete mode 100644 src/lair/jigsawpicture.h rename src/{emptyLvl => overlay_stub}/empty_level.c (75%) delete mode 100644 src/port/Controller/Mapper.cpp delete mode 100644 src/port/Controller/Mapper.h delete mode 100644 src/port/DevTools/FlagTracer.cpp delete mode 100644 src/port/DevTools/ThreadWatchdog.cpp delete mode 100644 src/port/DevTools/ThreadWatchdog.h create mode 100644 src/port/Enhancements/Camera/OrbitCameraCore.cpp create mode 100644 src/port/Enhancements/Camera/OrbitCameraCore.h delete mode 100644 src/port/Enhancements/Cosmetics/PlayerColors.cpp delete mode 100644 src/port/Enhancements/Cosmetics/PlayerColors.h delete mode 100644 src/port/Enhancements/Cutscenes/IntroLogos.cpp delete mode 100644 src/port/Enhancements/Fixes/TransientLevelState.cpp create mode 100644 src/port/Enhancements/Gameplay/DamageScale.cpp delete mode 100644 src/port/Enhancements/Gameplay/Difficulty.cpp create mode 100644 src/port/Enhancements/JinjoRetention/JinjoRetention.cpp create mode 100644 src/port/Enhancements/JinjoRetention/JinjoRetention.h create mode 100644 src/port/Enhancements/NoteRetention/NoteRetention.cpp create mode 100644 src/port/Enhancements/NoteRetention/NoteRetention.h delete mode 100644 src/port/Enhancements/Retention/JinjoRetention.cpp delete mode 100644 src/port/Enhancements/Retention/NoteRetention.cpp delete mode 100644 src/port/Enhancements/Retention/Retention.cpp delete mode 100644 src/port/Enhancements/Retention/Retention.h delete mode 100644 src/port/Enhancements/Retention/WormSync.cpp delete mode 100644 src/port/FilePicker.cpp delete mode 100644 src/port/FilePicker.h create mode 100644 src/port/Interpolation/AdaptiveFps.cpp create mode 100644 src/port/Interpolation/AdaptiveFps.h delete mode 100644 src/port/LaunchArgs.cpp delete mode 100644 src/port/LaunchArgs.h delete mode 100644 src/port/Network/Anchor/FightSync.c delete mode 100644 src/port/Network/Anchor/FightSync.h delete mode 100644 src/port/Network/Anchor/JigsawPedestal.cpp delete mode 100644 src/port/Network/Anchor/JigsawPedestal.h delete mode 100644 src/port/Network/Anchor/Packets/BreakObject.cpp delete mode 100644 src/port/Network/Anchor/Packets/CarryThrow.cpp delete mode 100644 src/port/Network/Anchor/Packets/CollectItem.cpp delete mode 100644 src/port/Network/Anchor/Packets/EggToll.cpp delete mode 100644 src/port/Network/Anchor/Packets/FightEvent.cpp delete mode 100644 src/port/Network/Anchor/Packets/FightState.cpp delete mode 100644 src/port/Network/Anchor/Packets/FightUpdate.cpp delete mode 100644 src/port/Network/Anchor/Packets/HutSmash.cpp delete mode 100644 src/port/Network/Anchor/Packets/JiggyCrane.cpp delete mode 100644 src/port/Network/Anchor/Packets/PedestalOwner.cpp delete mode 100644 src/port/Network/Anchor/Packets/PuzzleStep.cpp delete mode 100644 src/port/Network/Anchor/Packets/ScopedFlag.cpp delete mode 100644 src/port/Network/Anchor/Packets/ScopedState.cpp delete mode 100644 src/port/Network/Anchor/Packets/SetAbility.cpp delete mode 100644 src/port/Network/Anchor/Packets/SetItemCount.cpp delete mode 100644 src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp delete mode 100644 src/port/Network/Anchor/Packets/SpawnJiggy.cpp delete mode 100644 src/port/Network/Anchor/Packets/WaterRise.cpp delete mode 100644 src/port/OS/OS.h delete mode 100644 src/port/OS/OS_AI.cpp delete mode 100644 src/port/OS/OS_Cont.cpp delete mode 100644 src/port/OS/OS_Mesg.cpp delete mode 100644 src/port/OS/OS_RCP.cpp delete mode 100644 src/port/OS/OS_Threads.cpp delete mode 100644 src/port/OS/OS_Time.cpp delete mode 100644 src/port/OS/OS_Timer.cpp delete mode 100644 src/port/OS/OS_VI.cpp delete mode 100644 src/port/Patches/AnimVertexPatches.cpp delete mode 100644 src/port/Patches/PerfPatches.cpp delete mode 100644 src/port/Rando/CustomCollectible/CustomCollectible.cpp delete mode 100644 src/port/Rando/CustomCollectible/CustomCollectible.h delete mode 100644 src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp delete mode 100644 src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h delete mode 100644 src/port/Rando/ItemQueue.cpp delete mode 100644 src/port/Rando/ItemQueue.h delete mode 100644 src/port/Rando/ObjectBehavior/BlueEgg.cpp delete mode 100644 src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp delete mode 100644 src/port/Rando/ObjectBehavior/ExtraLife.cpp delete mode 100644 src/port/Rando/ObjectBehavior/MumboToken.cpp create mode 100644 src/port/Rando/ObjectBehavior/Prop.cpp delete mode 100644 src/port/Rando/Spoiler/File.cpp delete mode 100644 src/port/Rando/Spoiler/Generate.cpp delete mode 100644 src/port/Rando/Spoiler/RefreshOptions.cpp delete mode 100644 src/port/Rando/Spoiler/Spoiler.h delete mode 100644 src/port/Resource/Alt/AltDialogFont.cpp create mode 100644 src/port/Romhack/RomhackQuirks.cpp delete mode 100644 src/port/Romhack/RomhackRegistration.cpp delete mode 100644 src/port/Romhack/Shared/HackShared.cpp delete mode 100644 src/port/Romhack/Shared/HackShared.h delete mode 100644 src/port/Romhack/Shared/ProximityDialogs.cpp delete mode 100644 src/port/Romhack/Shared/ProximityDialogs.h delete mode 100644 src/port/Romhack/Shared/StealthNoise.cpp delete mode 100644 src/port/Romhack/Shared/StealthNoise.h delete mode 100644 src/port/Romhack/Shared/Storybook.cpp delete mode 100644 src/port/Romhack/Shared/Storybook.h delete mode 100644 src/port/Romhack/Specific/BubblingBog.cpp delete mode 100644 src/port/Romhack/Specific/CutThroatCoast.cpp delete mode 100644 src/port/Romhack/Specific/Dreamie.cpp delete mode 100644 src/port/Romhack/Specific/JiggiesOfTime.cpp delete mode 100644 src/port/Romhack/Specific/NewHorizons.cpp delete mode 100644 src/port/Romhack/Specific/Nostalgia64.cpp delete mode 100644 src/port/Romhack/Specific/TheGruntch.cpp rename src/port/{OS/libultra.c => stub.c} (62%) diff --git a/.github/macports.yml b/.github/macports.yml index de075020d..976224723 100644 --- a/.github/macports.yml +++ b/.github/macports.yml @@ -1,8 +1,6 @@ ports: - name: libsdl2 select: [ universal ] - - name: libsdl2_net - select: [ universal ] - name: libpng select: [ universal ] - name: glew diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 000000000..dfac3075b --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,48 @@ +name: Linux Validation +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Update machine + run: sudo apt update + - name: Install dependencies + run: sudo apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev libogg-dev libvorbis-dev + - name: Install latest SDL + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + wget https://www.libsdl.org/release/SDL2-2.24.1.tar.gz + tar -xzf SDL2-2.24.1.tar.gz + cd SDL2-2.24.1 + ./configure + make -j 10 + sudo make install + - name: Install latest tinyxml2 + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz + tar -xzf 10.0.0.tar.gz + cd tinyxml2-10.0.0 + mkdir -p build + cd build + cmake .. + make + sudo make install + - name: Build + run: | + cmake -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE=Release + cmake --build build-cmake -j + - name: Create Package + run: | + mkdir Lighthouse-release + mv build-cmake/Lighthouse Lighthouse-release/ + - name: Publish packaged artifacts + uses: actions/upload-artifact@v4 + with: + name: Lighthouse-linux-x64 + path: Lighthouse-release + retention-days: 1 diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml new file mode 100644 index 000000000..569dcca20 --- /dev/null +++ b/.github/workflows/mac.yml @@ -0,0 +1,23 @@ +name: MacOS Validation + +on: + pull_request: + branches: [ "*" ] + +jobs: + build: + runs-on: macos-14 + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + - uses: melusina-org/setup-macports@v1 + with: + parameters: '.github/macports.yml' + - uses: hendrikmuhs/ccache-action@v1.2 + with: + key: macos # ccache-macos + - name: Build + run: | + cmake -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE=Release -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" + cmake --build build-cmake -j \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f9d670ee5..8fb69d3a2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,7 +1,6 @@ name: GenerateBuilds on: push: - pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -9,11 +8,9 @@ concurrency: jobs: generate-port-o2r: - # Same-repo branches fire both push and pull_request; only build once. - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v4 with: submodules: true - name: Extract Project Version @@ -25,7 +22,7 @@ jobs: - name: Install dependencies run: sudo apt-get install gcc g++ git cmake ninja-build lsb-release - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.23 + uses: hendrikmuhs/ccache-action@v1.2.13 with: key: ${{ runner.os }}-o2r-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | @@ -44,9 +41,8 @@ jobs: run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" make -C Torch type=release -j3 - cp -r ./libultraship/src/fast/shaders ./port Torch/cmake-build-release/torch pack port lighthouse.o2r o2r -u ${{ steps.extract_version.outputs.version }} - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@v4 with: name: lighthouse.o2r path: lighthouse.o2r @@ -56,31 +52,31 @@ jobs: needs: generate-port-o2r runs-on: windows-2022 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v4 with: submodules: recursive - name: Build run: | - cmake -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64 + cmake -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64 -DCMAKE_BUILD_TYPE=Release cmake --build ./build/x64 --config Release --parallel 10 - name: Download lighthouse.o2r - uses: actions/download-artifact@v8 + uses: actions/download-artifact@v4 with: name: lighthouse.o2r - path: ./build/x64 + path: ./build/x64/Release - name: Create Package run: | mkdir lighthouse-release mkdir lighthouse-release/debug - mv build/x64/Lighthouse.exe lighthouse-release/ - mv build/x64/lighthouse.o2r lighthouse-release/ - mv build/x64/*.pdb lighthouse-release/debug/ + mv build/x64/Release/Lighthouse.exe lighthouse-release/ + mv build/x64/Release/lighthouse.o2r lighthouse-release/ + mv build/x64/Release/*.pdb lighthouse-release/debug/ mv README.md lighthouse-release/readme.txt mv config.yml lighthouse-release/ mv assets lighthouse-release/ Invoke-WebRequest -Uri "https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt" -OutFile "lighthouse-release/gamecontrollerdb.txt" - name: Upload build - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@v4 with: name: Lighthouse-windows path: lighthouse-release @@ -89,13 +85,13 @@ jobs: needs: generate-port-o2r runs-on: macos-14 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v6 with: submodules: recursive - uses: melusina-org/setup-macports@v1 with: parameters: '.github/macports.yml' - - uses: hendrikmuhs/ccache-action@v1.2.23 + - uses: hendrikmuhs/ccache-action@v1.2 with: key: macos # ccache-macos - name: Build @@ -103,7 +99,7 @@ jobs: cmake -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE=Release -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" cmake --build build-cmake -j - name: Download lighthouse.o2r - uses: actions/download-artifact@v8 + uses: actions/download-artifact@v4 with: name: lighthouse.o2r path: ./build-cmake @@ -113,7 +109,7 @@ jobs: mv _packages/*.dmg Lighthouse.dmg mv README.md readme.txt - name: Publish packaged artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@v4 with: name: Lighthouse-mac path: | @@ -124,7 +120,7 @@ jobs: needs: generate-port-o2r runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v4 with: submodules: recursive - name: Update machine @@ -132,7 +128,7 @@ jobs: - name: Install dependencies run: sudo apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev libogg-dev libvorbis-dev - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.23 + uses: hendrikmuhs/ccache-action@v1.2.14 with: key: linux-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | @@ -187,7 +183,7 @@ jobs: sudo make install sudo cp -av /usr/local/lib/libzip* /lib/x86_64-linux-gnu/ - name: Download lighthouse.o2r - uses: actions/download-artifact@v8 + uses: actions/download-artifact@v4 with: name: lighthouse.o2r path: ./build-cmake @@ -200,12 +196,11 @@ jobs: mv README.md readme.txt mv build-cmake/*.appimage lighthouse.appimage - name: Upload build - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@v4 with: name: Lighthouse-linux path: | lighthouse.appimage - readme.txt gamecontrollerdb.txt build-switch: @@ -215,7 +210,7 @@ jobs: container: image: devkitpro/devkita64:20241023 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v4 with: submodules: recursive - name: Install dependencies @@ -234,7 +229,7 @@ jobs: mv README.md readme.txt mv build-switch/*.nro Lighthouse.nro - name: Upload build - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@v4 with: name: Lighthouse-switch path: | diff --git a/.github/workflows/switch.yml b/.github/workflows/switch.yml new file mode 100644 index 000000000..db9773c5c --- /dev/null +++ b/.github/workflows/switch.yml @@ -0,0 +1,38 @@ +name: Switch Validation +on: [pull_request] + +jobs: + build-switch: + if: false + runs-on: ubuntu-latest + container: + image: devkitpro/devkita64:20241023 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ninja-build + sudo apt-get remove -y cmake + git -C libultraship remote add nx https://github.com/YoshiCrystal9/libultraship.git + git -C libultraship fetch nx + git -C libultraship checkout nx/main-nx + wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh + sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir + cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake + cmake --build build-switch --config Release -j3 + wget -O gamecontrollerdb.txt https://github.com/mdqinc/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt + mv README.md readme.txt + mv build-switch/*.nro Lighthouse.nro + - name: Upload build + uses: actions/upload-artifact@v4 + with: + name: Lighthouse-switch + retention-days: 1 + path: | + Lighthouse.nro + config.yml + assets + gamecontrollerdb.txt \ No newline at end of file diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 000000000..a0f8ae5e1 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,20 @@ +name: Windows Validation +on: [pull_request] + +jobs: + build: + runs-on: windows-2022 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Build + run: | + cmake -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64 -DCMAKE_BUILD_TYPE=Release + cmake --build ./build/x64 + - name: Upload build + uses: actions/upload-artifact@v4 + with: + name: lighthouse-windows + path: ./build/x64/Debug + retention-days: 1 \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 5481e188f..8f556ee49 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,4 @@ branch = main [submodule "Torch"] path = Torch - url = https://github.com/HarbourMasters/Torch.git + url = https://github.com/Malkierian/Torch.git diff --git a/CMakeLists.txt b/CMakeLists.txt index b4e2ec1ad..360b6670b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # Set the project version and language -project(Lighthouse VERSION 1.0.2 LANGUAGES C CXX ASM) +project(Lighthouse VERSION 0.0.1 LANGUAGES C CXX ASM) include(FetchContent) include(cmake/lighthouse-cvars.cmake) @@ -28,7 +28,7 @@ math(EXPR PATCH_INDEX "${PROJECT_VERSION_PATCH}") # Use the patch number to select the correct word list(GET NATO_PHONETIC_ALPHABET ${PATCH_INDEX} PROJECT_PATCH_WORD) -set(PROJECT_BUILD_NAME "Split Rock ${PROJECT_PATCH_WORD}" CACHE STRING "" FORCE) +set(PROJECT_BUILD_NAME "Barnard ${PROJECT_PATCH_WORD}" CACHE STRING "" FORCE) #set(PROJECT_TEAM "SonicDcer & Lywx" CACHE STRING "" FORCE) # Get Git Information @@ -188,16 +188,12 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/properties.h.in ${CMAKE_CURRENT_SOUR set(Header_Files "resource.h") source_group("include" FILES ${Header_Files}) -# Flag enum name tables for the Flag Tracer, derived from include/enums.h. -include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateFlagNames.cmake) - # Include directories include_directories( "${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/include" "${PROJECT_SOURCE_DIR}/lib/ultralib/include" "${PROJECT_SOURCE_DIR}/src" - "${CMAKE_BINARY_DIR}/generated" ) # Collect source files to build the executable @@ -222,8 +218,6 @@ file(GLOB_RECURSE ALL_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/include/*" ) -list(FILTER ALL_FILES EXCLUDE REGEX "src/unused/") - list(APPEND ALL_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc) @@ -503,7 +497,6 @@ option(BUILD_SM64 "Build with Super Mario 64 support" OFF) option(BUILD_MK64 "Build with Mario Kart 64 support" OFF) option(BUILD_SF64 "Build with Star Fox 64 support" OFF) option(BUILD_FZERO "Build with F-Zero X support" OFF) -option(BUILD_OOT "Build with Ocarina of Time support" OFF) option(BUILD_MARIO_ARTIST "Build with Mario Artist support" OFF) option(BUILD_NAUDIO "Build with NAudio support" OFF) add_subdirectory(Torch) @@ -548,7 +541,6 @@ if(MSVC) /we4311; # pointer truncation (e.g. void* to int) /we4312; # conversion to pointer of greater size (e.g. int to void*) /we4133; # incompatible pointer types - /wd4200; # we don't care about zero-sized flexible arrays ${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT}; ${DEFAULT_CXX_EXCEPTION_HANDLING} ) @@ -698,12 +690,10 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") > ) else() - if(NOT DEFINED CPU_OPTION) - if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(CPU_OPTION -msse2 -mfpmath=sse) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") - set(CPU_OPTION -mcpu=native) - endif() + if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + set(CPU_OPTION -msse2 -mfpmath=sse) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(CPU_OPTION -mcpu=native) endif() target_compile_options(${PROJECT_NAME} PRIVATE @@ -773,8 +763,6 @@ add_custom_target( if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") install(FILES "${CMAKE_BINARY_DIR}/lighthouse.o2r" DESTINATION . COMPONENT ${PROJECT_NAME}) - install(DIRECTORY "${CMAKE_SOURCE_DIR}/assets/" DESTINATION ./assets COMPONENT ${PROJECT_NAME}) - install(FILES "${CMAKE_BINARY_DIR}/config.yml" DESTINATION . COMPONENT ${PROJECT_NAME}) endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") diff --git a/README.md b/README.md index 2ef18d4ce..0597f77ba 100644 --- a/README.md +++ b/README.md @@ -2,44 +2,39 @@ [comment]: <> (Todo: Make Dark Mode Image) # Lighthouse -Harbour Masters port of Banjo Kazooie -Lead Developer: -* Malkierian - -Developers: -* JeodC -* Caladius +Lead Developers: +TODO: fill in ## Discord + Official Discord: https://discord.com/invite/shipofharkinian -If you're having any trouble after reading through this `README`, feel free ask for help in the Lighthouse text channels. Please keep in mind that we do not condone piracy. +If you're having any trouble after reading through this `README`, feel free ask for help in the Lighthouse Support text channels. Please keep in mind that we do not condone piracy. # Quick Start Lighthouse does not include any copyrighted assets. You are required to provide a supported copy of the game. ### 1. Verify your ROM dump -Any retail version listed below is supported. You can verify you have dumped a supported copy of the game by using the SHA-1 File Checksum Online at https://www.romhacking.net/hash/. +The supported ROMs are US 1.0 and US 1.1 Rev A versions. You can verify you have dumped a supported copy of the game by using the SHA-1 File Checksum Online at https://www.romhacking.net/hash/. -* `baserom.us.v10.z64`: `1fe1632098865f639e22c11b9a81ee8f29c75d7a` -* `baserom.us.v11.z64`: `ded6ee166e740ad1bc810fd678a84b48e245ab80` -* `baserom.jp.z64`: `90726d7e7cd5bf6cdfd38f45c9acbf4d45bd9fd8` -* `baserom.pal.z64`: `bb359a75941df74bf7290212c89fbc6e2c5601fe` +- `baserom.us.v10.z64`: `1fe1632098865f639e22c11b9a81ee8f29c75d7a` +- `baserom.us.v11.z64`: `ded6ee166e740ad1bc810fd678a84b48e245ab80` +- `baserom.jp.z64`: `90726d7e7cd5bf6cdfd38f45c9acbf4d45bd9fd8` +- `baserom.pal.z64`: `bb359a75941df74bf7290212c89fbc6e2c5601fe` -If you have multiple regions of the game and want to use them as language packs, see `# Language Packs` below. +TODO: add info about languages ### 2. Verify your ROM is in .z64 format Your ROM needs to be in .z64 format. If it's in .n64 format, use the following to convert it to a .z64: https://hack64.net/tools/swapper.php -### 3. Download Lighthouse from [Releases](https://github.com/HarbourMasters/Lighthouse/releases) - -### 4. Generating the OTR from the ROM and Play! +### 2. Download Lighthouse from [Releases](https://github.com/HarbourMasters/Lighthouse/releases) +### 3. Generating the OTR from the ROM and Play! #### Windows * Extract every file from the zip into a folder of your choosing. -* Run lighthouse.exe and select your compatible ROM. +* Run lighthouse.exe and select your US 1.0 or US 1.1 ROM. #### Linux * Extract every file from the zip into a folder of your choosing. @@ -47,57 +42,56 @@ Your ROM needs to be in .z64 format. If it's in .n64 format, use the following t #### MacOS * Extract every file from the zip into a folder of your choosing. -* Run lighthouse and select your compatible ROM. +* Run lighthouse and select your US 1.0 or US 1.1 ROM. -# Configuration +#### Nintendo Switch +* Run one of the PC releases to generate an `sf64.o2r` file. After launching the game on PC, you will be able to find these files in the same directory as `lighthouse.exe` or `lighthouse.appimage`. +* Copy the files to your sd card -Lighthouse ships with a file with many standard controller mappings that can be used as-is with most controllers. If your controller isn't recognized by Lighthouse, or isn't working properly, you can create your own custom mapping using the built-in mapper in the Settings menu. +# Configuration ### Default keyboard configuration -| N64 | A | B | L | R | Z | Start | Analog stick | C buttons | D-Pad | -| - | - | - | - | - | - | - | - | - | - | -| Keyboard | X | C | E | R | Z | Space | WASD | Arrow keys | TFGH | +| N64 | A | B | Z | Start | Analog stick | C buttons | D-Pad | +| - | - | - | - | - | - | - | - | +| Keyboard | X | C | Z | Space | WASD | Arrow keys | TFGH | ### Other shortcuts | Keys | Action | | - | - | -| ESC | Toggle menubar | -| Ctrl+R / ⌘R | Reset | +| F1 | Toggle menubar | +| F4 | Reset | | F11 | Fullscreen | | Tab | Toggle Alternate assets | ### Graphics Backends -Currently, there are three rendering APIs supported: DirectX11 (Windows), OpenGL (all platforms), and Metal (macOS). You can change which API to use in the `Settings` menu of the menubar, which requires a restart. If you're having an issue with crashing, you can change the API in the `lighthouse.cfg.json` file by finding the line `"Backend":{`... and changing the `id` value to `2` and set the `Name` to `OpenGL`. `DirectX 11` with id `1` is the default on Windows. `Metal` with id `3` is the default on macOS. - -# Language Packs - -Lighthouse supports using multiple regions of Banjo-Kazooie as language packs. Generate your base `bk.o2r` file and once Lighthouse has started, open the imgui menu. Under General -> Languages, you will be able to select another ROM to extract as a language pack. PAL supports UK, French, and German, and Japanese adds Japanese support. After the language pack is generated, the language it brings will be added to the dropdown menu. -# Romhacks +TODO: verify this info -Many romhacks can be extracted from patched ROMs and used as mods with Lighthouse. This can be done in-game using the Romhacks menu in the Settings section. If any hack isn't fully supported, the menu should inform you when extracting the mod. Most supported romhacks currently haven't been fully tested, so there may still be some issues. - -_NOTE: When using romhacks, only US v1.0 is supported, inherited from Banjo's Backpack. Therefore, it is recommended to use **US v1.0** as your base `bk.o2r` file. +Currently, there are three rendering APIs supported: DirectX11 (Windows), OpenGL (all platforms), and Metal (macOS). You can change which API to use in the `Settings` menu of the menubar, which requires a restart. If you're having an issue with crashing, you can change the API in the `lighthouse.cfg.json` file by finding the line `"Backend":{`... and changing the `id` value to `3` and set the `Name` to `OpenGL`. `DirectX 11` with id `2` is the default on Windows. `Metal` with id `4` is the default on macOS. # Custom Assets - Custom assets are packed in `.o2r` or `.otr` files. To use custom assets, place them in the `mods` folder. If you're interested in creating and/or packing your own custom asset `.o2r`/`.otr` files, check out the following tools: * [**retro - OTR and O2R generator**](https://github.com/HarbourMasters64/retro) -* [**fast64 - Blender plugin (Note that BK64 is not supported at this time)**](https://github.com/HarbourMasters/fast64) +* [**fast64 - Blender plugin (Note that SF64 is not supported at this time)**](https://github.com/HarbourMasters/fast64) # Development - ### Building + +TODO: add a main branch + If you want to manually compile Lighthouse, please consult the [building instructions](https://github.com/HarbourMasters/Lighthouse/blob/main/docs/BUILDING.md). ### Playtesting -If you want to playtest a continuous integration build, you can find them at the links below. Keep in mind that these are for playtesting only, and you will likely encounter bugs and possibly crashes. +If you want to playtest a continuous integration build, you can find them at the links below. Keep in mind that these are for playtesting only, and you will likely encounter bugs and possibly crashes. + +TODO: replace these with lighthouse builds -* [Windows](https://nightly.link/HarbourMasters/Lighthouse/workflows/main/main/Lighthouse-windows.zip) -* [macOS](https://nightly.link/HarbourMasters/Lighthouse/workflows/main/main/Lighthouse-mac.zip) -* [Linux](https://nightly.link/HarbourMasters/Lighthouse/workflows/main/main/Lighthouse-linux.zip) +* [Windows](https://nightly.link/HarbourMasters/Starship/workflows/main/main/starship-windows.zip) +* [macOS](https://nightly.link/HarbourMasters/Starship/workflows/main/main/starship-mac-x64.zip) +* [Linux](https://nightly.link/HarbourMasters/Starship/workflows/main/main/Starship-linux.zip) +* [Switch](https://nightly.link/HarbourMasters/Starship/workflows/main/main/Starship-switch.zip) @@ -108,5 +102,4 @@ If you want to playtest a continuous integration build, you can find them at the # Special Thanks: -* The Banjo decomp team -* Fredomato, scorched11 for work on rando +TODO: fill in diff --git a/Torch b/Torch index f89e94467..75956acb7 160000 --- a/Torch +++ b/Torch @@ -1 +1 @@ -Subproject commit f89e944671b406615246685a5a60b65e48ab01f8 +Subproject commit 75956acb7c2210427d3ac4cc7213421f6e1c490c diff --git a/assets/yaml/jp/rev0/soundfont.yaml b/assets/yaml/jp/rev0/soundfont.yaml index ee925d2ef..e0d1e89b1 100644 --- a/assets/yaml/jp/rev0/soundfont.yaml +++ b/assets/yaml/jp/rev0/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xDA80A0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xEC7890 size: 0x9FB0 symbol: soundfont2ctl diff --git a/assets/yaml/pal/rev0/soundfont.yaml b/assets/yaml/pal/rev0/soundfont.yaml index b549551f0..a1176d24a 100644 --- a/assets/yaml/pal/rev0/soundfont.yaml +++ b/assets/yaml/pal/rev0/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xDA8DF0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xEC85E0 size: 0x9FB0 symbol: soundfont2ctl diff --git a/assets/yaml/us/rev0/soundfont.yaml b/assets/yaml/us/rev0/soundfont.yaml index 7378d4f5d..d6220ade8 100644 --- a/assets/yaml/us/rev0/soundfont.yaml +++ b/assets/yaml/us/rev0/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xD846C0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xEA3EB0 size: 0x9FB0 symbol: soundfont2ctl diff --git a/assets/yaml/us/rev1/soundfont.yaml b/assets/yaml/us/rev1/soundfont.yaml index bb9ae6b69..138c28ffd 100644 --- a/assets/yaml/us/rev1/soundfont.yaml +++ b/assets/yaml/us/rev1/soundfont.yaml @@ -4,7 +4,7 @@ - '#include "structs.h"' soundfont1ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xD87CA0 size: 0x10DF0 symbol: soundfont1ctl @@ -17,7 +17,7 @@ soundfont1tbl: symbol: soundfont1tbl soundfont2ctl: - type: BK64:SOUNDFONT_CTL + type: BLOB offset: 0xEA7490 size: 0x9FB0 symbol: soundfont2ctl diff --git a/cmake/GenerateFlagNames.cmake b/cmake/GenerateFlagNames.cmake deleted file mode 100644 index a2b9388ef..000000000 --- a/cmake/GenerateFlagNames.cmake +++ /dev/null @@ -1,123 +0,0 @@ -# Lifts the flag enums out of include/enums.h into a lookup table for the Flag -# Tracer. Generated into the build tree so it can't drift from enums.h. - -function(_flagnames_parse_enum ENUM_NAME OUT_VAR) - set(_entries "") - set(_in_enum FALSE) - set(_next 0) - - foreach(_line IN LISTS FLAGNAMES_LINES) - if(NOT _in_enum) - if(_line MATCHES "^[ \t]*enum[ \t]+${ENUM_NAME}[ \t]*(\\{)?[ \t]*$") - set(_in_enum TRUE) - endif() - continue() - endif() - - if(_line MATCHES "^[ \t]*\\}") - break() - endif() - - string(REGEX REPLACE "//.*$" "" _clean "${_line}") - string(REGEX REPLACE "/\\*.*\\*/" "" _clean "${_clean}") - - if(_clean MATCHES "^[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*(=[ \t]*(0[xX][0-9a-fA-F]+|[0-9]+))?[ \t]*,?[ \t]*$") - set(_ident "${CMAKE_MATCH_1}") - set(_explicit "${CMAKE_MATCH_3}") - if(NOT _explicit STREQUAL "") - math(EXPR _next "${_explicit}") - endif() - list(APPEND _entries " { ${_next}, \"${_ident}\" },") - math(EXPR _next "${_next} + 1") - endif() - endforeach() - - if(_entries STREQUAL "") - message(FATAL_ERROR "GenerateFlagNames: no entries parsed for 'enum ${ENUM_NAME}'! Has enums.h changed shape?") - endif() - - string(REPLACE ";" "\n" _joined "${_entries}") - set(${OUT_VAR} "${_joined}" PARENT_SCOPE) -endfunction() - -function(_flagnames_emit_table ENUM_NAME TABLE_NAME OUT_VAR) - _flagnames_parse_enum("${ENUM_NAME}" _rows) - set(${OUT_VAR} - "// ${ENUM_NAME}\nstatic const FlagName ${TABLE_NAME}[] = {\n${_rows}\n};\n" - PARENT_SCOPE) -endfunction() - -set(FLAGNAMES_HEADER "${CMAKE_BINARY_DIR}/generated/FlagNames.generated.h") -set(FLAGNAMES_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/include/enums.h") - -file(STRINGS "${FLAGNAMES_SOURCE}" FLAGNAMES_LINES) - -set(FLAGNAMES_BODY -"// GENERATED at configure time by cmake/GenerateFlagNames.cmake from include/enums.h. -#pragma once - -struct FlagName { - int index; - const char* name; -}; -") - -foreach(_pair "file_progress_e:kFileProgressNames" "volatile_flags_e:kVolatileNames" "level_flags_e:kLevelNames") - string(REPLACE ":" ";" _pair "${_pair}") - list(GET _pair 0 _enum) - list(GET _pair 1 _table) - _flagnames_emit_table("${_enum}" "${_table}" _table_text) - string(APPEND FLAGNAMES_BODY "\n${_table_text}") -endforeach() - -set(FLAGNAMES_MAP_GROUPS - "sm_specific_flags:kSmNames:0xB" - "mm_specific_flags:kMmNames:0x1" - "ttc_specific_flags:kTtcNames:0x2" - "bgs_specific_flags:kBgsNames:0x4" - "fp_specific_flags:kFpNames:0x5" - "mmm_specific_flags:kMmmNames:0xA" - "rbb_main_specific_flags:kRbbMainNames:0x9" - "rbb_boat_room_specific_flags:kRbbBoatNames:0x9" - "ccw_zubba_specific_flags:kCcwZubbaNames:0x8" - "ccw_winter_specific_flags:kCcwWinterNames:0x8" - "lair_specific_flags:kLairNames:0x6" -) - -set(FLAGNAMES_GROUP_ROWS "") -foreach(_entry IN LISTS FLAGNAMES_MAP_GROUPS) - string(REPLACE ":" ";" _parts "${_entry}") - list(GET _parts 0 _enum) - list(GET _parts 1 _table) - list(GET _parts 2 _level) - _flagnames_emit_table("${_enum}" "${_table}" _table_text) - string(APPEND FLAGNAMES_BODY "\n${_table_text}") - list(APPEND FLAGNAMES_GROUP_ROWS - " { ${_level}, ${_table}, (int)(sizeof(${_table}) / sizeof(${_table}[0])) },") -endforeach() - -string(REPLACE ";" "\n" FLAGNAMES_GROUP_ROWS "${FLAGNAMES_GROUP_ROWS}") -string(APPEND FLAGNAMES_BODY -" -// Map-specific lookup needs the loaded level to disambiguate. -struct MapFlagGroup { - int level; - const FlagName* names; - int count; -}; - -static const MapFlagGroup kMapFlagGroups[] = { -${FLAGNAMES_GROUP_ROWS} -}; -") - -set(_existing "") -if(EXISTS "${FLAGNAMES_HEADER}") - file(READ "${FLAGNAMES_HEADER}" _existing) -endif() -if(NOT _existing STREQUAL "${FLAGNAMES_BODY}") - file(WRITE "${FLAGNAMES_HEADER}" "${FLAGNAMES_BODY}") - message(STATUS "Generated ${FLAGNAMES_HEADER}") -endif() - -set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${FLAGNAMES_SOURCE}") diff --git a/config.yml b/config.yml index 270dfe886..92309861a 100644 --- a/config.yml +++ b/config.yml @@ -19,7 +19,7 @@ ded6ee166e740ad1bc810fd678a84b48e245ab80: config: gbi: F3DEX_BK64 sort: OFFSET - logging: WARN + logging: ERROR textures: ADDITIONAL_DEFINES include_autogen: true output: @@ -34,7 +34,7 @@ bb359a75941df74bf7290212c89fbc6e2c5601fe: config: gbi: F3DEX_BK64 sort: OFFSET - logging: WARN + logging: ERROR textures: ADDITIONAL_DEFINES include_autogen: true output: @@ -49,7 +49,7 @@ bb359a75941df74bf7290212c89fbc6e2c5601fe: config: gbi: F3DEX_BK64 sort: OFFSET - logging: WARN + logging: ERROR textures: ADDITIONAL_DEFINES include_autogen: true output: diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 65d0ee921..96037377e 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -9,7 +9,7 @@ Requires: * The `MSVC v143 - VS 2022 C++ build tools` component of Visual Studio * Python 3 (can be installed manually or as part of Visual Studio) * Git (can be installed manually or as part of Visual Studio) - * Cmake version <= 3.3 (can be installed via chocolatey or manually) + * Cmake (can be installed via chocolatey or manually) During installation, check the "Desktop development with C++" feature set: @@ -22,10 +22,10 @@ It is recommended that you install Python and Git standalone, the install proces _Note: Be sure to either clone with the ``--recursive`` flag or do ``git submodule update --init`` after cloning to pull in the libultraship submodule!_ -2. Build and generate the `lighthouse.o2r` port assets archive. -3. Generate the `bk.o2r` ROM asset archive. +2. Place a Banjo-Kazooie `.z64` ROM in the `baseroms/` directory. +3. Build and generate the `bk.o2r` asset archive. -_Note: Instructions assume using powershell, however, it's recommended to use the GeneratePortO2R project in VS and the built-in extraction flow to create the asset archives +_Note: Instructions assume using powershell_ ```powershell # Navigate to the lighthouse repo within powershell. ie: cd "C:\yourpath\lighthouse" cd lighthouse @@ -216,13 +216,13 @@ cmake --build build-cmake --target clean ``` # Compatible Roms -Any retail version. See [the readme](https://github.com/HarbourMasters/Lighthouse/blob/develop/README.md#1-verify-your-rom-dump) +See [`supportedHashes.json`](supportedHashes.json) ## Getting CI to work on your fork The CI works via [Github Actions](https://github.com/features/actions) where we mostly make use of machines hosted by Github; except for the very first step of the CI process called "Extract assets". This step extracts assets from the ROM and generates the `bk.o2r` archive. -To get this step working on your fork, you'll need to enable actions for all sources in the Actions tab on GitHub. You can also add your own local runner on GitHub. +To get this step working on your fork, you'll need to add a machine to your own repository as a self-hosted runner via "Settings > Actions > Runners" in your repository settings. Make sure to add the 'asset-builder' tag to your newly added runner to assign it to run this step. To setup your runner as a service read the docs [here](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service?platform=linux). ### Runner on Windows You'll have to enable the ability to run unsigned scripts through PowerShell. To do this, open Powershell as administrator and run `set-executionpolicy remotesigned`. Most dependencies get installed as part of the CI process. You will also need to separately install 7z and add it to the PATH so `7z` can be run as a command. [Chocolatey](https://chocolatey.org/) or other package managers can be used to install it easily. diff --git a/docs/modding/LANGUAGE PACKS.md b/docs/modding/LANGUAGE PACKS.md index ef42bfc33..8164704e8 100644 --- a/docs/modding/LANGUAGE PACKS.md +++ b/docs/modding/LANGUAGE PACKS.md @@ -1,6 +1,6 @@ # Making a Language Pack -A language pack is a small companion archive that adds a new in-game language alongside the retail `bkpal.o2r` / `bkjp.o2r`. Players drop it into their `mods/~lang/` folder and pick the new language from the options menu. +A language pack is a small companion archive that adds a new in-game language alongside the retail `bkpal.o2r` / `bkjp.o2r`. Players drop it into their `mods/lang/` folder and pick the new language from the options menu. This guide walks through building one pack end to end: a **Spanish** translation, from the first export to a finished `bkes.o2r`. @@ -8,19 +8,6 @@ This guide walks through building one pack end to end: a **Spanish** translation ## 1. Export the text to editable YAML -Pack mode has to be on **before** you export. In the repo's `config.yml`, find your base ROM's entry (keyed by ROM hash) and add the `dialog_pack` flag to its `config:` block, pointing `output.binary` at your pack's filename: - -```yaml -config: - dialog_pack: true # add - output: - binary: bkes.o2r # was bk.o2r; the pack's filename -``` - -This is the one edit the pack flow makes to the base game's config, and it also redirects the normal game build - so **revert it once your pack is built**. - -Now run the export: - ``` torch modding export -s -d ``` @@ -33,13 +20,7 @@ This decodes every asset into an editable form under `/src/assets/asset | `lang/us/quizq/` | Grunty furnace quiz questions | 170 | | `lang/us/gruntyq/` | Final-boss Grunty questions | 30 | -You only edit the files you want to translate. Anything you leave alone stays in English. Next, edit the country code in **three places**: - -1. the folder name - `lang/us/` -> `lang/es/` (`es` for this example); -2. the top-level key inside each yaml you keep - `lang/us/dialog/ASSET_…` -> `lang/es/dialog/ASSET_…`; -3. both sides of every `modding.yml` entry - `assets/lang/us/…: assets/lang/us/….yaml` -> `assets/lang/es/…`. - -Then delete the asset yamls you won't be modifying and prune their `modding.yml` entries to match. +You only edit the files you want to translate. Anything you leave alone stays in English. Rename the `us` folder to your country code (`es` for this example) and delete whatever asset yamls you won't be modifying. --- @@ -77,9 +58,7 @@ lang/es/quizq/ASSET_1213_FF_QUIZ_QUESTION: - [0x83, 0xfd, 0x6c, "75"] ``` -Translate the question lines and the answer text. On each option, **keep the two bytes before the string** (`0xfd, 0x6c`) as they bind the answer to its slot; the importer rejects an option row without them. Grunty questions (`gruntyq/`) use the same shape. (Here `$` and `%` are font slots this pack draws as `¿` and `Á` once its font is in place; see below.) - -One yaml hygiene rule: always put double quotes around your translations - an unquoted `,`, `:` or `#` breaks the yaml when the pack is imported. +Translate the question lines and the answer text. On each option, **keep the two bytes before the string** (`0xfd, 0x6c`) as they bind the answer to its slot. (Here `$` and `%` are font slots this pack draws as `¿` and `Á` once its font is in place; see below.) ### How the text is encoded @@ -91,7 +70,7 @@ The dialog/quiz/grunty font (`0x6EB`) is a flat, contiguous sheet beginning at b ! " # $ % & ' ( ) * + , - . / 0-9 : ; < = > ? @ A-Z [ \ ] ^ ``` -The stock font holds only the ASCII set - `A–Z`, `0–9`, and punctuation. **None of Spanish's accents are in it**: `¡ ¿ Á É Í Ó Ú Ñ` all live in byte positions the stock font draws as ASCII symbols (`#`, `%`, `&`, …). So each accent has to be **added** to the font, and you type it as whatever slot you put it in. Our Spanish pack repaints eight symbol slots - `#` `$` `%` `&` `(` `)` `*` `+` → `¡` `¿` `Á` `É` `Í` `Ó` `Ú` `Ñ` (full table in [#5](#5-fonts-and-glyphs)). That's why `COMPA+ERO` renders *COMPAÑERO* (`+` = Ñ) and `$EST%S` renders *¿ESTÁS*. A `\xNN` escape works for any byte inside a **single-quoted** string (`'\xFD'` style - the importer decodes them, and it's the form the exporter itself emits for text carrying inline control codes). Use it for slots past `0x7E`, an extended sheet's high glyphs included; a literal backslash in such a string is `\\`. Don't put high escapes in *double*-quoted strings - there the yaml parser processes them itself, which is fine up to `\x7F` but re-encodes `\x80`–`\xFF` as two UTF-8 bytes, desyncing the text. +The stock font holds only the ASCII set - `A–Z`, `0–9`, and punctuation. **None of Spanish's accents are in it**: `¡ ¿ Á É Í Ó Ú Ñ` all live in byte positions the stock font draws as ASCII symbols (`#`, `%`, `&`, …). So each accent has to be **added** to the font, and you type it as whatever slot you put it in. Our Spanish pack repaints eight symbol slots - `#` `$` `%` `&` `(` `)` `*` `+` → `¡` `¿` `Á` `É` `Í` `Ó` `Ú` `Ñ` (full table in [#5](#5-fonts-and-glyphs)). That's why `COMPA+ERO` renders *COMPAÑERO* (`+` = Ñ) and `$EST%S` renders *¿ESTÁS*. A `\xNN` escape works for any byte inside a double-quoted string, if you'd rather not type the symbol. The same goes for lowercase `a–z` and any non-Latin script - no stock glyph, so you add one. There are two ways to add glyphs, both covered in [#5 Fonts and glyphs](#5-fonts-and-glyphs): @@ -104,7 +83,7 @@ Either way, you type the **slot**, and the replacement font makes it render. Pic ## 3. Declare the language -Two small things turn an ordinary import into a language pack: the `dialog_pack` config flag you already set in [step 1](#1-export-the-text-to-editable-yaml), and a header that names the language. +Two small things turn an ordinary import into a language pack: a header that names the language, and a config flag that puts the build into pack mode. ### Name the language @@ -119,7 +98,7 @@ strings: # optional - see "Hardcoded UI strings" below "": "" ``` -Torch turns this into the `langinfo` manifest that Lighthouse reads to build its language menu. Because it lives in your pack's source, the language list never touches the base game's asset yamls. The fields: +Torch turns this into the `langinfo` manifest that Lighthouse reads to build its language menu. Because it lives in your pack's source, you never touch the base game's canonical asset config. The fields: - **`name`** - what shows in the options menu. This label is drawn by the PC menu (not the in-game font), so the native spelling with real accents is fine here. - **`index`** - the language's slot; `0` for a single-language pack. @@ -199,9 +178,18 @@ strings: One limit comes with this approach: **word order is fixed by the engine.** The number always precedes its noun and the prefix always precedes the game number, so a language that needs the count *after* the noun can't reorder it here. The numbers and the clock are rendered by the engine and aren't translatable - only the words around them are. And the rebuild only happens for a pack that actually supplies these `strings:`; a base US/PAL game keeps its own built-in line. -### Pack mode +### Turn on pack mode + +The second piece is a `dialog_pack` flag in the config entry, plus an output name: -The `dialog_pack: true` flag was already set back in [step 1](#1-export-the-text-to-editable-yaml) - the export needs it too. At import time it's what trims the build down to just the translated assets, prefixes them under `lang//`, and builds the `langinfo` manifest. +```yaml +config: + dialog_pack: true + output: + binary: bkes.o2r +``` + +`dialog_pack: true` trims the build down to just the translated assets, prefixes them under `lang//`, and builds the `langinfo` manifest. --- @@ -211,7 +199,7 @@ The `dialog_pack: true` flag was already set back in [step 1](#1-export-the-text torch modding import o2r -s -d ``` -The importer walks the asset list: your edited yamls are re-encoded from ``, everything else parses straight from the ROM, and `dialog_pack` strips the result down to the language assets plus `langinfo`. The finished pack lands in **`/mods/~lang/`** automatically, named from your `output.binary` - `bkes.o2r` in our case. Copy that into Lighthouse's `mods/~lang/` folder and it shows up in the options menu. +The importer walks the asset list: your edited yamls are re-encoded from ``, everything else parses straight from the ROM, and `dialog_pack` strips the result down to the language assets plus `langinfo`. The finished pack lands in **`mods/lang/`** automatically, named from your `output.binary` - `bkes.o2r` in our case. Copy that into the game's `mods/lang/` folder and it shows up in the options menu. --- @@ -268,32 +256,15 @@ You can still ship that content by declaring it as an **additive** asset - a slo On import, `dialog_pack` scans your `modding.yml` for any `lang//{dialog,quizq,gruntyq,sprite}/ASSET_` the base table didn't provide and folds it into the pack. Use the **canonical (v1.0) id** for the slot (`0x11CA` for the Motzand credit) no matter which region your base ROM is. -This matters for the parade because Lighthouse keys the alternate (PAL/JP-style) parade on the *presence* of `0x11CA` in the active pack, not on the base version. A player on a plain US v1.0 `bk.o2r` who loads a pack that supplies `0x11CA` gets the Motzand parade order **and** the translated credit, while the rest of the game keeps using US assets. Cover `0x11CA` and the parade switches; omit it and the US parade is left untouched. - -### World-name banners - -The `sprite` folder covers the pause-menu **world-name banners** - the pre-rendered titles the JP release draws on its totals pages instead of bold-font text. There are twelve, one per menu page, and a pack ships them as additive sprites at `0x1600 + page`: - -| Id | Page | Id | Page | -|---|---|---|---| -| `0x1600` | Totals overview | `0x1606` | Bubblegloop Swamp | -| `0x1601` | Spiral Mountain | `0x1607` | Freezeezy Peak | -| `0x1602` | Gruntilda's Lair | `0x1608` | Gobi's Valley | -| `0x1603` | Mumbo's Mountain | `0x1609` | Mad Monster Mansion | -| `0x1604` | Treasure Trove Cove | `0x160A` | Rusty Bucket Bay | -| `0x1605` | Clanker's Cavern | `0x160B` | Click Clock Wood | +The `sprite` folder also covers **world-name banners** (one per world, at `0x1600`+). Provide them as RGBA32 intensity-mask sprites - the same format the JP cart uses - and the runtime tints each with its world's bold-font sphere colour, rendering titles as graphics instead of bold-font text. -Each page is checked on its own: ship any subset, and a page without a banner keeps drawing its name as bold-font text. A `script: 0` pack can banner just the handful of names its repainted font can't spell and leave the rest to text. Declare each one like any other additive asset (the yaml under `sprite/`, plus its `modding.yml` line). - -The sprite itself is a single-frame **RGBA32 intensity mask** - the same format as the JP originals. Draw the title as white-on-transparent artwork, not pre-coloured text: at draw time the runtime refills the mask live with the world's swirling bold-font sphere texture (the highlighted current-world page gets its own sphere; other pages the default fill). The banner renders centered on the page header at its native size and is only scaled down if it's wider than ~92% of the screen, so any sensible resolution works. - -(A `script: 1` pack that reuses the JP cart's own banners keeps their native ids - `0xE2C`–`0xE37` re-point to the `0x1600` slots automatically. `0xE38` is not a banner; it's the default fill texture the masks are filled with.) +This matters for the parade because Lighthouse keys the alternate (PAL/JP-style) parade on the *presence* of `0x11CA` in the active pack, not on the base version. A player on a plain US v1.0 `bk.o2r` who loads a pack that supplies `0x11CA` gets the Motzand parade order **and** the translated credit, while the rest of the game keeps using US assets. Cover `0x11CA` and the parade switches; omit it and the US parade is left untouched. --- ## 7. HD fonts & textures (optional) -Everything above produces an **SD** pack. Players running an HD texture pack need high-resolution versions of whatever you replaced, and those are made with a different tool: [Retro](https://github.com/HarbourMasters/retro), HarbourMasters' OTR/O2R generation tool. +Everything above produces an **SD** pack - the only kind Torch builds. Players running an HD texture pack need high-resolution versions of whatever you replaced, and those are made with a different tool: [Retro](https://github.com/HarbourMasters/retro), HarbourMasters' OTR/O2R generation tool. The two pipelines are separate - Torch doesn't build HD assets, and Retro doesn't build the SD pack. The two tiers live at different paths inside the o2r, scoped by language: diff --git a/docs/poweredbylus.darkmode.png b/docs/poweredbylus.darkmode.png deleted file mode 100644 index 2e2660814fdc04be71c078bd4e12800849de5394..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 213165 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 z

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 XE#MDywVZnl{iC6(rIPiB`OW_WIlKFS diff --git a/docs/poweredbylus.lightmode.png b/docs/poweredbylus.lightmode.png deleted file mode 100644 index 740675417b594e406d85069d54574f1dceadd7b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210989 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 PU&=nkg9`C~=wA9Cm#!~S diff --git a/include/actor.h b/include/actor.h index 88e37cde7..e786a2899 100644 --- a/include/actor.h +++ b/include/actor.h @@ -5,10 +5,6 @@ struct actorMarker_s; -// [port] actor_new is the only allocator of ActorMarkers, one per actor, so the -// marker pool and the actor array have to be sized off the same number. -#define ACTOR_POOL_SIZE 0x200 - #define ACTOR_FLAG_NONE (0) #define ACTOR_FLAG_UNKNOWN_0 (1 << 0) // 0x1 #define ACTOR_FLAG_UNKNOWN_1 (1 << 1) // 0x2 diff --git a/include/bk_math.h b/include/bk_math.h index 54928bb9a..53d2e4c3f 100644 --- a/include/bk_math.h +++ b/include/bk_math.h @@ -18,8 +18,6 @@ out[2] = c;\ } -#define TUPLE_SET(dst, value) { dst[0] = dst[1] = dst[2] = value; } - #define TUPLE_COPY(dst, src) {\ dst[0] = src[0];\ dst[1] = src[1];\ diff --git a/include/bool.h b/include/bool.h index fbbfd6d75..51ec6ef6e 100644 --- a/include/bool.h +++ b/include/bool.h @@ -3,19 +3,8 @@ #include -#ifndef __cplusplus #define NOT(boolean) ((boolean) ^ 1) #define BOOL(boolean) ((boolean) ? true : false) -#endif - -// Lighthouse [port] Decomp code uses TRUE/FALSE (typedef int bool upstream). -// Windows headers may also define these; values are identical. -#ifndef TRUE -#define TRUE true -#endif -#ifndef FALSE -#define FALSE false -#endif #if 0 #include diff --git a/include/bs_funcs.h b/include/bs_funcs.h index 16c904417..717d3099d 100644 --- a/include/bs_funcs.h +++ b/include/bs_funcs.h @@ -1,10 +1,6 @@ #ifndef __BS_FUNCS__ #define __BS_FUNCS__ -#ifdef __cplusplus -extern "C" { -#endif - //interrupt void func_802B5350(void); void func_80296608(void); @@ -46,9 +42,9 @@ void bsturn_init(void); void bsturn_update(void); void bsturn_end(void); //0xd -void timeout_transformation_init(void); -void timeout_transformation_update(void); -void timeout_transformation_end(void); +void func_802B63F8(void); +void func_802B64D0(void); +void func_802B6500(void); //bsow void bsow_init(void); void bsow_update(void); @@ -90,9 +86,9 @@ void bsbtrot_exit_init(void); void bsbtrot_exit_update(void); void bsbtrot_exit_end(void); //bsfly_knockback -void bsbfly_knockback_init(void); -void bsbfly_knockback_update(void); -void bsbfly_knockback_end(void); +void func_802A4D90(void); +void func_802A4EC8(void); +void func_802A4F44(void); //BS_1A_WONDERWING_ENTER void bsbwhirl_enter_init(void); void bsbwhirl_enter_update(void); @@ -121,17 +117,17 @@ void bsegghead_end(void); void bseggass_init(void); void bseggass_update(void); void bseggass_end(void); -//BS_1F_WALK_CREEP(void); +//BS_WALK_CREEP(void); void bswalk_creep_init(void); void bswalk_creep_update(void); //BS_20_LANDING(void); void bsstand_landing_init(void); void bsstand_landing_update(void); -//BS_21_BSHOCK_CHARGE(void); +//BS_BSHOCK_CHARGE(void); void bsbshock_charge_init(void); void bsbshock_charge_update(void); void bsbshock_charge_end(void); -//BS_22_BSHOCK_JUMP(void); +//BS_BSHOCK_JUMP(void); void bsbshock_init(void); void bsbshock_update(void); void bsbshock_end(void); @@ -143,7 +139,7 @@ void func_802A505C(void); //BS_FLY(void); void bsbfly_init(void); void bsbfly_update(void); -void bsbfly_end(void); +void func_802A3F70(void); //BS_25_LONGLEG_ENTER(void); void bsblongleg_enter_init(void); void bsblongleg_enter_update(void); @@ -152,30 +148,30 @@ void bsblongleg_enter_end(void); void bsblongleg_stand_enter(void); void bsblongleg_stand_update(void); void bsblongleg_stand_end(void); -//BS_27_LONGLEG_WALK(void); +//BS_LONGLEG_WALK(void); void bsblongleg_walk_init(void); void bsblongleg_walk_update(void); void bsblongleg_walk_end(void); -//BS_28_LONGLEG_JUMP(void); +//BS_LONGLEG_JUMP(void); void bsblongleg_jump_init(void); void bsblongleg_jump_update(void); void bsblongleg_jump_end(void); -//BS_29_LONGLEG_EXIT(void); +//BS_LONGLEG_EXIT(void); void bsblongleg_exit_init(void); void bsblongleg_exit_update(void); void bsblongleg_exit_end(void); -//BS_2A_BOMB(void); -void bsbfly_bomb_init(void); -void bsbfly_bomb_update(void); -void bsbfly_bomb_end(void); +//BS_BOMB(void); +void func_802A3F9C(void); +void func_802A411C(void); +void func_802A4404(void); //BS_2B_DIVE_IDLE(void); -void bsbdive_idle_init(void); -void bsbdive_idle_update(void); -void bsbdive_idle_end(void); +void func_802A762C(void); +void func_802A7674(void); +void func_802A7718(void); //BS_2C_DIVE_B(void); -void bsbdiveb_init(void); -void bsbdiveb_update(void); -void bsbdiveb_end(void); +void func_802A7738(void); +void func_802A7838(void); +void func_802A7A2C(void); //BS_2D_SWIM_IDLE, void bsswim_idle_init(void); void bsswim_idle_update(void); @@ -190,21 +186,21 @@ void bsjump_fall_update(void); void bsjump_fall_end(void); //BS_30_DIVE_ENTER void bsSwim_dive_init(void); -void bsSwim_dive_update(void); -void bsSwim_dive_end(void); -//BS_31_ROLL(void); +void func_802A7E2C(void); +void func_802A7F4C(void); +//BS_ROLL(void); int bstwirl_hitboxActive(void); void bstwirl_init(void); void bstwirl_update(void); void bstwirl_end(void); -//BS_32_SLIDE +//BS_SLIDE void bsslide_init(void); void bsslide_update(void); void bsslide_end(void); //0x33(void); -void bswashy_init(void); -void bswashy_update(void); -void bswashy_end(void); +void func_802B9ACC(void); +void func_802B9B14(void); +void func_802B9AAC(void); void func_802B9D00(void); //BS_34_JIG_NOTEDOOR(void); void bsjig_notedoor_init(void); @@ -214,18 +210,18 @@ void bsjig_notedoor_end(void); void bsant_idle_init(void); void bsant_idle_update(void); void bsant_idle_end(void); -//BS_36_ANT_WALK +//BS_ANT_WALK void bsant_walk_init(void); void bsant_walk_update(void); void bsant_walk_end(void); -//BS_37_ANT_WALK +//BS_ANT_JUMP void bsant_jump_init(void); void bsant_jump_update(void); void bsant_jump_end(void); //BS_39_DIVE_A -void bsswim_divea_init(void); -void bsswim_divea_update(void); -void bsswim_divea_end(void); +void func_802A7A54(void); +void func_802A7AB0(void); +void func_802A7BA8(void); //BS_3A_CARRY_IDLE(void); void bscarry_idle_init(void); void bscarry_idle_update(void); @@ -257,17 +253,17 @@ void func_802B1BF4(void); void func_802B1CF8(void); void func_802B1DA4(void); //0x40 -void bspumpkin_flush_init(void); -void bspumpkin_flush_update(void); -void bspumpkin_flush_end(void); +void func_802B2BF0(void); +void func_802B2C58(void); +void func_802B2D50(void); //BS_41_DIE void bsdie_init(void); void bsdie_update(void); void bsdie_end(void); //BS_42_DINGPOT -void bsfly_dingpotLaunch_init(void); -void bsfly_dingpotLaunch_update(void); -void bsfly_dingpotLaunch_end(void); +void func_802A5120(void); +void func_802A5190(void); +void func_802A51C0(void); //BS_43_ANT_DIE void bsant_die_init(void); void bsant_die_update(void); @@ -302,9 +298,9 @@ void bspumpkin_fall_init(void); void bspumpkin_fall_update(void); void bspumpkin_fall_end(void); //BS_4C_LANDING_IN_WATER -void bsbswim_landingInWater_init(void); -void bsbswim_landingInWater_update(void); -void bsbswim_landingInWater_end(void); +void func_802A846C(void); +void func_802A85EC(void); +void func_802A872C(void); //BS_4D_PUMPKIN_OW void __bspumpkin_ow_init(void); void __bspumpkin_ow_update(void); @@ -323,18 +319,18 @@ void bsclimb_move_init(void); void bsclimb_move_update(void); void bsclimb_move_end(void); //BS_51_CLIMB_EXIT -void bsjump_climbExit_init(void); -void bsjump_climbExit_update(void); -void bsjump_climbExit_end(void); +void func_802B1928(void); +void func_802B1A54(void); +void func_802B1BCC(void); //0x52 -void bssurf_init(void); -void bssurf_update(void); -void bssurf_end(void); +void func_802B5FD0(void); +void func_802B6064(void); +void func_802B60D0(void); void func_802B60D8(void); //0x53 -void timeout_banjo_init(void); -void timeout_banjo_update(void); -void timeout_banjo_end(void); +void func_802B6270(void); +void func_802B6314(void); +void func_802B63C8(void); //0x55 void bsblongleg_slide_init(void); @@ -342,14 +338,14 @@ void bsblongleg_slide_update(void); void bsblongleg_slide_end(void); //0x56 -void rebound_init(void); -void rebound_update(void); -void rebound_end(void); +void func_802B3868(void); +void func_802B3954(void); +void func_802B3A20(void); //0x57 -void bsbfly_beakbombend_init(void); -void bsbfly_beakbombend_update(void); -void bsbfly_beakbombend_end(void); +void func_802A4430(void); +void func_802A4548(void); +void func_802A4664(void); void func_802A505C(void); //0x58 void bsbfly_beakbomb_crash_init(void); @@ -362,9 +358,9 @@ void func_802A4CF0(void); void func_802A4D10(void); void func_802A505C(void); //0x54 -void bsbswim_die_init(void); -void bsbswim_die_update(void); -void bsbswim_die_end(void); +void func_802A7F6C(void); +void func_802A8098(void); +void func_802A82D4(void); //0x5B void bsthrow_init(void); @@ -392,9 +388,9 @@ void bscroc_fall_update(void); void bscroc_fall_end(void); //0x62 -void bsblongleg_locked_init(void); -void bsblongleg_locked_update(void); -void bsblongleg_locked_end(void); +void func_802A6394(void); +void func_802A63F0(void); +void func_802A6450(void); //0x63 void bscroc_ow_init(void); void bscroc_ow_update(void); @@ -426,9 +422,9 @@ void bswalrus_fall_update(void); void bswalrus_fall_end(void); //0x6B -void bsbee_locked_init(void); -void bsbee_locked_update(void); -void bsbee_locked_end(void); +void func_802A1F6C(void); +void func_802A1FC8(void); +void func_802A2014(void); //0x0000006C void bswalrus_ow_init(void); void bswalrus_ow_update(void); @@ -464,23 +460,23 @@ void bssplat_update(void); void bssplat_end(void); //0x00000073 -void bsrest_bs73unknown_init(void); -void bsrest_bs73unknown_update(void); -void bsrest_bs73unknown_end(void); +void func_802B3CEC(void); +void func_802B3D1C(void); +void func_802B3D6C(void); //0x00000074 -void bsrest_bs74unknown_init(void); -void bsrest_bs74unknown_update(void); -void bsrest_bs74unknown_end(void); +void func_802B3E2C(void); +void func_802B3E64(void); +void func_802B3EF4(void); //0x00000075 -void bsrest_bs75unknown_init(void); -void bsrest_bs75unknown_update(void); -void bsrest_bs75unknown_end(void); +void func_802B3D8C(void); +void func_802B3DBC(void); +void func_802B3E0C(void); //0x00000076 -void bsbfly_locked_init(void); -void bsbfly_locked_update(void); -void bsbfly_locked_end(void); +void func_802A4F74(void); +void func_802A4FC8(void); +void func_802A503C(void); //0x00000077 void bsswim_lookat_init(void); @@ -493,9 +489,9 @@ void bsbswim_lookat_update(void); void bsbswim_lookat_end(void); //0x00000079 -void bsbtrot_locked_init(void); -void bsbtrot_locked_update(void); -void bsbtrot_locked_end(void); +void bsbtrot_unk79_init(void); +void bsbtrot_unk79_update(void); +void bsbtrot_unk79_end(void); //0x0000007A void bswalk_mud_init(void); @@ -521,59 +517,59 @@ void bswalrus_sled_jump_update(void); void bswalrus_sled_jump_end(void); void func_802B98C0(void); //0x0000007F -void bsbswim_ow_init(void); -void bsbswim_ow_update(void); -void bsbswim_ow_end(void); +void func_802A7BD0(void); +void func_802A7CA8(void); +void func_802A7D74(void); //0x00000080 void bswalrus_timeout_init(void); -void bswalrus_timeout_update(void); -void bswalrus_timeout_end(void); +void func_802B9830(void); +void func_802B9880(void); //0x00000081 -void bswalrus_sledlocked_init(void); -void bswalrus_sledlocked_update(void); -void bswalrus_sledlocked_end(void); +void func_802B90D0(void); +void func_802B9130(void); +void func_802B917C(void); void func_802B98C0(void); //0x00000082 -void bswalrus_sledloseinair_init(void); -void bswalrus_sledloseinair_update(void); -void bswalrus_sledloseinair_end(void); +void func_802B95A0(void); +void func_802B963C(void); +void func_802B976C(void); void func_802B98C0(void); //0x00000085 -void bsbeemain_idle_init(void); -void bsbeemain_idle_update(void); -void bsbeemain_idle_end(void); +void func_802A1080(void); +void func_802A10D4(void); +void func_802A117C(void); //0x00000086 -void bsbeemain_walk_init(void); -void bsbeemain_walk_update(void); -void bsbeemain_walk_end(void); +void func_802A11A4(void); +void func_802A1214(void); +void func_802A12D4(void); //0x00000087 -void bsbeemain_jump_init(void); -void bsbeemain_jump_update(void); -void bsbeemain_jump_end(void); +void func_802A12FC(void); +void func_802A1438(void); +void func_802A163C(void); //0x00000088 -void bsbeemain_fall_init(void); -void bsbeemain_fall_update(void); -void bsbeemain_fall_end(void); +void func_802A1664(void); +void func_802A170C(void); +void func_802A18C8(void); //0x00000089 -void bsbeemain_ow_init(void); -void bsbeemain_ow_update(void); -void bsbeemain_ow_end(void); +void func_802A1B68(void); +void func_802A1B88(void); +void func_802A1BA8(void); //0x0000008A void bsbeemain_die_init(void); -void bsbeemain_die_update(void); -void bsbeemain_die_end(void); +void func_802A1DD8(void); +void func_802A1F2C(void); //0x0000008B -void bsbeefly_bs8Bunknown_init(void); -void bsbeefly_bs8Bunknown_update(void); -void bsbeefly_bs8Bunknown_end(void); +void func_802A0590(void); +void func_802A0630(void); +void func_802A0704(void); //0x0000008C void bsbeefly_enter(void); @@ -586,19 +582,19 @@ void bscroc_locked_update(void); void bscroc_locked_end(void); //0x0000008E -void bsant_locked_init(void); -void bsant_locked_update(void); -void bsant_locked_end(void); +void func_8029F398(void); +void func_8029F3F4(void); +void func_8029F440(void); //0x0000008F -void bspumpkin_locked_init(void); -void bspumpkin_locked_update(void); -void bspumpkin_locked_end(void); +void func_802B34A0(void); +void func_802B34F8(void); +void func_802B353C(void); //0x00000091 -void bsbfly_ow_init(void); -void bsbfly_ow_update(void); -void bsbfly_ow_end(void); +void func_802A4D30(void); +void func_802A4D50(void); +void func_802A4D70(void); void func_802A505C(void); //0x00000092 void bsant_drone_init(void); @@ -636,9 +632,9 @@ void bswalk_drone_update(void); void bswalk_drone_end(void); void bsdrone_interrupt(void); //0x00000099 -void bsbfly_drone_init(void); -void bsbfly_drone_update(void); -void bsbfly_drone_end(void); +void func_802A50B0(void); +void func_802A50D8(void); +void func_802A50F8(void); void bsdrone_interrupt(void); //0x0000009A void bsbtrot_drone_init(void); @@ -661,9 +657,9 @@ void bsbee_drone_update(void); void bsbee_drone_end(void); void bsdrone_interrupt(void); //0x0000009E -void bsclimb_locked_init(void); -void bsclimb_locked_update(void); -void bsclimb_locked_end(void); +void func_802ABCCC(void); +void func_802ABD0C(void); +void func_802ABD40(void); void func_802ABD60(void); //0x0000009F void bsant_bounce_init(void); @@ -686,9 +682,9 @@ void bswalrus_bounce_update(void); void bswalrus_bounce_end(void); //0x000000A3 -void bsbeemain_bounce_init(void); -void bsbeemain_bounce_update(void); -void bsbeemain_bounce_end(void); +void func_802A1BC8(void); +void func_802A1BE8(void); +void func_802A1C08(void); //0x000000A4 void bsbwhirl_drone_init(void); @@ -696,9 +692,9 @@ void bsbwhirl_drone_update(void); void bsbwhirl_drone_end(void); //0x000000A5 -void bsbwhirl_bsA5unknown_init(void); -void bsbwhirl_bsA5unknown_update(void); -void bsbwhirl_bsA5unknown_end(void); +void func_802AADBC(void); +void func_802AAE08(void); +void func_802AAE4C(void); void bsDroneGoTo_init(void); void bsDroneGoTo_update(void); @@ -716,8 +712,4 @@ void bsDroneEnter_end(void); void bsDroneVanish_init(void); void bsDroneVanish_update(void); void bsDroneVanish_end(void); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/checksums.h b/include/checksums.h deleted file mode 100644 index 403428120..000000000 --- a/include/checksums.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef BANJO_KAZOOIE_CHECKSUMS_H -#define BANJO_KAZOOIE_CHECKSUMS_H - -#include - -/* The checksums for the boot and core1 segments are stored right after the boot segment in ROM - */ - -#define CRC_BOOT_TEXT_CHECKSUM1 0 -#define CRC_BOOT_TEXT_CHECKSUM2 4 -#define CRC_CORE1_TEXT_CHECKSUM1 8 -#define CRC_CORE1_TEXT_CHECKSUM2 12 -#define CRC_CORE1_DATA_CHECKSUM1 16 -#define CRC_CORE1_DATA_CHECKSUM2 20 - -extern u8 crc_ROM_START[]; - -/* Each overlay bss section contains four checksum values, calculated from the rarezip decompressor. - * These values are written by the overlay loader. They are checked with pre-calculated values for - * different anti-tampering measurements. - * The exception is the core1 overlay, which checksums are written to a special place. - */ -struct overlay_checksums_s { - s32 text_checksum1; - s32 text_checksum2; - s32 data_checksum1; - s32 data_checksum2; -}; - -extern struct overlay_checksums_s gChecksumsCore1; -extern struct overlay_checksums_s gChecksumsCore2; -extern struct overlay_checksums_s gChecksumsCC; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsGV; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsMMM; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsTTC; -extern struct overlay_checksums_s gChecksumsMM; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsBGS; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsRBB; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsFP; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsSM; -extern struct overlay_checksums_s gChecksumsCutscenes; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsLair; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsFight; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsCCW; // (unused) no anti tampering measurements -extern struct overlay_checksums_s gChecksumsEmptyLvl; // (unused) no anti tampering measurements - -/* The pre-calculated checksums are located in random places. - * - * The calculation process should be as following (needs to be confirmed!!): - * 1. At compile time all checksum variables (listed below) are set to zero - * 2. The text checksums for all overlays (except core1) are calculated and written. - * 3. The data checksums are calculated in two passes: - * 3-1. Data checksum 1 is calculated and written for each overlay (except core1). - * 3-2. Data checksum 2 is calculated and written for each overlay (except core1). - * 4. The boot and core1 checksums are calculated and written to the CRC section. - * - * Notes: - * - Checksums 1 sums up every byte - * - Checksum 2 XORes every byte after it is shifted right by "current checksum 1 AND 0x17" - * (This means checksum 2 must be calculated together with checksum 1) - * (Step 3-1 discards checksum 2 and step 3-2 discards checksum 1) - * - Checksums without a correspondending variable are just discarded. - */ - -extern s32 D_803727F4; // core2 text checksum 2 (location: core2) -extern s32 D_80276574; // core2 data checksum 2 (location: core1) - -extern s32 D_80389BE0; // CC text checksum 1 (location: CC) -extern s32 D_80389BE4; // CC text checksum 2 (location: CC) -extern s32 D_80389BE8; // CC data checksum 1 (location: CC) -extern s32 D_80276570; // CC data checksum 2 (location: core1) - -extern s32 D_80390F30; // GV text checksum 1 (location: GV) -extern s32 D_80390F34; // GV text checksum 2 (location: GV) -extern s32 D_80390F38; // GV data checksum 1 (location: GV) -extern s32 D_80275904; // GV data checksum 2 (location: core1) - -extern s32 D_8038C300; // MMM text checksum 1 (location: MMM) -extern s32 D_8038C304; // MMM text checksum 2 (location: MMM) -extern s32 D_8038C308; // MMM data checksum 1 (location: MMM) -extern s32 D_80275854; // MMM data checksum 2 (location: core1) - -extern s32 D_8038C750; // TTC text checksum 1 (location: TTC) -extern s32 D_8038C754; // TTC text checksum 2 (location: TTC) -extern s32 D_8038C758; // TTC data checksum 1 (location: TTC) -extern s32 D_80276CB0; // TTC data checksum 2 (location: core1) - -extern s32 D_803899C0; // MM text checksum 1 (location: MM) -extern s32 D_803899C4; // MM text checksum 2 (location: MM) -extern s32 D_803899C8; // MM data checksum 1 (location: MM) -extern s32 D_80275654; // MM data checksum 2 (location: core1) - -extern s32 D_80390B20; // BGS text checksum 1 (location: BGS) -extern s32 D_80390B24; // BGS text checksum 2 (location: BGS) -extern s32 D_80390B28; // BGS data checksum 1 (location: BGS) -extern s32 D_802758F0; // BGS data checksum 2 (location: core1) - -extern s32 D_80276CB4; // RBB data checksum 2 (location: core1) - -extern s32 D_802758F4; // FP data checksum 2 (location: core1) - -extern s32 D_8038AAE0; // SM text checksum 1 (location: SM) -extern s32 D_8038AAE4; // SM text checksum 2 (location: SM) -extern s32 D_8038AAE8; // SM data checksum 1 (location: SM) -extern s32 D_80275650; // SM data checksum 2 (location: core1) - -extern s32 D_80275850; // Cutscenes data checksum 2 (location: core1) - -extern s32 D_80275900; // Lair data checksum 2 (location: core1) - -extern s32 D_80275D34; // Fight data checksum 2 (location: core1) - -extern s32 D_80275D30; // CCW data checksum 2 (location: core1) - -#endif diff --git a/include/core1/core1.h b/include/core1/core1.h index bf301700d..f63707888 100644 --- a/include/core1/core1.h +++ b/include/core1/core1.h @@ -2,7 +2,6 @@ #define BANJO_KAZOOIE_CORE1_CORE1_H #include -#include // [port] for ALSeqpConfig/ALHeap in audioManager decls (decomp gets this via SDK ultra64.h) #include "bool.h" #include "enums.h" #include "structs.h" @@ -24,10 +23,6 @@ #include "core1/viewport.h" #include "core1/vimgr.h" -#ifdef __cplusplus -extern "C" { -#endif - /* need to sort out in individual header files */ void* malloc(size_t size); @@ -43,20 +38,10 @@ void func_8025ABB8(enum comusic_e comusic_id, s32 arg1, s32 arg2, s32 arg3); int func_8025AD7C(enum comusic_e arg0); int func_8025ADBC(enum comusic_e arg0); +OSMesgQueue * audioManager_getFrameMesgQueue(void); void piMgr_read(void *vaddr, s32 devaddr, s32 size); -/* src/core1/code_1D00.c */ - -void audioManager_setupSeqp(ALSeqpConfig *config); -void audioManager_init(void); -ALHeap *audioManager_getALHeapInfo(void); -OSMesgQueue *audioManager_getDMANotifyMesgQueue(void); -OSIoMesg *audioManager_getExtraDMAMesg(void); -OSMesgQueue *audioManager_getFrameMesgQueue(void); -OSMesgQueue *audioManager_getReplyMesgQueue(void); - - /* src/core1/overlay.c */ void overlay_load( @@ -138,17 +123,17 @@ void core1_ce60_func_8024BD40(s32 arg0, s32 arg1); /* src/core1/depthbuffer.c */ -extern u8 D_8000E800[]; +extern u8 D_8000E800; -void depthbuffer_clear(Gfx **gfx); -void depthbuffer_clearRegion(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer); -bool depthbuffer_getUnk4(void); -bool depthbuffer_isDataPtrSet(void); -void depthbuffer_stub(void); -void depthbuffer_enable(bool enable); -void depthbuffer_setUnk4(bool value); -void depthbuffer_set(Gfx **gfx); -void *depthbuffer_getDataPtr(void); +void func_80253190(Gfx **gfx); +void func_80253208(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer); +int func_80253400(void); +bool depthBuffer_isPointerSet(void); +void depthBuffer_stub(void); +void func_80253428(int arg0); +void func_802534A8(int arg0); +void zBuffer_set(Gfx **gfx); +void *zBuffer_get(void); @@ -164,8 +149,8 @@ struct ucode_task_data_s { s32 unk4; // is only set for gfx tasks (0 or 0x40000000) void *data_ptr; // begin of dlist data (was u64* upstream; void* here for port-side casts) void *data_ptr_end; // end of dlist data - OSMesgQueue *audio_mesg_queue; // only relevant for audio tasks - OSMesg audio_mesg; // only relevant for audio tasks + OSMesgQueue *unk10; // only relevant for audio tasks + s32 unk14; // only relevant for audio tasks }; #define DEFAULT_FRAMEBUFFER_WIDTH 292 @@ -177,10 +162,10 @@ extern u16 gFramebuffers[2][DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIG void core1_15B30_requestLockForTaskDataID(void); void core1_15B30_requestReleaseForTaskDataID(void); -void core1_15B30_addAudioTaskData(Acmd *start, Acmd *end, OSMesgQueue *mesg_queue, OSMesg msg); -void setupFramebuffer(Gfx **gfx, void *color_buffer); -void setupFramebufferForGamemode(Gfx **gfx, s32 framebuffer_idx); -void setupScissorBoxAndFramebuffer(Gfx **gfx, void *color_buffer); +void core1_15B30_addAudioTaskData(Gfx **start, Gfx **end, void *mesg_queue, void *msg); +void func_80253640(Gfx ** gdl, void *arg1); +void scissorBox_SetForGameMode(Gfx **gdl, s32 framebuffer_idx); +void setupScissorBoxAndFramebuffer(Gfx **gfx, uintptr_t framebuffer_address); void setupDefaultScissorBoxAndFramebuffer(Gfx **gfx, s32 framebuffer_idx); void core1_15B30_finishDList_renderThread(Gfx **gfx); void core1_15B30_finishDList(Gfx **gfx); @@ -201,8 +186,8 @@ void graphicsCache_checkFrame(Gfx *gfxStart, Gfx *gfxEnd, Mtx *mtxStart, Mtx *mt void scissorBox_set(s32 left, s32 top, s32 right, s32 bottom); void scissorBox_setDefault(void); void core1_15B30_addTask7TaskData(s32 framebuffer_id); -void core1_15B30_toggleTexturePointFilter(void); -void graphicscache_swapAndGetStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx); +void toggleTextureFilterPoint(void); +void getGraphicsStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx); void dummy_func_80254464(void); /* src/core1/defragmanager.c */ @@ -215,11 +200,5 @@ void dummy_func_80254464(void); void defragManager_init(void); void defragManager_free(void); void defragManager_setPriority(OSPri pri); -void defragManager_resume(void); -void defragManager_pause(void); - -#ifdef __cplusplus -} -#endif #endif diff --git a/include/core1/main.h b/include/core1/main.h index 534adeaa0..4774cb689 100644 --- a/include/core1/main.h +++ b/include/core1/main.h @@ -3,15 +3,11 @@ #include #include "enums.h" -#ifdef __cplusplus -extern "C" { -#endif - void core1_main(s32 arg0); void func_8023DA74(void); void func_8023DA9C(s32 arg0); -s32 globalTimer_getTimeMasked(s32 mask); -s32 globalTimer_getTime(void); +u32 globalTimer_getTimeMasked(u32 mask); +//s32 globalTimer_getTime(void); void globalTimer_reset(void); enum map_e getSpecialBootMap(void); enum map_e getDefaultBootMap(void); @@ -29,8 +25,4 @@ void mainThread_create(void); OSThread *mainThread_get(void); void disableInput_set(void); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core1/ml.h b/include/core1/ml.h index 04ef38101..8968621c8 100644 --- a/include/core1/ml.h +++ b/include/core1/ml.h @@ -14,7 +14,7 @@ void ml_vec3f_cross_product(f32 dst[3], f32 vec1[3], f32 vec2[3]); void ml_vec3f_interpolate_fast(f32 dst[3], f32 start[3], f32 end[3], f32 t); f32 ml_vec3f_dot_product(f32 vec1[3], f32 vec2[3]); f32 ml_vec3f_distance(f32 vec1[3], f32 vec2[3]); -f32 ml_vec3f_distance_to_point(f32 arg0[3], f32 arg1[3], f32 arg2[3]); +f32 ml_func_802560D0(f32 arg0[3], f32 arg1[3], f32 arg2[3]); f32 ml_distanceSquared_vec3f(f32 vec1[3], f32 vec2[3]); void func_802562DC(f32 vec1[3], f32 vec2[3], f32 vec3[3]); f32 ml_vec3f_length_unused(f32 vec[3]); @@ -23,7 +23,7 @@ void ml_vec3f_normalize(f32 vec[3]); void ml_vec2f_normalize(f32 vec[2]); void ml_3f_normalize(f32 *x, f32 *y, f32 *z); void ml_vec3f_set_length_copy(f32 dst[3], f32 src[3], f32 len); -void ml_vec3f_clamp_deg360(f32 ptr[3]); +void func_80256664(f32 ptr[3]); void func_80256740(f32 vec[3]); void ml_vec3f_pitch_rotate_copy(f32 dst[3], f32 src[3], f32 pitch); void ml_vec3f_yaw_rotate_copy(f32 dst[3], f32 src[3], f32 yaw); @@ -39,7 +39,7 @@ f32 ml_acosf(f32 x); f32 func_8025715C(f32 val1, f32 val2); f32 func_80257204(f32 val1, f32 val2, f32 val3, f32 val4); f32 func_80257248(f32 vec1[3], f32 vec2[3]); -void ml_horizontal_and_vertical_angles(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2); +void func_8025727C(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2); void ml_init(void); void ml_free(void); f32 func_802575BC(f32 val); @@ -110,7 +110,7 @@ void ml_translate_y_local(f32 position[3], f32 rotation[3], f32 dy); void ml_translate_z_local(f32 dst[3], f32 src[3], f32 dz); void ml_translate_x_local(f32 dst[3], f32 src[3], f32 dx); void func_8025901C(f32 arg0, f32 arg1[3], f32 arg2[3], f32 arg3); -f32 ml_clamp_abs_f(f32 arg0, f32 arg1); +f32 func_80259198(f32 arg0, f32 arg1); f32 mlDiffDegF(f32 arg0, f32 arg1); bool ml_vec3f_point_within_horizontal_distance(f32 vec[3], f32 x, f32 z, f32 distance); bool ml_vec3f_within_horizontal_distance(f32 vec1[3], f32 vec2[3], f32 distance); @@ -118,7 +118,7 @@ bool ml_vec3w_within_horizontal_distance(s32 vec1[3], s32 vec2[3], s32 distance) bool ml_vec3f_within_distance(f32 vec1[3], f32 vec2[3], f32 distance); bool ml_stub_80259400(f32 x); void ml_sub_delta_time(f32 *x); -void ml_project_point_onto_vecf3(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); +void func_8025947C(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); f32 func_80259554(f32 dst[3], f32 vec1[3], f32 vec2[3], f32 vec3[3]); void func_802596AC(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); s32 ml_getViewportYawWithOffset(f32 x); diff --git a/include/core1/sns.h b/include/core1/sns.h index 321bb9d95..11301e48f 100644 --- a/include/core1/sns.h +++ b/include/core1/sns.h @@ -1,10 +1,6 @@ #ifndef BANJO_KAZOOIE_CORE1_SNS_H #define BANJO_KAZOOIE_CORE1_SNS_H -#ifdef __cplusplus -extern "C" { -#endif - /** * sns sets */ @@ -137,8 +133,4 @@ void sns_stub (void); void snspayload_append_key_to_outgoing_payload (struct SnsPayload *payload, s32 key); void snspayload_calc_checksum (struct SnsPayload *payload); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core1/sprite.h b/include/core1/sprite.h index 1ae8be8a6..d78f57896 100644 --- a/include/core1/sprite.h +++ b/include/core1/sprite.h @@ -1,10 +1,6 @@ #ifndef BANJO_KAZOOIE_CORE1_SPRITE_H #define BANJO_KAZOOIE_CORE1_SPRITE_H -#ifdef __cplusplus -extern "C" { -#endif - u32 sprite_getUnk8(BKSprite *self); u32 sprite_getUnkA(BKSprite *self); u32 sprite_getUnk6(BKSprite *self); @@ -12,8 +8,4 @@ u32 sprite_getUnk4(BKSprite *self); s32 sprite_getFrameCount(BKSprite *self); BKSpriteFrame *sprite_getFramePtr(BKSprite *self, u32 frame_id); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core1/viewport.h b/include/core1/viewport.h index 1a5bafaa8..64e6daf61 100644 --- a/include/core1/viewport.h +++ b/include/core1/viewport.h @@ -1,13 +1,9 @@ #ifndef BANJO_KAZOOIE_CORE1_VIEWPORT_H #define BANJO_KAZOOIE_CORE1_VIEWPORT_H -#ifdef __cplusplus -extern "C" { -#endif - void viewport_moveAlongZAxis(f32 offset); f32 viewport_getDistance(f32 arg0[3]); -void viewport_getLookVector(f32 arg0[3]); +void viewport_getLookbk_vector(f32 arg0[3]); void viewport_getPosition_vec3f(f32 arg0[3]); void viewport_getPosition_vec3w(s32 dst[3]); void viewport_getPosition_vec3s(s16 dst[3]); @@ -54,8 +50,4 @@ void viewport_backupState(void); void viewport_restoreState(void); void viewport_adjustPointDistance(f32 pos[3], f32 distance); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core2/ba/carry.h b/include/core2/ba/carry.h index af50dfa28..5c74db27c 100644 --- a/include/core2/ba/carry.h +++ b/include/core2/ba/carry.h @@ -9,7 +9,7 @@ void bacarry_end(void); void bacarry_update(void); void bacarry_reset_marker(void); -ActorMarker *bacarry_getMarker(void); +ActorMarker *bacarry_get_marker(void); void bacarry_set_marker(ActorMarker *arg0); void bacarry_set_offsets(f32 height, f32 rotation); diff --git a/include/core2/ba/model.h b/include/core2/ba/model.h index 2a22a4c20..47324d8c4 100644 --- a/include/core2/ba/model.h +++ b/include/core2/ba/model.h @@ -1,10 +1,6 @@ #ifndef _PLAYER_MODEL_H_ #define _PLAYER_MODEL_H_ -#ifdef __cplusplus -extern "C" { -#endif - typedef enum player_model_direction_e { PLAYER_MODEL_DIR_NONE = 0, PLAYER_MODEL_DIR_BANJO = 1, @@ -19,8 +15,4 @@ void baModel_setYDisplacement(f32); void baModel_8029217C(f32); void baModel_setVisible(s32 arg0); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core2/ba/physics.h b/include/core2/ba/physics.h index c29a820a9..e2d49e0c7 100644 --- a/include/core2/ba/physics.h +++ b/include/core2/ba/physics.h @@ -3,11 +3,6 @@ #include #include "libultraship/libultra/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - typedef enum ba_physics_type_e{ BA_PHYSICS_NONE, BA_PHYSICS_UNK1, @@ -55,9 +50,4 @@ void baphysics_set_gravity(f32); void baphysics_set_terminal_velocity(f32); int baphysics_is_slower_than(f32); int baphysics_goto_done(void); - -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core2/ba/timer.h b/include/core2/ba/timer.h index 95d191aca..186cf9ab0 100644 --- a/include/core2/ba/timer.h +++ b/include/core2/ba/timer.h @@ -4,7 +4,7 @@ #include void batimer_incrementBy(s32 id, f32 inc_value_sec); -bool batimer_decrement(s32 id); +int batimer_decrement(s32 id); void batimer_increment(s32 id); f32 batimer_get(s32 id); int batimer_isAt(s32 id, f32 value_sec); diff --git a/include/core2/bonetransform.h b/include/core2/bonetransform.h index 80be38b91..dfd76f140 100644 --- a/include/core2/bonetransform.h +++ b/include/core2/bonetransform.h @@ -2,10 +2,6 @@ #define _BONE_TRANSFORMATION_H_ #include -#ifdef __cplusplus -extern "C" { -#endif - typedef struct { f32 unk0[4]; f32 scale[3]; @@ -20,8 +16,4 @@ typedef struct bone_transform_list_s{ BoneTransformList *boneTransformList_new(void); BoneTransformList *boneTransformList_defrag(BoneTransformList *self); void boneTransformList_free(BoneTransformList *self); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core2/commonParticle.h b/include/core2/commonParticle.h index 2283965b3..bf6ded7a8 100644 --- a/include/core2/commonParticle.h +++ b/include/core2/commonParticle.h @@ -7,10 +7,6 @@ #include "prop.h" #include "core2/anim/sprite.h" -#ifdef __cplusplus -extern "C" { -#endif - #define PARTICLE_LIMIT 40 #ifndef FUNCUNK40_DEFINED @@ -80,8 +76,4 @@ void func_80344E3C(u8, f32[3]); void func_80344D94(u8, f32[3]); void func_80344EE4(u8, f32, f32); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core2/modelRender.h b/include/core2/modelRender.h index 2b955bd7f..2da2e1174 100644 --- a/include/core2/modelRender.h +++ b/include/core2/modelRender.h @@ -41,7 +41,7 @@ void modelRender_setEnvColor(s32 r, s32 g, s32 b, s32 a); void modelRender_setAlpha(s32 a); void modelRender_func_8033A444(AnimMtxList *arg0); void modelRender_setRefPoints(Vec3fArray *ref_points); -void modelRender_setAppendageVisibility(s32 arg0, s32 arg1); +void func_8033A45C(s32 arg0, s32 arg1); void modelRender_func_8033A470(s32 arg0, s32 arg1); void modelRender_setTextureList(BKTextureList *texture_list); void modelRender_setAnimatedTexturesCacheId(s32 arg0); diff --git a/include/core2/particle.h b/include/core2/particle.h index 28487e577..8ad811a4a 100644 --- a/include/core2/particle.h +++ b/include/core2/particle.h @@ -3,10 +3,6 @@ #include "structs.h" -#ifdef __cplusplus -extern "C" { -#endif - #define PART_EMIT_NO_OPA 0x20 #define PART_EMIT_NO_DEPTH 0x10 #define PART_EMIT_NO_LOOP 0x8 @@ -28,8 +24,4 @@ void func_802EFF9C(ParticleEmitter *self, f32); void partEmitMgr_freeEmitter(ParticleEmitter *self); -#ifdef __cplusplus -} -#endif - #endif diff --git a/src/core2/quiz/storage.h b/include/core2/quiz_storage.h similarity index 85% rename from src/core2/quiz/storage.h rename to include/core2/quiz_storage.h index 300fe5e03..039ff0c82 100644 --- a/src/core2/quiz/storage.h +++ b/include/core2/quiz_storage.h @@ -1,9 +1,5 @@ -// BanjoDecomp: core2/code_C9E70.h -#ifndef BANJO_KAZOOIE_CODE_C9E70_H -#define BANJO_KAZOOIE_CODE_C9E70_H - -#ifndef __CORE2_C9E70_H__ -#define __CORE2_C9E70_H__ +#ifndef __CORE2_QUIZ_STORAGE_H__ +#define __CORE2_QUIZ_STORAGE_H__ #include #include "structs.h" @@ -63,8 +59,8 @@ struct FF_StorageStruct { /* 08 */ s16 currentTileId; /* 0A */ u8 currFfMode; /* 0B */ u8 ffQuestionType; - /* 0C */ u8 questionTypeTableIndex; // Question Type Index - /* 0D */ u8 questionAssetIndex; // Question Asset Id + /* 0C */ u8 questionTypeTableIndex; + /* 0D */ u8 questionAssetIndex; /* 0E */ s8 unkE; /* 0F */ s8 unkF; @@ -94,5 +90,3 @@ struct FF_StorageStruct { /* 48 */ struct FF_StorageStruct_48 *unk48; }; // 0x4C #endif - -#endif // BANJO_KAZOOIE_CODE_C9E70_H diff --git a/include/core2/statetimer.h b/include/core2/statetimer.h index 3863783e8..0d15969f0 100644 --- a/include/core2/statetimer.h +++ b/include/core2/statetimer.h @@ -4,10 +4,6 @@ #include #include "structs.h" -#ifdef __cplusplus -extern "C" { -#endif - enum state_timer_e{ STATE_TIMER_0_UNKNOWN, STATE_TIMER_1_THROW = 1, @@ -28,8 +24,4 @@ void stateTimer_init(void); void stateTimer_clear(enum state_timer_e timer_id); void stateTimer_set(enum state_timer_e timer_id, f32 value); void stateTimer_update(void); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/core2/timedfunc.h b/include/core2/timedfunc.h index 1c3007b4f..2892d462e 100644 --- a/include/core2/timedfunc.h +++ b/include/core2/timedfunc.h @@ -4,9 +4,7 @@ #include "generic.h" -#ifndef __cplusplus #define reinterpret_cast(type, var) (*((type *)&var)) -#endif void timedFunc_set_0(f32 time, GenFunction_0 funcPtr); diff --git a/include/enums.h b/include/enums.h index 4e573581e..90de73ab1 100644 --- a/include/enums.h +++ b/include/enums.h @@ -449,7 +449,7 @@ enum level_flags_e LEVEL_FLAG_23_RBB_OPEN, LEVEL_FLAG_24_CCW_OPEN, - LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, + LEVEL_FLAG_25_CCW_UNKNOWN, LEVEL_FLAG_26_FP_WALRUS_JIGGY_DROPPED, LEVEL_FLAG_27_RBB_UNKNOWN, LEVEL_FLAG_28_RBB_UNKNOWN, @@ -632,7 +632,7 @@ typedef enum map_e MAP_5A_CCW_SUMMER_ZUBBA_HIVE = 0x5A, // Summer & Spring are swapped here MAP_5B_CCW_SPRING_ZUBBA_HIVE, MAP_5C_CCW_AUTUMN_ZUBBA_HIVE, - MAP_5D_UNUSED, + // Unused MAP_5E_CCW_SPRING_NABNUTS_HOUSE = 0x5E, MAP_5F_CCW_SUMMER_NABNUTS_HOUSE = 0x5F, MAP_60_CCW_AUTUMN_NABNUTS_HOUSE = 0x60, @@ -654,7 +654,7 @@ typedef enum map_e MAP_70_GL_CC_LOBBY = 0x70, MAP_71_GL_STATUE_ROOM, MAP_72_GL_BGS_LOBBY, - MAP_73_UNUSED, + // Unused MAP_74_GL_GV_PUZZLE = 0x74, MAP_75_GL_MMM_LOBBY, MAP_76_GL_640_NOTE_DOOR, @@ -1468,7 +1468,6 @@ enum sfx_e SFX_3F9_UNKNOWN, //chmole SFX_3FA_HONEYCOMB_TALKING, SFX_3FB_UNKNOWN, //conga - SFX_3FC_ZUBBA_UNK, SFX_405_UNKNOWN = 0x405, SFX_406_GOLD_BULLION_TALKING, @@ -1763,10 +1762,10 @@ enum mumbotoken_e typedef enum actor_e { - ACTOR_1_UNKNOWN = 0x1, + ACTOR_1_UNKNOWN = 0x1, ACTOR_2_UNKNOWN, - ACTOR_4_BIGBUTT = 0x4, + ACTOR_4_BIGBUTT = 0x4, ACTOR_5_TERMITE, ACTOR_6_GRUBLIN, ACTOR_7_MUMBO, @@ -1777,11 +1776,14 @@ typedef enum actor_e ACTOR_C_MUD_HUT, ACTOR_D_WOOD_DEMOLISHED, ACTOR_E_SMALL_BULL, - ACTOR_F_CHIMPY, + ACTOR_F_CHIMPY = 0xF, + + ACTOR_10E_BLUBBER_SHIP_TOP_HATCH = 0x10e, - ACTOR_11_JUJU_CTRL = 0x11, + ACTOR_11_JUJU_CTRL = 0x11, ACTOR_12_BEEHIVE, //ACTOR_13_SINKING_BOBBER + ACTOR_14_ORANGE_PROJECTILE = 0x14, ACTOR_15_UNKNOWN, @@ -1792,15 +1794,10 @@ typedef enum actor_e ACTOR_1B_FRAMERATE_20, ACTOR_1C_FRAMERATE_15, ACTOR_1D_FRAMERATE_12, - ACTOR_1E_LEAKY, - ACTOR_1F_UNUSED, // Maybe was supposed to be Termite Transformation? - ACTOR_20_TRANSFORM_PUMPKIN, - ACTOR_21_TRANSFORM_CROC, - ACTOR_22_TRANSFORM_WALRUS, - ACTOR_23_TRANSFORM_BEE, + + ACTOR_1E_LEAKY = 0x1E, ACTOR_25_CEMETARY_POT = 0x25, - ACTOR_26_CLIMB_BASE, ACTOR_29_ORANGE_COLLECTIBLE = 0x29, ACTOR_2A_GOLD_BULLION, @@ -1816,7 +1813,6 @@ typedef enum actor_e ACTOR_39_NAPPER = 0x39, ACTOR_3A_MOTZHAND, - ACTOR_3B_CLANKER_DIALOG_TRIGGER, ACTOR_3C_CC_KEY = 0x3C, ACTOR_3D_CLANKER_SAWBLADE_PROPELLOR_1, @@ -1905,31 +1901,31 @@ typedef enum actor_e ACTOR_BC_BANJOS_CURTAINS = 0xBC, ACTOR_BD_BANJOS_HOUSE_DOOR, - ACTOR_C5_CHIMPY_STUMP = 0xC5, + ACTOR_C5_CHIMPY_STUMP = 0xC5, ACTOR_C7_GRAVESTONE = 0xC7, - ACTOR_C8_BOGGY_2, + ACTOR_C8_BOGGY_2 = 0xC8, ACTOR_CA_TEEHEE = 0xCA, ACTOR_CB_1881_BARREL_TOP, - ACTOR_E4_FLIGHT_PAD = 0xE4, + ACTOR_E4_FLIGHT_PAD = 0xE4, - ACTOR_E6_GLOOP = 0xE6, + ACTOR_E6_GLOOP = 0xE6, ACTOR_E7_GLOOP_BUBBLE, ACTOR_E8_TANKTUP, ACTOR_E9_TANKTUP_LEG_FL, ACTOR_EA_TANKTUP_LEG_BL, ACTOR_EB_TANKTUP_LEG_FR, ACTOR_EC_TANKTUP_LEG_BR, - ACTOR_ED_PINK_EGG_LARGE, + ACTOR_ED_PINK_EGG_LARGE = 0xED, ACTOR_EE_PINK_EGG_MEDIUM, ACTOR_EF_PINK_EGG_SMALL, ACTOR_F0_PINK_EGG_SMALLEST, ACTOR_F1_LEAF_BOAT, ACTOR_F2_BLACK_SNIPPET, ACTOR_F3_EXPLOSION_RIPPLE, - ACTOR_F4_BURIED_TREASURE, + ACTOR_F4_BURIED_TREASURE = 0xF4, ACTOR_F5_MUTIE_SNIPPET, ACTOR_F6_BIG_ALLIGATOR, @@ -1940,13 +1936,12 @@ typedef enum actor_e ACTOR_105_UNKNOWN, ACTOR_106_UNKNOWN, ACTOR_107_UNKNOWN, - ACTOR_108_MODEL_PLAYER_SHADOW, - ACTOR_109_SHACK_DOOR, + + ACTOR_109_SHACK_DOOR = 0x109, ACTOR_10A_MANSION_DOOR, ACTOR_10B_CELLAR_HATCH, ACTOR_10C_CHURCH_GATE_LEFT_LOCK, ACTOR_10D_HEDGE_GATE_RIGHT_LOCK_1, - ACTOR_10E_BLUBBER_SHIP_TOP_HATCH, ACTOR_114_CHURCH_DOOR = 0x114, ACTOR_115_BLUBBER, @@ -1967,13 +1962,12 @@ typedef enum actor_e ACTOR_124_SIR_SLUSH, ACTOR_125_SNOWBALL, ACTOR_126_SIR_SLUSH_HAT, - ACTOR_129_RED_FEATHER = 0x129, ACTOR_12B_TUTORIAL_BOTTLES = 0x12B, ACTOR_12C_MOLEHILL, - ACTOR_12E_GOBI_1 = 0x12E, + ACTOR_12E_GOBI_1 = 0x12E, ACTOR_12F_GOBI_ROPE, ACTOR_130_GOBI_ROCK, ACTOR_131_GOBI_2, @@ -2000,8 +1994,8 @@ typedef enum actor_e ACTOR_147_ANCIENT_ONE, ACTOR_149_TTC_BLUBBER_UNKNOWN = 0x149, - ACTOR_14A_TTC_BLUBBER_UNKNOWN, - ACTOR_14B_TTC_BLUBBER_UNKNOWN, + ACTOR_14A_TTC_BLUBBER_UNKNOWN = 0x14a, + ACTOR_14B_TTC_BLUBBER_UNKNOWN = 0x14b, ACTOR_14E_BGS_ELEVATED_WALKWAY_SWITCH = 0x14E, ACTOR_14F_DESTROYED_JIGGY, @@ -2034,15 +2028,14 @@ typedef enum actor_e ACTOR_16B_CCW_AUTUMN_SEASON_DOOR, ACTOR_16C_CCW_SUMMER_SWITCH, ACTOR_16D_CCW_SUMMER_SEASON_DOOR, - ACTOR_16E_UNKNOWN, + ACTOR_16E_UNKNOWN = 0x16E, ACTOR_16F_QUARRIE, ACTOR_172_RBB_EGG_TOLL = 0x172, - ACTOR_173_RBB_CAGE_UP_SWITCH, - ACTOR_174_RBB_TNT_DOWN_SWITCH, - ACTOR_175_RUSTY_BUCKET_REAR_PROPELLER, - ACTOR_176_RBB_GREEN_PROPELLOR_SWITCH, - ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1, + + ACTOR_175_MODEL_RUSTY_BUCKET_REAR_PROPELLER = 0x175, + + ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1 = 0x177, ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, @@ -2054,7 +2047,7 @@ typedef enum actor_e ACTOR_180_RBB_SPINNING_DOUBLE_PIPE_2, ACTOR_181_SCARF_SLED = 0x181, - ACTOR_182_RACE_SLED, + ACTOR_182_RACE_SLED = 0x182, ACTOR_188_PIRANHA_WATER_PARTICLES = 0x188, @@ -2065,25 +2058,22 @@ typedef enum actor_e ACTOR_198_BANJOS_BED = 0x198, ACTOR_199_BANJOS_CHAIR, ACTOR_19A_BANJOS_STOVE, - ACTOR_19B_MUMBOS_HAND_WITH_PICTURE, + ACTOR_19C_MODEL_THE_END_SIGN = 0x19C, ACTOR_1BB_ENGINE_ROOM_PROPELLOR_1 = 0x1BB, ACTOR_1BC_ENGINE_ROOM_PROPELLOR_2, ACTOR_1BD_ENGINE_ROOM_PROPELLOR_3, - ACTOR_1BE_RBB_GREY_PROPELLOR_SWITCH, - ACTOR_1BF_WHISTLE_SWITCH_1, - ACTOR_1C0_WHISTLE_SWITCH_2, - ACTOR_1C1_WHISTLE_SWITCH_3, - ACTOR_1C2_WHISTLE_1, + + ACTOR_1C2_WHISTLE_1 = 0x1C2, ACTOR_1C3_WHISTLE_2, ACTOR_1C4_WHISTLE_3, - ACTOR_1C5_WHISTLE_CTRL, + + ACTOR_1C5_WHISTLE_CTRL = 0x1C5, ACTOR_1C6_GRIMLET, ACTOR_1C7_ANCHOR_SWITCH, ACTOR_1C8_SNORKEL, ACTOR_1C9_ANCHOR, - ACTOR_1CA_RAREWARE_FLAG, ACTOR_1CC_GRILLE_CHOMPA = 0x1CC, ACTOR_1CD_UNKNOWN, @@ -2105,7 +2095,6 @@ typedef enum actor_e ACTOR_1E2_CCW_SPRING_SWITCH, ACTOR_1E3_CCW_SPRING_SEASON_DOOR, ACTOR_1E4_TOOTS, - ACTOR_1E5_UNKNOWN, ACTOR_1E9_SNARE_BEAR = 0x1E9, ACTOR_1EA_POLAR_BEAR_CUB_BLUE, @@ -2174,11 +2163,11 @@ typedef enum actor_e ACTOR_230_BREAKABLE_FLOOR_COBWEB = 0x230, ACTOR_231_BREAKABLE_WALL_COBWEB, - ACTOR_233_CCW_MUMBOS_HUT = 0x233, ACTOR_234_CCW_ENTRANCE_DOOR = 0x234, ACTOR_235_FP_ENTRANCE_DOOR_LEFT, ACTOR_236_FP_ENTRANCE_DOOR_RIGHT, - ACTOR_237_CCW_WITCH_SWITCH, + + ACTOR_237_CCW_WITCH_SWITCH = 0x237, ACTOR_239_FP_WITCH_SWITCH = 0x239, ACTOR_23A_GL_ADVENT_CALENDAR_HATCH_DOOR, @@ -2191,7 +2180,8 @@ typedef enum actor_e ACTOR_242_FF_TELEPORT_PAD = 0x242, ACTOR_243_GV_SNS_CHAMBER_DOOR, ACTOR_244_GV_SNS_SARCOPHAGUS, - ACTOR_245_GV_SNS_SWITCH, + + ACTOR_245_GV_SNS_SWITCH = 0x245, ACTOR_246_FLIGHT_PAD_SWITCH, ACTOR_247_LAIR_SWITCH_FLIGHT_PAD, ACTOR_248_SHOCK_JUMP_PAD_SWITCH, @@ -2207,10 +2197,7 @@ typedef enum actor_e ACTOR_25C_SHARKFOOD_ISLAND, ACTOR_25D_ICE_KEY, ACTOR_25E_SNS_EGG, - ACTOR_25F_CCW_UNKNOWN_NABNUT_WINDOW, - ACTOR_260_CCW_UNKNOWN_NABNUT_WINDOW, - ACTOR_261_CCW_AUTUMN_NABNUT_WINDOW, - ACTOR_262_CCW_WINTER_NABNUT_WINDOW, + ACTOR_263_SUNNY_LIFEBOAT = 0x263, ACTOR_264_SHADOW_LIFEBOAT, ACTOR_265_DINING_DOOR, @@ -2228,9 +2215,6 @@ typedef enum actor_e ACTOR_282_BOSS_BOOM_BOX_LARGE, ACTOR_283_BOSS_BOOM_BOX_MEDIUM, ACTOR_284_BOSS_BOOM_BOX_SMALL, - ACTOR_285_JINXY_HEAD_SANDYBUTT_1, - ACTOR_286_JINXY_HEAD_SANDYBUTT_2, - ACTOR_287_JINXY_HEAD_SANDYBUTT_3, ACTOR_289_BETA_VENT = 0x289, ACTOR_28A_CLANKER_WHIPCRACK, @@ -2243,46 +2227,32 @@ typedef enum actor_e ACTOR_293_CLANKER_SAWBLADE_PROPELLOR_10, ACTOR_294_CLANKER_SAWBLADE_PROPELLOR_11, ACTOR_295_CLANKER_SAWBLADE_PROPELLOR_12, - ACTOR_296_BELL_BUOY, - ACTOR_297_ROWBOAT, - ACTOR_298_ZUBBA_DOOR_SUMMER, - ACTOR_299_ZUBBA_HONEY_LUMP, - ACTOR_29A_ZUBBA_DOOR_AUTUMN = 0x29A, + + ACTOR_298_ZUBBA_DOOR = 0x298, + + ACTOR_29A_ZUBBA_DOOR = 0x29A, ACTOR_29B_ZUBBA, - ACTOR_29C_ZUBBA_DOCILE, + ACTOR_29D_CCW_BEANSTALK = 0x29D, ACTOR_29E_CCW_GOBI, ACTOR_29F_CLUCKER, ACTOR_2A0_EAGLE_EGG, ACTOR_2A1_EEYRIE_BABY, ACTOR_2A2_CATERPILLAR, - ACTOR_2A3_EEYRIE_ADULT, + ACTOR_2A4_BOOM_BOX_SLOW = 0x2A4, - ACTOR_2A5_BOOM_BOX_MINIGAME_CTRL = 0x2A5, - ACTOR_2A6_NABNUT_SPRING = 0x2A6, - ACTOR_2A7_NABNUT_FULL_BELLY, + ACTOR_2A8_NABNUT = 0x2A8, ACTOR_2A9_ACORN, - ACTOR_2AA_GNAWTY_SWIMMING, - ACTOR_2AB_GNAWTY_SUMMER, - ACTOR_2AC_GNAWTY_BOULDER, - ACTOR_2AD_BOSS_BOOMBOX_CTRL, - ACTOR_2AE_LEAF_EMITTER_CCW_AUTUMN, - ACTOR_2AF_LEAF_EMITTER_CCW_HUB, - ACTOR_2B0_RAIN_EMITTER_CCW_SPRING, - ACTOR_2B1_RAIN_EMITTER_CCW_HUB, - ACTOR_2B2_SNOW_EMITTER_CCW_WINTER, - ACTOR_2B3_SNOW_EMITTER_CCW_HUB, - ACTOR_2B4_BOTTLES_BONUS_BANJO_HAND, - ACTOR_2B5_UNKNOWN, + + ACTOR_2AC_GNAWTY_BOULDER = 0x2AC, + + ACTOR_2B4_BOTTLES_BONUS_BANJO_HAND = 0x2B4, ACTOR_2D8_TWO_ICE_POLES_NEAR_CHEATO_3 = 0x2D8, - ACTOR_2D9_UNKNOWN, - ACTOR_2DA_UNKNOWN, - ACTOR_2DB_DINGPOT, - ACTOR_2DC_GNAWTYS_SHELVES, - ACTOR_2DD_GNAWTYS_BED, - ACTOR_2DE_GNAWTYS_DEN, + + ACTOR_2DB_DINGPOT = 0x2DB, + ACTOR_2DF_LIGHTHOUSE_B = 0x2DF, ACTOR_2E0_TTC_STAIRS_1, ACTOR_2E1_TTC_STAIRS_2, @@ -2290,11 +2260,12 @@ typedef enum actor_e ACTOR_2E3_LEVEL_ENTRY_SIGNS, ACTOR_2E4_WORLD_EXIT_PAD, ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE, - ACTOR_2E6_NABNUT_DOOR, - ACTOR_2E7_WHIPCRACK_ROOM_DOOR, + ACTOR_2E8_WINDOW = 0x2E8, ACTOR_2E9_WIDE_WINDOW, ACTOR_2EA_TALL_WINDOW, + + ACTOR_2E5_DOOR_OF_GRUNTY = 0x2e5, ACTOR_2F4_FISHBOWL = 0x2F4, ACTOR_2F5_CUCKOO_CLOCK, @@ -2302,25 +2273,17 @@ typedef enum actor_e ACTOR_2FF_GREEN_FOG_OUTSIDE_TOWER = 0x2FF, ACTOR_300_BIKINI_GIRL, - ACTOR_30B_DEAD_BEANSTALK = 0x30B, - ACTOR_30C_SNORE_Z, ACTOR_30D_BOOM_BOX_FAST = 0x30D, - ACTOR_30E_CUTSCENE_ADULT_EYRIE, + ACTOR_30F_WHIPCRACK = 0x30f, ACTOR_310_NABNUT_HOUSE_PILE_OF_ACORNS, - ACTOR_311_PINK_SQUIRREL, - ACTOR_312_NABNUT_BEDSHEETS, + ACTOR_313_NABNUT_BED = 0x313, ACTOR_314_NABNUT_IN_AUTUMN_HOUSE, - ACTOR_315_NABNUT_EATING_ACORNS, - ACTOR_316_UNKNOWN, - ACTOR_317_UNKNOWN, - ACTOR_318_CCW_UNKNOWN = 0x318, + ACTOR_319_GV_MAZE_CTRL = 0x319, - ACTOR_31A_INDOORS_GNAWTY, - ACTOR_31B_SPINNING_SINGLE_PIPE_SFX_CTRL, - ACTOR_31C_DOUBLE_SINGLE_PIPE_SFX_CTRL, - ACTOR_31D_SANDYBUTT_PYRAMID, + + ACTOR_31D_SANDYBUTT_PYRAMID = 0x31D, ACTOR_31E_PALM_TREE, ACTOR_32B_UNKNOWN = 0x32B, //something with Tanktup @@ -2346,12 +2309,12 @@ typedef enum actor_e ACTOR_348_BRENTILDA = 0x348, ACTOR_349_UNKNOWN, - ACTOR_34D_BEE_SWARM = 0x34D, + ACTOR_34D_BEE_SWARM = 0x34D, ACTOR_34E_LIMBO, ACTOR_34F_MUMMUM, ACTOR_350_SEAMAN_GRUBLIN, - ACTOR_351_UNKNOWN, - ACTOR_352_UNKNOWN, + + ACTOR_352_UNKNOWN = 0x352, ACTOR_353_XMAS_TREE_EGG_TOLL, ACTOR_354_DRIPS, @@ -2361,22 +2324,22 @@ typedef enum actor_e ACTOR_36A_15_MUMBO_TOKEN_SIGN, ACTOR_36B_10_MUMBO_TOKEN_SIGN, ACTOR_36C_25_MUMBO_TOKEN_SIGN, - ACTOR_36D_COLLYWOBBLE_B, - ACTOR_36E_BAWL_THE_ONION_B, - ACTOR_36F_TOPPER_THE_CARROT_B, - ACTOR_370_GOLD_FEATHER, - ACTOR_374_VACATION_TEXT_TRIGGER = 0x374, + ACTOR_COLLYWOBBLE_B = 0x36D, + ACTOR_BAWL_THE_ONION_B = 0x36E, + ACTOR_TOPPER_THE_CARROT_B = 0x36F, + ACTOR_370_GOLD_FEATHER = 0x370, + + ACTOR_374_VACATION_TEXT_TRIGGER = 0x374, ACTOR_375_GRUBLIN_HOOD, ACTOR_376_FF_MINIGAME, ACTOR_379_UNKNOWN = 0x379, ACTOR_37A_BOTTLES, - ACTOR_37D_ICECUBE_A = 0x37D, - ACTOR_37E_DEAD_SNAREBEAR, + ACTOR_37D_ICECUBE_A = 0x37d, - ACTOR_37F_LOGGO = 0x37F, + ACTOR_37F_LOGGO = 0x37F, ACTOR_380_SCARAB_BEETLE, ACTOR_381_PORTRAIT_CHOMPA, ACTOR_382_PORTRAIT_OF_GRUNTY, @@ -2400,7 +2363,7 @@ typedef enum actor_e ACTOR_3A6_BOSS_JINJO_GREEN, ACTOR_3A7_BOSS_JINJO_PINK, ACTOR_3A8_BOSS_JINJO_YELLOW, - ACTOR_3A9_JINJONATOR_STATUE_BASE, + ACTOR_3A9_JINJONATOR_STATUE_BASE = 0x3A9, ACTOR_3AA_GRUNTY_SPELL_GREEN_ATTACK = 0x3AA, ACTOR_3AB_GRUNTY_SPELL_BARRIER, @@ -2414,7 +2377,8 @@ typedef enum actor_e ACTOR_3BD_SM_BRIDGE_CHECKSUM_TRIGGER = 0x3BD, ACTOR_3BE_LAIR_UNKNOWN, - ACTOR_3BF_GRUNTLING_BLUE, + + ACTOR_3BF_GRUNTLING_BLUE = 0x3BF, ACTOR_3C0_GRUNTLING_BLACK, ACTOR_3C1_PURPLE_TEEHEE, ACTOR_3C2_GIANT_GRAVESTONE, @@ -2424,11 +2388,10 @@ typedef enum actor_e ACTOR_3C7_FF_PRIZE_GRUNTY_DOLL = 0x3C7, ACTOR_3C8_FF_PRIZE_TOOTY, ACTOR_3C9_FURNACE_FUN_PICK_PRICE, - ACTOR_3CA_ROCK_TRAPPING_GRUNTY, + ACTOR_3CA_ROCK_TRAPPING_GRUNTY = 0x3CA, ACTOR_3CB_UNKNOWN, - ACTOR_3CC_DUMMY_PLAYER_ANCHOR = 0x3CC, // Lighthouse [port] network anchor dummy player - ACTOR_3CD_CUSTOM_COLLECTIBLE = 0x3CD, // Lighthouse [port] rando custom collectible + ACTOR_3CC_DUMMY_PLAYER_ANCHOR = 0x3CC, } ActorID; enum bundle_e { @@ -2477,23 +2440,23 @@ enum bs_e { BS_0_NONE = 0x0, BS_1_IDLE = 0x1, BS_2_WALK_SLOW = 0x2, - BS_3_WALK = 0x3, + BS_WALK = 0x3, BS_4_WALK_FAST = 0x4, BS_5_JUMP = 0x5, - BS_6_CLAW = 0x6, - BS_7_CROUCH = 0x7, + BS_CLAW = 0x6, + BS_CROUCH = 0x7, BS_8_BTROT_JUMP = 0x8, BS_9_EGG_HEAD = 0x9, BS_A_EGG_ASS = 0xA, BS_B_UNKOWN = 0xB, - BS_C_SKID = 0xC, - BS_D_TIMEOUT_TRANSFORMATION = 0xD, + BS_SKID = 0xC, + BS_D_TIMEOUT = 0xD, BS_E_OW = 0xE, BS_F_BBUSTER = 0xF, - BS_10_BFLAP = 0x10, + BS_BFLAP = 0x10, BS_11_BPECK = 0x11, BS_12_BFLIP = 0x12, - BS_13_BBARGE = 0x13, + BS_BBARGE = 0x13, BS_14_BTROT_ENTER = 0x14, BS_15_BTROT_IDLE = 0x15, BS_16_BTROT_WALK = 0x16, @@ -2505,31 +2468,31 @@ enum bs_e { BS_1C_WONDERWING_WALK = 0x1C, BS_1D_WONDERWING_JUMP = 0x1D, BS_1E_WONDERWING_EXIT = 0x1E, - BS_1F_WALK_CREEP = 0x1F, + BS_WALK_CREEP = 0x1F, BS_20_LANDING = 0x20, - BS_21_BSHOCK_CHARGE = 0x21, - BS_22_BSHOCK_JUMP = 0x22, + BS_BSHOCK_CHARGE = 0x21, + BS_BSHOCK_JUMP = 0x22, BS_23_FLY_ENTER = 0x23, BS_24_FLY = 0x24, BS_25_LONGLEG_ENTER = 0x25, BS_26_LONGLEG_IDLE = 0x26, - BS_27_LONGLEG_WALK = 0x27, - BS_28_LONGLEG_JUMP = 0x28, - BS_29_LONGLEG_EXIT = 0x29, - BS_2A_BOMB = 0x2A, + BS_LONGLEG_WALK = 0x27, + BS_LONGLEG_JUMP = 0x28, + BS_LONGLEG_EXIT = 0x29, + BS_BOMB = 0x2A, BS_2B_DIVE_IDLE = 0x2B, BS_2C_DIVE_B = 0x2C, BS_2D_SWIM_IDLE = 0x2D, BS_2E_SWIM = 0x2E, BS_2F_FALL = 0x2F, BS_30_DIVE_ENTER = 0x30, - BS_31_ROLL = 0x31, - BS_32_SLIDE = 0x32, - BS_33_WASHY_UNKNOWN = 0x33, + BS_ROLL = 0x31, + BS_SLIDE = 0x32, + BS_34_JIG_NOTEDOOR = 0x34, BS_35_ANT_IDLE = 0x35, - BS_36_ANT_WALK = 0x36, - BS_37_ANT_WALK = 0x37, + BS_ANT_WALK = 0x36, + BS_ANT_JUMP = 0x37, BS_38_ANT_FALL = 0x38, BS_39_DIVE_A = 0x39, BS_3A_CARRY_IDLE = 0x3A, @@ -2537,14 +2500,14 @@ enum bs_e { BS_3C_TALK = 0x3C, BS_3D_FALL_TUMBLING = 0x3D, BS_3E_ANT_OW = 0x3E, - BS_3F_UNKNOWN = 0x3F, + BS_3F = 0x3F, BS_40_PUMPKIN_FLUSH = 0x40, BS_41_DIE = 0x41, BS_42_DINGPOT = 0x42, BS_43_ANT_DIE = 0x43, BS_44_JIG_JIGGY = 0x44, BS_45_BTROT_SLIDE = 0x45, - BS_46_UNKNOWN = 0x46, + BS_48_PUMPKIN_IDLE = 0x48, BS_49_PUMPKIN_WALK = 0x49, @@ -2556,39 +2519,39 @@ enum bs_e { BS_4F_CLIMB_IDLE = 0x4F, BS_50_CLIMB_MOVE = 0x50, BS_51_CLIMB_EXIT = 0x51, - BS_52_SURF = 0x52, //tumblar??? a.k.a bssurf - BS_53_TIMEOUT_BANJO = 0x53, + BS_52_UNKNOWN = 0x52, //tumblar??? a.k.a bssurf + BS_53_TIMEOUT = 0x53, BS_54_SWIM_DIE = 0x54, - BS_55_LONGLEG_SLIDE = 0x55, + BS_LONGLEG_SLIDE = 0x55, BS_56_RECOIL = 0x56, BS_57_BOMB_END = 0x57, BS_58_BEAKBOMB_CRASH = 0x58, BS_59_BFLY_UNK59 = 0x59, BS_5A_LOADZONE = 0x5A, - BS_5B_CARRY_THROW = 0x5B, + BS_CARRY_THROW = 0x5B, BS_5E_CROC_IDLE = 0x5E, - BS_5F_CROC_WALK = 0x5F, - BS_60_CROC_JUMP = 0x60, + BS_CROC_WALK = 0x5F, + BS_CROC_JUMP = 0x60, BS_61_CROC_FALL = 0x61, BS_62_LONGLEG_LOCKED = 0x62, - BS_63_CROC_OW = 0x63, - BS_64_CROC_DIE = 0x64, + BS_CROC_OW = 0x63, + BS_CROC_DIE = 0x64, BS_67_WALRUS_IDLE = 0x67, - BS_68_WALRUS_WALK = 0x68, - BS_69_WALRUS_JUMP = 0x69, + BS_WALRUS_WALK = 0x68, + BS_WALRUS_JUMP = 0x69, BS_6A_WALRUS_FALL = 0x6A, BS_6B_BEE_LOCKED = 0x6B, //[107] = "Locked", -- Bee, Mumbo Transform Cutscene - BS_6C_WALRUS_OW = 0x6C, - BS_6D_WALRUS_DIE = 0x6D, + BS_WALRUS_OW = 0x6C, + BS_WALRUS_DIE = 0x6D, BS_6E_CROC_BITE = 0x6E, - BS_6F_CROC_EAT_BAD = 0x6F, + BS_CROC_EAT_BAD = 0x6F, BS_70_CROC_EAT_GOOD = 0x70, BS_71_BTROT_FALL = 0x71, - BS_72_SPLAT = 0x72, // Getting up after fall damage + BS_SPLAT = 0x72, // Getting up after fall damage BS_73_UNKNOWN = 0x73, // locked_cutscene BS_74_UNKNOWN = 0x74, // locked jiggypad, xform, bottles BS_75_UNKNOWN = 0x75, // locked bottles @@ -2596,8 +2559,8 @@ enum bs_e { BS_77_SWIM_LOOKAT_DRONE = 0x77, BS_78_DIVE_LOOKAT_DRONE = 0x78, BS_79_BTROT_LOCKED = 0x79, - BS_7A_WALK_MUD = 0x7A, - BS_7B_BTROT_OW = 0x7B, + BS_WALK_MUD = 0x7A, + BS_BTROT_OW = 0x7B, BS_7C_SLED = 0x7C, BS_7D_WALRUS_SLED = 0x7D, BS_7E_WALRUS_SLED = 0x7E, @@ -2608,18 +2571,18 @@ enum bs_e { BS_85_BEE_IDLE = 0x85, - BS_86_BEE_WALK = 0x86, - BS_87_BEE_JUMP = 0x87, + BS_BEE_WALK = 0x86, + BS_BEE_JUMP = 0x87, BS_88_BEE_FALL = 0x88, - BS_89_BEE_OW = 0x89, - BS_8A_BEE_DIE = 0x8A, - BS_8B_UNKNOWN = 0x8B, - BS_8C_BEE_FLY = 0x8C, + BS_BEE_OW = 0x89, + BS_BEE_DIE = 0x8A, + + BS_BEE_FLY = 0x8C, BS_8D_CROC_LOCKED = 0x8D, BS_8E_ANT_LOCKED = 0x8E, // "Locked", -- Jiggy podium, Bottles' text outside Mumbo's BS_8F_PUMPKIN_LOCKED = 0x8F, - BS_91_FLY_OW = 0x91, + BS_FLY_OW = 0x91, BS_92_ANT_DRONE = 0x92, BS_93_PUMPKIN_DRONE = 0x93, BS_94_CROC_DRONE = 0x94, @@ -2633,11 +2596,11 @@ enum bs_e { BS_9C_WALRUS_SLED_DRONE = 0x9C, BS_9D_BEE_DRONE = 0x9D, BS_9E_CLIMB_LOCKED = 0x9E, - BS_9F_ANT_BOUNCE = 0x9F, - BS_A0_ANT_BOUNCE = 0xA0, - BS_A1_CROC_BOUNCE = 0xA1, - BS_A2_WALRUS_BOUNCE = 0xA2, - BS_A3_BEE_BOUNCE = 0xA3, + BS_ANT_BOUNCE = 0x9F, + BS_PUMPKIN_BOUNCE = 0xA0, + BS_CROC_BOUNCE = 0xA1, + BS_WALRUS_BOUNCE = 0xA2, + BS_BEE_BOUNCE = 0xA3, BS_A4_WONDERWING_DRONE = 0xA4, BS_A5_WONDERWING_UNKA5 = 0xA5 }; @@ -2687,24 +2650,18 @@ enum ttc_specific_flags { }; enum bgs_specific_flags { - BGS_SPECIFIC_FLAG_1 = 1, // WALKWAY_JIGGY - BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET, - BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING, - BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY, - BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED, - BGS_SPECIFIC_FLAG_6_MR_VILE, - BGS_SPECIFIC_FLAG_7, // WALKWAY_JIGGY - BGS_SPECIFIC_FLAG_8, // WALKWAY_JIGGY - BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED, - BGS_SPECIFIC_FLAG_A, // MAZE_JIGGY - BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET, - BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING, - BGS_SPECIFIC_FLAG_D_MAZE_JIGGY, - BGS_SPECIFIC_FLAG_E_UNUSED, - BGS_SPECIFIC_FLAG_F_UNUSED, - BGS_SPECIFIC_FLAG_10_FROG_MINIGAME_FIRST_MET, - BGS_SPECIFIC_FLAG_11_UNUSED, - BGS_SPECIFIC_FLAG_12_FROG_MINIGAME_BATTLE_ACTIVE + BGS_SPECIFIC_FLAG_1 = 1, + BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_RESET = 2, + BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_TIMER_RUNNING = 3, + BGS_SPECIFIC_FLAG_WALKWAY_JIGGY = 4, + BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_SWITCH_PRESSED = 5, + BGS_SPECIFIC_FLAG_7 = 7, + BGS_SPECIFIC_FLAG_8 = 8, + BGS_SPECIFIC_FLAG_MAZE_JIGGY_SWITCH_PRESSED = 9, + BGS_SPECIFIC_FLAG_A = 0xA, + BGS_SPECIFIC_FLAG_MAZE_JIGGY_RESET = 0xB, + BGS_SPECIFIC_FLAG_MAZE_JIGGY_TIMER_RUNNING = 0xC, + BGS_SPECIFIC_FLAG_MAZE_JIGGY = 0xD }; enum fp_specific_flags { @@ -2737,38 +2694,6 @@ enum mmm_specific_flags { MMM_SPECIFIC_FLAG_7_UNKNOWN }; -enum rbb_main_specific_flags { - RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER, - RBB_MAIN_SPECIFIC_FLAG_1_WHISTLE_SWITCH_1, - RBB_MAIN_SPECIFIC_FLAG_2_WHISTLE_SWITCH_2, - RBB_MAIN_SPECIFIC_FLAG_3_WHISTLE_SWITCH_3, - RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING, - - RBB_MAIN_SPECIFIC_FLAG_8_UNK = 8 -}; - -enum rbb_boat_room_specific_flags { - RBB_BOAT_ROOM_SPECIFIC_FLAG_0_HONEYCOMB_SPAWNED -}; - -enum ccw_season_e -{ - CCW_SEASON_0_SPRING, - CCW_SEASON_1_SUMMER, - CCW_SEASON_2_AUTUMN, - CCW_SEASON_3_WINTER -}; - -enum ccw_zubba_specific_flags { - CCW_ZUBBA_SPECIFIC_FLAG_7_SPRING_DIALOG = 0x7, - CCW_ZUBBA_SPECIFIC_FLAG_8_AUTUMN_DIALOG -}; - -enum ccw_winter_specific_flags { - CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT = 0x5, - CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT -}; - enum lair_specific_flags { LAIR_SPECIFIC_FLAG_7_UKNOWN = 0x7, LAIR_SPECIFIC_FLAG_9_UKNOWN = 0x9 @@ -3117,19 +3042,17 @@ typedef enum asset_e ASSET_132_ANIM_FLOTSAM_MOVE = 0x132, ASSET_133_ANIM_NIPPER_DIE = 0x133, - ASSET_137_ANIM_GRIMLET_ATTACK = 0x137, - ASSET_138_ANIM_ZOOMBOX, - ASSET_139_ANIM_BOTTLES_EXIT, - ASSET_13A_ANIM_BOTTLES_ENTER, - ASSET_13B_ANIM_BOTTLES_IDLE, - ASSET_13C_ANIM_MOLEHILL_UNKNOWN, - ASSET_13D_ANIM_MOLEHILL_UNKNOWN, - ASSET_13E_ANIM_SNORKEL_SWIM, - ASSET_13F_ANIM_SNORKEL_STUCK, - ASSET_140_ANIM_RAREWARE_FLAG, - ASSET_141_ANIM_ANCHOR_LOWERED, - ASSET_142_ANIM_ANCHOR_RISING, - ASSET_143_ANIM_SNOWMAN_BUTTON, + ASSET_138_ANIM_ZOOMBOX = 0x138, + ASSET_139_ANIM_BOTTLES_EXIT = 0x139, + ASSET_13A_ANIM_BOTTLES_ENTER = 0x13A, + ASSET_13B_ANIM_BOTTLES_IDLE = 0x13B, + + ASSET_13E_ANIM_SNORKEL_SWIM = 0x13E, + ASSET_13F_ANIM_SNORKEL_STUCK = 0x13F, + + ASSET_141_ANIM_ANCHOR_LOWERED = 0x141, + ASSET_142_ANIM_ANCHOR_RISING = 0x142, + ASSET_143_ANIM_SNOWMAN_BUTTON = 0x143, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR = 0x146, ASSET_147_ANIM_BOOMBOX_MOVE = 0x147, @@ -3156,18 +3079,12 @@ typedef enum asset_e ASSET_166_ANIM_BURIED_TREASURE_BOUNCE = 0x166, ASSET_167_ANIM_BSREST_MOVE = 0x167, - ASSET_16A_ANIM_BELL_BUOY = 0x16A, - ASSET_16B_ANIM_SNAREBEAR_ATTACK = 0x16B, - ASSET_16C_ANIM_SNAREBEAR_IDLE = 0x16C, - ASSET_16E_ANIM_MUMBO_RECLINE = 0x16E, ASSET_16F_ANIM_ZUBBA_FLY_MOVE = 0x16F, ASSET_170_ANIM_ZUBBA_FLY_IDLE = 0x170, ASSET_171_ANIM_ZUBBA_DIE = 0x171, ASSET_172_ANIM_ZUBBA_LAND = 0x172, - ASSET_173_ANIM_BEANSTALK_UNK = 0x173, - ASSET_174_ANIM_BEANSTALK_UNK = 0x174, - ASSET_175_ANIM_BEANSTALK_UNK = 0x175, + ASSET_176_ANIM_GOBI_YAWN = 0x176, ASSET_177_ANIM_GOBI_SLEEP = 0x177, @@ -3176,9 +3093,7 @@ typedef enum asset_e ASSET_17E_ANIM_POLAR_BEAR_CUB_SAD = 0x17E, ASSET_17F_ANIM_MUMBO_SWEEP = 0x17F, ASSET_180_ANIM_MUMBO_ROTATE = 0x180, - ASSET_181_ANIM_BEANSTALK_UNK = 0x181, - ASSET_182_ANIM_BEANSTALK_UNK = 0x182, - ASSET_183_ANIM_BEANSTALK_UNK = 0x183, + ASSET_184_ANIM_CLUCKER_ATTACK_SHORT = 0x184, ASSET_185_ANIM_CLUCKER_ATTACK_LONG = 0x185, ASSET_186_ANIM_CLUCKER_DIE = 0x186, @@ -3187,25 +3102,17 @@ typedef enum asset_e ASSET_189_ANIM_FLOTSAM_DIE = 0x189, ASSET_18A_ANIM_XMAS_GIFT = 0x18A, - ASSET_18D_ANIM_CATERPILLAR_UNK = 0x18D, ASSET_18E_ANIM_CATERPILLAR_IDLE = 0x18E, - ASSET_199_ANIM_EEYRIE_ADULT_UNK = 0x199, - ASSET_19A_ANIM_EEYRIE_ADULT_UNK = 0x19A, ASSET_19B_ANIM_UNKNOWN = 0x19B, - ASSET_19C_ANIM_BSWALRUS_BOUNCE = 0x19C, + ASSET_19D_ANIM_BSWALRUS_DIE = 0x19D, ASSET_19E_ANIM_BSWALRUS_SLED = 0x19E, ASSET_19F_ANIM_BSWALRUS_SLED_JUMP = 0x19F, ASSET_1A1_ANIM_SLED = 0x1A1, ASSET_1A2_ANIM_NABNUT_SLEEP = 0x1A2, - ASSET_1A3_ANIM_NABNUT_SPRING_LOOKING_AROUND = 0x1A3, - ASSET_1A4_ANIM_NABNUT_SPRING_EATING = 0x1A4, - ASSET_1A6_ANIM_GNAWTY_IDLE = 0x1A6, - ASSET_1A7_ANIM_GNAWTY_CHEERING = 0x1A7, - ASSET_1A8_ANIM_GNAWTY_RUNNING = 0x1A8, ASSET_1A9_ANIM_BSWALRUS_LOSS = 0x1A9, ASSET_1AF_ANIM_TWINKLY_MUNCHER_APPEAR = 0x1AF, @@ -3249,10 +3156,6 @@ typedef enum asset_e ASSET_217_ANIM_UNKNOWN = 0x217, - ASSET_21C_ANIM_SNORE_Z = 0x21C, - ASSET_21D_ANIM_ADULT_EYRIE_UNK = 0x21D, - ASSET_21E_ANIM_ADULT_EYRIE_UNK = 0x21E, - ASSET_220_ANIM_SIR_SLUSH_DIE = 0x220, ASSET_221_ANIM_WOZZA_IN_CAVE = 0x221, @@ -3269,11 +3172,8 @@ typedef enum asset_e ASSET_22D_ANIM_NABNUT_BACKFLIP = 0x22D, ASSET_22E_ANIM_NABNUT_STAND = 0x22E, ASSET_22F_ANIM_NABNUT_RUN = 0x22F, - ASSET_230_ANIM_PINK_SQUIRREL_UNK = 0x230, - ASSET_231_ANIM_NABNUT_BEDSHEETS_UNK = 0x231, ASSET_233_ANIM_ICECUBE = 0x233, - ASSET_234_ANIM_DEAD_SNAREBEAR = 0x234, ASSET_236_ANIM_BSPUMPKIN_REBOUND = 0x236, @@ -3309,24 +3209,12 @@ typedef enum asset_e ASSET_288_ANIM_FLIBBIT_OW = 0x288, - ASSET_2A1_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN = 0x2A1, - ASSET_2A2_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A3_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A4_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A5_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A6_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A7_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A8_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, - ASSET_2A9_ANIM_BAT_FALL, - ASSET_2AA_ANIM_BAT_DIE, - ASSET_2AB_ANIM_TEEHEE_DIE, + ASSET_2A9_ANIM_BAT_FALL = 0x2A9, + ASSET_2AA_ANIM_BAT_DIE = 0x2AA, + ASSET_2AB_ANIM_TEEHEE_DIE = 0x2AB, ASSET_2C0_ANIM_CHUMP_DIE = 0x2C0, - ASSET_2C6_ANIM_MUMBOS_HAND_WITH_PICTURE = 0x2C6, - ASSET_2C7_ANIM_MUMBOS_HAND_WITH_PICTURE, - ASSET_2C8_ANIM_MUMBOS_HAND_WITH_PICTURE, - // 2d1 Grey House Brick (Upon Smashing MM Huts) ASSET_2D2_MODEL_ORANGE = 0x2d2, //projectile // 2d3 MM Conga Tree @@ -3554,11 +3442,11 @@ typedef enum asset_e ASSET_3B0_SNACKER = 0x3B0, // 3b1 Concert Mumbo ASSET_3B2_MODEL_TWO_ICE_POLES_NEAR_CHEATO_3 = 0x3B2, - ASSET_3B3_MODEL_CCW_MUMBOS_HUT, - ASSET_3B4_MODEL_UNUSED, - ASSET_3B5_MODEL_UNUSED, - ASSET_3B6_MODEL_TTC_STAIRS_1, - ASSET_3B7_MODEL_TTC_STAIRS_2, + // 3b3 Mumbo's Hut + // Unused + // Unused + ASSET_3B6_MODEL_TTC_STAIRS_1 = 0x3B6, + ASSET_3B7_MODEL_TTC_STAIRS_1 = 0x3B7, // Unused // Unused // Unused @@ -3595,30 +3483,30 @@ typedef enum asset_e ASSET_3D9_MODEL_GV_KAZOOIE_DOOR = 0x3D9, // 3da GV Sun Door ASSET_3DB_MODEL_GV_STAR_HATCH = 0x3db, - ASSET_3DC_MODEL_MAGIC_CARPET, - ASSET_3DD_MODEL_RUBEE, - ASSET_3DE_MODEL_HISTUP, - ASSET_3DF_MODEL_TRUNKER, - ASSET_3E0_MODEL_GOBI, - ASSET_3E1_MODEL_RUBEES_EGG_POT, - ASSET_3E2_MODEL_GV_KAZOOIE_TARGET, - ASSET_3E3_MODEL_GOBI_ROPE, - ASSET_3E4_MODEL_GOBI_ROCK, - ASSET_3E5_MODEL_GRABBA_SHADOW, - ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, - ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW, - ASSET_3E8_MODEL_ANCIENT_ONE, - ASSET_3E9_MODEL_RED_ARROW, - ASSET_3EA_MODEL_RED_X, - ASSET_3EB_MODEL_RED_QUESTION_MARK, - ASSET_3EC_MODEL_SHRAPNEL, - ASSET_3ED_MODEL_BUZZBOMB, - ASSET_3EE_TANKTUP, - ASSET_3EF_MODEL_TANKTUP_LEG_FL, - ASSET_3F0_MODEL_TANKTUP_LEG_BL, - ASSET_3F1_MODEL_TANKTUP_LEG_FR, - ASSET_3F2_MODEL_TANKTUP_LEG_BR, - ASSET_3F3_MODEL_GOBI_SPIT, + ASSET_3DC_MODEL_MAGIC_CARPET = 0x3DC, + ASSET_3DD_MODEL_RUBEE = 0x3DD, + ASSET_3DE_MODEL_HISTUP = 0x3DE, + ASSET_3DF_MODEL_TRUNKER = 0x3DF, + ASSET_3E0_MODEL_GOBI = 0x3E0, + ASSET_3E1_MODEL_RUBEES_EGG_POT = 0x3E1, + ASSET_3E2_MODEL_GV_KAZOOIE_TARGET = 0x3E2, + ASSET_3E3_MODEL_GOBI_ROPE = 0x3E3, + ASSET_3E4_MODEL_GOBI_ROCK = 0x3E4, + ASSET_3E5_MODEL_GRABBA_SHADOW = 0x3E5, + // 3e6 GV Jinxy Head 2 + ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW = 0x3e7, + ASSET_3E8_MODEL_ANCIENT_ONE = 0x3E8, + ASSET_3E9_MODEL_RED_ARROW = 0x3E9, + ASSET_3EA_MODEL_RED_X = 0x3EA, + ASSET_3EB_MODEL_RED_QUESTION_MARK = 0x3EB, + ASSET_3EC_MODEL_SHRAPNEL = 0x3EC, + ASSET_3ED_MODEL_BUZZBOMB = 0x3ED, + ASSET_3EE_TANKTUP = 0x3EE, + ASSET_3EF_MODEL_TANKTUP_LEG_FL = 0x3EF, + ASSET_3F0_MODEL_TANKTUP_LEG_BL = 0x3F0, + ASSET_3F1_MODEL_TANKTUP_LEG_FR = 0x3F1, + ASSET_3F2_MODEL_TANKTUP_LEG_BR = 0x3F2, + ASSET_3F3_MODEL_GOBI_SPIT = 0x3F3, // Unused // 3f5 BGS Green Jiggy Switch ASSET_3F5_BGS_JIGGY_SWITCH = 0x3F5, @@ -3634,7 +3522,7 @@ typedef enum asset_e ASSET_3FF_MODEL_GV_SUN_DOOR = 0x3FF, ASSET_400_MODEL_SUN_SWITCH = 0x400, ASSET_401_MODEL_FLOTSAM = 0x401, - ASSET_402_MODEL_EGG_TOLL = 0x402, // Floating Green Orb + ASSET_402_MODEL_EGG_TOLL = 0x402, ASSET_403_MODEL_RUSTY_BUCKET_REAR_PROPELLER = 0x403, ASSET_404_MODEL_RBB_GREEN_PROPELLER_SWITCH = 0x404, ASSET_405_MODEL_RBB_GREY_PROPELLER_SWITCH = 0x405, @@ -3662,7 +3550,7 @@ typedef enum asset_e ASSET_41B_MODEL_ANCHOR_SWITCH = 0x41B, ASSET_41C_MODEL_SNORKEL = 0x41C, ASSET_41D_MODEL_ANCHOR = 0x41D, - ASSET_41E_MODEL_RAREWARE_FLAG = 0x41E, + // 41e RBB Rareware Flag // 41f (Gruntilda's Final Battle Forcefield?) // 420 (Explosion 2D?) ASSET_421_MODEL_FP_SNOWMAN_BUTTON = 0x421, @@ -3671,7 +3559,7 @@ typedef enum asset_e // 424 GV Cactus ASSET_425_MODEL_CROCTUS = 0x425, ASSET_426_MODEL_XMAS_TREE_STAR = 0x426, - ASSET_427_MODEL_WOODEN_PLANK = 0x427, + // 427 (Wooden Plank) ASSET_428_MODEL_BOSS_BOOM_BOX = 0x428, ASSET_429_MODEL_CC_KEY = 0x429, ASSET_42A_UNKNOWN = 0x42A, // 42a (Smoke 2D?) @@ -3692,15 +3580,15 @@ typedef enum asset_e ASSET_438_MODEL_HONEYCOMB_SWITCH = 0x438, // 439 (Unknown?) ASSET_43A_MODEL_CLANKER_SAWBLADE_PROPELLOR = 0x43A, - ASSET_43B_MODEL_BELL_BUOY, - ASSET_43C_MODEL_ROWBOAT, + // 43b RBB Bell Buoy + // 43c RBB Row Boat ASSET_43D_MODEL_MMM_CLOCK_SWITCH = 0x43D, ASSET_43E_MODEL_HEDGE_GATE_RIGHT_LOCK_2 = 0x43E, // 43f (White Star?) ASSET_440_MODEL_SNAREBEAR = 0x440, // 441 (Sir Slush Snowball?) ASSET_442_MODEL_TWINKLY_BOX = 0x442, - ASSET_443_MODEL_ZUBBA_HONEY_LUMP = 0x443, + // 443 CCW Zubba Honey Lump ASSET_444_MODEL_CCW_ZUBBA_DOOR = 0x444, ASSET_445_MODEL_CCW_ZUBBA_DOOR = 0x445, ASSET_446_MODEL_ZUBBA = 0x446, @@ -3731,9 +3619,9 @@ typedef enum asset_e // 45f (Firey Rock?) ASSET_460_MODEL_KAZOOIE_RACK_FEATHERS = 0x460, ASSET_461_MODEL_GREEN_FOG_OUTSIDE_TOWER, - ASSET_462_MODEL_PINK_SQUIRREL = 0x462, - ASSET_463_MODEL_NABNUT_BEDSHEETS = 0x463, - ASSET_464_MODEL_NABNUT_BED = 0x464, + // 462 Nabnut's Girlfriend + // 463 Nabnut's Bed Sheet + // 464 Nabnut's Bed // 465 Dead Snarebear // 466 (Sparkle 2D?) ASSET_467_MODEL_TRANSITION_FALLING_JIGGIES = 0x467, @@ -3748,12 +3636,12 @@ typedef enum asset_e ASSET_46F_MODEL_CUCKOO_CLOCK = 0x46F, // 470 Banjo's Bookshelves // 471 Empty Blow Picture Frame - ASSET_472_UNKNOWN = 0x472, // Blank Picture? - ASSET_473_MODEL_BBQ_MUMBO, - ASSET_474_MODEL_BBQ_GRILL_AND_FISH, - ASSET_475_SPRITE_GAME_OVER_HEART, - ASSET_476_SPRITE_BLUE_GLOW, - ASSET_477_SPRITE_YELLOW_GLOW, + // 472 Blank Picture + ASSET_473_MODEL_BBQ_MUMBO = 0x473, + ASSET_474_MODEL_BBQ_GRILL_AND_FISH = 0x474, + ASSET_475_SPRITE_GAME_OVER_HEART = 0x475, + ASSET_476_SPRITE_BLUE_GLOW = 0x476, + ASSET_477_SPRITE_YELLOW_GLOW = 0x477, // 478 (Yellow Glow?) ASSET_479_MODEL_BIKINI_GIRL = 0x479, // 47a (Brown Ball?) @@ -3775,7 +3663,7 @@ typedef enum asset_e ASSET_48A_MODEL_FLIGHT_PAD = 0x48A, ASSET_48B_MODEL_JIGGY_PODIUM = 0x48B, ASSET_48C_MODEL_BOOM_BOX = 0x48C, - ASSET_48D_MODEL_NABNUT_EATING_ACORNS = 0x48D, + // 48d Nabnut Eating Acorns ASSET_48E_MODEL_ACORN = 0x48E, ASSET_48F_MODEL_GNAWTY = 0x48F, ASSET_490_MODEL_GNAWTY_BOULDER = 0x490, @@ -3893,12 +3781,12 @@ typedef enum asset_e ASSET_4FE_MODEL_WHIPCRACK_PART_1 = 0x4FE, ASSET_4FF_MODEL_WHIPCRACK_PART_2 = 0x4FF, ASSET_500_MODEL_WHIPCRACK_PART_3 = 0x500, - ASSET_501_MODEL_MOUND_OF_ACORNS = 0x501, + // 501 CCW Mound Of Acorns ASSET_502_MODEL_NABNUT = 0x502, - ASSET_503_MODEL_NABNUT_BELLY_FULL = 0x503, + // 503 Nabnut (Belly Full) ASSET_504_MODEL_ICECUBE = 0x504, ASSET_505_MODEL_ICECUBE_CHUNK = 0x505, - ASSET_506_CCW_DEAD_SNAREBEAR = 0x506, + // 506 CCW Dead Snarebear (Venus Flytrap) ASSET_507_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_1 = 0x507, ASSET_508_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_2 = 0x508, ASSET_509_MODEL_GL_SARCOPHAGUS = 0x509, @@ -3921,28 +3809,28 @@ typedef enum asset_e ASSET_51C_MODEL_SCARAB_BEETLE_PART_1 = 0x51C, // 51d SCARAB BEETLE PART (Wing) ASSET_51E_MODEL_SCARAB_BEETLE_PART_2 = 0x51e, - ASSET_51F_MODEL_SCARAB_BEETLE_PART_3, - ASSET_520_MODEL_SCARAB_BEETLE_PART_4, - ASSET_521_MODEL_PORTRAIT_CHOMPA, - ASSET_522_MODEL_PORTRAIT_OF_GRUNTY, - ASSET_523_MODEL_PORTRAIT_CHOMPA_TEETH, - ASSET_524_MODEL_PORTRAIT_CHOMPA_HEAD, - ASSET_525_MODEL_PORTRAIT_CHOMPA_PART, - ASSET_526_SPRITE_FIRE, - ASSET_527_MODEL_PORTRAIT_OF_BLACKEYE, - ASSET_528_MODEL_PORTRAIT_OF_TOWER, - ASSET_529_MODEL_PORTRAIT_OF_TREE_AND_MOON, - ASSET_52A_MODEL_PORTRAIT_OF_TEEHEE, - ASSET_52B_MODEL_PORTRAIT_OF_MINION, - ASSET_52C_MODEL_GRUBLIN_HOOD, - ASSET_52D_MODEL_GRUBLIN_HOOD_HAT, - ASSET_52E_MODEL_CCW_SEASON_DOOR, - ASSET_52F_MODEL_BANJOS_CHAIR, - ASSET_530_MODEL_BANJOS_BED, - ASSET_531_MODEL_GNAWTYS_DEN, - ASSET_532_MODEL_BANJO_KAZOOIE_CUTSCENES, // (Gameboy/Beer/Sunglasses/Chair) - ASSET_533_MODEL_NABNUT_DOOR, - ASSET_534_MODEL_FLIGHT_PAD_SWITCH, + ASSET_51F_MODEL_SCARAB_BEETLE_PART_3 = 0x51F, + ASSET_520_MODEL_SCARAB_BEETLE_PART_4 = 0x520, + ASSET_521_MODEL_PORTRAIT_CHOMPA = 0x521, + ASSET_522_MODEL_PORTRAIT_OF_GRUNTY = 0x522, + ASSET_523_MODEL_PORTRAIT_CHOMPA_TEETH = 0x523, + ASSET_524_MODEL_PORTRAIT_CHOMPA_HEAD = 0x524, + ASSET_525_MODEL_PORTRAIT_CHOMPA_PART = 0x525, + ASSET_526_SPRITE_FIRE = 0x526, + ASSET_527_MODEL_PORTRAIT_OF_BLACKEYE = 0x527, + ASSET_528_MODEL_PORTRAIT_OF_TOWER = 0x528, + ASSET_529_MODEL_PORTRAIT_OF_TREE_AND_MOON = 0x529, + ASSET_52A_MODEL_PORTRAIT_OF_TEEHEE = 0x52A, + ASSET_52B_MODEL_PORTRAIT_OF_MINION = 0x52B, + ASSET_52C_MODEL_GRUBLIN_HOOD = 0x52C, + ASSET_52D_MODEL_GRUBLIN_HOOD_HAT = 0x52D, + ASSET_52E_MODEL_CCW_SEASON_DOOR = 0x52E, + ASSET_52F_MODEL_BANJOS_CHAIR = 0x52F, + ASSET_530_MODEL_BANJOS_BED = 0x530, + // 531 Gnawty's Den + ASSET_532_MODEL_BANJO_KAZOOIE_CUTSCENES = 0x532, // (Gameboy/Beer/Sunglasses/Chair) + // 533 CCW Nabnut's Door + ASSET_534_MODEL_FLIGHT_PAD_SWITCH = 0x534, // 535 Flight Pad Blue Fragment // 536 Flight Pad Red Fragment // 537 Flight Pad Yellow Fragment @@ -3967,40 +3855,40 @@ typedef enum asset_e ASSET_54A_MODEL_GRUNTLING_RED = 0x54A, // 54b (Big Fireball?) ASSET_54C_MODEL_GAME_OVER = 0x54C, - ASSET_54D_MODEL_BANJO_KAZOOIE_SIGN, - ASSET_54E_MODEL_COPYRIGHT_OVERLAY, - ASSET_54F_MODEL_CHEATO, - ASSET_550_MODEL_LARGE_DOOR_TO_FINAL_BATTLE, - ASSET_551_MODEL_JINJONATOR, - ASSET_552_MODEL_BROOMSTICK_PIECE_HEAD, - ASSET_553_MODEL_BROOMSTICK_PIECE_SHORT, - ASSET_554_MODEL_BROOMSTICK_PIECE_LONG, - ASSET_555_MODEL_BROOMSTICK_PIECE_EYE, - ASSET_556_MODEL_YELLOW_JINJO_BLAST, - ASSET_557_MODEL_ORANGE_JINJO_BLAST, - ASSET_558_MODEL_GREEN_JINJO_BLAST, - ASSET_559_MODEL_PINK_JINJO_BLAST, - ASSET_55A_MODEL_WORLD_EXIT_PAD, - ASSET_55B_MODEL_BOGGY_IGLOO, - ASSET_55C_MODEL_PRESS_START_OVERLAY, - ASSET_55D_MODEL_NO_CONTROLLER_OVERLAY, - ASSET_55E_MODEL_NAPPER, - ASSET_55F_MODEL_FF_PRIZE_WASHING_CAULDRON, - ASSET_560_MODEL_FF_PRIZE_GRUNTY_DOLL, - ASSET_561_MODEL_GRUNTLING_BLUE, - ASSET_562_MODEL_GRUNTLING_BLACK, - ASSET_563_MODEL_LEVEL_ENTRY_SIGNS, - ASSET_564_MODEL_PURPLE_TEEHEE, - ASSET_565_MODEL_BOTTLES_BONUS_BANJO_HAND, - ASSET_566_MODEL_BLACK_SNIPPET, - ASSET_567_MODEL_BLACK_CRAB_HEAD, - ASSET_568_MODEL_BLACK_CRAB_LEG, - ASSET_569_MODEL_BLACK_CRAB_CLAW, - ASSET_56A_MODEL_FP_HOUSE_CHIMNEY, - ASSET_56B_MODEL_SANDYBUTT_PYRAMID, - ASSET_56C_MODEL_THE_END_SIGN, - ASSET_56D_MUMBOS_HAND_WITH_PICTURE, // Mumbo's Hand with SNS pictures - ASSET_56E_HAMMERHEAD_BEACH_SCENERY, // Credits map + ASSET_54D_MODEL_BANJO_KAZOOIE_SIGN = 0x54D, + ASSET_54E_MODEL_COPYRIGHT_OVERLAY = 0x54E, + ASSET_54F_MODEL_CHEATO = 0x54F, + ASSET_550_MODEL_LARGE_DOOR_TO_FINAL_BATTLE = 0x550, + ASSET_551_MODEL_JINJONATOR = 0x551, + ASSET_552_MODEL_BROOMSTICK_PIECE_HEAD = 0x552, + ASSET_553_MODEL_BROOMSTICK_PIECE_SHORT = 0x553, + ASSET_554_MODEL_BROOMSTICK_PIECE_LONG = 0x554, + ASSET_555_MODEL_BROOMSTICK_PIECE_EYE = 0x555, + ASSET_556_MODEL_YELLOW_JINJO_BLAST = 0x556, + ASSET_557_MODEL_ORANGE_JINJO_BLAST = 0x557, + ASSET_558_MODEL_GREEN_JINJO_BLAST = 0x558, + ASSET_559_MODEL_PINK_JINJO_BLAST = 0x559, + ASSET_55A_MODEL_WORLD_EXIT_PAD = 0x55A, + ASSET_55B_MODEL_BOGGY_IGLOO = 0x55B, + ASSET_55C_MODEL_PRESS_START_OVERLAY = 0x55C, + ASSET_55D_MODEL_NO_CONTROLLER_OVERLAY = 0x55D, + ASSET_55E_MODEL_NAPPER = 0x55E, + ASSET_55F_MODEL_FF_PRIZE_WASHING_CAULDRON = 0x55F, + ASSET_560_MODEL_FF_PRIZE_GRUNTY_DOLL = 0x560, + ASSET_561_MODEL_GRUNTLING_BLUE = 0x561, + ASSET_562_MODEL_GRUNTLING_BLACK = 0x562, + ASSET_563_MODEL_LEVEL_ENTRY_SIGNS = 0x563, + ASSET_564_MODEL_PURPLE_TEEHEE = 0x564, + ASSET_565_MODEL_BOTTLES_BONUS_BANJO_HAND = 0x565, + ASSET_566_MODEL_BLACK_SNIPPET = 0x566, + ASSET_567_MODEL_BLACK_CRAB_HEAD = 0x567, + ASSET_568_MODEL_BLACK_CRAB_LEG = 0x568, + ASSET_569_MODEL_BLACK_CRAB_CLAW = 0x569, + ASSET_56A_MODEL_FP_HOUSE_CHIMNEY = 0x56A, + ASSET_56B_MODEL_SANDYBUTT_PYRAMID = 0x56B, + ASSET_56C_MODEL_THE_END_SIGN = 0x56C, + ASSET_56D_MUMBOS_HAND_WITH_PICTURE = 0x56D, // Mumbo's Hand with SNS pictures + // 56E Hammerhead Beach Scenery // 56F Unused // 570 Unused // Unused @@ -4842,7 +4730,7 @@ typedef enum asset_e ASSET_DA6_DIALOG_BEEHIVE_WITH_BEES = 0xDA6, ASSET_DA7_DIALOG_MUMBO_CCW_SUMMER = 0xDA7, ASSET_DA8_DIALOG_MUMBO_CCW_AUTUMN = 0xDA8, - ASSET_DA9_DIALOG_MUMBO_CCW_VACATION = 0xDA9, + ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS = 0xDAA, ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS = 0xDAB, ASSET_DAC_DIALOG_MUMBO_FAIL_TO_BUY = 0xDAC, @@ -4921,20 +4809,14 @@ typedef enum asset_e ASSET_F5D_DIALOG_MUMBO_MAGIC_RUN_OUT_FULL = 0xF5D, ASSET_F5E_DIALOG_MUMBO_MAGIC_RUN_OUT_ABREV = 0xF5E, - ASSET_F64_DIALOG_NOTEDOORS_LEARN = 0xF64, - ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, - ASSET_F66_DIALOG_UNKNOWN, - ASSET_F67_DIALOG_UNKNOWN, - ASSET_F68_DIALOG_MM_THREE_NEW_MOVES_TO_LEARN, - - ASSET_F6E_DIALOG_DIDNT_LEARN_ALL_MOVES_FROM_MM = 0xF6E, + ASSET_F64_DIALOG_NOTEDOORS_LEARN = 0xf64, + ASSET_F65_DIALOG_NOTEDOORS_REFRESHER = 0xF65, + ASSET_F66_DIALOG_UNKNOWN = 0xF66, + ASSET_F67_DIALOG_UNKNOWN = 0xF67, - ASSET_F79_DIALOG_UNKNOWN = 0xF79, - ASSET_F7A_DIALOG_UNKNOWN, - ASSET_F7B_DIALOG_BOTTLES_JIGSAW_PICTURE_MEET, - - ASSET_F7F_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_BEFORE_PODIUM = 0xF7F, - ASSET_F80_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_AFTER_PODIUM, + ASSET_F79_DIALOG_UNKNOWN = 0xf79, + ASSET_F7A_DIALOG_UNKNOWN = 0xF7A, + ASSET_F7B_DIALOG_BOTTLES_JIGSAW_PICTURE_MEET = 0xF7B, ASSET_FA8_EGG_CHEAT_ACTIVATION = 0xFA8, ASSET_FA9_RED_FEATHER_CHEAT_ACTIVATION = 0xFA9, @@ -5403,7 +5285,6 @@ typedef enum asset_e ASSET_1514_MODEL_GL_FF_ENTRANCE_XLU = 0x1514, ASSET_1515_MODEL_GL_BATTLEMENTS_XLU, - // [port] JP-exclusive sprites for world name banners SPRITE_WORLD_NAME_TOTAL = 0x1600, SPRITE_WORLD_NAME_SPIRAL_MOUNTAIN, SPRITE_WORLD_NAME_GRUNTILDAS_LAIR, @@ -5454,8 +5335,8 @@ enum marker_e{ MARKER_13_SNIPPET = 0x13, MARKER_14_SNACKER, MARKER_15_CLAM, - MARKER_16_UNKNOWN, // src/core2/code_4BE10.c - MARKER_17_CONCERT_BANJO, + + MARKER_17_CONCERT_BANJO = 0x17, MARKER_1B_CONCERT_TOOTY = 0x1B, MARKER_1C_INTRO_N64_CUBE, @@ -5478,8 +5359,8 @@ enum marker_e{ MARKER_32_PLAYER_SHADOW, MARKER_33_LEAKY, MARKER_34_CEMETARY_POT, - MARKER_35_CLIMB_BASE, - MARKER_36_ORANGE_COLLECTIBLE, + + MARKER_36_ORANGE_COLLECTIBLE = 0x36, MARKER_37_GOLD_BULLION, MARKER_38_TURBO_TALON_TRAINERS, MARKER_39_MUMBO_TOKEN, @@ -5503,8 +5384,8 @@ enum marker_e{ MARKER_53_EMPTY_HONEYCOMB, MARKER_55_HONEYCOMB = 0x55, - MARKER_56_UNKNOWN, - MARKER_57_STEAM, + + MARKER_57_STEAM = 0x57, MARKER_58_WADING_BOOTS_TOUCH_SPARKLE, MARKER_59_TURBO_TRAINERS_TOUCH_SPARKLE, MARKER_5A_JINJO_BLUE, @@ -5549,8 +5430,8 @@ enum marker_e{ MARKER_99_TEEHEE = 0x99, MARKER_9A_1881_BARREL_TOP, - MARKER_9B_MODEL_PLAYER_SHADOW, - MARKER_9C_SHACK_DOOR, + + MARKER_9C_SHACK_DOOR = 0x9C, MARKER_9D_MANSION_DOOR, MARKER_9E_CELLAR_HATCH, MARKER_9F_CHURCH_GATE_LEFT_LOCK, @@ -5581,7 +5462,7 @@ enum marker_e{ MARKER_B8_MOLEHILL, MARKER_B9_FP_SNOWMAN_BUTTON, MARKER_BA_XMAS_TREE, - MARKER_BB_JINXY_HEAD_SANDYBUTT, + MARKER_BB_UNKNOWN, MARKER_BC_GOBI_1, MARKER_BD_GOBI_ROPE, MARKER_BE_GOBI_ROCK, @@ -5712,7 +5593,7 @@ enum marker_e{ MARKER_167_SHARKFOOD_ISLAND, MARKER_168_ICE_KEY, MARKER_169_SNS_EGG, - MARKER_16A_FF_TELEPORT_PAD, // src/core2/code_4C020.c + // 0x16A src/core2/code_4C020.c MARKER_16B_SNIPPET_UPSIDEDOWN = 0x16B, MARKER_16C_NIPPER, MARKER_16D_CHEATO_1, @@ -5729,13 +5610,13 @@ enum marker_e{ MARKER_178_NO_CONTROLLER_OVERLAY, MARKER_179_JIGSAW_PUZZLE, MARKER_17A_BOTTLES_BONUS_BANJO_HAND, - MARKER_17B_UNKNOWN, - MARKER_17C_MODEL_THE_END_SIGN, + + MARKER_17C_MODEL_THE_END_SIGN = 0x17C, MARKER_17D_IRON_GATE_NO_LOCK, MARKER_182_RBB_EGG_TOLL = 0x182, - MARKER_183_RBB_CAGE_UP_SWITCH, - MARKER_184_RBB_TNT_DOWN_SWITCH, + MARKER_183_RBB_EGG_TOLL, + MARKER_184_RBB_EGG_TOLL, MARKER_185_RBB_REAR_PROPELLER, MARKER_186_RBB_GREEN_PROPELLER_SWITCH, MARKER_187_RBB_SPINNING_SINGLE_PIPE_1, @@ -5755,7 +5636,6 @@ enum marker_e{ MARKER_195_WHISTLE_SWITCH_1, MARKER_196_WHISTLE_SWITCH_2, MARKER_197_WHISTLE_SWITCH_3, - MARKER_198_RAREWARE_FLAG, MARKER_19A_TIPTUP = 0x19A, MARKER_19B_CHOIR_TURTLE_YELLOW, @@ -5773,49 +5653,33 @@ enum marker_e{ MARKER_1A7_CLANKER_WHIPCRACK, MARKER_1A9_CC_BREAKABLE_GRATES = 0x1A9, - MARKER_1AA_BELL_BUOY, - MARKER_1AB_ROWBOAT, - MARKER_1AC_ZUBBA_DOOR, - MARKER_1AD_ZUBBA_HONEY_LUMP, + + MARKER_1AC_ZUBBA_DOOR = 0x1AC, + MARKER_1AE_ZUBBA = 0x1AE, - MARKER_1AF_ZUBBA_DOCILE, + MARKER_1B0_CCW_BEANSTALK = 0x1B0, MARKER_1B1_CCW_GOBI, MARKER_1B2_CLUCKER_A, MARKER_1B3_EAGLE_EGG, MARKER_1B4_EEYRIE_BABY, MARKER_1B5_CATERPILLAR, - MARKER_1B6_EEYRIE_ADULT, + MARKER_1B7_BOOM_BOX = 0x1B7, - MARKER_1B8_BOOM_BOX_MINIGAME_CTRL = 0x1B8, - MARKER_1B9_NABNUT_SPRING = 0x1B9, - MARKER_1BA_NABNUT_FULL_BELLY, + MARKER_1BB_NABNUT = 0x1BB, - MARKER_1BC_CARRIED_ACORN, - MARKER_1BD_GNAWTY_SWIMMING, - MARKER_1BE_GNAWTY_SUMMER, + MARKER_1BF_GNAWTY_BOULDER = 0x1BF, - MARKER_1C0_BOSS_BOOMBOX_CTRL = 0x1C0, - MARKER_1C2_DEAD_BEANSTALK = 0x1C2, - MARKER_1C3_SNORE_Z, - MARKER_1C4_CUTSCENE_ADULT_EYRIE, MARKER_1C5_WHIPCRACK = 0x1C5, - MARKER_1C6_MOUND_OF_ACORNS, - MARKER_1C7_PINK_SQUIRREL, - MARKER_1C8_NABNUT_BEDSHEETS, - MARKER_1C9_NABNUT_BED, - MARKER_1CA_NABNUT, - MARKER_1CB_NABNUT_EATING_ACORNS, - MARKER_1CC_CCW_UNKNOWN, + MARKER_1CD_GV_MAZE_CTRL = 0x1CD, - MARKER_1CE_INDOOR_GNAWTY, + MARKER_1CF_GRILLE_CHOMPA_ATTACKING = 0x1CF, MARKER_1D0_CLUCKER_B, MARKER_1D1_PORTRAIT_CHOMPA_B, - MARKER_1D2_SPINNING_SINGLE_PIPE_SFX_CTRL, - MARKER_1D3_DOUBLE_SINGLE_PIPE_SFX_CTRL, - MARKER_1D4_SANDYBUTT_PYRAMID, + + MARKER_1D4_SANDYBUTT_PYRAMID = 0x1D4, MARKER_1D5_PALM_TREE, MARKER_1E0_BRENTILDA = 0x1E0, @@ -5838,7 +5702,6 @@ enum marker_e{ MARKER_1F2_WIDE_WINDOW, MARKER_1F3_TALL_WINDOW, MARKER_1F4_TOOTS, - MARKER_1F5_UNKNOWN, MARKER_1F9_SNARE_BEAR = 0x1F9, MARKER_1FA_POLAR_BEAR_CUB_BLUE, @@ -5868,9 +5731,6 @@ enum marker_e{ MARKER_218_LIMBO, MARKER_219_MUMMUM, MARKER_21A_SEAMAN_GRUBLIN, - MARKER_21B_UNKNOWN, - - MARKER_21E_CCW_MUMBOS_HUT = 0x21E, MARKER_224_BREAKABLE_FLOOR_COBWEB = 0x224, MARKER_225_BREAKABLE_WALL_COBWEB, @@ -5902,12 +5762,12 @@ enum marker_e{ MARKER_240_LAIR_SWITCH_FLIGHT_PAD, MARKER_241_SHOCK_JUMP_PAD_SWITCH, MARKER_242_LAIR_SWITCH_SHOCK_JUMP_PAD, - MARKER_243_NABNUT_DOOR, + MARKER_244_DINGPOT = 0x244, MARKER_245_XMAS_TREE_EGG_TOLL = 0x245, MARKER_250_ICECUBE_A = 0x250, - MARKER_251_DEAD_SNAREBEAR, + MARKER_252_LOGGO = 0x252, MARKER_253_SCARAB_BEETLE, MARKER_254_PORTRAIT_CHOMPA_A, @@ -5933,12 +5793,11 @@ enum marker_e{ MARKER_268_STAIRS_1, MARKER_269_STAIRS_2, MARKER_26A_LIGHTHOUSE_B, - MARKER_26B_GNAWTYS_DEN, - MARKER_26C_GNAWTYS_BED, - MARKER_26D_GNAWTYS_SHELVES, - MARKER_26E_UNKNOWN, // src/core2/code_4C020.c - MARKER_26F_UNKNOWN, // src/core2/code_4C020.c - MARKER_270_TWO_ICE_POLES_NEAR_CHEATO_3, + + // 0x26E src/core2/code_4C020.c + // 0x26F src/core2/code_4C020.c + + MARKER_270_TWO_ICE_POLES_NEAR_CHEATO_3 = 0x270, MARKER_276_STONE_JINJO = 0x276, @@ -5958,8 +5817,7 @@ enum marker_e{ MARKER_288_GRUNTY_SHADOW = 0x288, - MARKER_294_MUMBOS_HAND_WITH_PICTURE = 0x294, - MARKER_295_GRUNTLING_BLUE, + MARKER_295_GRUNTLING_BLUE = 0x295, MARKER_296_TEEHEE_PURPLE, MARKER_297_GIANT_GRAVESTONE, MARKER_298_MUMMUM_BALL, @@ -5971,7 +5829,6 @@ enum marker_e{ MARKER_29E_BIGBUTT_KNOCKED_DOWN, MARKER_29F_DUMMY_PLAYER_ANCHOR, - MARKER_300_CUSTOM_COLLECTIBLE, }; enum hitbox_e{ diff --git a/include/file_and_line.h b/include/file_and_line.h index 93f44d73f..a931d6b5e 100644 --- a/include/file_and_line.h +++ b/include/file_and_line.h @@ -1,11 +1,8 @@ #ifndef _FILE_AND_LINE_H_ #define _FILE_AND_LINE_H_ - #include - -#if 0 extern void __assert(const char *, const char *, int); -#endif + #ifdef NONMATCHING #define LINE(line_num) __LINE__ @@ -13,24 +10,18 @@ extern void __assert(const char *, const char *, int); #define matching_assert(EX, F, L) assert(EX) #else #define LINE(line_num) line_num - #ifdef __ANSI_CPP__ - #define FILE(file_name) #file_name + #define FILE(file_name) # file_name #else #define FILE(file_name) "file_name" #endif -#if 0 #ifdef __ANSI_CPP__ - #define matching_assert(EX, F, L) \ - ((EX) ? ((void)0) : __assert(#EX, #F, L)) + #define matching_assert(EX, F, L) ((EX)?((void)0):__assert( # EX , # F, L)) #else - #define matching_assert(EX, F, L) \ - ((EX) ? ((void)0) : __assert("EX", "F", L)) + #define matching_assert(EX, F , L) ((EX)?((void)0):__assert("EX", "F", L)) #endif #endif - #define matching_assert(EX, F, L) ((void)0) -#endif -#endif \ No newline at end of file +#endif diff --git a/include/functions.h b/include/functions.h index 8222da5b3..b6b8d686b 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2,18 +2,10 @@ #define FUNCTIONS_H #include -#include "string.h" -#include "math.h" - -#include "port/UI/cvar_prefixes.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#ifdef __cplusplus -extern "C" { -#endif #include "enums.h" #include "structs.h" +#include "string.h" #include "rand.h" #include "prop.h" @@ -29,21 +21,22 @@ extern "C" { #include "core2/staticcamera.h" #include "core2/anim/sprite.h" #include "core2/ba/anim.h" -#include "core2/ba/carry.h" -#include "core2/ba/drone.h" -#include "core2/lighting.h" -#include "core2/particle.h" #include "core2/ba/model.h" -#include "core2/ba/physics.h" #include "core2/ba/timer.h" #include "core2/nc/camera.h" -#include "core2/yaw.h" +#include "port/ShipUtils.h" +#include "port/UI/cvar_prefixes.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include "math.h" #include "bk_time.h" #include "bs_funcs.h" #include "bsint.h" #include "generic.h" +#include + // FuncUnk40 defined in core2/commonParticle.h — forward-typedef here to avoid circular include #ifndef FUNCUNK40_DEFINED #define FUNCUNK40_DEFINED @@ -67,14 +60,13 @@ extern f32 fabsf(f32); f32 cosf(f32); -// --- core2/propModelList.c --- +// --- core2/prop_assetcache.c --- BKModelBin *propModelList_getModelIfActive(s32 arg0); BKSpriteDisplayData *propModelList_getSpriteDisplayList(s32 arg0); BKSprite *propModelList_getSprite(s32 arg0); BKModelBin *propModelList_getModel(s32); // --- core2/actor_cubepropsystem.c --- -BKModelBin *marker_loadModelBin(ActorMarker *marker); ActorMarker *func_8032DCAC(void); BKVertexList *func_80330CFC(Actor *self, s32 arg1); BKModelBin *func_80330E28(Actor *self); @@ -95,7 +87,7 @@ void marker_setActorUpdateFunc(ActorMarker *marker, ActorUpdateFunc method); void marker_setCollisionScripts(ActorMarker *marker, MarkerCollisionFunc ow_func, MarkerCollisionFunc arg2, MarkerCollisionFunc die_func); void marker_setFreeMethod(ActorMarker *, void (*)(Actor *)); -// --- core2/gccube.c --- +// --- core2/actor_cubebounds.c --- NodeProp *cubeList_findNodePropByActorIdAndPosition_s32(enum actor_e actor_id, s32 position[3]); NodeProp *func_80305510(s32 arg0); BKCollisionTriangle *func_80303800(f32 volume_p1[3], f32 volume_p2[3], f32 arg2[3], u32 arg3); @@ -115,7 +107,10 @@ u8 GetCurrentMap(); s32 getGameMode(void); void transitionToMap(enum map_e map, s32 exit, s32 transition); -// --- core2/map/list.c --- +// --- core2/time.c --- +f32 time_getDelta(void); + +// --- core2/map_list.c --- BKCollisionTriangle *func_8029463C(void); BKModelBin *func_802946A8(void); BKCollisionTriangle *func_802946CC(void); @@ -128,7 +123,7 @@ BKCollisionTriangle *func_8031C5F4(struct0 *self); BKModelBin *func_8031C5DC(struct0 *self); struct0 *func_8031B9D8(void); -// --- core2/collision/dispatch.c --- +// --- core2/collision/funcs.c --- BKCollisionTriangle *func_80320B98(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3); // func_80320C94, func_80320DB0 return BKCollisionTriangle* but // have conflicting local externs (bool/s32/int) in decomp source files. @@ -159,8 +154,6 @@ Actor *marker_getActor(ActorMarker *); Actor *marker_getActorAndRotation(ActorMarker *marker, f32 rotation[3]); Actor *subaddie_getLinkedActor(Actor *); ActorMarker *func_8032B16C(enum jiggy_e jiggy_id); -ActorMarker *actorArray_findHoneycombMarkerById(enum honeycomb_e id); -ActorMarker *actorArray_findMumboTokenMarkerById(enum mumbotoken_e id); bool func_80329078(Actor *, s32, s32); bool func_80329480(Actor *); bool subaddie_maybe_set_state_position_direction(Actor *, s32, f32, s32, f32 ); @@ -199,6 +192,12 @@ struct56s *func_80343F00(s32 indx, f32 arg1[3]); Struct83s *func_803406B0(void); Struct83s *func_803406D4(Struct83s *self); +// --- core2/vtx/list.c --- + +// --- core2/spline_bezier.c --- + +// --- core2/model/render.c --- + // --- core2/vtx/colorapply.c --- Struct70s *func_8034C344(s32 arg0); Struct70s *func_8034C448(s32 arg0); @@ -242,8 +241,8 @@ BoneTransformList *anim_getStartTransform(Animation *self); BoneTransformList *anim_getTargetTransform(Animation *self); // --- core1/audio_manager.c --- -ALDMAproc audioManager_DMAInitProc(void *state); -OSThread *audioManager_getThread_PAL(void); +void *func_802403B8(void *state); +void *audioManager_getThread_PAL(void); // --- core2/anim/anim_sequencehandler.c --- u8 *func_8032479C(void); @@ -262,12 +261,20 @@ f32 babuzz_80290890(f32 arg0); f32 babuzz_80290920(f32 arg0, f32 arg1, f32 arg2); f32 baeyes_getEyePosition(s32 id); f32 baanim_getTimer(void); +f32 batimer_get(s32 id); f32 bafalldamage_get_distance_fallen(void); f32 bastick_calculateZonePosition(f32 arg0, f32 arg1, f32 arg2); f32 bastick_getX(void); f32 bastick_getAngle(void); f32 baModel_getYaw(void); -f32 climb_getRadius(void); +f32 baphysics_get_gravity(void); +f32 baphysics_get_target_horizontal_velocity(void); +f32 baphysics_get_target_vertical_velocity(void); +f32 baphysics_get_target_yaw(void); +f32 baphysics_get_vertical_velocity(void); +f32 baphysics_get_horizontal_velocity(void); +f32 baphysics_get_horizontal_velocity_percentage(void); +f32 climbGetRadius(void); f32 func_8029B3B0(f32 arg0); f32 func_8029B56C(f32 arg0, f32 arg1, f32 arg2, f32 arg3); f32 func_8029B9C0(void); @@ -294,7 +301,7 @@ f32 player_getYaw(void); // Only functions that return pointers or have no conflicting local externs. NodeProp *cube_findNodePropByActorId(Cube *cube, enum actor_e actor_id); -// --- core2/nc/cameranodelist.c --- +// --- core2/camera/cameranodelist.c --- PivotCameraNode *ncCameraNodeList_getPivotCameraNode(int camera_node_index); StaticCameraNode *ncCameraNodeList_getStaticCameraNode(int camera_node_index); ZoomCameraNode *ncCameraNodeList_getZoomCameraNode(int camera_node_index); @@ -302,61 +309,34 @@ RandomCameraNode *ncCameraNodeList_getRandomCameraNode(int camera_node_index); // MISC POINTER-RETURNING + OS + GBI PROTOTYPES -s16 *picturebox_getColorBuffer(void); +s16 *func_8030C704(void); // COMMONLY MISSING PROTOTYPES -// --- core2/jiggyscore.c --- +// --- core2/fx/score_jiggy.c --- u32 jiggyscore_isCollected(enum jiggy_e jiggy_id); int jiggyscore_isSpawned(enum jiggy_e jiggy_id); -// --- core2/honeycombscore.c --- +// --- core2/fx/score_honeycomb.c --- bool honeycombscore_get(enum honeycomb_e indx); -// --- core2/map/mapspecificflags.c --- +// --- core2/map/specificflags.c --- s32 mapSpecificFlags_get(s32 i); void mapSpecificFlags_set(s32, s32); -void mapSpecificFlags_setEx(s32 i, s32 val, s32 triggerEvent); -// --- core2/level/levelspecificflags.c --- +// --- core2/level/specificflags.c --- s32 levelSpecificFlags_get(s32 i); void levelSpecificFlags_set(s32, s32); -void levelSpecificFlags_setEx(s32 index, s32 val, s32 triggerEvent); -void levelSpecificFlags_getSizeAndPtr(s32 *size, u8 **addr); // --- core2/gameloop.c --- s32 getGameMode(void); void transitionToMap(enum map_e map, s32 exit, s32 transition); -// --- core2/gamestate.c --- +// --- core2/gamestate.c (item system) --- s32 item_empty(enum item_e item); void item_set(s32 item, s32 val); -void item_setEx(s32 item, s32 val, s32 triggerEvent); // --- core2/game_complete.c --- -enum AnchorFlagSpace { - ANCHOR_FLAGSPACE_FILE_PROGRESS = 0, - ANCHOR_FLAGSPACE_VOLATILE = 1, - ANCHOR_FLAGSPACE_LEVEL_SPECIFIC = 2, - ANCHOR_FLAGSPACE_MAP_SPECIFIC = 3, - ANCHOR_FLAGSPACE_RANDO_INF = 4, -}; -enum AnchorCollectibleSpace { - ANCHOR_COLLECTIBLE_JIGGY = 0, - ANCHOR_COLLECTIBLE_HONEYCOMB = 1, - ANCHOR_COLLECTIBLE_MUMBO = 2, - ANCHOR_COLLECTIBLE_NOTE = 3, - ANCHOR_COLLECTIBLE_JINJO = 4, - ANCHOR_COLLECTIBLE_WORM = 5, - ANCHOR_COLLECTIBLE_ACORN = 6, - ANCHOR_COLLECTIBLE_PRESENT_BLUE = 7, - ANCHOR_COLLECTIBLE_PRESENT_GREEN = 8, - ANCHOR_COLLECTIBLE_PRESENT_RED = 9, - ANCHOR_COLLECTIBLE_GOLD = 10, - ANCHOR_COLLECTIBLE_ORANGE = 11, -}; - -// --- core2/flags_bitfield.c --- bool fileProgressFlag_get(enum file_progress_e index); s32 fileProgressFlag_getN(enum file_progress_e offset, s32 numBits); s32 volatileFlag_get(enum volatile_flags_e index); @@ -365,11 +345,9 @@ s32 volatileFlag_getN(enum volatile_flags_e index, s32 numBits); void fileProgressFlag_setN(enum file_progress_e, s32, s32); void volatileFlag_set(enum volatile_flags_e index, s32 set); void volatileFlag_setN(enum volatile_flags_e startIndex, s32 set, s32 length); -void fileProgressFlag_setEx(enum file_progress_e index, s32 set, s32 triggerEvent); -void volatileFlag_setEx(enum volatile_flags_e index, s32 set, s32 triggerEvent); -// --- core2/dialog/progressDialog.c --- -void progressDialog_setAndTriggerDialog_0(enum volatile_flags_e arg0); +// --- core2/dialog/progress_dialogs.c --- +void volatileFlag_setAndTriggerDialog_0(enum volatile_flags_e arg0); // --- core1/init.c --- s32 globalTimer_getTime(void); @@ -382,14 +360,14 @@ void subaddie_set_ideal_yaw(Actor *self, int arg1); bool subaddie_playerIsWithinSphere(Actor *self, s32 dist); Actor *actor_spawnWithYaw_s32(enum actor_e id, s32 (*pos)[3], s32 rot); -// --- core2/gccube.c --- +// --- core2/actor_cubebounds.c --- bool nodeProp_findPositionFromActorId(enum actor_e actor_id, f32 *arg1); // --- core2/ba/ba_lookdir.c --- enum bsgroup_e player_movementGroup(void); enum hitbox_e player_getActiveHitbox(ActorMarker *marker); bool player_isDead(void); -bool player_isStableWithExtraSteps(void); +bool func_8028F20C(void); s32 func_8028F66C(enum bs_interrupt_e arg0); void func_8028F8F8(s32 arg0, bool arg1); void func_8028F918(s32 arg0); @@ -417,8 +395,7 @@ void func_8030E0FC(u8, f32, f32, f32); void sfxSource_func_8030E2C4(u8); void sfxSource_func_8030E2C4(u8 indx); void func_8030E4E4(enum sfx_e uid); -void gcsfx_playAtSampleRate(enum sfx_e uid, s32 sample_rate); -void gcsfx_play(enum sfx_e uid); +void gcsfx_playAtSampleRate(enum sfx_e uid); void func_8030E560(enum sfx_e uid, s32 arg1); void func_8030E58C(enum sfx_e uid, f32 arg1); void func_8030E5F4(enum sfx_e uid, f32 arg1); @@ -444,7 +421,7 @@ void sfxsource_setSfxId(u8 indx, enum sfx_e uid); void sfxsource_set_fade_distances(u8, f32, f32); void sfxsource_set_position(u8, f32[3]); -// --- core2/nc/camera_motor1.c --- +// --- core2/camera/camera_motor1.c --- void gcStaticCamera_activate(s32 arg0); bool func_802BB270(void); @@ -453,13 +430,13 @@ void func_803114D0(void); int gcdialog_hasCurrentTextId(void); bool gcdialog_showDialog(s32 text_id, s32 arg1, f32 *pos, ActorMarker *marker, void(*callback)(ActorMarker *, enum asset_e, s32), void(*arg5)(ActorMarker *, enum asset_e, s32)); -// --- core2/map/cutscene_skip.c --- +// --- core2/cutscene/lair.c --- void func_8031CD20(NodeProp *arg0, s32 arg1, s32 arg2); // --- core2/collision/polydetect.c --- void func_80340690(Struct83s *self); -// --- core2/gccube.c --- +// --- core2/actor_cubebounds.c --- bool func_803077FC(f32 arg0[3], s32 *arg1, s32 *arg2, s32 arg3, u32 arg4); bool func_80305C30(s32 arg0); bool func_80308F54(s32 cube_index); @@ -477,54 +454,54 @@ bool func_80331158(ActorMarker *arg0, f32 *arg1, f32 *arg2); // --- core2/ba/ba_lookdir.c --- bool func_8028F280(void); -// --- core2/ba/anim.c --- +// --- core2/ba/ba_anim.c --- bool baanim_isStopped(void); bool baanim_isAnimID(enum asset_e anim_id); AnimCtrl *baanim_getAnimCtrlPtr(void); bool baanim_isAt(f32); void baanim_playForDuration_loopSmooth(enum asset_e anim_id, f32 duration); -void baanim_playForDuration_loopSmoothStartingAt(enum asset_e anim_id, f32, f32); -void baanim_playForDuration_onceSmooth(enum asset_e anim_id, f32 duration); -void baanim_playForDuration_once(enum asset_e, f32); -void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 arg2); +void baanim_playForDuration_loopStartingAt(enum asset_e anim_id, f32, f32); +void baanim_playForDuration_once(enum asset_e anim_id, f32 duration); +void baanim_playForDuration_onceSmooth(enum asset_e, f32); +void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f32 arg2); void baanim_scaleDuration(f32); void baanim_setDurationRange(f32, f32); void baanim_setEnd(f32); void baanim_setEndAndDuration(f32, f32); void baanim_setVelocityMapRanges(f32, f32, f32, f32); -// --- core2/ba/hazards.c --- +// --- core2/ba/ba_groundsurface.c --- bool isOnFloor(void); bool isPlayerInHazard(void); bool canTakeGroundDamage(void); -// --- core2/ba/modelappendages.c --- -bool modelAppendages_hideTurboTrainers(void); -f32 modelAppendages_showBanjosLeftEye(void); -f32 modelAppendages_showBanjosRightEye(void); -void modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(bool, f32); -void modelAppendages_setBanjosLeftEyeVisibility(f32); -void modelAppendages_setBanjosRightEyeVisibility(f32); -bool modelAppendages_showKazooiesUpperHalf(void); -bool modelAppendages_showKazooiesAss(void); -bool modelAppendages_showKazooiesFeetAndShoes(void); -bool modelAppendages_hideWadingBoots(void); - -// --- core2/ba/carriedobj.c --- +// --- core2/ba/ba_animstate.c --- +bool func_8029DFE0(void); +f32 func_8029DFC8(void); +f32 func_8029DFD4(void); +void func_8029E090(bool, f32); +void func_8029E0C4(f32); +void func_8029E0D0(f32); +bool func_8029DFBC(void); +bool func_8029DFA4(void); +bool func_8029DFB0(void); +bool func_8029DFEC(void); + +// --- core2/ba/ba_carriedobj.c --- bool player_setCarryObjectPose(enum actor_e actor_id, Actor **arg1); -// --- core2/nc/camera_nodemanager.c --- +// --- core2/camera/camera_nodemanager.c --- bool func_802BB720(s32 arg0, f32 arg1[3], f32 arg2[3], s32 *arg3); bool func_802BB884(f32 arg0[3], f32 *arg1); bool func_802BC428(void); -// --- core2/nc/camera_fog.c --- +// --- core2/camera/camera_fog.c --- bool func_802BEF64(void); -// --- core2/nc/camera_focus.c --- +// --- core2/camera/camera_focus.c --- bool func_802BAC1C(void); -// --- core2/nc/dynamicCamera.c --- +// --- core2/camera/dynamicCamera.c --- bool func_802BC640(f32 arg0[3], f32 arg1[3], f32 arg2, s32 arg3); bool func_802BCE0C(f32 arg0[3], f32 arg1[3]); f32 func_802BD8D4(void); @@ -532,21 +509,21 @@ void func_802BD8A4(f32, f32, f32); void func_802BE230(f32, f32); void func_802BE244(f32, f32); -// --- core2/nc/dynamicCam12.c --- +// --- core2/camera/dynamicCam12.c --- bool __is_flying_in_FP(void); bool func_802C189C(void); -// --- core2/nc/dynamicCam13.c --- +// --- core2/camera/dynamicCam13.c --- bool func_802C0640(void); -// --- core2/nc/dynamicCamA.c --- +// --- core2/camera/dynamicCamA.c --- bool ncDynamicCamA_func_802C1EE0(void); bool ncDynamicCamA_func_802C1DB0(f32); -// --- core2/nc/1p.c --- -bool __ncba1p_fullyZoomedIn(void); +// --- core2/camera/firstpersoncamera.c --- +bool __ncFirstPersonCamera_fullyZoomedIn(void); -// --- core2/collision/dispatch.c --- +// --- core2/collision/funcs.c --- void func_80320B24(void *arg0, void *arg1, void *arg2); void func_80320B44(void *arg0, void *arg1, void *arg2, void *arg3); @@ -557,32 +534,37 @@ f32 func_80294438(void); f32 floor_getCurrentFloorYPosition(void); void func_80293D48(f32, f32); +// --- core2/spline_bezier.c --- + +// --- core2/vtx/list.c --- + // --- core2/spline_pathfollow.c --- void func_80343DEC(Actor *self); -// --- core2/spawnqueue.c --- +// --- core2/model/render.c --- + +// --- core2/spawn_queue.c --- +void __spawnQueue_add_0(void (*arg0)(void)); +void __spawnQueue_add_2(void (*arg0)(void), uintptr_t arg1, uintptr_t arg2); Actor *spawnQueue_actor_f32(enum actor_e actor_id, uintptr_t x, uintptr_t y, uintptr_t z); -Actor *spawnQueue_actor_s32(uintptr_t actor_id, uintptr_t x, uintptr_t y, uintptr_t z); -Actor *spawnQueue_actor_s16(uintptr_t actor_id, uintptr_t x, uintptr_t y, uintptr_t z); -void __spawnQueue_add_0(GenFunction_0); void __spawnQueue_add_1(GenFunction_1, uintptr_t); -void __spawnQueue_add_2(GenFunction_2, uintptr_t, uintptr_t); -void __spawnQueue_add_3(GenFunction_3, uintptr_t, uintptr_t, uintptr_t); -void __spawnQueue_add_4(GenFunction_4, uintptr_t, uintptr_t, uintptr_t, uintptr_t); -void __spawnQueue_add_5(GenFunction_5, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); #define SPAWNQUEUE_ADD_1(method, arg0) __spawnQueue_add_1((GenFunction_1) (method), reinterpret_cast(uintptr_t, (arg0))) +void __spawnQueue_add_4(GenFunction_4, uintptr_t, uintptr_t, uintptr_t, uintptr_t); -// --- core2/fx/commonParticle.c --- +// --- core2/sprite/displaydata.c --- void commonParticle_add(ActorMarker *arg0, s32 arg1, FuncUnk40 arg2); int commonParticle_new(enum common_particle_e particle_id, int arg1); // --- core2/particle/particle.c --- void particleEmitter_setModel(ParticleEmitter *self, enum asset_e model_id); +void particleEmitter_setSfx(ParticleEmitter *self, enum sfx_e sfx_id, s32 arg2); +void particleEmitter_setAlpha(ParticleEmitter *self, s32 arg1); void particleEmitter_setVelocityAccelerationAndPositionRanges(ParticleEmitter *self, ParticleSettingsVelocityAccelerationPosition *settings); void func_802EFC28(ParticleEmitter *self, ParticleSettingsScaleAndLifetimeDrawModeEmitCount *settings); ParticleEmitter *partEmitMgr_defragEmitter(ParticleEmitter *); ParticleEmitter *partEmitMgr_newEmitter(u32); ParticleEmitter *particleEmitter_new(u32 capacity); +void particleEmitter_func_802EFA20(ParticleEmitter *, f32, f32); void func_802EFF50(ParticleEmitter *, f32); void particleEmitter_emitInVolume(ParticleEmitter *, f32[3], f32[3], s32); void particleEmitter_emitN(ParticleEmitter *, int); @@ -610,7 +592,7 @@ void particleEmitter_update(ParticleEmitter *self); void particleEmitter_setVelocityAndAccelerationRanges(ParticleEmitter *, ParticleSettingsVelocityAcceleration *); // --- core2/quiz/game.c --- -void code_4C020_setHourglassTimer(s32 seconds); +void func_802D68F0(s32 seconds); void func_802D4A9C(Actor *self, s32 arg1); void func_802D4AC0(Actor *self, s32 arg1, enum file_progress_e arg2); void func_802D6264(f32, enum map_e, s32, s32, s32, enum file_progress_e); @@ -629,32 +611,32 @@ void coMusicPlayer_playMusic(enum comusic_e, s32); // --- core1/stopnswop.c --- bool sns_get_item_state(enum StopNSwop_Item item, s32 set); -// --- FP/ma/slalom.c --- +// --- FP/mapstate/slalom.c --- bool maSlalom_isActive(void); // --- FP/ch/boggy2.c --- bool func_8038A1A0(ActorMarker *marker); +// code3B10_checkGVChecksums omitted: decomp defines as (void) but callers pass Actor* + // --- CC/model_renderstate.c --- -void code13C0_checkCCChecksums(void); void CC_func_80387D4C(void); // OS function prototypes extern uintptr_t osVirtualToPhysical(void *addr); extern void *osPhysicalToVirtual(uintptr_t addr); -// GBI function prototypes +// GBI function prototypes (implementations in src/port/stub.c) void gSPSegment(void* value, int segNum, uintptr_t target); void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target); void gSPDisplayList(Gfx* pkt, Gfx* dl); void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset); void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0); -void gSPVertexSeg(Gfx* pkt, u32 seg, uintptr_t off, int n, int v0); void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr); int ResourceMgr_OTRSigCheck(char* imgData); -// --- BGS/bgsspawnqueue.c --- -void bgs_updateSpawnableActors(void); +// --- BGS/actor_spawninit.c --- +void BGS_func_8038F1E0(void); // --- BGS/ch/croctus.c --- void BGS_func_803885DC(void); @@ -666,14 +648,14 @@ void func_8038CEA0(void); void func_8038CEB8(void); // --- BGS/ch/mrvile.c --- -bool chMrVile_isInitialIdle(ActorMarker *marker); -bool chMrVile_playerWithinRange(ActorMarker *marker); -void chMrVile_setStateRunFromPlayer(ActorMarker *marker); -void chMrVile_setInitialIdleStill(ActorMarker *arg0); -void chMrVile_setStateAttackPlayer(ActorMarker *marker); -void chMrVile_setStateTalkToPlayer(ActorMarker *marker); -void chMrVile_setStatePlayMinigame(ActorMarker *marker); -void chMrVile_setStateIdleWalking(ActorMarker *marker); +bool BGS_func_8038C338(ActorMarker *marker); +bool func_8038C2A8(ActorMarker *marker); +void BGS_func_8038C434(ActorMarker *marker); +void BGS_func_8038C460(ActorMarker *arg0); +void func_8038C384(ActorMarker *marker); +void func_8038C3B0(ActorMarker *marker); +void func_8038C3DC(ActorMarker *marker); +void func_8038C408(ActorMarker *marker); // --- BGS/ch/mudhut.c --- void chMudHut_checkBGSChecksums(void); @@ -682,71 +664,66 @@ void chMudHut_checkBGSChecksums(void); void func_8038F51C(Actor *self); // --- BGS/ch/tiptup.c --- +s32 func_80388E70(ActorMarker *self); void chTiptup_choirHitReaction(ActorMarker *self, s32 arg1); -s32 chTiptup_getUnkB(ActorMarker *self); void func_80388FFC(ActorMarker *self, s32 *arg1, f32* arg2); // --- BGS/ch/yumblie.c --- bool chyumblie_is_edible(ActorMarker * arg0); bool func_8038B684(ActorMarker * arg0); -// --- BGS/mrvileminigame.c --- -bool chMrVileMinigame_mrVileConsumePiece(ActorMarker *marker, f32 position[3]); -s32 chMrVileMinigame_getPieceCount(ActorMarker *marker); -s32 chMrVileMinigame_getScoreDifference(ActorMarker *marker); -s32 chMrVileMinigame_getDialogIndex(ActorMarker *marker); -void chMrVileMinigame_newPiece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type); +// --- BGS/minigame_vile.c --- +bool chvilegame_cpu_consume_piece(ActorMarker *marker, f32 position[3]); +s32 chvilegame_get_piece_count(ActorMarker *marker); +s32 chvilegame_get_score_difference(ActorMarker *marker); +s32 func_8038A9E0(ActorMarker *marker); +void chvilegame_new_piece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type); void chvilegame_remove_piece(ActorMarker *game_marker, ActorMarker *piece_marker); -// --- CC/ccspawnqueue.c --- +// --- CC/actor_spawninit.c --- void CC_func_80387DA0(void); // --- CC/ch/clankertoothext.c --- void CC_func_803870E0(void); void func_803870EC(s32 arg0); -// --- CC/ma/clankerrings.c --- -void maClankerRings_release(void); -void maClankerRings_init(void); -void maClankerRings_update(void); +// --- CC/minigame_rings.c --- +void func_803880D4(void); +void func_80388104(void); +void func_8038817C(void); -// --- CC/ma/clanker.c --- +// --- CC/platform_physics.c --- int CC_func_80388CA0(void); -void maClanker_raiseClankerCutscene(void); -void maClanker_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); +void CC_func_8038868C(void); +void CC_func_80388760(Gfx **gfx, Mtx **mtx, Vtx **vtx); void CC_func_80388F4C(void); void func_80388B4C(f32 arg0[3]); void func_80388B78(f32 arg0[3], f32 arg1[3]); void func_80388BBC(f32 arg0[3], f32 arg1[3]); void func_80388CB4(void); void func_80388D54(void); -void maClanker_playScrewNoise(s32 arg0); -void maClanker_defrag(void); -void maClanker_release(void); -void maClanker_init(void); -void maClanker_update(void); -s32 maClankerRings_isMinigameActive(void); -void maClankerRings_passRing(s32); - -// --- CCW/ccwspawnqueue.c --- +void func_80388ED4(s32 arg0); +void func_803894A0(void); + +// --- CCW/actor_spawninit.c --- void CCW_func_8038DB6C(void); -// --- CCW/nabnut_winter.c --- -void chAutumnOutsideNabnut_getPosition(f32 dst[3]); +// --- CCW/ch/nabnut_winter.c --- +void func_8038BC50(f32 dst[3]); -// --- CCW/eyrie_baby.c --- +// --- CCW/ch/eyrie_baby.c --- void func_80389BD8(f32 dst[3]); -// --- CCW/ch/beanstalk.c --- -bool chCCWBeanstalk_hasSpawned(); -void chCCWBeanstalk_growBeanstalk(); +// --- CCW/flower.c --- +bool func_80388438(); +void func_803883F4(); -// --- CCW/ch/zubbahoneylump.c --- -void chZubbaFight_zubbaKilled(ActorMarker *marker); -void chZubbaFight_zubbaDisappear(ActorMarker *marker); -void chZubbaFight_zubbaScore(ActorMarker *marker, s32 *score, s32 *total); +// --- CCW/minigame_zubba.c --- +void func_803867C8(ActorMarker *marker); +void func_80386814(ActorMarker *marker); +void func_80386840(ActorMarker *marker, s32 *score, s32 *total); -// --- FP/fpspawnqueue.c --- +// --- FP/actor_spawninit.c --- void FP_func_80391324(void); // --- FP/ch/boggy2.c --- @@ -758,7 +735,7 @@ void chTwinkly_decideShatterColor(f32 position[3], enum marker_e marker_id); // --- FP/ch/twinklybox.c --- bool preventSnowmanAttack(ActorMarker *marker); -// --- FP/ma/slalom.c --- +// --- FP/mapstate/slalom.c --- bool maSlolam_WithinRadiusOfBoggy(f32 position[3], s32 radius); void maSlalom_end(); void maSlalom_init(void); @@ -771,25 +748,25 @@ void maSlalom_start(void); void maSlalom_unlinkBoggy(void); void maSlalom_update(void); -// --- FP/ma/snowbutton.c --- +// --- FP/mapstate/snowbutton.c --- void maSnowButton_decRemaining(void); void maSnowButton_end(void); void maSnowButton_init(void); void maSnowButton_update(void); -// --- FP/ma/snowy.c --- +// --- FP/mapstate/snowy.c --- void maSnowy_decRemaining(void); void maSnowy_end(void); void maSnowy_incTotal(void); void maSnowy_init(void); void maSnowy_update(void); -// --- FP/wozza_fire.c --- +// --- FP/ch/wozza_fire.c --- void func_803918C0(void); void func_8039195C(void); void func_80391994(void); -// --- GV/gvspawnqueue.c --- +// --- GV/actor_spawninit.c --- s32 code7FF0_getMagicCarpetState(Actor *arg0, s32 arg1); void GV_func_8038F154(void); @@ -809,10 +786,10 @@ bool chGobiRock_isDestroyed(void); // --- GV/ch/grabba.c --- s32 GV_func_8038C5BC(void); -// --- GV/handshadow.c --- +// --- GV/ch/handshadow.c --- void func_8038C748(void); -// --- GV/jinxy_head.c --- +// --- GV/ch/jinxy_head.c --- int func_8038E344(ActorMarker *this_marker); void func_8038E2FC(ActorMarker *this_marker); @@ -832,8 +809,8 @@ void gv_matchingGame_init(void); void gv_matchingGame_reset(void); void gv_matchingGame_update(void); -// --- GV/sandybutteggtoll.c --- -bool func_8038D388(void); +// --- GV/pyramid_trigger.c --- +int func_8038D388(void); // --- GV/water_pyramidactivate.c --- void func_803900F8(void); @@ -850,7 +827,7 @@ void gv_waterCtrl_end(void); void gv_waterCtrl_init(void); void gv_waterCtrl_update(void); -// --- MM/mmspawnqueue.c --- +// --- MM/actor_spawninit.c --- void MM_func_803888B0(void); // --- MM/ch/hut.c --- @@ -866,13 +843,13 @@ void func_803892A8(ActorMarker **ptr); // --- MM/ch/jujuhitbox.c --- void chjujuhitbox_setJuju(Actor *self, s32 slave_id, Actor *slavePtr); -// --- MMM/mmmspawnqueue.c --- +// --- MMM/actor_spawninit.c --- void MMM_func_803890E0(void); // --- MMM/organ_tiles.c --- void func_8038B5D8(Struct5Fs *arg0, Struct68s *arg1, s32 arg2, s32 arg3); -// --- MMM/ch/cemetarypot.c --- +// --- MMM/ch/flowerpot.c --- bool chFlowerpot_eggCollision(ActorMarker *marker); void chFlowerpot_reset(); @@ -914,7 +891,7 @@ void func_80389544(void); void func_803895B0(s32 arg0); void func_8038966C(void); -// --- RBB/rbbspawnqueue.c --- +// --- RBB/actor_spawninit.c --- void RBB_func_80386C48(void); // --- RBB/ch/eggtoll1.c --- @@ -924,8 +901,8 @@ void func_8038685C(ActorMarker *marker); s32 chWhistleCtrl_newEvent(Actor *self, s32 whistle_id, Actor *other); // --- RBB/miniboombox_container.c --- -void chBoomBoxMinigameCtrl_countInc(void); -void chBoomBoxMinigameCtrl_countDec(void); +void func_8038FB54(void); +void func_8038FB6C(void); // --- RBB/propellorctrl.c --- void rbb_propellorCtrl_reset(void); @@ -935,7 +912,7 @@ void rbb_propellorCtrl_update(void); // --- SM/quarrie_honeycomb.c --- bool codeBF0_shouldSpawnQuarrieHoneyComb(ActorMarker *marker); -// --- SM/smspawnqueue.c --- +// --- SM/crc.c --- void SM_resetSpawnableActors(); void codeF0_breakAbilitiesIfChecksumsFail(); @@ -954,7 +931,7 @@ void chTreasurehunt_resetProgress(void); // --- TTC/crc.c --- void code3040_checkTTCChecksums(void); -// --- TTC/ma/castle.c --- +// --- TTC/castle.c --- bool maCastle_hasBanjoKazooieCodeBeenEntered(void); bool maCastle_isSecretCheatCodeRelatedValueEqualToScrambledAddressValue(); void maCastle_init(void); @@ -976,10 +953,10 @@ void musicInstruments_init(void); // --- core1/musicplayer.c --- int func_8025AEEC(void); -s32 coMusicPlayer_getTrackCount(void); +s32 comusic_active_track_count(void); s32 func_8025ADD4(enum comusic_e id); -void coMusicPlayer_free(void); -void coMusicPlayer_init(void); +void comusicPlayer_free(void); +void comusicPlayer_init(void); void comusic_defrag(void); void func_8025A23C(s32 arg0); void func_8025A2B0(void); @@ -1003,7 +980,7 @@ void func_80244814(void *arg0); void func_80244978(intptr_t arg0, s16 type, s32 arg2); void func_80244A98(s32 arg0); -// --- core1/bamotor.c --- +// --- core1/io/ba_motor.c --- void baMotor_80250C08(void); void baMotor_80250FC0(void); void baMotor_init(void); @@ -1018,14 +995,18 @@ void func_802451A4(f32 arg0[3], f32 arg1[3], f32 arg2[3], f32 arg3[3], f32 arg4[ // --- core1/debugtext.c --- s32 gcdebugText_isThreadLocked(void); -void gcdebugText_showLargeValue(s32 arg0, s32 arg1); +void func_80247F24(s32 arg0, s32 arg1); void func_80247F9C(s32 arg0); void gcdebugText_pauseThread(void); -// --- core1/gu_perspective.c --- +// --- core1/defragmanager.c --- +void defragManager_free(void); +void defragManager_init(void); + +// --- core1/math/mlmtx.c --- void _guMtxF2L(float mf[4][4], Mtx *m); -// --- boot/inflate.c --- +// --- core1/inflate.c --- int bk_inflate(void); // --- core1/initthread.c --- @@ -1047,6 +1028,9 @@ void func_80255A04(void); void func_80255A14(void); void func_80255ACC(void); +// --- core1/ml.c --- +void func_802596AC(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]); + // --- core1/mlmtx.c --- void func_802515D4(f32 arg0[3][3]); @@ -1083,7 +1067,6 @@ void ability_setAllLearned(s32 val); void ability_setAllUsed(s32 val); void ability_setHasUsed(enum ability_e move); void ability_setLearned(s32 move, s32 val); -void ability_setLearnedEx(s32 move, s32 val, s32 triggerEvent); void ability_use(s32 arg0); // --- core2/actor_array.c --- @@ -1117,8 +1100,6 @@ void func_803268B4(void); void func_80326C24(s32 arg0); void func_803283BC(void); void func_803283D4(void); -void port_actorDespawn_beginDefer(void); -void port_actorDespawn_endDefer(void); void func_80328CA8(Actor *self, s32 angle); void func_803297FC(Actor *arg0, f32 *o1, f32 *o2); s32 func_80329904(ActorMarker *arg0, s32 arg1, f32 *arg2); @@ -1138,7 +1119,7 @@ void func_8032BC18(Actor *self); void func_8032BC60(Actor *self, s32 arg1, f32 arg2[3]); void subaddie_set_state_looped(Actor * self, u32 arg1); -// --- core2/gccube.c --- +// --- core2/actor_cubebounds.c --- bool func_80305248(f32 arg0[3], s32 arg1, f32 *arg2); bool func_8030526C(f32 arg0[3], s32 arg1, f32 *arg2); bool func_80305290(bool (* arg0)(NodeProp *), bool (* arg1)(Prop *)); @@ -1155,7 +1136,7 @@ s32 func_80307164(s32 arg0[3]); s32 func_80307258(f32 arg0[3], s32 arg1, s32 arg2); s32 nodeprop_getRadius(NodeProp *arg0); s32 nodeprop_getScale(NodeProp *nodeProp); -u32 nodeProp_getYaw(NodeProp *nodeProp); +u32 nodeprop_getYaw(NodeProp *nodeProp); void code7AF80_freeTotalCounts(void); void cubeList_defrag(); void cubeList_free(); @@ -1180,9 +1161,9 @@ void spawnableActorList_new(void); // --- core2/actor_cubepropsystem.c --- s32 actor_getAnimatedTexturesCacheId(Actor *actor); -s32 codeA5BC0_getNodePropCategory(NodeProp *arg0); -s32 codeA5BC0_getNodePropActorId(NodeProp *arg0); -s32 codeA5BC0_getNodePropMarkerId(NodeProp *arg0); +s32 codeA5BC0_getNodePropBit6(NodeProp *arg0); +s32 codeA5BC0_getNodePropUnk8(NodeProp *arg0); +s32 codeA5BC0_getNodePropUnkA(NodeProp *arg0); s32 codeA5BC0_getNodePropUnkC(NodeProp *arg0); s32 func_8032E49C(Cube *cube, enum actor_e *actor_id_list, NodeProp **node_list, s32 node_list_capacity); s32 func_8032E5A8(Cube *cube, s32 arg1, f32 (*arg2)[3], s32 capacity); @@ -1196,7 +1177,7 @@ void cube_sortAbsolute(Cube *cube); void cube_sortRelative(Cube *cube); void func_8032D3A8(void); void func_8032D3D8(Gfx **gdl, Mtx **mptr, Vtx **vptr); -void core2_A5BC0_drawScreenOverlayMarkers(Gfx **gdl, Mtx **mptr, Vtx **vptr); +void func_8032D474(Gfx **gdl, Mtx **mptr, Vtx **vptr); void func_8032E070(void); void func_8032EE2C(s32 arg0[3], s32 arg1, s32 arg2); void func_8032EE80(Cube *cube); @@ -1234,7 +1215,7 @@ void func_80296CC0(f32 arg0[3]); // --- core2/scorequeue/queue_timers.c --- bool func_802FCD98(struct8s *arg0); -// --- SM/ch/ambient_fish.c --- +// --- core2/ambient_fish.c --- void func_803500D8(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_803500E8(void); void func_80350174(void); @@ -1263,7 +1244,7 @@ void anim_resetSmooth(Animation *self); void anim_setIndex(Animation *self, enum asset_e arg1); void anim_update(Animation *self); -// --- core2/anim/animcache.c --- +// --- core2/anim/anim_cache.c --- bool animCache_inUse(s16 index); s16 animCache_getNew(void); void animCache_defrag(void); @@ -1279,7 +1260,14 @@ void func_80361E10(Actor *self); void func_80361E9C(Actor *self); void func_80361EE0(Actor *self); -// --- core2/anim/animtexturecache.c --- +// --- core2/anim/anim_texturecache.c --- +bool AnimTextureListCache_tryGetTextureOffset(s32 list_index, s32 texture_index, s32 *current_frame); +s32 AnimTextureListCache_newList(void); +void AnimTextureListCache_setAnimTextureList(s32 arg0, BKAnimTextureList *bk_anim_texture_list); +void AnimTextureListCache_free(void); +void AnimTextureListCache_freeList(s32 arg0); +void AnimTextureListCache_init(void); +void AnimTextureListCache_update(void); // --- core2/anim/bonetransformlist.c --- void boneTransformList_getBoneScale(BoneTransformList *self, s32 bone_id, f32 scale[3]); @@ -1289,7 +1277,7 @@ void func_8033A6B0(BoneTransformList *self, s32 bone_id, f32 arg2[3]); void func_8033A8F0(BoneTransformList *self, s32 bone_id, f32 arg2[4]); void func_8033A968(BoneTransformList *self, s32 bone_id, f32 arg2[3]); -// --- core2/anim/anseq.c --- +// --- core2/anim_sequence.c --- void anSeq_free(void **ppAnSeq); void anSeq_setActivationFrameDelay(void **ppAnSeq, s32 arg1); void anSeq_update(void **ppAnSeq, AnimCtrl *pAnCtl); @@ -1304,15 +1292,13 @@ void func_803353F4(intptr_t arg0, s32 arg1); void func_80335418(intptr_t arg0, s32 arg1); void sfxInstruments_init(void); -// --- core2/ba/anim.c --- +// --- core2/ba/ba_anim.c --- void baAnim_defrag(void); void baAnim_free(void); void baAnim_init(void); void baAnim_update(void); void baanim_80289F30(void); enum baanim_update_type_e baanim_getUpdateType(void); -void baanim_applyBottlesBonusMask(uintptr_t arg0, s32 mask); -s32 baanim_getActiveBottlesBonusMask(void); void baanim_setModifyMethod(void (*arg0)(uintptr_t, uintptr_t)); void baanim_setUpdateType(enum baanim_update_type_e arg0); @@ -1321,44 +1307,50 @@ void animBinCache_free(void); void animBinCache_init(void); void animBinCache_update(void); -// --- core2/ba/modelappendages.c --- -void modelAppendages_loadAppendage(void); -void modelAppendages_reset(void); -void modelAppendages_setKazooiesAssVisibility(bool); -void modelAppendages_setKazooiesFeetAndShoesVisibility(bool); -void modelAppendages_setKazooiesUpperHalfVisibility(bool); -void modelAppendages_setTurboTrainersVisibility(bool); -void modelAppendages_setSledVisibility(bool); -void modelAppendages_setWadingBootsVisibility(bool); -void modelAppendages_kazooiesUpperHalfVisibilityTimer(void); - -// --- core2/ba/babounds.c --- +// --- core2/ba/ba_animstate.c --- +void func_8029DD6C(void); +void func_8029DFF8(void); +void func_8029E058(bool); +void func_8029E064(bool); +void func_8029E070(bool); +void func_8029E0DC(bool); +void func_8029E0E8(bool); +void func_8029E0F4(bool); +void func_8029E100(void); + +// --- core2/ba/ba_bounds.c --- void babounds_init(void); void babounds_update(void); -// --- core2/ba/babuzz.c --- +// --- core2/ba/ba_buzz.c --- void babuzz_release(void); void babuzz_reset(void); -// --- core2/ba/carriedobj.c --- +// --- core2/ba/ba_carriedobj.c --- void bacarriedobj_dec(enum actor_e actor_id); void bacarriedobj_displayOnHud(enum actor_e actor_id); void bacarriedobj_inc(enum actor_e actor_id); void bacarriedobj_spawn(enum actor_e actor_id); -void bacarriedobj_incWithExtraSteps(enum actor_e actor_id); -void bacarriedobj_decWithExtraSteps(enum actor_e actor_id); -void bacarriedobj_displayOnHudWithExtraSteps(enum actor_e actor_id); void func_8028DEEC(enum actor_e actor_id, Actor *actor); -// --- core2/ba/drone.c --- +// --- core2/ba/ba_carry.c --- +void bacarry_end(void); +void bacarry_init(void); +void bacarry_reset_marker(void); +void bacarry_set_marker(ActorMarker *arg0); +void bacarry_update(void); + +// --- core2/ba/ba_scripted.c --- enum bs_e badrone_802926E8(void); +enum bs_e badrone_enter(void); enum bs_e badrone_look(void); enum bs_e badrone_transform(void); enum bs_e badrone_vanish(void); +void badrone_get_position_and_duration(f32 position[3], f32 *duration); void badrone_goto_end(void); void badrone_init(void); -// --- core2/ba/iFrame.c --- +// --- core2/ba/ba_eyeblink.c --- s32 baiFrame_getState(void); void baiFrame_reset(void); void baiFrame_start(void); @@ -1377,13 +1369,13 @@ void func_802C7478(Actor *actor); void func_802C75A0(Actor *actor, s32 arg1); void func_802C79C4(void); -// --- core2/ba/baeyes.c --- +// --- core2/ba/ba_eyes.c --- void baeyes_close(void); void baeyes_open(void); void baeyes_reset(void); void baeyes_update(void); -// --- core2/ba/falldamage.c --- +// --- core2/ba/ba_falldamage.c --- s32 bafalldamage_get_damage(s32 *damage); s32 bafalldamage_get_state(void); void bafalldamage_init(void); @@ -1396,7 +1388,7 @@ void func_80350BC8(void); void func_80350BFC(void); void func_80350CA4(void); -// --- core2/ba/hazards.c --- +// --- core2/ba/ba_groundsurface.c --- void freeHazardSfxId(void); void hazards_reset(void); void hazards_update(void); @@ -1411,7 +1403,7 @@ void func_80290298(void); // --- core2/ba/ba_hitbox.c --- enum hitbox_e hitbox_getHitboxForActor(ActorMarker *arg0); -// --- core2/ba/bainput.c --- +// --- core2/ba/ba_input.c --- int bainput_isEnabled(s32 arg0); int bainput_should_beak_barge(void); int bainput_should_beak_bust(void); @@ -1436,7 +1428,7 @@ s32 func_80291660(void); void func_80291590(void); void func_802915B8(void); -// --- core2/ba/bakey.c --- +// --- core2/ba/ba_key.c --- int bakey_getAndSetState(s32 button_indx, s32 val); int bakey_releaseCount(s32 button_indx); int bakey_released(s32 button_indx); @@ -1444,7 +1436,7 @@ void bakey_disableAll(s32 arg0); void bakey_reset(void); void bakey_update(void); -// --- core2/ba/balookat.c --- +// --- core2/ba/ba_lookat.c --- int balookat_try_get_position(f32 arg0[3]); s32 balookat_getState(void); void balookat_init(void); @@ -1459,9 +1451,9 @@ bool func_8028EFC8(void); bool func_8028EFEC(void); bool func_8028F070(void); bool func_8028F098(void); -bool player_isBanjoOrWishywashy(void); +bool func_8028F0D4(void); bool func_8028F150(void); -bool player_isInFirstPersonView(void); +bool func_8028F170(void); bool func_8028F1E0(void); bool func_8028F25C(void); bool func_8028F2A0(void); @@ -1475,16 +1467,16 @@ bool func_8028F530(s32 arg0); bool func_8028F55C(s32 arg0, ActorMarker *marker); bool func_8028F590(s32 arg0, ActorMarker *marker); bool func_8028F5F8(f32 arg0[3]); -bool player_transform(enum transformation_e xform_id); +bool func_8028FB88(enum transformation_e xform_id); bool func_8028FBD4(f32 arg0[3]); bool player_is_in_jiggy_jig(void); bool player_is_present(void); bool player_throwCarriedObject(void); enum actor_e carriedObj_getActorId(void); enum bswatergroup_e player_getWaterState(void); -enum marker_e bacarry_getMarkerId(void); +enum marker_e bacarry_get_markerId(void); f32 func_8028EC64(f32 arg0[3]); -bool ability_isUnlocked(enum ability_e uid); +int ability_isUnlocked(enum ability_e uid); int func_8028EC04(void); s32 func_8028E4A4(void); s32 func_8028F68C(enum bs_interrupt_e arg0, ActorMarker *marker); @@ -1521,7 +1513,7 @@ void player_getVelocity(f32 dst[3]); void player_setIdealRotation(f32 rotation[3]); void player_setRotation(f32 rotation[3]); -// --- core2/ba/marker.c --- +// --- core2/ba/ba_marker.c --- bool baMarker_isCollidable(void); enum actor_e baMarker_getCarriedObjectActorId(void); s32 baMarker_8028D688(void); @@ -1535,7 +1527,7 @@ void baMarker_init(void); void baMarker_setCarriedObject(enum actor_e actor_id); void baMarker_update(void); -// --- core2/ba/model.c --- +// --- core2/ba/ba_model.c --- void assetcache_release(void *); enum asset_e baModel_getModelId(void); s32 baModel_isVisible(void); @@ -1554,16 +1546,14 @@ void baModel_getPosition(f32* dst); void baModel_reset(void); void baModel_setEnvAlpha(s32 alpha); void baModel_setPostDraw(void (*draw_func)(Gfx **gfx, Mtx **mtx, Vtx **vtx)); +void baModel_setVisible(s32 arg0); void baModel_update(void); void baModel_updateModel(void); -// --- core2/ba/playermodel.c --- +// --- core2/ba/ba_modelselect.c --- s32 func_802985F0(void); void func_802986D0(void); void func_80298700(void); -void playerModel_set(void); -void playerModel_free(void); -enum asset_e playerModel_get(void); // --- core2/ba/ba_momentum.c --- void func_8029065C(void); @@ -1577,7 +1567,7 @@ void func_8032196C(void); void func_803219A8(void); void func_803219F4(s32 arg0); -// --- core2/ba/playerposition.c --- +// --- core2/ba/ba_position.c --- void playerPosition_init(void); void playerPosition_func_8029842C(void); void playerPosition_func_80298464(f32 arg0[3]); @@ -1585,8 +1575,7 @@ void playerPosition_func_80298504(f32 arg0[3]); void playerPosition_getOffset(f32 arg0[3]); void playerPosition_setOffset(f32 arg0[3]); void playerPosition_applyOffset(void); -void playerPosition_set(f32 arg0[3]); -void player_setWarpDestination(f32 position[3], f32 yaw, s32 exit_id); +void player_setPosition(f32 arg0[3]); // --- core2/ba/ba_recoil.c --- enum asset_e func_80294974(void); @@ -1604,7 +1593,7 @@ void get_throw_target_position(f32 dst[3]); void set_talk_target_position(f32 src[3]); void set_throw_target_position(f32 src[3]); -// --- core2/ba/basfx.c --- +// --- core2/ba/ba_sfx.c --- void basfx_80299AAC(void); void basfx_80299BD4(void); void basfx_80299DB8(void); @@ -1617,7 +1606,7 @@ void basfx_free(void); void basfx_reset(void); void basfx_update(void); -// --- core2/ba/ba_camera.c --- +// --- core2/ba/ba_sfxintensity.c --- void cameraMode_update(void); void func_80290B6C(void); void func_80291488(s32 arg0); @@ -1625,8 +1614,8 @@ void func_802914CC(s32 arg0); void func_8029151C(s32 arg0); void func_80291548(void); -// --- core2/ba/bsmethods.c --- -void bsmethods_reset(void); +// --- core2/ba/ba_state.c --- +void func_80295914(void); void func_80295B04(void); void func_80295C08(void (* arg0)(void)); void func_80295C14(void); @@ -1643,7 +1632,7 @@ void func_8032320C(void); void func_80323230(void); void func_80323238(void); -// --- core2/ba/bastick.c --- +// --- core2/ba/ba_stick.c --- void bastick_lockAtzero(bool arg0); void bastick_reset(void); void bastick_resetZones(void); @@ -1659,29 +1648,34 @@ void func_802992F0(void); void func_802993C8(void); void func_8029957C(s32 arg0); +// --- core2/ba/ba_timer.c --- +s32 batimer_decrement(s32 timer_id); +void batimer_incrementBy(s32 id, f32 inc_value_sec); +void batimer_set(s32 timer_id, f32 duration); + // --- core2/bs/ant.c --- int bsant_inSet(s32 move_indx); -// --- core2/bs/bBarge.c --- +// --- core2/bs/beak_barge.c --- s32 bsbbarge_hitboxActive(void); -// --- core2/bs/bFly.c --- +// --- core2/bs/beak_bomb.c --- int bsbfly_bombHitboxActive(void); int bsbfly_inSet(enum bs_e arg0); -// --- core2/bs/bLongLeg.c --- +// --- core2/bs/stilt_stride.c --- int bslongleg_inSet(s32 move_indx); -// --- core2/bs/bPeck.c --- +// --- core2/bs/beak_peck.c --- s32 bsbpeck_hitboxActive(void); -// --- core2/bs/bSwim.c --- +// --- core2/bs/beak_swim.c --- bool bsbswim_inSet(enum bs_e move_id); -// --- core2/bs/bTrot.c --- +// --- core2/bs/talon_trot.c --- int bsbtrot_inSet(s32 move_indx); -// --- core2/bs/bbuster.c --- +// --- core2/bs/beak_buster.c --- s32 bsbbuster_hitboxActive(void); s32 func_8029FC4C(void); void func_802A02B4(s32 arg0); @@ -1690,10 +1684,10 @@ void func_802A02B4(s32 arg0); void func_802A02C0(void); void func_802A0340(void); -// --- core2/bs/beeFly.c --- +// --- core2/bs/bee_fly.c --- int bsBeeFly_inSet(s32); -// --- core2/bs/bsStoredState.c --- +// --- core2/bs/bs_storedstate.c --- enum transformation_e bsStoredState_getTransformation(void); s32 bsStoredState_getTrotFlag(void); void bsStoredState_8029A924(void); @@ -1716,12 +1710,12 @@ void bscroc_set_ate_wrong_thing(void); // --- core2/bs/crouch.c --- enum bs_e func_802ADCD4(enum bs_e arg0); -// --- core2/bs/drone.c --- +// --- core2/bs/scripted.c --- void bsdrone_end(void); void bsdrone_init(void); void bsdrone_update(void); -// --- core2/bs/jig.c --- +// --- core2/bs/jiggy_dance.c --- int bsjig_inJiggyJig(enum bs_e state); void func_802B0CD8(void); @@ -1747,44 +1741,44 @@ void func_802B6FA8(void); // --- core2/bs/walrus.c --- int bswalrus_inSledSet(enum bs_e state); -// --- core2/nc/camera_ease.c --- +// --- core2/camera/camera_ease.c --- void func_802C2250(void); void func_802C2258(void); void func_802C22C0(f32 target_position[3], f32 target_rotation[3]); -// --- core2/nc/camera_focus.c --- +// --- core2/camera/camera_focus.c --- void func_802BABD8(void); void func_802BAC10(void); void func_802BAC58(void); -// --- core2/nc/camera_fog.c --- +// --- core2/camera/camera_fog.c --- void func_802BEE2C(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802BEF70(void); void func_802BEF78(void); void func_802BEFB0(void); -// --- core2/propModelList.c --- +// --- core2/prop_assetcache.c --- void propModelList_free(void); void propModelList_init(void); void propModelList_flush(s32 arg0); -// --- core2/nc/camera_motor1.c --- +// --- core2/camera/camera_motor1.c --- s32 func_802BB294(void); void func_802BAF20(void); void func_802BAF40(void); -// --- core2/nc/camera_motor2.c --- +// --- core2/camera/camera_motor2.c --- void func_802BB2A0(void); void func_802BB2A8(void); void func_802BB3C4(s32 arg0); void func_802BB41C(s32 arg0); void func_802BB4D8(f32 position[3], f32 rotation[3]); -// --- core2/nc/camera_nodemanager.c --- +// --- core2/camera/camera_nodemanager.c --- s32 ncCamera_getType(void); void camera_setType(enum camera_type_e camera_type); void func_802BBD0C(Gfx **gdl, Mtx **mptr, Vtx **vptr); -void core2_34790_getClipDistances(f32 *arg0, f32 *arg1); +void func_802BBD2C(f32 *arg0, f32 *arg1); void nccamera_init(void); void func_802BC10C(void); void func_802BC21C(s32 arg0, s32 arg1); @@ -1801,26 +1795,26 @@ s32 func_80322758(void); void func_80322764(void); void func_8032278C(s32 arg0, s32 arg1); -// --- core2/nc/camera_position.c --- +// --- core2/camera/camera_position.c --- void func_802BE940(void); -// --- core2/nc/camera_set.c --- +// --- core2/camera/camera_set.c --- void func_803525A0(f32 arg0[3]); -// --- core2/nc/cameranode_type1.c --- +// --- core2/camera/cameranode_type1.c --- bool code336F0_func_802BA87C(PivotCameraNode *self); bool code336F0_func_802BA89C(PivotCameraNode *self); bool code336F0_func_802BA8BC(PivotCameraNode *self); void code336F0_func_802BA7D8(PivotCameraNode *self, f32 arg1[3]); -// --- core2/nc/cameranode_type3.c --- +// --- core2/camera/cameranode_type3.c --- bool code33310_func_802BA4D0(ZoomCameraNode *self); bool code33310_func_802BA4F0(ZoomCameraNode *self); -// --- core2/nc/cameranode_type4.c --- +// --- core2/camera/cameranode_type4.c --- s32 code33250_func_802BA234(RandomCameraNode *self); -// --- core2/nc/cameranodelist.c --- +// --- core2/camera/cameranodelist.c --- s32 ncCameraNodeList_getNodeType(int camera_node_index); s32 ncCameraNodeList_nodeIsValid(int camera_node_index); void ncCameraNodeList_defrag(); @@ -1828,88 +1822,88 @@ void ncCameraNodeList_free(); void ncCameraNodeList_fromFile(File *file_ptr); void ncCameraNodeList_init(); -// --- core2/nc/dynamicCam1.c --- +// --- core2/camera/dynamicCam1.c --- void ncDynamicCam1_end(void); void ncDynamicCam1_init(void); void ncDynamicCam1_update(void); -// --- core2/nc/dynamicCam10.c --- +// --- core2/camera/dynamicCam10.c --- void ncDynamicCam10_end(void); void ncDynamicCam10_init(void); void ncDynamicCam10_update(void); -// --- core2/nc/dynamicCam11.c --- +// --- core2/camera/dynamicCam11.c --- void func_802BF798(s32 camera_node_index); void ncDynamicCam11_end(void); void ncDynamicCam11_init(void); void ncDynamicCam11_update(void); -// --- core2/nc/dynamicCam12.c --- +// --- core2/camera/dynamicCam12.c --- void dynamicCam12_init(void); void func_802C0F4C(void); void ncDynamicCam12_end(void); void ncDynamicCam12_update(void); -// --- core2/nc/dynamicCam13.c --- +// --- core2/camera/dynamicCam13.c --- void func_802C095C(void); void ncDynamicCam13_end(void); void ncDynamicCam13_init(void); void ncDynamicCam13_update(void); -// --- core2/nc/dynamicCam3.c --- +// --- core2/camera/dynamicCam3.c --- void ncDynamicCam3_end(void); void ncDynamicCam3_init(void); void ncDynamicCam3_update(void); -// --- core2/nc/fly.c --- -void ncbafly_end(void); -void ncbafly_func_802BFE74(bool); -void ncbafly_init(void); -void ncbafly_update(void); +// --- core2/camera/dynamicCam4.c --- +void ncDynamicCam4_end(void); +void ncDynamicCam4_func_802BFE74(bool); +void ncDynamicCam4_init(void); +void ncDynamicCam4_update(void); -// --- core2/nc/dynamicCam5.c --- +// --- core2/camera/dynamicCam5.c --- void ncDynamicCam5_end(void); void ncDynamicCam5_func_802BF590(f32 arg0[3]); void ncDynamicCam5_init(void); void ncDynamicCam5_update(void); -// --- core2/nc/dynamicCam8.c --- +// --- core2/camera/dynamicCam8.c --- void ncDynamicCam8_end(void); void ncDynamicCam8_func_802BF9B8(s32 arg0); void ncDynamicCam8_init(void); void ncDynamicCam8_update(void); -// --- core2/nc/dynamicCam9.c --- +// --- core2/camera/dynamicCam9.c --- void ncDynamicCam9_end(void); void ncDynamicCam9_init(void); void ncDynamicCam9_update(void); -// --- core2/nc/dynamicCamA.c --- +// --- core2/camera/dynamicCamA.c --- void ncDynamicCamA_end(void); void ncDynamicCamA_init(void); void ncDynamicCamA_update(void); -// --- core2/nc/dynamicCamB.c --- +// --- core2/camera/dynamicCamB.c --- void ncDynamicCamB_end(void); void ncDynamicCamB_init(void); void ncDynamicCamB_update(void); -// --- core2/nc/dynamicCamC.c --- +// --- core2/camera/dynamicCamC.c --- void ncDynamicCamC_end(void); void ncDynamicCamC_init(void); void ncDynamicCamC_update(void); -// --- core2/nc/die.c --- -void ncbadie_end(void); -void ncbadie_init(void); -void ncbadie_update(void); +// --- core2/camera/dynamicCamD.c --- +void ncDynamicCamD_end(void); +void ncDynamicCamD_init(void); +void ncDynamicCamD_update(void); -// --- core2/nc/dynamicCamF.c --- +// --- core2/camera/dynamicCamF.c --- void ncDynamicCamF_end(void); void ncDynamicCamF_init(void); void ncDynamicCamF_update(void); -// --- core2/nc/dynamicCamera.c --- +// --- core2/camera/dynamicCamera.c --- int func_802BE60C(void); int func_802BE834(f32 arg0[3]); int ncDynamicCamera_getState(void); @@ -1936,21 +1930,21 @@ void ncDynamicCamera_setState(s32 state); void ncDynamicCamera_setUpdateEnabled(bool arg0); void ncDynamicCamera_update(void); -// --- core2/nc/1p.c --- -s32 ncba1p_getState(void); -void ncba1p_getPositionAndRotation(f32 position[3], f32 rotation[3]); -void ncba1p_getZoomedInRotation(f32 dst[3]); -void ncba1p_reset(void); -void ncba1p_setState(enum nc_first_person_state state); -void ncba1p_setZoomedOutPosition(f32 src[3]); -void ncba1p_setZoomedOutRotation(f32 src[3]); +// --- core2/camera/firstpersoncamera.c --- +s32 ncFirstPersonCamera_getState(void); +void ncFirstPersonCamera_getPositionAndRotation(f32 position[3], f32 rotation[3]); +void ncFirstPersonCamera_getZoomedInRotation(f32 dst[3]); +void ncFirstPersonCamera_reset(void); +void ncFirstPersonCamera_setState(enum nc_first_person_state state); +void ncFirstPersonCamera_setZoomedOutPosition(f32 src[3]); +void ncFirstPersonCamera_setZoomedOutRotation(f32 src[3]); -// --- core2/nc/randomCamera.c --- +// --- core2/camera/randomCamera.c --- void ncRandomCamera_end(void); void ncRandomCamera_init(void); void ncRandomCamera_update(void); -// --- core2/nc/staticCamera.c --- +// --- core2/camera/staticCamera.c --- void ncStaticCamera_end(void); void ncStaticCamera_exit(void); void ncStaticCamera_getPosition(f32 dst[3]); @@ -1986,7 +1980,7 @@ s32 chBottlesBonusCursor_getState(void); void chBottlesBonusCursor_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void chBottlesBonusCursor_lose(void); -// --- core2/fx/drips.c --- +// --- core2/ch/drips.c --- void func_80359A40(f32 position[3], void *arg1, s32 cnt); // --- core2/ch/goldfeather.c --- @@ -1994,7 +1988,6 @@ void func_802D8BE4(bool gold_feather); // --- core2/ch/honeycomb.c --- enum honeycomb_e func_802CA1C4(Actor *self); -enum mumbotoken_e func_802E0CB0(Actor *self); void func_802CA1CC(enum honeycomb_e id); // --- core2/ch/jiggy.c --- @@ -2005,27 +1998,27 @@ void chjiggy_setJiggyId(Actor *self, u32 id); // --- core2/ch/jigsawdance.c --- void chJigsawDance_setState(Actor * self, u32 arg1); -// --- cutscenes/cutscene_trigger.c --- +// --- core2/ch/mmm_veggies.c --- void func_802CDAC4(Actor *); // --- core2/ch/mole.c --- int chmole_learnedAllLevelAbilities(enum level_e level); int chmole_learnedAllSpiralMountainAbilities(void); -// --- core2/gc/overlaycopyright.c --- +// --- core2/ch/overlaycopyright.c --- void chOverlayCopyright_func_802DCB0C(s32 arg0, s32 arg1); void chOverlayCopyright_spawn(s32 arg0, s32 arg1); -// --- core2/gc/overlaynocontroller.c --- +// --- core2/ch/overlaynocontroller.c --- void chOverlayNoController_func_802DD040(s32 arg0, s32 arg1); void chOverlayNoController_spawn(s32 arg0, s32 arg1); -// --- core2/gc/overlaypressstart.c --- +// --- core2/ch/overlaypressstart.c --- void chOverlayPressStart_func_802DCDB0(void); void chOverlayPressStart_func_802DCDC0(NodeProp *arg0, ActorMarker *arg1); void chOverlayPressStart_spawn(NodeProp *arg0, ActorMarker *arg1); -// --- core2/sfx/soundsource.c --- +// --- core2/ch/soundsource.c --- void func_802D09B8(Actor *self, s32 arg1); // --- core2/ch/trainers.c --- @@ -2038,9 +2031,9 @@ void chwadingboots_802D6E54(Actor *self); // --- core2/climb.c --- u8 func_8029825C(void); -void climb_clear(void); -void climb_release(void); -void climb_regrab_update(void); +void climbClear(void); +void climbRelease(void); +void func_80298344(void); // --- core2/bundle.c --- bool func_802C9C14(Actor *actor); @@ -2072,7 +2065,7 @@ void itemPrint_init(void); void itemPrint_reset(void); void itemPrint_update(void); -// --- core2/time_framedelta.c --- +// --- core2/collision/cachesize.c --- void func_8033DC04(void); void func_8033DC10(void); void func_8033DC18(void); @@ -2115,7 +2108,7 @@ void func_80351B28(Struct68s *arg0, f32 arg1[3]); void func_80351C2C(Struct68s *arg0, f32 arg1[3]); void func_80351C48(void); -// --- core2/collision/dispatch.c --- +// --- core2/collision/funcs.c --- bool func_803209F8(f32 arg0[3], f32 arg1[3], f32 *arg2, f32 arg3[3]); void func_80320B7C(void); void func_80320B84(void); @@ -2129,7 +2122,7 @@ s32 collision_getHitsToTrigger(CollisionParams *arg0); s32 collision_getDropBundleNum(CollisionParams *arg0); void func_8033D2F4(void); -// --- core2/map/envcolor.c --- +// --- core2/collision/init.c --- void func_8031B710(void); void func_8031B718(void); void func_8031B790(void); @@ -2160,18 +2153,18 @@ void func_803451B0(u8 index, f32 arg1[3]); void func_80356714(void); void codeCF5F0_forgetAllAbilitiesExceptClawSwipeIfChecksumsFail(void); -// --- GV/ch/mummum.c --- +// --- core2/cutscene/animated.c --- void func_8035D490(ActorMarker *marker); void func_8035D4F0(ActorMarker *marker, s32 arg1); -// --- core2/nc/camera_focustarget.c --- +// --- core2/cutscene/ctrl.c --- s32 func_802C0190(void); void func_802C0120(void); void func_802C0148(void); void func_802C0150(s32 arg0); void func_802C02D4(f32 arg0[3]); -// --- core2/map/cutscene_skip.c --- +// --- core2/cutscene/lair.c --- s32 cutscenetrigger_update(void); void func_8031CC8C(NodeProp *arg0, s32 arg1); void func_8031CC40(enum map_e map_id, s32 arg1); @@ -2185,7 +2178,7 @@ void clearScoreStates(void); void debugScoreStates(void); void warp_mmmEnterLoggo(NodeProp *arg0, ActorMarker *arg1); -// --- core2/map/warp_dispatch.c --- +// --- core2/cutscene/nodeupdate.c --- s32 func_8033451C(s32 arg0); s32 func_80334524(s32 arg0); s32 func_8033452C(s32 arg0); @@ -2195,7 +2188,7 @@ void func_803343F8(s32 indx); void func_80334428(void); void func_80334448(NodeProp *arg0, ActorMarker *arg1); -// --- core2/demo.c --- +// --- core2/demo_input.c --- int demo_readInput(OSContPad* arg0, s32* arg1); void demo_free(void); void demo_load(enum map_e map, s32 demo_id); @@ -2211,10 +2204,10 @@ void dialogBin_terminate(void); void dialogBin_update(void); void func_8031B62C(void); -// --- core2/dialog/progressDialog.c --- +// --- core2/dialog/progress_dialogs.c --- void progressDialog_showDialogMaskZero(enum file_progress_e progress_flag); -void progressDialog_setAndTriggerDialog_4(enum volatile_flags_e arg0); -void progressDialog_setAndTriggerDialog_E(enum volatile_flags_e arg0); +void volatileFlag_setAndTriggerDialog_4(enum volatile_flags_e arg0); +void volatileFlag_setAndTriggerDialog_E(enum volatile_flags_e arg0); // --- core2/inventory_slots.c --- void func_803246F0(u8* self, s32 indx); @@ -2248,7 +2241,7 @@ void func_802E67AC(void); void func_802E67C4(void); void func_802E6820(s32 arg0); -// --- core2/frame/rendermem.c --- +// --- core2/frame/bufferreadback.c --- bool func_802E4424(void); bool func_802E4A08(void); s32 func_802E4A98(s32 arg0); @@ -2270,18 +2263,18 @@ void func_802E4214(enum map_e map_id); void func_802E4384(void); void func_802E4A70(void); void func_802E4A80(void); -void game_draw(bool arg0); +void game_draw(s32 arg0); // --- core2/frame/rendermem.c --- void dummy_func_802E35D0(void); void func_802E3580(void); void func_802E35D8(void); -// --- core2/scorequeue/airscore.c --- +// --- core2/fx/airscore.c --- s32 fxairscore_count_to_time(s32 count); s32 fxairscore_time_to_count(s32 time); -// --- core2/scorequeue/common2score.c --- +// --- core2/fx/common2score.c --- enum item_e func_802FDD0C(struct8s *arg0); // --- core2/fx/effect_colordata.c --- @@ -2292,7 +2285,7 @@ void func_80345C78(f32 arg0[4], f32 arg1[3]); void func_80345CD4(f32 arg0[4], f32 arg1[4]); void func_80345D30(f32 arg0[4], f32 arg1[4], f32 arg2[4]); -// --- core2/fx/eggshatter.c --- +// --- core2/fx/effect_eggshatter.c --- void eggShatter_defrag(void); void eggShatter_draw(Gfx **gPtr, Mtx **mPtr, Vtx **vPtr); void eggShatter_free(void); @@ -2300,7 +2293,7 @@ void eggShatter_init(void); void eggShatter_new(f32 position[3]); void eggShatter_update(void); -// --- core2/gc/pictureframe.c --- +// --- core2/fx/effect_enemyrender.c --- Actor * func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802DF270(void); @@ -2311,7 +2304,7 @@ void func_802DAD8C(ParticleEmitter *pCtrl, Actor *self, enum asset_e model_id); void humanoidBaddie_enterInvulnerableState(ActorMarker *marker, s32 arg1); void humanoidBaddie_update(Actor *self); -// --- core2/mumboshandwithpicture.c --- +// --- core2/fx/effect_particle.c --- void func_802DF090(s32 arg0, s32 arg1); void func_802DF0C8(void); void func_802DF11C(s32 arg0, s32 arg1); @@ -2322,11 +2315,11 @@ void func_802929F8(void); // --- core2/fx/effect_simplesprite.c --- void func_802DC110(f32 *position, enum asset_e sprite_id); -// --- core2/fx/banjokazooiesign.c --- +// --- core2/fx/effect_spriteanim.c --- void func_802DC9A4(s32 arg0, s32 arg1); void func_802DC9DC(s32 arg0, s32 arg1); -// --- core2/scorequeue/honeycarrierscore.c --- +// --- core2/fx/honeycarrierscore.c --- void gcpausemenu_80314AC8(int arg0); // --- core2/fx/ripple.c --- @@ -2335,7 +2328,7 @@ void fxRipple_802F3584(s32 arg0, f32 position[3], uintptr_t arg2); void fxRipple_free(void); void fxRipple_init(void); -// --- core2/honeycombscore.c --- +// --- core2/fx/score_honeycomb.c --- s32 honeycombscore_get_level_total(enum level_e level_id); s32 honeycombscore_get_total(void); void honeycombscore_clear(void); @@ -2343,7 +2336,7 @@ void honeycombscore_debug(void); void honeycombscore_getSizeAndPtr(s32 *size, u8 **addr); void honeycombscore_set(enum honeycomb_e indx, bool val); -// --- core2/jiggyscore.c --- +// --- core2/fx/score_jiggy.c --- s32 jiggyscore_leveltotal(s32 lvl); s32 jiggyscore_total(void); void * jiggyscore_clearAllSpawned(void); @@ -2353,10 +2346,8 @@ void jiggyscore_getSizeAndPtr(s32 *size, u8 **addr); void jiggyscore_setCollected(s32 indx, s32 val); void jiggyscore_setSpawned(s32, s32); -// --- core2/fx/effect_jiggy_list.c --- +// --- core2/fx/score_jiggylist.c --- void codeABC00_spawnJiggyAtLocation(enum jiggy_e, f32[3]); -void codeABC00_spawnJiggyAtLocationEx(enum jiggy_e, f32[3], s32 triggerEvent); -s32 jiggylist_hasSpawnedObject(enum jiggy_e jiggy_id); void func_80332E08(void); void func_8033301C(void); void func_80333270(enum jiggy_e jiggy_id, f32 position[3], void (*method)(Actor *, ActorMarker *), ActorMarker *other_marker); @@ -2366,7 +2357,7 @@ void jiggylist_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void jiggylist_map_actors(void); void jiggylist_set_level(enum map_e map_id); -// --- core2/mumboscore.c --- +// --- core2/fx/score_mumbo.c --- bool mumboscore_get(enum mumbotoken_e indx); void mumboscore_clear(void); void mumboscore_debug(void); @@ -2395,25 +2386,24 @@ void gameSelect_saveAndExit(void); void gameSelect_setGameNumber(s32 arg0); void gameSelect_resetGameNumber(void); -// --- core2/flags_bitfield.c --- -s32 bitfieldarray_getBit(u8 *array, s32 index); -s32 bitfieldarray_getNBits(u8 *array, s32 offset, s32 numBits); +// --- core2/game_complete.c --- +s32 bitfield_get_bit(u8 *array, s32 index); +s32 bitfield_get_n_bits(u8 *array, s32 offset, s32 numBits); s32 dummy_func_80320240(void); s32 dummy_func_80320248(void); s32 fileProgressFlag_getAndSet(enum file_progress_e index, s32 set); s32 func_8032056C(void); s32 func_80320708(void); -void bitfieldarray_setBit(u8 *array, s32 index, s32 set); -void bitfieldarray_setNBits(u8 *array, s32 startIndex, s32 set, s32 length); +void bitfield_set_bit(u8 *array, s32 index, s32 set); +void bitfield_set_n_bits(u8 *array, s32 startIndex, s32 set, s32 length); void fileProgressFlag_getSizeAndPtr(s32 *size, u8 **addr); -void volatileFlag_getSizeAndPtr(s32 *size, u8 **addr); void fileProgressFlag_set(enum file_progress_e index, s32 set); void volatileFlag_backupAll(void); void volatileFlag_clear(void); void volatileFlag_restoreAll(void); // --- core2/gc/dialog.c --- -int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, s32 (*arg4)(ActorMarker *, enum asset_e, s32)); +int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, void (*arg4)(ActorMarker *, enum asset_e, s32)); int gcdialog_showDialogConditional(s32 text_id, s32 arg1, f32 *pos, ActorMarker *marker, void(*callback)(ActorMarker *, enum asset_e, s32), void(*arg5)(ActorMarker *, enum asset_e, s32), s32(*arg6)(ActorMarker *, s32, s32)); int gcdialog_getCurrentTextId(void); int func_803115C4(s32 next_state); @@ -2460,14 +2450,14 @@ void sky_free(void); void sky_reset(void); void sky_update(void); -// --- (data declarations - origin unknown) --- +// --- core2/gfx/displaylistdata.c --- void func_8030C180(void); void func_8030C1A0(void); void func_8030C204(void); void func_8030C2D4(Gfx **gdl, Mtx **mptr, Vtx **vptr); -void picturebox_setScissorBox(void); +void scissorBox_setSmall(void); -// --- core2/displaylist_init.c --- +// --- core2/gfx/displaylistinit.c --- void func_80315084(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_80315110(Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_803151D0(Gfx **gfx, Mtx **mtx, Vtx **vtx); @@ -2483,11 +2473,14 @@ void func_803411B0(void); void func_80341A54(void); void glspline_defrag(void); +// --- core2/level/lightconfig.c --- +// code35520_getDistanceVectors and code35520_selectTable are declared in core2/core2.h + // --- core2/level/metadata.c --- int barebound_set_active(s32 arg0); s32 barebound_802987B4(void); -// --- core2/level/levelspecificflags.c --- +// --- core2/level/specificflags.c --- s32 levelSpecificFlags_getN(s32 i, s32 n); s32 levelSpecificFlags_getSet(s32 arg0, s32 arg1); s32 levelSpecificFlags_validateCRC1(void); @@ -2495,7 +2488,7 @@ s32 levelSpecificFlags_validateCRC2(void); void levelSpecificFlags_clear(void); void levelSpecificFlags_setN(s32 index, s32 val, s32 n); -// --- core2/map/loadzone.c --- +// --- core2/load_zone.c --- void codeA960_forceLoadzone(s32); void func_80291910(void); void func_802919A0(void); @@ -2514,7 +2507,11 @@ void func_8034B9BC(s32 arg0); void func_8034B9E4(void); void func_8034BA7C(enum map_e map_id, s32 exit_id); -// --- core2/map/mapModel.c --- +// --- core2/map/model.c --- +// NOTE: func_802E76B0, collisionList_func_802E805C, func_802E8E88, func_802E9118, +// func_802E92AC, func_802E9DD8 return BKCollisionTriangle* but have conflicting +// local externs (bool/s32/void) in decomp source files. Files that need +// the pointer type already have correct local externs. BKCollisionTriangle *func_802E76B0(BKCollisionList *collisionList, BKVertexList *vertexList, f32 startPoint[3], f32 endPoint[3], f32 arg4[3], u32 flagFilter); Vec3fArray *func_803097A0(void); BKCollisionTriangle *func_80309B48(f32 startPoint[3], f32 endPoint[3], f32 arg2[3], u32 flagFilter); @@ -2531,25 +2528,26 @@ void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); void mapModel_setEnvColor(s32 r, s32 g, s32 b); void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/map/mapsavestate.c --- +// --- core2/map/savestate.c --- int game_is_frozen(void); // --- core2/map/gsworld.c --- +enum map_e gsworld_getMap(void); -// --- core2/map/mapspecificflags.c --- +// --- core2/map/specificflags.c --- s32 mapSpecificFlags_validateCRC1(void); u32 mapSpecificFlags_getClear(s32 i); u32 mapSpecificFlags_getN(s32 idx, s32 n); void mapSpecificFlags_clearAll(void); void mapSpecificFlags_setN(s32 idx, s32 val, s32 n); -// --- core2/map/list.c --- +// --- core2/map_list.c --- void func_8029A47C(s32 arg0[3]); void func_8029A4D0(void); void func_8029A54C(void); void func_8029A554(void); -// --- core2/fx/projectile_system.c --- +// --- core2/model/matrixrotate.c --- void func_8033F9C0(void); void func_8033FA24(void); @@ -2558,21 +2556,21 @@ void func_8033F738(ActorMarker *arg0); void func_8033F784(ActorMarker *arg0); void func_8033F7A4(ActorMarker *arg0, BKVertexList *arg1); -// --- core2/model/modelRender.c --- +// --- core2/model/render.c --- void modelRender_setBoneTransformList(BoneTransformList *arg0); // --- core2/model/rendernormal.c --- void animVerticesList_transform(BKAnimVerticesList *arg0, BKVertexList *arg1, AnimMtxList *mtx_list); -// --- core2/mumbo.c --- +// --- core2/mumbo_transforms.c --- void chmumbo_func_802D1724(void); void func_802D2CB8(void); void func_802D2CDC(void); -// --- core2/map/overlay.c --- +// --- core2/overlay.c --- // leveloverlay_* functions are declared in core2/core2.h -// --- MMM/bathroom_particles.c --- +// --- core2/particle/bathroom.c --- void func_8029ADA8(void); void func_8029ADCC(void); void func_8029AE1C(void); @@ -2580,7 +2578,7 @@ void func_8029AE48(void); void func_8029AE74(s32 arg0); void func_8029AF1C(void); -// --- core2/particle/dustemitter.c --- +// --- core2/particle/colordefault.c --- bool dustEmitter_isActive(s32 arg0); s32 dustEmitter_returnGiven(s32 arg0); void dustEmitter_init(void); @@ -2615,11 +2613,14 @@ void partEmitMgr_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr); void partEmitMgr_drawPass0(Gfx **gdl, Mtx **mptr, Vtx **vptr); void partEmitMgr_drawPass1(Gfx **gdl, Mtx **mptr, Vtx **vptr); void partEmitMgr_free(void); +void partEmitMgr_freeEmitter(ParticleEmitter *self); void partEmitMgr_init(void); void partEmitMgr_update(void); void particleEmitter_draw(ParticleEmitter *self, Gfx **gdl, Mtx **mPtr, Vtx **vPtr); void particleEmitter_emitUniformLine(ParticleEmitter *self, f32 start[3], f32 end[3], s32 count); void particleEmitter_free(ParticleEmitter *self); +void particleEmitter_func_802EFA78(ParticleEmitter *self, s32 arg1); +void particleEmitter_setParticleCallback(ParticleEmitter *self, void (*arg1)(ParticleEmitter *self, f32 pos[3])); // --- core2/bs/player_spawn.c --- bool func_8029BDE8(void); @@ -2652,7 +2653,7 @@ void func_8029C5E8(void); void func_8029C674(void); void func_8029C6D0(void); void func_8029C748(void); -void code_14420_setUpdateTypes(enum baanim_update_type_e arg0, enum yaw_state_e yaw_state, s32 arg2, BaPhysicsType arg3); +void func_8029C7F4(s32 arg0, s32 yaw_state, s32 arg2, s32 arg3); void code_14420_setVoidOutLocation(enum map_e map_id, s32 exit_id); void func_8029C848(AnimCtrl *arg0); void func_8029C984(void); @@ -2697,7 +2698,7 @@ void func_802F4200(f32 arg0[3]); void func_802F422C(void); void func_802F4250(void); -// --- core2/map/cutscene_triggers.c --- +// --- core2/cutscene_triggers.c --- void func_803223AC(void); void func_80322490(void); void func_803224FC(void); @@ -2714,21 +2715,21 @@ bool player_isActive(void); bool player_isFallTumbling(void); bool player_isInRBB(void); bool player_isSwimming(void); -bool can_dive(void); -bool can_feathery_flap(void); -bool can_peck(void); -bool can_view_first_person(void); -bool func_8028ABB8(void); -bool func_8028ADB4(void); -bool func_8028B394(void); -bool func_8028B4C4(void); -bool func_8028B528(void); -bool player_isOnDangerousGround(void); -bool player_isSliding(void); -bool player_isStable(void); -bool player_shouldFall(void); -bool player_shouldSlideTrot(void); -bool wishyWashyFlag_get(void); +int can_dive(void); +int can_feathery_flap(void); +int can_peck(void); +int can_view_first_person(void); +int func_8028ABB8(void); +int func_8028ADB4(void); +int func_8028B394(void); +int func_8028B4C4(void); +int func_8028B528(void); +int player_isOnDangerousGround(void); +int player_isSliding(void); +int player_isStable(void); +int player_shouldFall(void); +int player_shouldSlideTrot(void); +int wishyWashyFlag_get(void); s32 can_beak_barge(void); s32 can_beak_bomb(void); s32 can_beak_bust(void); @@ -2743,12 +2744,12 @@ s32 func_8028B120(void); void func_8028B6FC(void); void func_8028B71C(void); -// --- core2/gc/gameoversign.c --- +// --- core2/actor_gameover.c --- void func_802DC528(NodeProp *arg0, ActorMarker *arg1); void func_802DC560(NodeProp*, ActorMarker*); void func_802DC604(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/gc/transition.c --- +// --- core2/level_transition.c --- int func_8032190C(void); enum level_e level_get(void); void func_803216D0(enum map_e map); @@ -2756,7 +2757,7 @@ void func_80321854(void); void func_80321918(int arg0); void func_80321924(void); -// --- core2/quiz/quizquestionaskedbitfield.c --- +// --- core2/quiz/bitfield.c --- void quizQuestionAskedBitfield_defrag(void); void quizQuestionAskedBitfield_free(void); void quizQuestionAskedBitfield_init(void); @@ -2822,7 +2823,7 @@ void saveData_load(void *savedata); void savedata_init(void); void savedata_update_crc(void *buffer, s32 size); -// --- core2/fx/weather_snow.c --- +// --- core2/sfx/filedata.c --- void func_802F8FF0(void); void func_802F8FFC(void); void func_802F9054(void); @@ -2831,7 +2832,7 @@ void func_802F9114(void); void func_802F919C(void); void func_802F962C(Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/fx/weather.c --- +// --- core2/sfx/init.c --- struct3s * func_802F7C7C(void); struct6s * func_802F7C38(void); void func_802F7CC0(void); @@ -2841,7 +2842,7 @@ void func_802F7D44(void); void func_802F7DE4(void); void func_802F7E54(void); -// --- core2/fx/weather_leaves.c --- +// --- core2/sfx/playstate.c --- void func_802F8A70(struct6s *self); void func_802F8A90(struct6s *self, Gfx **gdl, Mtx **mptr, Vtx **vptr); void func_802F8B8C(struct6s *self); @@ -2876,7 +2877,7 @@ void sfxSource_setCallbackByIndex(u8 indx, void (*arg1)(u8)); void sfxSource_triggerCallbackByIndex(u8 indx); void func_8030DFB4(u8 indx, s32 arg1); -// --- core2/fx/weather_rain.c --- +// --- core2/sfx/streamctrl.c --- void func_802F80F0(struct3s *self); void func_802F8110(struct3s *self, Gfx **gdl, Mtx **mptr, u32 arg3); void func_802F8214(struct3s * self); @@ -2890,15 +2891,15 @@ void func_8034F734(void); void func_8034F774(void); void func_8034F918(void); -// --- core2/scorequeue/queue_collectibles.c --- +// --- core2/snacker_pool1.c --- bool func_802FBE04(void); void func_802FBB18(void); void func_802FBDFC(void); -// --- core2/scorequeue/queue_major_items.c --- +// --- core2/snacker_pool2.c --- bool func_802FC390(void); -// --- core2/spawnqueue.c --- +// --- core2/spawn_queue.c --- void spawnQueue_flush(void); void spawnQueue_free(void); void spawnQueue_func_802C3A18(void); @@ -2909,7 +2910,7 @@ void spawnQueue_unlock(void); // --- core2/spline_bezier.c --- -// --- core2/fx/commonParticle.c --- +// --- core2/sprite/displaydata.c --- s32 func_8033E8AC(void); u8 func_8033E93C(void); void commonParticle_init(void); @@ -2974,12 +2975,12 @@ void item_setMaxCount(s32 item); void itemscore_highNoteScores_fromSaveData(u8 *savedata); void itemscore_levelReset(enum level_e level); void notescore_getSizeAndPtr(s32 *size, void **ptr); -void itemscore_noteScores_getSizeAndPtr(s32 *size, u8 **addr); -void itemscore_noteScores_setLevel(enum level_e level, s32 score); void saveditem_getSizeAndPtr(s32 *size, u8 **buffer); void timeScores_getSizeAndPtr(s32 *size, void **ptr); -// --- core2/timedfuncqueue.c --- +// --- core2/texture/copy.c --- + +// --- core2/timed_funcqueue.c --- void func_80324C58(void); void func_80324DBC(f32 time, enum asset_e text_id, s32 arg2, f32 position[3], ActorMarker *caller, void (*callback_method_1)(ActorMarker *, enum asset_e, s32), void (*callback_method_2)(ActorMarker *, enum asset_e, s32)); void timedFuncQueue_defrag(void); @@ -2996,7 +2997,9 @@ void func_8034BF54(ActorMarker *marker); void func_8034BFF8(ActorMarker *marker); void func_8034C21C(ActorMarker *marker); -// --- core2/vtx/gclights.c --- +// --- core2/vtx/lighting.c --- +void lighting_free(); +void lighting_init(); void lightingVectorList_fromFile(File *file_ptr); // --- core2/vtx/listutils.c --- @@ -3020,13 +3023,20 @@ void func_8034C8D8(void); void func_8034C97C(void); void func_8034C9B0(int arg0); -// --- cutscenes/cutscenesspawnqueue.c --- +// --- core2/vtx/list.c --- + +// --- core2/yaw.c --- +void yaw_init(void); +void yaw_setUpdateState(s32 arg0); +void yaw_update(void); + +// --- cutscenes/actor_spawninit.c --- void cutscene_func_8038C4E0(void); -// --- fight/fight.c --- +// --- FINALE/fight.c --- void fight_addSpawnableActors(void); -// --- lair/lairspawnqueue.c --- +// --- lair/actor_spawninit.c --- void lair_func_8038A0C4(void); // --- lair/ch/brentilda.c --- @@ -3041,38 +3051,24 @@ void ff_init(void); void lair_func_8038E0B0(void); void lair_func_8038E768(Gfx **dl, Mtx **m, Vtx **v); -// --- lair/jigsawpicture.c --- +// --- LAIR/jigsawpicture.c --- bool jigsawPicture_isJigsawPictureComplete(s32 arg0); -// --- port/OS/libultra.c --- +// --- port/stub.c --- s32 osContSetCh(u8 ch); u32 __osGetSR(void); void osCreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p); void osDestroyThread(OSThread* thread); +void osDpSetStatus(u32 data); void osSetThreadPri(OSThread* thread, OSPri p); void osSpTaskYield(void); void osStartThread(OSThread* thread); void osStopThread(OSThread* t); -u32 bkGetSR(void); -float gu_sqrtf(float val); -void osViExtendVStart(u32 arg0); -OSYieldResult osSpTaskYielded(OSTask* task); -void __osError(s16 error_code, s16 num_args, ...); -s32 eeprom_readBlocks(s32 file, s32 offset, void* buffer, s32 count); -s32 eeprom_writeBlocks(s32 file, s32 offset, void* buffer, s32 count); - -// --- port/OS/OS_RCP.cpp --- -u32 osDpGetStatus(void); -void osDpSetStatus(u32 data); - -// --- port/OS/OS_VI.cpp --- -void* osViGetCurrentFramebuffer(void); -void* osViGetNextFramebuffer(void); -// --- provided by libultraship --- +// --- unmapped (definition not found in src/) --- s32 osPiReadIo(u32, u32 *); -// --- core2/ba/bastick.c --- +// --- core2/ba/ba_stick.c --- s32 bastick_getZone(void); // --- core2/ba/ba_lookdir.c --- @@ -3087,7 +3083,7 @@ void particleEmitter_manualFree(ParticleEmitter *self); // --- core2/anim/anim_bonetransform.c --- void func_8033BD20(void **arg0); -// --- core2/timedfuncqueue.c --- +// --- core2/timed_funcqueue.c --- bool timedFuncQueue_is_empty(void); // --- core2/fx/effect_colordata.c --- @@ -3114,13 +3110,13 @@ bool func_80245524(f32 arg0[3], void *arg1, intptr_t *arg2, f32 *arg3); // --- core2/bs/player_spawn.c --- void func_8029BC60(enum asset_e *anim_id, f32 *anim_duration); -// --- core2/frame/rendermem.c --- +// --- core2/frame/bufferreadback.c --- s32 func_802E4AD4(s32 arg0); // --- core2/sfx/instruments.c --- void func_8033543C(Struct81s *arg0); -// --- core2/fx/projectile_system.c --- +// --- core2/model/matrixrotate.c --- void func_8033F7F0(u8 indx, Gfx **gfx, Mtx **mtx, Vtx **vtx); // --- core2/spline_pathfollow.c --- @@ -3134,7 +3130,7 @@ void func_8034CF90(void *arg0, BKModel *arg1, s32 arg2); // --- core2/vtx/renderstart.c --- void setStruct6DsOpacity(Struct6Ds *arg0, s32 arg1); -// --- core2/anim/animcache.c --- +// --- core2/anim/anim_cache.c --- int animCache_getBoneTransformList(s16 index, BoneTransformList **arg1); // --- core2/anim/bonetransformlist.c --- @@ -3153,7 +3149,7 @@ bool chCollectible_collectRedFeather(ActorProp *arg0); bool chNipper_isInState7(s16 arg0[3]); // --- core2/actor_cubepropsystem.c --- -s32 codeA5BC0_getPositionAndSelectorOrRadius(void *arg0, s32 arg1[3]); +s32 codeA5BC0_getPositionAndReturnRadius(void *arg0, s32 arg1[3]); // --- core2/gamestate.c --- void itemscore_timeScores_fromSaveData(u16 *savedata); @@ -3163,20 +3159,25 @@ int savedata_8033CE40(void *buffer); int savedata_8033CC98(s32 filenum, void *buffer); void savedata_clear(void *savedata); -// --- core2/spawnqueue.c --- +// --- core2/spawn_queue.c --- void spawnQueue_defrag(void); -// --- port/MemShims.c --- -void bkmemcpy64(void *dest, void *src, s32 size); -void bkmemset64(void *dest, s32 value, s32 size); +void bkmemcpy64(void *dest, void *src, s32 size); // handwritten assembly code that performs an optimized 8 byte memcpy +void bkmemset64(void *dest, s32 value, s32 size); // handwritten assembly code that performs an optimized 8 byte memset +u32 bkGetSR(void); // handwritten assembly code that replicates the __osGetSR function // --- RBB/ch/engineparts.c --- f32 func_8038A6B8(ActorMarker *); -// --- core1/bamotor.c --- +// --- core1/io/ba_motor.c --- void baMotor_80250D94(f32, f32, f32); void baMotor_80250E94(f32, f32, f32, f32, f32, f32); +// --- core1/io/pfsmanager.c --- +OSContPad *func_8024F3F4(void); +OSMesgQueue *pfsManager_getFrameReplyQ(void); +void controller_copyFaceButtons(s32, s32 [6]); + // --- core1/memory.c --- void * bk_malloc(size_t size); void *bk_realloc(void* ptr, size_t size); @@ -3191,16 +3192,16 @@ void *assetcache_reload(enum asset_e assetId); // --- core2/sfx/trackmanager.c --- void musicKeepsPlaying(void); -// --- core2/ba/iFrame.c --- +// --- core2/ba/ba_eyeblink.c --- void baiFrame_startWithValue(f32); -// --- core2/ba/baeyes.c --- +// --- core2/ba/ba_eyes.c --- void baeyes_openSingleEye(s32, f32); -// --- core2/ba/falldamage.c --- +// --- core2/ba/ba_falldamage.c --- void bafalldamage_start(void); -// --- core2/ba/baflag.c --- +// --- core2/ba/ba_flag.c --- bool baflag_isFalse(enum misc_flag_e arg0); bool baflag_isTrue(enum misc_flag_e arg0); void baflag_clear(enum misc_flag_e arg0); @@ -3212,40 +3213,43 @@ void baflag_toggle(enum misc_flag_e arg0); f32 func_802915D8(void); f32 func_80291604(void); -// --- core2/ba/bakey.c --- +// --- core2/ba/ba_key.c --- int bakey_pressed(s32); u32 bakey_held(s32); -// --- core2/ba/marker.c --- +// --- core2/ba/ba_marker.c --- ActorMarker *baMarker_get(void); -// --- core2/ba/model.c --- +// --- core2/ba/ba_model.c --- f32 baModel_80292230(void); void baModel_80291A50(s32 arg0, f32* arg1); void baModel_80292078(s32, f32); void baModel_80292158(f32); -// --- core2/ba/physics.c --- +// --- core2/ba/ba_physics.c --- f32 get_slope_timer(void); +void baphysics_get_velocity(f32 dst[3]); +void baphysics_reset_gravity(void); +void baphysics_set_gravity(f32 gravity); -// --- core2/ba/playerposition.c --- -f32 playerPosition_getY(void); -void playerPosition_get(f32 dst[3]); +// --- core2/ba/ba_position.c --- +f32 player_getYPosition(void); +void _player_getPosition(f32 dst[3]); void playerPosition_addY(f32); -void playerPosition_setY(f32); +void player_setYPosition(f32); // --- core2/ba/ba_recoil.c --- f32 get_turbo_duration(void); void func_80294980(f32 arg0[3]); -// --- core2/ba/basfx.c --- +// --- core2/ba/ba_sfx.c --- void basfx_80299CF4(enum sfx_e, f32, s32); void basfx_80299D2C(enum sfx_e, f32, s32); void basfx_playJumpSfx(f32, f32); void basfx_playOwSfx(f32); void basfx_updateClockSfxSource(f32, f32); -// --- core2/ba/bastick.c --- +// --- core2/ba/ba_stick.c --- f32 bastick_distance(void); f32 bastick_getAngleRelativeToBanjo(void); f32 bastick_getY(void); @@ -3271,7 +3275,7 @@ void bs_setState(s32 state_id); void bs_updateState(void); void bs_setInterruptResponse(s32 arg0); -// --- core2/bs/bsStoredState.c --- +// --- core2/bs/bs_storedstate.c --- f32 bsStoredState_getLongLegTimer(void); f32 bsStoredState_getTurboTimer(void); void bsStoredState_setLongLegTimer(f32); @@ -3281,19 +3285,19 @@ void bsStoredState_setTurboTimer(f32); // --- core2/bs/walk.c --- f32 func_802B6F9C(void); -// --- core2/nc/camera_motor2.c --- +// --- core2/camera/camera_motor2.c --- void func_802BB3DC(s32, f32, f32); -// --- core2/nc/dynamicCam3.c --- +// --- core2/camera/dynamicCam3.c --- void func_802C1B20(f32); -// --- core2/nc/die.c --- -void ncbadie_func_802BF2C0(f32); +// --- core2/camera/dynamicCamD.c --- +void ncDynamicCamD_func_802BF2C0(f32); // --- core2/climb.c --- -f32 climb_getBottomY(void); -f32 climb_getTopY(void); -void climb_getBottom(f32 dst[3]); +f32 climbGetBottomY(void); +f32 climbGetTopY(void); +void climbGetBottom(f32 dst[3]); // --- core2/scorequeue/manager.c --- void func_802FAD64(enum item_e); @@ -3301,25 +3305,25 @@ void func_802FAD64(enum item_e); // --- core2/collision/hitboxdata.c --- enum marker_collision_func_type_e collision_getNextState(CollisionParams *arg0); -// --- core2/scorequeue/airscore.c --- +// --- core2/fx/airscore.c --- struct7s *fxairscore_new(s32); void fxairscore_draw(enum item_e, struct8s *, Gfx**, Mtx**, Vtx **); void fxairscore_free(s32, struct7s *); void fxairscore_update(enum item_e, struct7s *); -// --- core2/scorequeue/common1score.c --- +// --- core2/fx/common1score.c --- struct7s *fxcommon1score_new(enum asset_e item_id); void fxcommon1score_draw(enum item_e arg0, struct8s *arg1, Gfx **arg2, Mtx **arg3, Vtx **arg4); void fxcommon1score_free(enum item_e item_id, struct8s *); void fxcommon1score_update(enum item_e, struct8s *); -// --- core2/scorequeue/common2score.c --- +// --- core2/fx/common2score.c --- struct8s *fxcommon2score_new(enum item_e); void fxcommon2score_draw(enum item_e, struct8s *, Gfx**, Mtx**, Vtx **); void fxcommon2score_free(enum item_e, struct8s *); void fxcommon2score_update(s32, struct8s *); -// --- core2/scorequeue/common3score.c --- +// --- core2/fx/common3score.c --- void *fxcommon3score_new(enum item_e); void fxcommon3score_draw(enum item_e, void *, Gfx**, Mtx**, Vtx **); void fxcommon3score_free(enum item_e item_id, void *); @@ -3338,34 +3342,34 @@ void func_802927E0(f32, f32); void func_80292900(f32, f32); void func_80292974(f32, f32, f32); -// --- core2/fx/banjokazooiesign.c --- +// --- core2/fx/effect_spriteanim.c --- Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -// --- core2/scorequeue/healthscore.c --- +// --- core2/fx/healthscore.c --- struct7s *fxhealthscore_new(enum item_e); void fxhealthscore_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx); void fxhealthscore_free(enum item_e, struct8s *); void fxhealthscore_update(enum item_e, struct8s *); -// --- core2/scorequeue/honeycarrierscore.c --- +// --- core2/fx/honeycarrierscore.c --- struct7s *fxhoneycarrierscore_new(s32); void fxhoneycarrierscore_draw(s32, struct8s *, Gfx**, Mtx**, Vtx **); void fxhoneycarrierscore_free(s32, struct8s *); void fxhoneycarrierscore_update(s32, struct8s *); -// --- core2/scorequeue/jinjoscore.c --- +// --- core2/fx/jinjoscore.c --- struct8s *fxjinjoscore_new(enum item_e); void fxjinjoscore_draw(s32, struct8s *, Gfx**, Mtx**, Vtx **); void fxjinjoscore_free(enum item_e, struct8s *); void fxjinjoscore_update(enum item_e, struct8s *); -// --- core2/scorequeue/lifescore.c --- +// --- core2/fx/lifescore.c --- struct8s *fxlifescore_new(s32); void fxlifescore_draw(enum item_e, struct8s *, Gfx**, Mtx**, Vtx **); void fxlifescore_free(s32, struct8s *); void fxlifescore_update(enum item_e, struct8s *); -// --- core2/fx/effect_jiggy_list.c --- +// --- core2/fx/score_jiggylist.c --- void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]); // --- core2/fx/sparkle.c --- @@ -3383,7 +3387,7 @@ f32 barebound_get_vertical_velocity(void); f32 barebound_get_horizontal_velocity(void); f32 barebound_get_gravity(void); -// --- MMM/bathroom_particles.c --- +// --- core2/particle/bathroom.c --- void func_8029AD28(f32, s32); // --- core2/bs/player_spawn.c --- @@ -3405,14 +3409,14 @@ void pitch_setIdeal(f32); // --- core2/playerutils.c --- bool func_8028AED4(f32*, f32); -bool player_inWater(void); +int player_inWater(void); // --- core2/roll.c --- f32 roll_get(void); void roll_setAngularVelocity(f32, f32); void roll_setIdeal(f32); -// --- core2/fx/weather_leaves.c --- +// --- core2/sfx/playstate.c --- struct6s *func_802F8BE0(s32 arg0); // --- core2/sfx/randompitch.c --- @@ -3422,13 +3426,13 @@ void func_802F9F80(s32, f32, f32, f32); void func_802F9FD0(s32, f32, f32, f32); void func_802FA060(s32, s32, s32, f32); -// --- core2/fx/weather_rain.c --- +// --- core2/sfx/streamctrl.c --- struct3s *func_802F8264(s32 arg0); // --- core2/fx/projectile_anim.c --- void func_80352CF4(f32 *, f32 *, f32, f32); -// --- core2/timedfuncqueue.c --- +// --- core2/timed_funcqueue.c --- void func_80324D2C(f32, enum comusic_e); void func_80324D54(f32, enum sfx_e, f32, s32, f32 [3], f32, f32); void func_80324E38(f32, s32); @@ -3436,7 +3440,7 @@ void timed_exitStaticCamera(f32 time); void timed_playSfx(f32, enum sfx_e, f32, s32); void timed_setStaticCameraToNode(f32, s32); -// --- core2/vla.c --- +// --- core2/vector.c --- VLA * bk_vector_defrag(VLA *vla); VLA * bk_vector_new(u32 elemSize, u32 cnt); s32 bk_vector_getIndex(VLA *vla, void *element); @@ -3471,25 +3475,21 @@ Struct70s *func_8034C528(s32); Struct70s *func_8034C5AC(s32); s16 func_8034C50C(Struct70s *arg0); -// --- GV/gv_helpers.c --- -void rubeeEggPot_addedEggToPot(void); -s32 rubeeEggPot_getEggGoal(void); - -// --- core2/frame/auxbuffer.c --- -void picturebox_init(void); -void picturebox_free(void); -void picturebox_func_8030C180(void); -void picturebox_resetScissorBoxAndFramebuffer(Gfx **gfx, Mtx **mtx, Vtx **vtx); - -// --- core2/actor_cubepropsystem.c --- -void core2_A5BC0_drawUnknownMarkers(Gfx **gfx, Mtx **mtx, Vtx **vtx); +// --- core2/yaw.c --- +f32 yaw_get(void); +f32 yaw_getIdeal(void); +void yaw_applyIdeal(void); +void yaw_rotateTimed(f32); +void yaw_set(f32); +void yaw_setIdeal(f32); +void yaw_setVelocityBounded(f32, f32); -// --- core2/crc_bootvalidation.c --- -void codeCF5F0_init(void); -void codeCF5F0_triggerAntiTamperMeasurement(void); +// --- port/stub.c --- +float gu_sqrtf(float val); -#ifdef __cplusplus -} -#endif +// --- unknown source (no .c definition found) --- +void _guMtxIdentF_80245D44(float mf[4][4]); //static should NOT be here +void func_80241304(Mtx *m, float x, float y, float z); +BKModelBin * marker_loadModelBin(ActorMarker *marker); #endif // FUNCTIONS_H diff --git a/include/gc/gctransition.h b/include/gc/gctransition.h index d196963df..a891672a7 100644 --- a/include/gc/gctransition.h +++ b/include/gc/gctransition.h @@ -1,12 +1,8 @@ #ifndef __GC_TRANSITION__ #define __GC_TRANSITION__ -#ifdef __cplusplus -extern "C" { -#endif - void gctransition_defrag(void); -void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx); +void gctransition_draw(Gfx **arg0, Mtx **arg1, Vtx **arg2); void gctransition_8030BD4C(void); f32 gctransition_8030BD88(void); int gctransition_done(void); @@ -18,8 +14,4 @@ void gctransition_8030BEA4(s32 arg0); void gctransition_update(void); void gctransition_reset(void); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/model.h b/include/model.h index 3125d8c3e..282b9d5e8 100644 --- a/include/model.h +++ b/include/model.h @@ -4,10 +4,6 @@ #include #include "bool.h" -#ifdef __cplusplus -extern "C" { -#endif - /* Model header * Contains offsets relative to the start of the file to the various sections * If a section is not present in the file, the offset will be zero @@ -516,8 +512,4 @@ void model_free(BKModel *self); void gclights_recolor_vertices(BKVertexList *arg0, f32 position[3], f32 rotation[3], f32 scale, f32 arg4[3], BKVertexList *arg5); -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/prop.h b/include/prop.h index 564b2f560..c51c5c7d9 100644 --- a/include/prop.h +++ b/include/prop.h @@ -58,8 +58,6 @@ typedef struct model_prop_s{ u8 padB_3 :4; } ModelProp; -#define MODEL_ASSET_OFFSET 0x2D1 - // [port] On N64 the marker pointer is 4 bytes, so words[3] (12 bytes) covers // the entire struct. On 64-bit, the pointer is 8 bytes (16 bytes total). @@ -126,7 +124,7 @@ typedef struct actorMarker_s{ u32 unk40_22:1; u32 unk40_21:1; u32 unk40_20:1; - u32 unk40_19:1; // set for screen overlay sprites + u32 unk40_19:1; u32 pad40_18:19; Vec3fArray * unk44; BKModel * unk48; @@ -398,20 +396,13 @@ typedef struct { u32 pad10_0:1; } OtherNode; //can be inplace of NodeProp (see code7AF80_initCubeFromFile) size: 12 (0xC) bytes -// Distance scratch __cube_sort fills, one entry per prop. Cubes past this are -// left unsorted rather than overrunning it. -#define CUBE_SORT_SCRATCH_SIZE 0x400 - typedef struct cude_s{ s32 x:5; s32 y:5; s32 z:5; - // [port] were bitfields (:5/:6/:6). The 64th prop wrapped a count to 0, which - // realloc'd the prop array to nothing while live markers still pointed into it; - // unk0_4 is the front index of the node-prop partition and wrapped at 32. - u32 unk0_4:16; //node_prop_count - u16 prop1Cnt; - u16 prop2Cnt; + u32 prop1Cnt:6; + u32 prop2Cnt:6; + u32 unk0_4:5; //node_prop_count NodeProp *prop1Ptr; Prop *prop2Ptr; }Cube; diff --git a/include/structs.h b/include/structs.h index ce50d76ab..9652e2d14 100644 --- a/include/structs.h +++ b/include/structs.h @@ -8,10 +8,6 @@ #include "enums.h" #include "bool.h" -#ifdef __cplusplus -extern "C" { -#endif - // [port] Forward-declare struct tags used in function pointers inside structs below. // Without these, clang treats the struct tag as file-local to each struct definition. struct actor_s; @@ -437,7 +433,6 @@ typedef struct{ typedef struct struct_4D_s{ f32 unk0[3]; f32 unkC[3]; - u32 id; // [port] stable identity for frame interpolation }struct4Ds; typedef struct{ @@ -799,8 +794,4 @@ typedef struct { struct ALHeap *unkC; //heap u16 unk10; }Struct87s; -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/variables.h b/include/variables.h index fef76269d..cb494bd33 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1,10 +1,6 @@ #ifndef VARIABLES_H #define VARIABLES_H -#ifdef __cplusplus -extern "C" { -#endif - #define BAD_PI 3.141592654 #define BAD_DTOR (BAD_PI/ 180.0) #define M_TAU (2*M_PI) @@ -13,8 +9,4 @@ extern "C" { extern f32 climbPoleBottom[3]; extern f32 climbPoleTop[3]; -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/version.h b/include/version.h index 3efff4330..0f24f9c16 100644 --- a/include/version.h +++ b/include/version.h @@ -31,9 +31,6 @@ #define JP_EXCLUSIVE(body) #endif -// [port] AssetVersionRemap.h keys on usa0 -#define VER_SELECT(usa0, pal, usa1, jp) usa0 - #if VERSION == VERSION_USA_1_0 #define VER_SELECT(usa0, pal, usa1, jp) usa0 #elif VERSION == VERSION_PAL diff --git a/lib/ultralib/include/PR/gbi.h b/lib/ultralib/include/PR/gbi.h index 052fb33a8..4b21795f9 100644 --- a/lib/ultralib/include/PR/gbi.h +++ b/lib/ultralib/include/PR/gbi.h @@ -4579,7 +4579,7 @@ typedef union { #endif -// [port] Function declarations for GBI overrides in libultra.c +// [port] Function declarations for GBI overrides in stub.c // The decomp macros above are inside #if 0, so callers need prototypes // to avoid implicit-declaration truncation of 64-bit pointer arguments. #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) diff --git a/lib/ultralib/include/ultra_assert.h b/lib/ultralib/include/assert.h similarity index 100% rename from lib/ultralib/include/ultra_assert.h rename to lib/ultralib/include/assert.h diff --git a/libultraship b/libultraship index 2917d0f4f..2c63e7ede 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 2917d0f4fe62c579174561dcd34f327c9410bb72 +Subproject commit 2c63e7edef577cd2a3726ce24dfedd7f088f12ae diff --git a/port/anim/lighthouse_shrug b/port/anim/lighthouse_shrug deleted file mode 100644 index e751332baea9b383a8971b84151888ef31da6f35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 408 zcmZQzU|{fb^mYPL4Da`?y$8Y|Ht}Eq11C_i76T<1vX1nFdCTLvau7;J#-NenJPasg08i-8%dDv2Wcx}vz>zI$%BF(ih>~Cw6s);?sk0NdoStCxZOWxZ4JBp=H*Mi zeD8hl&+mNz00$53?;*e+mp=JP{j1+=y)^i;aJ7IJ0RE}#{Q7kyW4;7sQr_vQM(p- z{1?^7@xuG}Ki(+*B)&TBmRd*J?FhDJNuKM@=Kib3H#!b| zFQD&~e8GU@uTm1s;xCKG72=Te`5(oXT95L7Ww*fRyi*DUy?fVF%~xL`->C6s!u!~6 z3br_}cH4rTJNr8vpR4Te1NC2}*ZBGjjq{W#dCSx#udJ~SY^49)%f7S{-j77;Uef5| zG>|rC1!LZ)cuuf7$MJ}DbJ!l5PWdC%4MEeOc}z<%%ezjNf2A&Zg5saP_@`fzcq|J_ zU95!cw>8PTk<`H`uJgJh#+j(Wa$V}6)WcST^KLU~(|D)J*ln^MI&JYw^iPUs;RV^g zOCC*4W-6%#T$fB;>XFIlnyi;&bG-Rd{{zRT?^dL)gi==`$uD6^>bvBbIIPk0wW{b> z6a8wd>zCzMLahHdQJT!~d(A|!vGzEnc`(1Jc`|!!6dzh|9KVCG*d37;7 zD|{r7zQFgGf0m?fd%54ReihL_j5z;BRmLKP2c%UCwL|?Z$(xSFe&z^|^&GPIczylP z`G4mBm5BGXGRCK?G3URyF4&MfI3u_|ew}utuFcMM$l==C+^dUq1Wf}XaHWa9z z+I@R!ac*&xzb{N;Lz?%m@b>_oc~{GCX?ZVNwa5Bcw&r%>;mqk3ol3zDC8;bDgG zQB!!BCFc@Zo_6G1!WAAC6e;nhrGT+4=M*__DRX{~q#rJ6lxWf#^Ox~BxQM!|3-422 z%J%m>gmj;^a@agipV?JcuivVPwc-sxJx z$5`KNofn4Jf%81D^^WJEv3*?YdNaFbc9#6JZL#y`5}hCX_~apFp#1#ojdRxq%5Jc0 z%%3!0*)>1+(sY)&-NE|?%j{-==Qb>J_+Z_(SZ24w`eU=q$2gGM!iPEhAaz_GXW9U% z>#nT&DaT?-ttxd+NHPY{W88kEbqdTLbG|L|FOL9!{!lr z2X+wI_lsw)^v$8~D|ri8G`|1Do9g?03$~8PTfxr1r=AanzOUqIJla#=KY;I}e*F?m zjmSHJPR`IEmwL)7FXpD%Gp~NW1RnfQJKF0W{(k=Q!@ur(0k*?i$EN#_fA;OXef?PP WWt8=Ek1jmFcz*uWH|@(uQ2qz=^ZoV! diff --git a/port/models/lighthouse_GEO b/port/models/lighthouse_GEO deleted file mode 100644 index 166eeaa4ffea73290c9b3fece13e129f5d9f9b32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212 zcmZQzU|?|aaqVIq`=i+w43X#-0wRnsksnf!S*EyUOIU~l1f}iD`e}Uhr>m`rZAIIww?B|GmiS}{4>#@IP3HRi2z9xWwS$Kc) zIN!6u2MVtukN3+A@Gepyp}xPzw!Q`=+^tM=zPB9Wk1h>=JTnY+l03U zxA;eTnuLll6X{>c~E!{Q=l7 z6n>fZ$6!A}b!2~)_M2dTtMDT255b=Kr+utHb-YU)Zv)2Dc=vF;c>DtxpZhJEPcQvn zga7N2k8b+E3w!R@$UaZ|NA_K`AB_073a_Jm>faFgH_(3o^0Qa% zqw$7vytx?fRpGVtza94PsE+K1(7p-w?+dS?{Y=<*s*daj(f(1`50U&-(f(8STQ%+D z{q{N6=w8D3y>(r>|4t;0PS58C>QhOR+ak|zxGLKj=XaBn^Srl?dOG}fK^JRjACDK? zPl3P0t5{3_rSLx~x`zG>!9Re$SVO)7T+Zua75M|;gH@B~z~y}C?N2@re41+VJHQ`= z9$i5`5_~aq!IO^ye@Hd?5a{nfzu~AaVEs#=yGyk1MSLDsP5w6Yz0h5kso#P9T-CJS z0zOi7k$eaEaOln=`5(aLJn!lu-wK{rO}-mkzNg*Y6aIq`k3z_A4!lM+`3&&MqCUmcpzlilp zz6v3qe*@R=eaPQG!S51&nd83>-XJ>UZ$J1@)#N+Ddt^N!e|x~st0q4PenfQ0Upx4F zs>#!Qg#4xXNb|SKZx#Exv-*CXPFDHXL^n{!=Tm%sO?0dLn_^!}`}jOs0DeYz4S9V2 zECgqM$m8>77P!W%KlzR9ZwfPhkH0@@K03(Le1z{!4eCYKyH<}~U+^GP1pyR*QVPx83l9RbdKk;nD!jqHn9FY`(N zxE?+V&U})`_3$om=94_Ghj)N8pX6~p+y>5klE?LMnvV|h?qs9?neNZG^!@8hHu$xw z3#u#J1~1>2U5@%7?3kH@Vx3W|HI(&eJps+=Mea3Rnvbf_&DgX738mgkAb%NZULA4 zzFfu^iGNs+jQ_*PznsVGKb*Ar$6!CKg6oaru@muG0KT$<@i~?pXa12z`HSP#2Yabk zpK-L0;}^%P6VJaH_7?9rUhNof7Ryf|Ll;D0-~%|DLUO5}&%AI5hw@+bAT<7!wPcfeC2g~0t!25}P$j_7D{h=*? ztHDp6M?7oYVgnc3qH^KJL?y+et_KiJL?y+{(;>3JL?Cs{(#*2JL?Cs z{(wB|@3`KqKOnb$t`PcxtUn;P{;d%Dfvi6uxBkugfvi6uxBkugfvi6uxBkugfg9Op z{R92ee1!Ka%}3}L()TfN>mM7t>7Ty8!TwKpclY3Tcj!;7AAPPs`;B1#!EZx>@w9$+ z%mwmSz((PWxaR`7^~2*oCO-r&XV{{T$*q5G?<1F9N$$H&_mNxw-Q>vSuIc;u{WA39 zc77HT)(4}}4NAXX2=$75D^w@^-r9LusCYx`>w4Jh_chq3{eR$9;PU;p@oYZkUj?Q- zjBoR^`B?ql>O1|fanoV-WFET3IcWB8d4HuOdLa5A>F-*h#op@s9PHn8FF><@%Ylow z`abVEy>l(l?BDY4N=dZU_pRWwVQ>9dE4XN@?{nZk#`COy%Ylow`aYj@`gNF}^=J9y zN=dZU@2%i#-F#^FXRY9(t$xpe&vebu?9X!GqOE?(5%jMO*!z17DBlS$~!T7oEnt6vey5cw7FO67DzKFD;d(xu04px&PAr67Cahe>5fJ zmy)OaBZ+ullc;&lfqLellLx zUo@*e3xDayFn`t7pTJ*r8lP~VZT*eiZTip0 z>~Hlq)_2|WkUx!AR)15c^9%8``rG20u0O=r>T8Q{y8aMPtFJA-)=xm|{`nEsH7^TW!XHwk)NneGSsv1R&RjMrD@|6fz91O5O2 diff --git a/port/models/lighthouse_tex_0 b/port/models/lighthouse_tex_0 deleted file mode 100644 index dd7712dbb22e30163152cb041c5c395f17712929..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 zcma(~$&%t$5ai(Sclc-K?28ZnqnUwjV44P+O$b_I*9J%kNg$zp7h-D|(ZEdj?q6^* zwj+FWzE|}svr?&4DwX>E!*9RBllpT>T<&$B|1W+9<1hbI>Zerdw2xiy?Rq{RPhY>^ z4!h&=a{c4m>2SIxr#LvC-!|JY*e91OoZGj{*VE~oyk9O!@_xJQT`xSu+s%4^x_!SU zZ-?Y|0sn5dPZDq?JI6GWT^z6D-W^OwQw_s5RL!ysBk*0{cWuLP z+;tRfcl)hstyU}5Q01j+IhG%U(b~5xUDaKG9YK;}X}YFbmbTI?$Fw~^3?t7rG|h5D z&+!~lQB+ki?%}GcYHkoj>%g-N-S*?aGE{LPtyD#^99>i3PnPGou4NjwY5I|C$ihNd zYPu>Lrn*{6lDLEnIJ#@;wxcfjxuz-FY9X#vc_E78d@e0zQ4kbU2bV0)L}?)@i@6}L zmi&z4d43@;W-KSk@^T?bf*|vvAo9GVECqJT@`5NU!gMl&h}o2#bAmEvS&o}Q20t0I z+>DzGEHmXLk>@CK%r{C-LJ9xL>g&l@)OT|*D1R`jFLZR>kb;onz2~Ys-hx(My=kj0jfX8e$ zpUc6J%V+NmG_WGl2BNLnfU`r$2uD1oso%zX9}L_Cx;* D4uaQS diff --git a/port/models/lighthouse_tex_1 b/port/models/lighthouse_tex_1 deleted file mode 100644 index 4313a78346eb58bdee5df841b6c09ebfbc6faf21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 zcma)*-%nCu7{{NB*5A=>i#1$PcWqsCXG1Nj)r}LT7kbf#OGVi9#%yUqZc4~fTdcS+ z-AteqHf&Ct4iW`Z87Bn=M*I-TBXHiA-uE0mqIS`;`HrbVIrLllslX>E0$=LLT|R83_trhF!Ork-OnKl>!I;VAki$GOn#ccV;VU=U6@&-X|1 z$){F}9NPUwoObJUZsK&gKD0IZ*gR2B9m4yb{(jH?8P1p$Z@y}Hf%*9Iay-vlB7Pqt z-1N;Lx&D?2%;$1>QhusGRI2bx{uqtW%DK(CmbLA=v7)HzbEcO z$GWgDl#BDnxy9~=PrKP^1+=W3@c5|gN?(ZR!5O!<*^yx9mC)!Z3hL?G&sCsZqlP5x zYOOm{@HB#Ip01`4?3@ysyd)n*tg0UGLDBaN9ytGq28j8E;LwwyV1e_u!M!hZbV6_| zEufgrVSM22QCTC1^J}2Skv-w-9Z)%u!c?Bxp1@o{OAOu1qmrqQm^kq3Brs3-Ze#MlX?##KZyM%v2R!ITZO&XIMQfq3r=_g=y!Q{{^aG8omGk diff --git a/port/models/lighthouse_tex_2 b/port/models/lighthouse_tex_2 deleted file mode 100644 index 5a1a396cd86cdba73b1dfd59c83a625eb3da2fc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 zcmb_b$!)|i4Aeng)UhpWGkNEeN199vDJ3nWg$%W}Y}pR52tq)r1NGSp_ z1GIHMrkqQyrDRUQPXMGt;!@iU(Q3({*aHmtluOSF;#M<9Z$}@ReB@nP04ca}1OxUd zEdW$l2(4B?AwLH-(e-p RFi!tGU9=vqo4)_~ - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 deleted file mode 100644 index 42e911411..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_0 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 deleted file mode 100644 index 259b27c4e..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_1 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 deleted file mode 100644 index dc680a34a..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_2 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 deleted file mode 100644 index a134560fb..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_3 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 deleted file mode 100644 index 65134138f..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_4 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 deleted file mode 100644 index 3b458b736..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_5 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 b/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 deleted file mode 100644 index b21f2c4b7..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_tri_6 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 deleted file mode 100644 index 9f4483ec6..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_0 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 deleted file mode 100644 index 9339e42f0..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_1 +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 deleted file mode 100644 index e1122533a..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_2 +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 deleted file mode 100644 index 29c025d0f..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_3 +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 deleted file mode 100644 index c3c88918b..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_4 +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 deleted file mode 100644 index 70117ba12..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_5 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 b/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 deleted file mode 100644 index 70117ba12..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoItemDL_vtx_6 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL b/port/objects/object_archipelago_item/gArchipelagoJunkDL deleted file mode 100644 index 4beef5eb3..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 deleted file mode 100644 index f2137f135..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_0 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 deleted file mode 100644 index ae92327e4..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_1 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 deleted file mode 100644 index bbbc96439..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_2 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 deleted file mode 100644 index 6d11e6b1c..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_3 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 deleted file mode 100644 index 827df8c0d..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_4 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 deleted file mode 100644 index 6714bf7a4..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_5 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 deleted file mode 100644 index 3980be483..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_tri_6 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 deleted file mode 100644 index 9f4483ec6..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_0 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 deleted file mode 100644 index 9339e42f0..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_1 +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 deleted file mode 100644 index e1122533a..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_2 +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 deleted file mode 100644 index 29c025d0f..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_3 +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 deleted file mode 100644 index c3c88918b..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_4 +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 deleted file mode 100644 index 70117ba12..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_5 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 b/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 deleted file mode 100644 index 70117ba12..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoJunkDL_vtx_6 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL deleted file mode 100644 index ed07b28c9..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 deleted file mode 100644 index 1a679a463..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_0 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 deleted file mode 100644 index f49d299ef..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_1 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 deleted file mode 100644 index ea82a9347..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_2 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 deleted file mode 100644 index 8cfca6524..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_3 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 deleted file mode 100644 index 639c5aea4..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_4 +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 deleted file mode 100644 index 99a4852cb..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_5 +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 deleted file mode 100644 index e7ab8546c..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_6 +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 deleted file mode 100644 index 0f50ed430..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_tri_7 +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 deleted file mode 100644 index 9f4483ec6..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_0 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 deleted file mode 100644 index 9339e42f0..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_1 +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 deleted file mode 100644 index e1122533a..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_2 +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 deleted file mode 100644 index 29c025d0f..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_3 +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 deleted file mode 100644 index c3c88918b..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_4 +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 deleted file mode 100644 index 70117ba12..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_5 +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 deleted file mode 100644 index b76b5b312..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_6 +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 b/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 deleted file mode 100644 index b76b5b312..000000000 --- a/port/objects/object_archipelago_item/gArchipelagoProgressiveDL_vtx_7 +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black deleted file mode 100644 index 7ef279db5..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_black +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue deleted file mode 100644 index 770d70e48..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_blue +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green deleted file mode 100644 index 9a57f3f8c..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_green +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange deleted file mode 100644 index c3da3eff1..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_orange +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline deleted file mode 100644 index d39d1af92..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_outline +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink deleted file mode 100644 index e3b896b02..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_pink +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple deleted file mode 100644 index 64f362026..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_purple +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red deleted file mode 100644 index 8cc9fec5e..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_red +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow b/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow deleted file mode 100644 index 1b0d4be92..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoItemDL_yellow +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk deleted file mode 100644 index 7ef279db5..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_black_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk deleted file mode 100644 index b8f17f3bf..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_blue_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk deleted file mode 100644 index 05312bc76..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_green_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue deleted file mode 100644 index a55a1459a..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_blue +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green deleted file mode 100644 index 20d667aa3..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_green +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange deleted file mode 100644 index ad2a5ac38..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_orange +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline deleted file mode 100644 index d39d1af92..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_outline +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink deleted file mode 100644 index a3d546483..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_pink +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red deleted file mode 100644 index 78236fa28..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_red +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow deleted file mode 100644 index 8def121b7..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_grey_yellow +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk deleted file mode 100644 index 17867ed9c..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_orange_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk deleted file mode 100644 index 7a880f3e9..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_purple_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk deleted file mode 100644 index 20b763643..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_red_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk b/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk deleted file mode 100644 index 7e88e53d7..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoJunkDL_yellow_junk +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive deleted file mode 100644 index fa76abb08..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_arrow_gold_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive deleted file mode 100644 index 7ef279db5..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_black_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive deleted file mode 100644 index 770d70e48..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_blue_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive deleted file mode 100644 index 9a57f3f8c..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_green_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive deleted file mode 100644 index c3da3eff1..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_orange_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow deleted file mode 100644 index c41b05db9..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_arrow +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue deleted file mode 100644 index c9073d0cf..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_blue +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green deleted file mode 100644 index 84e26fe7a..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_green +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange deleted file mode 100644 index 076acfe28..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_orange +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline deleted file mode 100644 index d39d1af92..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_outline +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink deleted file mode 100644 index e3b896b02..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_pink +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red deleted file mode 100644 index 930fb41e6..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_red +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow deleted file mode 100644 index 383d9441c..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_progressive_yellow +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive deleted file mode 100644 index 64f362026..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_purple_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive deleted file mode 100644 index 8cc9fec5e..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_red_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive b/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive deleted file mode 100644 index 1b0d4be92..000000000 --- a/port/objects/object_archipelago_item/mat_gArchipelagoProgressiveDL_yellow_progressive +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/port/objects/object_archipelago_item/model.xml b/port/objects/object_archipelago_item/model.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/textures/icons/g2ShipIcon.png b/port/textures/icons/g2ShipIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..49785b681a18951b5611a04a8f594bea3bcab154 GIT binary patch literal 13286 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 z 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 #include "functions.h" #include "variables.h" @@ -13,7 +13,7 @@ extern ActorInfo chPinkEggMedium; extern ActorInfo chPinkEggSmall; extern ActorInfo chPinkEggSmallest; extern ActorInfo chMudHut; -extern ActorInfo gChTanktup; +extern ActorInfo chTanktup; extern ActorInfo gChTanktupLegFrontLeft; extern ActorInfo gChTanktupLegBackLeft; extern ActorInfo gChTanktupLegFrontRight; @@ -23,7 +23,7 @@ extern ActorInfo gChYellowFlibbit; extern ActorInfo D_80390960; extern ActorInfo gChYumblie; extern ActorInfo gChVile; -extern ActorInfo gChTiptup; +extern ActorInfo chTiptup; extern ActorInfo chChoirTurtleYellow; extern ActorInfo chChoirTurtleCyan; extern ActorInfo chChoirTurtleBlue; @@ -35,7 +35,7 @@ extern ActorInfo chLargeCrocodile; extern ActorInfo chLongSwampSwitch; extern ActorInfo chShortSwampSwitch; -void bgs_updateSpawnableActors(void){//bgs_updateSpawnableActors +void BGS_func_8038F1E0(void){//bgs_updateSpawnableActors spawnableActorList_add(&gChCroctus, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_3);//croctus spawnableActorList_add(&gChFlibbit, actor_new, ACTOR_FLAG_UNKNOWN_25 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_0); //flibbit spawnableActorList_add(&chPinkEggLargest, actor_new, ACTOR_FLAG_UNKNOWN_10); //pink_egg_largest @@ -44,7 +44,7 @@ void bgs_updateSpawnableActors(void){//bgs_updateSpawnableActors spawnableActorList_add(&chPinkEggSmall, actor_new, ACTOR_FLAG_UNKNOWN_10); //pink_egg_small spawnableActorList_add(&chPinkEggSmallest, actor_new, ACTOR_FLAG_UNKNOWN_10); //pink_egg_smallest spawnableActorList_add(&chMudHut, actor_new, ACTOR_FLAG_NONE); //mudhut_top - spawnableActorList_add(&gChTanktup, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_3);//tanktup + spawnableActorList_add(&chTanktup, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_3);//tanktup spawnableActorList_add(&gChTanktupLegFrontLeft, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_2);//tanktup_leg spawnableActorList_add(&gChTanktupLegBackLeft, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_2);//tanktup_leg spawnableActorList_add(&gChTanktupLegFrontRight, actor_new, ACTOR_FLAG_UNKNOWN_26 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_2);//tanktup_leg @@ -54,7 +54,7 @@ void bgs_updateSpawnableActors(void){//bgs_updateSpawnableActors spawnableActorList_add(&D_80390960, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&gChYumblie, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7); //yumblie spawnableActorList_add(&gChVile, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_1); //mr. vile - spawnableActorList_add(&gChTiptup, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup + spawnableActorList_add(&chTiptup, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup spawnableActorList_add(&chChoirTurtleYellow, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup_chiorMember spawnableActorList_add(&chChoirTurtleCyan, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup_chiorMember spawnableActorList_add(&chChoirTurtleBlue, actor_new, ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_3 ); //tiptup_chiorMember diff --git a/src/BGS/bss_pad.c b/src/BGS/bss_pad.c new file mode 100644 index 000000000..cc6b75e24 --- /dev/null +++ b/src/BGS/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_BGS_D_80391230[0x10]; diff --git a/src/BGS/ch/choirturtle.c b/src/BGS/ch/choir_turtle.c similarity index 95% rename from src/BGS/ch/choirturtle.c rename to src/BGS/ch/choir_turtle.c index fe30576bc..6c358bcb3 100644 --- a/src/BGS/ch/choirturtle.c +++ b/src/BGS/ch/choir_turtle.c @@ -1,4 +1,4 @@ -// BanjoDecomp: BGS/ch/choirturtle.c +// BanjoDecomp: code_3030.c #include #include "functions.h" #include "variables.h" @@ -62,7 +62,7 @@ void chChoirTurtle_ow2(ActorMarker *marker, ActorMarker *other_marker){ } Actor *chChoirTurtle_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - modelRender_setAppendageVisibility(4, marker->id - 0x19A); + func_8033A45C(4, marker->id - 0x19A); return actor_draw(marker, gfx, mtx, vtx); } @@ -96,7 +96,7 @@ void chChoirTurtle_update(Actor *this) { } } if (this->state == 1) { - if (local->tiptup_marker != NULL && (chTiptup_getUnkB(local->tiptup_marker) == local->unk0)) { + if (local->tiptup_marker != NULL && (func_80388E70(local->tiptup_marker) == local->unk0)) { chChoirTurtle_setState(this, 2); } } diff --git a/src/BGS/ch/croctus.c b/src/BGS/ch/croctus.c index 6c429088b..b589e5a60 100644 --- a/src/BGS/ch/croctus.c +++ b/src/BGS/ch/croctus.c @@ -1,14 +1,9 @@ -// BanjoDecomp: BGS/ch/croctus.c +// BanjoDecomp: croctus.c #include #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - -// Anchor: set while replaying a teammate's feed; suppresses camera/dialog + rebroadcast. -static s32 sCroctusRemote = 0; - -extern void func_80328748(AnimCtrl *, f32, f32); +extern s32 func_80328748(AnimCtrl *, f32, f32); extern void func_8028F94C(s32, f32[3]); extern void func_80324CFC(f32, enum comusic_e, s32); extern void func_803289EC(Actor *, f32, s32); @@ -16,15 +11,15 @@ extern void func_80326310(Actor *); extern void actor_setOpacity(Actor *, s32); extern void gcStaticCamera_activate(s32 arg0); + + void func_80387D18(ActorMarker *, u32); Actor *chCroctus_draw(ActorMarker *, Gfx**, Mtx **, Vtx**); -void chCroctus_update(Actor *this); +void chCroctus_updat(Actor *this); /* .data */ s16 D_803907B0[4] = {0x15, 0x16, 0x17, 0x18}; - ActorMarker *bgs_D_803907B8[5] = {NULL}; - ActorAnimationInfo chCroctusAnimations[] = { {0x000, 0.0f}, {0x14B, 3.3e+7f}, @@ -34,23 +29,12 @@ ActorAnimationInfo chCroctusAnimations[] = { {0x14B, 2.0f}, {0x14B, 2.0f} }; - -ActorInfo gChCroctus ={ - MARKER_FC_CROCTUS, ACTOR_1FA_CROCTUS, ASSET_425_MODEL_CROCTUS, +ActorInfo gChCroctus ={MARKER_FC_CROCTUS, ACTOR_1FA_CROCTUS, ASSET_425_MODEL_CROCTUS, 1, chCroctusAnimations, - chCroctus_update, actor_update_func_80326224, chCroctus_draw, + chCroctus_updat, actor_update_func_80326224, chCroctus_draw, 0, 0, 0.0f, 0 }; -enum chCroctusState { - CHCROCTUS_STATE_1_MOUTH_CLOSED = 1, - CHCROCTUS_STATE_2_MOUTH_OPENING, - CHCROCTUS_STATE_3_MOUTH_OPEN, - CHCROCTUS_STATE_4_MOUTH_CLOSING, - CHCROCTUS_STATE_5_FED, - CHCROCTUS_STATE_6_DESPAWN, -}; - /* .code */ void func_80387C90(Actor *arg0){ anctrl_setDuration(arg0->anctrl, 0.4 + 0.9999999999999999 * ((f32)(5 - arg0->actorTypeSpecificField) * 0.25)); @@ -62,7 +46,7 @@ void func_80387D18(ActorMarker * arg0, u32 arg1){ this = marker_getActor(arg0); nextActPtr = spawn_child_actor(0x6A, &this); - nextActPtr->state = CHCROCTUS_STATE_2_MOUTH_OPENING; + nextActPtr->state = 2; nextActPtr->actorTypeSpecificField = 0x8C; nextActPtr->lifetime_value = 3.0f; nextActPtr->unk38_31 = arg1; @@ -80,16 +64,18 @@ void *chCroctus_jiggySpawn(ActorMarker * arg0){ spawnPos[1] = this->position_y; spawnPos[2] = this->position_z; marker->propPtr->unk8_3 = 0; - gcStaticCamera_activate(0x19); //related to temporary switch to fixed camera + gcStaticCamera_activate(0x19); jiggy_spawn(JIGGY_22_CROCTUS, spawnPos); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); + return NULL; } -void func_80387E00(ActorMarker *arg0){ - Actor * this = marker_getActor(arg0); +void func_80387E00(uintptr_t arg0){ + ActorMarker *marker = reinterpret_cast(ActorMarker *, arg0); + Actor * this = marker_getActor(marker); func_803262E4(this); - __spawnQueue_add_2((GenFunction_2)func_80387D18, reinterpret_cast(uintptr_t, arg0), 0x1E); + __spawnQueue_add_2((void (*)(void))func_80387D18, (uintptr_t)marker, 0x1E); } void func_80387E40(ActorMarker * arg0){ @@ -98,24 +84,22 @@ void func_80387E40(ActorMarker * arg0){ if(arg0); } -void chCroctus_activateNextCroctus(ActorMarker *caller, enum asset_e text_id, s32 arg2){ +void func_80387E68(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this; - if(text_id == VER_SELECT(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0x9C9, 0, 0)){ + if(text_id == 0xC86){ this = marker_getActor(caller); timed_playSfx(0.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); timed_playSfx(1.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); func_80324CFC(0.4f, COMUSIC_43_ENTER_LEVEL_GLITTER, 22000); func_80324D2C(4.5f, COMUSIC_43_ENTER_LEVEL_GLITTER); - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_5_FED, 0.79f, 1); + subaddie_set_state_with_direction(this, 5, 0.79f, 1); func_80326310(this); //did not disappear when moved, after cutscene still there with collision but broken - bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = TRUE; - timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, reinterpret_cast(uintptr_t, bgs_D_803907B8[this->actorTypeSpecificField])); - if(!sCroctusRemote){ - timed_setStaticCameraToNode(0.8f, 9); - func_80324DBC(3.4f, VER_SELECT(ASSET_C87_DIALOG_CROCTUS_SECOND_SPAWN, 0x9CA, 0, 0), 0xE, NULL, NULL, chCroctus_activateNextCroctus, NULL); - } - __spawnQueue_add_2((GenFunction_2) func_80387D18, reinterpret_cast(uintptr_t, this->marker), 0x46); + bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = true; + timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, (uintptr_t)bgs_D_803907B8[this->actorTypeSpecificField]); + timed_setStaticCameraToNode(0.8f, 9); + func_80324DBC(3.4f, 0xC87, 0xE, NULL, NULL, func_80387E68, NULL); + __spawnQueue_add_2((void (*)(void))func_80387D18, (uintptr_t)this->marker, 0x46); } else{ timed_exitStaticCamera(0.0f); @@ -123,7 +107,7 @@ void chCroctus_activateNextCroctus(ActorMarker *caller, enum asset_e text_id, s3 } } -void chCroctus_update(Actor *this){ +void chCroctus_updat(Actor *this){ int j; if(!this->volatile_initialized){ @@ -131,12 +115,12 @@ void chCroctus_update(Actor *this){ marker_despawn(this->marker); return; } - this->volatile_initialized = TRUE; + this->volatile_initialized = true; if(bgs_D_803907B8[this->actorTypeSpecificField - 1] == 0){ bgs_D_803907B8[this->actorTypeSpecificField - 1] = this->marker; - for(j = this->actorTypeSpecificField; j < 6; j++){ + for(j = this->actorTypeSpecificField; j < 5; j++){ if(bgs_D_803907B8[j] != NULL){ - bgs_D_803907B8[j]->propPtr->isNotFeatherEggOrNote = FALSE; + bgs_D_803907B8[j]->propPtr->isNotFeatherEggOrNote = false; actor_setOpacity(marker_getActor(bgs_D_803907B8[j]), 0); } }//L803880C8 @@ -145,130 +129,105 @@ void chCroctus_update(Actor *this){ if(j >= 0){ - this->marker->propPtr->isNotFeatherEggOrNote = FALSE; + this->marker->propPtr->isNotFeatherEggOrNote = false; actor_setOpacity(this, 0); } - this->marker->propPtr->unk8_3 = TRUE; + this->marker->propPtr->unk8_3 = true; }//L80388144 func_803289EC(this, 0.0f, 1); this->lifetime_value = 0.0f; return; }//L80388160 - // Anchor: teammate finished the chain — despawn our heads unless mid-cutscene (state 5/6). - if(jiggyscore_isSpawned(JIGGY_22_CROCTUS) && this->state != 5 && this->state != 6){ - marker_despawn(this->marker); - return; - } - - // Anchor: replay a teammate's feed of the active head (field 5 handled by the despawn above). - if (this->actorTypeSpecificField < 5 && this->state != 5 && this->state != 6 && !this->unk38_31 - && this->marker->propPtr->isNotFeatherEggOrNote - && (port_puzzleStep_get(ANCHOR_PUZZLE_BGS_CROCTUS) & (1 << (this->actorTypeSpecificField - 1)))) { - sCroctusRemote = 1; - this->unk38_31 = 1; - } - if(this->unk38_31){ - if ((this->state != CHCROCTUS_STATE_5_FED) && (this->state != CHCROCTUS_STATE_6_DESPAWN)) { - if (!sCroctusRemote) { - port_puzzleStep_orBits(ANCHOR_PUZZLE_BGS_CROCTUS, 1 << (this->actorTypeSpecificField - 1)); - } + if ((this->state != 5) && (this->state != 6)) { coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); //TODO ISSUE HERE if (this->actorTypeSpecificField == 1) { - // Anchor: func_8028F94C = look-at, released only by the dialog we skip; don't push when replaying. - if (!sCroctusRemote) { - func_8028F94C(2, this->position); - } - if (sCroctusRemote) { - chCroctus_activateNextCroctus(this->marker, VER_SELECT(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0x9C9, 0, 0), 0); - } else { - gcdialog_showDialog(VER_SELECT(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0x9C9, 0, 0), 0xE, this->position, this->marker, chCroctus_activateNextCroctus, NULL); - } - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_6_DESPAWN, 0.79f, 1); + func_8028F94C(2, this->position); + gcdialog_showDialog(ASSET_C86_DIALOG_CROCTUS_FIRST_SUCCESS, 0xE, this->position, this->marker, func_80387E68, NULL); + subaddie_set_state_with_direction(this, 6, 0.79f, 1); } else { - timed_playSfx(0.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); - timed_playSfx(1.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); + timed_playSfx(0.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); //0.4f + timed_playSfx(1.4f, SFX_C9_PAUSEMENU_ENTER, 1.0f, 32000); //1.4f func_80324CFC(0.4f, COMUSIC_43_ENTER_LEVEL_GLITTER, 22000); func_80324D2C(4.5f, COMUSIC_43_ENTER_LEVEL_GLITTER); - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_5_FED, 0.79f, 1); + subaddie_set_state_with_direction(this, 5, 0.79f, 1); if (this->actorTypeSpecificField == 5) { - timedFunc_set_1(0.9f, (GenFunction_1) func_80387E40, reinterpret_cast(uintptr_t, this->marker)); + timedFunc_set_1(0.9f, (GenFunction_1) func_80387E40, (uintptr_t)this->marker); } else { func_80326310(this); } if (this->actorTypeSpecificField < 5) { - bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = TRUE; - timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, reinterpret_cast(uintptr_t, bgs_D_803907B8[this->actorTypeSpecificField])); - if (!sCroctusRemote) gcStaticCamera_activate(D_803907B0[this->actorTypeSpecificField-1]); + bgs_D_803907B8[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = true; + timedFunc_set_1(1.1f, (GenFunction_1)func_80387E00, (uintptr_t)bgs_D_803907B8[this->actorTypeSpecificField]); + gcStaticCamera_activate(D_803907B0[this->actorTypeSpecificField-1]); } else { - timedFunc_set_1(0.8f, (GenFunction_1)chCroctus_jiggySpawn, reinterpret_cast(uintptr_t, this->marker)); + timedFunc_set_1(0.8f, (GenFunction_1)chCroctus_jiggySpawn, (uintptr_t)this->marker); } - __spawnQueue_add_2((GenFunction_2)func_80387D18, reinterpret_cast(uintptr_t, this->marker), 0x46); + __spawnQueue_add_2((void (*)(void))func_80387D18, (uintptr_t)this->marker, 0x46); } } }//L80388348 - sCroctusRemote = 0; switch(this->state){ - case CHCROCTUS_STATE_1_MOUTH_CLOSED:// L80388370 - this->lifetime_value += time_getDelta(); - if(0.7 <= this->lifetime_value){ - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_2_MOUTH_OPENING, 0.0f, 1); - func_80387C90(this); - this->lifetime_value = 0.0f; - func_80324D54(0.1f, SFX_D0_GRIMLET_SQUEAK, 1.0f, 0x7530, this->position, 0.0f, 1800.0f); - } - break; - - case CHCROCTUS_STATE_2_MOUTH_OPENING:// L80388400 - if(actor_animationIsAt(this, 0.62f)){ - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_3_MOUTH_OPEN, 0.62f, 1); - } - break; - - case CHCROCTUS_STATE_3_MOUTH_OPEN:// L80388434 - this->lifetime_value += time_getDelta(); - if( this->lifetime_value >= 0.13 + 0.7/4 * (5 - this->actorTypeSpecificField)){ - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_4_MOUTH_CLOSING, 0.62f, 1); - func_80387C90(this); - this->lifetime_value = 0.0f; - func_80324D54(0.3f, SFX_406_GOLD_BULLION_TALKING, 1.0f, 0x55f0, this->position, 0.0f, 1800.0f); - } - break; + case 1:// L80388370 + this->lifetime_value += time_getDelta(); + if(0.7 <= this->lifetime_value){ + subaddie_set_state_with_direction(this, 2, 0.0f, 1); + func_80387C90(this); + this->lifetime_value = 0.0f; + func_80324D54(0.1f, SFX_D0_GRIMLET_SQUEAK, 1.0f, 0x7530, this->position, 0.0f, 1800.0f); + } + break; - case CHCROCTUS_STATE_4_MOUTH_CLOSING:// L8038850C - if(actor_animationIsAt(this, 0.0f)){ - subaddie_set_state_with_direction(this, CHCROCTUS_STATE_1_MOUTH_CLOSED, 0.0f, 1); - } - break; + case 2:// L80388400 + if(actor_animationIsAt(this, 0.62f)){ + subaddie_set_state_with_direction(this, 3, 0.62f, 1); + } + break; + + case 3:// L80388434 + this->lifetime_value += time_getDelta(); + if( this->lifetime_value >= 0.13 + 0.7/4 * (5 - this->actorTypeSpecificField)){ + subaddie_set_state_with_direction(this, 4, 0.62f, 1); + func_80387C90(this); + this->lifetime_value = 0.0f; + func_80324D54(0.3f, 0x406, 1.0f, 0x55f0, this->position, 0.0f, 1800.0f); + } + break; - case CHCROCTUS_STATE_5_FED:// L80388538 - func_80328748(this->anctrl, 0.79f, 0.97f); - if( actor_animationIsAt(this, 0.84f) - && !anctrl_isPlayedForwards(this->anctrl) - && func_802BB270() - ){ - gcsfx_playWithPitch(SFX_C8_CRUNCH, randf2(0.93f, 1.07f), 22000); - } - break; + case 4:// L8038850C + if(actor_animationIsAt(this, 0.0f)){ + subaddie_set_state_with_direction(this, 1, 0.0f, 1); + } + break; + + case 5:// L80388538 + func_80328748(this->anctrl, 0.79f, 0.97f); + if( actor_animationIsAt(this, 0.84f) + && !anctrl_isPlayedForwards(this->anctrl) + && func_802BB270() + ){ + gcsfx_playWithPitch(SFX_C8_CRUNCH, randf2(0.93f, 1.07f), 22000); + } + break; - case CHCROCTUS_STATE_6_DESPAWN:// L803885B0 - func_80328748(this->anctrl, 0.79f, 0.97f); + case 6:// L803885B0 + func_80328748(this->anctrl, 0.79f, 0.97f); - break; + break; } } void BGS_func_803885DC(void){ s32 i; - for(i = 0; i < 5; i++) + for(i = 0; i<5; i++) bgs_D_803907B8[i] = 0; } Actor *chCroctus_draw(ActorMarker *this, Gfx** gdl, Mtx ** mptr, Vtx **vtx){ Actor *thisActor; thisActor = marker_getActor(this); - modelRender_setAppendageVisibility(1, thisActor->actorTypeSpecificField); + func_8033A45C(1, thisActor->actorTypeSpecificField); return actor_draw(this, gdl, mptr, vtx); } diff --git a/src/BGS/ch/frogminigame.c b/src/BGS/ch/frogminigame.c index d4752a841..964e069a9 100644 --- a/src/BGS/ch/frogminigame.c +++ b/src/BGS/ch/frogminigame.c @@ -4,7 +4,7 @@ #include "variables.h" -void chFrogMinigame_update(Actor *); +void chfrogminigame_update(Actor *); void chFrogMinigame_setState(Actor * arg0, u32 next_state); void func_8025A58C(u32, u32); void timed_exitStaticCamera(f32); @@ -12,20 +12,11 @@ void timed_exitStaticCamera(f32); ActorInfo chFrogMinigame = {MARKER_C4_YELLOW_FLIBBIT_CTRL, ACTOR_136_YELLOW_FLIBBIT_CONTROLLER, 0x00, 0x00, NULL, - chFrogMinigame_update, NULL, func_80325340, + chfrogminigame_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; -enum chFrogMinigameState { - CH_FROG_MINIGAME_STATE_1_IDLE = 1, - CH_FROG_MINIGAME_STATE_2_ENTER_BATTLE, - CH_FROG_MINIGAME_STATE_3_BATTLE, - CH_FROG_MINIGAME_STATE_4_COMPLETE, - CH_FROG_MINIGAME_STATE_5_SPAWN_JIGGY, - CH_FROG_MINIGAME_STATE_6_DESPAWN -}; - /* .bss */ u8 D_80391240[4]; @@ -46,7 +37,7 @@ static void __chFrogMinigame_textCallback(ActorMarker *marker, enum asset_e text } } -void chFrogMinigame_stopFlibbitFightMusic(Actor * arg0){ +void func_8038CBB4(Actor * arg0){ if(!arg0->bgs_6730.unk4) return; func_8025A58C(-1, 400); @@ -66,13 +57,13 @@ void chFrogMinigame_setState(Actor * arg0, u32 next_state){ mapSpecificFlags_set(0x10, 1); if(!fileProgressFlag_get(FILEPROG_1B_MET_YELLOW_FLIBBITS)){ fileProgressFlag_set(FILEPROG_1B_MET_YELLOW_FLIBBITS, 1); - gcdialog_showDialog(VER_SELECT(ASSET_C81_DIALOG_YELLOW_FLIBBITS_MEET, 0x9C4, 0, 0), 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); + gcdialog_showDialog(ASSET_C81_DIALOG_YELLOW_FLIBBITS_MEET, 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); }else{ if(!arg0->bgs_6730.unk8){ - gcdialog_showDialog(VER_SELECT(ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0x9C6, 0, 0), 0x4, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); + gcdialog_showDialog(ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0x4, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); } else{ - __chFrogMinigame_textCallback(arg0->marker, VER_SELECT(ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0x9C6, 0, 0), 0); + __chFrogMinigame_textCallback(arg0->marker, ASSET_C83_DIALOG_YELLOW_FLIBBITS_RETURN, 0); return; } } @@ -98,12 +89,12 @@ void chFrogMinigame_setState(Actor * arg0, u32 next_state){ } } else{ - chFrogMinigame_stopFlibbitFightMusic(arg0); + func_8038CBB4(arg0); } } - if (next_state == CH_FROG_MINIGAME_STATE_4_COMPLETE) { - gcdialog_showDialog(VER_SELECT(ASSET_C82_DIALOG_YELLOW_FLIBBITS_COMPLETE, 0x9C5, 0, 0), 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); + if (next_state == 4) { + gcdialog_showDialog(ASSET_C82_DIALOG_YELLOW_FLIBBITS_COMPLETE, 0xf, arg0->position, arg0->marker, __chFrogMinigame_textCallback, 0); } if(next_state == 5){ @@ -137,7 +128,7 @@ void BGS_func_8038CED0(void){ D_80391240[3]++; } -void chFrogMinigame_update(Actor *this){ +void chfrogminigame_update(Actor *this){ f32 player_position[3]; u32 sp28; ActorLocal_BGS_6730 *local; @@ -190,7 +181,7 @@ void chFrogMinigame_update(Actor *this){ else{ //L8038D0E0 if(local->unk4 && !local->unk8){ - chFrogMinigame_stopFlibbitFightMusic(this); + func_8038CBB4(this); } } } diff --git a/src/BGS/ch/leafboat.c b/src/BGS/ch/leafboat.c index 04d3ac1d0..4efcf8b16 100644 --- a/src/BGS/ch/leafboat.c +++ b/src/BGS/ch/leafboat.c @@ -153,9 +153,9 @@ void chLeafBoat_update(Actor *this){ local->unk60[1] = this->yaw; local->unk60[2] = this->roll; this->lifetime_value += time_getDelta(); - playerPosition_get(player_position); + _player_getPosition(player_position); if( func_80294660() == 0x100 - && player_isStableWithExtraSteps() + && func_8028F20C() && this->marker->isBanjoOnTop ){ sp44 = local->unk54[0] - player_position[0]; diff --git a/src/BGS/ch/mrvile.c b/src/BGS/ch/mrvile.c index 4ac36b28c..b5c54892a 100644 --- a/src/BGS/ch/mrvile.c +++ b/src/BGS/ch/mrvile.c @@ -7,12 +7,12 @@ #include "core2/modelRender.h" #include "port/Enhancements/Events/Hooks/Events.h" -Actor *chMrVile_draw(ActorMarker*, Gfx **, Mtx **, Vtx **); -void chMrVile_update(Actor *); -void chMrVile_attackPlayer(ActorMarker *); +Actor *chvile_draw(ActorMarker*, Gfx **, Mtx **, Vtx **); +void chvile_update(Actor *); +void func_8038BB40(ActorMarker *); extern BKCollisionTriangle *func_80320C94(f32[3], f32[3], f32, f32[3], s32, u32); -extern bool chMrVileMinigame_findClosestPiece(ActorMarker *, f32[3], f32, f32[3]); +extern bool chvilegame_find_closest_piece(ActorMarker *, f32[3], f32, f32[3]); typedef struct chmrvile_s{ u8 unk0; @@ -30,7 +30,7 @@ typedef struct chmrvile_s{ /* .data */ ActorInfo gChVile = {MARKER_C8_MR_VILE, ACTOR_13A_MR_VILE, ASSET_373_MODEL_MR_VILE, 0x00, NULL, - chMrVile_update, NULL, chMrVile_draw, + chvile_update, NULL, chvile_draw, 0, 0, 0.0f, 0 }; @@ -73,13 +73,13 @@ void func_8038B9F0(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3, s32 arg4) { } } -void chMrVile_attackPlayer(ActorMarker * arg0){ +void func_8038BB40(ActorMarker * arg0){ Actor *this; ActorLocal_MrVile *local; this = marker_getActor(arg0); local = (ActorLocal_MrVile *)&this->local; - if(chMrVileMinigame_getDialogIndex(local->game_marker) >= 3){ + if(func_8038A9E0(local->game_marker) >= 3){ item_set(ITEM_14_HEALTH, 0); func_8028F66C(BS_INTR_F); } @@ -89,7 +89,7 @@ void chMrVile_attackPlayer(ActorMarker * arg0){ } } -void chMrVile_setAction(Actor *this, s32 arg1){ +void BGS_func_8038BBA0(Actor *this, s32 arg1){ ActorLocal_MrVile *local; local = (ActorLocal_MrVile *)&this->local; @@ -109,7 +109,7 @@ void chMrVile_setAction(Actor *this, s32 arg1){ skeletalAnim_swap(this->unk148, 0x124, 0.1f, 0.5f); //0x124 = croc_munch if(this->state == 4){ timed_playSfx(0.31f, SFX_4C_LIP_SMACK, 0.90f, 25000); - timedFunc_set_1(0.31f, (GenFunction_1)chMrVile_attackPlayer, (uintptr_t)this->marker); + timedFunc_set_1(0.31f, (GenFunction_1)func_8038BB40, (uintptr_t)this->marker); } else{ timed_playSfx(0.31f, SFX_4C_LIP_SMACK, 0.90f, 25000); @@ -138,7 +138,7 @@ void func_8038BD84(Actor *this){ local->unk28[0] = 0.0f; local->unk28[1] = 0.0f; local->unk28[2] = 0.0f; - chMrVile_setAction(this, 101); + BGS_func_8038BBA0(this, 101); } void func_8038BDD4(Actor *this) { @@ -195,37 +195,37 @@ void func_8038BDD4(Actor *this) { } } -void chMrVile_setState(Actor * this, s32 next_state){ +void chVile_setState(Actor * this, s32 next_state){ ActorLocal_MrVile *local; local = (ActorLocal_MrVile *)&this->local; if(next_state == 1) - chMrVile_setAction(this, 101); + BGS_func_8038BBA0(this, 101); if(next_state == 2) - chMrVile_setAction(this, 101); + BGS_func_8038BBA0(this, 101); if(next_state == 3) - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); if(next_state == 4) - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); if(next_state == 5){ local->target_position[0] = local->target_position[1] = local->target_position[2] = 0.0f; - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); } if(next_state == 6){ local->target_position[0] = local->target_position[1] = local->target_position[2] = 0.0f; local->unk24 = 300.0f; - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); } this->state = next_state; } -Actor *chMrVile_draw(ActorMarker *marker, Gfx **gfx, Mtx** mtx, Vtx **vtx){ +Actor *chvile_draw(ActorMarker *marker, Gfx **gfx, Mtx** mtx, Vtx **vtx){ Actor *this; ActorLocal_MrVile *local; f32 position[3]; @@ -246,14 +246,14 @@ Actor *chMrVile_draw(ActorMarker *marker, Gfx **gfx, Mtx** mtx, Vtx **vtx){ return this; } -f32 *chMrVile_getPostion(ActorMarker *marker){ +f32 *chVile_getPostion(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); return this->position; } -bool chMrVile_playerWithinRange(ActorMarker *marker) { +bool func_8038C2A8(ActorMarker *marker) { f32 player_position[3]; Actor *this; ActorLocal_MrVile *local; @@ -268,14 +268,14 @@ bool chMrVile_playerWithinRange(ActorMarker *marker) { } -bool chMrVile_isInitialIdle(ActorMarker *marker){ +bool BGS_func_8038C338(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); return this->state == 1; } -void chMrVile_free(Actor *this){ +void chvile_free(Actor *this){ ActorLocal_MrVile *local; local = (ActorLocal_MrVile *)&this->local; @@ -283,46 +283,46 @@ void chMrVile_free(Actor *this){ } -void chMrVile_setStateAttackPlayer(ActorMarker *marker){ +void func_8038C384(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chMrVile_setState(this, 4); + chVile_setState(this, 4); } -void chMrVile_setStateTalkToPlayer(ActorMarker *marker){ +void func_8038C3B0(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chMrVile_setState(this, 2); + chVile_setState(this, 2); } -void chMrVile_setStatePlayMinigame(ActorMarker *marker){ +void func_8038C3DC(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chMrVile_setState(this, 3); + chVile_setState(this, 3); } -void chMrVile_setStateIdleWalking(ActorMarker *marker){ +void func_8038C408(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chMrVile_setState(this, 5); + chVile_setState(this, 5); } -void chMrVile_setStateRunFromPlayer(ActorMarker *marker){ +void BGS_func_8038C434(ActorMarker *marker){ Actor *this; this = marker_getActor(marker); - chMrVile_setState(this, 6); + chVile_setState(this, 6); } -void chMrVile_setInitialIdleStill(ActorMarker *arg0){ - chMrVile_setState(marker_getActor(arg0), 1); +void BGS_func_8038C460(ActorMarker *arg0){ + chVile_setState(marker_getActor(arg0), 1); } -void chMrVile_update(Actor *this) { +void chvile_update(Actor *this) { f32 player_position[3]; f32 sp90; f32 temp_a0; @@ -341,12 +341,12 @@ void chMrVile_update(Actor *this) { local = (ActorLocal_MrVile *)&this->local; if (!this->volatile_initialized) { this->volatile_initialized = true; - this->marker->actorFreeFunc = chMrVile_free; + this->marker->actorFreeFunc = chvile_free; local->unk0 = 0; local->unk4 = assetcache_get(0x3F6); local->game_marker = NULL; func_8038BD84(this); - chMrVile_setState(this, 1); + chVile_setState(this, 1); return; } if (local->game_marker == NULL) { @@ -372,18 +372,18 @@ void chMrVile_update(Actor *this) { if (((sp84 > 50.0f) && (0.05 < sp7C)) || (sp7C < -0.05)) { this->yaw += sp7C * 20.0f; } else { - chMrVile_setState(this, 1); + chVile_setState(this, 1); } } if (this->state == 3) { - var_v1 = chMrVileMinigame_findClosestPiece(local->game_marker, this->position, this->yaw, local->target_position) && mapSpecificFlags_get(6); + var_v1 = chvilegame_find_closest_piece(local->game_marker, this->position, this->yaw, local->target_position) && mapSpecificFlags_get(6); if (!var_v1) { local->target_position[0] = 0.0f; local->target_position[1] = 0.0f; local->target_position[2] = 0.0f; } if (local->game_marker != NULL) { - temp_v0 = chMrVileMinigame_getScoreDifference(local->game_marker); + temp_v0 = chvilegame_get_score_difference(local->game_marker); if (temp_v0 >= 2) { local->unk10 = 200.0f; } else if (temp_v0 >= 0) { @@ -393,29 +393,29 @@ void chMrVile_update(Actor *this) { } else { local->unk10 = 450.0f; } - local->unk10 *= D_80390A94[chMrVileMinigame_getDialogIndex(local->game_marker)]; + local->unk10 *= D_80390A94[func_8038A9E0(local->game_marker)]; CALL_EVENT(OnMrVileSetSpeed, &local->unk10); } - if (chMrVileMinigame_getDialogIndex(local->game_marker) < 7) { + if (func_8038A9E0(local->game_marker) < 7) { func_80258A4C(this->position, this->yaw - 90.0f, local->target_position, &sp70, &sp6C, &sp68); if (local->unkC == 102) { if ((-0.8 < sp68) && (sp68 < 0.8) && (sp70 <= 150.0f) && var_v1) { - chMrVile_setAction(this, 103); + BGS_func_8038BBA0(this, 103); } } if (local->unkC == 103) { if (sp70 <= 50.0f) { - if (chMrVileMinigame_mrVileConsumePiece(local->game_marker, local->target_position)) { - chMrVile_setAction(this, 104); + if (chvilegame_cpu_consume_piece(local->game_marker, local->target_position)) { + BGS_func_8038BBA0(this, 104); } else { - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); } } else if (skeletalAnim_getLoopCount(this->unk148) >= 3) { - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); } } if ((local->unkC == 104) && (skeletalAnim_getLoopCount(this->unk148) >= 3)) { - chMrVile_setAction(this, 102); + BGS_func_8038BBA0(this, 102); } } } @@ -423,10 +423,10 @@ void chMrVile_update(Actor *this) { player_getPosition(local->target_position); local->unk10 = 500.0f; if ((local->unkC == 102) && (ml_vec3f_distance(this->position, local->target_position) < 200.0f)) { - chMrVile_setAction(this, 103); + BGS_func_8038BBA0(this, 103); } if ((local->unkC == 103) && (skeletalAnim_getLoopCount(this->unk148) >= 2)) { - chMrVile_setState(this, 1); + chVile_setState(this, 1); } } if (this->state == 5) { @@ -460,7 +460,7 @@ void chMrVile_update(Actor *this) { // [port] Anchor sync entry points. // Applies a streamed transform + anim mode from the minigame authority. -void chMrVile_netApplyUpdate(Actor *this, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode){ +void chvile_netApplyUpdate(Actor *this, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode){ ActorLocal_MrVile *local = (ActorLocal_MrVile *)&this->local; this->position[0] = position[0]; @@ -470,11 +470,11 @@ void chMrVile_netApplyUpdate(Actor *this, const f32 position[3], f32 pitch, f32 this->yaw = yaw; this->roll = roll; if (local->unkC != anim_mode) { - chMrVile_setAction(this, anim_mode); + BGS_func_8038BBA0(this, anim_mode); } } -s32 chMrVile_netGetAnimMode(Actor *this){ +s32 chvile_netGetAnimMode(Actor *this){ ActorLocal_MrVile *local = (ActorLocal_MrVile *)&this->local; return local->unkC; diff --git a/src/BGS/ch/mudhut.c b/src/BGS/ch/mudhut.c index dfb64a49b..eccc0113c 100644 --- a/src/BGS/ch/mudhut.c +++ b/src/BGS/ch/mudhut.c @@ -6,8 +6,6 @@ #include -#include "port/Patches/Patches.h" - /* TODO move declarations to respective headers*/ extern void player_stateTimer_set(enum state_timer_e, f32); extern f32 player_stateTimer_get(enum state_timer_e); @@ -65,7 +63,7 @@ Actor *chMudHut_draw(ActorMarker *this, Gfx** gdl, Mtx** mtx, Vtx **vtx){ Actor *thisActor; thisActor = marker_getActor(this); - modelRender_setAppendageVisibility(1, thisActor->state == 1); + func_8033A45C(1, thisActor->state == 1); if(thisActor->state == 3) return thisActor; @@ -81,34 +79,8 @@ void chMudHut_spawnExplosion(ActorMarker *this){ if(this); } -static void chMudHut_dropRecordedBundle(Actor *this, s32 tmp, s32 fullBundle){ - f32 pos[3]; - if(tmp < 0 || tmp >= 5){ - return; // jiggy / out of range: handled by JIGGY_SPAWN, not the hut - } - if(!fullBundle && tmp == 2){ - return; // note: spawn live but skip on reload - } - pos[0] = this->position_x; - pos[1] = this->position_y + 130.0f; - pos[2] = this->position_z; - __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, D_80390B50[tmp], reinterpret_cast(s32, pos[0]), reinterpret_cast(s32, pos[1]), reinterpret_cast(s32, pos[2])); -} - -static void chMudHut_replaySmash(Actor *this, s32 tmp){ - sfx_playFadeShorthandDefault(SFX_5B_HEAVY_STUFF_FALLING, 1.0f, 28000, this->position, 0x12C, 0xBB8); - subaddie_set_state(this, 2); - this->marker->propPtr->unk8_3 = 0; - actor_playAnimationOnce(this); - if(tmp == 5){ - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - } - __spawnQueue_add_1((GenFunction_1)chMudHut_spawnExplosion, (uintptr_t)this->marker); - chMudHut_dropRecordedBundle(this, tmp, 1); -} - void chMudHut_update(Actor *this){ - + f32 diffPos[3]; f32 plyrPos[3]; s32 tmp; @@ -117,14 +89,6 @@ void chMudHut_update(Actor *this){ if(!this->initialized){ this->marker->collidable = false; this->initialized = true; - // Anchor: already smashed this session — restore broken, re-drop non-tracked loot. - tmp = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); - if(tmp >= 0){ - this->state = 3; - this->marker->propPtr->unk8_3 = 0; - chMudHut_dropRecordedBundle(this, tmp, 0); - return; - } } switch(this->state){ @@ -134,9 +98,9 @@ void chMudHut_update(Actor *this){ diffPos[0] = plyrPos[0] - this->position_x; diffPos[1] = plyrPos[1] - this->position_y; diffPos[2] = plyrPos[2] - this->position_z; - if( (150.0f < diffPos[1]) - && (player_getActiveHitbox(this->marker) == HITBOX_1_BEAK_BUSTER) - && (player_isStableWithExtraSteps()) + if( (150.0f < diffPos[1]) + && (player_getActiveHitbox(this->marker) == HITBOX_1_BEAK_BUSTER) + && (func_8028F20C()) && (LENGTH_VEC3F(diffPos) < 350.f) ){ tmp = (s32)( (this->position_y - 600.f)/430.0f); @@ -160,13 +124,6 @@ void chMudHut_update(Actor *this){ else { jiggy_spawn(JIGGY_23_BGS_HUTS, diffPos); } - port_hutSmash_record((s32)this->position_x, (s32)this->position_y, (s32)this->position_z, tmp); - } - else { - tmp = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); - if(tmp >= 0){ - chMudHut_replaySmash(this, tmp); - } } break; case 2: diff --git a/src/BGS/ch/pinkegg.c b/src/BGS/ch/pinkegg.c index 1e513513d..7845ccfc6 100644 --- a/src/BGS/ch/pinkegg.c +++ b/src/BGS/ch/pinkegg.c @@ -3,8 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - typedef struct chpinkegg_s{ u32 unk0; u32 unk4; @@ -75,8 +73,8 @@ Actor *chPinkEgg_draw(ActorMarker *this, Gfx ** gdl, Mtx** mptr, Vtx **arg3){ u32 t7; t7 = marker_getActor(this)->state == 3; - modelRender_setAppendageVisibility(1, NOT(sp18 = t7)); - modelRender_setAppendageVisibility(2, sp18); + func_8033A45C(1, NOT(sp18 = t7)); + func_8033A45C(2, sp18); return actor_draw(this, gdl, mptr, arg3); } @@ -92,11 +90,9 @@ void chPinkEgg_collision(ActorMarker *this, ActorMarker *other_marker){ actor_playAnimationOnce(thisActor); this->collidable = false; thisActor->unk124_6 = 0; - tmp = (ActorLocal_PinkEgg *) &thisActor->local; - port_puzzleStep_orBits(ANCHOR_PUZZLE_BGS_PINKEGG, 1 << tmp->unk0); - if(D_803906C4[tmp->unk0] != 0){ - __spawnQueue_add_2((GenFunction_2)chPinkEgg_spawnNext, (uintptr_t)thisActor->marker, tmp->unk0); - } else if(!jiggyscore_isSpawned(JIGGY_21_BGS_PINKEGG)){ + if(D_803906C4[(tmp = (ActorLocal_PinkEgg *) &thisActor->local)->unk0] != 0){ + __spawnQueue_add_2((void (*)(void))chPinkEgg_spawnNext, (uintptr_t)thisActor->marker, tmp->unk0); + } else { jiggy_spawn(JIGGY_21_BGS_PINKEGG, thisActor->position); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); } @@ -109,19 +105,6 @@ void chPinkEgg_update(Actor *this){ this->initialized = true; } - // Anchor: team finished the chain — despawn unless mid-break (state 3). - if(jiggyscore_isSpawned(JIGGY_21_BGS_PINKEGG) && this->state != 3){ - marker_despawn(this->marker); - return; - } - - // Anchor: replay teammates' layer breaks. - if((port_puzzleStep_get(ANCHOR_PUZZLE_BGS_PINKEGG) & (1 << ((ActorLocal_PinkEgg *)&this->local)->unk0)) - && this->state != 3){ - chPinkEgg_collision(this->marker, NULL); - return; - } - switch(this->state){ case 1: if(!((ActorLocal_PinkEgg *) &this->local)->unk4){ diff --git a/src/BGS/ch/swampswitch.c b/src/BGS/ch/swampswitch.c index cc9b28f97..382ff6a76 100644 --- a/src/BGS/ch/swampswitch.c +++ b/src/BGS/ch/swampswitch.c @@ -40,7 +40,7 @@ void chLongSwampSwitch_update(Actor *this){ if(mapSpecificFlags_get(7)){ mapSpecificFlags_set(7, 0); if(!mapSpecificFlags_get(3) || (item_getCount(0) > 0)){ - code_4C020_setHourglassTimer(45); + func_802D68F0(45); } } if(!mapSpecificFlags_get(5)){ @@ -60,7 +60,7 @@ void chLongSwampSwitch_update(Actor *this){ } //L8038EFB4 if( this->velocity_x != 0.0f && !mapSpecificFlags_get(3) && func_802BB270()){ mapSpecificFlags_set(3,1); - code_4C020_setHourglassTimer(45); //adjusts timer + func_802D68F0(45); //adjusts timer item_set(ITEM_6_HOURGLASS,1); } //L8038EFB4 } @@ -83,7 +83,7 @@ void chShortSwampSwitch_update(Actor *this){ if(mapSpecificFlags_get(8)){ mapSpecificFlags_set(8, 0); if(!mapSpecificFlags_get(0xC) || (item_getCount(0) > 0)){ - code_4C020_setHourglassTimer(10); + func_802D68F0(10); } } if(!mapSpecificFlags_get(9)){ @@ -103,7 +103,7 @@ void chShortSwampSwitch_update(Actor *this){ } //L8038EFB4 if( this->velocity_x != 0.0f && !mapSpecificFlags_get(0xC) && func_802BB270()){ mapSpecificFlags_set(0xC,1); - code_4C020_setHourglassTimer(10); //adjusts timer + func_802D68F0(10); //adjusts timer item_set(ITEM_6_HOURGLASS,1); } //L8038EFB4 } diff --git a/src/BGS/ch/tanktup.c b/src/BGS/ch/tanktup.c index 457de1af0..6dd23ca02 100644 --- a/src/BGS/ch/tanktup.c +++ b/src/BGS/ch/tanktup.c @@ -1,15 +1,16 @@ -// BanjoDecomp: BGS/ch/tanktup.c +// BanjoDecomp: tanktup.c #include #include "functions.h" #include "variables.h" #include "prop.h" -#include "port/Patches/Patches.h" - void timed_exitStaticCamera(f32); +#include "core2/timedfunc.h" + void func_8028E668(f32[3], f32, f32, f32); +extern void __spawnQueue_add_3(GenFunction_3, uintptr_t, uintptr_t, uintptr_t); void chTanktup_update(Actor *); @@ -28,19 +29,11 @@ ActorAnimationInfo BGS_D_80390C20[] = { {0x107, 1.75f} }; -ActorInfo gChTanktup = { - MARKER_6C_TANKTUP, ACTOR_E8_TANKTUP, ASSET_3EE_TANKTUP, - 0x01, BGS_D_80390C20, +ActorInfo chTanktup = {MARKER_6C_TANKTUP, ACTOR_E8_TANKTUP, ASSET_3EE_TANKTUP, 0x01, BGS_D_80390C20, chTanktup_update, actor_update_func_80326224, actor_draw, 0, 0x80, 0.0f, 0 }; -enum chTanktupState { - CH_TANKTUP_STATE_1_UNK = 1, - CH_TANKTUP_STATE_2_UNK, - CH_TANKTUP_STATE_3_UNK, -}; - /* .code */ void func_8038F470(ActorMarker *this, s32 arg1, enum chtanktup_leg_e leg_id){ Actor* thisActor; @@ -74,7 +67,9 @@ s32 func_8038F570(s16 *arg0){ pos[1] = (f32)arg0[1]; pos[2] = (f32)arg0[2]; spawnPtr = actorArray_findClosestActorFromActorId(pos, ACTOR_E8_TANKTUP, -1, 0); - return spawnPtr->state == CH_TANKTUP_STATE_3_UNK; + return spawnPtr->state == 3; + + } void func_8038F5E4(ActorMarker *marker, enum asset_e text_id, s32 arg2){ @@ -98,174 +93,138 @@ void func_8038F610(Actor *this) { void func_8028F94C(s32, f32[3]); void func_8028F918(s32); -// Anchor: set when state 2 took the head-raise look-at/freeze push; state 3 releases it. -static s32 sTanktupCameraPushed = 0; -static s32 sTanktupPoseCatchUp = 0; - void chTanktup_update(Actor *this) { - ActorLocal_TanktupBody *local = (ActorLocal_TanktupBody *) (&this->local); - f32 sp48[3]; - s32 sp44; - NodeProp *temp_v0; - if (!this->initialized) + ActorLocal_TanktupBody *local = (ActorLocal_TanktupBody *) (&this->local); + f32 sp48[3]; + s32 sp44; + NodeProp *temp_v0; + if (!this->initialized) + { + temp_v0 = nodeprop_findByActorIdAndActorPosition(ACTOR_32B_UNKNOWN, this); + if (temp_v0 == 0) { - temp_v0 = nodeprop_findByActorIdAndActorPosition(ACTOR_32B_UNKNOWN, this); - if (temp_v0 == 0) - { - local->unk18[0] = 3672.0f; - local->unk18[1] = 100.0f; - local->unk18[2] = 987.0f; - } - else - { - nodeprop_getPosition(temp_v0, local->unk18); - } - this->has_met_before = FALSE; - this->initialized = TRUE; + local->unk18[0] = 3672.0f; + local->unk18[1] = 100.0f; + local->unk18[2] = 987.0f; } - if (!this->volatile_initialized) + else { - this->volatile_initialized = TRUE; - this->marker->propPtr->unk8_3 = 1; - actor_collisionOff(this); - this->scale = 1.0f; - sTanktupCameraPushed = 0; - // Anchor: adopt the team's already-retracted legs. - { - s32 legBits = port_puzzleStep_get(ANCHOR_PUZZLE_BGS_TANKTUP); - for (sp44 = 0; sp44 < 4; sp44++) - { - if (legBits & (1 << sp44)) - { - local->unk0[sp44] = 1; - } - } - } - for (sp44 = 0; sp44 < 4; sp44++) + nodeprop_getPosition(temp_v0, local->unk18); + } + this->has_met_before = false; + this->initialized = true; + } + if (!this->volatile_initialized) + { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = 1; + actor_collisionOff(this); + this->scale = 1.0f; + for (sp44 = 0; sp44 < 4; sp44++) + { + if (local->unk0[sp44] == 0) + { + __spawnQueue_add_3((GenFunction_3)func_8038F470, (uintptr_t)this->marker, local->unk0[sp44], sp44); + } + } + + if (local) + { + ; + } + } + switch (this->state) + { + case 1: + func_8038F610(this); + player_getPosition(sp48); + if (!this->has_met_before) + { + if ((((ml_vec3f_distance(local->unk18, sp48) < 250.0f) && (ml_vec3f_distance(local->unk18, sp48) > 80.0f)) && (!player_movementGroup())) && (player_getTransformation() == TRANSFORM_1_BANJO)) + { + gcdialog_showDialog(ASSET_C7E_DIALOG_TANKTUP_MEET, 0, 0, 0, 0, 0); + this->has_met_before = true; + } + } + if (local->unk10) + { + subaddie_set_state_with_direction(this, 2, 0.0f, -1); + local->unk10 = 0; + sp44 = 0; + (void)&sp44; + local->unk14 = 1; + for (; sp44 < 4; sp44++) + { + if (local->unk0[sp44] == 0) { - if (local->unk0[sp44] == 0) - { - __spawnQueue_add_3((GenFunction_3)func_8038F470, reinterpret_cast(uintptr_t, this->marker), local->unk0[sp44], sp44); - } + local->unk14 = 0; } + } - if (local) + if ((!this->unk138_23) && (!local->unk14)) + { + if (gcdialog_showDialog(ASSET_C80_DIALOG_TANKTUP_HIT, 0, 0, 0, 0, 0)) { - ; + this->unk138_23 = 1; } + } } - // Anchor: team completed Tanktup but our body is still idle (state 1) — raise the head to match. - if (this->state == CH_TANKTUP_STATE_1_UNK && jiggyscore_isSpawned(JIGGY_26_BGS_TANKTUP)) + break; + + case 2: + func_8038F610(this); + if (actor_animationIsAt(this, 0.6f) && local->unk14) { - sTanktupPoseCatchUp = 1; // [port] pose only, no presentation - subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_3_UNK, 0.0f, -1); - actor_playAnimationOnce(this); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + func_8028F94C(2, local->unk18); } - switch (this->state) + if (actor_animationIsAt(this, 0.99f)) { - case CH_TANKTUP_STATE_1_UNK: - func_8038F610(this); - player_getPosition(sp48); - if (!this->has_met_before) - { - if ((((ml_vec3f_distance(local->unk18, sp48) < 250.0f) && (ml_vec3f_distance(local->unk18, sp48) > 80.0f)) && (!player_movementGroup())) && (player_getTransformation() == TRANSFORM_1_BANJO)) - { - gcdialog_showDialog(VER_SELECT(ASSET_C7E_DIALOG_TANKTUP_MEET, 0x9C1, 0, 0), 0, 0, 0, 0, 0); - this->has_met_before = TRUE; - } - } - if (local->unk10) - { - subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_2_UNK, 0.0f, -1); - local->unk10 = 0; - sp44 = 0; - if(&sp44); - local->unk14 = 1; - for (; sp44 < 4; sp44++) - { - if (local->unk0[sp44] == 0) - { - local->unk14 = 0; - } - } + if (!local->unk14) + { + subaddie_set_state_with_direction(this, 1, 0.0f, -1); + } + else + { + subaddie_set_state_with_direction(this, 3, 0.0f, -1); + actor_playAnimationOnce(this); + } + } + break; - if ((!this->unk138_23) && (!local->unk14)) - { - if (gcdialog_showDialog(VER_SELECT(ASSET_C80_DIALOG_TANKTUP_HIT, 0x9C3, 0, 0), 0, 0, 0, 0, 0)) - { - this->unk138_23 = 1; - } - } - } - break; + case 3: + if (actor_animationIsAt(this, 0.1f) != 0) + { + timed_setStaticCameraToNode(0.0f, 0xD); + } + if (actor_animationIsAt(this, 0.55f) != 0) + { + func_8030E624(0x797FF885U); + } + if (actor_animationIsAt(this, 0.4f) != 0) + { + f32 sp34[3]; + vec3fArray_get_vec3f(this->marker->unk44, 6, sp34); + bundle_setYaw(this->yaw); + sp34[1] -= 125.0f; + jiggy_spawn(JIGGY_26_BGS_TANKTUP, sp34); + } + if (actor_animationIsAt(this, 0.9f) != 0) + { + func_8028F918(0); + if (jiggyscore_isCollected(JIGGY_26_BGS_TANKTUP) == 0) + { + gcdialog_showDialog(ASSET_C7F_DIALOG_TANKTUP_COMPLETE, 0xF, this->position, this->marker, func_8038F5E4, 0); + } + else + { + func_8038F5E4(this->marker, ASSET_C7F_DIALOG_TANKTUP_COMPLETE, -1); + } + } + break; - case CH_TANKTUP_STATE_2_UNK: - func_8038F610(this); - if (actor_animationIsAt(this, 0.6f) && local->unk14) - { - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - func_8028F94C(2, local->unk18); - sTanktupCameraPushed = 1; - } - if (actor_animationIsAt(this, 0.99f)) - { - if (!local->unk14) - { - subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_1_UNK, 0.0f, -1); - } - else - { - sTanktupPoseCatchUp = 0; // [port] solved for real: keep the presentation - subaddie_set_state_with_direction(this, CH_TANKTUP_STATE_3_UNK, 0.0f, -1); - actor_playAnimationOnce(this); - } - } - break; + } - case CH_TANKTUP_STATE_3_UNK: - { - f32 pp[3]; - s32 near; - player_getPosition(pp); - near = ml_vec3f_distance(local->unk18, pp) < 700.0f; - if (actor_animationIsAt(this, 0.1f) != 0 && near && !sTanktupPoseCatchUp) - { - timed_setStaticCameraToNode(0.0f, 0xD); - } - if (actor_animationIsAt(this, 0.55f) != 0 && !sTanktupPoseCatchUp) - { - func_8030E624(0x797FF885U); // SFX_85_ROUGH_COUGH - } - if (actor_animationIsAt(this, 0.4f) != 0 && jiggyscore_isSpawned(JIGGY_26_BGS_TANKTUP) == 0) - { - f32 sp34[3]; - vec3fArray_get_vec3f(this->marker->unk44, 6, sp34); - bundle_setYaw(this->yaw); - sp34[1] -= 125.0f; - jiggy_spawn(JIGGY_26_BGS_TANKTUP, sp34); - } - if (actor_animationIsAt(this, 0.9f) != 0) - { - // Anchor: release the freeze/look-at if state 2 took it, independent of the proximity check below. - if (sTanktupCameraPushed) - { - func_8028F918(0); - sTanktupCameraPushed = 0; - } - if (near) - { - if (jiggyscore_isCollected(JIGGY_26_BGS_TANKTUP) == 0) - { - gcdialog_showDialog(VER_SELECT(ASSET_C7F_DIALOG_TANKTUP_COMPLETE, 0x9C2, 0, 0), 0xF, this->position, this->marker, func_8038F5E4, 0); - } - else - { - func_8038F5E4(this->marker, VER_SELECT(ASSET_C7F_DIALOG_TANKTUP_COMPLETE, 0x9C2, 0, 0), -1); - } - } - } - break; - } - } } + diff --git a/src/BGS/ch/tanktuplegs.c b/src/BGS/ch/tanktup_legs.c similarity index 75% rename from src/BGS/ch/tanktuplegs.c rename to src/BGS/ch/tanktup_legs.c index 7ca9610ad..b63be8fe1 100644 --- a/src/BGS/ch/tanktuplegs.c +++ b/src/BGS/ch/tanktup_legs.c @@ -1,9 +1,8 @@ -// BanjoDecomp: BGS/ch/tanktuplegs.c +// BanjoDecomp: code_9750.c #include #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" void timed_exitStaticCamera(f32); void func_8028E668(f32[3], f32, f32, f32); @@ -61,7 +60,7 @@ ActorInfo gChTanktupLegBackRight = {MARKER_6D_TANKTUP_LEG, ACTOR_EC_TANKTUP_LEG_ }; /* .code */ -void chTanktupLeg_retractLeg(ActorMarker *this, s32 arg1){ +void func_8038FB40(ActorMarker *this, s32 arg1){ Actor * thisActor; thisActor = marker_getActor(this); @@ -70,31 +69,25 @@ void chTanktupLeg_retractLeg(ActorMarker *this, s32 arg1){ FUNC_8030E624(SFX_A_BANJO_LANDING_05, 0.8f, 32750); } -void chTanktupLeg_despawn(ActorMarker *this, ActorMarker *other_marker){ +void BGS_func_8038FB84(ActorMarker *this, ActorMarker *other_marker){ Actor *thisActor; thisActor = marker_getActor(this); sfx_playFadeShorthandDefault( SFX_87_TANKTUP_OOOHW, 1.0f, 32750, thisActor->position, 1000, 3000); - timedFunc_set_2(0.65f, (GenFunction_2) chTanktupLeg_retractLeg, (uintptr_t) this, (uintptr_t) other_marker); + timedFunc_set_2(0.65f, (GenFunction_2) func_8038FB40, (uintptr_t) this, (uintptr_t) other_marker); func_8038F51C(thisActor); this->collidable = false; - port_puzzleStep_orBits(ANCHOR_PUZZLE_BGS_TANKTUP, 1 << thisActor->unk10_12); } void chTanktupLeg_update(Actor *this){ if(!this->initialized){ this->initialized = true; this->marker->propPtr->unk8_3 = 1; - marker_setCollisionScripts(this->marker, NULL, NULL, chTanktupLeg_despawn); - } - // Anchor: teammate hit this leg remotely — replay the pull-in. - if(this->state == 1 && this->marker->collidable - && (port_puzzleStep_get(ANCHOR_PUZZLE_BGS_TANKTUP) & (1 << this->unk10_12))){ - chTanktupLeg_despawn(this->marker, NULL); + marker_setCollisionScripts(this->marker, NULL, NULL, BGS_func_8038FB84); } if(this->state == 2){ if(anctrl_isAt(this->anctrl, 0.65f)){ - gcsfx_play(SFX_7C_CHEBOOF); + gcsfx_playAtSampleRate(SFX_7C_CHEBOOF); } if(anctrl_isStopped(this->anctrl)){ marker_despawn(this->marker); diff --git a/src/BGS/ch/tiptup.c b/src/BGS/ch/tiptup.c index cf2bd5323..c93e4112c 100644 --- a/src/BGS/ch/tiptup.c +++ b/src/BGS/ch/tiptup.c @@ -1,4 +1,4 @@ -// BanjoDecomp: BGS/ch/tiptup.c +// BanjoDecomp: ch/code_2270.c #include #include "functions.h" #include "variables.h" @@ -12,72 +12,34 @@ typedef struct{ typedef struct ch_bgs_2270_s{ u32 unk0; - bk_vector(Struct_BGS_2270_0s) *unk4; // vector? + bk_vector(Struct_BGS_2270_0s) *unk4; u8 unk8; u8 unk9; - u8 round; + u8 unkA; u8 unkB; - f32 animTimer; + f32 unkC; } ActorLocal_Tiptup; void chTiptup_update(Actor *this); Actor *actor_draw(ActorMarker *, Gfx **, Mtx **, Vtx **); -ActorInfo gChTiptup = { +ActorInfo chTiptup = { MARKER_19A_TIPTUP, ACTOR_27A_TIPTUP, ASSET_3F8_MODEL_TIPTUP, 0, NULL, chTiptup_update, NULL, actor_draw, 0, 0, 2.5f, 0 }; +s16 D_80390854[] = {0, ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT, ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT, ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT}; //see again texts +s16 D_8039085C[] = {0, ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE, ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE, ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE}; //success texts +u8 D_80390864[] = {3, 3, 5, 7}; //chchoirgame_sequence_length +f32 D_80390868[3] = {0.0f, 100.0f, -1020.0f}; //chchoirgame_jiggy_position -s16 chTiptupRepeatDialogs[] = { - 0, // [port] decomp uses NULL; these are asset ids, not pointers - VER_SELECT(ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT, 0x9BB, 0, 0), - VER_SELECT(ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT, 0x9BD, 0, 0), - VER_SELECT(ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT, 0x9BF, 0, 0) -}; - -s16 chTiptupSuccessDialogs[] = { - 0, // [port] decomp uses NULL; these are asset ids, not pointers - VER_SELECT(ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE, 0x9BA, 0, 0), - VER_SELECT(ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE, 0x9BC, 0, 0), - VER_SELECT(ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE, 0x9BE, 0, 0) -}; - -u8 chTiptupSequenceLength[] = {3, 3, 5, 7}; -f32 chTiptupJiggyPosition[3] = {0.0f, 100.0f, -1020.0f}; - -enum chTiptupState { - CH_TIPTUP_STATE_1_IDLE = 1, - CH_TIPTUP_STATE_2_INSTRUCTIONS_DIALOG, - CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE, - CH_TIPTUP_STATE_4_AWAIT_SEQUENCE_COMPLETION, - CH_TIPTUP_STATE_5_WIN_MINIGAME, - CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG -}; - -enum chTiptupSpecificFlag { - CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY, - CH_TIPTUP_SPECIFIC_FLAG_1_TIPTUP_MISS -}; - -enum TiptupRound { - TIPTUP_ROUND_1, - TIPTUP_ROUND_2, - TIPTUP_ROUND_3, - TIPTUP_ROUND_FF -}; - -#define TIPTUP_TIMER 30 // Seconds -#define FIRST_CHOIR_MEMBER 1 -#define LAST_CHOIR_MEMBER 7 - -void chTiptup_minigameComplete(ActorMarker *this){ - chTiptup_setState(marker_getActor(this), CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG); +void BGS_func_80388660(ActorMarker *this){ + chTiptup_setState(marker_getActor(this), 6); } void chTiptup_jiggySpawn(void){ - jiggy_spawn(JIGGY_27_BGS_TIPTUP, chTiptupJiggyPosition); + jiggy_spawn(JIGGY_27_BGS_TIPTUP, D_80390868); //spawn jiggy after minigame } void chTiptup_activatePattern(ActorMarker *this, s32 arg1){ @@ -99,8 +61,8 @@ void chTiptup_activateTimer(ActorMarker *this){ thisActor = marker_getActor(this); item_set(ITEM_6_HOURGLASS, 1); - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(TIPTUP_TIMER, 25, 0, 0) * 60 - 1); - chTiptup_setState(thisActor, CH_TIPTUP_STATE_5_WIN_MINIGAME); + item_set(ITEM_0_HOURGLASS_TIMER, 30*60-1); + chTiptup_setState(thisActor, 5); } void chTiptup_sfxCorrectHit(void){ @@ -116,21 +78,21 @@ void chTiptup_textEvent(ActorMarker *this, enum asset_e text_id, s32 arg2){ thisActor = marker_getActor(this); switch(text_id){ - case VER_SELECT(ASSET_C72_DIALOG_TIPTUP_MEET_1, 0x9B5, 0, 0): - case VER_SELECT(ASSET_C74_DIALOG_TIPTUP_MEET_3, 0x9B7, 0, 0): - chTiptup_setState(thisActor, CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE); + case ASSET_C72_DIALOG_TIPTUP_MEET_1: + case ASSET_C74_DIALOG_TIPTUP_MEET_3: + chTiptup_setState(thisActor, 3); break; - case VER_SELECT(ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT, 0x9BB, 0, 0): - case VER_SELECT(ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT, 0x9BD, 0, 0): - case VER_SELECT(ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT, 0x9BF, 0, 0): - chTiptup_setState(thisActor, CH_TIPTUP_STATE_4_AWAIT_SEQUENCE_COMPLETION); + case ASSET_C78_DIALOG_TIPTUP_LESSON_1_REPEAT: + case ASSET_C7A_DIALOG_TIPTUP_LESSON_2_REPEAT: + case ASSET_C7C_DIALOG_TIPTUP_LESSON_3_REPEAT: + chTiptup_setState(thisActor, 4); break; - case VER_SELECT(ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE, 0x9BA, 0, 0): - case VER_SELECT(ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE, 0x9BC, 0, 0): + case ASSET_C77_DIALOG_TIPTUP_LESSON_1_COMPLETE: + case ASSET_C79_DIALOG_TIPTUP_LESSON_2_COMPLETE: func_80324E38(0.0f, 0); - chTiptup_setState(thisActor, CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE); + chTiptup_setState(thisActor, 3); break; - case VER_SELECT(ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE, 0x9BE, 0, 0): + case ASSET_C7B_DIALOG_TIPTUP_LESSON_3_COMPLETE: timedFunc_set_0(0.0f, chTiptup_jiggySpawn); timed_exitStaticCamera(2.5f); func_80324E38(2.5f, 0); @@ -151,164 +113,113 @@ void chTiptup_correctHit(ActorMarker *this){ return; if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - item_set(ITEM_6_HOURGLASS, 0); - volatileFlag_set(VOLATILE_FLAG_3, 0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 1); + item_set(ITEM_6_HOURGLASS,0); + volatileFlag_set(VOLATILE_FLAG_3,0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON,1); } else{ - chTiptup_minigameComplete(thisActor->marker); + BGS_func_80388660(thisActor->marker); } } -void chTiptup_setState(Actor *this, s32 next_state){ +void chTiptup_setState(Actor *this, s32 arg1){ ActorLocal_Tiptup *unqPtr; f32 sp54; - f32 sequence_time; - s32 current_member_index; + + f32 tmpf; + s32 i; s32 j; s32 prev_member; s32 rand2; Struct_BGS_2270_0s *s1; unqPtr = (ActorLocal_Tiptup *)&this->local; - this->state = next_state; - unqPtr->animTimer = 0.0f; - if(this->state == CH_TIPTUP_STATE_1_IDLE){ + this->state = arg1; + unqPtr->unkC = 0.0f; + if(this->state == 1){ skeletalAnim_set(this->unk148, ASSET_12B_ANIM_TIPTUP_IDLE, 1.0f, 9.0f); - unqPtr->animTimer = randf2(5.0f, 15.0f); + unqPtr->unkC = randf2(5.0f, 15.0f); } - if(this->state == CH_TIPTUP_STATE_2_INSTRUCTIONS_DIALOG){ + if(this->state == 2){ skeletalAnim_set(this->unk148, ASSET_12B_ANIM_TIPTUP_IDLE, 1.0f, 9.0f); - unqPtr->animTimer = randf2(5.0f, 15.0f); + unqPtr->unkC = randf2(5.0f, 15.0f); if (!this->has_met_before) { - this->has_met_before = TRUE; - - if (unqPtr->round == TIPTUP_ROUND_1) { - gcdialog_showDialog( - VER_SELECT(ASSET_C72_DIALOG_TIPTUP_MEET_1, 0x9B5, 0, 0), - 0xe, - this->position, - this->marker, - chTiptup_textEvent, - 0); + this->has_met_before = true; + + if (unqPtr->unkA == 0) { + gcdialog_showDialog(ASSET_C72_DIALOG_TIPTUP_MEET_1, 0xe, this->position, this->marker, chTiptup_textEvent, 0); } else { - gcdialog_showDialog( - VER_SELECT(ASSET_C74_DIALOG_TIPTUP_MEET_3, 0x9B7, 0, 0), - 0xf, - this->position, - this->marker, - chTiptup_textEvent, - 0); + gcdialog_showDialog(ASSET_C74_DIALOG_TIPTUP_MEET_3, 0xf, this->position, this->marker, chTiptup_textEvent, 0); } } else { - gcdialog_showDialog( - chTiptupRepeatDialogs[unqPtr->round], - 0xf, - this->position, - this->marker, - chTiptup_textEvent, - 0); + gcdialog_showDialog(D_80390854[unqPtr->unkA], 0xf, this->position, this->marker, chTiptup_textEvent, 0); } } - if(this->state == CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE){ + if(this->state == 3){ unqPtr->unk0 = 0; bk_vector_clear(unqPtr->unk4); func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.5f, 0); - sequence_time = 0.5f; - current_member_index = 0; + tmpf = 0.5f; + i = 0; prev_member = 0; - for(; current_member_index < chTiptupSequenceLength[unqPtr->round]; current_member_index++){ - sequence_time += randf2(1.0f, 1.5f); - // while loop prevents same choir member in a row - while((rand2 = randi2(FIRST_CHOIR_MEMBER, LAST_CHOIR_MEMBER)) == prev_member); - timedFunc_set_2( - sequence_time, - (GenFunction_2) chTiptup_activatePattern, - reinterpret_cast(uintptr_t, this->marker), - rand2); - timedFunc_set_2( - sequence_time + 0.1, - (GenFunction_2)chTiptup_activatePattern, - reinterpret_cast(uintptr_t, this->marker), - 0); + for(; i < D_80390864[unqPtr->unkA]; i++){ + tmpf += randf2(1.0f, 1.5f); + while((rand2 = randi2(1,7)) == prev_member); + timedFunc_set_2(tmpf, (GenFunction_2) chTiptup_activatePattern, (uintptr_t)this->marker, rand2); + timedFunc_set_2(tmpf + 0.1, (GenFunction_2)chTiptup_activatePattern, (uintptr_t)this->marker, 0); prev_member = rand2; }//L80388B7C - timed_exitStaticCamera(sequence_time += 2.5); - if(!unqPtr->round && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - func_80324DBC( - sequence_time + 0.5, - VER_SELECT(ASSET_C73_DIALOG_TIPTUP_MEET_2, 0x9B6, 0, 0), - 0xe, - this->position, - this->marker, - chTiptup_textEvent, - 0); - unqPtr->round = TIPTUP_ROUND_2; + timed_exitStaticCamera(tmpf += 2.5); + if(!unqPtr->unkA && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ + func_80324DBC(tmpf + 0.5, ASSET_C73_DIALOG_TIPTUP_MEET_2, 0xe, this->position, this->marker, chTiptup_textEvent, 0); + unqPtr->unkA = 1; } - func_80324E38(sp54 = sequence_time + 0.6, 0); + func_80324E38(sp54 = tmpf + 0.6, 0); if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - timedFunc_set_1( - sp54, - (GenFunction_1)chTiptup_activateTimer, - reinterpret_cast(uintptr_t, this->marker)); + timedFunc_set_1(sp54, (GenFunction_1)chTiptup_activateTimer, (uintptr_t)this->marker); }else{ - this->state = CH_TIPTUP_STATE_5_WIN_MINIGAME; + this->state = 0x05; } - mapSpecificFlags_set(CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY, 0); + mapSpecificFlags_set(0, 0); }//L80388C6C - if(this->state == CH_TIPTUP_STATE_4_AWAIT_SEQUENCE_COMPLETION){ + if(this->state == 4){ unqPtr->unk0 = 0; func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.5f, 0); - sequence_time = 0.5f; + tmpf = 0.5f; for(j = 0; j < bk_vector_size(unqPtr->unk4); j++){ s1 = (Struct_BGS_2270_0s *)bk_vector_at(unqPtr->unk4,j); - sequence_time += randf2(1.0f, 1.5f); - timedFunc_set_2( - sequence_time, - (GenFunction_2)chTiptup_activatePattern, - reinterpret_cast(uintptr_t, this->marker), - s1->unk0); - timedFunc_set_2( - sequence_time + 0.1, - (GenFunction_2)chTiptup_activatePattern, - reinterpret_cast(uintptr_t, this->marker), - 0); + tmpf += randf2(1.0f, 1.5f); + timedFunc_set_2(tmpf, (GenFunction_2)chTiptup_activatePattern, (uintptr_t)this->marker, s1->unk0); + timedFunc_set_2(tmpf + 0.1, (GenFunction_2)chTiptup_activatePattern, (uintptr_t)this->marker, 0); } - timed_exitStaticCamera(sequence_time += 2.5); - func_80324E38(sequence_time + 0.6, 0); + timed_exitStaticCamera(tmpf += 2.5); + func_80324E38(tmpf + 0.6,0); bk_vector_clear(unqPtr->unk4); - this->state = CH_TIPTUP_STATE_5_WIN_MINIGAME; + this->state = 0x05; }//L80388D8C - if(this->state == CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG){ - if(unqPtr->round == TIPTUP_ROUND_FF){ + if(this->state == 6){ + if(unqPtr->unkA == 3){ coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); } func_80324E38(0.5f, 3); timed_setStaticCameraToNode(1.5f, 1); - func_80324DBC( - 2.0f, - chTiptupSuccessDialogs[unqPtr->round++], - 0xF, - this->position, - this->marker, - chTiptup_textEvent, - 0); + func_80324DBC(2.0f, D_8039085C[unqPtr->unkA++], 0xF, this->position, this->marker, chTiptup_textEvent, 0); } } -void chTiptup_bouncePlayerOff(ActorMarker *arg0, ActorMarker *arg1){ - func_8028F428(2, arg0); +void func_80388E44(ActorMarker *arg0, ActorMarker *arg1){ + func_8028F428(2,arg0); } -s32 chTiptup_getUnkB(ActorMarker *this){ +s32 func_80388E70(ActorMarker *this){ Actor *ptr; ActorLocal_Tiptup *local; @@ -325,34 +236,27 @@ void chTiptup_choirHitReaction(ActorMarker *this, s32 arg1){ thisActor = marker_getActor(this); unqPtr = (ActorLocal_Tiptup *)&thisActor->local; if((s32)unqPtr->unk0 >= (s32) bk_vector_size(unqPtr->unk4)){ - if(!mapSpecificFlags_get(CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY) - && gcdialog_showDialog(VER_SELECT(ASSET_C76_DIALOG_CHOIR_MEMBER_HIT_AFTER_JIGGY, 0x9B9, 0, 0), 0, 0, 0, 0, 0)) - { - mapSpecificFlags_set(CH_TIPTUP_SPECIFIC_FLAG_0_CHOIR_MEMBER_HIT_AFTER_JIGGY, 1); - } + if(!mapSpecificFlags_get(0) && gcdialog_showDialog(ASSET_C76_DIALOG_CHOIR_MEMBER_HIT_AFTER_JIGGY, 0, 0, 0, 0, 0)) + mapSpecificFlags_set(0,1); }else{ tmp = (Struct_BGS_2270_0s *)bk_vector_at(unqPtr->unk4, unqPtr->unk0); if(arg1 == tmp->unk0){ - timedFunc_set_1(0.5f, (GenFunction_1)chTiptup_correctHit, reinterpret_cast(uintptr_t, thisActor->marker)); + timedFunc_set_1(0.5f, (GenFunction_1)chTiptup_correctHit, (uintptr_t)thisActor->marker); } else{ func_8028F55C(1, thisActor->marker); timedFunc_set_0(0.5f, chTiptup_sfxIncorrectHit); - if(!mapSpecificFlags_get(CH_TIPTUP_SPECIFIC_FLAG_1_TIPTUP_MISS) - && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) - && gcdialog_showDialog(VER_SELECT(ASSET_C75_DIALOG_TIPTUP_MISS, 0x9B8, 0, 0), 0, NULL, NULL, NULL, NULL)) - { - mapSpecificFlags_set(CH_TIPTUP_SPECIFIC_FLAG_1_TIPTUP_MISS, TRUE); - } + if(!mapSpecificFlags_get(1) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && gcdialog_showDialog(ASSET_C75_DIALOG_TIPTUP_MISS, 0, NULL, NULL, NULL, NULL)) + mapSpecificFlags_set(1,true); } } } -void chTiptup_setMinigameProgress(Actor *this){ +void func_80388FC0(Actor *this){ ActorLocal_Tiptup *local; local = (ActorLocal_Tiptup *)&this->local; - fileProgressFlag_setN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, local->round, 2); + fileProgressFlag_setN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, local->unkA, 2); bk_vector_free(local->unk4); } @@ -366,88 +270,80 @@ void func_80388FFC(ActorMarker *this, s32 *arg1, f32* arg2){ *arg2 = 0.52 + (f64)localPtr->unk9 * 0.12; localPtr->unk9++; *arg1 = localPtr->unk9; + } void chTiptup_update(Actor *this){ f32 player_position[3]; ActorLocal_Tiptup *unqPtr; - f32 time_delta; - f32 sp38; // unused - f32 sp34; // unused - f32 sp30; // something about yaw + f32 sp3C; + f32 sp38; + f32 sp34; + f32 sp30; unqPtr = (ActorLocal_Tiptup *)&this->local; - time_delta = time_getDelta(); + sp3C = time_getDelta(); if(!this->volatile_initialized){ - this->volatile_initialized = TRUE; - this->marker->actorFreeFunc = chTiptup_setMinigameProgress; - marker_setCollisionScripts(this->marker, chTiptup_bouncePlayerOff, NULL, NULL); + this->volatile_initialized = true; + this->marker->actorFreeFunc = func_80388FC0; + marker_setCollisionScripts(this->marker, func_80388E44, NULL, NULL); unqPtr->unk0 = 0; unqPtr->unk4 = bk_vector_new(sizeof(Struct_BGS_2270_0s), 8); unqPtr->unk8 = 0; unqPtr->unk9 = 0; - unqPtr->round = fileProgressFlag_getN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, 2); + unqPtr->unkA = fileProgressFlag_getN(FILEPROG_0_TIPTUP_MINIGAME_PROGRESS, 2); unqPtr->unkB = 0; - unqPtr->animTimer = 0.0f; + unqPtr->unkC = 0.0f; if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ - unqPtr->round = TIPTUP_ROUND_FF; + unqPtr->unkA = 3; this->position_y = this->position_y - 300.0f; } - chTiptup_setState(this, CH_TIPTUP_STATE_1_IDLE); - if(jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP) - && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) - && !volatileFlag_get(VOLATILE_FLAG_1)) - { + chTiptup_setState(this, 1); + if(jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && !volatileFlag_get(VOLATILE_FLAG_1)) marker_despawn(this->marker); - } } else{ player_getPosition(player_position); - if(skeletalAnim_getAnimId(this->unk148) == ASSET_12C_ANIM_TIPTUP_TAPPING - && skeletalAnim_getLoopCount(this->unk148) > 0) - { + if(skeletalAnim_getAnimId(this->unk148) == ASSET_12C_ANIM_TIPTUP_TAPPING && skeletalAnim_getLoopCount(this->unk148) > 0){ skeletalAnim_set(this->unk148, ASSET_12B_ANIM_TIPTUP_IDLE, 1.0f, 9.0f); - unqPtr->animTimer = randf2(5.0f, 15.0f); + unqPtr->unkC = randf2(5.0f, 15.0f); } - if(ml_timer_update(&unqPtr->animTimer, time_delta)){ + if(ml_timer_update(&unqPtr->unkC, sp3C)){ skeletalAnim_set(this->unk148, ASSET_12C_ANIM_TIPTUP_TAPPING, 1.0f, 4.0f); } func_80258A4C(this->position, this->yaw - 90.0f, player_position, &sp38, &sp34, &sp30); - this->yaw = this->yaw + 5.0f * sp30; - if(this->state == CH_TIPTUP_STATE_1_IDLE){ + this->yaw = this->yaw + 5.0f*sp30; + if(this->state == 1){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(volatileFlag_get(VOLATILE_FLAG_3)){ - func_80324E38(0.0f, 0); - chTiptup_setState(this, CH_TIPTUP_STATE_3_FF_GIVE_SEQUENCE); + func_80324E38(0.0f,0); + chTiptup_setState(this, 3); } } else{ - if(ml_vec3f_distance(this->position, player_position) < 300.0f - && player_getTransformation() == TRANSFORM_1_BANJO - && !jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP)) - { - chTiptup_setState(this, CH_TIPTUP_STATE_2_INSTRUCTIONS_DIALOG); + if(ml_vec3f_distance(this->position, player_position) < 300.0f && player_getTransformation() == TRANSFORM_1_BANJO && !jiggyscore_isSpawned(JIGGY_27_BGS_TIPTUP)){ + chTiptup_setState(this, 2); } } } - if(this->state == CH_TIPTUP_STATE_5_WIN_MINIGAME){ + if(this->state == 5){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(item_empty(ITEM_0_HOURGLASS_TIMER)){ - item_set(ITEM_6_HOURGLASS, 1); - volatileFlag_set(VOLATILE_FLAG_3, 0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); + item_set(ITEM_6_HOURGLASS,1); + volatileFlag_set(VOLATILE_FLAG_3,0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON,0); } } //L80389370 else{ if(ml_vec3f_distance(this->position, player_position) >= 300.0f) - chTiptup_setState(this, CH_TIPTUP_STATE_1_IDLE); + chTiptup_setState(this, 1); } }//L803893A0 - if(this->state == CH_TIPTUP_STATE_6_AFTER_JIGGY_DIALOG){ + if(this->state == 6){ if(ml_vec3f_distance(this->position, player_position) < 300.0f && !unqPtr->unk8){ unqPtr->unk8 = 1; - gcdialog_showDialog(VER_SELECT(ASSET_C7D_DIALOG_TIPTUP_MEET_AFTER_JIGGY, 0x9C0, 0, 0), 4, 0, 0, 0, 0); + gcdialog_showDialog(ASSET_C7D_DIALOG_TIPTUP_MEET_AFTER_JIGGY, 4, 0, 0, 0, 0); } } } diff --git a/src/BGS/ch/yellowflibbit.c b/src/BGS/ch/yellowflibbit.c index bc30286b9..d167e5f95 100644 --- a/src/BGS/ch/yellowflibbit.c +++ b/src/BGS/ch/yellowflibbit.c @@ -360,7 +360,6 @@ void gChYellowFlibbit_update(Actor *this) { local->unk10[0] = (s16) (s32) this->position[0]; local->unk10[1] = (s16) (s32) this->position[1]; local->unk10[2] = (s16) (s32) this->position[2]; - this->state = 0; // [port] Zero-init, which vanilla did not need because of draw distance gChYellowFlibbit_setState(this, 1); if (jiggyscore_isSpawned(JIGGY_24_BGS_FLIBBITS) != 0) { marker_despawn(this->marker); diff --git a/src/BGS/ch/yumblie.c b/src/BGS/ch/yumblie.c index 7b2e90594..6c37db606 100644 --- a/src/BGS/ch/yumblie.c +++ b/src/BGS/ch/yumblie.c @@ -45,7 +45,7 @@ bool func_8038B160(Actor *this){ s32 temp_v0; local = (ActorLocal_Yumblie *)&this->local; - temp_v0 = chMrVileMinigame_getDialogIndex(local->game_marker); + temp_v0 = func_8038A9E0(local->game_marker); if ((temp_v0 == 1) || (temp_v0 == 4)) { return false; @@ -70,7 +70,7 @@ void chyumblie_set_state(Actor* this, enum chyumblie_state_e next_state){ if(next_state == 2){ this->yaw = randf2(0.0f, 360.0f); s0->unk4 = (sNetForcedPieceType >= 0) ? (u8)sNetForcedPieceType : func_8038B160(this); - chMrVileMinigame_newPiece(s0->game_marker, this->marker, this->position, s0->unk4); + chvilegame_new_piece(s0->game_marker, this->marker, this->position, s0->unk4); skeletalAnim_set(this->unk148, (s0->unk4)? ASSET_128_ANIM_GRUMBLIE_APPEAR : ASSET_125_ANIM_YUMBLIE_APPEAR, 0.0f, 1.5f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } @@ -198,7 +198,7 @@ void chyumblie_update(Actor *this){ sp50 = skeletalAnim_getProgress(this->unk148); if(this->state == YUMBLIE_STATE_1_UNDER_GROUND){ if(ml_timer_update(&s0->unk8, sp4C)){ - if(EventSystem_Should(VB_VILE_YUMBLIE_EMERGE, mapSpecificFlags_get(6) && (12 > chMrVileMinigame_getPieceCount(s0->game_marker)))){ + if(EventSystem_Should(VB_VILE_YUMBLIE_EMERGE, mapSpecificFlags_get(6) && (12 > chvilegame_get_piece_count(s0->game_marker)))){ chyumblie_set_state(this, YUMBLIE_STATE_2_APPEAR); } else{ diff --git a/src/BGS/checksums.c b/src/BGS/checksums.c deleted file mode 100644 index d802484b3..000000000 --- a/src/BGS/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: BGS/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsBGS; diff --git a/src/BGS/crc.c b/src/BGS/crc.c index 86979482f..96786bf61 100644 --- a/src/BGS/crc.c +++ b/src/BGS/crc.c @@ -1,8 +1,7 @@ // BanjoDecomp: crc.c #include -#include "checksums.h" -#include "version.h" -s32 D_80390B20 = VER_SELECT(0x00282B61, 0x002871C5, 0, 0); // BGS_TEXT_CRC1 -s32 D_80390B24 = VER_SELECT(0xccdaeea0, 0xEDE9F826, 0, 0); // BGS_TEXT_CRC2 -s32 D_80390B28 = VER_SELECT(0x0002DE6B, 0x0002EA91, 0, 0); // BGS_DATA_CRC1 +//TODO Implement CRC calculation in Makefile(?) +u32 D_80390B20 = 0x00282B61; //BGS.code CRC1 +u32 D_80390B24 = 0xccdaeea0; //BGS.code CRC2 +u32 D_80390B28 = 0x0002DE6B; //BGS.data CRC1 (with this value = 0) diff --git a/src/BGS/mrvileminigame.c b/src/BGS/minigame_vile.c similarity index 58% rename from src/BGS/mrvileminigame.c rename to src/BGS/minigame_vile.c index 7b68b78d4..707058982 100644 --- a/src/BGS/mrvileminigame.c +++ b/src/BGS/minigame_vile.c @@ -1,4 +1,4 @@ -// BanjoDecomp: BGS/mrvileminigame.c +// BanjoDecomp: code_3420.c #include #include "functions.h" #include "bk_math.h" @@ -6,7 +6,7 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/Network/Anchor/VileSync.h" -extern f32 *chMrVile_getPostion(ActorMarker *); +extern f32 *chVile_getPostion(ActorMarker *); extern void bundle_setRandomVelocity(f32); extern void func_802FDCB8(s32); @@ -21,122 +21,95 @@ typedef struct { // u8 pad1[3]; bk_vector(struct vilegame_piece) *game_pieces; BKModelBin *grumblie_model_bin; - u8 dialogIndex; - u8 mode; + u8 unkC; + u8 unkD; u8 player_score; u8 vile_score; f32 type_change_timer; ActorMarker *vile_marker; -}chMrVileMinigameActor; +}ActorLocal_BGS_3420; -void chMrVileMinigame_setState(Actor *this, s32 next_state); -void chMrVileMinigame_update(Actor *this); +void func_8038A068(Actor *this, s32 next_state); +void chvilegame_update(Actor *this); /* .data */ ActorInfo D_80390960 = { MARKER_C6_VILE_GAME_CTRL, ACTOR_138_VILE_GAME_CTRL, 0, 0, NULL, - chMrVileMinigame_update, NULL, func_80325340, + chvilegame_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; // Vile Wins -enum asset_e chMrVileMinigamePlayerLosesDialog[] = { +enum asset_e D_80390984[] = { 0, - VER_SELECT(ASSET_C66_DIALOG_MR_VILE_WINS_ROUND_1, 0x9A9, 0, 0), - VER_SELECT(ASSET_C68_DIALOG_MR_VILE_WINS_ROUND_2, 0x9AB, 0, 0), - VER_SELECT(ASSET_C6A_DIALOG_MR_VILE_WINS_ROUND_3, 0x9AD, 0, 0), - VER_SELECT(ASSET_C92_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_2, 0x9D5, 0, 0), - VER_SELECT(ASSET_C93_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_3, 0x9D6, 0, 0), - VER_SELECT(ASSET_C94_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_4, 0x9D7, 0, 0), + ASSET_C66_DIALOG_MR_VILE_WINS_ROUND_1, + ASSET_C68_DIALOG_MR_VILE_WINS_ROUND_2, + ASSET_C6A_DIALOG_MR_VILE_WINS_ROUND_3, + ASSET_C92_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_2, + ASSET_C93_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_3, + ASSET_C94_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_4, 0 }; // Player Wins -enum asset_e chMrVileMinigamePlayerWinsDialog[] = { +enum asset_e D_803909A4[] = { 0, - VER_SELECT(ASSET_C67_DIALOG_MR_VILE_ROUND_2_START, 0x9AA, 0, 0), - VER_SELECT(ASSET_C69_DIALOG_MR_VILE_ROUND_3_START, 0x9AC, 0, 0), + ASSET_C67_DIALOG_MR_VILE_ROUND_2_START, + ASSET_C69_DIALOG_MR_VILE_ROUND_3_START, 0, - VER_SELECT(ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, 0x9D8, 0, 0), - VER_SELECT(ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, 0x9D9, 0, 0), - VER_SELECT(ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3, 0x9DA, 0, 0) + ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, + ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, + ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3 }; // Player Wins Rematch -enum asset_e chMrVileMinigamePlayerWinsRematchDialog[] = { +enum asset_e D_803909C0[] = { 0, - VER_SELECT(ASSET_C6E_DIALOG_MR_VILE_LOSE_ROUND_2_REMATCH, 0x9B1, 0, 0), - VER_SELECT(ASSET_C6F_DIALOG_MR_VILE_LOSE_ROUND_3_REMATCH, 0x9B2, 0, 0), + ASSET_C6E_DIALOG_MR_VILE_LOSE_ROUND_2_REMATCH, + ASSET_C6F_DIALOG_MR_VILE_LOSE_ROUND_3_REMATCH, 0, - VER_SELECT(ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, 0x9D8, 0, 0), - VER_SELECT(ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, 0x9D9, 0, 0), - VER_SELECT(ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3, 0x9DA, 0, 0) + ASSET_C95_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_1, + ASSET_C96_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_2, + ASSET_C97_DIALOG_MR_VILE_LOSES_EXTRA_CHALLENGE_3 }; -enum asset_e chMrVileMinigamePlayerDeclinesDialog[] = { - VER_SELECT(ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, 0x9A8, 0, 0), - VER_SELECT(ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, 0x9A8, 0, 0), - VER_SELECT(ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, 0x9A8, 0, 0), - VER_SELECT(ASSET_C8F_DIALOG_MR_VILE_PLAYER_DECLINES_EXTRA_CHALLENGE, 0x9D2, 0, 0), +// Player Declines +enum asset_e D_803909DC[] = { + ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, + ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, + ASSET_C65_DIALOG_MR_VILE_PLAYER_DECLINES, + ASSET_C8F_DIALOG_MR_VILE_PLAYER_DECLINES_EXTRA_CHALLENGE, 0, 0, 0 }; -enum asset_e chMrVileMinigameRound1AndChallengeDialog[] = { - VER_SELECT(ASSET_C64_DIALOG_MR_VILE_ROUND_1_START, 0x9A7, 0, 0), +// Round 1 Regular & Extra Challenge +enum asset_e BGS_D_803909F8[] = { + ASSET_C64_DIALOG_MR_VILE_ROUND_1_START, 0, 0, - VER_SELECT(ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0x9D1, 0, 0), + ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0, 0, 0, 0 }; -enum asset_e chMrVileMinigameRematchDialog[] = { - VER_SELECT(ASSET_C6D_DIALOG_MR_VILE_LOSE_ROUND_1_REMATCH, 0x9B0, 0, 0), - VER_SELECT(ASSET_C70_DIALOG_MR_VILE_WIN_ROUND_2_REMATCH, 0x9B3, 0, 0), - VER_SELECT(ASSET_C71_DIALOG_MR_VILE_WIN_ROUND_3_REMATCH, 0x9B4, 0, 0), - VER_SELECT(ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0x9D1, 0, 0), +enum asset_e D_80390A18[] = { + ASSET_C6D_DIALOG_MR_VILE_LOSE_ROUND_1_REMATCH, + ASSET_C70_DIALOG_MR_VILE_WIN_ROUND_2_REMATCH, + ASSET_C71_DIALOG_MR_VILE_WIN_ROUND_3_REMATCH, + ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0, 0, 0, 0 }; -enum MrVileMinigameState { - MR_VILE_MINIGAME_STATE_0_NO_INIT = 0, - MR_VILE_MINIGAME_STATE_1_IDLE, - MR_VILE_MINIGAME_STATE_2_YES_OR_NO, - MR_VILE_MINIGAME_STATE_3_DECLINE_MINIGAME, - MR_VILE_MINIGAME_STATE_4_ROUND_INTRO_EXPLANATION, - MR_VILE_MINIGAME_STATE_5_PLAYING_MINIGAME, - MR_VILE_MINIGAME_STATE_6_VILE_WINS, - MR_VILE_MINIGAME_STATE_7_ATTACK_PLAYER, - MR_VILE_MINIGAME_STATE_8_PLAYER_WINS, - MR_VILE_MINIGAME_STATE_9_DROP_JIGGY, - MR_VILE_MINIGAME_STATE_A_DROP_EXTRA_LIVES -}; - -enum MrVileMinigameMode { - MR_VILE_MINIGAME_MODE_0_ROUND_1 = 0, - MR_VILE_MINIGAME_MODE_1_ROUND_2, - MR_VILE_MINIGAME_MODE_2_ROUND_3, - MR_VILE_MINIGAME_MODE_3_CHALLENGE_1_AND_FF, - MR_VILE_MINIGAME_MODE_4_CHALLENGE_2, - MR_VILE_MINIGAME_MODE_4_CHALLENGE_3 -}; - -#define MR_VILE_MINIGAME_TIMER VER_SELECT(3600, 3000, 0, 0) -#define TYPE_CHANGE_TIMER_REGULAR 10.0f -#define TYPE_CHANGE_TIMER_FF 5.0f -#define EXTRA_LIFE_SCORE 35 -#define MAX_DISTANCE_FROM_PIECE 65.25 - /* .code */ -bool chMrVileMinigame_didPlayerConsumePiece(f32 arg0[3]) { +bool BGS_func_80389810(f32 arg0[3]) { if (player_movementGroup() != BSGROUP_7_CROC_ATTACK) { return false; } @@ -144,8 +117,8 @@ bool chMrVileMinigame_didPlayerConsumePiece(f32 arg0[3]) { return true; } -void chMrVileMinigame_spawnJiggy(Actor *this, s32 arg1) { - chMrVileMinigameActor *local; +void BGS_func_80389850(Actor *this, s32 arg1) { + ActorLocal_BGS_3420 *local; Actor *vile; f32 sp94[3]; f32 sp88[3]; @@ -153,7 +126,7 @@ void chMrVileMinigame_spawnJiggy(Actor *this, s32 arg1) { s32 var_s0; s32 var_v0; - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; vile = marker_getActor(local->vile_marker); if (arg1 != 0) { if (LENGTH_VEC3F(this->position) < 800.0f) { @@ -201,127 +174,120 @@ void chMrVileMinigame_spawnJiggy(Actor *this, s32 arg1) { ncStaticCamera_setPositionAndRotation(sp94, sp88); } -void chMrVileMinigame_vileOffersMinigame(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void func_80389B48(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); if(arg2 == 1){ - chMrVileMinigame_setState(this, 4); + func_8038A068(this, 4); } else{ - chMrVileMinigame_setState(this, 3); + func_8038A068(this, 3); } } -void chMrVileMinigame_setStateIdleAfterDeclined(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void func_80389B98(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); - chMrVileMinigame_setState(this, 1); + func_8038A068(this, 1); } -void chMrVileMinigame_setStatePlayingMinigame(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void func_80389BC8(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); - chMrVileMinigame_setState(this, 5); + func_8038A068(this, 5); } -void chMrVileMinigame_vileAttacksPlayer(ActorMarker *marker, enum asset_e text_id, s32 arg2) { +void func_80389BF8(ActorMarker *marker, enum asset_e text_id, s32 arg2) { Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - local->dialogIndex--; - chMrVileMinigame_setState(this, 7); + local->unkC--; + func_8038A068(this, 7); } -void chMrVileMinigame_vileWinsRound(ActorMarker *marker) { +void func_80389C58(ActorMarker *marker) { Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; - chMrVileMinigame_spawnJiggy(this, 0); - gcdialog_showDialog(chMrVileMinigamePlayerLosesDialog[local->dialogIndex], 0xF, chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_vileAttacksPlayer, NULL); + local = (ActorLocal_BGS_3420 *)&this->local; + BGS_func_80389850(this, 0); + gcdialog_showDialog(D_80390984[local->unkC], 0xF, chVile_getPostion(local->vile_marker), this->marker, func_80389BF8, NULL); } -void chMrVileMinigame_startNextRound(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void BGS_func_80389CD8(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - chMrVileMinigame_setState(this, 5); + func_8038A068(this, 5); } -void chMrVileMinigame_playerWinsRound(ActorMarker *marker) { +void func_80389D20(ActorMarker *marker) { Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; - chMrVileMinigame_spawnJiggy(this, 0); - if (local->dialogIndex == local->mode) { - gcdialog_showDialog(chMrVileMinigamePlayerWinsDialog[local->dialogIndex], 0xF, chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_startNextRound, NULL); + local = (ActorLocal_BGS_3420 *)&this->local; + BGS_func_80389850(this, 0); + if (local->unkC == local->unkD) { + gcdialog_showDialog(D_803909A4[local->unkC], 0xF, chVile_getPostion(local->vile_marker), this->marker, BGS_func_80389CD8, NULL); } else { - gcdialog_showDialog(chMrVileMinigamePlayerWinsRematchDialog[local->dialogIndex], 0xF, chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_startNextRound, NULL); + gcdialog_showDialog(D_803909C0[local->unkC], 0xF, chVile_getPostion(local->vile_marker), this->marker, BGS_func_80389CD8, NULL); } func_80347A14(0); } -void chMrVileMinigame_setStateIdleAfterDeclinedAfterJiggy(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void func_80389DF8(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; this = marker_getActor(marker); timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - chMrVileMinigame_setState(this, 1); + func_8038A068(this, 1); } -void chMrVileMinigame_vileDropsJiggy(ActorMarker *marker) { +void func_80389E40(ActorMarker *marker) { Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; - - chMrVileMinigame_spawnJiggy(this, 1); - gcdialog_showDialog( - VER_SELECT(ASSET_C6B_DIALOG_MR_VILE_PLAYER_WINS, 0x9AE, 0, 0), - 0xF, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_setStateIdleAfterDeclinedAfterJiggy, - NULL - ); + local = (ActorLocal_BGS_3420 *)&this->local; + + BGS_func_80389850(this, 1); + gcdialog_showDialog(0xC6B, 0xF, chVile_getPostion(local->vile_marker), this->marker, func_80389DF8, NULL); } -void chMrVileMinigame_setStateIdleAfterExtraLives(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void func_80389EAC(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); - local->dialogIndex = 3; - chMrVileMinigame_setState(this, 1); + local->unkC = 3; + func_8038A068(this, 1); } -void chMrVileMinigame_vileDropsExtraLives(ActorMarker *marker) { +void func_80389F08(ActorMarker *marker) { Actor *vile; Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; s32 i; s32 var_s2; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; - chMrVileMinigame_spawnJiggy(this, 0); + local = (ActorLocal_BGS_3420 *)&this->local; + BGS_func_80389850(this, 0); var_s2 = actorArray_actorCount(ACTOR_49_EXTRA_LIFE); vile = marker_getActor(local->vile_marker); if (var_s2 > 0) { @@ -337,14 +303,7 @@ void chMrVileMinigame_vileDropsExtraLives(ActorMarker *marker) { item_inc(ITEM_16_LIFE); } } - gcdialog_showDialog( - VER_SELECT(ASSET_C98_DIALOG_MR_VILE_GIVES_PRIZE, 0x9DB, 0, 0), - 0xF, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_setStateIdleAfterExtraLives, - NULL - ); + gcdialog_showDialog(0xC98, 0xF, chVile_getPostion(local->vile_marker), this->marker, func_80389EAC, NULL); } @@ -352,85 +311,46 @@ void func_8038A044(void){ func_8025A58C(-1, 400); } -void chMrVileMinigame_setState(Actor *this, s32 next_state) { - chMrVileMinigameActor *local; +void func_8038A068(Actor *this, s32 next_state) { + ActorLocal_BGS_3420 *local; - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; mapSpecificFlags_set(6, false); if (next_state == 1) { if (local->vile_marker != NULL) { - chMrVile_setStateIdleWalking(local->vile_marker); + func_8038C408(local->vile_marker); } } - if (next_state == MR_VILE_MINIGAME_STATE_2_YES_OR_NO) { - chMrVile_setStateTalkToPlayer(local->vile_marker); - if (local->dialogIndex == 3) { - if (local->mode >= MR_VILE_MINIGAME_MODE_4_CHALLENGE_2) { - gcdialog_showDialog( - VER_SELECT(ASSET_C91_DIALOG_MR_VILE_EXTRA_CHALLENGE_REMATCH_2, 0x9D4, 0, 0), - 0xE, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_vileOffersMinigame, - NULL - ); + if (next_state == 2) { + func_8038C3B0(local->vile_marker); + if (local->unkC == 3) { + if (local->unkD >= 4) { + gcdialog_showDialog(0xC91, 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389B48, NULL); } else { - gcdialog_showDialog( - (local->dialogIndex == local->mode) ? - VER_SELECT(ASSET_C8D_DIALOG_MR_VILE_EXTRA_CHALLENGE_INTRO, 0x9D0, 0, 0) : - VER_SELECT(ASSET_C90_DIALOG_MR_VILE_EXTRA_CHALLENGE_REMATCH_1, 0x9D3, 0, 0), - 0xE, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_vileOffersMinigame, - NULL - ); + gcdialog_showDialog((local->unkC == local->unkD) ? 0xC8D : 0xC90, 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389B48, NULL); } } else { - gcdialog_showDialog( - (local->dialogIndex == local->mode) ? - VER_SELECT(ASSET_C63_DIALOG_MR_VILE_INTRO, 0x9A6, 0, 0) : - VER_SELECT(ASSET_C6C_DIALOG_MR_VILE_TRY_AGAIN, 0x9AF, 0, 0), - 0xE, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_vileOffersMinigame, - NULL - ); + gcdialog_showDialog((local->unkC == local->unkD) ? 0xC63 : 0xC6C, 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389B48, NULL); } } - if (next_state == MR_VILE_MINIGAME_STATE_3_DECLINE_MINIGAME) { - gcdialog_showDialog( - chMrVileMinigamePlayerDeclinesDialog[local->dialogIndex], - 4, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_setStateIdleAfterDeclined, - NULL - ); - } - if (next_state == MR_VILE_MINIGAME_STATE_4_ROUND_INTRO_EXPLANATION) { - if (local->dialogIndex == local->mode) { - gcdialog_showDialog( - chMrVileMinigameRound1AndChallengeDialog[local->dialogIndex], - 0xE | ((chMrVileMinigameRound1AndChallengeDialog[local->dialogIndex] == VER_SELECT(ASSET_C8E_DIALOG_MR_VILE_WINS_EXTRA_CHALLENGE_1, 0x9D1, 0, 0)) ? 1 : 0) | 0xE, - chMrVile_getPostion(local->vile_marker), - this->marker, - chMrVileMinigame_setStatePlayingMinigame, - NULL - ); + if (next_state == 3) { + gcdialog_showDialog(D_803909DC[local->unkC], 4, chVile_getPostion(local->vile_marker), this->marker, func_80389B98, NULL); + } + if (next_state == 4) { + if (local->unkC == local->unkD) { + gcdialog_showDialog(BGS_D_803909F8[local->unkC], 0xE | ((BGS_D_803909F8[local->unkC] == 0xC8E) ? 1 : 0) | 0xE, chVile_getPostion(local->vile_marker), this->marker, func_80389BC8, NULL); } else { - gcdialog_showDialog(chMrVileMinigameRematchDialog[local->dialogIndex], 0xF , chMrVile_getPostion(local->vile_marker), this->marker, chMrVileMinigame_setStatePlayingMinigame, NULL); + gcdialog_showDialog(D_80390A18[local->unkC], 0xF , chVile_getPostion(local->vile_marker), this->marker, func_80389BC8, NULL); } func_80347A14(0); } if (next_state == 5) { - local->dialogIndex++; - if (local->mode < local->dialogIndex) { - local->mode = local->dialogIndex; + local->unkC++; + if (local->unkD < local->unkC) { + local->unkD = local->unkC; } - if (local->dialogIndex == 7) { - chMrVile_setStateRunFromPlayer(local->vile_marker); + if (local->unkC == 7) { + BGS_func_8038C434(local->vile_marker); } else { local->current_type = YUMBLIE; local->player_score = 0; @@ -443,69 +363,69 @@ void chMrVileMinigame_setState(Actor *this, s32 next_state) { item_set(ITEM_0_HOURGLASS_TIMER, 3600-1); item_set(ITEM_6_HOURGLASS, true); mapSpecificFlags_set(6, true); - chMrVile_setStatePlayMinigame(local->vile_marker); + func_8038C3DC(local->vile_marker); func_8025A58C(0, 4000); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_55_BGS_MR_VILE, 28000); } } if (this->state == 5) { - if (local->dialogIndex != 7) { + if (local->unkC != 7) { item_set(ITEM_6_HOURGLASS, false); if ((next_state != 6) && (next_state != 8) && (next_state != 9)) { func_8038A044(); } } - chMrVile_setInitialIdleStill(local->vile_marker); + BGS_func_8038C460(local->vile_marker); func_80347A14(1); } if (next_state == 6) { - chMrVile_setStateTalkToPlayer(local->vile_marker); + func_8038C3B0(local->vile_marker); func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3C_MINIGAME_LOSS, 28000); timedFunc_set_0(4.0f, (GenFunction_0)func_8038A044); - timedFunc_set_1(4.0f, (GenFunction_1)chMrVileMinigame_vileWinsRound, (uintptr_t)this->marker); + timedFunc_set_1(4.0f, (GenFunction_1)func_80389C58, (uintptr_t)this->marker); } if (next_state == 8) { - chMrVile_setStateTalkToPlayer(local->vile_marker); + func_8038C3B0(local->vile_marker); func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3B_MINIGAME_VICTORY, 28000); timedFunc_set_0(3.0f, (GenFunction_0)func_8038A044); - timedFunc_set_1(3.0f, (GenFunction_1)chMrVileMinigame_playerWinsRound, (uintptr_t)this->marker); + timedFunc_set_1(3.0f, (GenFunction_1)func_80389D20, (uintptr_t)this->marker); } if (next_state == 9) { - chMrVile_setStateTalkToPlayer(local->vile_marker); + func_8038C3B0(local->vile_marker); func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3B_MINIGAME_VICTORY, 28000); timedFunc_set_0(3.0f, (GenFunction_0)func_8038A044); - timedFunc_set_1(3.0f, (GenFunction_1)chMrVileMinigame_vileDropsJiggy, (uintptr_t)this->marker); + timedFunc_set_1(3.0f, (GenFunction_1)func_80389E40, (uintptr_t)this->marker); } if (next_state == 0xA) { - chMrVile_setStateTalkToPlayer(local->vile_marker); + func_8038C3B0(local->vile_marker); func_80324E38(0.5f, 3); timedFunc_set_2(1.0f, (GenFunction_2) coMusicPlayer_playMusic, COMUSIC_3B_MINIGAME_VICTORY, 28000); - timedFunc_set_1(3.0f, (GenFunction_1) chMrVileMinigame_vileDropsExtraLives, (uintptr_t)this->marker); + timedFunc_set_1(3.0f, (GenFunction_1) func_80389F08, (uintptr_t)this->marker); } if (next_state == 7) { - chMrVile_setStateAttackPlayer(local->vile_marker); + func_8038C384(local->vile_marker); } this->state = next_state; // [port] Anchor: authority claim/release and round lifecycle react to this event CALL_EVENT(OnVileGameStateChange, next_state); } -void chMrVileMinigame_playerConsumePiece(Actor *this) { - chMrVileMinigameActor *local; +void chvilegame_player_consume_piece(Actor *this) { + ActorLocal_BGS_3420 *local; bool is_correct_type; f32 sp44[3]; struct vilegame_piece *begin; struct vilegame_piece *end; struct vilegame_piece *i_ptr; - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; begin = (struct vilegame_piece *)bk_vector_getBegin(local->game_pieces); end = (struct vilegame_piece *) bk_vector_getEnd(local->game_pieces); - if ((end != begin) && chMrVileMinigame_didPlayerConsumePiece(sp44)){ + if ((end != begin) && BGS_func_80389810(sp44)){ sp44[1] = 0.0f; for(i_ptr = begin; i_ptr < end; i_ptr++){ if ((ml_vec3f_distance(i_ptr->position, sp44) < 65.25) && chyumblie_is_edible(i_ptr->marker)) { @@ -535,15 +455,15 @@ void chMrVileMinigame_playerConsumePiece(Actor *this) { } } -bool chMrVileMinigame_mrVileConsumePiece(ActorMarker *marker, f32 position[3]) { +bool chvilegame_cpu_consume_piece(ActorMarker *marker, f32 position[3]) { Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; struct vilegame_piece *begin; struct vilegame_piece *end; struct vilegame_piece *i_ptr; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; if (this->state != 5){ return false; } @@ -563,49 +483,49 @@ bool chMrVileMinigame_mrVileConsumePiece(ActorMarker *marker, f32 position[3]) { BKModelBin *chvilegame_get_grumblie_model(ActorMarker *marker){ Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; return local->grumblie_model_bin; } -s32 chMrVileMinigame_getPieceCount(ActorMarker *marker){ +s32 chvilegame_get_piece_count(ActorMarker *marker){ Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; return bk_vector_size(local->game_pieces); } -s32 chMrVileMinigame_getDialogIndex(ActorMarker *marker){ +s32 func_8038A9E0(ActorMarker *marker){ Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; - return local->dialogIndex; + local = (ActorLocal_BGS_3420 *)&this->local; + return local->unkC; } -s32 chMrVileMinigame_getScoreDifference(ActorMarker *marker){ +s32 chvilegame_get_score_difference(ActorMarker *marker){ Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; return local->vile_score - local->player_score; } -bool chMrVileMinigame_findClosestPiece(ActorMarker *marker, f32 position[3], f32 yaw, f32 dst[3]) { +bool chvilegame_find_closest_piece(ActorMarker *marker, f32 position[3], f32 yaw, f32 dst[3]) { f32 piece_direction[3]; f32 target_direction[3]; Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; struct vilegame_piece *closest_piece; struct vilegame_piece *begin; struct vilegame_piece *end; @@ -614,7 +534,7 @@ bool chMrVileMinigame_findClosestPiece(ActorMarker *marker, f32 position[3], f32 f32 angle_diff; this = marker_getActor(marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; target_direction[0] = 0.0f; target_direction[1] = 0.0f; target_direction[2] = 100.0f; @@ -649,13 +569,13 @@ bool chMrVileMinigame_findClosestPiece(ActorMarker *marker, f32 position[3], f32 return false; } -void chMrVileMinigame_newPiece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type){ +void chvilegame_new_piece(ActorMarker *game_marker, ActorMarker *piece_marker, f32 position[3], u32 yumblie_type){ Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; struct vilegame_piece *temp_v0; this = marker_getActor(game_marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; temp_v0 = (struct vilegame_piece *)bk_vector_pushBackNew(&local->game_pieces); temp_v0->type = yumblie_type; temp_v0->marker = piece_marker; @@ -665,14 +585,14 @@ void chMrVileMinigame_newPiece(ActorMarker *game_marker, ActorMarker *piece_mark temp_v0->position[1] = 0.0f; } -void chMrVileMinigame_free(Actor *this){ - chMrVileMinigameActor *local; +void chvilegame_free(Actor *this){ + ActorLocal_BGS_3420 *local; - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; // [port] Teardown ordering hazard: if Mr Vile is freed before this controller, its skeletal - // anim (unk148) is already NULL and chMrVileMinigame_setState(this, 0) -> skeletalAnim_set crashes. Skip it. + // anim (unk148) is already NULL and func_8038A068(this, 0) -> skeletalAnim_set crashes. Skip it. #if 0 - chMrVileMinigame_setState(this, 0); + func_8038A068(this, 0); #endif bk_vector_free(local->game_pieces); assetcache_release(local->grumblie_model_bin); @@ -680,13 +600,13 @@ void chMrVileMinigame_free(Actor *this){ void chvilegame_remove_piece(ActorMarker *game_marker, ActorMarker *piece_marker) { Actor *this; - chMrVileMinigameActor *local; + ActorLocal_BGS_3420 *local; struct vilegame_piece *begin; struct vilegame_piece *end; struct vilegame_piece *i_ptr; this = marker_getActor(game_marker); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; begin = (struct vilegame_piece *)bk_vector_getBegin(local->game_pieces); end = (struct vilegame_piece *)bk_vector_getEnd(local->game_pieces); for(i_ptr = begin; i_ptr < end; i_ptr++){ @@ -697,8 +617,8 @@ void chvilegame_remove_piece(ActorMarker *game_marker, ActorMarker *piece_marker } } -void chMrVileMinigame_update(Actor *this) { - chMrVileMinigameActor *local; +void chvilegame_update(Actor *this) { + ActorLocal_BGS_3420 *local; f32 sp50; f32 sp4C; u8 temp_v0; @@ -706,28 +626,28 @@ void chMrVileMinigame_update(Actor *this) { s32 sp2C; sp50 = time_getDelta(); - local = (chMrVileMinigameActor *)&this->local; + local = (ActorLocal_BGS_3420 *)&this->local; if (!this->volatile_initialized) { this->volatile_initialized = true; - this->marker->actorFreeFunc = &chMrVileMinigame_free; + this->marker->actorFreeFunc = &chvilegame_free; local->game_pieces = bk_vector_new(sizeof(struct vilegame_piece), 0x20); local->grumblie_model_bin = assetcache_get(0x3F7); - local->dialogIndex = 0; + local->unkC = 0; local->vile_marker = NULL; if (this->state == 0) { - local->mode = 0; + local->unkD = 0; } else { this->state = 0; } if (jiggyscore_isSpawned(JIGGY_28_BGS_MR_VILE)) { - local->dialogIndex = 3; - local->mode = 3; + local->unkC = 3; + local->unkD = 3; } if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - local->dialogIndex = 2; - local->mode = 3; + local->unkC = 2; + local->unkD = 3; } - chMrVileMinigame_setState(this, 1); + func_8038A068(this, 1); return; } if (local->vile_marker == NULL) { @@ -736,8 +656,8 @@ void chMrVileMinigame_update(Actor *this) { // [port] Anchor: followers are driven by snapshots; only local chomp detection (for // eat requests) and HUD mirroring run here. if (!EventSystem_Should(VB_VILE_GAME_UPDATE, true)) { - if ((this->state == 5) && (local->dialogIndex != 7)) { - chMrVileMinigame_playerConsumePiece(this); + if ((this->state == 5) && (local->unkC != 7)) { + chvilegame_player_consume_piece(this); if (local->type_change_timer > 3.5) { if (local->current_type != 0) { item_adjustByDiffWithHud(ITEM_1D_GRUMBLIE, false); @@ -754,21 +674,21 @@ void chMrVileMinigame_update(Actor *this) { if (this->state == 1) { if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { if (volatileFlag_get(VOLATILE_FLAG_3)) { - chMrVileMinigame_setState(this, 5); + func_8038A068(this, 5); } - } else if (chMrVile_playerWithinRange(local->vile_marker)) { - chMrVileMinigame_setState(this, 2); + } else if (func_8038C2A8(local->vile_marker)) { + func_8038A068(this, 2); } } if (this->state == 5) { - if (local->dialogIndex == 7) { + if (local->unkC == 7) { controller_copyFaceButtons(0, sp30); - if ((sp30[FACE_BUTTON(BUTTON_B)] > 0) && chMrVile_playerWithinRange(local->vile_marker)) { - chMrVileMinigame_setState(this, 0xA); + if ((sp30[FACE_BUTTON(BUTTON_B)] > 0) && func_8038C2A8(local->vile_marker)) { + func_8038A068(this, 0xA); } } else { - chMrVileMinigame_playerConsumePiece(this); - if ((local->dialogIndex == 3) || (local->dialogIndex == 6)) { + chvilegame_player_consume_piece(this); + if ((local->unkC == 3) || (local->unkC == 6)) { if (ml_timer_update(&local->type_change_timer, sp50)) { local->current_type = !local->current_type; if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { @@ -795,21 +715,21 @@ void chMrVileMinigame_update(Actor *this) { if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { volatileFlag_set(VOLATILE_FLAG_3, 0); volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, BOOL(local->vile_score < local->player_score)); - chMrVileMinigame_setState(this, 1); + func_8038A068(this, 1); } else if (local->vile_score < local->player_score) { - if (local->dialogIndex == 3) { - chMrVileMinigame_setState(this, 9); + if (local->unkC == 3) { + func_8038A068(this, 9); } else { - chMrVileMinigame_setState(this, 8); + func_8038A068(this, 8); } } else { - chMrVileMinigame_setState(this, 6); + func_8038A068(this, 6); } } } } - if ((this->state == 7) && (chMrVile_isInitialIdle(local->vile_marker) != 0)) { - chMrVileMinigame_setState(this, 1); + if ((this->state == 7) && (BGS_func_8038C338(local->vile_marker) != 0)) { + func_8038A068(this, 1); } } @@ -818,7 +738,7 @@ void chMrVileMinigame_update(Actor *this) { // Fills a snapshot from the live controller. Only the stable states (idle, playing, and // the round-end results) are broadcast; dialog states cannot be reconstructed remotely. bool chvilegame_netGather(Actor *this, VileGameSnapshot *dst){ - chMrVileMinigameActor *local = (chMrVileMinigameActor *)&this->local; + ActorLocal_BGS_3420 *local = (ActorLocal_BGS_3420 *)&this->local; switch (this->state) { case 1: // idle @@ -832,8 +752,8 @@ bool chvilegame_netGather(Actor *this, VileGameSnapshot *dst){ return false; } dst->gameState = this->state; - dst->round = local->dialogIndex; - dst->maxRound = local->mode; + dst->round = local->unkC; + dst->maxRound = local->unkD; dst->currentType = local->current_type; dst->typeChangeTimer = local->type_change_timer; dst->playerScore = local->player_score; @@ -843,13 +763,13 @@ bool chvilegame_netGather(Actor *this, VileGameSnapshot *dst){ } // Forces the controller to match an authoritative snapshot (followers + late joiners). -// Mirrors the state-5 side effects of chMrVileMinigame_setState without the dialog/round bookkeeping. +// Mirrors the state-5 side effects of func_8038A068 without the dialog/round bookkeeping. void chvilegame_netApply(Actor *this, const VileGameSnapshot *src){ - chMrVileMinigameActor *local = (chMrVileMinigameActor *)&this->local; + ActorLocal_BGS_3420 *local = (ActorLocal_BGS_3420 *)&this->local; s32 drift; - local->dialogIndex = src->round; - local->mode = src->maxRound; + local->unkC = src->round; + local->unkD = src->maxRound; local->current_type = src->currentType; local->type_change_timer = src->typeChangeTimer; local->player_score = src->playerScore; @@ -863,14 +783,14 @@ void chvilegame_netApply(Actor *this, const VileGameSnapshot *src){ item_set(ITEM_6_HOURGLASS, true); mapSpecificFlags_set(6, true); if (local->vile_marker != NULL) { - chMrVile_setStatePlayMinigame(local->vile_marker); + func_8038C3DC(local->vile_marker); } func_8025A58C(0, 4000); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_55_BGS_MR_VILE, 28000); } else { item_set(ITEM_6_HOURGLASS, false); mapSpecificFlags_set(6, false); - // Round-end result presentation, mirroring chMrVileMinigame_setState's timed callbacks + // Round-end result presentation, mirroring func_8038A068's timed callbacks // (dialogs and the static camera stay on the authority). if (src->gameState == 6) { timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_3C_MINIGAME_LOSS, 28000); @@ -893,13 +813,13 @@ void chvilegame_netApply(Actor *this, const VileGameSnapshot *src){ } // Authority-side: consume the piece at position on behalf of a remote player. Mirrors -// chMrVileMinigame_playerConsumePiece without reading the local player's mouth position. -// position[1] must be 0 to match piece positions (see chMrVileMinigame_newPiece). +// chvilegame_player_consume_piece without reading the local player's mouth position. +// position[1] must be 0 to match piece positions (see chvilegame_new_piece). // On success, reports the consumed piece's type and whether it matched the required // type so the requesting client can replay the croc's eat feedback (see // chvilegame_netPlayEatFeedback). bool chvilegame_netConsumeRemote(Actor *this, f32 position[3], s32 *out_piece_type, s32 *out_correct_type){ - chMrVileMinigameActor *local = (chMrVileMinigameActor *)&this->local; + ActorLocal_BGS_3420 *local = (ActorLocal_BGS_3420 *)&this->local; bool is_correct_type; struct vilegame_piece *begin; struct vilegame_piece *end; @@ -933,7 +853,7 @@ bool chvilegame_netConsumeRemote(Actor *this, f32 position[3], s32 *out_piece_ty // remote eat request: the croc chomp animation (which carries the chomp SFX) plus // the wrong-type reaction when the eaten piece didn't match the required type. The // score and piece removal are authority-driven and arrive separately; this is the -// cosmetic half of chMrVileMinigame_playerConsumePiece that the follower otherwise skips. +// cosmetic half of chvilegame_player_consume_piece that the follower otherwise skips. void chvilegame_netPlayEatFeedback(s32 piece_type, s32 correct_type){ func_8028F6B8(BS_INTR_17, (piece_type != YUMBLIE) ? ASSET_3F7_MODEL_GRUMBLIE : ASSET_3F6_MODEL_YUMBLIE); if (!correct_type) { diff --git a/src/CC/ccspawnqueue.c b/src/CC/actor_spawninit.c similarity index 98% rename from src/CC/ccspawnqueue.c rename to src/CC/actor_spawninit.c index 573976ea3..58cfe57a2 100644 --- a/src/CC/ccspawnqueue.c +++ b/src/CC/actor_spawninit.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CC/ccspawnqueue.c +// BanjoDecomp: code_19B0.c #include #include "functions.h" #include "variables.h" diff --git a/src/CC/bss_pad.c b/src/CC/bss_pad.c new file mode 100644 index 000000000..e4ba390c4 --- /dev/null +++ b/src/CC/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_CC_D_80389F70[0x10]; diff --git a/src/CC/ch/ccgrates.c b/src/CC/ch/clanker.c similarity index 73% rename from src/CC/ch/ccgrates.c rename to src/CC/ch/clanker.c index 2bfc9f718..b9043260e 100644 --- a/src/CC/ch/ccgrates.c +++ b/src/CC/ch/clanker.c @@ -1,11 +1,8 @@ -// BanjoDecomp: CC/ch/ccgrates.c +// BanjoDecomp: code_3400.c #include #include "functions.h" #include "variables.h" -extern void port_breakable_recordBreak(s32 markerId, s32 x, s32 y, s32 z); -extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); - typedef struct { u8 *unk0; f32 unk4; @@ -68,8 +65,6 @@ void chCCGrate_die(ActorMarker *marker, ActorMarker *other_marker){ if(actor->state == 1){ chCCGrate_setNextState(actor, *local->unk0); - port_breakable_recordBreak((s32)actor->marker->id, (s32)actor->position[0], - (s32)actor->position[1], (s32)actor->position[2]); } } @@ -87,18 +82,11 @@ void chCCGrate_update(Actor * this){ if(this->modelCacheIndex == 0x28E && jiggyscore_isSpawned(JIGGY_18_CC_BOLT)){ marker_despawn(this->marker); } - else if(port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, - (s32)this->position[0], (s32)this->position[1], - (s32)this->position[2])){ - marker_despawn(this->marker); - } return; }//L803899D4 if(this->state == 1){ - if(local->unk8 || port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, - (s32)this->position[0], (s32)this->position[1], - (s32)this->position[2])){ + if(local->unk8){ chCCGrate_setNextState(this, *local->unk0); } }//L80389A10 diff --git a/src/CC/ch/clankertoothext.c b/src/CC/ch/clankertoothext.c index d0a1b2a2f..a4395f326 100644 --- a/src/CC/ch/clankertoothext.c +++ b/src/CC/ch/clankertoothext.c @@ -5,28 +5,26 @@ #include -#include "port/Patches/Patches.h" - typedef struct{ s32 unk0; s32 egg_count; f32 unk8; }ActorLocal_CC_BF0; -void maClankerTooth_update(Actor *this); +void chClankerTooth_update(Actor *this); /* .data */ extern ActorInfo D_80389B00 = { MARKER_4C_CLANKER_TOKEN_TOOTH_EXT, ACTOR_44_CLANKER_TOKEN_TOOTH_EXTERIOR, ASSET_309_MODEL_CLANKER_TOKEN_TOOTH_EXTERIOR, 0, NULL, - maClankerTooth_update, actor_update_func_80326224, actor_draw, + chClankerTooth_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; extern ActorInfo D_80389B24 = { MARKER_4D_CLANKER_JIGGY_TOOTH_EXT, ACTOR_45_CLANKER_JIGGY_TOOTH_EXTERIOR, ASSET_30A_MODEL_CLANKER_JIGGY_TOOTH_EXTERIOR, 0, NULL, - maClankerTooth_update, actor_update_func_80326224, actor_draw, + chClankerTooth_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; @@ -34,7 +32,7 @@ extern ActorInfo D_80389B24 = { u8 D_80389F80; /* .code */ -void maClankerTooth_setNextState(Actor *this, s32 next_state){ +void chClankerTooth_setNextState(Actor *this, s32 next_state){ ActorLocal_CC_BF0 *local = (ActorLocal_CC_BF0 *)&this->local; s32 prev_state = this->state; this->state = next_state; @@ -67,7 +65,7 @@ void func_803870EC(s32 arg0) { D_80389F80 = arg0; } -void maClankerTooth_update(Actor *this){ +void chClankerTooth_update(Actor *this){ ActorMarker *marker = this->marker; f32 sp70[3]; ActorLocal_CC_BF0 *local = (ActorLocal_CC_BF0 *)&this->local; @@ -87,24 +85,11 @@ void maClankerTooth_update(Actor *this){ this->roll = 0.0f; local->unk0 = (marker->modelId == 0x309) ? 1 : 2; local->egg_count = 0; - maClankerTooth_setNextState(this, 1); + chClankerTooth_setNextState(this, 1); if(levelSpecificFlags_get((local->unk0 == 1)? LEVEL_FLAG_0_CC_TOKEN_TOOTH_OPEN: LEVEL_FLAG_1_CC_JIGGY_TOOTH_OPEN)){ - maClankerTooth_setNextState(this, 3); + chClankerTooth_setNextState(this, 3); } }//L803871D8 - if(this->state == 1){ - s32 base = (local->unk0 - 1) * 3; - s32 bits = (port_puzzleStep_get(ANCHOR_PUZZLE_CC_CLANKER_TEETH) >> base) & 0x7; - s32 shared = (bits & 1) + ((bits >> 1) & 1) + ((bits >> 2) & 1); - while(this->state == 1 && local->egg_count < shared){ - local->egg_count++; - if(local->egg_count == 3){ - maClankerTooth_setNextState(this, 2); - }else{ - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - } - } - } player_getPosition(sp70); local->unk8 += sp68; if(this->state == 2){ @@ -136,11 +121,8 @@ void maClankerTooth_update(Actor *this){ if(this->state == 1 && D_80389F80 == local->unk0){ D_80389F80 = 0; local->egg_count++; - // Anchor: broadcast cumulative egg progress. - port_puzzleStep_orBits(ANCHOR_PUZZLE_CC_CLANKER_TEETH, - ((1 << local->egg_count) - 1) << ((local->unk0 - 1) * 3)); if(local->egg_count == 3){ - maClankerTooth_setNextState(this, 2); + chClankerTooth_setNextState(this, 2); }else{ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); } @@ -148,19 +130,9 @@ void maClankerTooth_update(Actor *this){ else if(this->state == 2 && 1.0f <= local->unk8){ flagCnt = levelSpecificFlags_get(LEVEL_FLAG_0_CC_TOKEN_TOOTH_OPEN) + levelSpecificFlags_get(LEVEL_FLAG_1_CC_JIGGY_TOOTH_OPEN); if(!jiggyscore_isCollected(JIGGY_1B_CC_TOOTH)){ - gcdialog_showDialog( - (local->unk0 == 1)? - ((flagCnt == 0)? - VER_SELECT(ASSET_D30_DIALOG_CLANKER_RIGHT_TOOTH_FIRST, 0xA03, 0, 0) : VER_SELECT(ASSET_D31_DIALOG_CLANKER_RIGHT_TOOTH_SECOND, 0xA04, 0, 0)) : - ((flagCnt == 0)? - VER_SELECT(ASSET_D2E_DIALOG_CLANKER_LEFT_TOOTH_FIRST, 0xA01, 0, 0) : VER_SELECT(ASSET_D2F_DIALOG_CLANKER_LEFT_TOOTH_SECOND, 0xA02, 0, 0)), - 4, - NULL, - NULL, - NULL, - NULL); + gcdialog_showDialog((local->unk0 == 1)? ((flagCnt == 0)? 0xd30 : 0xd31) : ((flagCnt == 0)? 0xd2e : 0xd2f), 4, NULL, NULL, NULL, NULL); } - maClankerTooth_setNextState(this, 3); + chClankerTooth_setNextState(this, 3); }//L80387474 if(this->state == 3){ diff --git a/src/CC/ch/clankerkey.c b/src/CC/ch/key.c similarity index 91% rename from src/CC/ch/clankerkey.c rename to src/CC/ch/key.c index 6b4793514..8ab935b43 100644 --- a/src/CC/ch/clankerkey.c +++ b/src/CC/ch/key.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CC/ch/clankerkey.c +// BanjoDecomp: code_530.c #include "functions.h" #include "variables.h" #include @@ -7,7 +7,7 @@ extern void func_8030E730(s32, f32, s32); -void maClanker_raiseClanker(void); +void func_80388EA4(void); typedef struct { @@ -21,12 +21,12 @@ typedef struct { f32 unk14; } ActorLocal_CC_530; -void maClankerKey_update(Actor* this); +void chClankerKey_update(Actor* this); /* .data */ ActorInfo D_80389AD0 = { MARKER_4A_CC_KEY, ACTOR_3C_CC_KEY, ASSET_429_MODEL_CC_KEY, 0, NULL, - maClankerKey_update, actor_update_func_80326224, actor_draw, + chClankerKey_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; @@ -60,7 +60,7 @@ void CC_func_80386920(Actor *this, s32 next_state){ } if(next_state == 4){ - maClanker_raiseClankerCutscene(); + CC_func_8038868C(); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); } @@ -83,7 +83,7 @@ void func_80386AF8(Actor *arg0) { sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); } -void maClankerKey_update(Actor *this){ +void chClankerKey_update(Actor *this){ ActorMarker *marker = this->marker; f32 sp58[3]; ActorLocal_CC_530 * local = (ActorLocal_CC_530 *)&this->local; @@ -117,10 +117,6 @@ void maClankerKey_update(Actor *this){ } } else{//L80386C40 - // Anchor: teammate raised Clanker — snap the key to finished (state 5). - if(this->state == 1 && jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ - CC_func_80386920(this, 5); - } local->unk14 += tick; player_getPosition(sp58); if(local->unk1 && ! local->unk2){ @@ -200,7 +196,7 @@ void maClankerKey_update(Actor *this){ this->pitch = (f32)local->unk10 + 180.0f*(local->unk14/5.0f); if(5.0f <= local->unk14){ CC_func_80386920(this, 5); - maClanker_raiseClanker(); + func_80388EA4(); } }//L80386FC0 } diff --git a/src/CC/ch/clankerscrew.c b/src/CC/ch/screw.c similarity index 88% rename from src/CC/ch/clankerscrew.c rename to src/CC/ch/screw.c index e507fc6f6..ec6183ee3 100644 --- a/src/CC/ch/clankerscrew.c +++ b/src/CC/ch/screw.c @@ -1,4 +1,4 @@ -// BanjoDecomp: CC/ch/clankerscrew.c +// BanjoDecomp: code_0.c #include "functions.h" #include "variables.h" #include @@ -22,10 +22,10 @@ ActorInfo D_80389AA0 = { }; /* .code */ -void maClankersScrew_setNextState(Actor *this, s32 next_state){ +void CC_func_803863F0(Actor *this, s32 next_state){ ActorLocal_CC_0 * local = (ActorLocal_CC_0 *)this->local; if(this->state == 4){ - maClanker_playScrewNoise(0); + func_80388ED4(0); } this->state = next_state; local->unkC = 1; @@ -36,7 +36,7 @@ void maClankersScrew_setNextState(Actor *this, s32 next_state){ local->unk4 = 2.0f; } if(this->state == 2){ - maClanker_playScrewNoise(1); + func_80388ED4(1); } if(this->state == 3){ local->unk0 = 1.0f; @@ -57,7 +57,7 @@ void func_803864D4(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; marker->propPtr->unk8_3 = 1; - maClankersScrew_setNextState(this, 1); + CC_func_803863F0(this, 1); }//L80386530 func_80388B4C(sp4C); @@ -74,20 +74,20 @@ void func_803864D4(Actor *this){ local->unk4 = 0.05f; } else{ - maClankersScrew_setNextState(this, 2); + CC_func_803863F0(this, 2); } }//L80386634 if(ml_timer_update(&local->unk0, sp3C)){ - maClankersScrew_setNextState(this, 4); + CC_func_803863F0(this, 4); } if((this->state == 2) && (1.0 <= local->unk8)){ - maClankersScrew_setNextState(this, 3); + CC_func_803863F0(this, 3); }//L803866B4 if((this->state == 4) && (1.0 <= local->unk8)){ - maClankersScrew_setNextState(this, 1); + CC_func_803863F0(this, 1); }//L80386714 if(this->state == 1){ diff --git a/src/CC/ch/tooth.c b/src/CC/ch/tooth.c index 073116e40..654456e8c 100644 --- a/src/CC/ch/tooth.c +++ b/src/CC/ch/tooth.c @@ -80,9 +80,6 @@ extern void chTooth_update(Actor * this){ __chTooth_setState(this, 1); } } - else if(this->state == 1 && levelSpecificFlags_get(local->unk0->level_flag)){ - __chTooth_setState(this, 2); - } else if(this->state == 2){//L803876B4 if(local->unk0->jiggy_id && !jiggyscore_isSpawned(local->unk0->jiggy_id)){ player_getPosition(sp24); diff --git a/src/CC/checksums.c b/src/CC/checksums.c deleted file mode 100644 index e6997aa4b..000000000 --- a/src/CC/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: CC/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsCC; diff --git a/src/CC/crc.c b/src/CC/crc.c index 06714581c..23d6de395 100644 --- a/src/CC/crc.c +++ b/src/CC/crc.c @@ -1,8 +1,8 @@ // BanjoDecomp: crc.c #include -#include "checksums.h" -#include "version.h" -s32 D_80389BE0 = VER_SELECT(0x000D46A1, 0x000D4EB5, 0, 0); // CC_TEXT_CRC1 -s32 D_80389BE4 = VER_SELECT(0x871BA43E, 0xEE8A9B79, 0, 0); // CC_TEXT_CRC2 -s32 D_80389BE8 = VER_SELECT(0x0000DF9F, 0x0000EACE, 0, 0); // CC_DATA_CRC1 +/* .data */ +//TODO Implement CRC calculation in Makefile(?) +u32 D_80389BE0 = 0x000D46A1; //CC.code CRC1 +u32 D_80389BE4 = 0x871BA43E; //CC.code CRC2 +u32 D_80389BE8 = 0x0000DF9F; //CC.data CRC1 (with this value = 0) diff --git a/src/CC/ma/clanker.c b/src/CC/ma/clanker.c deleted file mode 100644 index 07ecbe059..000000000 --- a/src/CC/ma/clanker.c +++ /dev/null @@ -1,451 +0,0 @@ -// BanjoDecomp: CC/ma/clanker.c -#include -#include "core1/core1.h" -#include "functions.h" -#include "variables.h" - -#include "core2/modelRender.h" - -extern BKCollisionTriangle *func_8028EF48(void); -extern void func_8030E9FC(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); -extern void func_8030EA54(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); -extern void func_8031CE28(s32, s32, f32); -void timed_exitStaticCamera(f32); -extern BKCollisionTriangle *collisionList_func_802E805C(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32[3], u32); -extern void func_80340200(Struct83s *, f32[3], f32[3], f32, f32[3], s16[3], BKVertexList *, f32[3]); -extern BKCollisionTriangle *func_802E9118(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32, f32[3], s32, s32); -extern BKCollisionTriangle *func_802E9DD8(BKCollisionList *, BKVertexList *, f32[3], f32 *, f32, f32[3], f32, f32[3], s32); -extern int func_80340020(Struct83s *, f32[3], f32[3], f32, f32[3], BKVertexList *, f32[3], f32[3]); - -extern void boneTransformList_getBoneScale(BoneTransformList *, s32, f32[3]); -extern void boneTransformList_setBoneScale(BoneTransformList *, s32, f32[3]); -extern void func_8033A9A8(BoneTransformList *, s32, f32[3]); -extern void modelRender_setAppendageVisibility(s32, s32); -extern void modelRender_setBoneTransformList(BoneTransformList *); -extern void func_8028FAB0(f32[3]); -extern void baModel_802921D4(f32[3]); - -/* .data */ -f32 maClankerJiggyPosition[3] = {5700.0f, 4300.0f, 0.0f}; -f32 D_80389C0C[3] = {0.0f, 27.0f, 0.0f}; -f32 D_80389C18[3] = {0.0f, -27.0f, 0.0f}; -f32 maClankerRaisedSoundPosition[3] = {4000.0f, 3500.0f, 0.0f}; - -/* .bss */ -struct { - SkeletalAnimation *skeletonAnim; - u8 sfxsourceIdx; - //u8 pad5[0x3]; - f32 unk8; // screw timer? - f32 meetDialogPosition[3]; - Struct83s *unk18; - BKCollisionList *collisionList; - u8 triggerMeetDialog; - u8 currentState; - //u8 pad22[0x2]; - BKModelBin * model; - f32 position[3]; - Vec3fArray *unk34; - f32 timeDelta; - f32 unk3C; // raised sound timer? - BKVertexList *vertexList1; - BKVertexList *vertexList2; - u8 hasMetPlayer; - u8 unk49; - //u8 pad4A[2]; - f32 unk4C; // timer? - s32 unk50; // related to unk4C & unk54 - f32 unk54; // timer? -} maClanker; - -enum maClankerState_e { - MACLANKER_STATE_0_NOT_INITIALIZED, - MACLANKER_STATE_1_IDLE_UNDERWATER, - MACLANKER_STATE_2_LIFTING, - MACLANKER_STATE_3_IDLE_RAISED -}; - -BKCollisionTriangle *__maClanker_getClankerCollisionTris(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3){ // [port] pointer-width args - BKCollisionTriangle *collision_tris; - - collision_tris = collisionList_func_802E805C(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3); - if(collision_tris && func_8029453C()){ - func_80340200(maClanker.unk18, maClanker.position, 0, 1.0f, 0, collision_tris->unk0, maClanker.vertexList1, arg1); - } - return collision_tris; -} - -void __code1F70_func_80388428(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3[3], s32 arg4, u32 arg5){ // [port] pointer-width args - func_802E9118(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3, arg4, arg5); -} - -void func_803884A8(f32 arg0[3], f32 arg1, f32 arg2[3], u32 arg3){ // [port] pointer-width args - func_802E9DD8(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3); -} - -void maClanker_setState(s32 next_state){ - s32 current_state; - if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ - sfxSource_triggerCallbackByIndex(maClanker.sfxsourceIdx); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.6f, 20000); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 20000); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.9f, 20000); - func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 1.0f, 20000); - }//L80388594 - current_state = maClanker.currentState; - maClanker.currentState = next_state; - maClanker.timeDelta = 0.0f; - if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ - skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); - } - if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ - func_8030DD90(maClanker.sfxsourceIdx, 0); - sfxsource_playSfxAtVolume(maClanker.sfxsourceIdx, 1.0f); - sfxsource_setSfxId(maClanker.sfxsourceIdx, SFX_7D_ANCHOR_LIFTING); - sfxSource_setunk43_7ByIndex(maClanker.sfxsourceIdx, 3); - sfxsource_setSampleRate(maClanker.sfxsourceIdx, 27000); - sfxSource_func_8030E2C4(maClanker.sfxsourceIdx); - } - - if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ - if(current_state != MACLANKER_STATE_2_LIFTING){ - skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); - } - maClanker.position[1] = 1100.0f; - } -} - -void maClanker_spawnJiggy(void) { - jiggy_spawn(JIGGY_17_CC_CLANKER_RAISED, maClankerJiggyPosition); -} - -void maClanker_raiseClankerCutscene(void) { - func_80324E38(0, 3); - timed_setStaticCameraToNode(0, 0); - timed_setStaticCameraToNode(5.5f, 1); - timed_setStaticCameraToNode(7.0f, 2); - timed_setStaticCameraToNode(12.5f, 3); - timedFunc_set_0(13.0f, &maClanker_spawnJiggy); - timed_setStaticCameraToNode(16.0f, 1); - if (jiggyscore_isCollected(JIGGY_17_CC_CLANKER_RAISED) == FALSE) { - func_80324DBC(18.0f, VER_SELECT(ASSET_D2C_DIALOG_CLANKER_KEY_COMPLETE, 0x9FF, 0, 0), 4, NULL, NULL, NULL, 0); - } - timed_exitStaticCamera(18.0f); - func_80324E38(18.0f, 0); -} - - -void maClanker_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ - BKVertexList *tmp_vertex_list; - BoneTransformList *bone_transform_list; - f32 player_position[3]; - f32 viewport_position[3]; - int i; - s32 tmp_s0; - f32 sp84[3]; - s32 pad80; - f32 sp74[3]; - f32 sp68[3]; - f32 sp5C[3]; - - - if(maClanker.currentState == MACLANKER_STATE_0_NOT_INITIALIZED) - return; - - viewport_getPosition_vec3f(viewport_position); - - if(viewport_position[0] < -2600.0f || 11600.0f < viewport_position[0]) - return; - - bone_transform_list = skeletalAnim_getBoneTransformList(maClanker.skeletonAnim); - boneTransformList_getBoneScale(bone_transform_list, 0x40, sp84); - for( i = 0; i < 3; i++){ - sp84[i] = sp84[i] + (1.3 - sp84[i]) * maClanker.unk8; - } - - boneTransformList_setBoneScale(bone_transform_list, 0x40, sp84); - - if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ - func_8033A9A8(bone_transform_list, 0x44, D_80389C0C); - func_8033A9A8(bone_transform_list, 0x45, D_80389C0C); - func_8033A9A8(bone_transform_list, 0x46, D_80389C0C); - - func_8033A9A8(bone_transform_list, 0x47, D_80389C18); - func_8033A9A8(bone_transform_list, 0x48, D_80389C18); - func_8033A9A8(bone_transform_list, 0x49, D_80389C18); - } - - player_getPosition(player_position); - - for(i = 0; i < 2; i++){//L803888FC - vec3fArray_get_vec3f(maClanker.unk34, (i == 0) ? 0x10 : 0xf, sp74); - sp68[0] = player_position[0] - sp74[0]; - sp68[1] = player_position[1] - sp74[1]; - sp68[2] = player_position[2] - sp74[2]; - ml_vec3f_normalize(sp68); - - sp5C[0] = 0.0f; - sp5C[1] = sp68[2] * 45.0f; - sp5C[2] = -sp68[1] * 45.0f; - func_8033A9A8(bone_transform_list, (i == 0) ? 0x42 : 0x43, sp5C); - } - tmp_vertex_list = maClanker.vertexList1; - maClanker.vertexList1 = maClanker.vertexList2; - maClanker.vertexList2 = tmp_vertex_list; - - modelRender_setAppendageVisibility(1, (maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED) ? 1 : 0); - tmp_s0 = (viewport_position[0] < 100.0f)? 0 : 1; - modelRender_setAppendageVisibility(2, 1); - modelRender_setAppendageVisibility(3, 1); - modelRender_setAppendageVisibility(4, tmp_s0); - modelRender_setAppendageVisibility(5, tmp_s0); - modelRender_setAppendageVisibility(6, tmp_s0); - modelRender_setAppendageVisibility(7, tmp_s0); - modelRender_setAppendageVisibility(8, tmp_s0); - if(tmp_s0){ - tmp_s0 = (s32)(maClanker.unk4C * 3.99 + 1.0); - modelRender_setAppendageVisibility(2, tmp_s0); - modelRender_setAppendageVisibility(3, tmp_s0); - } - modelRender_setBoneTransformList(bone_transform_list); - modelRender_setRefPoints(maClanker.unk34); - modelRender_setVertexList(maClanker.vertexList1); - modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); - modelRender_draw(gfx, mtx, maClanker.position, NULL, 1.0f, NULL, maClanker.model); - if(func_80340020(maClanker.unk18, maClanker.position, 0, 1.0f, 0, maClanker.vertexList1, player_position, player_position)){ - func_8028FAB0(player_position); - baModel_802921D4(player_position); - } -} - -void func_80388B4C(f32 arg0[3]) { // [port] pointer-width - vec3fArray_get_vec3f(maClanker.unk34, 5, arg0); -} - -void func_80388B78(f32 arg0[3], f32 arg1[3]){ - vec3fArray_get_vec3f(maClanker.unk34, 7, arg0); - vec3fArray_get_vec3f(maClanker.unk34, 8, arg1); -} - -void func_80388BBC(f32 arg0[3], f32 arg1[3]){ - vec3fArray_get_vec3f(maClanker.unk34, 9, arg0); - vec3fArray_get_vec3f(maClanker.unk34, 10, arg1); -} - -void func_80388C00(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width - func_8031CD20(arg0, 0xb, 3); -} - -void func_80388C28(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width - func_8031CD20(arg0, 0xb, 4); -} - -void func_80388C50(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width - func_8031CD20(arg0, 0xb, 1); -} - -void CC_func_80388C78(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width - func_8031CD20(arg0, 0xb, 2); -} - -int CC_func_80388CA0(void){ - return maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED; -} - -void maClanker_release(void){ - if(maClanker.currentState){ - skeletalAnim_free(maClanker.skeletonAnim); - sfxsource_freeSfxsourceByIndex(maClanker.sfxsourceIdx); - func_80340690(maClanker.unk18); - vec3fArray_free(maClanker.unk34); - if(modelbin_getVtxList(maClanker.model) != maClanker.vertexList1) - vtxList_free(maClanker.vertexList1); - if(modelbin_getVtxList(maClanker.model) != maClanker.vertexList2) - vtxList_free(maClanker.vertexList2); - assetcache_release((void *)maClanker.model); - maClanker.unk34 = NULL; - maClanker.skeletonAnim = NULL; - maClanker.unk18 = NULL; - } -} - -void maClanker_init(void){ - maClanker.currentState = MACLANKER_STATE_0_NOT_INITIALIZED; - if(gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN){ - maClanker.skeletonAnim = skeletalAnim_new(); - maClanker.sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); - maClanker.unk8 = 1.0f; - maClanker.unk18 = func_803406B0(); - maClanker.currentState = MACLANKER_STATE_0_NOT_INITIALIZED; - maClanker.model = assetcache_get(ASSET_88E_MODEL_CLANKER_CHAIN); - maClanker.collisionList = modelbin_getCollisionList(maClanker.model); - maClanker.unk34 = vec3fArray_new(); - maClanker.unk3C = 1.0f; - maClanker.vertexList1 = modelbin_getVtxList(maClanker.model); - maClanker.vertexList2 = vtxList_clone(maClanker.vertexList1); - maClanker.hasMetPlayer = FALSE; - maClanker.unk49 = 0; - maClanker.unk50 = 0; - maClanker.unk4C = 0.0f; - maClanker.unk54 = 1.0f; - maClanker.position[0] = 5500.0f; - maClanker.position[2] = 0.0f; - maClanker.position[1] = 0.0f; - func_80320B24(__maClanker_getClankerCollisionTris, __code1F70_func_80388428, func_803884A8); - if(!nodeProp_findPositionFromActorId(ACTOR_3B_CLANKER_DIALOG_TRIGGER, maClanker.meetDialogPosition)){ - maClanker.meetDialogPosition[0] = 0.0f; - maClanker.meetDialogPosition[1] = -1e+06f; - maClanker.meetDialogPosition[2] = 0.0f; - } - if(jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ - maClanker_setState(MACLANKER_STATE_3_IDLE_RAISED); - } - else{ - maClanker_setState(MACLANKER_STATE_1_IDLE_UNDERWATER); - } - } -} - -void maClanker_raiseClanker(void){ - if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ - maClanker_setState(MACLANKER_STATE_2_LIFTING); - } -} - -void maClanker_playScrewNoise(s32 arg0){ - f32 sp1C[3]; - vec3fArray_get_vec3f(maClanker.unk34, 5, sp1C); - if(arg0 != 0){ - sfx_playFadeShorthandDefault(SFX_91_METALLIC_SOUND, 0.7f, 32675, sp1C, 100, 6000); - } - else{ - sfx_playFadeShorthandDefault(SFX_82_METAL_BREAK, 0.9f, 24000, sp1C, 100, 6000); - } - maClanker.unk8 = 1.0f; -} - -void maClanker_update(void){ - f32 player_position[3]; - f32 time_delta = time_getDelta(); - f32 sp64; - f32 sp60; - f32 sp54[3]; - f32 sp48[3]; - BKCollisionTriangle *tmp_v0; - f32 pad[3]; - - code13C0_checkCCChecksums(); - if(maClanker.currentState != MACLANKER_STATE_0_NOT_INITIALIZED && gsworld_getUnk0() == 2){ - // Anchor: teammate raised Clanker — play the physical raise (no cutscene). - if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER && jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ - maClanker_raiseClanker(); - } - player_getPosition(player_position); - maClanker.triggerMeetDialog = (ml_vec3f_distance(player_position, maClanker.meetDialogPosition) < 200.0f); - - maClanker.timeDelta += time_delta; - sp64 = skeletalAnim_getProgress(maClanker.skeletonAnim); - skeletalAnim_update(maClanker.skeletonAnim, time_delta, 1); - sp60 = skeletalAnim_getProgress(maClanker.skeletonAnim); - if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ - vec3fArray_get_vec3f(maClanker.unk34, 5, sp54); - if(sp60 < sp64){ - sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.6f, 32300, sp54, 1000, 5000); - }//L80389058 - - if(sp64 < 0.3 && 0.3 <= sp60){ - sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.5f, 32300, sp54, 1000, 5000); - } - }//L8038909C - - if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ - maClanker.position[1] += 100.0f * time_delta; - } - - if(0.0f < maClanker.unk8){ - maClanker.unk8 -= time_delta / 2; - if(maClanker.unk8 <= 0.0f) - maClanker.unk8 = 0.0f; - } - - if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){ - if(maClanker.triggerMeetDialog && skeletalAnim_getAnimId(maClanker.skeletonAnim) != ASSET_C4_ANIM_CLANKER_BITE){ - skeletalAnim_set(maClanker.skeletonAnim, ASSET_C4_ANIM_CLANKER_BITE, 1.0f, 10.0f); - if(!maClanker.hasMetPlayer){ - gcdialog_showDialog(VER_SELECT(ASSET_D2B_DIALOG_CLANKER_MEET, 0x9FE, 0, 0), 0xE, maClanker.position, NULL, NULL, NULL); - maClanker.hasMetPlayer = TRUE; - } - }//L8038918C - - if(!maClanker.triggerMeetDialog && skeletalAnim_getAnimId(maClanker.skeletonAnim) == ASSET_C4_ANIM_CLANKER_BITE){ - skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 1.0f, 10.0f); - } - }//L803891BC - - if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){ - func_803114D0(); - if(1100.0f <= maClanker.position[1]){ - maClanker_setState(MACLANKER_STATE_3_IDLE_RAISED); - } - }//L803891F8 - - if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ - vec3fArray_get_vec3f(maClanker.unk34, 6, sp48); - if(ml_vec3f_distance(sp48, player_position) <= 130.0f && player_position[1] - sp48[1] < 50.0f){ - func_8031D04C(MAP_21_CC_WITCH_SWITCH_ROOM, WARP_CC_WITCH_SWITCH_1_TOP_ENTRANCE); - } - }//L80389260 - - if( maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ - tmp_v0 = func_8028EF48(); - if( tmp_v0 && !maClanker.unk49 - ){ - if(tmp_v0->flags & 2){ - func_8031CE28(0x22, 5, 180.0f); - maClanker.unk49++; - } - else if(tmp_v0->flags & 4){ - func_8031CE28(0x22, 4, 0.0f); - maClanker.unk49++; - } - } - }//L803892DC - if(ml_timer_update(&maClanker.unk3C, time_delta)){ - if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){ - func_8030E9FC(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, maClankerRaisedSoundPosition, 2000.0f, 4000.0f); - }else{ - func_8030EA54(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, maClankerRaisedSoundPosition, 2000.0f, 4000.0f); - }//L80389384 - maClanker.unk3C = randf2(3.0f, 6.0f); - }//L803893A0 - if(maClanker.unk50 == 0){ - if(ml_timer_update(&maClanker.unk54, time_delta)) - maClanker.unk50 = 1; - } - - if(maClanker.unk50){ - maClanker.unk4C += maClanker.unk50 * ((time_delta * 30.0) / 4); - if(1.0f < maClanker.unk4C){ - maClanker.unk50 = -1; - maClanker.unk4C = 1.0f; - } - else if(maClanker.unk4C < 0.0f){ - maClanker.unk50 = 0; - maClanker.unk4C = 0.0f; - maClanker.unk54 = randf2(0.1f, 7.0f); - } - } - }//L80389490 - -} - -void maClanker_defrag(void){ - if(maClanker.unk34) - maClanker.unk34 = vec3fArray_defrag(maClanker.unk34); - - if(maClanker.skeletonAnim) - maClanker.skeletonAnim = defrag(maClanker.skeletonAnim); - - if(maClanker.unk18) - maClanker.unk18 = func_803406D4(maClanker.unk18); -} diff --git a/src/CC/ma/clankerrings.c b/src/CC/ma/clankerrings.c deleted file mode 100644 index 2c8657806..000000000 --- a/src/CC/ma/clankerrings.c +++ /dev/null @@ -1,130 +0,0 @@ -// BanjoDecomp: CC/ma/clankerrings.c -#include -#include "functions.h" -#include "variables.h" -#include "../CC.h" - -extern void port_ccWater_broadcastRise(int32_t map, int32_t waterId, int32_t targetDy, f32 duration); - -/* .data */ -f32 maClankerRingsJiggyPosition[3] = {0.0f, 1300.0f, -2800.0f}; - -#define RINGS_TIMER VER_SELECT(48, 40, 0, 0) // Seconds -#define RING_COUNT 9 - -/* .bss */ -struct { - u8 currentActiveRing; - u8 isMinigameActive; - f32 timer1; - f32 timer2; -} maClankerRings; - -/* .code */ -void func_80387F80(void){ - func_8034E71C((Struct73s *)func_8034C5AC(0x131), 0x190, 0.0f); // [port] cast to match decomp behavior -} - -void maClankerRings_startMinigame(void){ - item_set(ITEM_0_HOURGLASS_TIMER, RINGS_TIMER * 60 - 1); - item_set(ITEM_6_HOURGLASS, 1); - maClankerRings.isMinigameActive = 1; -} - -void maClankerRings_endMinigame(void){ - item_set(ITEM_6_HOURGLASS, 0); - maClankerRings.isMinigameActive = 0; -} - -s32 maClankerRings_isMinigameActive(void){ - if(maClankerRings.currentActiveRing > 0 && maClankerRings.currentActiveRing < 0xA){ - return maClankerRings.currentActiveRing; - } - return 0; -} - -void maClankerRings_passRing(s32 ring_num){ - if(ring_num == maClankerRings.currentActiveRing){ - if(ring_num == 1){ - maClankerRings_startMinigame(); - } - maClankerRings.currentActiveRing++; - if(maClankerRings.currentActiveRing >= RING_COUNT){ - maClankerRings_endMinigame(); - maClankerRings.timer2 = 1.0f; - } - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - } - else{//L803880BC - coMusicPlayer_playMusic(COMUSIC_2C_BUZZER, 28000); - } -} - -void maClankerRings_release(void){ - if(maClankerRings.currentActiveRing != 0){ - maClankerRings_endMinigame(); - } -} - -void maClankerRings_init(void){ - maClankerRings.currentActiveRing = 0; - if(gsworld_getMap() == MAP_22_CC_INSIDE_CLANKER){ - if(jiggyscore_isSpawned(JIGGY_1C_CC_RINGS)){ - timedFunc_set_0(0.0f, func_80387F80); - } - else{ - maClankerRings.currentActiveRing = 1; - maClankerRings.isMinigameActive = 0; - maClankerRings.timer2 = 0.0f; - maClankerRings.timer1 = 0.0f; - } - } -} - -void maClankerRings_update(void){ - f32 player_position[3]; - f32 time_delta = time_getDelta(); - Struct70s *tmp_v0; // [port] pointer-width - - if(maClankerRings.currentActiveRing != 0){ - if(jiggyscore_isSpawned(JIGGY_1C_CC_RINGS) && maClankerRings.currentActiveRing < RING_COUNT){ - maClankerRings_endMinigame(); - // func_80387F80 snaps water to risen height; VB listener suppresses it when connected (rise already animating). - if(EventSystem_Should(VB_CC_RINGS_SNAP_WATER, true)){ - func_80387F80(); - } - maClankerRings.currentActiveRing = 0; - return; - } - maClankerRings.timer1 += time_delta; - player_getPosition(player_position); - if(ml_timer_update(&maClankerRings.timer2, time_delta)){ - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(2.0f, 0); - timedJiggySpawn(2.1f, JIGGY_1C_CC_RINGS, maClankerRingsJiggyPosition); - func_80324E38(5.0f, 0); - timed_exitStaticCamera(5.0f); - tmp_v0 = func_8034C5AC(0x131); - if(tmp_v0){ - func_8034E78C((Struct73s *)tmp_v0, 0x190, 12.0f); // [port] cast matches decomp behavior - } - port_ccWater_broadcastRise(MAP_22_CC_INSIDE_CLANKER, 0x131, 0x190, 12.0f); - maClankerRings.timer1 = 0.0f; - }//L80388264 - if(!(maClankerRings.currentActiveRing < 2) && maClankerRings.isMinigameActive != 0){ - if( (player_position[0] < -1100.0f && player_position[1] < -40.0f) - || (1560.0f < player_position[0]) - || (2850.0f < player_position[2]) - || (player_position[2] < -3000.0f) - || (maClankerRings.currentActiveRing < RING_COUNT && item_empty(ITEM_6_HOURGLASS)) - ){ - maClankerRings_endMinigame(); - coMusicPlayer_playMusic(COMUSIC_3C_MINIGAME_LOSS, 28000); - maClankerRings_release(); - maClankerRings_init(); - } - }//L8038834C - }//L8038834C -} - diff --git a/src/CC/minigame_rings.c b/src/CC/minigame_rings.c new file mode 100644 index 000000000..3a243bedf --- /dev/null +++ b/src/CC/minigame_rings.c @@ -0,0 +1,115 @@ +// BanjoDecomp: code_1B90.c +#include +#include "functions.h" +#include "variables.h" +#include "CC.h" + +/* .data */ +f32 D_80389BF0[3] = {0.0f, 1300.0f, -2800.0f}; + +/* .bss */ +struct { + u8 unk0; + u8 unk1; + f32 unk4; + f32 unk8; +} D_80389F90; + +/* .code */ +void func_80387F80(void){ + func_8034E71C((Struct73s *)func_8034C5AC(0x131), 0x190, 0.0f); +} + +void CC_func_80387FB0(void){ + item_set(ITEM_0_HOURGLASS_TIMER, 48*60 - 1); + item_set(ITEM_6_HOURGLASS, 1); + D_80389F90.unk1 = 1; +} + +void func_80387FE8(void){ + item_set(ITEM_6_HOURGLASS, 0); + D_80389F90.unk1 = 0; +} + +s32 func_80388010(void){ + if(D_80389F90.unk0 > 0 && D_80389F90.unk0 < 0xA){ + return D_80389F90.unk0; + } + return 0; +} + +void func_8038803C(s32 arg0){ + if(arg0 == D_80389F90.unk0){ + if(arg0 == 1){ + CC_func_80387FB0(); + } + D_80389F90.unk0++; + if(D_80389F90.unk0 >= 9){ + func_80387FE8(); + D_80389F90.unk8 = 1.0f; + } + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); + } + else{//L803880BC + coMusicPlayer_playMusic(COMUSIC_2C_BUZZER, 28000); + } +} + +void func_803880D4(void){ + if(D_80389F90.unk0 != 0){ + func_80387FE8(); + } +} + +void func_80388104(void){ + D_80389F90.unk0 = 0; + if(gsworld_getMap() == MAP_22_CC_INSIDE_CLANKER){ + if(jiggyscore_isSpawned(JIGGY_1C_CC_RINGS)){ + timedFunc_set_0(0.0f, func_80387F80); + } + else{ + D_80389F90.unk0 = 1; + D_80389F90.unk1 = 0; + D_80389F90.unk8 = 0.0f; + D_80389F90.unk4 = 0.0f; + } + } +} + +void func_8038817C(void){ + f32 sp24[3]; + f32 sp20 = time_getDelta(); + Struct70s *tmp_v0; + + if(D_80389F90.unk0 != 0){ + D_80389F90.unk4 += sp20; + player_getPosition(sp24); + if(ml_timer_update(&D_80389F90.unk8, sp20)){ + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(2.0f, 0); + timedJiggySpawn(2.1f, JIGGY_1C_CC_RINGS, D_80389BF0); + func_80324E38(5.0f, 0); + timed_exitStaticCamera(5.0f); + tmp_v0 = func_8034C5AC(0x131); + if(tmp_v0){ + func_8034E78C((Struct73s *)tmp_v0, 0x190, 12.0f); + } + D_80389F90.unk4 = 0.0f; + }//L80388264 + if(!(D_80389F90.unk0 < 2) && D_80389F90.unk1 != 0){ + if( (sp24[0] < -1100.0f && sp24[1] < -40.0f) + || (1560.0f < sp24[0]) + || (2850.0f < sp24[2]) + || (sp24[2] < -3000.0f) + || (D_80389F90.unk0 < 9 && item_empty(ITEM_6_HOURGLASS)) + ){ + func_80387FE8(); + coMusicPlayer_playMusic(COMUSIC_3C_MINIGAME_LOSS, 28000); + func_803880D4(); + func_80388104(); + } + }//L8038834C + }//L8038834C +} + diff --git a/src/CC/model_renderstate.c b/src/CC/model_renderstate.c index 921b09134..b44d296cc 100644 --- a/src/CC/model_renderstate.c +++ b/src/CC/model_renderstate.c @@ -38,15 +38,15 @@ void func_803877B0(Struct_CC_13C0_1* arg0, void* arg1, f32 position[3], f32 rota return; if (temp_v0 == 0) { - modelRender_setAppendageVisibility(1, 1); + func_8033A45C(1, 1); } else if (temp_v0 == 1) { - modelRender_setAppendageVisibility(1, 2); + func_8033A45C(1, 2); } else if (temp_v0 == 2) { - modelRender_setAppendageVisibility(1, 2); + func_8033A45C(1, 2); rotation[2] += (arg0->unkC * 20.0f); arg4 = arg4*(1.0f - arg0->unkC); } - modelRender_setAppendageVisibility(2, 0); + func_8033A45C(2, 0); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); modelRender_draw(gfx, mtx, position, rotation, arg4, NULL, modeL_ptr); } @@ -109,7 +109,7 @@ void CC_func_80387A40(Struct_CC_13C0_1* arg0, Struct68s* arg1, f32 arg2) { s32 sp28; arg0->unkC += arg2; - temp_v0 = maClankerRings_isMinigameActive(); + temp_v0 = func_80388010(); if (temp_v0 == 0) { func_803878AC(arg0, arg1, 3); } else { @@ -140,7 +140,7 @@ void CC_func_80387A40(Struct_CC_13C0_1* arg0, Struct68s* arg1, f32 arg2) { sp28 = ((sp50[0]*sp44[0] + sp50[1]*sp44[1] + sp50[2]*sp44[2]) >= 0.0f) ? 1 : -1; if (sp28 == -arg0->unk8) { if (LENGTH_VEC3F(sp50) < (func_80351830(arg1) * 250.0f)) { - maClankerRings_passRing(arg0->unk0); + func_8038803C(arg0->unk0); } } arg0->unk8 = sp28; @@ -166,18 +166,6 @@ void code13C0_makeCameraFlipAndTilt(void){ } -void code13C0_checkCCChecksums(void){ -#if ANTI_TAMPER - u32 rom_data; - u32 unused; - osPiReadIo(0x504, &rom_data); - rom_data = (rom_data & 0xffff) + 0xffff5BA0; - if(rom_data){ - code13C0_makeCameraFlipAndTilt(); - } -#endif -} - void CC_func_80387D4C(void){ // [port] anti-tamper: ROM CRC check via osPiReadIo — not applicable on PC #if ANTI_TAMPER diff --git a/src/CC/platform_physics.c b/src/CC/platform_physics.c new file mode 100644 index 000000000..1e20fd654 --- /dev/null +++ b/src/CC/platform_physics.c @@ -0,0 +1,441 @@ +// BanjoDecomp: code_1F70.c +#include +#include "core1/core1.h" +#include "functions.h" +#include "variables.h" + +#include "core2/modelRender.h" +#include "core2/bonetransform.h" + +extern BKCollisionTriangle *func_8028EF48(void); +extern void func_8030E9FC(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); +extern void func_8030EA54(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6); +extern void func_8031CE28(s32, s32, f32); +void timed_exitStaticCamera(f32); +extern BKCollisionTriangle *collisionList_func_802E805C(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32[3], u32); +extern void func_80340200(Struct83s *, f32[3], f32[3], f32, f32[3], s16[3], BKVertexList *, f32[3]); +extern BKCollisionTriangle *func_802E9118(BKCollisionList *, BKVertexList *, f32[3], f32[3], f32, f32[3], f32[3], f32, f32[3], s32, s32); +extern BKCollisionTriangle *func_802E9DD8(BKCollisionList *, BKVertexList *, f32[3], f32 *, f32, f32[3], f32, f32[3], s32); +extern bool func_80340020(Struct83s *, f32[3], f32[3], f32, f32 *, BKVertexList *, f32[3], f32[3]); + +extern void boneTransformList_getBoneScale(BoneTransformList *, s32, f32[3]); +extern void boneTransformList_setBoneScale(BoneTransformList *, s32, f32[3]); +extern void func_8033A9A8(BoneTransformList *, s32, f32[3]); +extern void func_8033A45C(s32, s32); +extern void modelRender_setBoneTransformList(BoneTransformList *); +extern void func_8028FAB0(f32[3]); +extern void baModel_802921D4(f32[3]); + +/* .data */ +f32 D_80389C00[3] = {5700.0f, 4300.0f, 0.0f}; +f32 D_80389C0C[3] = {0.0f, 27.0f, 0.0f}; +f32 D_80389C18[3] = {0.0f, -27.0f, 0.0f}; +f32 D_80389C24[3] = {4000.0f, 3500.0f, 0.0f}; + +/* .bss */ +struct { + SkeletalAnimation *unk0; + u8 sfxsourceIdx; + //u8 pad5[0x3]; + f32 unk8; + f32 unkC[3]; + Struct83s *unk18; + BKCollisionList *unk1C; + u8 unk20; + u8 unk21; + //u8 pad22[0x2]; + BKModelBin * unk24; + f32 unk28[3]; + Vec3fArray *unk34; + f32 unk38; + f32 unk3C; + BKVertexList *unk40; + BKVertexList *unk44; + u8 unk48; + u8 unk49; + //u8 pad4A[2]; + f32 unk4C; + s32 unk50; + f32 unk54; +}D_80389FA0; + +BKCollisionTriangle *__code1F70_func_80388360(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3){ + BKCollisionTriangle *out_v0; + + out_v0 = collisionList_func_802E805C(D_80389FA0.unk1C, D_80389FA0.unk40, D_80389FA0.unk28, 0, 1.0f, arg0, arg1, arg2, arg3); + if(out_v0 && func_8029453C()){ + func_80340200(D_80389FA0.unk18, D_80389FA0.unk28, 0, 1.0f, 0, out_v0->unk0, D_80389FA0.unk40, arg1); + } + return out_v0; +} + +void __code1F70_func_80388428(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3[3], s32 arg4, u32 arg5){ + func_802E9118(D_80389FA0.unk1C, D_80389FA0.unk40, D_80389FA0.unk28, 0, 1.0f, arg0, arg1, arg2, arg3, arg4, arg5); +} + +void func_803884A8(f32 arg0[3], f32 arg1, f32 arg2[3], u32 arg3){ + func_802E9DD8(D_80389FA0.unk1C, D_80389FA0.unk40, D_80389FA0.unk28, 0, 1.0f, arg0, arg1, arg2, arg3); +} + +void func_80388518(s32 arg0){ + s32 sp24; + if(D_80389FA0.unk21 == 2){ + sfxSource_triggerCallbackByIndex(D_80389FA0.sfxsourceIdx); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.6f, 20000); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 20000); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.9f, 20000); + func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 1.0f, 20000); + }//L80388594 + sp24 = D_80389FA0.unk21; + D_80389FA0.unk21 = arg0; + D_80389FA0.unk38 = 0.0f; + if(D_80389FA0.unk21 == 1){ + skeletalAnim_set(D_80389FA0.unk0, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); + } + if(D_80389FA0.unk21 == 2){ + func_8030DD90(D_80389FA0.sfxsourceIdx, 0); + sfxsource_playSfxAtVolume(D_80389FA0.sfxsourceIdx, 1.0f); + sfxsource_setSfxId(D_80389FA0.sfxsourceIdx, SFX_7D_ANCHOR_LIFTING); + sfxSource_setunk43_7ByIndex(D_80389FA0.sfxsourceIdx, 3); + sfxsource_setSampleRate(D_80389FA0.sfxsourceIdx, 27000); + sfxSource_func_8030E2C4(D_80389FA0.sfxsourceIdx); + } + + if(D_80389FA0.unk21 == 3){ + if(sp24 != 2){ + skeletalAnim_set(D_80389FA0.unk0, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f); + } + D_80389FA0.unk28[1] = 1100.0f; + } +} + +void func_80388664(void) { + jiggy_spawn(JIGGY_17_CC_CLANKER_RAISED, D_80389C00); +} + +void CC_func_8038868C(void) { + func_80324E38(0, 3); + timed_setStaticCameraToNode(0, 0); + timed_setStaticCameraToNode(5.5f, 1); + timed_setStaticCameraToNode(7.0f, 2); + timed_setStaticCameraToNode(12.5f, 3); + timedFunc_set_0(13.0f, &func_80388664); + timed_setStaticCameraToNode(16.0f, 1); + if (jiggyscore_isCollected(JIGGY_17_CC_CLANKER_RAISED) == 0) { + func_80324DBC(18.0f, 0xD2C, 4, NULL, NULL, NULL, 0); + } + timed_exitStaticCamera(18.0f); + func_80324E38(18.0f, 0); +} + + +void CC_func_80388760(Gfx **gfx, Mtx **mtx, Vtx **vtx){ + BKVertexList *tmp_v0; + BoneTransformList *s1; + f32 spA4[3]; + f32 sp98[3]; + int i; + s32 tmp_s0; + f32 sp84[3]; + s32 pad80; + f32 sp74[3]; + f32 sp68[3]; + f32 sp5C[3]; + + + if(D_80389FA0.unk21 == 0) + return; + + viewport_getPosition_vec3f(sp98); + + if(sp98[0] < -2600.0f || 11600.0f < sp98[0]) + return; + + s1 = skeletalAnim_getBoneTransformList(D_80389FA0.unk0); + boneTransformList_getBoneScale(s1, 0x40, sp84); + for( i = 0; i < 3; i++){ + sp84[i] = sp84[i] + (1.3 - sp84[i])*D_80389FA0.unk8; + } + + boneTransformList_setBoneScale(s1, 0x40, sp84); + + if(D_80389FA0.unk21 == 1){ + func_8033A9A8(s1, 0x44, D_80389C0C); + func_8033A9A8(s1, 0x45, D_80389C0C); + func_8033A9A8(s1, 0x46, D_80389C0C); + + func_8033A9A8(s1, 0x47, D_80389C18); + func_8033A9A8(s1, 0x48, D_80389C18); + func_8033A9A8(s1, 0x49, D_80389C18); + } + + player_getPosition(spA4); + + for(i = 0; i < 2; i++){//L803888FC + vec3fArray_get_vec3f(D_80389FA0.unk34, (i == 0) ? 0x10 : 0xf, sp74); + sp68[0] = spA4[0] - sp74[0]; + sp68[1] = spA4[1] - sp74[1]; + sp68[2] = spA4[2] - sp74[2]; + ml_vec3f_normalize(sp68); + + sp5C[0] = 0.0f; + sp5C[1] = sp68[2]*45.0f; + sp5C[2] = -sp68[1]*45.0f; + func_8033A9A8(s1, (i == 0)?0x42:0x43, sp5C); + } + tmp_v0 = D_80389FA0.unk40; + D_80389FA0.unk40 = D_80389FA0.unk44; + D_80389FA0.unk44 = tmp_v0; + + func_8033A45C(1, (D_80389FA0.unk21 == 3) ? 1 : 0); + tmp_s0 = (sp98[0] < 100.0f)? 0 : 1; + func_8033A45C(2, 1); + func_8033A45C(3, 1); + func_8033A45C(4, tmp_s0); + func_8033A45C(5, tmp_s0); + func_8033A45C(6, tmp_s0); + func_8033A45C(7, tmp_s0); + func_8033A45C(8, tmp_s0); + if(tmp_s0){ + tmp_s0 = (s32)(D_80389FA0.unk4C*3.99 + 1.0); + func_8033A45C(2, tmp_s0); + func_8033A45C(3, tmp_s0); + } + modelRender_setBoneTransformList(s1); + modelRender_setRefPoints(D_80389FA0.unk34); + modelRender_setVertexList(D_80389FA0.unk40); + modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); + modelRender_draw(gfx, mtx, D_80389FA0.unk28, NULL, 1.0f, NULL, D_80389FA0.unk24); + if(func_80340020(D_80389FA0.unk18, D_80389FA0.unk28, 0, 1.0f, 0, D_80389FA0.unk40, spA4, spA4)){ + func_8028FAB0(spA4); + baModel_802921D4(spA4); + } +} + +void func_80388B4C(f32 arg0[3]) { + vec3fArray_get_vec3f(D_80389FA0.unk34, 5, arg0); +} + +void func_80388B78(f32 arg0[3], f32 arg1[3]){ + vec3fArray_get_vec3f(D_80389FA0.unk34, 7, arg0); + vec3fArray_get_vec3f(D_80389FA0.unk34, 8, arg1); +} + +void func_80388BBC(f32 arg0[3], f32 arg1[3]){ + vec3fArray_get_vec3f(D_80389FA0.unk34, 9, arg0); + vec3fArray_get_vec3f(D_80389FA0.unk34, 10, arg1); +} + +void func_80388C00(NodeProp *arg0, ActorMarker *arg1){ + func_8031CD20(arg0, 0xb, 3); +} + +void func_80388C28(NodeProp *arg0, ActorMarker *arg1){ + func_8031CD20(arg0, 0xb, 4); +} + +void func_80388C50(NodeProp *arg0, ActorMarker *arg1){ + func_8031CD20(arg0, 0xb, 1); +} + +void CC_func_80388C78(NodeProp *arg0, ActorMarker *arg1){ + func_8031CD20(arg0, 0xb, 2); +} + +int CC_func_80388CA0(void){ + return D_80389FA0.unk21 == 3; +} + +void func_80388CB4(void){ + if(D_80389FA0.unk21){ + skeletalAnim_free(D_80389FA0.unk0); + sfxsource_freeSfxsourceByIndex(D_80389FA0.sfxsourceIdx); + func_80340690(D_80389FA0.unk18); + vec3fArray_free(D_80389FA0.unk34); + if(modelbin_getVtxList(D_80389FA0.unk24) != D_80389FA0.unk40) + vtxList_free(D_80389FA0.unk40); + if(modelbin_getVtxList(D_80389FA0.unk24) != D_80389FA0.unk44) + vtxList_free(D_80389FA0.unk44); + assetcache_release((void *)D_80389FA0.unk24); + D_80389FA0.unk34 = NULL; + D_80389FA0.unk0 = NULL; + D_80389FA0.unk18 = NULL; + } +} + +void func_80388D54(void){ + D_80389FA0.unk21 = 0; + if(gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN){ + D_80389FA0.unk0 = skeletalAnim_new(); + D_80389FA0.sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); + D_80389FA0.unk8 = 1.0f; + D_80389FA0.unk18 = func_803406B0(); + D_80389FA0.unk21 = 0; + D_80389FA0.unk24 = assetcache_get(ASSET_88E_MODEL_CLANKER_CHAIN); + D_80389FA0.unk1C = modelbin_getCollisionList(D_80389FA0.unk24); + D_80389FA0.unk34 = vec3fArray_new(); + D_80389FA0.unk3C = 1.0f; + D_80389FA0.unk40 = modelbin_getVtxList(D_80389FA0.unk24); + D_80389FA0.unk44 = vtxList_clone(D_80389FA0.unk40); + D_80389FA0.unk48 = 0; + D_80389FA0.unk49 = 0; + D_80389FA0.unk50 = 0; + D_80389FA0.unk4C = 0.0f; + D_80389FA0.unk54 = 1.0f; + D_80389FA0.unk28[0] = 5500.0f; + D_80389FA0.unk28[2] = 0.0f; + D_80389FA0.unk28[1] = 0.0f; + func_80320B24(__code1F70_func_80388360, __code1F70_func_80388428, func_803884A8); + if(!nodeProp_findPositionFromActorId(0x3B, D_80389FA0.unkC)){ + D_80389FA0.unkC[0] = 0.0f; + D_80389FA0.unkC[1] =-1e+06f; + D_80389FA0.unkC[2] = 0.0f; + } + if(jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){ + func_80388518(3); + } + else{ + func_80388518(1); + } + } +} + +void func_80388EA4(void){ + if(D_80389FA0.unk21 == 1){ + func_80388518(2); + } +} + +void func_80388ED4(s32 arg0){ + f32 sp1C[3]; + vec3fArray_get_vec3f(D_80389FA0.unk34, 5, sp1C); + if(arg0 != 0){ + sfx_playFadeShorthandDefault(SFX_91_METALLIC_SOUND, 0.7f, 32675, sp1C, 100, 6000); + } + else{ + sfx_playFadeShorthandDefault(SFX_82_METAL_BREAK, 0.9f, 24000, sp1C, 100, 6000); + } + D_80389FA0.unk8 = 1.0f; +} + +void CC_func_80388F4C(void){ + f32 sp6C[3]; + f32 sp68 = time_getDelta(); + f32 sp64; + f32 sp60; + f32 sp54[3]; + f32 sp48[3]; + BKCollisionTriangle *tmp_v0; + f32 pad[3]; + + CC_func_80387D4C(); + if(D_80389FA0.unk21 != 0 && gsworld_getUnk0() == 2){ + player_getPosition(sp6C); + D_80389FA0.unk20 = (ml_vec3f_distance(sp6C, D_80389FA0.unkC) < 200.0f); + + D_80389FA0.unk38 += sp68; + sp64 = skeletalAnim_getProgress(D_80389FA0.unk0); + skeletalAnim_update(D_80389FA0.unk0, sp68, 1); + sp60 = skeletalAnim_getProgress(D_80389FA0.unk0); + if(D_80389FA0.unk21 == 3){ + vec3fArray_get_vec3f(D_80389FA0.unk34, 5, sp54); + if(sp60 < sp64){ + sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.6f, 32300, sp54, 1000, 5000); + }//L80389058 + + if(sp64 < 0.3 && 0.3 <= sp60){ + sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.5f, 32300, sp54, 1000, 5000); + } + }//L8038909C + + if(D_80389FA0.unk21 == 2){ + D_80389FA0.unk28[1] += 100.0f*sp68; + } + + if(0.0f < D_80389FA0.unk8){ + D_80389FA0.unk8 -= sp68/2; + if(D_80389FA0.unk8 <= 0.0f) + D_80389FA0.unk8 = 0.0f; + } + + if(D_80389FA0.unk21 == 1){ + if(D_80389FA0.unk20 && skeletalAnim_getAnimId(D_80389FA0.unk0) != ASSET_C4_ANIM_CLANKER_BITE){ + skeletalAnim_set(D_80389FA0.unk0, ASSET_C4_ANIM_CLANKER_BITE, 1.0f, 10.0f); + if(!D_80389FA0.unk48){ + gcdialog_showDialog(ASSET_D2B_DIALOG_CLANKER_MEET, 0xE, D_80389FA0.unk28, NULL, NULL, NULL); + D_80389FA0.unk48 = true; + } + }//L8038918C + + if(!D_80389FA0.unk20 && skeletalAnim_getAnimId(D_80389FA0.unk0) == ASSET_C4_ANIM_CLANKER_BITE){ + skeletalAnim_set(D_80389FA0.unk0, ASSET_C3_ANIM_CLANKER_IDLE, 1.0f, 10.0f); + } + }//L803891BC + + if(D_80389FA0.unk21 == 2){ + func_803114D0(); + if(1100.0f <= D_80389FA0.unk28[1]){ + func_80388518(3); + } + }//L803891F8 + + if(D_80389FA0.unk21 == 3){ + vec3fArray_get_vec3f(D_80389FA0.unk34, 6, sp48); + if(ml_vec3f_distance(sp48, sp6C) <= 130.0f && sp6C[1] - sp48[1] < 50.0f){ + func_8031D04C(MAP_21_CC_WITCH_SWITCH_ROOM, WARP_CC_WITCH_SWITCH_1_TOP_ENTRANCE); + } + }//L80389260 + + if( D_80389FA0.unk21 == 3){ + tmp_v0 = func_8028EF48(); + if( tmp_v0 && !D_80389FA0.unk49 + ){ + if(tmp_v0->flags & 2){ + func_8031CE28(0x22, 5, 180.0f); + D_80389FA0.unk49++; + } + else if(tmp_v0->flags & 4){ + func_8031CE28(0x22, 4, 0.0f); + D_80389FA0.unk49++; + } + } + }//L803892DC + if(ml_timer_update(&D_80389FA0.unk3C, sp68)){ + if(D_80389FA0.unk21 == 3){ + func_8030E9FC(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, D_80389C24, 2000.0f, 4000.0f); + }else{ + func_8030EA54(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, D_80389C24, 2000.0f, 4000.0f); + }//L80389384 + D_80389FA0.unk3C = randf2(3.0f, 6.0f); + }//L803893A0 + if(D_80389FA0.unk50 == 0){ + if(ml_timer_update(&D_80389FA0.unk54, sp68)) + D_80389FA0.unk50 = 1; + } + + if(D_80389FA0.unk50){ + D_80389FA0.unk4C += D_80389FA0.unk50 * ((sp68 * 30.0)/4); + if(1.0f < D_80389FA0.unk4C){ + D_80389FA0.unk50 = -1; + D_80389FA0.unk4C = 1.0f; + } + else if(D_80389FA0.unk4C < 0.0f){ + D_80389FA0.unk50 = 0; + D_80389FA0.unk4C = 0.0f; + D_80389FA0.unk54 = randf2(0.1f, 7.0f); + } + } + }//L80389490 + +} + +void func_803894A0(void){ + if(D_80389FA0.unk34) + D_80389FA0.unk34 = vec3fArray_defrag(D_80389FA0.unk34); + + if(D_80389FA0.unk0) + D_80389FA0.unk0 = defrag(D_80389FA0.unk0); + + if(D_80389FA0.unk18) + D_80389FA0.unk18 = func_803406D4(D_80389FA0.unk18); +} diff --git a/src/CCW/actor_spawninit.c b/src/CCW/actor_spawninit.c new file mode 100644 index 000000000..032d47abd --- /dev/null +++ b/src/CCW/actor_spawninit.c @@ -0,0 +1,157 @@ +// BanjoDecomp: code_76C0.c +#include +#include "functions.h" +#include "variables.h" +#include "prop.h" +#include "actor.h" + +extern void func_802D3D54(Actor *); +extern void func_802D3D74(Actor *); +extern void func_80325F84(Actor *); + + +extern ActorInfo D_8038EB50; +extern ActorInfo D_8038EB74; +extern ActorInfo D_8038EBA0; +extern ActorInfo D_8038EBD0; +extern ActorInfo D_8038EC14; +extern ActorInfo D_8038EC70; +extern ActorInfo D_8038ECA0; +extern ActorInfo D_8038ECE8; +extern ActorInfo D_8038EE70; +extern ActorInfo D_8038F130; +extern ActorInfo chCaterpillar; +extern ActorInfo D_8038F190; +extern ActorInfo D_8038F230; +extern ActorInfo D_8038F6F0; +extern ActorInfo D_8038ED50; +extern ActorInfo D_8038ED98; +extern ActorInfo D_8038EDE0; +extern ActorInfo D_8038EE28; +extern ActorInfo D_8038ED74; +extern ActorInfo D_8038EDBC; +extern ActorInfo D_8038EE04; +extern ActorInfo D_8038EE4C; +extern ActorInfo D_8038F270; +extern ActorInfo D_8038F300; +extern ActorInfo D_8038F35C; +extern ActorInfo D_8038F380; +extern ActorInfo D_8038F3A4; +extern ActorInfo D_8038F3C8; +extern ActorInfo D_8038F3EC; +extern ActorInfo D_8038F410; +extern ActorInfo D_8038F434; +extern ActorInfo D_8038F460; +extern ActorInfo D_8038F4A8; +extern ActorInfo D_8038F4D0; +extern ActorInfo D_8038F614; +extern ActorInfo chGnawtyBoulder; +extern ActorInfo D_8038F908; +extern ActorInfo D_8038F8C0; +extern ActorInfo D_8038F720; +extern ActorInfo D_8038F744; +extern ActorInfo D_8038F768; +extern ActorInfo D_8038F78C; +extern ActorInfo chGrublinHood; +extern ActorInfo gChVacationTextTrigger; +extern ActorInfo D_8038F7D4; +extern ActorInfo D_8038F7B0; +extern ActorInfo D_8038F888; +extern ActorInfo D_8038F7F8; +extern ActorInfo D_8038F81C; +extern ActorInfo D_8038F840; +extern ActorInfo D_8038F864; + +void CCW_func_8038DB0C(Actor *this); +void func_8038DAB0(Actor *this); + +/* .data */ +ActorInfo D_8038F720 = { 0x239, 0x25F, 0x4FC, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F744 = { 0x236, 0x260, 0x4F9, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F768 = { 0x237, 0x261, 0x4FA, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F78C = { 0x238, 0x262, 0x4FB, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F7B0 = { 0x243, 0x2E6, 0x533, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F7D4 = { 0x263, 0x2E7, 0x518, 0x1, NULL, func_8038DAB0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F7F8 = { 0x21E, 0x233, 0x3B3, 0x1, NULL, func_802D3D74, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F81C = { 0x26B, 0x2DE, 0x531, 0x1, NULL, CCW_func_8038DB0C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F840 = { 0x26C, 0x2DD, 0x53E, 0x1, NULL, CCW_func_8038DB0C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F864 = { 0x26D, 0x2DC, 0x53F, 0x1, NULL, CCW_func_8038DB0C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8038F888 = { 0x1CC, 0x318, 0x0, 0x0, NULL, func_80325F84, NULL, func_80325340, 0, 0, 0.0f, 0}; + + +/* .code */ +void func_8038DAB0(Actor *this){ + if(!this->initialized){ + func_802D3CE8(this); + this->initialized = true; + + if (levelSpecificFlags_get(LEVEL_FLAG_38_CCW_UNKNOWN)) { + marker_despawn(this->marker); + } + } +} + +void CCW_func_8038DB0C(Actor *this){ + if(!this->initialized){ + func_802D3D74(this); + this->initialized = true; + this->position_x = 325.8f; + this->position_y = 600.0f; + this->position_z = 0.0f; + } +} + +void CCW_func_8038DB6C(void) +{ + spawnableActorList_add(&D_8038EB50, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_8038EB74, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_8038EBA0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); + spawnableActorList_add(&D_8038EBD0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&D_8038EC14, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038EC70, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_8038ECA0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_8038ECE8, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_8038EE70, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F130, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&chCaterpillar, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F190, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_8038F230, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F6F0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038ED50, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038ED98, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038EDE0, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038EE28, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038ED74, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038EDBC, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038EE04, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038EE4C, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038F270, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F300, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F35C, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F380, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_8038F3A4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F3C8, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F3EC, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_8038F410, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F434, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F460, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F4A8, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F4D0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_8038F614, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&chGnawtyBoulder, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_8038F908, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&D_8038F8C0, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&D_8038F720, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038F744, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038F768, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038F78C, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&chGrublinHood, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&gChVacationTextTrigger, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038F7D4, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038F7B0, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038F888, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_8038F7F8, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038F81C, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038F840, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038F864, actor_new, ACTOR_FLAG_UNKNOWN_10); +} diff --git a/src/CCW/bss_pad.c b/src/CCW/bss_pad.c new file mode 100644 index 000000000..152d079d3 --- /dev/null +++ b/src/CCW/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_CCW_8038FDD0[0x10]; diff --git a/src/CCW/ccwspawnqueue.c b/src/CCW/ccwspawnqueue.c deleted file mode 100644 index 3519d36f7..000000000 --- a/src/CCW/ccwspawnqueue.c +++ /dev/null @@ -1,229 +0,0 @@ -// BanjoDecomp: CCW/ccwspawnqueue.c -#include -#include "functions.h" -#include "variables.h" -#include "prop.h" -#include "actor.h" - -extern void chMMMBreakableWooden_update(Actor *); -extern void func_802D3D74(Actor *); -extern void func_80325F84(Actor *); - - -extern ActorInfo chZubbaDoorSummer; -extern ActorInfo chZubbaDoorAutumn; -extern ActorInfo chZubbaHoneyLump; -extern ActorInfo chZubba; -extern ActorInfo chZubbaDocile; -extern ActorInfo chCCWBeanstalk; -extern ActorInfo chDeadBeanstalk; -extern ActorInfo chCCWGobi; -extern ActorInfo chEyrieEgg; -extern ActorInfo chEyrieBaby; -extern ActorInfo chCaterpillar; -extern ActorInfo chEyrieAdult; -extern ActorInfo chCutsceneAdultEyrie; -extern ActorInfo chSnoreZ; -extern ActorInfo chCCWSpringSwitchDoor; -extern ActorInfo chCCWSummerSwitchDoor; -extern ActorInfo chCCWAutumnSwitchDoor; -extern ActorInfo chCCWWinterSwitchDoor; -extern ActorInfo chCCWSpringSwitch; -extern ActorInfo chCCWSummerSwitch; -extern ActorInfo chCCWAutumnSwitch; -extern ActorInfo chCCWWinterSwitch; -extern ActorInfo chNabnutSpring; -extern ActorInfo chNabnutBellyFull; -extern ActorInfo chAutumnOutdoorNabnut; -extern ActorInfo chMoundOfAcorns; -extern ActorInfo chPinkSquirrel; -extern ActorInfo chNabnutBedsheets; -extern ActorInfo chNabnutBed; -extern ActorInfo chNabnut; -extern ActorInfo chNabnutAutumnEatingAcorns; -extern ActorInfo chCarriedAcorn; -extern ActorInfo chGnawtySwimming; -extern ActorInfo chGnawtySummer; -extern ActorInfo chIndoorsGnawty; -extern ActorInfo chGnawtyBoulder; -extern ActorInfo chSnarebear; -extern ActorInfo chDeadSnarebear; -extern ActorInfo chNabnutWindowSpring; -extern ActorInfo chNabnutWindowSummer; -extern ActorInfo chNabnutWindowAutumn; -extern ActorInfo chNabnutWindowWinter; -extern ActorInfo chGrublinHood; -extern ActorInfo gChVacationTextTrigger; -extern ActorInfo chCCWWhipcrackRoomDoor; -extern ActorInfo chNabnutDoor; -extern ActorInfo D_8038F888; -extern ActorInfo chCCWMumbosHut; -extern ActorInfo chGnawtysDen; -extern ActorInfo chGnawtysBed; -extern ActorInfo chGnawtysShelves; - -void code_76C0_ccwGnawtysStuffUpdate(Actor *this); -void code_76C0_ccwWhipcrackRoomDoorUpdate(Actor *this); - -/* .data */ - -#if VERSION == VERSION_PAL -Actor* cc_pal_unk_draw(ActorMarker *, Gfx **, Mtx **, Vtx **); -#endif - -// Unused -ActorInfo chNabnutWindowSpring = { - MARKER_239_CCW_UNKNOWN_NABNUT_WINDOW, ACTOR_25F_CCW_UNKNOWN_NABNUT_WINDOW, ASSET_4FC_MODEL_CCW_UNKNOWN_NABNUT_WINDOW, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -// Unused -ActorInfo chNabnutWindowSummer = { - MARKER_236_CCW_UNKNOWN_NABNUT_WINDOW, ACTOR_260_CCW_UNKNOWN_NABNUT_WINDOW, ASSET_4F9_MODEL_CCW_UNKNOWN_NABNUT_WINDOW, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chNabnutWindowAutumn = { - MARKER_237_CCW_AUTUMN_NABNUT_WINDOW, ACTOR_261_CCW_AUTUMN_NABNUT_WINDOW, ASSET_4FA_MODEL_CCW_AUTUMN_NABNUT_WINDOW, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chNabnutWindowWinter = { - MARKER_238_CCW_WINTER_NABNUT_WINDOW, ACTOR_262_CCW_WINTER_NABNUT_WINDOW, ASSET_4FB_MODEL_CCW_WINTER_NABNUT_WINDOW, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chNabnutDoor = { - MARKER_243_NABNUT_DOOR, ACTOR_2E6_NABNUT_DOOR, ASSET_533_MODEL_NABNUT_DOOR, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCCWWhipcrackRoomDoor = { - MARKER_263_CCW_WHIPCRACK_ROOM_DOOR, ACTOR_2E7_WHIPCRACK_ROOM_DOOR, ASSET_518_MODEL_CCW_WHIPCRACK_ROOM_DOOR, - 0x1, NULL, - code_76C0_ccwWhipcrackRoomDoorUpdate, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCCWMumbosHut = { - MARKER_21E_CCW_MUMBOS_HUT, ACTOR_233_CCW_MUMBOS_HUT, ASSET_3B3_MODEL_CCW_MUMBOS_HUT, - 0x1, NULL, - func_802D3D74, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chGnawtysDen = { - MARKER_26B_GNAWTYS_DEN, ACTOR_2DE_GNAWTYS_DEN, ASSET_531_MODEL_GNAWTYS_DEN, - 0x1, NULL, - code_76C0_ccwGnawtysStuffUpdate, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chGnawtysBed = { - MARKER_26C_GNAWTYS_BED, ACTOR_2DD_GNAWTYS_BED, ASSET_53E_MODEL_GNAWTY_BED, - 0x1, NULL, - code_76C0_ccwGnawtysStuffUpdate, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chGnawtysShelves = { - MARKER_26D_GNAWTYS_SHELVES, ACTOR_2DC_GNAWTYS_SHELVES, ASSET_53F_MODEL_GNAWTY_SHELVES, - 0x1, NULL, - code_76C0_ccwGnawtysStuffUpdate, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_8038F888 = { - MARKER_1CC_CCW_UNKNOWN, ACTOR_318_CCW_UNKNOWN, 0x0, - 0x0, NULL, - func_80325F84, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -/* .code */ -void code_76C0_ccwWhipcrackRoomDoorUpdate(Actor *this){ - if(!this->initialized){ - func_802D3CE8(this); - this->initialized = true; - } - // Anchor: checked live, not just at spawn. - if (levelSpecificFlags_get(LEVEL_FLAG_38_CCW_UNKNOWN)) { - marker_despawn(this->marker); - } -} - -void code_76C0_ccwGnawtysStuffUpdate(Actor *this){ - if(!this->initialized){ - func_802D3D74(this); - this->initialized = true; - // Position For Gnawty's Den - this->position_x = 325.8f; - this->position_y = 600.0f; - this->position_z = 0.0f; - } -} - -void CCW_func_8038DB6C(void) -{ - spawnableActorList_add(&chZubbaDoorSummer, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chZubbaDoorAutumn, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chZubbaHoneyLump, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); - spawnableActorList_add(&chZubba, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&chZubbaDocile, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chCCWBeanstalk, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chDeadBeanstalk, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chCCWGobi, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chEyrieEgg, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chEyrieBaby, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chCaterpillar, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chEyrieAdult, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chCutsceneAdultEyrie, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chSnoreZ, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chCCWSpringSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chCCWSummerSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chCCWAutumnSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chCCWWinterSwitchDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chCCWSpringSwitch, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCCWSummerSwitch, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCCWAutumnSwitch, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCCWWinterSwitch, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chNabnutSpring, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chNabnutBellyFull, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chAutumnOutdoorNabnut, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chMoundOfAcorns, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chPinkSquirrel, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chNabnutBedsheets, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chNabnutBed, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chNabnut, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chNabnutAutumnEatingAcorns, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chCarriedAcorn, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chGnawtySwimming, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chGnawtySummer, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chIndoorsGnawty, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chGnawtyBoulder, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chSnarebear, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chDeadSnarebear, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chNabnutWindowSpring, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chNabnutWindowSummer, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chNabnutWindowAutumn, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chNabnutWindowWinter, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chGrublinHood, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&gChVacationTextTrigger, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCCWWhipcrackRoomDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chNabnutDoor, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&D_8038F888, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chCCWMumbosHut, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chGnawtysDen, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chGnawtysBed, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chGnawtysShelves, actor_new, ACTOR_FLAG_UNKNOWN_10); -} diff --git a/src/CCW/ch/acorn.c b/src/CCW/ch/acorn.c index 3c7f23894..7602302f5 100644 --- a/src/CCW/ch/acorn.c +++ b/src/CCW/ch/acorn.c @@ -1,143 +1,101 @@ -// BanjoDecomp: CCW/ch/acorn.c +// BanjoDecomp: code_61E0.c #include #include "functions.h" #include "variables.h" -#include "port/Enhancements/Retention/Retention.h" -extern ActorMarker *bacarry_getMarkerWithExtraSteps(void); -extern s32 port_remoteCarry_displayUpdate(Actor *this); -extern void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]); +extern ActorMarker *func_8028E86C(void); typedef struct { - f32 position[3]; - f32 unkC[3]; // some kind of distance - f32 unk18; // something time related -} ActorLocal_ChCarriedAcorn; + f32 unk0[3]; + f32 unkC[3]; + f32 unk18; +}ActorLocal_CCW_61E0; -void chCarriedAcorn_update(Actor *this); +void func_8038C7A8(Actor *this); /* .data */ -ActorInfo chCarriedAcorn = { - MARKER_1BC_CARRIED_ACORN, ACTOR_2A9_ACORN, ASSET_48E_MODEL_ACORN, - 0x0, NULL, - chCarriedAcorn_update, NULL, actor_draw, - 0, 0, 0.8f, 0 -}; - -enum chCarriedAcorn_State_e { - CH_CARRIED_ACORN_STATE_0_NOT_INIT, - CH_CARRIED_ACORN_STATE_1_PULL_OUT, - CH_CARRIED_ACORN_STATE_2_HOLDING, - CH_CARRIED_ACORN_STATE_3_TOSS, - CH_CARRIED_ACORN_STATE_4_GIVEN_TO_NABNUT, - CH_CARRIED_ACORN_STATE_5_DESPAWN -}; +ActorInfo D_8038F460 = { 0x1BC, 0x2A9, 0x48E, 0x0, NULL, func_8038C7A8, NULL, actor_draw, 0, 0, 0.8f, 0}; /* .code */ -void chCarriedAcorn_sfxBoing(ActorMarker* marker) { +void CCW_func_8038C5D0(ActorMarker* marker) { Actor* actor = marker_getActor(marker); func_8030E878(SFX_3F2_BOING, randf2(0.95f, 1.05f), 26000, actor->position, 500.0f, 1000.0f); } -void chCarriedAcorn_sfxBanjoNoise(ActorMarker* marker) { +void CCW_func_8038C638(ActorMarker* marker) { Actor* actor = marker_getActor(marker); func_8030E878(SFX_5_BANJO_LANDING_01, randf2(0.95f, 1.05f), 22000, actor->position, 500.0f, 1000.0f); } -void chCarriedAcorn_setNextState(Actor *this, s32 next_state) { - ActorLocal_ChCarriedAcorn *local; +void CCW_func_8038C6A0(Actor *this, s32 next_state) { + ActorLocal_CCW_61E0 *local; - local = (ActorLocal_ChCarriedAcorn *)&this->local; - if (next_state == CH_CARRIED_ACORN_STATE_1_PULL_OUT) { - skeletalAnim_set(this->unk148, ASSET_25B_ANIM_ACORN_IDLE, 0.0f, 1.0f); - skeletalAnim_setCallback_1(this->unk148, 0.5f, (GenFunction_1)chCarriedAcorn_sfxBoing, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.7f, (GenFunction_1)chCarriedAcorn_sfxBanjoNoise, (uintptr_t)this->marker); + local = (ActorLocal_CCW_61E0 *)&this->local; + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x25B, 0.0f, 1.0f); + skeletalAnim_setCallback_1(this->unk148, 0.5f, (GenFunction_1)CCW_func_8038C5D0, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.7f, (GenFunction_1)CCW_func_8038C638, (uintptr_t)this->marker); } - if (next_state == CH_CARRIED_ACORN_STATE_3_TOSS) { - local->position[0] = this->position[0]; - local->position[1] = this->position[1]; - local->position[2] = this->position[2]; - chAutumnOutsideNabnut_getPosition(local->unkC); + if (next_state == 3) { + local->unk0[0] = this->position[0]; + local->unk0[1] = this->position[1]; + local->unk0[2] = this->position[2]; + func_8038BC50(local->unkC); local->unk18 = 0.0f; } - if (next_state == CH_CARRIED_ACORN_STATE_4_GIVEN_TO_NABNUT) { + if (next_state == 4) { coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); marker_despawn(this->marker); } - if (next_state == CH_CARRIED_ACORN_STATE_5_DESPAWN) { + if (next_state == 5) { marker_despawn(this->marker); } this->state = next_state; } -void chCarriedAcorn_update(Actor *this) { - bool player_is_carrying_acorn; - ActorLocal_ChCarriedAcorn *local; - f32 time_delta; - f32 player_position[3]; - - local = (ActorLocal_ChCarriedAcorn *)&this->local; - time_delta = time_getDelta(); - - if (port_remoteCarry_displayUpdate(this)) { - return; - } +void func_8038C7A8(Actor *this) { + bool sp4C; + ActorLocal_CCW_61E0 *local; + f32 sp44; + f32 sp38[3]; + local = (ActorLocal_CCW_61E0 *)&this->local; + sp44 = time_getDelta(); if (!this->volatile_initialized) { this->volatile_initialized = true; return; } - player_is_carrying_acorn = (bacarry_getMarkerWithExtraSteps() == this->marker); - if (this->state == CH_CARRIED_ACORN_STATE_0_NOT_INIT) { - if (player_is_carrying_acorn) { - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_2_HOLDING); - } else { - s32 acornSuppress; - port_carriedSync_register(ANCHOR_COLLECTIBLE_ACORN, this->marker, (s32)this->position[0], - (s32)this->position[1], (s32)this->position[2], &acornSuppress); - if (acornSuppress) { - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); - return; - } - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_1_PULL_OUT); - } + sp4C = (func_8028E86C() == this->marker); + if (this->state == 0) { + CCW_func_8038C6A0(this, sp4C ? 2 : 1); } - if (this->state == CH_CARRIED_ACORN_STATE_1_PULL_OUT) { - if (port_carriedSync_consumeRemoteDespawn(ANCHOR_COLLECTIBLE_ACORN, this->marker)) { - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); - return; - } - player_getPosition(player_position); - if (ml_vec3f_distance(this->position, player_position) < 50.0f) { - bacarriedobj_incWithExtraSteps(ACTOR_2A9_ACORN); + if (this->state == 1) { + player_getPosition(sp38); + if (ml_vec3f_distance(this->position, sp38) < 50.0f) { + func_8028F030(0x2A9); sfx_playFadeShorthandDefault(SFX_C5_TWINKLY_POP, 1.0f, 25000, this->position, 500, 2500); - port_carriedSync_onLocalCollect(ANCHOR_COLLECTIBLE_ACORN, this->marker); - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); + CCW_func_8038C6A0(this, 5); } } - if (this->state == CH_CARRIED_ACORN_STATE_2_HOLDING) { + if (this->state == 2) { if (this->unk138_21) { - f32 throwTarget[3]; - chAutumnOutsideNabnut_getPosition(throwTarget); - port_anchor_onCarryThrow(this->marker->id, this->position, throwTarget); - bacarriedobj_decWithExtraSteps(ACTOR_2A9_ACORN); - port_carriedSync_onLocalSpend(ANCHOR_COLLECTIBLE_ACORN); - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_3_TOSS); - } else if (!player_is_carrying_acorn) { - bacarriedobj_displayOnHudWithExtraSteps(ACTOR_2A9_ACORN); - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_5_DESPAWN); + func_8028F010(0x2A9); + CCW_func_8038C6A0(this, 3); + } else if (!sp4C) { + func_8028F050(0x2A9); + CCW_func_8038C6A0(this, 5); } } - if (this->state == CH_CARRIED_ACORN_STATE_3_TOSS) { - local->unk18 += 3.3333333333333333 * time_delta; + if (this->state == 3) { + local->unk18 += 3.3333333333333333 * sp44; local->unk18 = (local->unk18 > 1.0) ? 1.0 : local->unk18; - ml_vec3f_interpolate_fast(this->position, local->position, local->unkC, local->unk18); + ml_vec3f_interpolate_fast(this->position, local->unk0, local->unkC, local->unk18); this->position[1] += 50.0f * sinf(local->unk18 * BAD_PI); if (local->unk18 == 1.0) { - chCarriedAcorn_setNextState(this, CH_CARRIED_ACORN_STATE_4_GIVEN_TO_NABNUT); + CCW_func_8038C6A0(this, 4); } } } diff --git a/src/CCW/ch/adulteyrie.c b/src/CCW/ch/adulteyrie.c deleted file mode 100644 index a67ebde26..000000000 --- a/src/CCW/ch/adulteyrie.c +++ /dev/null @@ -1,129 +0,0 @@ -// BanjoDecomp: CCW/ch/adulteyrie.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 unk0; - f32 unk4; - s16 unk8; - s16 unkA; -}Struct_CCW_4530_0; - -void chEyrieAdult_setNextState(Actor *this, s32 next_state); -Actor *chEyrieAdult_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chEyrieAdult_update(Actor *this); - -/* .data */ -// This is the idle Eyrie in the nest -ActorInfo chEyrieAdult = { - MARKER_1B6_EEYRIE_ADULT, ACTOR_2A3_EEYRIE_ADULT, ASSET_487_MODEL_EAGLE_ADULT, - 0x0, NULL, - chEyrieAdult_update, NULL, chEyrieAdult_draw, - 0, 0, 0.0f, 0 -}; - -Struct_CCW_4530_0 chEyrieAdultSFX[] = { - {0.15f, 0.9f, SFX_A5_EYRIE_CRY, 25000}, - {0.3f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, - {0.6f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, - {0.68f, 0.85f, SFX_2_CLAW_SWIPE, 23000}, - {0.75f, 0.9f, SFX_2_CLAW_SWIPE, 28000}, - {0.8f, 0.95f, SFX_2_CLAW_SWIPE, 30000}, - {0.81f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, - {0.86f, 1.0f, SFX_2_CLAW_SWIPE, 31000}, - {0.93f, 1.0f, SFX_2_CLAW_SWIPE, 32000}, - 0 -}; - -enum chEyrieAdult_State_e { - CH_EERYIE_ADULT_STATE_0_NOT_INIT, - CH_EERYIE_ADULT_STATE_1_WAITING, - CH_EERYIE_ADULT_STATE_2_MEET_DIALOG, - CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF, - CH_EERYIE_ADULT_STATE_4_DESPAWN -}; - -/* .code */ -void chEyrieAdult_setMarkerToState3(ActorMarker* marker, enum asset_e text_id, s32 arg2) { - chEyrieAdult_setNextState(marker_getActor(marker), CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF); -} - -void chEyrieAdult_setNextState(Actor *this, s32 next_state) { - if (next_state == CH_EERYIE_ADULT_STATE_1_WAITING) { - skeletalAnim_set(this->unk148, ASSET_199_ANIM_EEYRIE_ADULT_UNK, 0.0f, 6.5f); - } - if (next_state == CH_EERYIE_ADULT_STATE_2_MEET_DIALOG) { - gcdialog_showDialog(VER_SELECT(ASSET_CDC_DIALOG_ADULT_EYRIE_MEET_WINTER, 0x09F1, 0, 0), VER_SELECT(0xA, 0xE, 0, 0), this->position, this->marker, chEyrieAdult_setMarkerToState3, NULL); - } - if (next_state == CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF) { - skeletalAnim_set(this->unk148, ASSET_19A_ANIM_EEYRIE_ADULT_UNK, 0.0f, 7.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 0); - } - if (next_state == CH_EERYIE_ADULT_STATE_4_DESPAWN) { - mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT, 1); - marker_despawn(this->marker); - } - this->state = next_state; -} - -Actor *chEyrieAdult_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor *this; - - this = marker_getActor(marker); - if(this->state == CH_EERYIE_ADULT_STATE_0_NOT_INIT) - return this; - return actor_draw(marker, gfx, mtx, vtx); -} - -void chEyrieAdult_update(Actor *this) { - f32 player_position[3]; - f32 sp50; - f32 sp4C; - Struct_CCW_4530_0 *iPtr; - f32 sp44; - f32 sp40; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT, false); - if( (!fileProgressFlag_get(FILEPROG_E8_AUTMN_EYRIE_FED) || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) - && !volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - ) { - marker_despawn(this->marker); - } - else{ - chEyrieAdult_setNextState(this, CH_EERYIE_ADULT_STATE_1_WAITING); - } - return; - } - - if (this->state == CH_EERYIE_ADULT_STATE_1_WAITING) { - skeletalAnim_getProgressRange(this->unk148, &sp50, &sp4C); - if ((sp50 < 0.21) && (0.21 <= sp4C)) { - func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); - } - - if ((sp50 < 0.56) && (0.56 <= sp4C)) { - func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); - } - - player_getPosition(player_position); - if (ml_vec3f_distance(this->position, player_position) < 850.0f) { - chEyrieAdult_setNextState(this, CH_EERYIE_ADULT_STATE_2_MEET_DIALOG); - } - } - if (this->state == CH_EERYIE_ADULT_STATE_3_FLIGHT_TAKE_OFF) { - skeletalAnim_getProgressRange(this->unk148, &sp44, &sp40); - for(iPtr = &chEyrieAdultSFX[0]; iPtr->unk0 > 0.0f; iPtr++){ - if ((sp44 < iPtr->unk0) && (iPtr->unk0 <= sp40)) { - func_8030E878(iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 500.0f, 2500.0f); - } - } - if (skeletalAnim_getLoopCount(this->unk148) > 0) { - chEyrieAdult_setNextState(this, CH_EERYIE_ADULT_STATE_4_DESPAWN); - } - } -} diff --git a/src/CCW/ch/beanstalk.c b/src/CCW/ch/beanstalk.c deleted file mode 100644 index e7723a5fe..000000000 --- a/src/CCW/ch/beanstalk.c +++ /dev/null @@ -1,239 +0,0 @@ -// BanjoDecomp: CCW/ch/beanstalk.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - s16 waitingAnim; - u8 waitingAnimBehavior; - u8 isInit; - s16 growingAnim; - s16 grownAnim; - s16 completeFileProgress; - s16 completeSpawnsJiggy; -}Struct_CCW_1B20_0; - -typedef struct{ - Struct_CCW_1B20_0 *unk0; -}ActorLocal_CCW_1B20; - -void chCCWBeanstalk_setNextState(Actor *this, s32 next_state); -Actor *chCCWBeanstalk_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chCCWBeanstalk_update(Actor *this); - -enum chCCWBeanstalk_State_e { - CH_CCW_BEANSTALK_STATE_0_NOT_INIT, - CH_CCW_BEANSTALK_STATE_1_WAITING, - CH_CCW_BEANSTALK_STATE_2_GROWING, - CH_CCW_BEANSTALK_STATE_3_GROWN -}; - -/* .data */ -Struct_CCW_1B20_0 D_8038EC40[4] ={ - { - ASSET_173_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_4_STOPPED, - 0, // Is Initialized - ASSET_173_ANIM_BEANSTALK_UNK, - ASSET_181_ANIM_BEANSTALK_UNK, - FILEPROG_E3_CCW_FLOWER_SPRING, - false - }, - { - ASSET_181_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_1_LOOP, - 1, // Is Initialized - ASSET_174_ANIM_BEANSTALK_UNK, - ASSET_182_ANIM_BEANSTALK_UNK, - FILEPROG_E4_CCW_FLOWER_SUMMER, - false - }, - { - ASSET_182_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_1_LOOP, - 1, // Is Initialized - ASSET_175_ANIM_BEANSTALK_UNK, - ASSET_183_ANIM_BEANSTALK_UNK, - FILEPROG_E5_CCW_FLOWER_AUTUMN, - true - }, - { - ASSET_183_ANIM_BEANSTALK_UNK, SKELETAL_ANIM_1_LOOP, - 1, // Is Initialized - 0, - 0, - 0, - false - } -}; - -// Anchor: set during a remote-water replay; skips camera/fanfare/jiggy spawn. -static s32 sFlowerRemoteGrow = 0; - -ActorInfo chCCWBeanstalk = { - MARKER_1B0_CCW_BEANSTALK, ACTOR_29D_CCW_BEANSTALK, ASSET_447_MODEL_CCW_BEANSTALK, - 0x0, NULL, - chCCWBeanstalk_update, NULL, chCCWBeanstalk_draw, - 0, 0, 1.0f, 0 -}; - -f32 chCCWBeanstalkJiggyPosition[3] = {200.0f, 2120.0f, -5570.0f}; - -/* .code */ -void chCCWBeanstalk_spawnJiggy() { - jiggy_spawn(JIGGY_4D_CCW_FLOWER, chCCWBeanstalkJiggyPosition); -} - -void chCCWBeanstalk_setNextStateByMarker(ActorMarker* marker, s32 next_state) { - chCCWBeanstalk_setNextState(marker_getActor(marker), next_state); -} - -void chCCWBeanstalk_setNextState(Actor *this, s32 next_state){ - ActorLocal_CCW_1B20 *local; - f32 phi_f22; - - local = (ActorLocal_CCW_1B20 *)&this->local; - - if (next_state == CH_CCW_BEANSTALK_STATE_1_WAITING) { - this->marker->propPtr->unk8_3 = local->unk0->isInit; - skeletalAnim_set(this->unk148, local->unk0->waitingAnim, 0.0f, 5.0f); - skeletalAnim_setBehavior(this->unk148, local->unk0->waitingAnimBehavior); - } - if (next_state == CH_CCW_BEANSTALK_STATE_2_GROWING) { - if (gsworld_getMap() == MAP_43_CCW_SPRING && !sFlowerRemoteGrow) { - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - } - fileProgressFlag_set(local->unk0->completeFileProgress, true); - skeletalAnim_set(this->unk148, local->unk0->growingAnim, 0.0f, 6.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if (gsworld_getMap() == MAP_43_CCW_SPRING && !sFlowerRemoteGrow) { - func_80324E38(0.0f, 3); - } - if (!sFlowerRemoteGrow) { - timed_setStaticCameraToNode(0.0f, 0); - } - for( phi_f22 = 0.0f; phi_f22 <= 1.0f; phi_f22 += 0.1) { - timed_playSfx(phi_f22 * 5.7, 0x2C, phi_f22 * 0.3 + 0.7, (s32) (32000.0f - phi_f22 * 5000.0f)); - } - if (local->unk0->completeSpawnsJiggy != false) { - if (!sFlowerRemoteGrow) { - timed_setStaticCameraToNode(6.0f, 1); - timedFunc_set_0(6.1f, (GenFunction_0)chCCWBeanstalk_spawnJiggy); - } - timedFunc_set_2( - 8.0f, - (GenFunction_2)chCCWBeanstalk_setNextStateByMarker, - (uintptr_t)this->marker, - CH_CCW_BEANSTALK_STATE_3_GROWN); - } else { - if (gsworld_getMap() == MAP_43_CCW_SPRING && !sFlowerRemoteGrow) { - timed_exitStaticCamera(7.0f); - func_80324E38(7.0f, 0); - } - timedFunc_set_2( - 7.0f, - (GenFunction_2)chCCWBeanstalk_setNextStateByMarker, - (uintptr_t)this->marker, - CH_CCW_BEANSTALK_STATE_3_GROWN); - } - } - - if (next_state == CH_CCW_BEANSTALK_STATE_3_GROWN) { - this->marker->propPtr->unk8_3 = true; - skeletalAnim_set(this->unk148, local->unk0->grownAnim, 0.1f, 5.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - this->state = next_state; -} - -s32 func_80388260(ActorMarker *marker, s32 arg1){ - return marker->unk40_31 != 1; -} - -void chCCWBeanstalk_feed(ActorMarker *marker, ActorMarker *other_marker) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); -} - -void chCCWBeanstalk_spawnBeanstalk(ActorMarker* marker, ActorMarker *other_marker) { - Actor* actor = marker_getActor(marker); - - // [port] v1.1 fix: don't allow re-planting flower in Spring after it's already been planted - if (EventSystem_Should(VB_CCW_FLOWER_REPLANT, - gsworld_getMap() == MAP_43_CCW_SPRING && actor->state == CH_CCW_BEANSTALK_STATE_1_WAITING && - !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING))) { - chCCWBeanstalk_setNextState(actor, CH_CCW_BEANSTALK_STATE_2_GROWING); - } -} - -Actor *chCCWBeanstalk_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - s32 sp18; - - this = marker_getActor(marker); - if ((this->state == CH_CCW_BEANSTALK_STATE_1_WAITING) - && !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING)) - { - return func_80325340(marker, gfx, mtx, vtx); - } - - if ((skeletalAnim_getAnimId(this->unk148) == 0x175) - && (0.49 <= skeletalAnim_getProgress(this->unk148))) - { - sp18 = 1; - } else { - sp18 = 0; - } - sp18 = (skeletalAnim_getAnimId(this->unk148) == 0x183)? 1 : sp18; - modelRender_setAppendageVisibility(3, sp18); - modelRender_setAppendageVisibility(4, sp18); - return actor_draw(marker, gfx, mtx, vtx); -} - -void chCCWBeanstalk_growBeanstalk() { - Actor* actor = actorArray_findActorFromActorId(ACTOR_29D_CCW_BEANSTALK); - if (actor && actor->state == CH_CCW_BEANSTALK_STATE_1_WAITING) { - chCCWBeanstalk_setNextState(actor, CH_CCW_BEANSTALK_STATE_2_GROWING); - } -} - -bool chCCWBeanstalk_hasSpawned() { - Actor* actor = actorArray_findActorFromActorId(ACTOR_29D_CCW_BEANSTALK); - if (actor && actor->state == CH_CCW_BEANSTALK_STATE_2_GROWING) { - return true; - } - return false; -} - -void chCCWBeanstalk_update(Actor *this) { - ActorLocal_CCW_1B20 *local; - - local = (ActorLocal_CCW_1B20 *)&this->local; - if (!this->volatile_initialized) { - this->volatile_initialized = true; - func_803300C0(this->marker, (s32 (*)(ActorMarker *, ActorMarker *))func_80388260); - marker_setCollisionScripts(this->marker, NULL, chCCWBeanstalk_feed, chCCWBeanstalk_spawnBeanstalk); - actor_collisionOn(this); - if (!jiggyscore_isSpawned(JIGGY_4D_CCW_FLOWER)) { - fileProgressFlag_set(FILEPROG_E5_CCW_FLOWER_AUTUMN, false); - } - - for(local->unk0 = &D_8038EC40[0]; local->unk0 < D_8038EC40 + 3; local->unk0++){ - if(!fileProgressFlag_get(local->unk0->completeFileProgress)){ - break; - } - } - - if (!fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING) - && (gsworld_getMap() != MAP_43_CCW_SPRING)) - { - marker_despawn(this->marker); - } - else{ - chCCWBeanstalk_setNextState(this, CH_CCW_BEANSTALK_STATE_1_WAITING); - } - return; - } - - if ((this->state == CH_CCW_BEANSTALK_STATE_1_WAITING) && EventSystem_Should(VB_CCW_FLOWER_REMOTE_GROW, false, (s32)local->unk0->completeFileProgress)) { - sFlowerRemoteGrow = 1; - chCCWBeanstalk_setNextState(this, CH_CCW_BEANSTALK_STATE_2_GROWING); - sFlowerRemoteGrow = 0; - } -} diff --git a/src/CCW/ch/caterpillar.c b/src/CCW/ch/caterpillar.c index 51c8f0777..90049e190 100644 --- a/src/CCW/ch/caterpillar.c +++ b/src/CCW/ch/caterpillar.c @@ -1,18 +1,15 @@ -// BanjoDecomp: CCW/ch/caterpillar.c +// BanjoDecomp: code_3DA0.c #include #include "functions.h" #include "variables.h" -#include "port/Enhancements/Retention/Retention.h" -extern ActorMarker *bacarry_getMarkerWithExtraSteps(void); +extern ActorMarker *func_8028E86C(void); extern void func_8028F7D4(f32, f32); -extern s32 port_remoteCarry_displayUpdate(Actor *this); -extern void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]); typedef struct { - f32 position[3]; - f32 unkC[3]; // some kind of distance - f32 unk18[3]; // something time related + f32 unk0[3]; + f32 unkC[3]; + f32 unk18[3]; f32 unk24; } ActorLocal_Caterpillar; @@ -27,52 +24,41 @@ ActorInfo chCaterpillar = { 0, 0, 1.0f, 0 }; -enum chCaterpillar_State_e { - CH_CATERPILLAR_STATE_0_NOT_INIT, - CH_CATERPILLAR_STATE_1_PULL_OUT, - CH_CATERPILLAR_STATE_2_HOLDING, - CH_CATERPILLAR_STATE_3_TOSS, - CH_CATERPILLAR_STATE_4_GIVEN_TO_EEYRIE, - CH_CATERPILLAR_STATE_5_DESPAWN -}; - /* .code */ f32 func_8038A190(Actor *this, f32 *arg1) { - f32 floor_y_position; - f32 caterpillar_y_position; - - floor_y_position = mapModel_getFloorY(arg1); - caterpillar_y_position = this->position[1]; - if (((caterpillar_y_position + 50.0f) < floor_y_position) - || (floor_y_position < (caterpillar_y_position - 50.0f))) - { - return caterpillar_y_position; + f32 temp_f0; + f32 temp_f2; + + temp_f0 = mapModel_getFloorY(arg1); + temp_f2 = this->position[1]; + if (((temp_f2 + 50.0f) < temp_f0) || (temp_f0 < (temp_f2 - 50.0f))) { + return temp_f2; } - return floor_y_position; + return temp_f0; } void chcaterpillar_setState(Actor *this, s32 next_state) { ActorLocal_Caterpillar *local = (ActorLocal_Caterpillar *)&this->local; - if (next_state == CH_CATERPILLAR_STATE_1_PULL_OUT) { - skeletalAnim_set(this->unk148, ASSET_18D_ANIM_CATERPILLAR_UNK, 0.0f, randf2(1.9f, 2.1f)); + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x18D, 0.0f, randf2(1.9f, 2.1f)); } - if (next_state == CH_CATERPILLAR_STATE_2_HOLDING) { + if (next_state == 2) { func_8028F7D4(-25.0f, 90.0f); - skeletalAnim_set(this->unk148, ASSET_18E_ANIM_CATERPILLAR_IDLE, 0.2f, 2.0f); + skeletalAnim_set(this->unk148, 0x18E, 0.2f, 2.0f); } - if (next_state == CH_CATERPILLAR_STATE_3_TOSS) { - skeletalAnim_set(this->unk148, ASSET_18E_ANIM_CATERPILLAR_IDLE, 0.2f, 2.0f); + if (next_state == 3) { + skeletalAnim_set(this->unk148, 0x18E, 0.2f, 2.0f); local->unkC[0] = this->position[0]; local->unkC[1] = this->position[1]; local->unkC[2] = this->position[2]; local->unk24 = 0.0f; } - if (next_state == CH_CATERPILLAR_STATE_4_GIVEN_TO_EEYRIE) { + if (next_state == 4) { coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); marker_despawn(this->marker); } - if (next_state == CH_CATERPILLAR_STATE_5_DESPAWN) { + if (next_state == 5) { actor_collisionOff(this); } this->state = next_state; @@ -80,16 +66,16 @@ void chcaterpillar_setState(Actor *this, s32 next_state) { Actor* chcaterpillar_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - if(this->state == CH_CATERPILLAR_STATE_5_DESPAWN){ + if(this->state == 5){ return func_80325340(marker, gfx, mtx, vtx); } return actor_draw(marker, gfx, mtx, vtx); } void chcaterpillar_update(Actor *this){ - bool player_is_carrying_caterpillar; + bool sp8C; ActorLocal_Caterpillar *local = (ActorLocal_Caterpillar *)&this->local; - f32 time_delta; + f32 sp84; enum map_e map_id; f32 sp74[3]; f32 sp70; @@ -100,63 +86,48 @@ void chcaterpillar_update(Actor *this){ f32 sp54[3]; int i; - if (port_remoteCarry_displayUpdate(this)) { - return; - } - - player_is_carrying_caterpillar = bacarry_getMarkerWithExtraSteps() == this->marker; - time_delta = time_getDelta(); + sp8C = func_8028E86C() == this->marker; + sp84 = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = true; - local->position[0] = this->position[0]; - local->position[1] = this->position[1]; - local->position[2] = this->position[2]; - if(player_is_carrying_caterpillar){ - chcaterpillar_setState(this, CH_CATERPILLAR_STATE_2_HOLDING); + local->unk0[0] = this->position[0]; + local->unk0[1] = this->position[1]; + local->unk0[2] = this->position[2]; + if(sp8C){ + chcaterpillar_setState(this, 2); } else{//L8038A408 map_id = gsworld_getMap(); if ( !fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED) || ( map_id == MAP_45_CCW_AUTUMN && !fileProgressFlag_get(FILEPROG_E7_SUMMER_EYRIE_FED)) ) { - chcaterpillar_setState(this, CH_CATERPILLAR_STATE_5_DESPAWN); + chcaterpillar_setState(this, 5); } else { - s32 wormSuppress; - port_carriedSync_register(ANCHOR_COLLECTIBLE_WORM, this->marker, (s32)this->position[0], - (s32)this->position[1], (s32)this->position[2], &wormSuppress); - if (wormSuppress) { - marker_despawn(this->marker); - return; - } - chcaterpillar_setState(this, CH_CATERPILLAR_STATE_1_PULL_OUT); + chcaterpillar_setState(this, 1); }//L8038A45C } }//L8038A45C - if(this->state == CH_CATERPILLAR_STATE_1_PULL_OUT){ - if(port_carriedSync_consumeRemoteDespawn(ANCHOR_COLLECTIBLE_WORM, this->marker)){ - marker_despawn(this->marker); - return; - } + if(this->state == 1){ skeletalAnim_getProgressRange(this->unk148, &sp64, &sp60); player_getPosition(sp74); - if(ml_vec3f_distance(this->position, local->position) < 10.0f){ + if(ml_vec3f_distance(this->position, local->unk0) < 10.0f){ for(i = 0; i < 10; i++){ - local->position[0] = randf2(-300.0f, 300.0f) + this->position_x; - local->position[1] = this->position_y; - local->position[2] = randf2(-300.0f, 300.0f) + this->position_z; - if( !(ml_vec3f_distance(local->position, this->position) < 50.0f) && func_80329210(this, &local->position)) + local->unk0[0] = randf2(-300.0f, 300.0f) + this->position_x; + local->unk0[1] = this->position_y; + local->unk0[2] = randf2(-300.0f, 300.0f) + this->position_z; + if( !(ml_vec3f_distance(local->unk0, this->position) < 50.0f) && func_80329210(this, &local->unk0)) break; }//L8038A544 if(i == 10){ - local->position[0] = this->position[0];\ - local->position[1] = this->position[1];\ - local->position[2] = this->position[2]; + local->unk0[0] = this->position[0];\ + local->unk0[1] = this->position[1];\ + local->unk0[2] = this->position[2]; }//L8038A564 if (i); - local->position[1] = func_8038A190(this, local->position); + local->unk0[1] = func_8038A190(this, local->unk0); }//L8038A570 if(sp64 <= 0.1 && 0.1 < sp60){ @@ -164,8 +135,8 @@ void chcaterpillar_update(Actor *this){ }//L8038A5EC if(0.65 < sp60){ - func_80258A4C(this->position, this->yaw - 90.0f, local->position, &sp70, &sp6C, &sp68); - this->yaw += (sp68*100.0f) * time_delta; + func_80258A4C(this->position, this->yaw - 90.0f, local->unk0, &sp70, &sp6C, &sp68); + this->yaw += (sp68*100.0f)*sp84; }//L8038A668 if(sp60 <= 0.4){ @@ -173,50 +144,45 @@ void chcaterpillar_update(Actor *this){ sp54[2] = 0.0f; sp54[0] = 65.0f; ml_vec3f_yaw_rotate_copy(sp54, sp54, this->yaw - 90.0f); - this->position[0] += time_delta * sp54[0]; - this->position[2] += time_delta * sp54[2]; + this->position[0] += sp84*sp54[0]; + this->position[2] += sp84*sp54[2]; if(this->marker->unk14_21){ this->position[1] = func_8038A190(this, this->position); } }//L8038A714 if(ml_vec3f_distance(this->position, sp74) < 50.0f){ - bacarriedobj_incWithExtraSteps(ACTOR_2A2_CATERPILLAR); + func_8028F030(ACTOR_2A2_CATERPILLAR); if(!volatileFlag_get(VOLATILE_FLAG_B2_HAS_COLLECTED_CATERPILLAR)){ - gcdialog_showDialog(VER_SELECT(ASSET_CC7_DIALOG_CATERPILLAR_COLLECT, 0x09DC, 0, 0), 4, NULL, NULL, NULL, NULL); - volatileFlag_set(VOLATILE_FLAG_B2_HAS_COLLECTED_CATERPILLAR, TRUE); + gcdialog_showDialog(ASSET_CC7_DIALOG_CATERPILLAR_COLLECT, 4, NULL, NULL, NULL, NULL); + volatileFlag_set(VOLATILE_FLAG_B2_HAS_COLLECTED_CATERPILLAR, true); } sfx_playFadeShorthandDefault(SFX_C5_TWINKLY_POP, 1.0f, 25000, this->position, 0x1f4, 0x9c4); - port_carriedSync_onLocalCollect(ANCHOR_COLLECTIBLE_WORM, this->marker); marker_despawn(this->marker); } }//L8038A794 - if(this->state == CH_CATERPILLAR_STATE_2_HOLDING){ + if(this->state == 2){ if(this->unk138_21){ - f32 throwTarget[3]; - func_80389BD8(throwTarget); - port_anchor_onCarryThrow(this->marker->id, this->position, throwTarget); - bacarriedobj_decWithExtraSteps(ACTOR_2A2_CATERPILLAR); - port_carriedSync_onLocalSpend(ANCHOR_COLLECTIBLE_WORM); - chcaterpillar_setState(this, CH_CATERPILLAR_STATE_3_TOSS); + func_8028F010(ACTOR_2A2_CATERPILLAR); + chcaterpillar_setState(this, 3); } - else if(!player_is_carrying_caterpillar){ - bacarriedobj_displayOnHudWithExtraSteps(ACTOR_2A2_CATERPILLAR); + else if(!sp8C){ + func_8028F050(ACTOR_2A2_CATERPILLAR); marker_despawn(this->marker); } }//L8038A804 - if(this->state == CH_CATERPILLAR_STATE_3_TOSS){ + if(this->state == 3){ func_80389BD8(local->unk18); - local->unk24 += 3.3333333333333335 * time_delta; + local->unk24 += 3.3333333333333335*sp84; local->unk24 = (1.0 < local->unk24) ? 1.0 : local->unk24; ml_vec3f_interpolate_fast(this->position, local->unkC, local->unk18, local->unk24); - this->position[1] += 50.0f*sinf(local->unk24 * 3.141592654); + this->position[1] += 50.0f*sinf(local->unk24*3.141592654); if(1.0 == local->unk24){ - chcaterpillar_setState(this, CH_CATERPILLAR_STATE_4_GIVEN_TO_EEYRIE); + chcaterpillar_setState(this, 4); } }//L8038A8FC } diff --git a/src/CCW/ch/cutsceneadulteyrie.c b/src/CCW/ch/cutsceneadulteyrie.c deleted file mode 100644 index 986470de2..000000000 --- a/src/CCW/ch/cutsceneadulteyrie.c +++ /dev/null @@ -1,114 +0,0 @@ -// BanjoDecomp: CCW/ch/cutsceneadulteyrie.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 unk0; - f32 unk4; - s16 unk8; - s16 unkA; -}Struct_CCW_4960_0; - -Actor *chCutsceneAdultEyrie_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chCutsceneAdultEyrie_update(Actor *this); - -/* .data */ -// This is the flying Eyrie that poops the Jiggy -ActorInfo chCutsceneAdultEyrie = { - MARKER_1C4_CUTSCENE_ADULT_EYRIE, ACTOR_30E_CUTSCENE_ADULT_EYRIE, ASSET_487_MODEL_EAGLE_ADULT, - 0x0, NULL, - chCutsceneAdultEyrie_update, chCutsceneAdultEyrie_update, chCutsceneAdultEyrie_draw, - 0, 0, 0.0f, 0 -}; - -Struct_CCW_4960_0 chCutsceneAdultEyrieSFX[] = { - {0.5f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, - 0 -}; - -enum chCutsceneAdultEyrie_State_e { - CH_CUTSCENE_ADULT_EYRIE_STATE_0_NOT_INIT, - CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK, - CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK, - CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK, - CH_CUTSCENE_ADULT_EYRIE_STATE_4_UNK -}; - -/* .code */ -void chCutsceneAdultEyrie_setNextState(Actor *this, s32 next_state) { - if (next_state == CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK) { - gcdialog_showDialog(VER_SELECT(ASSET_CDD_DIALOG_ADULT_EYRIE_COMPLETE_WINTER, 0x09F2, 0, 0), 0, NULL, NULL, NULL, NULL); - if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK) { - mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT, 0); - timed_setStaticCameraToNode(0.0f, 1); - } - skeletalAnim_set(this->unk148, ASSET_21D_ANIM_ADULT_EYRIE_UNK, 0.2f, 0.5f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - if (next_state == CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK) { - skeletalAnim_set(this->unk148, ASSET_21E_ANIM_ADULT_EYRIE_UNK, 0.2f, 2.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - } - if (next_state == CH_CUTSCENE_ADULT_EYRIE_STATE_4_UNK) { - timed_exitStaticCamera(0.0f); - func_80324E38(0.0f, 0); - marker_despawn(this->marker); - } - this->state = next_state; -} - -Actor *chCutsceneAdultEyrie_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor *this; - - this = marker_getActor(marker); - if(this->state < CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK) - return this; - return actor_draw(marker, gfx, mtx, vtx); -} - -void chCutsceneAdultEyrie_update(Actor *this) { - Struct_CCW_4960_0 *iPtr; - f32 sp38; - f32 sp34; - f32 sp30; - f32 sp2C; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK); - return; - } - if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_1_UNK){ - if(mapSpecificFlags_get(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT)) { - mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_5_EEYRIE_ADULT, false); - chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK); - } - } - if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK) { - actor_update_func_80326224(this); - skeletalAnim_getProgressRange(this->unk148, &sp38, &sp34); - for(iPtr = &chCutsceneAdultEyrieSFX[0]; iPtr->unk0 > 0.0f; iPtr++){ - if ((sp38 < iPtr->unk0) && (iPtr->unk0 <= sp34)) { - func_8030E878((s32) iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 1500.0f, 4500.0f); - } - } - if (mapSpecificFlags_get(CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT)) { - mapSpecificFlags_set(CCW_WINTER_SPECIFIC_FLAG_6_CUTSCENE_EEYRIE_ADULT, false); - chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK); - } - if (0.99 < this->unk48) { - chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_4_UNK); - } - } - if (this->state == CH_CUTSCENE_ADULT_EYRIE_STATE_3_UNK) { - actor_update_func_80326224(this); - skeletalAnim_getProgressRange(this->unk148, &sp30, &sp2C); - if ((sp30 <= 0.5) && (sp2C >= 0.5) && !jiggyscore_isCollected(JIGGY_49_CCW_EYRIE)) { - jiggy_spawn(JIGGY_49_CCW_EYRIE, this->position); - } - if (skeletalAnim_getLoopCount(this->unk148) > 0) { - chCutsceneAdultEyrie_setNextState(this, CH_CUTSCENE_ADULT_EYRIE_STATE_2_UNK); - } - } -} diff --git a/src/CCW/ch/deadbeanstalk.c b/src/CCW/ch/deadbeanstalk.c index 7f5eca32c..b98e15bf3 100644 --- a/src/CCW/ch/deadbeanstalk.c +++ b/src/CCW/ch/deadbeanstalk.c @@ -6,14 +6,8 @@ void chDeadBeanstalk_update(Actor *this); /* .data */ - -enum chDeadBeanstalk_state_e { - DEAD_BEANSTALK_STATE_0_NOT_INIT, - DEAD_BEANSTALK_STATE_1_IDLE -}; - -ActorInfo chDeadBeanstalk = { - MARKER_1C2_DEAD_BEANSTALK, ACTOR_30B_DEAD_BEANSTALK, ASSET_4E3_MODEL_DEAD_BEANSTALK, +ActorInfo D_8038ECA0 = { + 0x1C2, 0x30B, 0x4E3, 0x0, NULL, chDeadBeanstalk_update, NULL, actor_draw, 0, 0, 1.0f, 0 @@ -21,7 +15,7 @@ ActorInfo chDeadBeanstalk = { /* .code */ void chDeadBeanstalk_setNextState(Actor *this, s32 next_state){ - if(next_state == DEAD_BEANSTALK_STATE_1_IDLE){ + if(next_state == 1){ skeletalAnim_set(this->unk148, 0x219, 0.0f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); } @@ -32,7 +26,7 @@ void chDeadBeanstalk_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; if(fileProgressFlag_get(FILEPROG_E5_CCW_FLOWER_AUTUMN)){ - chDeadBeanstalk_setNextState(this, DEAD_BEANSTALK_STATE_1_IDLE); + chDeadBeanstalk_setNextState(this, 1); } else{ marker_despawn(this->marker); diff --git a/src/CCW/ch/deadsnarebear.c b/src/CCW/ch/deadsnarebear.c deleted file mode 100644 index ab6532cec..000000000 --- a/src/CCW/ch/deadsnarebear.c +++ /dev/null @@ -1,25 +0,0 @@ -// BanjoDecomp: CCW/ch/deadsnarebear.c -#include -#include "functions.h" -#include "variables.h" - -void chDeadSnarebear_update(Actor *this); - - -ActorAnimationInfo chDeadSnarebearAnimations[] = { - {0x000, 0.0f}, - {ASSET_234_ANIM_DEAD_SNAREBEAR, 2.0f} -}; - -ActorInfo chDeadSnarebear = { - MARKER_251_DEAD_SNAREBEAR, ACTOR_37E_DEAD_SNAREBEAR, ASSET_506_CCW_DEAD_SNAREBEAR, - 0x1, chDeadSnarebearAnimations, - chDeadSnarebear_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -/* .code */ -void chDeadSnarebear_update(Actor *this){ - this->marker->propPtr->unk8_3 = true; - actor_collisionOff(this); -} diff --git a/src/CCW/ch/eyrie_baby.c b/src/CCW/ch/eyrie_baby.c new file mode 100644 index 000000000..1edf612dd --- /dev/null +++ b/src/CCW/ch/eyrie_baby.c @@ -0,0 +1,301 @@ +// BanjoDecomp: code_3310.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 unk0; + s16 unk4; + f32 unk8; + s16 unkC; +}Struct_CCW_3310_1; + +typedef struct { + s16 map_id; + s16 unk2; // enum file_progress_e + s16 unk4; // enum file_progress_e + s16 unk6; + Struct_CCW_3310_1 *unk8; + s16 unkC; + s16 unkE; + Struct_CCW_3310_1 *unk10; + s16 unk14; + // u8 pad16[2]; + Struct_CCW_3310_1 *unk18; + s16 unk1C; + // u8 pad1E[0x2]; + Struct_CCW_3310_1 *unk20; + u8 unk24; + u8 unk25; + s16 unk26; + s16 unk28; + // u8 pad2A[2]; +}Struct_CCW_3310_0; + +typedef struct { + Struct_CCW_3310_0 *unk0; + u8 unk4; + //u8 pad5[3]; + Struct_CCW_3310_1 *unk8; + s32 unkC[3]; +}ActorLocal_CCW_3310; + +Actor *func_80389B24(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void CCW_func_80389BFC(Actor *this); + +/* .data */ +Struct_CCW_3310_1 D_8038EEA0[] = { + {0.11f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, + {0.22f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, + {0.34f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, + {0.55f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, + {0.65f, SFX_2_CLAW_SWIPE, 1.0f, 26000}, + {0.77f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, + {0.87f, SFX_2_CLAW_SWIPE, 1.0f, 24000}, + 0 +}; + +Struct_CCW_3310_1 D_8038EF20[] = { + {0.1f, SFX_80_YUMYUM_CLACK, 0.9f, 15000}, + {0.25f, SFX_4C_LIP_SMACK, 1.0f, 15000}, + {0.31f, SFX_4C_LIP_SMACK, 0.9f, 15000}, + {0.38f, SFX_4C_LIP_SMACK, 1.0f, 15000}, + {0.48f, SFX_4C_LIP_SMACK, 0.9f, 15000}, + {0.55f, SFX_97_BLUBBER_BURPS, 0.9f, 32700}, + {0.6f , SFX_2C_PULLING_NOISE, 0.7f, 25000}, + {0.73f, SFX_2C_PULLING_NOISE, 0.8f, 27000}, + {0.85f, SFX_2C_PULLING_NOISE, 0.9f, 29000}, + 0 +}; + +Struct_CCW_3310_1 D_8038EFC0[] = { + {0.2f , SFX_105_EYRIE_YAWN, 1.1f, 25000}, + {0.27f, SFX_105_EYRIE_YAWN, 1.0f, 25000}, + {0.35f, SFX_105_EYRIE_YAWN, 0.9f, 25000}, + {0.6f , SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, + {0.66f, SFX_106_EYRIE_LIPSMACK, 0.9f, 23000}, + {0.83f, SFX_1D_HITTING_AN_ENEMY_1, 0.7f, 27000}, + 0 +}; + +Struct_CCW_3310_1 D_8038F030[] = { + {0.2f , SFX_5D_BANJO_RAAOWW, 1.0f, 25000}, + {0.72f, SFX_5E_BANJO_PHEWWW, 1.0f, 25000}, + 0 +}; + +Struct_CCW_3310_1 D_8038F060[] = { + {0.95f, SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, + 0 +}; + +Struct_CCW_3310_0 D_8038F080[] = { + {MAP_43_CCW_SPRING, 0, FILEPROG_E6_SPRING_EYRIE_HATCHED, 0, NULL, 3, 0, NULL, 0x18F, D_8038EFC0, 0x190, D_8038F030, 0, 0, 0, 0}, + {MAP_44_CCW_SUMMER, FILEPROG_E6_SPRING_EYRIE_HATCHED, FILEPROG_E7_SUMMER_EYRIE_FED, 0x191, D_8038EEA0, 2, 0x192, D_8038EF20, 0x193, D_8038EFC0, 0x194, D_8038F030, 2, 5, 0x21A, 0xCD7}, + {MAP_45_CCW_AUTUMN, FILEPROG_E7_SUMMER_EYRIE_FED, FILEPROG_E8_AUTMN_EYRIE_FED, 0x195, D_8038EEA0, 2, 0x196, D_8038EF20, 0x197, D_8038EFC0, 0x198, D_8038F030, 4, 0xA, 0x21B, 0xCDA}, + 0 +}; + +ActorInfo D_8038F130 = { MARKER_1B4_EEYRIE_BABY, ACTOR_2A1_EEYRIE_BABY, ASSET_484_MODEL_EAGLE_BABY, 0x0, NULL, CCW_func_80389BFC, NULL, func_80389B24, 0, 0, 0.0f, 0}; + +/* .bss */ +f32 D_8038FDE0[3]; + +/* .code */ +void func_80389700(ActorMarker *marker, enum asset_e text_id, s32 arg2) { + timed_exitStaticCamera(0.5f); + func_80324E38(0.5f, 0); +} + +void func_80389740(ActorMarker *marker) { + Actor *this = marker_getActor(marker); + if (this->marker->unk14_21) { + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x30C, reinterpret_cast(s32, D_8038FDE0[0]), reinterpret_cast(s32, D_8038FDE0[1]), reinterpret_cast(s32, D_8038FDE0[2])); + } +} + +void func_80389798() { + func_8030E6D4(SFX_18C_EYRIE_MAMA); +} + +void func_803897B8(Actor *this, s32 next_state) { + ActorLocal_CCW_3310 *local; + + local = (ActorLocal_CCW_3310 *)&this->local; + local->unk8 = NULL; + if (next_state == 1) { + if (local->unk0->unk6 != 0) { + skeletalAnim_set(this->unk148, local->unk0->unk6, 0.2f, 6.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + local->unk8 = local->unk0->unk8; + } + if ((this->state == 1) && (next_state == 2)) { + fileProgressFlag_set(local->unk0->unk4, true); + } + if (next_state == 5) { + func_8028F784(1); + skeletalAnim_set(this->unk148, local->unk0->unk26, 0.2f, 2.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + local->unk8 = &D_8038F060[0]; + } + + if (next_state == 2) { + skeletalAnim_set(this->unk148, local->unk0->unkE, 0.2f, 8.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + func_80324E38(0.5f, 3); + timed_setStaticCameraToNode(0.5f, local->unk0->unk24); + timed_exitStaticCamera(16.5f); + func_80324E38(16.5f, 0); + local->unk8 = local->unk0->unk10; + } + if (next_state == 3) { + actor_collisionOff(this); + skeletalAnim_set(this->unk148, local->unk0->unk14, 0.5f, 8.5f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + if (local->unk0->map_id == MAP_43_CCW_SPRING) { + gcdialog_showDialog(0xCD6, 4, NULL, NULL, NULL, NULL); + skeletalAnim_setCallback_0(this->unk148, 0.65f, (GenFunction_0)&func_80389798); + } + if (local->unk0->map_id == MAP_44_CCW_SUMMER) { + gcdialog_showDialog(0xCD9, 4, NULL, NULL, NULL, NULL); + } + if (local->unk0->map_id == MAP_45_CCW_AUTUMN) { + gcdialog_showDialog(0xCDB, 4, NULL, NULL, NULL, NULL); + } + local->unk8 = local->unk0->unk18; + } + if (next_state == 4) { + func_8028F784(0); + skeletalAnim_set(this->unk148, local->unk0->unk1C, 0.2f, 6.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + skeletalAnim_setCallback_1(this->unk148, 0.2f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.4f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.72f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.82f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.92f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); + local->unk8 = local->unk0->unk20; + } + this->state = next_state; +} + +Actor *func_80389B24(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor *this; + ActorLocal_CCW_3310 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_3310 *)&this->local; + if( (this->state == 0) + || ((this->state == 1) && (local->unk0->unk6 == 0)) + ) { + return this; + } + func_8033A45C(3, (this->state == 4) ? 2 : 1); + actor_draw(marker, gfx, mtx, vtx); + vec3fArray_get_vec3f(func_80329934(), 5, D_8038FDE0); + return this; +} + +void func_80389BD8(f32 dst[3]){ + dst[0] = D_8038FDE0[0]; + dst[1] = D_8038FDE0[1]; + dst[2] = D_8038FDE0[2]; +} + +void CCW_func_80389BFC(Actor *this) { + Struct_CCW_3310_1 *iPtr; + ActorLocal_CCW_3310 *local; + f32 sp5C; + f32 sp58; + f32 sp4C[3]; + + local = (ActorLocal_CCW_3310 *)&this->local; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = true; + this->has_met_before = false; + this->position[0] = -4900.0f; + this->position[1] = 4619.0f; + this->position[2] = 0.0f; + D_8038FDE0[0] = this->position[0]; + D_8038FDE0[1] = this->position[1]; + D_8038FDE0[2] = this->position[2]; + if (this->state == 0) { + local->unk4 = 0U; + } + local->unk0 = &D_8038F080[0]; + while(local->unk0->map_id != 0 && gsworld_getMap() != local->unk0->map_id){ + local->unk0++; + } + + if ((local->unk0->unk2 != 0) && !fileProgressFlag_get(local->unk0->unk2)) { + marker_despawn(this->marker); + } else if (!fileProgressFlag_get(local->unk0->unk4)) { + func_803897B8(this, 1); + } else { + func_803897B8(this, 4); + } + + if (jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE) != 0) { + marker_despawn(this->marker); + } + return; + } + + if (local->unk8) { + skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); + for(iPtr = local->unk8; iPtr->unk0 > 0.0f; iPtr ++){ + if ((sp5C < iPtr->unk0) && (iPtr->unk0 <= sp58)) { + func_8030E878((s32) iPtr->unk4, randf2(iPtr->unk8 - 0.05, iPtr->unk8 + 0.05), iPtr->unkC, this->position, 500.0f, 2500.0f); + } + } + } + if (this->state == 1) { + player_getPosition(sp4C); + if( !this->has_met_before + && (local->unkC[2] >= 6500) + && (sp4C[2] < 6500.0f) + && (local->unk0->unk28 != 0) + ){ + this->has_met_before = true; + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, local->unk0->unk24); + func_80324DBC(0.0f, local->unk0->unk28, 6, NULL, this->marker, func_80389700, NULL); + } + local->unkC[0] = (s32) sp4C[0]; + local->unkC[1] = (s32) sp4C[1]; + local->unkC[2] = (s32) sp4C[2]; + if (item_getCount(ITEM_22_CATERPILLAR) == 0) { + func_8028F784(0); + } + if ((local->unk0->map_id != MAP_43_CCW_SPRING) && ((this->position[0] + 500.0f) < sp4C[0])) { + player_setCarryObjectPoseInCylinder(this->position, 1110.0f, 200.0f, ACTOR_2A2_CATERPILLAR, &this); + if ((local->unk0->unkE != 0) && (carriedObj_getActorId() == ACTOR_2A2_CATERPILLAR) && (ml_vec3f_distance(this->position, sp4C) < 1010.0f) && (player_throwCarriedObject() != 0)) { + player_setThrowTargetPosition(D_8038FDE0); + if ((local->unk0->map_id == MAP_44_CCW_SUMMER) && (local->unk4 == 0)) { + gcdialog_showDialog(0xCD8, 4, NULL, NULL, NULL, NULL); + } + local->unk4++; + if (local->unk4 < local->unk0->unk25) { + func_803897B8(this, 5); + } else { + func_803897B8(this, 2); + } + } + } + if (fileProgressFlag_get(local->unk0->unk4)) { + func_803897B8(this, local->unk0->unkC); + } + } + if ((this->state == 2) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { + func_803897B8(this, 3); + } + if ((this->state == 3) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { + func_803897B8(this, 4); + } + if ((this->state == 5) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { + func_803897B8(this, 1); + } +} diff --git a/src/CCW/ch/eyrie_egg.c b/src/CCW/ch/eyrie_egg.c new file mode 100644 index 000000000..615630179 --- /dev/null +++ b/src/CCW/ch/eyrie_egg.c @@ -0,0 +1,70 @@ +// BanjoDecomp: code_3050.c +#include +#include "functions.h" +#include "variables.h" + +Actor *CCW_func_8038954C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_803895F4(Actor *this); + +/* .data */ +ActorInfo D_8038EE70 = { 0x1B3, 0x2A0, 0x483, 0x0, NULL, func_803895F4, NULL, CCW_func_8038954C, 0, 0, 0.0f, 0}; + +/* .code */ +void func_80389440(Actor *this, s32 next_state) { + void *temp_v0; + + if (next_state == 2) { + sfxsource_play(SFX_AA_BGS_EGG_BREAKING_1, 28000); + this->marker->propPtr->unk8_3 = false; + fileProgressFlag_set(FILEPROG_E6_SPRING_EYRIE_HATCHED, true); + skeletalAnim_set(this->unk148, 0x187, 0.0f, 2.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 2); + timed_exitStaticCamera(8.0f); + func_80324E38(8.0f, 0); + } + this->state = next_state; +} + +void func_8038950C(ActorMarker* marker, ActorMarker* other_marker) { + Actor* actor = marker_getActor(marker); + if (actor->state == 1) { + func_80389440(actor, 2); + } +} + +Actor *CCW_func_8038954C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + + this = marker_getActor(marker); + if (this->state == 0) + return this; + + func_8033A45C(3, (this->state < 2) ? 1 : 0); + func_8033A45C(4, (this->state < 2) ? 0 : 1); + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_803895F4(Actor *this) { + f32 sp2C; + f32 sp28; + + if(!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = true; + marker_setCollisionScripts(this->marker, NULL, NULL, &func_8038950C); + func_80389440(this, 1); + if (fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED) || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) { + marker_despawn(this->marker); + } + return; + } + + if (this->state == 2) { + skeletalAnim_getProgressRange(this->unk148, &sp2C, &sp28); + if ((sp2C < 0.5) && (sp28 >= 0.5)) { + func_80326310(this); + } + } +} diff --git a/src/CCW/ch/eyrie_summer.c b/src/CCW/ch/eyrie_summer.c new file mode 100644 index 000000000..0ba4d601a --- /dev/null +++ b/src/CCW/ch/eyrie_summer.c @@ -0,0 +1,120 @@ +// BanjoDecomp: code_4530.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 unk0; + f32 unk4; + s16 unk8; + s16 unkA; +}Struct_CCW_4530_0; + +void func_8038A950(Actor *this, s32 next_state); +Actor *func_8038AA38(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_8038AA8C(Actor *this); + +/* .data */ +ActorInfo D_8038F190 = { + 0x1B6, 0x2A3, 0x487, + 0x0, NULL, + func_8038AA8C, NULL, func_8038AA38, + 0, 0, 0.0f, 0 +}; + +Struct_CCW_4530_0 D_8038F1B4[] = { + {0.15f, 0.9f, SFX_A5_EYRIE_CRY, 25000}, + {0.3f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, + {0.6f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, + {0.68f, 0.85f, SFX_2_CLAW_SWIPE, 23000}, + {0.75f, 0.9f, SFX_2_CLAW_SWIPE, 28000}, + {0.8f, 0.95f, SFX_2_CLAW_SWIPE, 30000}, + {0.81f, 1.0f, SFX_A5_EYRIE_CRY, 32000}, + {0.86f, 1.0f, SFX_2_CLAW_SWIPE, 31000}, + {0.93f, 1.0f, SFX_2_CLAW_SWIPE, 32000}, +0 +}; + +/* .code */ +void func_8038A920(ActorMarker* marker, enum asset_e text_id, s32 arg2) { + func_8038A950(marker_getActor(marker), 3); +} + +void func_8038A950(Actor *this, s32 next_state) { + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x199, 0.0f, 6.5f); + } + if (next_state == 2) { + gcdialog_showDialog(0xCDC, 0xA, this->position, this->marker, func_8038A920, NULL); + } + if (next_state == 3) { + skeletalAnim_set(this->unk148, 0x19A, 0.0f, 7.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 0); + } + if (next_state == 4) { + mapSpecificFlags_set(5, 1); + marker_despawn(this->marker); + } + this->state = next_state; +} + +Actor *func_8038AA38(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor *this; + + this = marker_getActor(marker); + if(this->state == 0) + return this; + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_8038AA8C(Actor *this) { + f32 sp54[3]; + f32 sp50; + f32 sp4C; + Struct_CCW_4530_0 *iPtr; + f32 sp44; + f32 sp40; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + mapSpecificFlags_set(5, false); + if( (!fileProgressFlag_get(FILEPROG_E8_AUTMN_EYRIE_FED) || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) + && !volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) + ) { + marker_despawn(this->marker); + } + else{ + func_8038A950(this, 1); + } + return; + } + + if (this->state == 1) { + skeletalAnim_getProgressRange(this->unk148, &sp50, &sp4C); + if ((sp50 < 0.21) && (0.21 <= sp4C)) { + func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); + } + + if ((sp50 < 0.56) && (0.56 <= sp4C)) { + func_8030E878(0xA5, randf2(0.9f, 1.1f), 32000, this->position, 500.0f, 2500.0f); + } + + player_getPosition(sp54); + if (ml_vec3f_distance(this->position, sp54) < 850.0f) { + func_8038A950(this, 2); + } + } + if (this->state == 3) { + skeletalAnim_getProgressRange(this->unk148, &sp44, &sp40); + for(iPtr = &D_8038F1B4[0]; iPtr->unk0 > 0.0f; iPtr++){ + if ((sp44 < iPtr->unk0) && (iPtr->unk0 <= sp40)) { + func_8030E878(iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 500.0f, 2500.0f); + } + } + if (skeletalAnim_getLoopCount(this->unk148) > 0) { + func_8038A950(this, 4); + } + } +} diff --git a/src/CCW/ch/eyrie_winter.c b/src/CCW/ch/eyrie_winter.c new file mode 100644 index 000000000..92b8bcbf4 --- /dev/null +++ b/src/CCW/ch/eyrie_winter.c @@ -0,0 +1,105 @@ +// BanjoDecomp: code_4960.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 unk0; + f32 unk4; + s16 unk8; + s16 unkA; +}Struct_CCW_4960_0; + +Actor *func_8038AE64(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_8038AEBC(Actor *this); + +/* .data */ +ActorInfo D_8038F230 = { + 0x1C4, 0x30E, 0x487, + 0x0, NULL, + func_8038AEBC, func_8038AEBC, func_8038AE64, + 0, 0, 0.0f, 0 +}; + +Struct_CCW_4960_0 D_8038F254[] = { + {0.5f, 0.8f, SFX_2_CLAW_SWIPE, 20000}, + 0 +}; + +/* .code */ +void func_8038AD50(Actor *this, s32 next_state) { + if (next_state == 2) { + gcdialog_showDialog(0xCDD, 0, NULL, NULL, NULL, NULL); + if (this->state == 1) { + mapSpecificFlags_set(6, 0); + timed_setStaticCameraToNode(0.0f, 1); + } + skeletalAnim_set(this->unk148, 0x21D, 0.2f, 0.5f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + if (next_state == 3) { + skeletalAnim_set(this->unk148, 0x21E, 0.2f, 2.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + } + if (next_state == 4) { + timed_exitStaticCamera(0.0f); + func_80324E38(0.0f, 0); + marker_despawn(this->marker); + } + this->state = next_state; +} + +Actor *func_8038AE64(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor *this; + + this = marker_getActor(marker); + if(this->state < 2) + return this; + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_8038AEBC(Actor *this) { + Struct_CCW_4960_0 *iPtr; + f32 sp38; + f32 sp34; + f32 sp30; + f32 sp2C; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + func_8038AD50(this, 1); + return; + } + if (this->state == 1){ + if(mapSpecificFlags_get(5)) { + mapSpecificFlags_set(5, false); + func_8038AD50(this, 2); + } + } + if (this->state == 2) { + actor_update_func_80326224(this); + skeletalAnim_getProgressRange(this->unk148, &sp38, &sp34); + for(iPtr = &D_8038F254[0]; iPtr->unk0 > 0.0f; iPtr++){ + if ((sp38 < iPtr->unk0) && (iPtr->unk0 <= sp34)) { + func_8030E878((s32) iPtr->unk8, iPtr->unk4, iPtr->unkA, this->position, 1500.0f, 4500.0f); + } + } + if (mapSpecificFlags_get(6)) { + mapSpecificFlags_set(6, false); + func_8038AD50(this, 3); + } + if (0.99 < this->unk48) { + func_8038AD50(this, 4); + } + } + if (this->state == 3) { + actor_update_func_80326224(this); + skeletalAnim_getProgressRange(this->unk148, &sp30, &sp2C); + if ((sp30 <= 0.5) && (sp2C >= 0.5)) { + jiggy_spawn(JIGGY_49_CCW_EYRIE, this->position); + } + if (skeletalAnim_getLoopCount(this->unk148) > 0) { + func_8038AD50(this, 2); + } + } +} diff --git a/src/CCW/ch/eyrieegg.c b/src/CCW/ch/eyrieegg.c deleted file mode 100644 index 416e03837..000000000 --- a/src/CCW/ch/eyrieegg.c +++ /dev/null @@ -1,94 +0,0 @@ -// BanjoDecomp: CCW/ch/eyrieegg.c -#include -#include "functions.h" -#include "variables.h" - -Actor *chEyrieEgg_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chEyrieEgg_update(Actor *this); - -/* .data */ -ActorInfo chEyrieEgg = { - MARKER_1B3_EAGLE_EGG, ACTOR_2A0_EAGLE_EGG, ASSET_483_MODEL_EAGLE_EGG, - 0x0, NULL, - chEyrieEgg_update, NULL, chEyrieEgg_draw, - 0, 0, 0.0f, 0 -}; - -enum chEyrieEgg_State_e { - CH_EYRIE_EGG_STATE_0_NOT_INIT, - CH_EYRIE_EGG_STATE_1_IDLE, - CH_EYRIE_EGG_STATE_2_BREAKING -}; - -// Anchor: set while replaying a teammate's hatch; skips the camera pan. -static s32 sChEyrieEggRemote = 0; - -/* .code */ -void chEyrieEgg_setNextState(Actor *this, s32 next_state) { - void *temp_v0; - - if (next_state == CH_EYRIE_EGG_STATE_2_BREAKING) { - sfxsource_play(SFX_AA_BGS_EGG_BREAKING_1, 28000); - this->marker->propPtr->unk8_3 = false; - fileProgressFlag_set(FILEPROG_E6_SPRING_EYRIE_HATCHED, true); - skeletalAnim_set(this->unk148, 0x187, 0.0f, 2.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if (!sChEyrieEggRemote) { - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 2); - timed_exitStaticCamera(8.0f); - func_80324E38(8.0f, 0); - } - } - this->state = next_state; -} - -void chEyrieEgg_die(ActorMarker* marker, ActorMarker* other_marker) { - Actor* actor = marker_getActor(marker); - if (actor->state == CH_EYRIE_EGG_STATE_1_IDLE) { - chEyrieEgg_setNextState(actor, CH_EYRIE_EGG_STATE_2_BREAKING); - } -} - -Actor *chEyrieEgg_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - - this = marker_getActor(marker); - if (this->state == CH_EYRIE_EGG_STATE_0_NOT_INIT) - return this; - - modelRender_setAppendageVisibility(3, (this->state < CH_EYRIE_EGG_STATE_2_BREAKING) ? 1 : 0); - modelRender_setAppendageVisibility(4, (this->state < CH_EYRIE_EGG_STATE_2_BREAKING) ? 0 : 1); - return actor_draw(marker, gfx, mtx, vtx); -} - -void chEyrieEgg_update(Actor *this) { - f32 sp2C; - f32 sp28; - - if(!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = true; - marker_setCollisionScripts(this->marker, NULL, NULL, &chEyrieEgg_die); - chEyrieEgg_setNextState(this, CH_EYRIE_EGG_STATE_1_IDLE); - if (fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED) - || jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE)) - { - marker_despawn(this->marker); - } - return; - } - - if (this->state == CH_EYRIE_EGG_STATE_1_IDLE && fileProgressFlag_get(FILEPROG_E6_SPRING_EYRIE_HATCHED)) { - sChEyrieEggRemote = 1; - chEyrieEgg_setNextState(this, CH_EYRIE_EGG_STATE_2_BREAKING); - sChEyrieEggRemote = 0; - } - - if (this->state == CH_EYRIE_EGG_STATE_2_BREAKING) { - skeletalAnim_getProgressRange(this->unk148, &sp2C, &sp28); - if ((sp2C < 0.5) && (sp28 >= 0.5)) { - func_80326310(this); - } - } -} diff --git a/src/CCW/ch/fairy.c b/src/CCW/ch/fairy.c new file mode 100644 index 000000000..9c44ac9d0 --- /dev/null +++ b/src/CCW/ch/fairy.c @@ -0,0 +1,129 @@ +// BanjoDecomp: code_6620.c +#include +#include "functions.h" +#include "variables.h" + +extern ParticleEmitter *func_802EDD8C(f32[3], f32, f32); + +typedef struct{ + s16 map_id; + s16 unk2; + s16 unk4; +}Struct_CCW_6620_0; + +typedef struct{ + Struct_CCW_6620_0 *unk0; + f32 unk4[3]; +}ActorLocal_CCW_6620; + +Actor *CCW_func_8038CBF0(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_8038CC4C(Actor *this); + +/* .data */ +Struct_CCW_6620_0 D_8038F490[] ={ + {0x43, 0, 0xCCE}, + {0x45, 1, 0xCD1}, + {0x46, 1, 0xCD3}, + 0 +}; + +ActorInfo D_8038F4A8 = { + 0x1BD, 0x2AA, 0x48F, + 0x0, NULL, + func_8038CC4C, NULL, CCW_func_8038CBF0, + 0, 0, 2.2f, 0 +}; + +/* .code */ +void func_8038CA10(ActorMarker *marker) { + Actor *this; + ActorLocal_CCW_6620 *local; + ParticleEmitter *pCtrl; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_6620 *)&this->local; + + if (this->marker->unk14_21) { + if (0.65 < (f64) randf()) { + pCtrl = func_802EDD8C(local->unk4, 0.0f, this->position[1] + 500.0f); + particleEmitter_setStartingScaleRange(pCtrl, 0.04f, 0.05f); + particleEmitter_setFinalScaleRange(pCtrl, 0.18f, 0.2f); + particleEmitter_setSpawnPositionRange(pCtrl, -10.0f, 0.0f, -10.0f, 10.0f, 20.0f, 10.0f); + particleEmitter_setParticleVelocityRange(pCtrl, 0.0f, 31.0f, 0.0f, 0.0f, 37.0f, 0.0f); + particleEmitter_emitN(pCtrl, 1); + } + } +} + +void func_8038CB40(Actor *this, s32 next_state) { + int i; + + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x289, 0.2f, 1.1f); + for(i = 0; i < 10; i++){ + skeletalAnim_setCallback_1(this->unk148, randf(), (GenFunction_1)func_8038CA10, (uintptr_t)this->marker); + } + } + this->state = next_state; +} + + +Actor *CCW_func_8038CBF0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + ActorLocal_CCW_6620 *local; + + this = actor_draw(marker, gfx, mtx, vtx); + local = (ActorLocal_CCW_6620 *)&this->local; + if (this->marker->unk14_21) { + vec3fArray_get_vec3f(func_80329934(), 5, local->unk4); + } + return this; +} + +void func_8038CC4C(Actor *this) { + ActorLocal_CCW_6620 *local; + f32 sp50[3]; + f32 sp4C; + f32 sp48; + f32 sp44; + f32 sp38[3]; + + local = (ActorLocal_CCW_6620 *)&this->local; + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + local->unk0 = &D_8038F490[0]; + while(local->unk0->map_id != 0 && gsworld_getMap() != local->unk0->map_id){ + local->unk0++; + } + func_8038CB40(this, 1); + + if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); + } + + if ((local->unk0->unk2 != 0) && levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN)) { + marker_despawn(this->marker); + } + + return; + } + + if (this->state == 1 && this->marker->unk14_21) { + player_getPosition(sp50); + func_80258A4C(this->position, this->yaw - 90.0f, sp50, &sp4C, &sp48, &sp44); + if (sp4C > 100.0f) { + this->yaw += 30.0f * sp44; + } + } + if (!this->has_met_before) { + player_getPosition(sp38); + if (ml_vec3f_distance(this->position, sp38) < 900.0f) { + if (local->unk0->map_id != MAP_46_CCW_WINTER || func_8028F2FC()) { + gcdialog_showDialog(local->unk0->unk4, 4, NULL, NULL, NULL, NULL); + this->has_met_before = true; + } + } + } +} diff --git a/src/CCW/ch/gnawty.c b/src/CCW/ch/gnawty.c new file mode 100644 index 000000000..9095dce6e --- /dev/null +++ b/src/CCW/ch/gnawty.c @@ -0,0 +1,143 @@ +// BanjoDecomp: code_6AC0.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + f32 unk0; + f32 unk4; + s16 unk8; + s16 unkA; +}Struct_CCW_6AC0_0; + +void func_8038CFB4(Actor *this); + +/* .data */ +ActorInfo D_8038F4D0 = { + 0x1BE, 0x2AB, 0x48F, + 0x0, NULL, + func_8038CFB4, func_8038CFB4, actor_draw, + 0, 0, 2.2f, 0 +}; + +Struct_CCW_6AC0_0 D_8038F4F4[] = { + {0.11f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.23f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.34f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.58f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, + {0.8f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, + 0 +}; + +Struct_CCW_6AC0_0 D_8038F53C[] = { + {0.07f, 1.6f, SFX_56_BANJO_HUI, 32000}, + {0.17f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.22f, 1.6f, SFX_55_BANJO_HOO_2, 32000}, + {0.31f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.33f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, + {0.45f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.49f, 1.7f, SFX_55_BANJO_HOO_2, 32600}, + {0.6f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.63f, 1.7f, SFX_56_BANJO_HUI, 32600}, + {0.74f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.79f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, + {0.9f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + 0 +}; + +Struct_CCW_6AC0_0 D_8038F5D8[] = { + {0.01f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + {0.5f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, + 0 +}; + +/* .code */ +void func_8038CEB0(Actor *this, s32 next_state) { + ActorProp *temp_v0; + + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x1A6, 0.2f, 4.5f); + } + if (next_state == 2) { + this->marker->propPtr->unk8_3 = false; + skeletalAnim_set(this->unk148, 0x1A7, 0.2f, 3.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + gcdialog_showDialog(0xCD0, 0x24, NULL, NULL, NULL, NULL); + } + if (next_state == 3) { + skeletalAnim_set(this->unk148, 0x1A8, 0.2f, 0.5f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + if (next_state == 4) { + marker_despawn(this->marker); + } + this->state = next_state; +} + +void func_8038CFB4(Actor *this) { + Struct_CCW_6AC0_0 *phi_s0; + f32 sp70; + f32 sp6C; + f32 sp60[3]; + + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + func_8038CEB0(this, 1); + if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY) != 0) { + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); + } + if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) != false) { + marker_despawn(this->marker); + } + return; + } + + if (this->state == 1) { + phi_s0 = D_8038F4F4; + } else if (this->state == 2) { + phi_s0 = D_8038F53C; + } else if (this->state == 3) { + phi_s0 = D_8038F5D8; + } else{ + phi_s0 = NULL; + } + + if (phi_s0 != NULL) { + skeletalAnim_getProgressRange(this->unk148, &sp70, &sp6C); + while(phi_s0->unk0 > 0.0f){ + if (((sp70 < phi_s0->unk0) || (sp6C < sp70)) && (phi_s0->unk0 <= sp6C)) { + func_8030E878(phi_s0->unk8, randf2(phi_s0->unk4 - 0.05, phi_s0->unk4 + 0.05), randi2(phi_s0->unkA - 200, phi_s0->unkA + 100), this->position, 500.0f, 1500.0f); + } + phi_s0++; + } + } + + if (this->state == 1) { + if (!this->has_met_before) { + player_getPosition(sp60); + if (ml_vec3f_distance(this->position, sp60) < 900.0f) { + gcdialog_showDialog(0xCCF, 4, NULL, NULL, NULL, NULL); + this->has_met_before = true; + } + } + + if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) != false) { + func_8038CEB0(this, 2); + } + } + + if (this->state == 2){ + if((skeletalAnim_getLoopCount(this->unk148) > 0)) { + func_8038CEB0(this, 3); + } + } + + if (this->state == 3) { + actor_update_func_80326224(this); + if (0.99 < (f64) this->unk48) { + func_8038CEB0(this, 4); + } + } +} diff --git a/src/CCW/ch/gnawtyboulder.c b/src/CCW/ch/gnawtyboulder.c index 03a991b11..344e657b9 100644 --- a/src/CCW/ch/gnawtyboulder.c +++ b/src/CCW/ch/gnawtyboulder.c @@ -4,20 +4,12 @@ #include "variables.h" typedef struct { - f32 unk0; // time related + f32 unk0; } ActorLocal_CCW_7120; void chGnawtyBoulder_update(Actor *this); /* .data */ - -enum chGnawtyBoulder_state_e { - GNAWTY_BOULDER_STATE_0_NOT_INIT, - GNAWTY_BOULDER_STATE_1_IDLE, - GNAWTY_BOULDER_STATE_2_BREAK, - GNAWTY_BOULDER_STATE_3_DESPAWN -}; - ActorInfo chGnawtyBoulder = { 0x1BF, 0x2AC, 0x490, 0x0, NULL, @@ -26,7 +18,7 @@ ActorInfo chGnawtyBoulder = { }; /* .code */ -void chGnawtyBoulder_emitSmoke(Actor *this) { +void CCW_func_8038D510(Actor *this) { static s32 D_8038F664[3] = {0xDE, 0xA7, 0x71}; static ParticleSettingsVelocityPosition D_8038F670 = { {{ 0.0f, 50.0f, 0.0f}, { 70.0f, 100.0f, 70.0f}}, @@ -47,7 +39,7 @@ void chGnawtyBoulder_emitSmoke(Actor *this) { particleEmitter_emitN(pCtrl, 6); } -void chGnawtyBoulder_emitRock(Actor *this) { +void func_8038D5DC(Actor *this) { static ParticleSettingsVelocityAccelerationPosition D_8038F6A0 ={ {{-100.0f, -50.0f, -100.0f}, {100.0f, 50.0f, 100.0f}}, {{ 0.0f, -800.0f, 0.0f}, { 0.0f, -800.0f, 0.0f}}, @@ -59,7 +51,7 @@ void chGnawtyBoulder_emitRock(Actor *this) { pCtrl = partEmitMgr_newEmitter(30); particleEmitter_func_802EF9F8(pCtrl, 0.6f); particleEmitter_func_802EFA18(pCtrl, 3); - particleEmitter_setModel(pCtrl, ASSET_896_MODEL_GOLD_ROCK); + particleEmitter_setModel(pCtrl, 0x896); particleEmitter_setPosition(pCtrl, this->position); particleEmitter_setStartingScaleRange(pCtrl, 0.05f, 0.3f); particleEmitter_setAngularVelocityRange(pCtrl, @@ -76,35 +68,35 @@ void chGnawtyBoulder_setNextState(Actor *this, s32 next_state) { ActorLocal_CCW_7120 *local = (ActorLocal_CCW_7120 *)&this->local; local->unk0 = 0.0f; - if (next_state == GNAWTY_BOULDER_STATE_2_BREAK) { + if (next_state == 2) { this->marker->propPtr->unk8_3 = false; func_802BB3DC(0, 60.0f, 0.7f); - chGnawtyBoulder_emitSmoke(this); - chGnawtyBoulder_emitRock(this); + CCW_func_8038D510(this); + func_8038D5DC(this); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.3f, 15000); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.5f, 15000); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.7f, 15000); FUNC_8030E624(SFX_9B_BOULDER_BREAKING_1, 0.9f, 15000); func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.5f, 3); - timedFunc_set_2(0.5f, (GenFunction_2)levelSpecificFlags_set, LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); + timedFunc_set_2(0.5f, (GenFunction_2)levelSpecificFlags_set, LEVEL_FLAG_25_CCW_UNKNOWN, true); timed_exitStaticCamera(4.0f); func_80324E38(4.0f, 0); local->unk0 = 0.5f; marker_despawn(this->marker); } - if (next_state == GNAWTY_BOULDER_STATE_3_DESPAWN) { + if (next_state == 3) { marker_despawn(this->marker); } this->state = next_state; } -void chGnawtyBoulder_die(ActorMarker* marker, ActorMarker *other_marker) { +void func_8038D81C(ActorMarker* marker, ActorMarker *other_marker) { Actor* actor = marker_getActor(marker); - if (actor->state == GNAWTY_BOULDER_STATE_1_IDLE) { + if (actor->state == 1) { // [port] v1.1 fix: rock is indestructible in Spring (prevents sequence break) if (EventSystem_Should(VB_CCW_GNAWTY_SPRING_ROCK, gsworld_getMap() != MAP_43_CCW_SPRING)) { - chGnawtyBoulder_setNextState(actor, GNAWTY_BOULDER_STATE_2_BREAK); + chGnawtyBoulder_setNextState(actor, 2); } } } @@ -117,30 +109,21 @@ void chGnawtyBoulder_update(Actor *this) { if (!this->volatile_initialized) { this->marker->propPtr->unk8_3 = true; this->volatile_initialized = true; - marker_setCollisionScripts(this->marker, NULL, &chGnawtyBoulder_die, NULL); - chGnawtyBoulder_setNextState(this, GNAWTY_BOULDER_STATE_1_IDLE); + marker_setCollisionScripts(this->marker, NULL, &func_8038D81C, NULL); + chGnawtyBoulder_setNextState(this, 1); if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY) != false) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); } - if ((levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) != false) - && (gsworld_getMap() != MAP_43_CCW_SPRING)) - { + if ((levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) != false) && (gsworld_getMap() != MAP_43_CCW_SPRING)) { marker_despawn(this->marker); } return; - } - // Anchor: teammate broke the boulder — despawn live (no break cutscene). - if (this->state == GNAWTY_BOULDER_STATE_1_IDLE - && levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) - && gsworld_getMap() != MAP_43_CCW_SPRING) { - marker_despawn(this->marker); - return; - } - if(this->state == GNAWTY_BOULDER_STATE_2_BREAK){ + } + if(this->state == 2){ if (ml_timer_update(&local->unk0, tick) ) { - chGnawtyBoulder_setNextState(this, GNAWTY_BOULDER_STATE_3_DESPAWN); + chGnawtyBoulder_setNextState(this, 3); } } } diff --git a/src/CCW/ch/ccwgobi.c b/src/CCW/ch/gobi_ccw.c similarity index 55% rename from src/CCW/ch/ccwgobi.c rename to src/CCW/ch/gobi_ccw.c index 3b1525d25..4080d3459 100644 --- a/src/CCW/ch/ccwgobi.c +++ b/src/CCW/ch/gobi_ccw.c @@ -1,110 +1,89 @@ -// BanjoDecomp: CCW/ch/ccwgobi.c +// BanjoDecomp: code_2270.c #include #include "functions.h" #include "variables.h" typedef struct{ s16 map_id; - s16 summerMeetDialog; - s16 summerCompleteDialog; - s16 autumnCompleteDialog; -} CH_CCW_Gobi_Dialogs; + s16 unk2; + s16 unk4; + s16 unk6; +}Struct_CCW_2270_0; typedef struct{ - CH_CCW_Gobi_Dialogs *dialogs; - SkeletalAnimation *skeletal_anim; + Struct_CCW_2270_0 *unk0; + SkeletalAnimation *unk4; BKModelBin *spit_model; -} ActorLocal_chGobiCCW; +}ActorLocal_chGobiCCW; -void chCCWGobi_setState(Actor *this, s32 next_state); +void CCW_func_8038868C(Actor *this, s32 next_state); Actor *chGobiCCW_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chGobiCCW_update(Actor *this); /* .data */ -CH_CCW_Gobi_Dialogs chCCWGobiDialogs[] = { - { - MAP_44_CCW_SUMMER, - VER_SELECT(ASSET_CDE_DIALOG_CCW_GOBI_MEET_SUMMER, 0x09F3, 0, 0), - VER_SELECT(ASSET_CDF_DIALOG_CCW_GOBI_COMPLETE_SUMMER, 0x09F4, 0, 0), - 0 // [port] decomp uses NULL; dialog fields are asset ids, not pointers - }, - { - MAP_45_CCW_AUTUMN, - 0, - 0, - VER_SELECT(ASSET_CE0_DIALOG_CCW_GOBI_COMPLETE_FALL, 0x09F5, 0, 0) - }, - { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion +Struct_CCW_2270_0 D_8038ECD0[] = { + {MAP_44_CCW_SUMMER, 0xCDE, 0xCDF, 0x000}, + {MAP_45_CCW_AUTUMN, 0x000, 0x000, 0xCE0}, + 0 }; -ActorInfo chCCWGobi = { +ActorInfo D_8038ECE8 = { MARKER_1B1_CCW_GOBI, ACTOR_29E_CCW_GOBI, ASSET_3E0_MODEL_GOBI, 0x0, NULL, chGobiCCW_update, chGobiCCW_update, chGobiCCW_draw, 0, 0, 1.0f, 0 }; -enum chccwgobi_state_e { - CH_CCW_GOBI_STATE_0_NOT_INIT, - CH_CCW_GOBI_STATE_1_WAITING, - CH_CCW_GOBI_STATE_2_SPITTING, - CH_CCW_GOBI_STATE_3_GROW_BEANSTALK, - CH_CCW_GOBI_STATE_4_DONE_SPITTING, - CH_CCW_GOBI_STATE_5_GETTING_UP, - CH_CCW_GOBI_STATE_6_RUN_AWAY, - CH_CCW_GOBI_STATE_7_DESPAWN -}; - /* .code */ -void chCCWGobi_setStateByMarker(ActorMarker* marker, s32 arg1) { - chCCWGobi_setState(marker_getActor(marker), arg1); +void CCW_func_80388660(ActorMarker* marker, s32 arg1) { + CCW_func_8038868C(marker_getActor(marker), arg1); } -void chCCWGobi_setState(Actor *this, s32 next_state) { +void CCW_func_8038868C(Actor *this, s32 next_state) { ActorLocal_chGobiCCW *local; local = (ActorLocal_chGobiCCW*)&this->local; - if (next_state == CH_CCW_GOBI_STATE_1_WAITING) { + if (next_state == 1) { skeletalAnim_set(this->unk148, ASSET_F4_ANIM_GOBI_IDLE, 0.5f, 12.0f); } - if (next_state == CH_CCW_GOBI_STATE_2_SPITTING) { - if (local->dialogs->summerCompleteDialog != 0) { - gcdialog_showDialog(local->dialogs->summerCompleteDialog, 4, NULL, NULL, NULL, NULL); + if (next_state == 2) { + if (local->unk0->unk4 != 0) { + gcdialog_showDialog(local->unk0->unk4, 4, NULL, NULL, NULL, NULL); } skeletalAnim_set(this->unk148, ASSET_FC_ANIM_GOBI_SPITTING, 0.2f, 3.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - skeletalAnim_set(local->skeletal_anim, ASSET_100_ANIM_GOBI_SPIT, 0.0f, 3.0f); - skeletalAnim_setBehavior(local->skeletal_anim, 2); + skeletalAnim_set(local->unk4, ASSET_100_ANIM_GOBI_SPIT, 0.0f, 3.0f); + skeletalAnim_setBehavior(local->unk4, 2); func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.0f, (gsworld_getMap() == MAP_44_CCW_SUMMER) ? 1 : 2); timed_playSfx(0.05f, SFX_84_GOBI_CRYING, 1.1f, 32000); timed_playSfx(0.8f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(1.4f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(2.0f, SFX_4B_GULPING, 0.8f, 28000); - timedFunc_set_2(3.2f, (GenFunction_2) chCCWGobi_setStateByMarker, (uintptr_t)this->marker, 3); + timedFunc_set_2(3.2f, (GenFunction_2) CCW_func_80388660, (uintptr_t)this->marker, 3); } - if (next_state == CH_CCW_GOBI_STATE_3_GROW_BEANSTALK) { - chCCWBeanstalk_growBeanstalk(); + if (next_state == 3) { + func_803883F4(); } - if (next_state == CH_CCW_GOBI_STATE_4_DONE_SPITTING) { + if (next_state == 4) { skeletalAnim_set(this->unk148, ASSET_176_ANIM_GOBI_YAWN, 0.5f, 4.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); } - if (next_state == CH_CCW_GOBI_STATE_5_GETTING_UP) { - if (local->dialogs->autumnCompleteDialog != NULL) { - gcdialog_showDialog((s32) local->dialogs->autumnCompleteDialog, 4, NULL, NULL, NULL, NULL); + if (next_state == 5) { + if (local->unk0->unk6 != 0) { + gcdialog_showDialog((s32) local->unk0->unk6, 4, NULL, NULL, NULL, NULL); } skeletalAnim_set(this->unk148, ASSET_FD_ANIM_GOBI2_GETTING_UP, 0.23f, 0.5f); timed_setStaticCameraToNode(0.0f, 3); } - if (next_state == CH_CCW_GOBI_STATE_6_RUN_AWAY) { + if (next_state == 6) { skeletalAnim_set(this->unk148, ASSET_F8_ANIM_GOBI_RUNNING, 0.1f, 0.71f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); } - if (next_state == CH_CCW_GOBI_STATE_7_DESPAWN) { + if (next_state == 7) { timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); marker_despawn(this->marker); @@ -115,9 +94,9 @@ void chCCWGobi_setState(Actor *this, s32 next_state) { void func_8038894C(ActorMarker* marker, ActorMarker *other_marker) { Actor* actor = marker_getActor(marker); - if (actor->state == CH_CCW_GOBI_STATE_1_WAITING) { + if (actor->state == 1) { actor_collisionOff(actor); - timedFunc_set_2(0.5f, (GenFunction_2)chCCWGobi_setStateByMarker, (uintptr_t)actor->marker, 2); + timedFunc_set_2(0.5f, (GenFunction_2)CCW_func_80388660, (uintptr_t)actor->marker, 2); } } @@ -134,7 +113,7 @@ Actor *chGobiCCW_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ sp2C[1] = this->yaw; sp2C[2] = this->roll; - modelRender_setBoneTransformList(skeletalAnim_getBoneTransformList(local->skeletal_anim)); + modelRender_setBoneTransformList(skeletalAnim_getBoneTransformList(local->unk4)); modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); modelRender_draw(gfx, mtx, this->position, sp2C, 1.0f, NULL, local->spit_model); } @@ -144,13 +123,13 @@ Actor *chGobiCCW_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ void chGobiCCW_free(Actor *this){ ActorLocal_chGobiCCW *local = (ActorLocal_chGobiCCW*)&this->local; - skeletalAnim_free(local->skeletal_anim); + skeletalAnim_free(local->unk4); assetcache_release(local->spit_model); } void chGobiCCW_update(Actor *this) { ActorLocal_chGobiCCW *local; - f32 player_position[3]; + f32 sp48[3]; f32 sp44; f32 sp40; @@ -160,56 +139,54 @@ void chGobiCCW_update(Actor *this) { this->marker->propPtr->unk8_3 = true; this->marker->actorFreeFunc = chGobiCCW_free; this->has_met_before = false; - local->skeletal_anim = skeletalAnim_new(); + local->unk4 = skeletalAnim_new(); local->spit_model = assetcache_get(ASSET_3F3_MODEL_GOBI_SPIT); marker_setCollisionScripts(this->marker, NULL, func_8038894C, NULL); if(!jiggyscore_isSpawned(JIGGY_4D_CCW_FLOWER)) { fileProgressFlag_set(FILEPROG_E5_CCW_FLOWER_AUTUMN, false); } - local->dialogs = &chCCWGobiDialogs[0]; - while((local->dialogs->map_id != NULL) && (gsworld_getMap() != local->dialogs->map_id)) { - local->dialogs++; + local->unk0 = &D_8038ECD0[0]; + while((local->unk0->map_id != 0) && (gsworld_getMap() != local->unk0->map_id)) { + local->unk0++; } if( (gsworld_getMap() == MAP_44_CCW_SUMMER) && fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING) && !fileProgressFlag_get(FILEPROG_E4_CCW_FLOWER_SUMMER)) { - chCCWGobi_setState(this, CH_CCW_GOBI_STATE_1_WAITING); + CCW_func_8038868C(this, 1); } else if( (gsworld_getMap() == MAP_45_CCW_AUTUMN) && fileProgressFlag_get(FILEPROG_E4_CCW_FLOWER_SUMMER) && !fileProgressFlag_get(FILEPROG_E5_CCW_FLOWER_AUTUMN) ) { - chCCWGobi_setState(this, CH_CCW_GOBI_STATE_1_WAITING); + CCW_func_8038868C(this, 1); } else{ marker_despawn(this->marker); } return; } - if(this->state == CH_CCW_GOBI_STATE_1_WAITING){ + if(this->state == 1){ if (!this->has_met_before) { - player_getPosition(player_position); - if (ml_vec3f_distance(this->position, player_position) < 600.0f) { - if (local->dialogs->summerMeetDialog != NULL) { - gcdialog_showDialog((s32) local->dialogs->summerMeetDialog, 4, NULL, NULL, NULL, NULL); + player_getPosition(sp48); + if (ml_vec3f_distance(this->position, sp48) < 600.0f) { + if (local->unk0->unk2 != 0) { + gcdialog_showDialog((s32) local->unk0->unk2, 4, NULL, NULL, NULL, NULL); } this->has_met_before = true; } } } - if (this->state == CH_CCW_GOBI_STATE_2_SPITTING) { - skeletalAnim_update(local->skeletal_anim, time_getDelta(), 1); + if (this->state == 2) { + skeletalAnim_update(local->unk4, time_getDelta(), 1); } - if(this->state == CH_CCW_GOBI_STATE_3_GROW_BEANSTALK){ - if (!chCCWBeanstalk_hasSpawned()) { + if(this->state == 3){ + if (!func_80388438()) { if (gsworld_getMap() == MAP_44_CCW_SUMMER) { - chCCWGobi_setState(this, CH_CCW_GOBI_STATE_4_DONE_SPITTING); + CCW_func_8038868C(this, 4); } else { - chCCWGobi_setState(this, CH_CCW_GOBI_STATE_5_GETTING_UP); + CCW_func_8038868C(this, 5); } } } - if (this->state == CH_CCW_GOBI_STATE_4_DONE_SPITTING) { - if ((skeletalAnim_getAnimId(this->unk148) == ASSET_176_ANIM_GOBI_YAWN) - && (skeletalAnim_getLoopCount(this->unk148) > 0)) - { + if (this->state == 4) { + if ((skeletalAnim_getAnimId(this->unk148) == ASSET_176_ANIM_GOBI_YAWN) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { skeletalAnim_set(this->unk148, ASSET_177_ANIM_GOBI_SLEEP, 0.1f, 4.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); } @@ -225,16 +202,16 @@ void chGobiCCW_update(Actor *this) { } } - if (this->state == CH_CCW_GOBI_STATE_5_GETTING_UP){ + if (this->state == 5){ if(skeletalAnim_getLoopCount(this->unk148) > 0) { - chCCWGobi_setState(this, CH_CCW_GOBI_STATE_6_RUN_AWAY); + CCW_func_8038868C(this, 6); } } - if (this->state == CH_CCW_GOBI_STATE_6_RUN_AWAY) { + if (this->state == 6) { actor_update_func_80326224(this); if (0.99 < (f64) this->unk48) { - chCCWGobi_setState(this, CH_CCW_GOBI_STATE_7_DESPAWN); + CCW_func_8038868C(this, 7); } } } diff --git a/src/CCW/ch/grublinhood.c b/src/CCW/ch/grublinhood.c index 0e1ffac87..2e99ab8aa 100644 --- a/src/CCW/ch/grublinhood.c +++ b/src/CCW/ch/grublinhood.c @@ -7,9 +7,17 @@ extern void func_802DABA0(ParticleEmitter *, f32[3], f32, enum asset_e); -extern void modelRender_setAppendageVisibility(s32, s32); +extern void func_8033A45C(s32, s32); extern void humanoidBaddie_ow(ActorMarker *, ActorMarker *); +enum ccw_season_e +{ + SPRING, + SUMMER, + AUTUMN, + WINTER +}; + void chgrublinhood_update(Actor *this); Actor *chgrublinhood_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); @@ -72,18 +80,18 @@ Actor *chgrublinhood_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ this = marker_getActor(marker); local = (Humanoid_Baddies_Actor *)&this->local; - modelRender_setAppendageVisibility(3, (local->baddieSpecific == CCW_SEASON_1_SUMMER) ? 1 : 2); - modelRender_setAppendageVisibility(4, (local->baddieSpecific == CCW_SEASON_1_SUMMER) ? 1 : 2); - modelRender_setAppendageVisibility(5, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); - modelRender_setAppendageVisibility(6, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); - modelRender_setAppendageVisibility(7, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); - modelRender_setAppendageVisibility(8, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 1 : 2); - modelRender_setAppendageVisibility(9, (local->baddieSpecific == CCW_SEASON_1_SUMMER) ? 1 : 0); - modelRender_setAppendageVisibility(10, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 0 : (local->baddieSpecific == CCW_SEASON_2_AUTUMN) ? 1 : 2); - modelRender_setAppendageVisibility(11, (local->baddieSpecific < CCW_SEASON_2_AUTUMN) ? 0 : (local->baddieSpecific == CCW_SEASON_2_AUTUMN) ? 1 : 2); - modelRender_setAppendageVisibility(12, (local->baddieSpecific == CCW_SEASON_3_WINTER) ? 2 : 1); - modelRender_setAppendageVisibility(13, (local->baddieSpecific == CCW_SEASON_3_WINTER) ? 1 : 0); - modelRender_setAppendageVisibility(14, (this->has_met_before)? false : true); + func_8033A45C(3, (local->baddieSpecific == SUMMER) ? 1 : 2); + func_8033A45C(4, (local->baddieSpecific == SUMMER) ? 1 : 2); + func_8033A45C(5, (local->baddieSpecific < AUTUMN) ? 1 : 2); + func_8033A45C(6, (local->baddieSpecific < AUTUMN) ? 1 : 2); + func_8033A45C(7, (local->baddieSpecific < AUTUMN) ? 1 : 2); + func_8033A45C(8, (local->baddieSpecific < AUTUMN) ? 1 : 2); + func_8033A45C(9, (local->baddieSpecific == SUMMER) ? 1 : 0); + func_8033A45C(10, (local->baddieSpecific < AUTUMN) ? 0 : (local->baddieSpecific == AUTUMN) ? 1 : 2); + func_8033A45C(11, (local->baddieSpecific < AUTUMN) ? 0 : (local->baddieSpecific == AUTUMN) ? 1 : 2); + func_8033A45C(12, (local->baddieSpecific == WINTER) ? 2 : 1); + func_8033A45C(13, (local->baddieSpecific == WINTER) ? 1 : 0); + func_8033A45C(14, (this->has_met_before)? false : true); return actor_draw(marker, gfx, mtx, vtx); } @@ -113,14 +121,14 @@ enum ccw_season_e __get_current_season(Actor *this){ case MAP_5B_CCW_SPRING_ZUBBA_HIVE:// 8038E930 case MAP_5E_CCW_SPRING_NABNUTS_HOUSE:// 8038E930 case MAP_65_CCW_SPRING_WHIPCRACK_ROOM:// 8038E930 - return CCW_SEASON_0_SPRING; + return SPRING; case MAP_44_CCW_SUMMER:// 8038E938 case MAP_4B_CCW_SUMMER_MUMBOS_SKULL:// 8038E938 case MAP_5A_CCW_SUMMER_ZUBBA_HIVE:// 8038E938 case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE:// 8038E938 case MAP_66_CCW_SUMMER_WHIPCRACK_ROOM:// 8038E938 - return CCW_SEASON_1_SUMMER; + return SUMMER; case MAP_45_CCW_AUTUMN:// 8038E940 case MAP_4C_CCW_AUTUMN_MUMBOS_SKULL:// 8038E940 @@ -128,7 +136,7 @@ enum ccw_season_e __get_current_season(Actor *this){ case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE:// 8038E940 case MAP_63_CCW_AUTUMN_NABNUTS_WATER_SUPPLY:// 8038E940 case MAP_67_CCW_AUTUMN_WHIPCRACK_ROOM:// 8038E940 - return CCW_SEASON_2_AUTUMN; + return AUTUMN; case MAP_46_CCW_WINTER:// 8038E948 case MAP_4D_CCW_WINTER_MUMBOS_SKULL:// 8038E948 @@ -136,10 +144,11 @@ enum ccw_season_e __get_current_season(Actor *this){ case MAP_62_CCW_WINTER_HONEYCOMB_ROOM:// 8038E948 case MAP_64_CCW_WINTER_NABNUTS_WATER_SUPPLY:// 8038E948 case MAP_68_CCW_WINTER_WHIPCRACK_ROOM:// 8038E948 - return CCW_SEASON_3_WINTER; + return WINTER; default: - return CCW_SEASON_0_SPRING; + return SPRING; + } } diff --git a/src/CCW/ch/indoorsgnawty.c b/src/CCW/ch/indoorsgnawty.c deleted file mode 100644 index 325748fa0..000000000 --- a/src/CCW/ch/indoorsgnawty.c +++ /dev/null @@ -1,98 +0,0 @@ -// BanjoDecomp: CCW/ch/indoorsgnawty.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - s16 map; - s16 meetBeforeJiggyDialog; - s16 meetAfterJiggyDialog; -} CH_Indoors_Gnawty_Dialogs; - -typedef struct{ - CH_Indoors_Gnawty_Dialogs *dialogs; -} ActorLocal_chIndoorsGnawty; - -void chIndoorsGnawty_update(Actor *this); -Actor *chIndoorsGnawty_draw(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); - -/* .data */ -CH_Indoors_Gnawty_Dialogs chIndoorsGnawtyDialogs[] = { - { - MAP_45_CCW_AUTUMN, - VER_SELECT(ASSET_CD2_DIALOG_GNAWTY_MEET_FALL_INSIDE, 0x9E7, 0, 0), - 0 // [port] decomp uses NULL; dialog fields are asset ids, not pointers - }, - { - MAP_46_CCW_WINTER, - VER_SELECT(ASSET_CD4_DIALOG_GNAWTY_MEET_WINTER_INSIDE_JIGGY, 0x09E9, 0, 0), - VER_SELECT(ASSET_CD5_DIALOG_GNAWTY_MEET_WINTER_INSIDE_AFTER_JIGGY, 0x09EA, 0, 0) - }, - { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion -}; - -ActorInfo chIndoorsGnawty = { - MARKER_1CE_INDOOR_GNAWTY, ACTOR_31A_INDOORS_GNAWTY, ASSET_48F_MODEL_GNAWTY, - 0x0, NULL, - chIndoorsGnawty_update, NULL, chIndoorsGnawty_draw, - 0, 0, 2.2f, 0 -}; - -enum chIndoorsGnawty_State_e { - CH_INDOOR_GNAWTY_STATE_0_NOT_INIT, - CH_INDOOR_GNAWTY_STATE_1_IDLE -}; - -/* .code */ -void chIndoorsGnawty_setNextState(Actor *this, s32 next_state) { - if (next_state == CH_INDOOR_GNAWTY_STATE_1_IDLE) { - skeletalAnim_set(this->unk148, ASSET_1A6_ANIM_GNAWTY_IDLE, 0.2f, 5.5f); - } - - this->state = next_state; -} - -Actor *chIndoorsGnawty_draw(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { - if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) == false) { - return func_80325340(marker, gfx, mtx, vtx); - } - - return actor_draw(marker, gfx, mtx, vtx); -} - -void chIndoorsGnawty_update(Actor *this) { - ActorLocal_chIndoorsGnawty *local; - f32 plyr_pos[3]; - - local = (ActorLocal_chIndoorsGnawty *)&this->local; - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - local->dialogs = chIndoorsGnawtyDialogs; - while (local->dialogs->map != 0 && gsworld_getMap() != local->dialogs->map) { - local->dialogs++; - } - - chIndoorsGnawty_setNextState(this, CH_INDOOR_GNAWTY_STATE_1_IDLE); - if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); - } - return; - } - - if(!this->has_met_before){ - player_getPosition(plyr_pos); - if (ml_vec3f_distance(this->position, plyr_pos) < 600.0f) { - if (!jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { - gcdialog_showDialog(local->dialogs->meetBeforeJiggyDialog, 4, NULL, NULL, NULL, NULL); - } else { - if (local->dialogs->meetAfterJiggyDialog) { - gcdialog_showDialog(local->dialogs->meetAfterJiggyDialog, 4, NULL, NULL, NULL, NULL); - } - } - this->has_met_before = true; - } - } - -} diff --git a/src/CCW/ch/nabnut_autumn.c b/src/CCW/ch/nabnut_autumn.c new file mode 100644 index 000000000..11c4c56ed --- /dev/null +++ b/src/CCW/ch/nabnut_autumn.c @@ -0,0 +1,172 @@ +// BanjoDecomp: code_5540.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + s32 returned_acorn_count; +}ActorLocal_CCW_5540; + +void chnabnut_setState(Actor *this, s32 next_state); +Actor *chnabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void chnabnut_update(Actor *this); + +enum nabnut_state_e{ + NABNUT_STATE_1_SAD = 1, + NABNUT_STATE_2_WAIT, + NABNUT_STATE_3_BACKFLIP, + NABNUT_STATE_4_THANK_PLAYER, + NABNUT_STATE_5_EXIT, + NABNUT_STATE_6_DESPAWN +}; + +/* .data */ +f32 D_8038F350[3] = {0.0f, 0.0f, 0.0f}; +ActorInfo D_8038F35C = { + MARKER_1BB_NABNUT, ACTOR_2A8_NABNUT, ASSET_502_MODEL_NABNUT, + 0x0, NULL, + chnabnut_update, chnabnut_update, chnabnut_draw, + 0, 0, 1.2f, 0 +}; + +/* .code */ +void __chnabnut_setState_method(ActorMarker* marker, s32 next_state) { + chnabnut_setState(marker_getActor(marker), next_state); +} + +void chnabnut_setState(Actor *this, s32 next_state) { + + if (next_state == NABNUT_STATE_1_SAD) { + skeletalAnim_set(this->unk148, ASSET_22C_ANIM_NABNUT_CRY, 0.2f, 10.6f); + } + + if (next_state == NABNUT_STATE_2_WAIT) { + timedFunc_set_2(1.0f, (GenFunction_2)__chnabnut_setState_method, (uintptr_t)this->marker, NABNUT_STATE_3_BACKFLIP); + } + + if (next_state == NABNUT_STATE_3_BACKFLIP) { + this->marker->propPtr->unk8_3 = false; + skeletalAnim_set(this->unk148, ASSET_22D_ANIM_NABNUT_BACKFLIP, 0.2f, 3.13f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 0xB); + gcdialog_showDialog(0xCCC, 0x20, this->position, NULL, NULL, NULL); + } + + if (next_state == NABNUT_STATE_4_THANK_PLAYER) { + skeletalAnim_set(this->unk148, ASSET_22E_ANIM_NABNUT_STAND, 0.2f, 3.53f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + bundle_setYaw(this->yaw - 40.0f); + jiggy_spawn(JIGGY_4A_CCW_NABNUT, this->position); + } + + if (next_state == NABNUT_STATE_5_EXIT) { + skeletalAnim_set(this->unk148, ASSET_22F_ANIM_NABNUT_RUN, 0.2f, 0.34f); + } + + if (next_state == NABNUT_STATE_6_DESPAWN) { + func_80324E38(0.0f, 0); + timed_exitStaticCamera(0.0f); + marker_despawn(this->marker); + } + + this->state = next_state; +} + +Actor *chnabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + Actor *out; + void *sp24; + f32 temp_f2; + + this = marker_getActor(marker); + func_8033A45C(3, 0); + func_8033A45C(4, 0); + func_8033A45C(5, 1); + func_8033A45C(6, 0); + func_8033A45C(7, 1); + func_8033A45C(8, 1); + func_8033A45C(9, 0); + func_8033A45C(0xA, 1); + if (this->state == 1) { + temp_f2 = skeletalAnim_getProgress(this->unk148); + if ((0.116 <= temp_f2) && (temp_f2 <= 0.32)) { + sp24 = this->unk130; + this->unk130 = NULL; + func_8033A45C(1, 4); + out = actor_draw(marker, gfx, mtx, vtx); + out->unk130 = sp24; + return out; + } + } + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_8038BC50(f32 dst[3]){ + dst[0] = D_8038F350[0]; + dst[1] = D_8038F350[1]; + dst[2] = D_8038F350[2]; +} + +void chnabnut_update(Actor *this) { + ActorLocal_CCW_5540 *local; + f32 sp30[3]; + f32 sp2C; + f32 sp28; + f32 sp24; + + local = (ActorLocal_CCW_5540 *)&this->local; + if (!this->volatile_initialized) { + this->volatile_initialized = true; + D_8038F350[0] = this->position[0]; + D_8038F350[1] = this->position[1]; + D_8038F350[2] = this->position[2]; + if (this->state == 0) { + this->has_met_before = false; + local->returned_acorn_count = 0; + } + chnabnut_setState(this, 1); + if(jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT)) { + marker_despawn(this->marker); + } + return; + } + + if (this->state == NABNUT_STATE_1_SAD) { + player_getPosition(sp30); + if (!this->has_met_before && (ml_vec3f_distance(this->position, sp30) < 400.0f)) { + this->has_met_before = true; + gcdialog_showDialog(0xCCA, 0xE, this->position, NULL, NULL, NULL); + } + if (item_getCount(ITEM_23_ACORNS) > 0) { + func_80258A4C(this->position, this->yaw - 90.0f, sp30, &sp2C, &sp28, &sp24); + this->yaw += sp24 * 10.0f; + } + if (this->has_met_before && !gcdialog_hasCurrentTextId()) { + player_setCarryObjectPoseInCylinder(this->position, 500.0f, 200.0f, ACTOR_2A9_ACORN, &this); + if ((carriedObj_getActorId() == ACTOR_2A9_ACORN) && (ml_vec3f_distance(this->position, sp30) < 300.0f) && player_throwCarriedObject()) { + player_setThrowTargetPosition(D_8038F350); + local->returned_acorn_count++; + if (local->returned_acorn_count == 6) { + chnabnut_setState(this, NABNUT_STATE_2_WAIT); + } else if (item_getCount(ITEM_23_ACORNS) == 1) { + gcdialog_showDialog(0xCCB, 0x20, this->position, NULL, NULL, NULL); + } + } + } + } + if ((this->state == NABNUT_STATE_3_BACKFLIP) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { + chnabnut_setState(this, NABNUT_STATE_4_THANK_PLAYER); + } + if ((this->state == NABNUT_STATE_4_THANK_PLAYER) && (skeletalAnim_getLoopCount(this->unk148) > 0)) { + chnabnut_setState(this, NABNUT_STATE_5_EXIT); + } + if (this->state == NABNUT_STATE_5_EXIT) { + actor_update_func_80326224(this); + func_8028FC8C(this->position); + if (0.99 < this->unk48) { + chnabnut_setState(this, NABNUT_STATE_6_DESPAWN); + } + } + func_8028E668(this->position, 300.0f, -50.0f, 120.0f); +} diff --git a/src/CCW/ch/nabnut_dialog.c b/src/CCW/ch/nabnut_dialog.c new file mode 100644 index 000000000..27565536b --- /dev/null +++ b/src/CCW/ch/nabnut_dialog.c @@ -0,0 +1,85 @@ +// BanjoDecomp: code_6EC0.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + s16 map; + s16 unk2; + s16 unk4; +}Struct_CCW_6EC0_0; + +typedef struct{ + Struct_CCW_6EC0_0 *unk0; +}ActorLocal_CCW_6EC0; + +void func_8038D368(Actor *this); +Actor *func_8038D30C(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); + +/* .data */ +Struct_CCW_6EC0_0 D_8038F600[] = { + {MAP_45_CCW_AUTUMN, 0xCD2, 0}, + {MAP_46_CCW_WINTER, 0xCD4, 0xCD5}, + 0 +}; + +ActorInfo D_8038F614 = { + 0x1CE, 0x31A, 0x48F, + 0x0, NULL, + func_8038D368, NULL, func_8038D30C, + 0, 0, 2.2f, 0 +}; + +/* .code */ +void func_8038D2B0(Actor *this, s32 next_state) { + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x1A6, 0.2f, 5.5f); + } + + this->state = next_state; +} + +Actor *func_8038D30C(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { + if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_UNKNOWN) == false) { + return func_80325340(marker, gfx, mtx, vtx); + } + + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_8038D368(Actor *this) { + ActorLocal_CCW_6EC0 *local; + f32 plyr_pos[3]; + + local = (ActorLocal_CCW_6EC0 *)&this->local; + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + local->unk0 = D_8038F600; + while (local->unk0->map != 0 && gsworld_getMap() != local->unk0->map) { + local->unk0++; + } + + func_8038D2B0(this, 1); + if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { + levelSpecificFlags_set(LEVEL_FLAG_25_CCW_UNKNOWN, true); + } + return; + } + + if(!this->has_met_before){ + player_getPosition(plyr_pos); + if (ml_vec3f_distance(this->position, plyr_pos) < 600.0f) { + if (!jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { + gcdialog_showDialog(local->unk0->unk2, 4, NULL, NULL, NULL, NULL); + } else { + if (local->unk0->unk4) { + gcdialog_showDialog(local->unk0->unk4, 4, NULL, NULL, NULL, NULL); + } + } + this->has_met_before = true; + } + } + +} diff --git a/src/CCW/ch/nabnut_spring.c b/src/CCW/ch/nabnut_spring.c new file mode 100644 index 000000000..e502ca7ea --- /dev/null +++ b/src/CCW/ch/nabnut_spring.c @@ -0,0 +1,97 @@ +// BanjoDecomp: code_4D00.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct { + f32 unk0; +}ActorLocal_CCW_4D00; + +typedef struct { + f32 unk0; + f32 unk4; + s16 unk8; + s16 unkA; +}Struct_CCW_4D00_0; + +void func_8038B19C(Actor *this); + +/* .data */ +ActorInfo D_8038F270 = { + 0x1B9, 0x2A6, 0x502, + 0x0, NULL, + func_8038B19C, NULL, actor_draw, + 0, 0, 0.0f, 0 +}; + +Struct_CCW_4D00_0 D_8038F294[] = { + {0.12f, 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, + {0.21f, 1.7f, SFX_A7_WOODEN_SWOSH, 8500}, + {0.3f , 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, + {0.51f, 1.0f, SFX_4C_LIP_SMACK, 22000}, + {0.65f, 1.05f, SFX_4C_LIP_SMACK, 23000}, + {0.76f, 1.0f, SFX_4C_LIP_SMACK, 22000}, + {0.88f, 1.0f, SFX_4C_LIP_SMACK, 23000}, + 0 +}; + +/* .code */ +void func_8038B0F0(Actor *this, s32 next_state) { + ActorLocal_CCW_4D00 *local = (ActorLocal_CCW_4D00 *)&this->local; + + local->unk0 = 0.0f; + if (next_state == 1) { + skeletalAnim_swap(this->unk148, 0x1A3, 0.2f, 11.0f); + local->unk0 = randf2(3.0f, 10.0f); + } + if (next_state == 2) { + skeletalAnim_set(this->unk148, 0x1A4, 0.2f, 3.0f); + } + this->state = next_state; +} + +void func_8038B19C(Actor *this) { + ActorLocal_CCW_4D00 *local; + f32 tick; + Struct_CCW_4D00_0 *iPtr; + f32 sp50; + f32 sp4C; + + local = (ActorLocal_CCW_4D00 *)&this->local; + tick = time_getDelta(); + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->has_met_before = false; + func_8038B0F0(this, 1); + } + + if ((this->state == 1) && ml_timer_update(&local->unk0, tick)) { + func_8038B0F0(this, 2); + } + + if (this->state == 2) { + skeletalAnim_getProgressRange(this->unk148, &sp50, &sp4C); + for(iPtr = &D_8038F294[0]; iPtr->unk0 > 0.0f; iPtr++){ + if ((sp50 < iPtr->unk0) && (iPtr->unk0 <= sp4C)) { + func_8030E878(iPtr->unk8, randf2(iPtr->unk4 - 0.05, iPtr->unk4 + 0.05), randi2(iPtr->unkA - 0x1F4, iPtr->unkA + 0x1F4), this->position, 500.0f, 2500.0f); + } + } + + if ((sp50 < 0.97) && (0.97 <= sp4C)) { + if (randf() >= 0.5) { + func_8030E878(SFX_AE_YUMYUM_TALKING, randf2(1.8f, 1.85f), randi2(19000, 21000), this->position, 500.0f, 2500.0f); + } else { + func_8030E878(SFX_4B_GULPING, randf2(1.4f, 1.45f), randi2(24000, 26000), this->position, 500.0f, 2500.0f); + } + } + if (skeletalAnim_getLoopCount(this->unk148) > 0) { + func_8038B0F0(this, 1); + } + } + if (!this->has_met_before && func_803292E0(this)) { + this->has_met_before = true; + gcdialog_showDialog(0xCC8, 0, NULL, NULL, NULL, NULL); + } + func_8028E668(this->position, 300.0f, -50.0f, 120.0f); +} diff --git a/src/CCW/ch/bellyfullnabnut.c b/src/CCW/ch/nabnut_summer.c similarity index 61% rename from src/CCW/ch/bellyfullnabnut.c rename to src/CCW/ch/nabnut_summer.c index 135c17016..8388d0c15 100644 --- a/src/CCW/ch/bellyfullnabnut.c +++ b/src/CCW/ch/nabnut_summer.c @@ -1,19 +1,19 @@ -// BanjoDecomp: CCW/ch/bellyfullnabnut.c +// BanjoDecomp: code_50D0.c #include #include "functions.h" #include "variables.h" -void chNabnutBellyFull_update(Actor *this); +void func_8038B87C(Actor *this); /* .data */ -ActorInfo chNabnutBellyFull = { - MARKER_1BA_NABNUT_FULL_BELLY, ACTOR_2A7_NABNUT_FULL_BELLY, ASSET_503_MODEL_NABNUT_BELLY_FULL, +ActorInfo D_8038F300 = { + 0x1BA, 0x2A7, 0x503, 0x0, NULL, - chNabnutBellyFull_update, NULL, actor_draw, + func_8038B87C, NULL, actor_draw, 0, 0, 2.0f, 0 }; -s32 chNabnutBellyFullSFX[] = { +s32 D_8038F324[] = { SFX_97_BLUBBER_BURPS, SFX_3E_POOP_NOISE, SFX_F6_BLUBBER_TALKING_2, @@ -23,39 +23,23 @@ s32 chNabnutBellyFullSFX[] = { 0 }; -enum ChNabnutBellyFull_State_e { - CH_NABNUT_BELLY_FULL_STATE_1_UNK = 1 -}; - /* .code */ void func_8038B4C0(ActorMarker *marker) { Actor *this; - static s32 chNabnutBellyFullSFXIndex = 0; + static s32 D_8038F340 = 0; this = marker_getActor(marker); - func_8030E878( - chNabnutBellyFullSFX[chNabnutBellyFullSFXIndex], - randf2(1.1f, 1.2f), - (s32) randf2(31000.0f, 32000.0f), - this->position, - 500.0f, - 2500.0f); - chNabnutBellyFullSFXIndex++; - if (chNabnutBellyFullSFX[chNabnutBellyFullSFXIndex] == 0) { - chNabnutBellyFullSFXIndex = 0; + func_8030E878(D_8038F324[D_8038F340], randf2(1.1f, 1.2f), (s32) randf2(31000.0f, 32000.0f), this->position, 500.0f, 2500.0f); + D_8038F340++; + if (D_8038F324[D_8038F340] == 0) { + D_8038F340 = 0; } } void func_8038B58C(ActorMarker* marker) { Actor* actor = marker_getActor(marker); - func_8030E878( - SFX_81_UUU, - randf2(1.0f, 1.1f), - (s32) randf2(31000.0f, 32000.0f), - actor->position, - 500.0f, - 2500.0f); + func_8030E878(0x81, randf2(1.0f, 1.1f), (s32) randf2(31000.0f, 32000.0f), actor->position, 500.0f, 2500.0f); } void func_8038B610(ActorMarker* marker) { @@ -93,23 +77,23 @@ void func_8038B6DC(ActorMarker *marker) { skeletalAnim_setCallback_1(this->unk148, 0.9f, (GenFunction_1)func_8038B6DC, (uintptr_t)this->marker); } -void chNabnutBellyFull_setNextState(Actor *this, s32 next_state) { - if (next_state == CH_NABNUT_BELLY_FULL_STATE_1_UNK) { +void func_8038B814(Actor *this, s32 next_state) { + if (next_state == 1) { skeletalAnim_set(this->unk148, 0x22B, 0.2f, 11.0f); func_8038B6DC(this->marker); } this->state = next_state; } -void chNabnutBellyFull_update(Actor *this) { +void func_8038B87C(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; this->has_met_before = false; - chNabnutBellyFull_setNextState(this, CH_NABNUT_BELLY_FULL_STATE_1_UNK); + func_8038B814(this, 1); } if (!this->has_met_before && func_803292E0(this)) { - this->has_met_before = TRUE; - gcdialog_showDialog(VER_SELECT(ASSET_CC9_DIALOG_NABNUT_MEET_SUMMER, 0x09DE, 0, 0), 0, NULL, NULL, NULL, NULL); + this->has_met_before = true; + gcdialog_showDialog(0xCC9, 0, NULL, NULL, NULL, NULL); } func_8028E668(this->position, 300.0f, -50.0f, 120.0f); } diff --git a/src/CCW/ch/nabnut_winter.c b/src/CCW/ch/nabnut_winter.c new file mode 100644 index 000000000..a1aac88c5 --- /dev/null +++ b/src/CCW/ch/nabnut_winter.c @@ -0,0 +1,124 @@ +// BanjoDecomp: code_5BF0.c +#include +#include "functions.h" +#include "variables.h" + +extern void func_8028E668(f32[3], f32, f32, f32); + +Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); +void func_8038C41C(Actor *this); + +/* .data */ +ActorInfo D_8038F380 = { 0x1C6, 0x310, 0x501, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038F3A4 = { 0x1C7, 0x311, 0x462, 0x0, NULL, func_8038C41C, NULL, func_8038C380, 0, 0, 0.0f, 0}; +ActorInfo D_8038F3C8 = { 0x1C8, 0x312, 0x463, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038F3EC = { 0x1C9, 0x313, 0x464, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038F410 = { 0x1CA, 0x314, 0x502, 0x0, NULL, func_8038C41C, NULL, actor_draw, 0, 0, 2.0f, 0}; +ActorInfo D_8038F434 = { 0x1CB, 0x315, 0x48D, 0x0, NULL, func_8038C41C, NULL, func_8038C380, 0, 0, 0.0f, 0}; + +/* .code */ +void func_8038BFE0(ActorMarker* marker) { + Actor* sp2C = marker_getActor(marker); + func_8030E878(SFX_5D_BANJO_RAAOWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); +} + +void func_8038C064(ActorMarker* marker) { + Actor* sp2C = marker_getActor(marker); + func_8030E878(SFX_5E_BANJO_PHEWWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); +} + +void func_8038C0E8(ActorMarker* marker) { + Actor* sp24 = marker_getActor(marker); + f32 sp20 = randf2(0.9f, 1.1f); + + func_8030E878(SFX_81_UUU, sp20, (s32)randf2(10000.0f, 31000.0f), sp24->position, 500.0f, 2500.0f); +} + +void CCW_func_8038C16C(Actor *this, s32 next_state) { + Actor *other; + + if (next_state == 1) { + this->position[1] -= 300.0f; + } + + if (this->state == 1) { + this->position[1] += 300.0f; + } + + if (next_state == 2) { + if (this->marker->id == 0x1CA) { + skeletalAnim_set(this->unk148, 0x22E, 0.2f, 3.53f); + skeletalAnim_setCallback_1(this->unk148, 0.1f, (GenFunction_1)func_8038C0E8, (uintptr_t)this->marker); + } + if (this->marker->id == 0x1C7) { + skeletalAnim_set(this->unk148, 0x230, 0.2f, 4.0f); + } + if (this->marker->id == 0x1CB) { + skeletalAnim_set(this->unk148, 0x1A2, 0.2f, 4.0f); + skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_8038BFE0, (uintptr_t)this->marker); + skeletalAnim_setCallback_1(this->unk148, 0.65f, (GenFunction_1)func_8038C064, (uintptr_t)this->marker); + } + if (this->marker->id == 0x1C8) { + skeletalAnim_set(this->unk148, 0x231, 0.2f, 4.0f); + } + if ((this->marker->id == 0x1C7) || (this->marker->id == 0x1CB) || (this->marker->id == 0x1C8)) { + other = actorArray_findActorFromActorId(0x313); + if (other != 0) { + this->position[0] = other->position[0]; + this->position[1] = other->position[1]; + this->position[2] = other->position[2]; + this->pitch = other->pitch; + this->yaw = other->yaw; + this->roll = other->roll; + } + } + } + this->state = next_state; +} + +Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { + func_8033A45C(3, 0); + func_8033A45C(4, 0); + func_8033A45C(5, 0); + func_8033A45C(6, 1); + func_8033A45C(7, 0); + func_8033A45C(8, 0); + func_8033A45C(9, 0); + func_8033A45C(0xA, 1); + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_8038C41C(Actor *this) { + f32 sp2C[3]; + + if (!this->volatile_initialized) { + this->marker->propPtr->unk8_3 = true; + this->volatile_initialized = true; + this->has_met_before = false; + return; + } + + if (this->state == 0) { + if( gsworld_getMap() == MAP_60_CCW_AUTUMN_NABNUTS_HOUSE + && !jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT) + && (this->marker->id == 0x1C6 || this->marker->id == 0x1CA) + ){ + CCW_func_8038C16C(this, 1); + } else { + CCW_func_8038C16C(this, 2); + } + } + + if ((this->marker->id == 0x1CA) && (this->state != 1)) { + func_8028E668(this->position, 300.0f, -50.0f, 120.0f); + } + + if ((this->marker->id == 0x1CB) && (this->state == 2)) { + player_getPosition(sp2C); + if (!this->has_met_before && (ml_vec3f_distance(this->position, sp2C) < 400.0f)) { + this->has_met_before = true; + gcdialog_showDialog(0xCCD, 0, NULL, NULL, NULL, NULL); + } + } +} + diff --git a/src/CCW/ch/outsideautumnnabnut.c b/src/CCW/ch/outsideautumnnabnut.c deleted file mode 100644 index 23893dd91..000000000 --- a/src/CCW/ch/outsideautumnnabnut.c +++ /dev/null @@ -1,226 +0,0 @@ -// BanjoDecomp: CCW/ch/outsideautumnnabnut.c -#include -#include "functions.h" -#include "variables.h" -#include "port/Patches/Patches.h" - -// Anchor: set during a remote completion replay; skips the finisher's camera/dialog. -static s32 sNabnutRemote = 0; - -typedef struct { - s32 returned_acorn_count; -}ActorLocal_ChAutumnNabnutPosition; - -void chAutumnOutsideNabnut_setState(Actor *this, s32 next_state); -Actor *__chAutumnOutsideNabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chAutumnOutsideNabnut_update(Actor *this); - -enum chautumnoutdoornabnut_state_e{ - CH_AUTUMN_OUTDOOR_NABNUT_STATE_0_NOT_INIT, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_6_DESPAWN -}; - -/* .data */ -f32 chAutumnOutdoorNabnutPosition[3] = {0.0f, 0.0f, 0.0f}; // updates on init - -#define AUTUMN_NABNUT_ACORN_COUNT 6 - -ActorInfo chAutumnOutdoorNabnut = { - MARKER_1BB_NABNUT, ACTOR_2A8_NABNUT, ASSET_502_MODEL_NABNUT, - 0x0, NULL, - chAutumnOutsideNabnut_update, chAutumnOutsideNabnut_update, __chAutumnOutsideNabnut_draw, - 0, 0, 1.2f, 0 -}; - -/* .code */ -void __chAutumnOutsideNabnut_setStateMethod(ActorMarker* marker, s32 next_state) { - chAutumnOutsideNabnut_setState(marker_getActor(marker), next_state); -} - -void chAutumnOutsideNabnut_setState(Actor *this, s32 next_state) { - - if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { - skeletalAnim_set(this->unk148, ASSET_22C_ANIM_NABNUT_CRY, 0.2f, 10.6f); - } - - if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT) { - timedFunc_set_2( - 1.0f, - (GenFunction_2)__chAutumnOutsideNabnut_setStateMethod, - (uintptr_t)this->marker, - CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP); - } - - if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP) { - this->marker->propPtr->unk8_3 = false; - skeletalAnim_set(this->unk148, ASSET_22D_ANIM_NABNUT_BACKFLIP, 0.2f, 3.13f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if (!sNabnutRemote) { - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 0xB); - gcdialog_showDialog( - VER_SELECT(ASSET_CCC_DIALOG_NABNUT_ACORN_COMPLETE, 0x09E1, 0, 0), - 0x20, this->position, - NULL, NULL, NULL); - } - } - - if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER) { - skeletalAnim_set(this->unk148, ASSET_22E_ANIM_NABNUT_STAND, 0.2f, 3.53f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - bundle_setYaw(this->yaw - 40.0f); - if (!jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT)) { - jiggy_spawn(JIGGY_4A_CCW_NABNUT, this->position); - } - } - - if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT) { - skeletalAnim_set(this->unk148, ASSET_22F_ANIM_NABNUT_RUN, 0.2f, 0.34f); - } - - if (next_state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_6_DESPAWN) { - if (!sNabnutRemote) { - func_80324E38(0.0f, 0); - timed_exitStaticCamera(0.0f); - } - marker_despawn(this->marker); - } - - this->state = next_state; -} - -Actor *__chAutumnOutsideNabnut_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - Actor *out; - void *sp24; - f32 temp_f2; - - this = marker_getActor(marker); - modelRender_setAppendageVisibility(3, 0); - modelRender_setAppendageVisibility(4, 0); - modelRender_setAppendageVisibility(5, 1); - modelRender_setAppendageVisibility(6, 0); - modelRender_setAppendageVisibility(7, 1); - modelRender_setAppendageVisibility(8, 1); - modelRender_setAppendageVisibility(9, 0); - modelRender_setAppendageVisibility(0xA, 1); - if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { - temp_f2 = skeletalAnim_getProgress(this->unk148); - if ((0.116 <= temp_f2) && (temp_f2 <= 0.32)) { - sp24 = this->unk130; - this->unk130 = NULL; - modelRender_setAppendageVisibility(1, 4); - out = actor_draw(marker, gfx, mtx, vtx); - out->unk130 = sp24; - return out; - } - } - return actor_draw(marker, gfx, mtx, vtx); -} - -void chAutumnOutsideNabnut_getPosition(f32 dst[3]){ - dst[0] = chAutumnOutdoorNabnutPosition[0]; - dst[1] = chAutumnOutdoorNabnutPosition[1]; - dst[2] = chAutumnOutdoorNabnutPosition[2]; -} - -void chAutumnOutsideNabnut_update(Actor *this) { - ActorLocal_ChAutumnNabnutPosition *local; - f32 player_position[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; - - local = (ActorLocal_ChAutumnNabnutPosition *)&this->local; - if (!this->volatile_initialized) { - this->volatile_initialized = true; - chAutumnOutdoorNabnutPosition[0] = this->position[0]; - chAutumnOutdoorNabnutPosition[1] = this->position[1]; - chAutumnOutdoorNabnutPosition[2] = this->position[2]; - if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_0_NOT_INIT) { - this->has_met_before = false; - local->returned_acorn_count = port_puzzleCount_get(ANCHOR_COUNT_CCW_NABNUT_ACORNS); - sNabnutRemote = 0; - } - chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD); - if(jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT)) { - marker_despawn(this->marker); - } - return; - } - - if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { - player_getPosition(player_position); - if (!this->has_met_before - && (ml_vec3f_distance(this->position, player_position) < 400.0f)) - { - this->has_met_before = true; - gcdialog_showDialog( - VER_SELECT(ASSET_CCA_DIALOG_NABNUT_MEET_FALL, 0x09DF, 0, 0), - 0xE, this->position, - NULL, NULL, NULL); - } - if (item_getCount(ITEM_23_ACORNS) > 0) { - func_80258A4C( - this->position, - this->yaw - 90.0f, - player_position, - &horizontal_distance, - &distance_in_front, - &side_angle_radian); - this->yaw += side_angle_radian * 10.0f; - } - if (this->has_met_before && !gcdialog_hasCurrentTextId()) { - player_setCarryObjectPoseInCylinder(this->position, 500.0f, 200.0f, ACTOR_2A9_ACORN, &this); - if ((carriedObj_getActorId() == ACTOR_2A9_ACORN) - && (ml_vec3f_distance(this->position, player_position) < 300.0f) - && player_throwCarriedObject()) - { - player_setThrowTargetPosition(chAutumnOutdoorNabnutPosition); - port_puzzleCount_add(ANCHOR_COUNT_CCW_NABNUT_ACORNS, 1); - local->returned_acorn_count = port_puzzleCount_get(ANCHOR_COUNT_CCW_NABNUT_ACORNS); - if (local->returned_acorn_count >= AUTUMN_NABNUT_ACORN_COUNT) { - chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT); - } else if (item_getCount(ITEM_23_ACORNS) == 1) { - gcdialog_showDialog( - VER_SELECT(ASSET_CCB_DIALOG_NABNUT_ACORN_CHECK, 0x09E0, 0, 0), - 0x20, this->position, - NULL, NULL, NULL); - } - } - } - if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_1_SAD) { - s32 sharedReturned = port_puzzleCount_get(ANCHOR_COUNT_CCW_NABNUT_ACORNS); - if (sharedReturned > local->returned_acorn_count) { - local->returned_acorn_count = sharedReturned; - if (sharedReturned >= AUTUMN_NABNUT_ACORN_COUNT) { - sNabnutRemote = 1; - chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_2_WAIT); - } - } - } - } - if ((this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_3_BACKFLIP) - && (skeletalAnim_getLoopCount(this->unk148) > 0)) - { - chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER); - } - if ((this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_4_THANK_PLAYER) - && (skeletalAnim_getLoopCount(this->unk148) > 0)) - { - chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT); - } - if (this->state == CH_AUTUMN_OUTDOOR_NABNUT_STATE_5_EXIT) { - actor_update_func_80326224(this); - func_8028FC8C(this->position); - if (0.99 < this->unk48) { - chAutumnOutsideNabnut_setState(this, CH_AUTUMN_OUTDOOR_NABNUT_STATE_6_DESPAWN); - } - } - func_8028E668(this->position, 300.0f, -50.0f, 120.0f); -} diff --git a/src/CCW/ch/seasonswitchdoors.c b/src/CCW/ch/seasonswitchdoors.c deleted file mode 100644 index 9882d0946..000000000 --- a/src/CCW/ch/seasonswitchdoors.c +++ /dev/null @@ -1,245 +0,0 @@ -// BanjoDecomp: CCW/ch/seasonswitchdoors.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - u8 unk0; - u8 returnMapId; - u8 cameraNode; - u8 returnEntryPoint; -} CH_Season_Switch_Doors_Cutscene_Info; - -void chSeasonSwitchDoors_update(Actor *this); -void chSeasonSwitch_update(Actor *this); - -/* .data */ -CH_Season_Switch_Doors_Cutscene_Info chSeasonSwitchDoorsCutsceneInfo[] = { - {0, MAP_40_CCW_HUB, 0, 5}, - {0, MAP_43_CCW_SPRING, 1, 5}, - {0, MAP_44_CCW_SUMMER, 2, 5}, - {0, MAP_45_CCW_AUTUMN, 3, 15} -}; - -ActorAnimationInfo chSeasonSwitchAnimations[] = { - {0, 0.0f}, - {0, 0.0f}, - {0, 0.0f}, - {0, 0.0f}, - {ASSET_D4_ANIM_SWITCH_DOWN, 0.5f}, - {ASSET_D4_ANIM_SWITCH_DOWN, 100000000.0f} -}; - -ActorInfo chCCWSpringSwitchDoor = { - MARKER_133_CCW_SPRING_SEASON_DOOR, ACTOR_1E3_CCW_SPRING_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, - 0x1, NULL, - chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0x4000, 0.0f, 0 -}; - -ActorInfo chCCWSpringSwitch = { - MARKER_132_CCW_SPRING_SWITCH, ACTOR_1E2_CCW_SPRING_SWITCH, ASSET_4F5_MODEL_CCW_SPRING_SWITCH, - 0x5, chSeasonSwitchAnimations, - chSeasonSwitch_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCCWSummerSwitchDoor = { - MARKER_131_CCW_SUMMER_SEASON_DOOR, ACTOR_16D_CCW_SUMMER_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, - 0x1, NULL, - chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0x4000, 0.0f, 0 -}; - -ActorInfo chCCWSummerSwitch = { - MARKER_130_CCW_SUMMER_SWITCH, ACTOR_16C_CCW_SUMMER_SWITCH, ASSET_4F6_MODEL_CCW_SUMMER_SWITCH, - 0x5, chSeasonSwitchAnimations, - chSeasonSwitch_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCCWAutumnSwitchDoor = { - MARKER_12F_CCW_AUTUMN_SEASON_DOOR, ACTOR_16B_CCW_AUTUMN_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, - 0x1, NULL, - chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0x4000, 0.0f, 0 -}; - -ActorInfo chCCWAutumnSwitch = { - MARKER_12E_CCW_AUTUMN_SWITCH, ACTOR_16A_CCW_AUTUMN_SWITCH, ASSET_4F7_MODEL_CCW_AUTUMN_SWITCH, - 0x5, chSeasonSwitchAnimations, - chSeasonSwitch_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCCWWinterSwitchDoor = { - MARKER_12D_CCW_WINTER_SEASON_DOOR, ACTOR_169_CCW_WINTER_SEASON_DOOR, ASSET_52E_MODEL_CCW_SEASON_DOOR, - 0x1, NULL, - chSeasonSwitchDoors_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0x4000, 0.0f, 0 -}; - -ActorInfo chCCWWinterSwitch = { - MARKER_12C_CCW_WINTER_SWITCH, ACTOR_168_CCW_WINTER_SWITCH, ASSET_4F8_MODEL_CCW_WINTER_SWITCH, - 0x5, chSeasonSwitchAnimations, - chSeasonSwitch_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -enum chCCWSeasonSwitchDoor_State_e { - CH_CCW_SEASON_SWITCH_DOOR_STATE_0_NOT_INIT, - CH_CCW_SEASON_SWITCH_DOOR_STATE_1_LOWERED, - CH_CCW_SEASON_SWITCH_DOOR_STATE_2_OPENING, - CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED, - CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION -}; - -/* .code */ -s32 chCCWSwitchAndDoor_getSeason(Actor *this){ - switch(this->marker->id){ - case MARKER_133_CCW_SPRING_SEASON_DOOR: //L80388F28 - case MARKER_132_CCW_SPRING_SWITCH: //L80388F28 - return CCW_SEASON_0_SPRING; - - case MARKER_131_CCW_SUMMER_SEASON_DOOR: //L80388F30 - case MARKER_130_CCW_SUMMER_SWITCH: //L80388F30 - return CCW_SEASON_1_SUMMER; - - case MARKER_12F_CCW_AUTUMN_SEASON_DOOR: //L80388F38 - case MARKER_12E_CCW_AUTUMN_SWITCH: //L80388F38 - return CCW_SEASON_2_AUTUMN; - - case MARKER_12D_CCW_WINTER_SEASON_DOOR: //L80388F40 - case MARKER_12C_CCW_WINTER_SWITCH: //L80388F40 - return CCW_SEASON_3_WINTER; - - default: - return CCW_SEASON_0_SPRING; - } -} - - -void chSeasonSwitch_pressed(ActorMarker *marker, ActorMarker *other_marker){ - Actor *this; - - this = marker_getActor(marker); - if ((player_movementGroup() != BSGROUP_1_INTR) && !this->unk38_0) { - this->unk38_0 = true; - actor_collisionOff(this); - subaddie_set_state_with_direction(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION, 0.0f, 1); - actor_playAnimationOnce(this); - func_8030E6D4(SFX_90_SWITCH_PRESS); - } -} - -void chSeasonSwitch_update(Actor *this) { - - if (!this->initialized) { - this->unk138_31 = this->unk124_0 = true; - this->marker->propPtr->unk8_3 = true; - this->unk10_12 = chCCWSwitchAndDoor_getSeason(this); - this->initialized = true; - } - if (!this->volatile_initialized) { - if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { - if (EventSystem_Should(VB_CCW_SEASON_SWITCH_PRESSED_INIT, true, this)) { - actor_playAnimationOnce(this); - subaddie_set_state_with_direction(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION, 0.999f, 1); - } - actor_collisionOff(this); - } else { - marker_setCollisionScripts(this->marker, NULL, &chSeasonSwitch_pressed, NULL); - } - this->unk38_0 = false; - this->volatile_initialized = true; - } - // Anchor: teammate pressed this switch (flag synced) — drop it to match; unk38_0 stays false. - if( this->state != CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION - && fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN) - ){ - actor_playAnimationOnce(this); - subaddie_set_state_with_direction(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION, 0.999f, 1); - actor_collisionOff(this); - } - if( (this->state == CH_CCW_SEASON_SWITCH_DOOR_STATE_4_NO_COLLISION) - && this->unk38_0 - && actor_animationIsAt(this, 0.999f) - ){ - func_802D6264( - 1.1f, - 0x40, - this->unk10_12 + 0x3C, - 0x2B, - chSeasonSwitchDoorsCutsceneInfo[this->unk10_12].returnEntryPoint, - this->unk10_12 + 0x8B); - func_80324E38(0.5f, 3); - timedFunc_set_2(1.1f, (GenFunction_2)levelSpecificFlags_set, this->unk10_12 + 7, true); - func_80324E38(5.6f, 0); - } -} - -void chSeasonSwitchDoors_doorOpening(void* marker) { - Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); - actor->unk44_31 = func_8030ED2C(SFX_3EC_CCW_DOOR_OPENING, 3); - func_8030DD90(actor->unk44_31, 0); - sfxsource_setSampleRate(actor->unk44_31, 11000); - sfxsource_playSfxAtVolume(actor->unk44_31, 0.3f); - sfxSource_func_8030E2C4(actor->unk44_31); -} - -void chSeasonSwitchDoors_doorOpened(void* marker) { - Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); - sfxSource_triggerCallbackByIndex(actor->unk44_31); - sfxsource_freeSfxsourceByIndex(actor->unk44_31); - actor->unk44_31 = 0U; - FUNC_8030E624(SFX_6C_LOCKUP_CLOSING, 1.0f, 25000); -} - -void chSeasonSwitchDoors_update(Actor *this) { - ActorProp *temp_v1; - u32 temp_v0; - u32 temp_v1_2; - - if(!this->initialized) { - this->unk58_2 = false; - this->unk10_12 = chCCWSwitchAndDoor_getSeason(this); - this->marker->propPtr->unk8_3 = true; - actor_collisionOff(this); - this->initialized = true; - } - if (!this->volatile_initialized) { - this->unk1C[0] = this->position[0]; - this->unk1C[1] = this->position[1]; - this->unk1C[2] = this->position[2]; - // [port] A savestate-restored door comes back at its raised position with - // volatile_initialized cleared. - if (this->state != CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED) { - this->unk1C[1] += 250.0f; - } - - this->volatile_initialized = true; - if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { - subaddie_set_state(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED); - } - } - - switch (this->state) { /* irregular */ - case CH_CCW_SEASON_SWITCH_DOOR_STATE_1_LOWERED: - if (levelSpecificFlags_get(this->unk10_12 + 7)) { - timedFunc_set_1(0.05f, (GenFunction_1)chSeasonSwitchDoors_doorOpening, (uintptr_t)this->marker); - timedFunc_set_1(4.0f, (GenFunction_1)chSeasonSwitchDoors_doorOpened, (uintptr_t)this->marker); - subaddie_set_state(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_2_OPENING); - } - break; - case CH_CCW_SEASON_SWITCH_DOOR_STATE_2_OPENING: - this->position[1] += 60.0f * time_getDelta(); - if (this->unk1C[1] <= this->position[1]) { - levelSpecificFlags_set(this->unk10_12 + 7, false); - subaddie_set_state(this, CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED); - } - break; - case CH_CCW_SEASON_SWITCH_DOOR_STATE_3_RAISED: - this->position[1] = this->unk1C[1]; - break; - } -} diff --git a/src/CCW/ch/snarebear.c b/src/CCW/ch/snarebear.c index de8de25c8..88af55bee 100644 --- a/src/CCW/ch/snarebear.c +++ b/src/CCW/ch/snarebear.c @@ -1,140 +1,24 @@ -// BanjoDecomp: CCW/ch/snarebear.c +// BanjoDecomp: code_7BC0.c #include #include "functions.h" #include "variables.h" +void func_8038DFB0(Actor *this); -void chSnarebear_update(Actor *this); -/* .data */ -ActorAnimationInfo chSnarebearAnimations[] = { - {0x000, 0.0f}, - {ASSET_16C_ANIM_SNAREBEAR_IDLE, 2.0f}, - {ASSET_16B_ANIM_SNAREBEAR_ATTACK, 1.2f} +ActorAnimationInfo D_8038F8B0[] = { + {0x000, 0.0f}, + {0x234, 2.0f} }; -ActorInfo chSnarebear = { - MARKER_1F9_SNARE_BEAR, ACTOR_1E9_SNARE_BEAR, ASSET_440_MODEL_SNAREBEAR, - 0x1, chSnarebearAnimations, - chSnarebear_update, actor_update_func_80326224, actor_draw, +ActorInfo D_8038F8C0 = { 0x251, 0x37E, 0x506, + 0x1, D_8038F8B0, + func_8038DFB0, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -enum chSnarebear_State_e { - CH_SNAREBEAR_STATE_0_NOT_INIT, - CH_SNAREBEAR_STATE_1_IDLE, - CH_SNAREBEAR_STATE_2_ATTACK -}; - /* .code */ -void chSnarebear_idle(Actor* actor) { - subaddie_set_state_with_direction(actor, CH_SNAREBEAR_STATE_1_IDLE, 0.001f, 1); - actor->unk38_31 = randi2(0, 0); -} - -void chSnarebear_attack(Actor* actor) { - subaddie_set_state_with_direction(actor, CH_SNAREBEAR_STATE_2_ATTACK, 0.001f, 1); -} - -void func_8038E060(BoneTransformList *bone_transform_list, ActorMarker *marker){ - Actor *this; - f32 sp28[3]; - s32 pad24; - f32 sp18[4]; // quaternion: func_80345C78 writes 4 floats - - this = marker_getActor(marker); - if(bone_transform_list){ - sp28[0] = 0.0f; - sp28[1] = this->unk1C[0]; - sp28[2] = 0.0f; - - - func_80345C78(sp18, sp28); - func_8033A8F0(bone_transform_list, 1, sp18); - modelRender_setBoneTransformList(bone_transform_list); - } -} - -void chSnarebear_update(Actor *this) { - f32 player_position[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; - f32 time_delta; - - time_delta = time_getDelta(); - - if(!subaddie_playerIsWithinSphere(this, 3000)) return; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - func_8028746C(this->anctrl, (GenFunction_2)func_8038E060); - func_8028748C(this->anctrl, (uintptr_t)this->marker); - this->marker->propPtr->unk8_3 = true; - this->unk1C[0] = 0.0f; - this->unk38_31 = 0; - } - - if (player_getTransformation() == TRANSFORM_6_BEE) { - actor_collisionOff(this); - } else { - actor_collisionOn(this); - player_getPosition(player_position); - func_80258A4C( - this->position, - this->yaw - 90.0f, - player_position, - &horizontal_distance, - &distance_in_front, - &side_angle_radian); - if( (horizontal_distance < 1050.0f) - && (side_angle_radian > -1.0f) - && (side_angle_radian < 1.0f) - ) { - func_80258A4C( - this->position, - this->unk1C[0] + (this->yaw - 90.0f), - player_position, - &horizontal_distance, - &distance_in_front, - &side_angle_radian); - this->unk1C[0] += side_angle_radian * 160.0f * time_delta; - } else { - if (this->unk1C[0] > 0.0f) { - this->unk1C[0] -= (30.0f * time_delta); - this->unk1C[0] = (this->unk1C[0] < 0.0f) ? 0.0f : this->unk1C[0]; - - } else if (this->unk1C[0] < 0.0f) { - this->unk1C[0] += (30.0f * time_delta); - this->unk1C[0] = (this->unk1C[0] > 0.0f) ? 0.0f : this->unk1C[0]; - } - } - } - switch (this->state) { - case CH_SNAREBEAR_STATE_1_IDLE: - if (this->unk38_31 != 0) { - this->unk38_31--; - break; - } - if( subaddie_playerIsWithinSphereAndActive(this, 680) - && (this->unk38_31 == 0) - && (player_getTransformation() == TRANSFORM_1_BANJO) - ) { - chSnarebear_attack(this); - } - break; - - case CH_SNAREBEAR_STATE_2_ATTACK: - if (actor_animationIsAt(this, 0.999f)) { - chSnarebear_idle(this); - break; - } - if( actor_animationIsAt(this, 0.18f) - || actor_animationIsAt(this, 0.47f) - || actor_animationIsAt(this, 0.78f) - ) { - sfx_playFadeShorthandDefault(SFX_80_YUMYUM_CLACK, 1.0f, 32000, this->position, 1500, 3000); - } - break; - } +void func_8038DFB0(Actor *this){ + this->marker->propPtr->unk8_3 = true; + actor_collisionOff(this); } diff --git a/src/CCW/ch/snore.c b/src/CCW/ch/snore.c index 74a08c8fb..f4159827c 100644 --- a/src/CCW/ch/snore.c +++ b/src/CCW/ch/snore.c @@ -6,27 +6,15 @@ void chSnoreZ_update(Actor *this); /* .data */ - -enum chSnoreZ_state_e { - SNORE_Z_STATE_0_NOT_INIT, - SNORE_Z_STATE_1_SPAWN_IN, - SNORE_Z_STATE_2_FADE_AWAY -}; - -ActorInfo chSnoreZ = { - MARKER_1C3_SNORE_Z, ACTOR_30C_SNORE_Z, ASSET_4E4_MODEL_SNORE_Z, - 0x0, NULL, - chSnoreZ_update, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; +ActorInfo D_8038F6F0 = { 0x1C3, 0x30C, 0x4E4, 0x0, NULL, chSnoreZ_update, NULL, actor_draw, 0, 0, 0.0f, 0}; /* .code */ void chSnoreZ_setNextState(Actor *this, s32 next_state) { - if (next_state == SNORE_Z_STATE_1_SPAWN_IN) { - skeletalAnim_set(this->unk148, ASSET_21C_ANIM_SNORE_Z, 0.0f, 6.0f); + if (next_state == 1) { + skeletalAnim_set(this->unk148, 0x21C, 0.0f, 6.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } - if (next_state == SNORE_Z_STATE_2_FADE_AWAY) { + if (next_state == 2) { func_80326310(this); } this->state = next_state; @@ -39,15 +27,15 @@ void chSnoreZ_update(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; - this->depth_mode = MODEL_RENDER_DEPTH_COMPARE; + this->depth_mode = 2; this->marker->unk40_22 = true; - chSnoreZ_setNextState(this, SNORE_Z_STATE_1_SPAWN_IN); + chSnoreZ_setNextState(this, 1); } - if (this->state == SNORE_Z_STATE_1_SPAWN_IN) { + if (this->state == 1) { this = this; skeletalAnim_getProgressRange(this->unk148, &sp24, &sp20); if ((sp24 < 0.25f) && (sp20 >= 0.25f)) { - chSnoreZ_setNextState(this, SNORE_Z_STATE_2_FADE_AWAY); + chSnoreZ_setNextState(this, 2); } } } diff --git a/src/CCW/ch/springnabnut.c b/src/CCW/ch/springnabnut.c deleted file mode 100644 index 82023570c..000000000 --- a/src/CCW/ch/springnabnut.c +++ /dev/null @@ -1,110 +0,0 @@ -// BanjoDecomp: CCW/ch/springnabnut.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct { - f32 currSFXProgress; -}ActorLocal_CCW_4D00; - -typedef struct { - f32 sfxProgress; - f32 volume; - s16 sfxId; - s16 sampleRate; -} CH_NABNUT_SPRING_SFX; - -void chNabnutSpring_update(Actor *this); - -/* .data */ - -ActorInfo chNabnutSpring = { - MARKER_1B9_NABNUT_SPRING, ACTOR_2A6_NABNUT_SPRING, ASSET_502_MODEL_NABNUT, - 0x0, NULL, - chNabnutSpring_update, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -CH_NABNUT_SPRING_SFX chNabnutSpringSfx[] = { - {0.12f, 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, - {0.21f, 1.7f, SFX_A7_WOODEN_SWOSH, 8500}, - {0.3f , 1.6f, SFX_A7_WOODEN_SWOSH, 8000}, - {0.51f, 1.0f, SFX_4C_LIP_SMACK, 22000}, - {0.65f, 1.05f, SFX_4C_LIP_SMACK, 23000}, - {0.76f, 1.0f, SFX_4C_LIP_SMACK, 22000}, - {0.88f, 1.0f, SFX_4C_LIP_SMACK, 23000}, - 0 -}; - -enum chNabnutSpring_State_e { - CH_NABNUT_SPRING_STATE_0_NOT_INIT, - CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND, - CH_NABNUT_SPRING_STATE_2_EATING -}; - -/* .code */ -void chNabnutSpring_setState(Actor *this, s32 next_state) { - ActorLocal_CCW_4D00 *local = (ActorLocal_CCW_4D00 *)&this->local; - - local->currSFXProgress = 0.0f; - if (next_state == CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND) { - skeletalAnim_swap(this->unk148, ASSET_1A3_ANIM_NABNUT_SPRING_LOOKING_AROUND, 0.2f, 11.0f); - local->currSFXProgress = randf2(3.0f, 10.0f); - } - if (next_state == CH_NABNUT_SPRING_STATE_2_EATING) { - skeletalAnim_set(this->unk148, ASSET_1A4_ANIM_NABNUT_SPRING_EATING, 0.2f, 3.0f); - } - this->state = next_state; -} - -void chNabnutSpring_update(Actor *this) { - ActorLocal_CCW_4D00 *local; - f32 tick; - CH_NABNUT_SPRING_SFX *iPtr; - f32 prev_progress; - f32 curr_progress; - - local = (ActorLocal_CCW_4D00 *)&this->local; - tick = time_getDelta(); - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->has_met_before = false; - chNabnutSpring_setState(this, CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND); - } - - if ((this->state == CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND) && ml_timer_update(&local->currSFXProgress, tick)) { - chNabnutSpring_setState(this, CH_NABNUT_SPRING_STATE_2_EATING); - } - - if (this->state == CH_NABNUT_SPRING_STATE_2_EATING) { - skeletalAnim_getProgressRange(this->unk148, &prev_progress, &curr_progress); - for(iPtr = &chNabnutSpringSfx[0]; iPtr->sfxProgress > 0.0f; iPtr++){ - if ((prev_progress < iPtr->sfxProgress) && (iPtr->sfxProgress <= curr_progress)) { - func_8030E878( - iPtr->sfxId, - randf2(iPtr->volume - 0.05, iPtr->volume + 0.05), - randi2(iPtr->sampleRate - 500, iPtr->sampleRate + 500), - this->position, - 500.0f, - 2500.0f); - } - } - - if ((prev_progress < 0.97) && (0.97 <= curr_progress)) { - if (randf() >= 0.5) { - func_8030E878(SFX_AE_YUMYUM_TALKING, randf2(1.8f, 1.85f), randi2(19000, 21000), this->position, 500.0f, 2500.0f); - } else { - func_8030E878(SFX_4B_GULPING, randf2(1.4f, 1.45f), randi2(24000, 26000), this->position, 500.0f, 2500.0f); - } - } - if (skeletalAnim_getLoopCount(this->unk148) > 0) { - chNabnutSpring_setState(this, CH_NABNUT_SPRING_STATE_1_LOOKING_AROUND); - } - } - if (!this->has_met_before && func_803292E0(this)) { - this->has_met_before = TRUE; - gcdialog_showDialog(VER_SELECT(ASSET_CC8_DIALOG_NABNUT_MEET_SPRING, 0x09DD, 0, 0), 0, NULL, NULL, NULL, NULL); - } - func_8028E668(this->position, 300.0f, -50.0f, 120.0f); -} diff --git a/src/CCW/ch/summeroutsidegnawty.c b/src/CCW/ch/summeroutsidegnawty.c deleted file mode 100644 index 4ebb00d9c..000000000 --- a/src/CCW/ch/summeroutsidegnawty.c +++ /dev/null @@ -1,160 +0,0 @@ -// BanjoDecomp: CCW/ch/summeroutsidegnawty.c -#include -#include "functions.h" -#include "variables.h" - -typedef struct{ - f32 sfxProgress; - f32 volume; - s16 sfxId; - s16 sampleRate; -} CH_Gnawty_Summer_SFX; - -void chGnawtySummer_update(Actor *this); - -/* .data */ - -ActorInfo chGnawtySummer = { - MARKER_1BE_GNAWTY_SUMMER, ACTOR_2AB_GNAWTY_SUMMER, ASSET_48F_MODEL_GNAWTY, - 0x0, NULL, - chGnawtySummer_update, chGnawtySummer_update, actor_draw, - 0, 0, 2.2f, 0 -}; - -CH_Gnawty_Summer_SFX chGnawtySummerIdleSfx[] = { - {0.11f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.23f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.34f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.58f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, - {0.8f, 1.0f, SFX_4D_WET_WIGGLING, 9000}, - 0 -}; - -CH_Gnawty_Summer_SFX chGnawtySummerCheeringSfx[] = { - {0.07f, 1.6f, SFX_56_BANJO_HUI, 32000}, - {0.17f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.22f, 1.6f, SFX_55_BANJO_HOO_2, 32000}, - {0.31f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.33f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, - {0.45f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.49f, 1.7f, SFX_55_BANJO_HOO_2, 32600}, - {0.6f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.63f, 1.7f, SFX_56_BANJO_HUI, 32600}, - {0.74f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.79f, 1.6f, SFX_54_BANJO_HOO_1, 32000}, - {0.9f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - 0 -}; - -CH_Gnawty_Summer_SFX chGnawtySummerRunningSfx[] = { - {0.01f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - {0.5f, 1.0f, SFX_10_BANJO_LANDING_07, 9000}, - 0 -}; - -enum chGnawtySummer_State_e { - CH_GNAWTY_SUMMER_STATE_0_NOT_INIT, - CH_GNAWTY_SUMMER_STATE_1_IDLE, - CH_GNAWTY_SUMMER_STATE_2_CHEERING, - CH_GNAWTY_SUMMER_STATE_3_RUNNING, - CH_GNAWTY_SUMMER_STATE_4_DESPAWN -}; - -/* .code */ -void chGnawtySummer_setState(Actor *this, s32 next_state) { - ActorProp *temp_v0; - - if (next_state == CH_GNAWTY_SUMMER_STATE_1_IDLE) { - skeletalAnim_set(this->unk148, ASSET_1A6_ANIM_GNAWTY_IDLE, 0.2f, 4.5f); - } - if (next_state == CH_GNAWTY_SUMMER_STATE_2_CHEERING) { - this->marker->propPtr->unk8_3 = false; - skeletalAnim_set(this->unk148, ASSET_1A7_ANIM_GNAWTY_CHEERING, 0.2f, 3.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - gcdialog_showDialog(VER_SELECT(ASSET_CD0_DIALOG_GNAWTY_COMPLETE_SUMMER, 0x9E5, 0, 0), 0x24, NULL, NULL, NULL, NULL); - } - if (next_state == CH_GNAWTY_SUMMER_STATE_3_RUNNING) { - skeletalAnim_set(this->unk148, ASSET_1A8_ANIM_GNAWTY_RUNNING, 0.2f, 0.5f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - if (next_state == CH_GNAWTY_SUMMER_STATE_4_DESPAWN) { - marker_despawn(this->marker); - } - this->state = next_state; -} - -void chGnawtySummer_update(Actor *this) { - CH_Gnawty_Summer_SFX *sfx_list; - f32 prev_progress; - f32 curr_progress; - f32 player_position[3]; - - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_1_IDLE); - if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY) != false) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); - } - if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) != false) { - marker_despawn(this->marker); - } - return; - } - - if (this->state == CH_GNAWTY_SUMMER_STATE_1_IDLE) { - sfx_list = chGnawtySummerIdleSfx; - } else if (this->state == CH_GNAWTY_SUMMER_STATE_2_CHEERING) { - sfx_list = chGnawtySummerCheeringSfx; - } else if (this->state == CH_GNAWTY_SUMMER_STATE_3_RUNNING) { - sfx_list = chGnawtySummerRunningSfx; - } else{ - sfx_list = NULL; - } - - if (sfx_list != NULL) { - skeletalAnim_getProgressRange(this->unk148, &prev_progress, &curr_progress); - while(sfx_list->sfxProgress > 0.0f){ - if (((prev_progress < sfx_list->sfxProgress) || (curr_progress < prev_progress)) - && (sfx_list->sfxProgress <= curr_progress)) - { - func_8030E878( - sfx_list->sfxId, - randf2(sfx_list->volume - 0.05, sfx_list->volume + 0.05), - randi2(sfx_list->sampleRate - 200, sfx_list->sampleRate + 100), - this->position, - 500.0f, - 1500.0f); - } - sfx_list++; - } - } - - if (this->state == CH_GNAWTY_SUMMER_STATE_1_IDLE) { - if (!this->has_met_before) { - player_getPosition(player_position); - if (ml_vec3f_distance(this->position, player_position) < 900.0f) { - gcdialog_showDialog(VER_SELECT(ASSET_CCF_DIALOG_GNAWTY_MEET_SUMMER, 0x9E4, 0, 0), 4, NULL, NULL, NULL, NULL); - this->has_met_before = TRUE; - } - } - - if (levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED) != false) { - chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_2_CHEERING); - } - } - - if (this->state == CH_GNAWTY_SUMMER_STATE_2_CHEERING){ - if((skeletalAnim_getLoopCount(this->unk148) > 0)) { - chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_3_RUNNING); - } - } - - if (this->state == CH_GNAWTY_SUMMER_STATE_3_RUNNING) { - actor_update_func_80326224(this); - if (0.99 < (f64) this->unk48) { - chGnawtySummer_setState(this, CH_GNAWTY_SUMMER_STATE_4_DESPAWN); - } - } -} diff --git a/src/CCW/ch/swimminggnawty.c b/src/CCW/ch/swimminggnawty.c deleted file mode 100644 index 2976ce50e..000000000 --- a/src/CCW/ch/swimminggnawty.c +++ /dev/null @@ -1,140 +0,0 @@ -// BanjoDecomp: CCW/ch/swimminggnawty.c -#include -#include "functions.h" -#include "variables.h" - -extern ParticleEmitter *func_802EDD8C(f32[3], f32, f32); - -typedef struct{ - s16 map_id; - s16 despawnIfJiggyCollected; - s16 dialog; -} CH_GNAWTY_SWIMMING_DIALOG; - -typedef struct{ - CH_GNAWTY_SWIMMING_DIALOG *dialog; - f32 unk4[3]; -} ActorLocal_CCW_6620; - -Actor *chGnawtySwimming_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chGnawtySwimming_update(Actor *this); - -/* .data */ -CH_GNAWTY_SWIMMING_DIALOG chGnawtySwimmingDialogs[] ={ - {MAP_43_CCW_SPRING, FALSE, VER_SELECT(ASSET_CCE_DIALOG_GNAWTY_MEET_SPRING, 0x09E3, 0, 0)}, - {MAP_45_CCW_AUTUMN, TRUE, VER_SELECT(ASSET_CD1_DIALOG_GNAWTY_MEET_FALL_OUTSIDE, 0x09E6, 0, 0)}, - {MAP_46_CCW_WINTER, TRUE, VER_SELECT(ASSET_CD3_DIALOG_GNAWTY_MEET_WINTER_OUTSIDE, 0x09E8, 0, 0)}, - { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion -}; - -enum chGnawtySwimming_State_e { - CH_GNAWTY_SWIMMING_STATE_0_NOT_INIT, - CH_GNAWTY_SWIMMING_STATE_1_SWIMMING -}; - -ActorInfo chGnawtySwimming = { - MARKER_1BD_GNAWTY_SWIMMING, ACTOR_2AA_GNAWTY_SWIMMING, ASSET_48F_MODEL_GNAWTY, - 0x0, NULL, - chGnawtySwimming_update, NULL, chGnawtySwimming_draw, - 0, 0, 2.2f, 0 -}; - -/* .code */ -void chGnawtySwimming_emitParticles(ActorMarker *marker) { - Actor *this; - ActorLocal_CCW_6620 *local; - ParticleEmitter *pCtrl; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_6620 *)&this->local; - - if (this->marker->unk14_21) { - if (0.65 < (f64) randf()) { - pCtrl = func_802EDD8C(local->unk4, 0.0f, this->position[1] + 500.0f); - particleEmitter_setStartingScaleRange(pCtrl, 0.04f, 0.05f); - particleEmitter_setFinalScaleRange(pCtrl, 0.18f, 0.2f); - particleEmitter_setSpawnPositionRange(pCtrl, -10.0f, 0.0f, -10.0f, 10.0f, 20.0f, 10.0f); - particleEmitter_setParticleVelocityRange(pCtrl, 0.0f, 31.0f, 0.0f, 0.0f, 37.0f, 0.0f); - particleEmitter_emitN(pCtrl, 1); - } - } -} - -void chGnawtySwimming_setState(Actor *this, s32 next_state) { - int i; - - if (next_state == CH_GNAWTY_SWIMMING_STATE_1_SWIMMING) { - skeletalAnim_set(this->unk148, 0x289, 0.2f, 1.1f); - for(i = 0; i < 10; i++){ - skeletalAnim_setCallback_1(this->unk148, randf(), (GenFunction_1)chGnawtySwimming_emitParticles, (uintptr_t)this->marker); - } - } - this->state = next_state; -} - - -Actor *chGnawtySwimming_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this; - ActorLocal_CCW_6620 *local; - - this = actor_draw(marker, gfx, mtx, vtx); - local = (ActorLocal_CCW_6620 *)&this->local; - if (this->marker->unk14_21) { - vec3fArray_get_vec3f(func_80329934(), 5, local->unk4); - } - return this; -} - -void chGnawtySwimming_update(Actor *this) { - ActorLocal_CCW_6620 *local; - f32 player_pos_1[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; - f32 player_pos_2[3]; - - local = (ActorLocal_CCW_6620 *)&this->local; - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - local->dialog = &chGnawtySwimmingDialogs[0]; - while(local->dialog->map_id != 0 && gsworld_getMap() != local->dialog->map_id){ - local->dialog++; - } - chGnawtySwimming_setState(this, CH_GNAWTY_SWIMMING_STATE_1_SWIMMING); - - if (jiggyscore_isCollected(JIGGY_4B_CCW_GNAWTY)) { - levelSpecificFlags_set(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED, true); - } - - if ((local->dialog->despawnIfJiggyCollected != false) - && levelSpecificFlags_get(LEVEL_FLAG_25_CCW_GNAWTY_JIGGY_COLLECTED)) - { - marker_despawn(this->marker); - } - - return; - } - - if (this->state == CH_GNAWTY_SWIMMING_STATE_1_SWIMMING && this->marker->unk14_21) { - player_getPosition(player_pos_1); - func_80258A4C( - this->position, this->yaw - 90.0f, player_pos_1, - &horizontal_distance, &distance_in_front, &side_angle_radian); - if (horizontal_distance > 100.0f) { - this->yaw += 30.0f * side_angle_radian; - } - } - if (!this->has_met_before) { - player_getPosition(player_pos_2); - if (ml_vec3f_distance(this->position, player_pos_2) < 900.0f) { - if (local->dialog->map_id != MAP_46_CCW_WINTER - || func_8028F2FC()) - { - gcdialog_showDialog(local->dialog->dialog, 4, NULL, NULL, NULL, NULL); - this->has_met_before = true; - } - } - } -} diff --git a/src/CCW/ch/vacationtexttrigger.c b/src/CCW/ch/vacationtexttrigger.c index dbf39717e..474616d49 100644 --- a/src/CCW/ch/vacationtexttrigger.c +++ b/src/CCW/ch/vacationtexttrigger.c @@ -39,7 +39,7 @@ void chVacationTextTrigger_update(Actor* this) { // Start dialog if player is within trigger if (__playerIsWithinTrigger(0, -107, 188) != 0) { - gcdialog_showDialog(VER_SELECT(ASSET_DA9_DIALOG_MUMBO_CCW_VACATION, 0x0A27, 0, 0), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(0xDA9, 4, NULL, NULL, NULL, NULL); volatileFlag_set(VOLATILE_FLAG_13_HAS_TRIGGERED_MUMBO_VACATION_TEXT, 1); } } diff --git a/src/CCW/ch/zubba.c b/src/CCW/ch/zubba.c new file mode 100644 index 000000000..d3367f084 --- /dev/null +++ b/src/CCW/ch/zubba.c @@ -0,0 +1,216 @@ +// BanjoDecomp: code_950.c +#include +#include "functions.h" +#include "variables.h" + +extern void func_8030DBFC(u8, f32, f32, f32); + +typedef struct{ + u8 sfxsourceIdx; + //u8 pad1[3]; + ActorMarker *unk4; + f32 unk8[3]; + f32 unk14; + f32 unk18; +}ActorLocal_CCW_950; + +void chwasp_update(Actor *this); + +/* .data */ +ActorInfo D_8038EBD0 = { MARKER_1AE_ZUBBA, ACTOR_29B_ZUBBA, ASSET_446_MODEL_ZUBBA, 0x0, NULL, chwasp_update, NULL, actor_draw, 0, 0, 1.0f, 0}; + +/* .code */ +void chwasp_setState(Actor *this, s32 next_state) { + ActorLocal_CCW_950 *local; + f32 sp50[3]; + f32 sp44[3]; + + local = (ActorLocal_CCW_950 *)&this->local; + local->unk18 = 0.0f; + if (next_state == 1) { + local->unk18 = 800.0f; + skeletalAnim_set(this->unk148, ASSET_16F_ANIM_ZUBBA_FLY_MOVE, 0.0f, 0.65f); + } + if (next_state == 2) { + skeletalAnim_set(this->unk148, ASSET_170_ANIM_ZUBBA_FLY_IDLE, 0.1f, 0.65f); + player_getPosition(sp50); + sp50[1] += 50.0f; + local->unk8[0] = sp50[0] - this->position[0]; + local->unk8[1] = sp50[1] - this->position[1]; + local->unk8[2] = sp50[2] - this->position[2]; + ml_vec3f_normalize(local->unk8); + if ((local->unk8[0] == 0.0f) && (local->unk8[1] == 0.0f) && (local->unk8[2] == 0.0f)) { + local->unk8[1] = -1.0f; + } + } + if (next_state == 3) { + sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); + func_80324D54(randf2(0.1f, 0.4f), 0x3FC, randf2(0.95f, 1.1f), 32000, this->position, 500.0f, 3000.0f); + actor_collisionOff(this); + } + if (next_state == 4) { + skeletalAnim_set(this->unk148, ASSET_171_ANIM_ZUBBA_DIE, 0.1f, 0.2f); + sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); + func_80324D54(0.1f, 0x66, randf2(1.6f, 1.7f), 32000, this->position, 500.0f, 3000.0f); + func_803867C8(local->unk4); + actor_collisionOff(this); + player_getPosition(sp44); + sp44[1] += 50.0f; + local->unk8[0] = this->position[0] - sp44[0]; + local->unk8[1] = this->position[1] - sp44[1]; + local->unk8[2] = this->position[2] - sp44[2]; + ml_vec3f_normalize(local->unk8); + if ((local->unk8[0] == 0.0f) && (local->unk8[1] == 0.0f) && (local->unk8[2] == 0.0f)) { + local->unk8[1] = -1.0f; + } + } + if (next_state == 5) { + func_8030E878(SFX_A_BANJO_LANDING_05, randf2(0.85f, 0.95f), 18000, this->position, 500.0f, 3000.0f); + skeletalAnim_set(this->unk148, ASSET_172_ANIM_ZUBBA_LAND, 0.0f, 1.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + } + if (next_state == 6) { + marker_despawn(this->marker); + } + if (next_state == 7) { + func_80386814(local->unk4); + marker_despawn(this->marker); + } + this->state = next_state; +} + + +void func_80387124(ActorMarker* marker, ActorMarker *other_marker) { + chwasp_setState(marker_getActor(marker), 3); +} + +void CCW_func_80387150(ActorMarker* marker, ActorMarker *other_marker) { + chwasp_setState(marker_getActor(marker), 4); +} + +void func_8038717C(Actor *this){ + ActorLocal_CCW_950 *local; + + local = (ActorLocal_CCW_950 *)&this->local; + sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); +} + +void chwasp_update(Actor *this) { + ActorLocal_CCW_950 *local; + f32 sp68; + Actor *other; + s32 sp60; + s32 sp5C; + f32 sp50[3]; + f32 sp4C; + f32 sp48; + f32 sp44; + f32 temp_f0; + f32 pad; + + + sp68 = time_getDelta(); + local = (ActorLocal_CCW_950 *)&this->local; + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->actorFreeFunc = func_8038717C; + local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); + local->unk4 = 0; + local->unk14 = 1000.0f; + sfxsource_setSfxId(local->sfxsourceIdx, 0x3FA); + sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); + sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); + sfxsource_setSampleRate(local->sfxsourceIdx, 0); + marker_setCollisionScripts(this->marker, func_80387124, NULL, CCW_func_80387150); + chwasp_setState(this, 1); + return; + } + if(local->unk4 == NULL) { + other = actorArray_findActorFromActorId(0x299); + if (other == NULL) { + marker_despawn(this->marker); + return; + } + local->unk4 = other->marker; + func_80386840(local->unk4, &sp60, &sp5C); + local->unk14 = (((f32)sp60 /(f32)sp5C) * 1000.0f) + 1000.0f; + } + + if (this->state == 1) { + temp_f0 = this->position[1]; + this->position[0] += 0.1 * sp68; + this->position[1] += local->unk18 * sp68; + if ((temp_f0 < 0.0f) && (this->position[1] >= 0.0f)) { + func_8030E878(SFX_A_BANJO_LANDING_05, randf2(1.0f, 1.1f), 18000, this->position, 500.0f, 3000.0f); + } + player_getPosition(sp50); + func_80258A4C(this->position, this->yaw - 90.0f, sp50, &sp4C, &sp48, &sp44); + this->yaw += 360.0f * sp44 * sp68; + if (this->position[1] > 150.0f) { + local->unk18 -= 2000.0f * sp68; + if (local->unk18 < 0.0f) { + chwasp_setState(this, 2); + } + } + } + + if (this->state == 2) { + if (local->unk18 < local->unk14) { + local->unk18 += (4.0f * local->unk14 * sp68); + } + this->position[0] += local->unk8[0] * local->unk18 * sp68; + this->position[1] += local->unk8[1] * local->unk18 * sp68; + this->position[2] += local->unk8[2] * local->unk18 * sp68; + if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) + || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) + || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) + ){ + chwasp_setState(this, 7); + } + } + + if (this->state == 3) { + this->position[1] += local->unk18 * sp68; + if (local->unk18 < local->unk14) { + local->unk18 += 2000.0f * sp68; + } + + if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) + || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) + || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) + ) { + chwasp_setState(this, 7); + } + } + + if (this->state == 4) { + this->position[0] += local->unk8[0] * 1000.0f * sp68; + this->position[1] -= local->unk18 * sp68; + this->position[2] += local->unk8[2] * 1000.0f * sp68; + if (local->unk18 < local->unk14) { + local->unk18 += (1000.0f * sp68); + } + if (this->position[1] <= 0.0f) { + this->position[1] = 0.0f; + chwasp_setState(this, 5); + } + } + + if (this->state == 5) { + this->position[1] -= 300.0f * sp68; + if (this->position[1] < -200.0f) { + chwasp_setState(this, 6); + } + } + + if(this->state); + if (this->state == 2) { + func_8030DBFC(local->sfxsourceIdx, 1.0f, 1.1f, 0.05f); + } else { + func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); + } + sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); + sfxsource_set_position(local->sfxsourceIdx, this->position); + sfxSource_func_8030E2C4(local->sfxsourceIdx); + sfxsource_setSampleRate(local->sfxsourceIdx, (s32) ((local->unk18 / local->unk14) * 10000.0f)); +} diff --git a/src/CCW/ch/zubba_hive_npc.c b/src/CCW/ch/zubba_hive_npc.c new file mode 100644 index 000000000..30c3a34ac --- /dev/null +++ b/src/CCW/ch/zubba_hive_npc.c @@ -0,0 +1,133 @@ +// BanjoDecomp: code_14B0.c +#include "functions.h" +#include "variables.h" +#include + +#include + +extern void func_8030DBFC(u8, f32, f32, f32); +extern void sfxsource_setSampleRate(u8, s32); + +typedef struct{ + s16 unk0; + u8 unk2; + u8 unk3; + s16 unk4; +}Struct_CCW_14B0_0; + +typedef struct { + u8 sfxsourceIdx; + // u8 pad1[3]; + Struct_CCW_14B0_0 *unk4; + f32 unk8; + f32 unkC[3]; + f32 unk18[3]; +}ActorLocal_CCW_14B0; + +void CCW_func_80387A40(Actor *this); + +/* .data */ +Struct_CCW_14B0_0 D_8038EC00[] = { + {MAP_5B_CCW_SPRING_ZUBBA_HIVE, 0x7, 0x4C, 0xCE1}, + {MAP_5C_CCW_AUTUMN_ZUBBA_HIVE, 0x8, 0x00, 0xCE5}, + 0 +}; + +ActorInfo D_8038EC14 = { 0x1AF, 0x29C, 0x446, 0x0, NULL, CCW_func_80387A40, NULL, actor_draw, 0, 0, 1.0f, 0}; + +/* .code */ +void func_803878A0(Actor *this, s32 next_state) { + ActorLocal_CCW_14B0 *local = (ActorLocal_CCW_14B0 *)&this->local; + int i; + + if (next_state == 1) { + if (skeletalAnim_getAnimId(this->unk148) != 0x16F) { + skeletalAnim_set(this->unk148, 0x16F, 0.1f, 0.65f); + } + for(i = 0; i < 10; i++){ + local->unkC[0] = randf2(-500.0f, 500.0f); + local->unkC[1] = randf2(400.0f, 900.0f); + local->unkC[2] = randf2(-400.0f, 700.0f); + if(ml_vec3f_distance(this->position, local->unkC) > 800.0f) + break; + } + local->unk8 = randf2(500.0f, 1000.0f); + } + this->state = next_state; +} + +void CCW_func_80387A20(Actor *this){ + ActorLocal_CCW_14B0 *local = (ActorLocal_CCW_14B0 *)&this->local; + sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); +} + +void CCW_func_80387A40(Actor *this) { + ActorLocal_CCW_14B0 *local; + f32 sp68; + f32 sp5C[3]; + f32 sp58; + f32 sp54; + f32 sp50; + f32 sp44[3]; + + local = (ActorLocal_CCW_14B0 *)&this->local; + sp68 = time_getDelta(); + if (!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->actorFreeFunc = CCW_func_80387A20; + local->unk4 = &D_8038EC00[0]; + while((local->unk4->unk0 != 0) && (gsworld_getMap() != local->unk4->unk0)) { + local->unk4++; + } + local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); + local->unk18[0] = local->unk18[1] = local->unk18[2] = 0.0f; + sfxsource_setSfxId(local->sfxsourceIdx, 0x3FA); + sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); + sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); + sfxsource_setSampleRate(local->sfxsourceIdx, 0); + func_803878A0(this, 1); + return; + } + + if (this->state == 1) { + sp5C[0] = local->unkC[0] - this->position[0]; + sp5C[1] = local->unkC[1] - this->position[1]; + sp5C[2] = local->unkC[2] - this->position[2]; + if (ml_vec3f_distance(this->position, local->unkC) < 500.0f) { + ml_vec3f_set_length(sp5C, local->unk8 * 8.0f); + } else { + ml_vec3f_set_length(sp5C, local->unk8 * 2); + } + this->position[0] += (local->unk18[0] * sp68) + (sp5C[0] * sp68 * sp68); + this->position[1] += (local->unk18[1] * sp68) + (sp5C[1] * sp68 * sp68); + this->position[2] += (local->unk18[2] * sp68) + (sp5C[2] * sp68 * sp68); + local->unk18[0] += sp5C[0] * sp68; + local->unk18[1] += sp5C[1] * sp68; + local->unk18[2] += sp5C[2] * sp68; + if (local->unk8 < LENGTH_VEC3F(local->unk18)) { + ml_vec3f_set_length(local->unk18, local->unk8); + } + func_80258A4C(this->position, this->yaw - 90.0f, local->unkC, &sp58, &sp54, &sp50); + this->yaw += 140.0f * sp50 * sp68; + if (ml_vec3f_distance(this->position, local->unkC) < 100.0f) { + func_803878A0(this, 1); + } + } + + if(this->position[0]); + + func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); + sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); + sfxsource_set_position(local->sfxsourceIdx, this->position); + sfxSource_func_8030E2C4(local->sfxsourceIdx); + sfxsource_setSampleRate(local->sfxsourceIdx, 2000.0f + 8000.0f*(LENGTH_VEC3F(local->unk18)/ local->unk8)); + if (!mapSpecificFlags_get(local->unk4->unk2)) { + player_getPosition(sp44); + if (sp44[2] > -600.0f) { + if (!local->unk4->unk3 || !jiggyscore_isCollected(local->unk4->unk3) ) { + gcdialog_showDialog(local->unk4->unk4, 4, NULL, NULL, NULL, NULL); + mapSpecificFlags_set(local->unk4->unk2, true); + } + } + } +} diff --git a/src/CCW/ch/zubbadoor.c b/src/CCW/ch/zubbadoor.c index b8f6d1a26..3ec863763 100644 --- a/src/CCW/ch/zubbadoor.c +++ b/src/CCW/ch/zubbadoor.c @@ -3,31 +3,14 @@ #include "functions.h" #include "variables.h" -void chZubbaDoor_update(Actor *this); +void func_803864B8(Actor *this); -ActorInfo chZubbaDoorSummer = { - MARKER_1AC_ZUBBA_DOOR, ACTOR_298_ZUBBA_DOOR_SUMMER, ASSET_444_MODEL_CCW_ZUBBA_DOOR, - 0x0, NULL, - chZubbaDoor_update, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chZubbaDoorAutumn = { - MARKER_1AC_ZUBBA_DOOR, ACTOR_29A_ZUBBA_DOOR_AUTUMN, ASSET_445_MODEL_CCW_ZUBBA_DOOR, - 0x0, NULL, - chZubbaDoor_update, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -enum chZubbaDoor_State_e { - CH_ZUBBA_DOOR_STATE_0_NOT_INIT, - CH_ZUBBA_DOOR_STATE_1_IDLE, - CH_ZUBBA_DOOR_STATE_2_DESPAWN -}; +ActorInfo D_8038EB50 = { 0x1AC, 0x298, 0x444, 0x0, NULL, func_803864B8, NULL, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038EB74 = { 0x1AC, 0x29A, 0x445, 0x0, NULL, func_803864B8, NULL, actor_draw, 0, 0, 0.0f, 0}; /* .code */ -void chZubbaDoor_setState(Actor *this, s32 next_state){ - if(next_state == CH_ZUBBA_DOOR_STATE_2_DESPAWN){ +void CCW_func_803863F0(Actor *this, s32 next_state){ + if(next_state == 2){ sfx_playFadeShorthandDefault(SFX_2F_ORANGE_SPLAT, 1.0f, 32000, this->position, 500, 3000); levelSpecificFlags_set(LEVEL_FLAG_10_CCW_BREAK_ZUBBA_DOOR, true); marker_despawn(this->marker); @@ -37,19 +20,17 @@ void chZubbaDoor_setState(Actor *this, s32 next_state){ void chZubbaDoor_die(ActorMarker* marker, ActorMarker *arg1) { Actor* actor = marker_getActor(marker); - if (actor->state == CH_ZUBBA_DOOR_STATE_1_IDLE - && gsworld_getMap() == MAP_44_CCW_SUMMER) - { - chZubbaDoor_setState(actor, CH_ZUBBA_DOOR_STATE_2_DESPAWN); + if (actor->state == 1 && gsworld_getMap() == MAP_44_CCW_SUMMER) { + CCW_func_803863F0(actor, 2); } } -void chZubbaDoor_update(Actor *this){ +void func_803864B8(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; this->marker->propPtr->unk8_3 = true; marker_setCollisionScripts(this->marker, NULL, NULL, chZubbaDoor_die); - chZubbaDoor_setState(this, CH_ZUBBA_DOOR_STATE_1_IDLE); + CCW_func_803863F0(this, 1); if (levelSpecificFlags_get(LEVEL_FLAG_10_CCW_BREAK_ZUBBA_DOOR)) { marker_despawn(this->marker); diff --git a/src/CCW/ch/zubbahoneylump.c b/src/CCW/ch/zubbahoneylump.c deleted file mode 100644 index e9180e887..000000000 --- a/src/CCW/ch/zubbahoneylump.c +++ /dev/null @@ -1,244 +0,0 @@ -// BanjoDecomp: CCW/ch/zubbahoneylump.c -#include -#include "core1/core1.h" -#include "functions.h" -#include "variables.h" - - - -typedef struct{ - ActorMarker *jiggyMarker; - s32 spawnedZubbaCount; - s32 zubbasDefeated; - f32 unkC; // time related -}ActorLocal_CCW_160; - -void chZubbaFight_setState(Actor *this, s32 next_state); -void chZubbaFight_update(Actor *this); - -/* .data */ -ActorInfo chZubbaHoneyLump = { - MARKER_1AD_ZUBBA_HONEY_LUMP, ACTOR_299_ZUBBA_HONEY_LUMP, ASSET_443_MODEL_ZUBBA_HONEY_LUMP, - 0x0, NULL, - chZubbaFight_update, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -enum chZubbaFight_State_e { - CH_ZUBBA_FIGHT_STATE_0_NOT_INIT, - CH_ZUBBA_FIGHT_STATE_1_IDLE, - CH_ZUBBA_FIGHT_STATE_2_DIALOG, - CH_ZUBBA_FIGHT_STATE_3_FIGHT, - CH_ZUBBA_FIGHT_STATE_4_FIGHT_COMPLETE -}; - -#define NUM_OF_ZUBBAS_TO_DEFEAT 10 - -/* .code */ -void chZubbaFight_jiggy(ActorMarker *marker){ - Actor *this; - ActorLocal_CCW_160 *local; - - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - this->unk124_11 = 2; - this->alpha_124_19 = 0xFF; - if (local->jiggyMarker != NULL) { - actor_collisionOn(marker_getActor(local->jiggyMarker)); - } - coMusicPlayer_playMusic(COMUSIC_3D_JIGGY_SPAWN, 28000); -} - -void chZubbaFight_startFightDialog(ActorMarker* marker, enum asset_e text_id, s32 arg2) { - chZubbaFight_setState(marker_getActor(marker), CH_ZUBBA_FIGHT_STATE_3_FIGHT); -} - -void chZubbaFight_setState(Actor *this, s32 next_state) { - ActorLocal_CCW_160 *local; - - local = (ActorLocal_CCW_160 *)&this->local; - local->unkC = 0.0f; - if (next_state == CH_ZUBBA_FIGHT_STATE_2_DIALOG) { - if (!volatileFlag_getAndSet(VOLATILE_FLAG_B5, 1)) { - gcdialog_showDialog( - VER_SELECT(ASSET_CE2_DIALOG_ZUBBA_MEET_SUMMER, 0x09F7, 0, 0), 4, NULL, this->marker, chZubbaFight_startFightDialog, NULL); - } else { - gcdialog_showDialog(VER_SELECT(ASSET_CE3_DIALOG_ZUBBA_RETURN, 0x09F8, 0, 0), 4, NULL, NULL, NULL, NULL); - chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_3_FIGHT); - return; - } - } - - if (next_state == CH_ZUBBA_FIGHT_STATE_3_FIGHT) { - local->unkC = 0.1f; - func_8025A58C(0, 4000); - coMusicPlayer_playMusic(COMUSIC_4B_CCW_ZUBBA_FIGHT, 30000); - } - - if (next_state == CH_ZUBBA_FIGHT_STATE_4_FIGHT_COMPLETE) { - if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - item_set(ITEM_6_HOURGLASS, false); - volatileFlag_set(VOLATILE_FLAG_3, 0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 1); - } else { - gcdialog_showDialog(VER_SELECT(ASSET_CE4_DIALOG_ZUBBA_COMPLETE, 0x09F9, 0, 0), 4, NULL, NULL, NULL, NULL); - func_8025A58C(-1, 400); - comusic_8025AB44(COMUSIC_4B_CCW_ZUBBA_FIGHT, 0, 400); - func_8025AABC(COMUSIC_4B_CCW_ZUBBA_FIGHT); - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(2.0f, 4); - timedFunc_set_1(2.0f, (GenFunction_1)chZubbaFight_jiggy, (uintptr_t)this->marker); - timed_exitStaticCamera(4.0f); - func_80324E38(4.0f, 0); - } - } - this->state = next_state; -} - -void chZubbaFight_zubbaKilled(ActorMarker *marker){ - Actor *this; - ActorLocal_CCW_160 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - local->zubbasDefeated++; - local->spawnedZubbaCount--; - if(local->zubbasDefeated == NUM_OF_ZUBBAS_TO_DEFEAT){ - chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_4_FIGHT_COMPLETE); - } -} - -void chZubbaFight_zubbaDisappear(ActorMarker *marker){ - Actor *this; - ActorLocal_CCW_160 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - local->spawnedZubbaCount--; -} - -void chZubbaFight_zubbaScore(ActorMarker *marker, s32 *score, s32 *total){ - Actor *this; - ActorLocal_CCW_160 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_160 *)&this->local; - - *score = local->zubbasDefeated; - *total = NUM_OF_ZUBBAS_TO_DEFEAT; -} - -void chZubbaFight_update(Actor *this) { - ActorLocal_CCW_160 *local; - f32 time_delta; - Actor *jiggy_actor; - f32 sp78[3]; - f32 sp6C[3]; - s32 pad68; - f32 player_position_1[3]; - s32 phi_s0; - f32 sp4C[3]; - f32 player_position_2[3]; - s32 phi_v0; - f32 tmp; - - time_delta = time_getDelta(); - local = (ActorLocal_CCW_160 *)&this->local; - if(!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = true; - local->jiggyMarker = (ActorMarker *)(uintptr_t)1; // [port] full pointer-width sentinel write - local->spawnedZubbaCount = 0; - local->zubbasDefeated = 0; - local->unkC = 0.0f; - if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - this->position_y -= 300.0f; - } - chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_1_IDLE); - return; - } - if ((uintptr_t)local->jiggyMarker == 1) { - jiggy_actor = actorArray_findActorFromActorId(ACTOR_46_JIGGY); - if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { - local->jiggyMarker = NULL; - if (jiggy_actor != NULL) { - actor_collisionOff(jiggy_actor); - jiggy_actor->position[1] -= 300.0f; - } - } else if (jiggy_actor != NULL) { - local->jiggyMarker = jiggy_actor->marker; - actor_collisionOff(jiggy_actor); - if (jiggyscore_isCollected(JIGGY_4C_CCW_ZUBBAS) != 0) { - marker_despawn(local->jiggyMarker); - marker_despawn(this->marker); - } - } else { - marker_despawn(this->marker); - } - return; - } - - if (local->jiggyMarker != NULL) { - jiggy_actor = marker_getActor(local->jiggyMarker); - viewport_getPosition_vec3f(sp78); - sp6C[0] = this->position[0] - sp78[0]; - sp6C[1] = this->position[1] - sp78[1]; - sp6C[2] = this->position[2] - sp78[2]; - sp6C[1] = 0.0f; - ml_vec3f_set_length(sp6C, 20.0f); - jiggy_actor->position[0] = this->position[0] + sp6C[0]; - jiggy_actor->position[1] = this->position[1] + sp6C[1]; - jiggy_actor->position[2] = this->position[2] + sp6C[2]; - } - if (ml_timer_update(&local->unkC, time_delta)) { - if ((local->spawnedZubbaCount < 3) && ((local->zubbasDefeated + local->spawnedZubbaCount) < 10)) { - player_getPosition(player_position_1); - for(phi_s0 = 0; phi_s0 < 20; phi_s0++){ - sp4C[0] = randf2(-500.0f, 500.0f); - sp4C[1] = -100.0f; - sp4C[2] = randf2(-500.0f, 900.0f); - - if(ml_vec3f_distance(this->position, sp4C) < 400.0f) - continue; - - tmp = ml_vec3f_distance(player_position_1, sp4C); - phi_v0 = (phi_s0 < 0xA) ? 500 : 200; - if(tmp < (f32) phi_v0) - continue; - - if(viewport_isPointOutsideFrustum_3f(sp4C[0], 0.0f, sp4C[2])) - break; - - } - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_29B_ZUBBA, reinterpret_cast(s32, sp4C[0]), reinterpret_cast(s32, sp4C[1]), reinterpret_cast(s32, sp4C[2])); - local->spawnedZubbaCount++; - } - local->unkC = randf2(0.5 - ((local->zubbasDefeated / 10) * 0.4), 1.0 - ((local->zubbasDefeated / 10) * 0.8)); - } - if (this->state == CH_ZUBBA_FIGHT_STATE_1_IDLE) { - if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) - && volatileFlag_get(VOLATILE_FLAG_3)) - { - item_set(ITEM_6_HOURGLASS, 1); - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(1800, 1500, 1, 1) - 1); - chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_3_FIGHT); - } else if ((local->jiggyMarker != NULL) && (gsworld_getMap() == MAP_5A_CCW_SUMMER_ZUBBA_HIVE)) { - player_getPosition(player_position_2); - if ((ml_vec3f_distance(this->position, player_position_2) < 300.0f) - && (player_getTransformation() == TRANSFORM_1_BANJO)) - { - chZubbaFight_setState(this, CH_ZUBBA_FIGHT_STATE_2_DIALOG); - } - } - } - if ((this->state == CH_ZUBBA_FIGHT_STATE_3_FIGHT) - && volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) - && item_empty(ITEM_0_HOURGLASS_TIMER)) - { - item_set(ITEM_6_HOURGLASS, 0); - volatileFlag_set(VOLATILE_FLAG_3, 0); - volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); - } -} diff --git a/src/CCW/checksums.c b/src/CCW/checksums.c deleted file mode 100644 index 11836811f..000000000 --- a/src/CCW/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: CCW/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsCCW; diff --git a/src/CCW/eyrie_baby.c b/src/CCW/eyrie_baby.c deleted file mode 100644 index 50c384f8e..000000000 --- a/src/CCW/eyrie_baby.c +++ /dev/null @@ -1,382 +0,0 @@ -// BanjoDecomp: code_3310.c -#include -#include "functions.h" -#include "variables.h" -#include "port/Patches/Patches.h" - -typedef struct { - f32 unk0; - s16 unk4; - f32 unk8; - s16 unkC; -} Eyrie_Baby_SFX; - -typedef struct { - s16 map_id; - s16 requiredFileProgress; - s16 unlocksFileProgress; - s16 waitingAnimation; - Eyrie_Baby_SFX *waitingSFX; - s16 nextStateWhenComplete; // Probably only used for Spring - s16 yawningAnimation; - Eyrie_Baby_SFX *yawnSFX; - s16 goingToSleepAnimation; - // u8 pad16[2]; - Eyrie_Baby_SFX *goingToSleepSFX; - s16 sleepingAnimation; - // u8 pad1E[0x2]; - Eyrie_Baby_SFX *sleepingSFX; - u8 cameraNode; - u8 caterpillarRequirement; - s16 eatingAnimation; - s16 meetDialog; - // u8 pad2A[2]; -} Eyrie_Baby_Dialog; - -typedef struct { - Eyrie_Baby_Dialog *progression; - u8 eatenCount; - //u8 pad5[3]; - Eyrie_Baby_SFX *sfx; - s32 unkC[3]; // something about player position? -} ActorLocal_CCW_3310; - -Actor *chEyrieBaby_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chEyrieBaby_update(Actor *this); - -/* .data */ -enum cheyriebaby_state_e { - CH_EYRIE_BABY_STATE_0_NOT_HATCHED, - CH_EYRIE_BABY_STATE_1_IDLE, - CH_EYRIE_BABY_STATE_2_YAWNING, - CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP, - CH_EYRIE_BABY_STATE_4_SLEEPING, - CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS -}; - -Eyrie_Baby_SFX chEyrieBabyWaitingSFX[] = { - {0.11f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, - {0.22f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, - {0.34f, SFX_4A_CLUCKER_AHH, 1.1f, 25000}, - {0.55f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, - {0.65f, SFX_2_CLAW_SWIPE, 1.0f, 26000}, - {0.77f, SFX_2_CLAW_SWIPE, 1.1f, 25000}, - {0.87f, SFX_2_CLAW_SWIPE, 1.0f, 24000}, - 0 -}; - -Eyrie_Baby_SFX chEyrieBabyYawnSFX[] = { - {0.1f, SFX_80_YUMYUM_CLACK, 0.9f, 15000}, - {0.25f, SFX_4C_LIP_SMACK, 1.0f, 15000}, - {0.31f, SFX_4C_LIP_SMACK, 0.9f, 15000}, - {0.38f, SFX_4C_LIP_SMACK, 1.0f, 15000}, - {0.48f, SFX_4C_LIP_SMACK, 0.9f, 15000}, - {0.55f, SFX_97_BLUBBER_BURPS, 0.9f, 32700}, - {0.6f , SFX_2C_PULLING_NOISE, 0.7f, 25000}, - {0.73f, SFX_2C_PULLING_NOISE, 0.8f, 27000}, - {0.85f, SFX_2C_PULLING_NOISE, 0.9f, 29000}, - 0 -}; - -Eyrie_Baby_SFX chEyrieBabyGoingToSleepSFX[] = { - {0.2f , SFX_105_EYRIE_YAWN, 1.1f, 25000}, - {0.27f, SFX_105_EYRIE_YAWN, 1.0f, 25000}, - {0.35f, SFX_105_EYRIE_YAWN, 0.9f, 25000}, - {0.6f , SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, - {0.66f, SFX_106_EYRIE_LIPSMACK, 0.9f, 23000}, - {0.83f, SFX_1D_HITTING_AN_ENEMY_1, 0.7f, 27000}, - 0 -}; - -Eyrie_Baby_SFX chEyrieBabySleepingSFX[] = { - {0.2f , SFX_5D_BANJO_RAAOWW, 1.0f, 25000}, - {0.72f, SFX_5E_BANJO_PHEWWW, 1.0f, 25000}, - 0 -}; - -Eyrie_Baby_SFX chEyrieBabyEatingSFX[] = { - {0.95f, SFX_106_EYRIE_LIPSMACK, 1.0f, 25000}, - 0 -}; - -Eyrie_Baby_Dialog chEyrieBabyProgression[] = { - { - MAP_43_CCW_SPRING, // Map - 0, FILEPROG_E6_SPRING_EYRIE_HATCHED, // File Progress - 0, NULL, // Waiting - CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP, // Unk - 0, NULL, // Yawning - 0x18F, chEyrieBabyGoingToSleepSFX, // Going To Sleep - 0x190, chEyrieBabySleepingSFX, // Sleeping - 0, // Camera Node - 0, // Caterpillar Requirement - 0, // Eating Animation - 0 // Meet Dialog - }, - { - MAP_44_CCW_SUMMER, // Map - FILEPROG_E6_SPRING_EYRIE_HATCHED, FILEPROG_E7_SUMMER_EYRIE_FED, // File Progress - 0x191, chEyrieBabyWaitingSFX, // Waiting - CH_EYRIE_BABY_STATE_2_YAWNING, // Unk - 0x192, chEyrieBabyYawnSFX, // Yawning - 0x193, chEyrieBabyGoingToSleepSFX, // Going To Sleep - 0x194, chEyrieBabySleepingSFX, // Sleeping - 2, // Camera Node - 5, // Caterpillar Requirement - 0x21A, // Eating Animation - VER_SELECT(ASSET_CD7_DIALOG_BABY_EYRIE_MEET_SUMMER, 0x09EC, 0, 0) // Meet Dialog - }, - { - MAP_45_CCW_AUTUMN, // Map - FILEPROG_E7_SUMMER_EYRIE_FED, FILEPROG_E8_AUTMN_EYRIE_FED, // File Progress - 0x195, chEyrieBabyWaitingSFX, // Waiting - CH_EYRIE_BABY_STATE_2_YAWNING, // Unk - 0x196, chEyrieBabyYawnSFX, // Yawning - 0x197, chEyrieBabyGoingToSleepSFX, // Going To Sleep - 0x198, chEyrieBabySleepingSFX, // Sleeping - 4, // Camera Node - 10, // Caterpillar Requirement - 0x21B, // Eating Animation - VER_SELECT(ASSET_CDA_DIALOG_BABY_EYRIE_MEET_FALL, 0x09EF, 0, 0) // Meet Dialog - }, - { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion -}; - -ActorInfo chEyrieBaby = { - MARKER_1B4_EEYRIE_BABY, ACTOR_2A1_EEYRIE_BABY, ASSET_484_MODEL_EAGLE_BABY, - 0x0, NULL, - chEyrieBaby_update, NULL, chEyrieBaby_draw, - 0, 0, 0.0f, 0 -}; - -/* .bss */ -f32 chEyrieBabyThrowPosition[3]; - -/* .code */ -void func_80389700(ActorMarker *marker, enum asset_e text_id, s32 arg2) { - timed_exitStaticCamera(0.5f); - func_80324E38(0.5f, 0); -} - -void func_80389740(ActorMarker *marker) { - Actor *this = marker_getActor(marker); - if (this->marker->unk14_21) { - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x30C, reinterpret_cast(s32, chEyrieBabyThrowPosition[0]), reinterpret_cast(s32, chEyrieBabyThrowPosition[1]), reinterpret_cast(s32, chEyrieBabyThrowPosition[2])); - } -} - -void chEyrieBaby_saysMama() { - func_8030E6D4(SFX_18C_EYRIE_MAMA); -} - -void chEyrieBaby_setState(Actor *this, s32 next_state) { - ActorLocal_CCW_3310 *local; - - local = (ActorLocal_CCW_3310 *)&this->local; - local->sfx = NULL; - if (next_state == CH_EYRIE_BABY_STATE_1_IDLE) { - if (local->progression->waitingAnimation != NULL) { - skeletalAnim_set(this->unk148, local->progression->waitingAnimation, 0.2f, 6.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - } - local->sfx = local->progression->waitingSFX; - } - if ((this->state == CH_EYRIE_BABY_STATE_1_IDLE) - && (next_state == CH_EYRIE_BABY_STATE_2_YAWNING)) { - fileProgressFlag_set(local->progression->unlocksFileProgress, true); - } - if (next_state == CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS) { - func_8028F784(1); - skeletalAnim_set(this->unk148, local->progression->eatingAnimation, 0.2f, 2.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - local->sfx = &chEyrieBabyEatingSFX[0]; - } - - if (next_state == CH_EYRIE_BABY_STATE_2_YAWNING) { - skeletalAnim_set(this->unk148, local->progression->yawningAnimation, 0.2f, 8.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - func_80324E38(0.5f, 3); - timed_setStaticCameraToNode(0.5f, local->progression->cameraNode); - timed_exitStaticCamera(16.5f); - func_80324E38(16.5f, 0); - local->sfx = local->progression->yawnSFX; - } - if (next_state == CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP) { - actor_collisionOff(this); - skeletalAnim_set(this->unk148, local->progression->goingToSleepAnimation, 0.5f, 8.5f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if (local->progression->map_id == MAP_43_CCW_SPRING) { - gcdialog_showDialog(VER_SELECT(ASSET_CD6_DIALOG_BABY_EYRIE_HATCH, 0x09EB, 0, 0), 4, NULL, NULL, NULL, NULL); - skeletalAnim_setCallback_0(this->unk148, 0.65f, &chEyrieBaby_saysMama); - } - if (local->progression->map_id == MAP_44_CCW_SUMMER) { - gcdialog_showDialog(VER_SELECT(ASSET_CD9_DIALOG_BABY_EYRIE_COMPLETE_SUMMER, 0x09EE, 0, 0), 4, NULL, NULL, NULL, NULL); - } - if (local->progression->map_id == MAP_45_CCW_AUTUMN) { - gcdialog_showDialog(VER_SELECT(ASSET_CDB_DIALOG_BABY_EYRIE_COMPLETE_FALL, 0x09F0, 0, 0), 4, NULL, NULL, NULL, NULL); - } - local->sfx = local->progression->goingToSleepSFX; - } - if (next_state == CH_EYRIE_BABY_STATE_4_SLEEPING) { - func_8028F784(0); - skeletalAnim_set(this->unk148, local->progression->sleepingAnimation, 0.2f, 6.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); - skeletalAnim_setCallback_1(this->unk148, 0.2f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.4f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.72f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.82f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.92f, (GenFunction_1)func_80389740, (uintptr_t)this->marker); - local->sfx = local->progression->sleepingSFX; - } - this->state = next_state; -} - -Actor *chEyrieBaby_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor *this; - ActorLocal_CCW_3310 *local; - - this = marker_getActor(marker); - local = (ActorLocal_CCW_3310 *)&this->local; - if( (this->state == CH_EYRIE_BABY_STATE_0_NOT_HATCHED) - || ((this->state == CH_EYRIE_BABY_STATE_1_IDLE) - && (local->progression->waitingAnimation == NULL)) - ) { - return this; - } - modelRender_setAppendageVisibility(3, (this->state == CH_EYRIE_BABY_STATE_4_SLEEPING) ? 2 : 1); - actor_draw(marker, gfx, mtx, vtx); - vec3fArray_get_vec3f(func_80329934(), 5, chEyrieBabyThrowPosition); - return this; -} - -void func_80389BD8(f32 dst[3]){ - dst[0] = chEyrieBabyThrowPosition[0]; - dst[1] = chEyrieBabyThrowPosition[1]; - dst[2] = chEyrieBabyThrowPosition[2]; -} - -void chEyrieBaby_update(Actor *this) { - Eyrie_Baby_SFX *iPtr; - ActorLocal_CCW_3310 *local; - f32 sp5C; - f32 sp58; - f32 player_position[3]; - - local = (ActorLocal_CCW_3310 *)&this->local; - - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->propPtr->unk8_3 = true; - this->has_met_before = false; - this->position[0] = -4900.0f; - this->position[1] = 4619.0f; - this->position[2] = 0.0f; - chEyrieBabyThrowPosition[0] = this->position[0]; - chEyrieBabyThrowPosition[1] = this->position[1]; - chEyrieBabyThrowPosition[2] = this->position[2]; - if (this->state == CH_EYRIE_BABY_STATE_0_NOT_HATCHED) { - local->eatenCount = (u32)port_puzzleCount_get(ANCHOR_COUNT_CCW_EYRIE_FED); - } - local->progression = &chEyrieBabyProgression[0]; - while(local->progression->map_id != NULL && gsworld_getMap() != local->progression->map_id){ - local->progression++; - } - - if ((local->progression->requiredFileProgress != NULL) - && !fileProgressFlag_get(local->progression->requiredFileProgress)) - { - marker_despawn(this->marker); - } else if (!fileProgressFlag_get(local->progression->unlocksFileProgress)) { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_1_IDLE); - } else { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_4_SLEEPING); - } - - if (jiggyscore_isSpawned(JIGGY_49_CCW_EYRIE) != false) { - marker_despawn(this->marker); - } - return; - } - - if (local->sfx) { - skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); - for(iPtr = local->sfx; iPtr->unk0 > 0.0f; iPtr ++){ - if ((sp5C < iPtr->unk0) && (iPtr->unk0 <= sp58)) { - func_8030E878((s32) iPtr->unk4, randf2(iPtr->unk8 - 0.05, iPtr->unk8 + 0.05), iPtr->unkC, this->position, 500.0f, 2500.0f); - } - } - } - if (this->state == CH_EYRIE_BABY_STATE_1_IDLE) { - player_getPosition(player_position); - if( !this->has_met_before - && (local->unkC[2] >= 6500) - && (player_position[2] < 6500.0f) - && (local->progression->meetDialog != NULL) - ){ - this->has_met_before = true; - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, local->progression->cameraNode); - func_80324DBC(0.0f, local->progression->meetDialog, 6, NULL, this->marker, func_80389700, NULL); - } - local->unkC[0] = (s32) player_position[0]; - local->unkC[1] = (s32) player_position[1]; - local->unkC[2] = (s32) player_position[2]; - if (item_getCount(ITEM_22_CATERPILLAR) == 0) { - func_8028F784(0); - } - if ((local->progression->map_id != MAP_43_CCW_SPRING) - && ((this->position[0] + 500.0f) < player_position[0])) - { - player_setCarryObjectPoseInCylinder(this->position, 1110.0f, 200.0f, ACTOR_2A2_CATERPILLAR, &this); - if ((local->progression->yawningAnimation != NULL) - && (carriedObj_getActorId() == ACTOR_2A2_CATERPILLAR) - && (ml_vec3f_distance(this->position, player_position) < 1010.0f) - && (player_throwCarriedObject() != 0)) - { - player_setThrowTargetPosition(chEyrieBabyThrowPosition); - if ((local->progression->map_id == MAP_44_CCW_SUMMER) - && (local->eatenCount == 0)) - { - gcdialog_showDialog(VER_SELECT(ASSET_CD8_DIALOG_BABY_EYRIE_CHECK_SUMMER, 0x09ED, 0, 0), 4, NULL, NULL, NULL, NULL); - } - port_puzzleCount_add(ANCHOR_COUNT_CCW_EYRIE_FED, 1); - local->eatenCount = (u32)port_puzzleCount_get(ANCHOR_COUNT_CCW_EYRIE_FED); - if (local->eatenCount < local->progression->caterpillarRequirement) { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS); - } else { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_2_YAWNING); - } - } - } - // Anchor: teammate fed a worm — play the interim eat animation; final feed handled below. - if (this->state == CH_EYRIE_BABY_STATE_1_IDLE) { - s32 sharedFed = port_puzzleCount_get(ANCHOR_COUNT_CCW_EYRIE_FED); - if (sharedFed > (s32)local->eatenCount) { - local->eatenCount = (u32)sharedFed; - if ((s32)local->eatenCount < (s32)local->progression->caterpillarRequirement) { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS); - } - } - } - if (this->state == CH_EYRIE_BABY_STATE_1_IDLE && fileProgressFlag_get(local->progression->unlocksFileProgress)) { - // Anchor: fed flag synced from a teammate — skip to sleep state (spring keeps its hatch cutscene). - chEyrieBaby_setState(this, (local->progression->map_id == MAP_43_CCW_SPRING) ? local->progression->nextStateWhenComplete : CH_EYRIE_BABY_STATE_4_SLEEPING); - } - } - if ((this->state == CH_EYRIE_BABY_STATE_2_YAWNING) - && (skeletalAnim_getLoopCount(this->unk148) > 0)) - { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP); - } - if ((this->state == CH_EYRIE_BABY_STATE_3_GOING_TO_SLEEP) - && (skeletalAnim_getLoopCount(this->unk148) > 0)) - { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_4_SLEEPING); - } - if ((this->state == CH_EYRIE_BABY_STATE_5_EATING_CATERPILLARS) - && (skeletalAnim_getLoopCount(this->unk148) > 0)) - { - chEyrieBaby_setState(this, CH_EYRIE_BABY_STATE_1_IDLE); - } -} diff --git a/src/CCW/flower.c b/src/CCW/flower.c new file mode 100644 index 000000000..376fdf2be --- /dev/null +++ b/src/CCW/flower.c @@ -0,0 +1,170 @@ +// BanjoDecomp: code_1B20.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + s16 unk0; + u8 unk2; + u8 unk3; + s16 unk4; + s16 unk6; + s16 unk8; // enum file_progress_e + s16 unkA; +}Struct_CCW_1B20_0; + +typedef struct{ + Struct_CCW_1B20_0 *unk0; +}ActorLocal_CCW_1B20; + +void func_80387F64(Actor *this, s32 next_state); +Actor *CCW_func_803882F4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_80388478(Actor *this); + +/* .data */ +Struct_CCW_1B20_0 D_8038EC40[4] ={ + {0x173, 4, 0, 0x173, 0x181, 0xE3, 0}, + {0x181, 1, 1, 0x174, 0x182, 0xE4, 0}, + {0x182, 1, 1, 0x175, 0x183, 0xE5, 1}, + {0x183, 1, 1, 0x000, 0x000, 0x00, 0} +}; + +ActorInfo D_8038EC70 = { 0x1B0, 0x29D, 0x447, 0x0, NULL, func_80388478, NULL, CCW_func_803882F4, 0, 0, 1.0f, 0}; +f32 D_8038EC94[3] = {200.0f, 2120.0f, -5570.0f}; + +/* .code */ +void func_80387F10() { + jiggy_spawn(JIGGY_4D_CCW_FLOWER, D_8038EC94); +} + +void func_80387F38(ActorMarker* marker, s32 arg1) { + func_80387F64(marker_getActor(marker), arg1); +} + +void func_80387F64(Actor *this, s32 next_state){ + ActorLocal_CCW_1B20 *local; + f32 phi_f22; + + local = (ActorLocal_CCW_1B20 *)&this->local; + + if (next_state == 1) { + this->marker->propPtr->unk8_3 = local->unk0->unk3; + skeletalAnim_set(this->unk148, local->unk0->unk0, 0.0f, 5.0f); + skeletalAnim_setBehavior(this->unk148, local->unk0->unk2); + } + if (next_state == 2) { + if (gsworld_getMap() == MAP_43_CCW_SPRING) { + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + } + fileProgressFlag_set(local->unk0->unk8, true); + skeletalAnim_set(this->unk148, local->unk0->unk4, 0.0f, 6.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); + if (gsworld_getMap() == MAP_43_CCW_SPRING) { + func_80324E38(0.0f, 3); + } + timed_setStaticCameraToNode(0.0f, 0); + for( phi_f22 = 0.0f; phi_f22 <= 1.0f; phi_f22 += 0.1) { + timed_playSfx(phi_f22 * 5.7, 0x2C, phi_f22 * 0.3 + 0.7, (s32) (32000.0f - phi_f22 * 5000.0f)); + } + if (local->unk0->unkA != 0) { + timed_setStaticCameraToNode(6.0f, 1); + timedFunc_set_0(6.1f, (GenFunction_0)func_80387F10); + timedFunc_set_2(8.0f, (GenFunction_2)func_80387F38, (uintptr_t)this->marker, 3); + } else { + if (gsworld_getMap() == MAP_43_CCW_SPRING) { + timed_exitStaticCamera(7.0f); + func_80324E38(7.0f, 0); + } + timedFunc_set_2(7.0f, (GenFunction_2)func_80387F38, (uintptr_t)this->marker, 3); + } + } + + if (next_state == 3) { + this->marker->propPtr->unk8_3 = true; + skeletalAnim_set(this->unk148, local->unk0->unk6, 0.1f, 5.0f); + skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); + } + this->state = next_state; +} + +s32 func_80388260(ActorMarker *marker, s32 arg1){ + return marker->unk40_31 != 1; +} + +void CCW_func_80388278(ActorMarker *marker, ActorMarker *other_marker) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); +} + +void func_803882A4(ActorMarker* marker, ActorMarker *other_marker) { + Actor* actor = marker_getActor(marker); + + // [port] v1.1 fix: don't allow re-planting flower in Spring after it's already been planted + if (EventSystem_Should(VB_CCW_FLOWER_REPLANT, + gsworld_getMap() == MAP_43_CCW_SPRING && actor->state == 1 && + !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING))) { + func_80387F64(actor, 2); + } +} + +Actor *CCW_func_803882F4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { + Actor *this; + s32 sp18; + + this = marker_getActor(marker); + if ((this->state == 1) && !fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING)) { + return func_80325340(marker, gfx, mtx, vtx); + } + + if ((skeletalAnim_getAnimId(this->unk148) == 0x175) && (0.49 <= skeletalAnim_getProgress(this->unk148))) { + sp18 = 1; + } else { + sp18 = 0; + } + sp18 = (skeletalAnim_getAnimId(this->unk148) == 0x183)? 1 : sp18; + func_8033A45C(3, sp18); + func_8033A45C(4, sp18); + return actor_draw(marker, gfx, mtx, vtx); +} + +void func_803883F4() { + Actor* actor = actorArray_findActorFromActorId(0x29D); + if (actor && actor->state == 1) { + func_80387F64(actor, 2); + } +} + +bool func_80388438() { + Actor* actor = actorArray_findActorFromActorId(0x29D); + if (actor && actor->state == 2) { + return true; + } + return false; +} + +void func_80388478(Actor *this) { + ActorLocal_CCW_1B20 *local; + + local = (ActorLocal_CCW_1B20 *)&this->local; + if (!this->volatile_initialized) { + this->volatile_initialized = true; + func_803300C0(this->marker, (s32 (*)(ActorMarker *, ActorMarker *))func_80388260); + marker_setCollisionScripts(this->marker, NULL, CCW_func_80388278, func_803882A4); + actor_collisionOn(this); + if (!jiggyscore_isSpawned(JIGGY_4D_CCW_FLOWER)) { + fileProgressFlag_set(FILEPROG_E5_CCW_FLOWER_AUTUMN, false); + } + + for(local->unk0 = &D_8038EC40[0]; local->unk0 < D_8038EC40 + 3; local->unk0++){ + if(!fileProgressFlag_get(local->unk0->unk8)){ + break; + } + } + + if (!fileProgressFlag_get(FILEPROG_E3_CCW_FLOWER_SPRING) && (gsworld_getMap() != MAP_43_CCW_SPRING)) { + marker_despawn(this->marker); + } + else{ + func_80387F64(this, 1); + } + } +} diff --git a/src/CCW/minigame_zubba.c b/src/CCW/minigame_zubba.c new file mode 100644 index 000000000..a1b71edc1 --- /dev/null +++ b/src/CCW/minigame_zubba.c @@ -0,0 +1,221 @@ +// BanjoDecomp: code_160.c +#include +#include "core1/core1.h" +#include "functions.h" +#include "variables.h" + + + +typedef struct{ + ActorMarker *unk0; + s32 unk4; + s32 unk8; + f32 unkC; +}ActorLocal_CCW_160; + +void func_803865F4(Actor *this, s32 next_state); +void func_8038687C(Actor *this); + +/* .data */ +ActorInfo D_8038EBA0 = { 0x1AD, 0x299, 0x443, 0x0, NULL, func_8038687C, NULL, actor_draw, 0, 0, 0.0f, 0}; + +/* .code */ +void CCW_func_80386550(ActorMarker *marker){ + Actor *this; + ActorLocal_CCW_160 *local; + + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + this->unk124_11 = 2; + this->alpha_124_19 = 0xFF; + if (local->unk0 != NULL) { + actor_collisionOn(marker_getActor(local->unk0)); + } + coMusicPlayer_playMusic(COMUSIC_3D_JIGGY_SPAWN, 28000); +} + +void func_803865C4(ActorMarker* marker, enum asset_e text_id, s32 arg2) { + func_803865F4(marker_getActor(marker), 3); +} + +void func_803865F4(Actor *this, s32 next_state) { + ActorLocal_CCW_160 *local; + + local = (ActorLocal_CCW_160 *)&this->local; + local->unkC = 0.0f; + if (next_state == 2) { + if (!volatileFlag_getAndSet(VOLATILE_FLAG_B5, 1)) { + gcdialog_showDialog(0xCE2, 4, NULL, this->marker, func_803865C4, NULL); + } else { + gcdialog_showDialog(0xCE3, 4, NULL, NULL, NULL, NULL); + func_803865F4(this, 3); + return; + } + } + + if (next_state == 3) { + local->unkC = 0.1f; + func_8025A58C(0, 4000); + coMusicPlayer_playMusic(COMUSIC_4B_CCW_ZUBBA_FIGHT, 30000); + } + + if (next_state == 4) { + if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { + item_set(ITEM_6_HOURGLASS, false); + volatileFlag_set(VOLATILE_FLAG_3, 0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 1); + } else { + gcdialog_showDialog(0xCE4, 4, NULL, NULL, NULL, NULL); + func_8025A58C(-1, 400); + comusic_8025AB44(COMUSIC_4B_CCW_ZUBBA_FIGHT, 0, 400); + func_8025AABC(COMUSIC_4B_CCW_ZUBBA_FIGHT); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(2.0f, 4); + timedFunc_set_1(2.0f, (GenFunction_1)CCW_func_80386550, (uintptr_t)this->marker); + timed_exitStaticCamera(4.0f); + func_80324E38(4.0f, 0); + } + } + this->state = next_state; +} + +void func_803867C8(ActorMarker *marker){ + Actor *this; + ActorLocal_CCW_160 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + local->unk8++; + local->unk4--; + if(local->unk8 == 10){ + func_803865F4(this, 4); + } +} + +void func_80386814(ActorMarker *marker){ + Actor *this; + ActorLocal_CCW_160 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + local->unk4--; +} + +void func_80386840(ActorMarker *marker, s32 *score, s32 *total){ + Actor *this; + ActorLocal_CCW_160 *local; + + this = marker_getActor(marker); + local = (ActorLocal_CCW_160 *)&this->local; + + *score = local->unk8; + *total = 10; +} + +void func_8038687C(Actor *this) { + ActorLocal_CCW_160 *local; + f32 sp88; + Actor *other; + f32 sp78[3]; + f32 sp6C[3]; + s32 pad68; + f32 sp5C[3]; + s32 phi_s0; + f32 sp4C[3]; + f32 sp40[3]; + s32 phi_v0; + f32 tmp; + + sp88 = time_getDelta(); + local = (ActorLocal_CCW_160 *)&this->local; + if(!this->volatile_initialized) { + this->volatile_initialized = true; + this->marker->propPtr->unk8_3 = true; + reinterpret_cast(s32, local->unk0) = 1; + local->unk4 = 0; + local->unk8 = 0; + local->unkC = 0.0f; + if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { + this->position_y -= 300.0f; + } + func_803865F4(this, 1); + return; + } + if ((uintptr_t)local->unk0 == 1) { + other = actorArray_findActorFromActorId(0x46); + if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { + local->unk0 = NULL; + if (other != NULL) { + actor_collisionOff(other); + other->position[1] -= 300.0f; + } + } else if (other != NULL) { + local->unk0 = other->marker; + actor_collisionOff(other); + if (jiggyscore_isCollected(JIGGY_4C_CCW_ZUBBAS) != 0) { + marker_despawn(local->unk0); + marker_despawn(this->marker); + } + } else { + marker_despawn(this->marker); + } + return; + } + + if (local->unk0 != NULL) { + other = marker_getActor(local->unk0); + viewport_getPosition_vec3f(sp78); + sp6C[0] = this->position[0] - sp78[0]; + sp6C[1] = this->position[1] - sp78[1]; + sp6C[2] = this->position[2] - sp78[2]; + sp6C[1] = 0.0f; + ml_vec3f_set_length(sp6C, 20.0f); + other->position[0] = this->position[0] + sp6C[0]; + other->position[1] = this->position[1] + sp6C[1]; + other->position[2] = this->position[2] + sp6C[2]; + } + if (ml_timer_update(&local->unkC, sp88)) { + if ((local->unk4 < 3) && ((local->unk8 + local->unk4) < 10)) { + player_getPosition(sp5C); + for(phi_s0 = 0; phi_s0 < 20; phi_s0++){ + sp4C[0] = randf2(-500.0f, 500.0f); + sp4C[1] = -100.0f; + sp4C[2] = randf2(-500.0f, 900.0f); + + if(ml_vec3f_distance(this->position, sp4C) < 400.0f) + continue; + + tmp = ml_vec3f_distance(sp5C, sp4C); + phi_v0 = (phi_s0 < 0xA) ? 500 : 200; + if(tmp < (f32) phi_v0) + continue; + + if(viewport_isPointOutsideFrustum_3f(sp4C[0], 0.0f, sp4C[2])) + break; + + } + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x29B, reinterpret_cast(s32, sp4C[0]), reinterpret_cast(s32, sp4C[1]), reinterpret_cast(s32, sp4C[2])); + local->unk4++; + } + local->unkC = randf2(0.5 - ((local->unk8 / 10) * 0.4), 1.0 - ((local->unk8 / 10) * 0.8)); + } + if (this->state == 1) { + if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && volatileFlag_get(VOLATILE_FLAG_3)) { + item_set(ITEM_6_HOURGLASS, 1); + item_set(ITEM_0_HOURGLASS_TIMER, 1800 - 1); + func_803865F4(this, 3); + } else if ((local->unk0 != NULL) && (gsworld_getMap() == MAP_5A_CCW_SUMMER_ZUBBA_HIVE)) { + player_getPosition(sp40); + if ((ml_vec3f_distance(this->position, sp40) < 300.0f) && (player_getTransformation() == TRANSFORM_1_BANJO)) { + func_803865F4(this, 2); + } + } + } + if ((this->state == 3) && volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) && item_empty(ITEM_0_HOURGLASS_TIMER)) { + item_set(ITEM_6_HOURGLASS, 0); + volatileFlag_set(VOLATILE_FLAG_3, 0); + volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); + } +} diff --git a/src/CCW/nabnut_winter.c b/src/CCW/nabnut_winter.c deleted file mode 100644 index 13589719b..000000000 --- a/src/CCW/nabnut_winter.c +++ /dev/null @@ -1,174 +0,0 @@ -// BanjoDecomp: code_5BF0.c -#include -#include "functions.h" -#include "variables.h" - -extern void func_8028E668(f32[3], f32, f32, f32); - -Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); -void func_8038C41C(Actor *this); - -/* .data */ - -ActorInfo chMoundOfAcorns = { - MARKER_1C6_MOUND_OF_ACORNS, ACTOR_310_NABNUT_HOUSE_PILE_OF_ACORNS, ASSET_501_MODEL_MOUND_OF_ACORNS, - 0x0, NULL, - func_8038C41C, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chPinkSquirrel = { - MARKER_1C7_PINK_SQUIRREL, ACTOR_311_PINK_SQUIRREL, ASSET_462_MODEL_PINK_SQUIRREL, - 0x0, NULL, - func_8038C41C, NULL, func_8038C380, - 0, 0, 0.0f, 0 -}; - -ActorInfo chNabnutBedsheets = { - MARKER_1C8_NABNUT_BEDSHEETS, ACTOR_312_NABNUT_BEDSHEETS, ASSET_463_MODEL_NABNUT_BEDSHEETS, - 0x0, NULL, - func_8038C41C, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chNabnutBed = { - MARKER_1C9_NABNUT_BED, ACTOR_313_NABNUT_BED, ASSET_464_MODEL_NABNUT_BED, - 0x0, NULL, - func_8038C41C, NULL, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chNabnut = { - MARKER_1CA_NABNUT, ACTOR_314_NABNUT_IN_AUTUMN_HOUSE, ASSET_502_MODEL_NABNUT, - 0x0, NULL, - func_8038C41C, NULL, actor_draw, - 0, 0, 2.0f, 0 -}; - -ActorInfo chNabnutAutumnEatingAcorns = { - MARKER_1CB_NABNUT_EATING_ACORNS, ACTOR_315_NABNUT_EATING_ACORNS, ASSET_48D_MODEL_NABNUT_EATING_ACORNS, - 0x0, NULL, func_8038C41C, - NULL, func_8038C380, - 0, 0, 0.0f, 0 -}; - -enum code_5BF0_state_e { - CODE_5BF0_STATE_0_NOT_INIT, - CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY, - CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY -}; - -/* .code */ -void func_8038BFE0(ActorMarker* marker) { - Actor* sp2C = marker_getActor(marker); - func_8030E878(SFX_5D_BANJO_RAAOWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); -} - -void func_8038C064(ActorMarker* marker) { - Actor* sp2C = marker_getActor(marker); - func_8030E878(SFX_5E_BANJO_PHEWWW, randf2(1.0f, 1.1f), (s32)randf2(21000.0f, 22000.0f), sp2C->position, 500.0f, 2500.0f); -} - -void func_8038C0E8(ActorMarker* marker) { - Actor* sp24 = marker_getActor(marker); - f32 sp20 = randf2(0.9f, 1.1f); - - func_8030E878(SFX_81_UUU, sp20, (s32)randf2(10000.0f, 31000.0f), sp24->position, 500.0f, 2500.0f); -} - -void code_5BF0_setState(Actor *this, s32 next_state) { - Actor *other; - - if (next_state == CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY) { - this->position[1] -= 300.0f; - } - - if (this->state == CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY) { - this->position[1] += 300.0f; - } - - if (next_state == CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY) { - if (this->marker->id == MARKER_1CA_NABNUT) { - skeletalAnim_set(this->unk148, ASSET_22E_ANIM_NABNUT_STAND, 0.2f, 3.53f); - skeletalAnim_setCallback_1(this->unk148, 0.1f, (GenFunction_1)func_8038C0E8, (uintptr_t)this->marker); - } - if (this->marker->id == MARKER_1C7_PINK_SQUIRREL) { - skeletalAnim_set(this->unk148, ASSET_230_ANIM_PINK_SQUIRREL_UNK, 0.2f, 4.0f); - } - if (this->marker->id == MARKER_1CB_NABNUT_EATING_ACORNS) { - skeletalAnim_set(this->unk148, ASSET_1A2_ANIM_NABNUT_SLEEP, 0.2f, 4.0f); - skeletalAnim_setCallback_1(this->unk148, 0.3f, (GenFunction_1)func_8038BFE0, (uintptr_t)this->marker); - skeletalAnim_setCallback_1(this->unk148, 0.65f, (GenFunction_1)func_8038C064, (uintptr_t)this->marker); - } - if (this->marker->id == MARKER_1C8_NABNUT_BEDSHEETS) { - skeletalAnim_set(this->unk148, ASSET_231_ANIM_NABNUT_BEDSHEETS_UNK, 0.2f, 4.0f); - } - if ((this->marker->id == MARKER_1C7_PINK_SQUIRREL) - || (this->marker->id == MARKER_1CB_NABNUT_EATING_ACORNS) - || (this->marker->id == MARKER_1C8_NABNUT_BEDSHEETS)) - { - other = actorArray_findActorFromActorId(ACTOR_313_NABNUT_BED); - if (other != 0) { - this->position[0] = other->position[0]; - this->position[1] = other->position[1]; - this->position[2] = other->position[2]; - this->pitch = other->pitch; - this->yaw = other->yaw; - this->roll = other->roll; - } - } - } - this->state = next_state; -} - -Actor *func_8038C380(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { - modelRender_setAppendageVisibility(3, 0); - modelRender_setAppendageVisibility(4, 0); - modelRender_setAppendageVisibility(5, 0); - modelRender_setAppendageVisibility(6, 1); - modelRender_setAppendageVisibility(7, 0); - modelRender_setAppendageVisibility(8, 0); - modelRender_setAppendageVisibility(9, 0); - modelRender_setAppendageVisibility(0xA, 1); - return actor_draw(marker, gfx, mtx, vtx); -} - -void func_8038C41C(Actor *this) { - f32 player_position[3]; - - if (!this->volatile_initialized) { - this->marker->propPtr->unk8_3 = true; - this->volatile_initialized = true; - this->has_met_before = false; - return; - } - - if (this->state == CODE_5BF0_STATE_0_NOT_INIT) { - if( gsworld_getMap() == MAP_60_CCW_AUTUMN_NABNUTS_HOUSE - && !jiggyscore_isSpawned(JIGGY_4A_CCW_NABNUT) - && (this->marker->id == MARKER_1C6_MOUND_OF_ACORNS - || this->marker->id == MARKER_1CA_NABNUT) - ){ - code_5BF0_setState(this, CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY); - } else { - code_5BF0_setState(this, CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY); - } - } - - if ((this->marker->id == MARKER_1CA_NABNUT) - && (this->state != CODE_5BF0_STATE_1_CCW_AUTUMN_AFTER_ACORN_JIGGY)) - { - func_8028E668(this->position, 300.0f, -50.0f, 120.0f); - } - - if ((this->marker->id == MARKER_1CB_NABNUT_EATING_ACORNS) - && (this->state == CODE_5BF0_STATE_2_CCW_WINTER_OR_NO_ACORN_JIGGY)) - { - player_getPosition(player_position); - if (!this->has_met_before && (ml_vec3f_distance(this->position, player_position) < 400.0f)) { - this->has_met_before = TRUE; - gcdialog_showDialog(VER_SELECT(ASSET_CCD_DIALOG_NABNUT_MEET_WINTER, 0x09E2, 0, 0), 0, NULL, NULL, NULL, NULL); - } - } -} - diff --git a/src/CCW/seasonal_switch.c b/src/CCW/seasonal_switch.c new file mode 100644 index 000000000..e5a397dba --- /dev/null +++ b/src/CCW/seasonal_switch.c @@ -0,0 +1,171 @@ +// BanjoDecomp: code_2B00.c +#include +#include "functions.h" +#include "variables.h" + +typedef struct{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; +}Struct_CCW_2B00_0; + +void func_80389268(Actor *this); +void func_80388FD4(Actor *this); + +/* .data */ +Struct_CCW_2B00_0 D_8038ED10[] = { + {0, 0x40, 0, 5}, + {0, 0x43, 1, 5}, + {0, 0x44, 2, 5}, + {0, 0x45, 3, 15} +}; + +ActorAnimationInfo D_8038ED20[] = { + {0, 0.0f}, + {0, 0.0f}, + {0, 0.0f}, + {0, 0.0f}, + {ASSET_D4_ANIM_SWITCH_DOWN, 0.5f}, + {ASSET_D4_ANIM_SWITCH_DOWN, 100000000.0f} +}; + +ActorInfo D_8038ED50 = { 0x133, 0x1E3, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; +ActorInfo D_8038ED74 = { 0x132, 0x1E2, 0x4F5, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038ED98 = { 0x131, 0x16D, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; +ActorInfo D_8038EDBC = { 0x130, 0x16C, 0x4F6, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038EDE0 = { 0x12F, 0x16B, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; +ActorInfo D_8038EE04 = { 0x12E, 0x16A, 0x4F7, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8038EE28 = { 0x12D, 0x169, 0x52E, 0x1, NULL, func_80389268, actor_update_func_80326224, actor_drawFullDepth, 0, 0x4000, 0.0f, 0}; +ActorInfo D_8038EE4C = { 0x12C, 0x168, 0x4F8, 0x5, D_8038ED20, func_80388FD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; + +/* .code */ +s32 func_80388EF0(Actor *this){ + switch(this->marker->id){ + case 0x133: //L80388F28 + case 0x132: //L80388F28 + return 0; + + case 0x131: //L80388F30 + case 0x130: //L80388F30 + return 1; + + case 0x12F: //L80388F38 + case 0x12E: //L80388F38 + return 2; + + case 0x12D: //L80388F40 + case 0x12C: //L80388F40 + return 3; + + default: + return 0; + } +} + + +void func_80388F50(ActorMarker *marker, ActorMarker *other_marker){ + Actor *this; + + this = marker_getActor(marker); + if ((player_movementGroup() != BSGROUP_1_INTR) && !this->unk38_0) { + this->unk38_0 = true; + actor_collisionOff(this); + subaddie_set_state_with_direction(this, 4, 0.0f, 1); + actor_playAnimationOnce(this); + func_8030E6D4(SFX_90_SWITCH_PRESS); + } +} + +void func_80388FD4(Actor *this) { + + if (!this->initialized) { + this->unk138_31 = this->unk124_0 = true; + this->marker->propPtr->unk8_3 = true; + this->unk10_12 = func_80388EF0(this); + this->initialized = true; + } + if (!this->volatile_initialized) { + if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { + actor_playAnimationOnce(this); + subaddie_set_state_with_direction(this, 4, 0.999f, 1); + actor_collisionOff(this); + } else { + marker_setCollisionScripts(this->marker, NULL, &func_80388F50, NULL); + } + this->unk38_0 = false; + this->volatile_initialized = true; + } + if( (this->state == 4) + && this->unk38_0 + && actor_animationIsAt(this, 0.999f) + ){ + func_802D6264(1.1f, 0x40, this->unk10_12 + 0x3C, 0x2B, D_8038ED10[this->unk10_12].unk3, this->unk10_12 + 0x8B); + func_80324E38(0.5f, 3); + timedFunc_set_2(1.1f, (GenFunction_2)levelSpecificFlags_set, this->unk10_12 + 7, true); + func_80324E38(5.6f, 0); + } +} + +void func_803891B0(void* marker) { + Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); + actor->unk44_31 = func_8030ED2C(SFX_3EC_CCW_DOOR_OPENING, 3); + func_8030DD90(actor->unk44_31, 0); + sfxsource_setSampleRate(actor->unk44_31, 0x2AF8); + sfxsource_playSfxAtVolume(actor->unk44_31, 0.3f); + sfxSource_func_8030E2C4(actor->unk44_31); +} + +void func_8038921C(void* marker) { + Actor* actor = marker_getActor(reinterpret_cast(ActorMarker*, marker)); + sfxSource_triggerCallbackByIndex(actor->unk44_31); + sfxsource_freeSfxsourceByIndex(actor->unk44_31); + actor->unk44_31 = 0U; + FUNC_8030E624(SFX_6C_LOCKUP_CLOSING, 1.0f, 25000); +} + +void func_80389268(Actor *this) { + ActorProp *temp_v1; + u32 temp_v0; + u32 temp_v1_2; + + if(!this->initialized) { + this->unk58_2 = false; + this->unk10_12 = func_80388EF0(this); + this->marker->propPtr->unk8_3 = true; + actor_collisionOff(this); + this->initialized = true; + } + if (!this->volatile_initialized) { + this->unk1C[0] = this->position[0]; + this->unk1C[1] = this->position[1]; + this->unk1C[2] = this->position[2]; + this->unk1C[1] += 250.0f; + + this->volatile_initialized = true; + if (fileProgressFlag_get(this->unk10_12 + FILEPROG_8B_CCW_SPRING_OPEN)) { + subaddie_set_state(this, 3); + } + } + + + switch (this->state) { /* irregular */ + case 1: + if (levelSpecificFlags_get(this->unk10_12 + 7)) { + timedFunc_set_1(0.05f, (GenFunction_1)func_803891B0, (uintptr_t)this->marker); + timedFunc_set_1(4.0f, (GenFunction_1)func_8038921C, (uintptr_t)this->marker); + subaddie_set_state(this, 2); + } + break; + case 2: + this->position[1] += 60.0f * time_getDelta(); + if (this->unk1C[1] <= this->position[1]) { + levelSpecificFlags_set(this->unk10_12 + 7, false); + subaddie_set_state(this, 3); + } + break; + case 3: + this->position[1] = this->unk1C[1]; + break; + } +} diff --git a/src/CCW/snarebear_proximity.c b/src/CCW/snarebear_proximity.c new file mode 100644 index 000000000..1090a0529 --- /dev/null +++ b/src/CCW/snarebear_proximity.c @@ -0,0 +1,122 @@ +// BanjoDecomp: code_7BF0.c +#include +#include "functions.h" +#include "variables.h" + + +void func_8038E0C8(Actor *this); + +/* .data */ +ActorAnimationInfo D_8038F8F0[] = { + {0x000, 0.0f}, + {0x16C, 2.0f}, + {0x16B, 1.2f} +}; + +ActorInfo D_8038F908 = { + MARKER_1F9_SNARE_BEAR, ACTOR_1E9_SNARE_BEAR, ASSET_440_MODEL_SNAREBEAR, + 0x1, D_8038F8F0, + func_8038E0C8, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +/* .code */ +void func_8038DFE0(Actor* actor) { + subaddie_set_state_with_direction(actor, 1, 0.001f, 1); + actor->unk38_31 = randi2(0, 0); +} + +void CCW_func_8038E034(Actor* actor) { + subaddie_set_state_with_direction(actor, 2, 0.001f, 1); +} + +void func_8038E060(BoneTransformList *arg0, ActorMarker *marker){ + Actor *this; + f32 sp28[3]; + s32 pad24; + f32 sp18[4]; // quaternion: func_80345C78 writes 4 floats + + this = marker_getActor(marker); + if(arg0){ + sp28[0] = 0.0f; + sp28[1] = this->unk1C[0]; + sp28[2] = 0.0f; + + + func_80345C78(sp18, sp28); + func_8033A8F0(arg0, 1, sp18); + modelRender_setBoneTransformList(arg0); + } +} + +void func_8038E0C8(Actor *this) { + f32 sp44[3]; + f32 sp40; + f32 sp3C; + f32 sp38; + f32 sp34; + + sp34 = time_getDelta(); + + if(!subaddie_playerIsWithinSphere(this, 3000)) return; + + if (!this->volatile_initialized) { + this->volatile_initialized = true; + func_8028746C(this->anctrl, (GenFunction_2)func_8038E060); + func_8028748C(this->anctrl, (uintptr_t)this->marker); + this->marker->propPtr->unk8_3 = true; + this->unk1C[0] = 0.0f; + this->unk38_31 = 0; + } + + if (player_getTransformation() == TRANSFORM_6_BEE) { + actor_collisionOff(this); + } else { + actor_collisionOn(this); + player_getPosition(sp44); + func_80258A4C(this->position, this->yaw - 90.0f, sp44, &sp40, &sp3C, &sp38); + if( (sp40 < 1050.0f) + && (sp38 > -1.0f) + && (sp38 < 1.0f) + ) { + func_80258A4C(this->position, this->unk1C[0] + (this->yaw - 90.0f), sp44, &sp40, &sp3C, &sp38); + this->unk1C[0] += sp38 * 160.0f * sp34; + } else { + if (this->unk1C[0] > 0.0f) { + this->unk1C[0] -= (30.0f * sp34); + this->unk1C[0] = (this->unk1C[0] < 0.0f) ? 0.0f : this->unk1C[0]; + + } else if (this->unk1C[0] < 0.0f) { + this->unk1C[0] += (30.0f * sp34); + this->unk1C[0] = (this->unk1C[0] > 0.0f) ? 0.0f : this->unk1C[0]; + } + } + } + switch (this->state) { + case 1: + if (this->unk38_31 != 0) { + this->unk38_31--; + break; + } + if( subaddie_playerIsWithinSphereAndActive(this, 0x2A8) + && (this->unk38_31 == 0) + && (player_getTransformation() == TRANSFORM_1_BANJO) + ) { + CCW_func_8038E034(this); + } + break; + + case 2: + if (actor_animationIsAt(this, 0.999f)) { + func_8038DFE0(this); + break; + } + if( actor_animationIsAt(this, 0.18f) + || actor_animationIsAt(this, 0.47f) + || actor_animationIsAt(this, 0.78f) + ) { + sfx_playFadeShorthandDefault(SFX_80_YUMYUM_CLACK, 1.0f, 32000, this->position, 1500, 3000); + } + break; + } +} diff --git a/src/CCW/zubba.c b/src/CCW/zubba.c deleted file mode 100644 index bb9095edc..000000000 --- a/src/CCW/zubba.c +++ /dev/null @@ -1,240 +0,0 @@ -// BanjoDecomp: code_950.c -#include -#include "functions.h" -#include "variables.h" - -extern void func_8030DBFC(u8, f32, f32, f32); - -typedef struct{ - u8 sfxsourceIdx; - //u8 pad1[3]; - ActorMarker *honeyLumpMarker; - f32 distanceToPlayer[3]; - f32 unk14; - f32 unk18; // time related -}ActorLocal_CCW_950; - -void chZubba_update(Actor *this); - -/* .data */ -ActorInfo chZubba = { - MARKER_1AE_ZUBBA, ACTOR_29B_ZUBBA, ASSET_446_MODEL_ZUBBA, - 0x0, NULL, - chZubba_update, NULL, actor_draw, - 0, 0, 1.0f, 0 -}; - -enum chzubba_state_e { - CH_ZUBBA_STATE_0_NOT_INIT, - CH_ZUBBA_STATE_1_NON_AGRO_FLYING, - CH_ZUBBA_STATE_2_ATTACK, - CH_ZUBBA_STATE_3_HIT_PLAYER, - CH_ZUBBA_STATE_4_DIE, - CH_ZUBBA_STATE_5_SPLAT, - CH_ZUBBA_STATE_6_DIE_DESPAWN, - CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN -}; - -/* .code */ -void chZubba_setState(Actor *this, s32 next_state) { - ActorLocal_CCW_950 *local; - f32 player_position_1[3]; - f32 player_position_2[3]; - - local = (ActorLocal_CCW_950 *)&this->local; - local->unk18 = 0.0f; - if (next_state == CH_ZUBBA_STATE_1_NON_AGRO_FLYING) { - local->unk18 = 800.0f; - skeletalAnim_set(this->unk148, ASSET_16F_ANIM_ZUBBA_FLY_MOVE, 0.0f, 0.65f); - } - if (next_state == CH_ZUBBA_STATE_2_ATTACK) { - skeletalAnim_set(this->unk148, ASSET_170_ANIM_ZUBBA_FLY_IDLE, 0.1f, 0.65f); - player_getPosition(player_position_1); - player_position_1[1] += 50.0f; - local->distanceToPlayer[0] = player_position_1[0] - this->position[0]; - local->distanceToPlayer[1] = player_position_1[1] - this->position[1]; - local->distanceToPlayer[2] = player_position_1[2] - this->position[2]; - ml_vec3f_normalize(local->distanceToPlayer); - if ((local->distanceToPlayer[0] == 0.0f) - && (local->distanceToPlayer[1] == 0.0f) - && (local->distanceToPlayer[2] == 0.0f)) - { - local->distanceToPlayer[1] = -1.0f; - } - } - if (next_state == CH_ZUBBA_STATE_3_HIT_PLAYER) { - sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); - func_80324D54(randf2(0.1f, 0.4f), SFX_3FC_ZUBBA_UNK, randf2(0.95f, 1.1f), 32000, this->position, 500.0f, 3000.0f); - actor_collisionOff(this); - } - if (next_state == CH_ZUBBA_STATE_4_DIE) { - skeletalAnim_set(this->unk148, ASSET_171_ANIM_ZUBBA_DIE, 0.1f, 0.2f); - sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.2f, 32200, this->position, 500, 3000); - func_80324D54(0.1f, 0x66, randf2(1.6f, 1.7f), 32000, this->position, 500.0f, 3000.0f); - chZubbaFight_zubbaKilled(local->honeyLumpMarker); - actor_collisionOff(this); - player_getPosition(player_position_2); - player_position_2[1] += 50.0f; - local->distanceToPlayer[0] = this->position[0] - player_position_2[0]; - local->distanceToPlayer[1] = this->position[1] - player_position_2[1]; - local->distanceToPlayer[2] = this->position[2] - player_position_2[2]; - ml_vec3f_normalize(local->distanceToPlayer); - if ((local->distanceToPlayer[0] == 0.0f) - && (local->distanceToPlayer[1] == 0.0f) - && (local->distanceToPlayer[2] == 0.0f)) - { - local->distanceToPlayer[1] = -1.0f; - } - } - if (next_state == CH_ZUBBA_STATE_5_SPLAT) { - func_8030E878(SFX_A_BANJO_LANDING_05, randf2(0.85f, 0.95f), 18000, this->position, 500.0f, 3000.0f); - skeletalAnim_set(this->unk148, ASSET_172_ANIM_ZUBBA_LAND, 0.0f, 1.0f); - skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - } - if (next_state == CH_ZUBBA_STATE_6_DIE_DESPAWN) { - marker_despawn(this->marker); - } - if (next_state == CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN) { - chZubbaFight_zubbaDisappear(local->honeyLumpMarker); - marker_despawn(this->marker); - } - this->state = next_state; -} - - -void chZubba_hitPlayer(ActorMarker* marker, ActorMarker *other_marker) { - chZubba_setState(marker_getActor(marker), CH_ZUBBA_STATE_3_HIT_PLAYER); -} - -void chZubba_die(ActorMarker* marker, ActorMarker *other_marker) { - chZubba_setState(marker_getActor(marker), CH_ZUBBA_STATE_4_DIE); -} - -void chZubba_freeSfx(Actor *this){ - ActorLocal_CCW_950 *local; - - local = (ActorLocal_CCW_950 *)&this->local; - sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); -} - -void chZubba_update(Actor *this) { - ActorLocal_CCW_950 *local; - f32 time_delta; - Actor *honey_lump_actor; - s32 zubbas_defeated; - s32 zubbas_to_defeat; - f32 player_position[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; - f32 temp_f0; - f32 pad; - - - time_delta = time_getDelta(); - local = (ActorLocal_CCW_950 *)&this->local; - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->actorFreeFunc = chZubba_freeSfx; - local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); - local->honeyLumpMarker = 0; - local->unk14 = 1000.0f; - sfxsource_setSfxId(local->sfxsourceIdx, SFX_3FA_HONEYCOMB_TALKING); - sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); - sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); - sfxsource_setSampleRate(local->sfxsourceIdx, 0); - marker_setCollisionScripts(this->marker, chZubba_hitPlayer, NULL, chZubba_die); - chZubba_setState(this, CH_ZUBBA_STATE_1_NON_AGRO_FLYING); - return; - } - if(local->honeyLumpMarker == NULL) { - honey_lump_actor = actorArray_findActorFromActorId(ACTOR_299_ZUBBA_HONEY_LUMP); - if (honey_lump_actor == NULL) { - marker_despawn(this->marker); - return; - } - local->honeyLumpMarker = honey_lump_actor->marker; - chZubbaFight_zubbaScore(local->honeyLumpMarker, &zubbas_defeated, &zubbas_to_defeat); - local->unk14 = (((f32)zubbas_defeated /(f32)zubbas_to_defeat) * 1000.0f) + 1000.0f; - } - - if (this->state == CH_ZUBBA_STATE_1_NON_AGRO_FLYING) { - temp_f0 = this->position[1]; - this->position[0] += 0.1 * time_delta; - this->position[1] += local->unk18 * time_delta; - if ((temp_f0 < 0.0f) && (this->position[1] >= 0.0f)) { - func_8030E878(SFX_A_BANJO_LANDING_05, randf2(1.0f, 1.1f), 18000, this->position, 500.0f, 3000.0f); - } - player_getPosition(player_position); - func_80258A4C( - this->position, this->yaw - 90.0f, player_position, - &horizontal_distance, &distance_in_front, &side_angle_radian); - this->yaw += 360.0f * side_angle_radian * time_delta; - if (this->position[1] > 150.0f) { - local->unk18 -= 2000.0f * time_delta; - if (local->unk18 < 0.0f) { - chZubba_setState(this, CH_ZUBBA_STATE_2_ATTACK); - } - } - } - - if (this->state == CH_ZUBBA_STATE_2_ATTACK) { - if (local->unk18 < local->unk14) { - local->unk18 += (4.0f * local->unk14 * time_delta); - } - this->position[0] += local->distanceToPlayer[0] * local->unk18 * time_delta; - this->position[1] += local->distanceToPlayer[1] * local->unk18 * time_delta; - this->position[2] += local->distanceToPlayer[2] * local->unk18 * time_delta; - if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) - || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) - || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) - ){ - chZubba_setState(this, CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN); - } - } - - if (this->state == CH_ZUBBA_STATE_3_HIT_PLAYER) { - this->position[1] += local->unk18 * time_delta; - if (local->unk18 < local->unk14) { - local->unk18 += 2000.0f * time_delta; - } - - if( (this->position[0] < -1500.0f) || (1500.0f < this->position[0]) - || (this->position[1] < -100.0f) || (1300.0f < this->position[1]) - || (this->position[2] < -1200.0f) || (this->position[2] > 2000.0f) - ) { - chZubba_setState(this, CH_ZUBBA_STATE_7_FIGHT_COMPLETE_DESPAWN); - } - } - - if (this->state == CH_ZUBBA_STATE_4_DIE) { - this->position[0] += local->distanceToPlayer[0] * 1000.0f * time_delta; - this->position[1] -= local->unk18 * time_delta; - this->position[2] += local->distanceToPlayer[2] * 1000.0f * time_delta; - if (local->unk18 < local->unk14) { - local->unk18 += (1000.0f * time_delta); - } - if (this->position[1] <= 0.0f) { - this->position[1] = 0.0f; - chZubba_setState(this, CH_ZUBBA_STATE_5_SPLAT); - } - } - - if (this->state == CH_ZUBBA_STATE_5_SPLAT) { - this->position[1] -= 300.0f * time_delta; - if (this->position[1] < -200.0f) { - chZubba_setState(this, CH_ZUBBA_STATE_6_DIE_DESPAWN); - } - } - - if(this->state); - if (this->state == CH_ZUBBA_STATE_2_ATTACK) { - func_8030DBFC(local->sfxsourceIdx, 1.0f, 1.1f, 0.05f); - } else { - func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); - } - sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); - sfxsource_set_position(local->sfxsourceIdx, this->position); - sfxSource_func_8030E2C4(local->sfxsourceIdx); - sfxsource_setSampleRate(local->sfxsourceIdx, (s32) ((local->unk18 / local->unk14) * 10000.0f)); -} diff --git a/src/CCW/zubba_hive_npc.c b/src/CCW/zubba_hive_npc.c deleted file mode 100644 index d6097dbbb..000000000 --- a/src/CCW/zubba_hive_npc.c +++ /dev/null @@ -1,157 +0,0 @@ -// BanjoDecomp: code_14B0.c -#include "functions.h" -#include "variables.h" -#include - -#include - -extern void func_8030DBFC(u8, f32, f32, f32); -extern void sfxsource_setSampleRate(u8, s32); - -typedef struct{ - s16 map; - u8 mapFlag; - u8 jiggyId; - s16 textId; -} Zubba_Docile_Dialog; - -typedef struct { - u8 sfxsourceIdx; - // u8 pad1[3]; - Zubba_Docile_Dialog *dialog; - f32 unk8; // random value? - f32 targetPosition[3]; - f32 unk18[3]; // some kind of position? -} ActorLocal_ZubbaDocile; - -void chZubbaDocile_update(Actor *this); - -/* .data */ -Zubba_Docile_Dialog chZubbaDocileDialog[] = { - { - MAP_5B_CCW_SPRING_ZUBBA_HIVE, - CCW_ZUBBA_SPECIFIC_FLAG_7_SPRING_DIALOG, - JIGGY_4C_CCW_ZUBBAS, - VER_SELECT(ASSET_CE1_DIALOG_ZUBBA_MEET_SPRING, 0x09F6, 0, 0) - }, - { - MAP_5C_CCW_AUTUMN_ZUBBA_HIVE, - CCW_ZUBBA_SPECIFIC_FLAG_8_AUTUMN_DIALOG, - 0, // [port] decomp uses NULL; jiggyId is an integer, not a pointer - VER_SELECT(ASSET_CE5_DIALOG_ZUBBA_MEET_FALL, 0x09FA, 0, 0) - }, - { 0 } // [port] decomp uses NULL; first field is an integer and clang errors on -Wint-conversion -}; - -ActorInfo chZubbaDocile = { - MARKER_1AF_ZUBBA_DOCILE, ACTOR_29C_ZUBBA_DOCILE, ASSET_446_MODEL_ZUBBA, - 0x0, NULL, - chZubbaDocile_update, NULL, actor_draw, - 0, 0, 1.0f, 0 -}; - -enum chzubbadocile_state_e { - CH_ZUBBA_DOCILE_STATE_0_NOT_INIT, - CH_ZUBBA_DOCILE_STATE_1_DOCILE -}; - -/* .code */ -void chZubbaDocile_setState(Actor *this, s32 next_state) { - ActorLocal_ZubbaDocile *local = (ActorLocal_ZubbaDocile *)&this->local; - int i; - - if (next_state == CH_ZUBBA_DOCILE_STATE_1_DOCILE) { - if (skeletalAnim_getAnimId(this->unk148) != ASSET_16F_ANIM_ZUBBA_FLY_MOVE) { - skeletalAnim_set(this->unk148, ASSET_16F_ANIM_ZUBBA_FLY_MOVE, 0.1f, 0.65f); - } - for(i = 0; i < 10; i++){ - local->targetPosition[0] = randf2(-500.0f, 500.0f); - local->targetPosition[1] = randf2(400.0f, 900.0f); - local->targetPosition[2] = randf2(-400.0f, 700.0f); - if(ml_vec3f_distance(this->position, local->targetPosition) > 800.0f) - break; - } - local->unk8 = randf2(500.0f, 1000.0f); - } - this->state = next_state; -} - -void chZubbaDocile_free(Actor *this){ - ActorLocal_ZubbaDocile *local = (ActorLocal_ZubbaDocile *)&this->local; - sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); -} - -void chZubbaDocile_update(Actor *this) { - ActorLocal_ZubbaDocile *local; - f32 time_delta; - f32 distance[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; - f32 player_position[3]; - - local = (ActorLocal_ZubbaDocile *)&this->local; - time_delta = time_getDelta(); - if (!this->volatile_initialized) { - this->volatile_initialized = true; - this->marker->actorFreeFunc = chZubbaDocile_free; - local->dialog = &chZubbaDocileDialog[0]; - while((local->dialog->map != 0) && (gsworld_getMap() != local->dialog->map)) { - local->dialog++; - } - local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); - local->unk18[0] = local->unk18[1] = local->unk18[2] = 0.0f; - sfxsource_setSfxId(local->sfxsourceIdx, SFX_3FA_HONEYCOMB_TALKING); - sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 2); - sfxsource_playSfxAtVolume(local->sfxsourceIdx, 0.9f); - sfxsource_setSampleRate(local->sfxsourceIdx, 0); - chZubbaDocile_setState(this, CH_ZUBBA_DOCILE_STATE_1_DOCILE); - return; - } - - if (this->state == CH_ZUBBA_DOCILE_STATE_1_DOCILE) { - distance[0] = local->targetPosition[0] - this->position[0]; - distance[1] = local->targetPosition[1] - this->position[1]; - distance[2] = local->targetPosition[2] - this->position[2]; - if (ml_vec3f_distance(this->position, local->targetPosition) < 500.0f) { - ml_vec3f_set_length(distance, local->unk8 * 8.0f); - } else { - ml_vec3f_set_length(distance, local->unk8 * 2); - } - this->position[0] += (local->unk18[0] * time_delta) + (distance[0] * time_delta * time_delta); - this->position[1] += (local->unk18[1] * time_delta) + (distance[1] * time_delta * time_delta); - this->position[2] += (local->unk18[2] * time_delta) + (distance[2] * time_delta * time_delta); - local->unk18[0] += distance[0] * time_delta; - local->unk18[1] += distance[1] * time_delta; - local->unk18[2] += distance[2] * time_delta; - if (local->unk8 < LENGTH_VEC3F(local->unk18)) { - ml_vec3f_set_length(local->unk18, local->unk8); - } - func_80258A4C( - this->position, this->yaw - 90.0f, local->targetPosition, - &horizontal_distance, &distance_in_front, &side_angle_radian); - this->yaw += 140.0f * side_angle_radian * time_delta; - if (ml_vec3f_distance(this->position, local->targetPosition) < 100.0f) { - chZubbaDocile_setState(this, CH_ZUBBA_DOCILE_STATE_1_DOCILE); - } - } - - if(this->position[0]); - - func_8030DBFC(local->sfxsourceIdx, 0.8f, 0.9f, 0.05f); - sfxsource_set_fade_distances(local->sfxsourceIdx, 500.0f, 1500.0f); - sfxsource_set_position(local->sfxsourceIdx, this->position); - sfxSource_func_8030E2C4(local->sfxsourceIdx); - sfxsource_setSampleRate(local->sfxsourceIdx, 2000.0f + 8000.0f * (LENGTH_VEC3F(local->unk18) / local->unk8)); - if (!mapSpecificFlags_get(local->dialog->mapFlag)) { - player_getPosition(player_position); - if (player_position[2] > -600.0f) { - if (!local->dialog->jiggyId - || !jiggyscore_isCollected(local->dialog->jiggyId)) - { - gcdialog_showDialog(local->dialog->textId, 4, NULL, NULL, NULL, NULL); - mapSpecificFlags_set(local->dialog->mapFlag, true); - } - } - } -} diff --git a/src/fight/chbossjinjo.c b/src/FINALE/ch/chbossjinjo.c similarity index 99% rename from src/fight/chbossjinjo.c rename to src/FINALE/ch/chbossjinjo.c index 3fb61196b..2d43be5ca 100644 --- a/src/fight/chbossjinjo.c +++ b/src/FINALE/ch/chbossjinjo.c @@ -3,7 +3,7 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "fight.h" +#include "../fight.h" #include "core2/particle.h" extern void func_80324CFC(f32, enum comusic_e, s32); diff --git a/src/fight/chbossjinjobase.c b/src/FINALE/ch/chbossjinjobase.c similarity index 95% rename from src/fight/chbossjinjobase.c rename to src/FINALE/ch/chbossjinjobase.c index 1cc5265b1..f73718b4c 100644 --- a/src/fight/chbossjinjobase.c +++ b/src/FINALE/ch/chbossjinjobase.c @@ -1,13 +1,11 @@ // BanjoDecomp: fight/chbossjinjobase.c -#include "fight.h" +#include "../fight.h" #include "functions.h" #include "variables.h" #include #include -#include "port/Network/Anchor/FightSync.h" - typedef struct { u8 sfxsourceIdx; } ActorLocal_BossJinjoBase; @@ -49,15 +47,9 @@ void chBossJinjoBase_func_8038D3DC(Actor *this, s32 arg1, f32 arg2, f32 arg3, f3 void chBossJinjoBase_getHitByEgg(ActorMarker *this, ActorMarker *other) { Actor *actor_bossjinjobase = marker_getActor(this); - // Anchor: follower forwards to authority; accepted egg replays here via EGG_FED (other == NULL). - if (other != NULL && FightSync_ForwardEgg(actor_bossjinjobase->actorTypeSpecificField, 0)) { - return; - } - if (actor_bossjinjobase->state != CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { comusic_playTrack(COMUSIC_2B_DING_B); actor_bossjinjobase->unk38_31++; - FightSync_ReplicateEgg(actor_bossjinjobase->actorTypeSpecificField, 0); if (actor_bossjinjobase->unk38_31 >= 3) { subaddie_set_state(actor_bossjinjobase, CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO); diff --git a/src/fight/chbossshadow.c b/src/FINALE/ch/chbossshadow.c similarity index 97% rename from src/fight/chbossshadow.c rename to src/FINALE/ch/chbossshadow.c index 48bda115e..153ac9ed8 100644 --- a/src/fight/chbossshadow.c +++ b/src/FINALE/ch/chbossshadow.c @@ -2,7 +2,7 @@ #include #include "functions.h" #include "variables.h" -#include "fight.h" +#include "../fight.h" ActorInfo chBossShadow = { MARKER_288_GRUNTY_SHADOW, ACTOR_3AF_GRUNTY_SHADOW, ASSET_3BF_MODEL_PLAYER_SHADOW, 1, NULL, chBossShadow_update, actor_update_func_80326224, chBossShadow_draw, 0, 0, 0.0f, 0 }; diff --git a/src/fight/chfinalboss.c b/src/FINALE/ch/chfinalboss.c similarity index 95% rename from src/fight/chfinalboss.c rename to src/FINALE/ch/chfinalboss.c index 5b2b3f511..90aad6680 100644 --- a/src/fight/chfinalboss.c +++ b/src/FINALE/ch/chfinalboss.c @@ -1,16 +1,15 @@ // BanjoDecomp: fight/chfinalboss.c -#include "fight.h" +#include "../fight.h" #include "functions.h" #include "variables.h" #include #include -#include "port/Network/Anchor/FightSync.h" - extern bool func_8028F4B8(f32[3], f32, f32); extern int func_80320ED8(ActorMarker *, f32, s32); s32 subaddie_getYawToPosition(Actor*, f32*); +Actor *actor_spawnWithYaw_f32(); extern Actor* func_80329958(ActorMarker *this, s32 arg1); extern void func_803298D8(); extern void func_80324CFC(f32, enum comusic_e, s32); @@ -21,8 +20,6 @@ extern void player_setIdealRotation(f32[3]); extern f32 func_8033229C(ActorMarker *); void func_8034DF30(Struct6Ds *, f32[3], f32[3], f32); -// ActorLocal_FinalBoss moved to fight.h for the Anchor fight-sync layer. -#if 0 typedef struct chfinalboss_s { u8 phase; u8 hits; @@ -49,7 +46,6 @@ typedef struct chfinalboss_s { f32 unk28; f32 unk2C; } ActorLocal_FinalBoss; -#endif f32 fight_D_80391380[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; f32 fight_D_80391390[4] = { 0.33f, 0.33f, 0.33f, 1.0f }; @@ -144,8 +140,6 @@ f32 D_80392750; f32 D_80392758[3]; f32 D_80392768[3]; f32 D_80392778[3]; -// Anchor: lead time from the last local aim; followers reuse it to re-aim at their own player. -f32 __chFinalBossFireballFlightTime; f32 chFinalBossPlayerPosition[3]; f32 chFinalBossPosition[3]; ActorMarker *__chFinalBossShadowMarker; @@ -167,9 +161,9 @@ Actor *chfinalboss_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { Actor *this = marker_getActor(marker); ActorLocal_FinalBoss *local = (ActorLocal_FinalBoss *)&this->local; - modelRender_setAppendageVisibility(3, local->unkD); - modelRender_setAppendageVisibility(4, local->unkE); - modelRender_setAppendageVisibility(5, local->unkC); + func_8033A45C(3, local->unkD); + func_8033A45C(4, local->unkE); + func_8033A45C(5, local->unkC); if (local->phase == FINALBOSS_PHASE_1_BROOMSTICK) { modelRender_func_8033A25C(false); @@ -314,7 +308,7 @@ void chfinalboss_func_80386B54(f32 *arg0, f32 arg1) { } } -bool chfinalboss_turnTowardPlayer(Actor *this, f32 arg1) { +bool chfinalboss_func_80386BEC(Actor *this, f32 arg1) { this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, arg1); if ((this->yaw_ideal < (this->yaw + arg1)) && ((this->yaw - arg1) < this->yaw_ideal)) { @@ -353,7 +347,7 @@ void chfinalboss_func_80386CF8(Actor *actor) { sp4C[0] = sp28[0] + sp34[0]; sp4C[1] = sp28[1] + sp34[1]; sp4C[2] = sp28[2] + sp34[2]; - ml_horizontal_and_vertical_angles(sp28[0], sp28[1], sp28[2], sp4C[0], sp4C[1], sp4C[2], &sp40[0], &sp40[1]); + func_8025727C(sp28[0], sp28[1], sp28[2], sp4C[0], sp4C[1], sp4C[2], &sp40[0], &sp40[1]); sp40[0] = 360.0f - sp40[0]; sp40[2] = 0.0f; ncStaticCamera_setPositionAndRotation(sp4C, sp40); @@ -366,13 +360,8 @@ void __chfinalboss_dropHealth(ActorMarker *marker) { } void chfinalboss_despawnFlightPad(void) { - // Anchor: a follower that joined late never spawned one. - if (__chFinalBossFlightPadMarker == NULL) { - return; - } marker_despawn(__chFinalBossFlightPadMarker); __chFinalBossFlightPadMarker = NULL; - FightSync_OnFlightPadDespawned(); } void chfinalboss_spawnFlightPad(s32 arg0) { @@ -383,7 +372,6 @@ void chfinalboss_spawnFlightPad(s32 arg0) { flight_pad->alpha_124_19 = 0; flight_pad->unk38_31 = 6; __chFinalBossFlightPadMarker = flight_pad->marker; - FightSync_OnFlightPadSpawned(); } void chfinalboss_func_80386EC0(s32 arg0) { @@ -392,8 +380,6 @@ void chfinalboss_func_80386EC0(s32 arg0) { marker = actor_spawnWithYaw_f32(0x38A, D_80392758, 0)->marker; func_8030E878(SFX_147_GRUNTY_SPELL_ATTACK_2, randf2(0.95f, 1.05f), 32000, D_80392758, 5000.0f, 12000.0f); chGreenBlast_func_803900DC(marker, D_80392758, D_80392768[1], D_80392768[2]); - // Anchor: replay this green blast on followers with the exact same vectors. - FightSync_OnSpellSpawned(2); } void chfinalboss_func_80386F5C(ActorMarker * arg0, f32 arg1[3], f32 arg2, f32 arg3) { @@ -412,8 +398,6 @@ void chfinalboss_func_80386FD8(s32 arg0) { marker = actor_spawnWithYaw_f32(0x389, D_80392758, 0)->marker; func_8030E878(SFX_146_GRUNTY_SPELL_ATTACK_1, randf2(0.95f, 1.05f), 32000, D_80392758, 5000.0f, 12000.0f); chSpellFireball_func_8038FB84(marker, D_80392758, D_80392768, D_80392778); - // Anchor: replay this fireball on followers with the exact same vectors. - FightSync_OnSpellSpawned(0); } void chfinalboss_func_80387074(s32 arg0) { @@ -422,11 +406,9 @@ void chfinalboss_func_80387074(s32 arg0) { marker = actor_spawnWithYaw_f32(0x3AA, D_80392758, 0)->marker; func_8030E878(SFX_146_GRUNTY_SPELL_ATTACK_1, randf2(0.95f, 1.05f), 32000, D_80392758, 5000.0f, 12000.0f); chSpellFireball_func_8038FB84(marker, D_80392758, D_80392768, D_80392778); - // Anchor: replay this final-spell fireball on followers with the exact same vectors. - FightSync_OnSpellSpawned(1); } -void chfinalboss_throwObject(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3) { +void chfinalboss_func_80387110(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3) { Actor *temp_v0; ActorLocal_FinalBoss *local; f32 sp2C[3]; @@ -459,7 +441,6 @@ void chfinalboss_throwObject(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg D_80392768[i] = (sp2C[i] - arg1[i]) / arg2 - (D_80392778[i] * arg2 / 2); } if (arg3 == 0) { - __chFinalBossFireballFlightTime = arg2; SPAWNQUEUE_ADD_1(chfinalboss_func_80386FD8, marker); } else{ @@ -467,14 +448,14 @@ void chfinalboss_throwObject(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg } } -void chfinalboss_throwFinalSpell(Actor *arg0) { +void chfinalboss_func_803872F8(Actor *arg0) { f32 vec[3]; vec3fArray_get_vec3f(arg0->marker->unk44, 0xA, vec); - chfinalboss_throwObject(arg0->marker, vec, 3.0f, 1); + chfinalboss_func_80387110(arg0->marker, vec, 3.0f, 1); } -s32 chfinalboss_throwFireball(Actor *this, f32 arg1) { +s32 chfinalboss_func_80387340(Actor *this, f32 arg1) { f32 sp24[3]; if (actor_animationIsAt(this, 0.50f) != 0) { @@ -485,7 +466,7 @@ s32 chfinalboss_throwFireball(Actor *this, f32 arg1) { sp24[1] = this->position_y; sp24[2] = this->position_z; } - chfinalboss_throwObject(this->marker, sp24, arg1, 0); + chfinalboss_func_80387110(this->marker, sp24, arg1, 0); return 1; } return 0; @@ -947,7 +928,7 @@ void chfinalboss_phase1_update(ActorMarker *marker) { chfinalboss_func_80386600(this->marker, 0); chfinalboss_spawnBroomstickGlowParticles(this); chfinalboss_func_80387ACC(this, 60.0f * sp54); - if (chfinalboss_turnTowardPlayer(this, 240.0f * sp54)) { + if (chfinalboss_func_80386BEC(this, 240.0f * sp54)) { chfinalboss_phase1_setState(this, 5); chfinalboss_func_80386654(1.0f, fight_D_80391380, fight_D_80391390); } @@ -1045,9 +1026,9 @@ void chfinalboss_phase1_update(ActorMarker *marker) { break; case 10: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_turnTowardPlayer(this, 30.0f); + chfinalboss_func_80386BEC(this, 30.0f); chfinalboss_func_8038871C(this, 460.0f, 400.0f * sp54); - chfinalboss_throwFireball(this, 1.0f); + chfinalboss_func_80387340(this, 1.0f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_phase1_setState(this, 2); chfinalboss_func_803880A0(this, 2000.0f); @@ -1055,14 +1036,14 @@ void chfinalboss_phase1_update(ActorMarker *marker) { break; case 11: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_turnTowardPlayer(this, 30.0f); + chfinalboss_func_80386BEC(this, 30.0f); if (local->unk9) { chfinalboss_func_8038871C(this, 460.0f, 400.0f * sp54); } break; case 12: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_turnTowardPlayer(this, 30.0f); + chfinalboss_func_80386BEC(this, 30.0f); chfinalboss_func_8038871C(this, 460.0f, 400.0f * sp54); chfinalboss_func_803873DC(this, 600.0f, 2000.0f); if (actor_animationIsAt(this, 0.9999f)) { @@ -1073,7 +1054,7 @@ void chfinalboss_phase1_update(ActorMarker *marker) { break; case 13: chfinalboss_func_80387ACC(this, 60.0f * sp54); - chfinalboss_turnTowardPlayer(this, 30.0f); + chfinalboss_func_80386BEC(this, 30.0f); if (actor_animationIsAt(this, 0.9999f)) { if (local->hits >= 4) { chfinalboss_phase1_setState(this, 0xB); @@ -1146,13 +1127,13 @@ void chfinalboss_phase2_update(ActorMarker *marker) { break; case 15: - if (chfinalboss_turnTowardPlayer(this, 9.0f)) { + if (chfinalboss_func_80386BEC(this, 9.0f)) { chfinalboss_phase2_setState(this, 0x10); } break; case 16: - chfinalboss_turnTowardPlayer(this, 3.0f); - chfinalboss_throwFireball(this, 1.3f); + chfinalboss_func_80386BEC(this, 3.0f); + chfinalboss_func_80387340(this, 1.3f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_phase2_setState(this, 0x12); local->unk3++; @@ -1166,19 +1147,19 @@ void chfinalboss_phase2_update(ActorMarker *marker) { } break; case 17: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); chfinalboss_func_803873DC(this, 1200.0f, 2400.0f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_setPhase(this->marker, FINALBOSS_PHASE_3_FLIGHT); } break; case 18: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); if (this->lifetime_value > 0.0) { this->lifetime_value = this->lifetime_value - sp4C; break; } - if (chfinalboss_turnTowardPlayer(this, 3.0f)) { + if (chfinalboss_func_80386BEC(this, 3.0f)) { chfinalboss_phase2_setState(this, 0x10); } break; @@ -1239,7 +1220,6 @@ void __chfinalboss_spawnStatue(enum ch_bossjinjo_e statue_id) { } sp1C->lifetime_value = (statue_id == BOSSJINJO_5_JINJONATOR) ? 5.25f : 1.54f; sp1C->actorTypeSpecificField = statue_id; - FightSync_OnStatueSpawned(statue_id); } void chfinalboss_spawnStatue(s32 statue_id) { @@ -1252,7 +1232,6 @@ void __chfinalboss_spawnSpellBarrier(ActorMarker *marker) { actor = marker_getActor(marker); actor->partnerActor = spawn_child_actor(ACTOR_3AB_GRUNTY_SPELL_BARRIER, &actor)->marker; __chFinalBossSpellBarrierActive = true; - FightSync_OnBarrierSpawned(); } void chfinalboss_spawnSpellBarrier(ActorMarker *arg0) { @@ -1354,13 +1333,13 @@ void chfinalboss_phase3_update(ActorMarker *marker) { } break; case 23: - if (chfinalboss_turnTowardPlayer(this, 9.0f) && (baiFrame_getState() != 3)) { + if (chfinalboss_func_80386BEC(this, 9.0f) && (baiFrame_getState() != 3)) { chfinalboss_phase3_setState(this, 0x18); } break; case 24: - chfinalboss_turnTowardPlayer(this, 3.0f); - if (chfinalboss_throwFireball(this, 1.3f)) { + chfinalboss_func_80386BEC(this, 3.0f); + if (chfinalboss_func_80387340(this, 1.3f)) { local->unk3++; } if (actor_animationIsAt(this, 0.9999f)) { @@ -1567,8 +1546,6 @@ void chfinalboss_phase4_update(ActorMarker *marker) { sp70 = local->hits; sp6C = chfinalboss_findCollidingJinjo(this, func_8033229C(this->marker)); if (sp6C != NULL) { - // Anchor: only the authority detects the slam; despawn followers' copy of this jinjo too. - FightSync_OnJinjoSlam(marker_getActor(sp6C)->actorTypeSpecificField); chbossjinjo_attack(sp6C); if (!fileProgressFlag_get(FILEPROG_D1_HAS_ACTIVATED_A_JINJO_STATUE_IN_FINAL_FIGHT)) { fileProgressFlag_set(FILEPROG_D1_HAS_ACTIVATED_A_JINJO_STATUE_IN_FINAL_FIGHT, true); @@ -1603,15 +1580,15 @@ void chfinalboss_phase4_update(ActorMarker *marker) { break; case 29: - if ((chfinalboss_turnTowardPlayer(this, 9.0f)) && (baiFrame_getState() != 3) && (sFinalBossJinjoStatueActivated == 0)) { + if ((chfinalboss_func_80386BEC(this, 9.0f)) && (baiFrame_getState() != 3) && (sFinalBossJinjoStatueActivated == 0)) { chfinalboss_phase4_setState(this, 0x1E); } break; case 30: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); if (sFinalBossJinjoStatueActivated == 0) { - chfinalboss_throwFireball(this, 1.0f); + chfinalboss_func_80387340(this, 1.0f); if (actor_animationIsAt(this, 0.9999f)) { local->unk3++; chfinalboss_phase4_setState(this, 0x1F); @@ -1623,12 +1600,12 @@ void chfinalboss_phase4_update(ActorMarker *marker) { break; case 31: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); if (this->lifetime_value > 0.0) { this->lifetime_value -= sp74; break; } - if (chfinalboss_turnTowardPlayer(this, 3.0f)) { + if (chfinalboss_func_80386BEC(this, 3.0f)) { chfinalboss_phase4_setState(this, 0x1E); } break; @@ -1640,7 +1617,7 @@ void chfinalboss_phase4_update(ActorMarker *marker) { break; case 33: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); sp5C[0] = this->position[0] + (this->velocity[0] * sp74); sp5C[1] = this->position[1] + (this->velocity[1] * sp74); sp5C[2] = this->position[2] + (this->velocity[2] * sp74); @@ -1838,22 +1815,22 @@ void chfinalboss_phase5_update(ActorMarker *marker) { } switch (this->state) { case 35: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); break; case 36: - if (chfinalboss_turnTowardPlayer(this, 9.0f) && (baiFrame_getState() != 3)) { + if (chfinalboss_func_80386BEC(this, 9.0f) && (baiFrame_getState() != 3)) { chfinalboss_phase5_setState(this, 0x25); } break; case 37: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); if (baiFrame_getState() == 3) { chfinalboss_phase5_setState(this, 0x24); break; } - if (chfinalboss_throwFireball(this, 1.0f)) { + if (chfinalboss_func_80387340(this, 1.0f)) { local->unk3++; } if ((actor_animationIsAt(this, 0.9999f)) && (local->unk3 >= 5)) { @@ -1862,7 +1839,7 @@ void chfinalboss_phase5_update(ActorMarker *marker) { break; case 38: - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); chfinalboss_func_803873DC(this, 700.0f, 2400.0f); if (actor_animationIsAt(this, 0.9999f)) { chfinalboss_phase5_setState(this, 0x27); @@ -1874,7 +1851,7 @@ void chfinalboss_phase5_update(ActorMarker *marker) { if (local->unk8) { chfinalboss_func_80386C68(this, 4.5f); } else { - chfinalboss_turnTowardPlayer(this, 3.0f); + chfinalboss_func_80386BEC(this, 3.0f); } if (this->lifetime_value > 0.0) { this->lifetime_value -= dt; @@ -1947,7 +1924,7 @@ void chfinalboss_phase5_update(ActorMarker *marker) { FUNC_8030E624(SFX_130_GRUNTY_ECHOING_CRY, 1.0f, 32000); } if (actor_animationIsAt(this, 0.85f)) { - chfinalboss_throwFinalSpell(this); + chfinalboss_func_803872F8(this); } if (actor_animationIsAt(this, 0.9f)) { ncStaticCamera_exit(); @@ -2043,10 +2020,6 @@ void chfinalboss_collisionPassive(ActorMarker *marker, ActorMarker *other_marker this = marker_getActor(marker); local = (ActorLocal_FinalBoss *)&this->local; - // Anchor: follower's hit is forwarded to the authority (with phase). - if (other_marker != NULL && FightSync_ForwardBossHit(local->phase)) { - return; - } switch (local->phase) { case 1: if (local->hits == 0) { @@ -2150,7 +2123,6 @@ void chfinalboss_update(Actor *this){ local->unk8 = 0; local->unk9 = 0; local->unkB = 0; - FightSync_OnBossSpawned(); for(i = 0; i < 4; i++){ __chFinalBossJinjoStatueMarker[i] = NULL; @@ -2176,8 +2148,6 @@ void chfinalboss_update(Actor *this){ timed_playSfx(2.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 32000); }//L8038BF0C - // Anchor: followers skip the boss brain - state rides FIGHT_UPDATE/FIGHT_EVENT instead. - if (!FightSync_BossFollowerTick(this)) switch(local->phase) { case FINALBOSS_PHASE_0_INTRO: chfinalboss_phase0_update(this->marker); @@ -2271,7 +2241,6 @@ void chfinalboss_setBossDefeated(void) { sp4C = actorArray_findActorFromActorId(ACTOR_38B_GRUNTILDA_FINAL_BOSS); sp48 = (ActorLocal_FinalBoss *)&sp4C->local; - FightSync_OnBossDefeated(); sp34 = chstonejinjo_getBreakUpTime(); temp_f20 = sp34 + chjinjonator_80391234(); sp40 = chjinjonator_80391240(); diff --git a/src/fight/chjinjonator.c b/src/FINALE/ch/chjinjonator.c similarity index 99% rename from src/fight/chjinjonator.c rename to src/FINALE/ch/chjinjonator.c index 4566ed1b9..470f72003 100644 --- a/src/fight/chjinjonator.c +++ b/src/FINALE/ch/chjinjonator.c @@ -2,7 +2,7 @@ #include #include "functions.h" #include "variables.h" -#include "fight.h" +#include "../fight.h" extern void func_80324CFC(f32, s32, s32); extern void func_802F9E44(s32, f32, f32, f32, f32); diff --git a/src/fight/chjinjonatorbase.c b/src/FINALE/ch/chjinjonatorbase.c similarity index 85% rename from src/fight/chjinjonatorbase.c rename to src/FINALE/ch/chjinjonatorbase.c index 591f74524..e2d52a7e4 100644 --- a/src/fight/chjinjonatorbase.c +++ b/src/FINALE/ch/chjinjonatorbase.c @@ -2,9 +2,7 @@ #include #include "functions.h" #include "variables.h" -#include "fight.h" - -#include "port/Network/Anchor/FightSync.h" +#include "../fight.h" typedef struct { u8 egg_hits[4]; @@ -44,16 +42,18 @@ void chjinjonatorbase_func_8038E0D4(Actor *arg0, s32 arg1, f32 arg2, f32 arg3, f } } -static void __chjinjonatorbase_applyEgg(Actor *actor_jinjonatorbase, s32 indx) { +void chjinjonatorbase_getHitByEgg(ActorMarker *this, ActorMarker *other) { + Actor *actor_jinjonatorbase = marker_getActor(this); ActorLocal_BossJinjonatorBase *local = (ActorLocal_BossJinjonatorBase *) &actor_jinjonatorbase->local; + int indx = this->unk40_31 - 1; s32 remaining_hits; + f32 pad; if (actor_jinjonatorbase->state != CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { if (local->egg_hits[indx]) { local->egg_hits[indx]--; comusic_playTrack(COMUSIC_2B_DING_B); - FightSync_ReplicateEgg(BOSSJINJO_5_JINJONATOR, indx); - + if (local->egg_hits[indx] <= 0) { chjinjonatorbase_func_8038E0D4(actor_jinjonatorbase, indx + 0x19a, -100.0f, 0.0f, 1.2f); func_80324D54(1.2f, SFX_90_SWITCH_PRESS, 1.0f, 32000, actor_jinjonatorbase->position, 1000.0f, 2000.0f); @@ -70,46 +70,6 @@ static void __chjinjonatorbase_applyEgg(Actor *actor_jinjonatorbase, s32 indx) { } } -void chjinjonatorbase_getHitByEgg(ActorMarker *this, ActorMarker *other) { - Actor *actor_jinjonatorbase = marker_getActor(this); - int indx = this->unk40_31 - 1; - - // Anchor: follower forwards to authority; accepted egg replays via EGG_FED. - if (other != NULL && FightSync_ForwardEgg(BOSSJINJO_5_JINJONATOR, indx)) { - return; - } - - __chjinjonatorbase_applyEgg(actor_jinjonatorbase, indx); -} - -// Anchor: remaining-egg count per pad for the latecomer snapshot; false if pedestal isn't up. -bool chjinjonatorbase_netGetPads(u8 pads[4]) { - Actor *actor_jinjonatorbase = actorArray_findActorFromActorId(ACTOR_3A9_JINJONATOR_STATUE_BASE); - ActorLocal_BossJinjonatorBase *local; - s32 i; - - if (actor_jinjonatorbase == NULL || actor_jinjonatorbase->despawn_flag) { - for (i = 0; i < 4; i++) { - pads[i] = 5; - } - return false; - } - local = (ActorLocal_BossJinjonatorBase *) &actor_jinjonatorbase->local; - for (i = 0; i < 4; i++) { - pads[i] = local->egg_hits[i]; - } - return true; -} - -void chjinjonatorbase_netApplyEgg(s32 pad_index) { - Actor *actor_jinjonatorbase = actorArray_findActorFromActorId(ACTOR_3A9_JINJONATOR_STATUE_BASE); - - if (actor_jinjonatorbase == NULL || pad_index < 0 || pad_index >= 4) { - return; - } - __chjinjonatorbase_applyEgg(actor_jinjonatorbase, pad_index); -} - void chjinjonatorbase_spawnActivator(ActorMarker *marker) { Actor *sp24 = marker_getActor(marker); diff --git a/src/fight/chgreenblast.c b/src/FINALE/chgreenblast.c similarity index 100% rename from src/fight/chgreenblast.c rename to src/FINALE/chgreenblast.c diff --git a/src/fight/chspellbarrier.c b/src/FINALE/chspellbarrier.c similarity index 100% rename from src/fight/chspellbarrier.c rename to src/FINALE/chspellbarrier.c diff --git a/src/fight/chspellfireball.c b/src/FINALE/chspellfireball.c similarity index 100% rename from src/fight/chspellfireball.c rename to src/FINALE/chspellfireball.c diff --git a/src/fight/chstonejinjo.c b/src/FINALE/chstonejinjo.c similarity index 100% rename from src/fight/chstonejinjo.c rename to src/FINALE/chstonejinjo.c diff --git a/src/fight/fight.c b/src/FINALE/fight.c similarity index 99% rename from src/fight/fight.c rename to src/FINALE/fight.c index c22543b63..c068e4ef9 100644 --- a/src/fight/fight.c +++ b/src/FINALE/fight.c @@ -6,6 +6,8 @@ #include "fight.h" #include "actor.h" +u8 sFightPadding[0x10]; + void fight_addSpawnableActors(void) { spawnableActorList_add(&chSpellFireball, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20); diff --git a/src/fight/fight.h b/src/FINALE/fight.h similarity index 94% rename from src/fight/fight.h rename to src/FINALE/fight.h index 7f960766a..d0bcd7bda 100644 --- a/src/fight/fight.h +++ b/src/FINALE/fight.h @@ -84,34 +84,6 @@ extern ActorInfo chGreenBlast; extern ActorInfo chJinjonator; extern ActorInfo chBossShadow; -// Moved from chfinalboss.c for the Anchor fight-sync layer. -typedef struct chfinalboss_s { - u8 phase; - u8 hits; - u8 unk2; - u8 unk3; - u8 unk4; - u8 unk5; - u8 player_hit_in_phase3; - u8 mirror_phase5; - u8 unk8; - u8 unk9; - u8 unkA; - u8 unkB; - u8 unkC; - u8 unkD; - u8 unkE; - u8 unkF; - s32 player_hit_in_phase1; - f32 unk14; - f32 unk18; - f32 unk1C; - f32 unk20; - u8 pad24[4]; - f32 unk28; - f32 unk2C; -} ActorLocal_FinalBoss; - // fight.c extern void fight_addSpawnableActors(void); @@ -127,7 +99,7 @@ extern void chfinalboss_createGreenGlowParticle(f32 position[3], s32 color[3]); extern void chfinalboss_createSingleSpriteParticle(f32 position[3], enum asset_e sprite_id); extern void chfinalboss_spawnBroomstickGlowParticles(Actor *this); extern void chfinalboss_func_80386B54(f32 *arg0, f32 arg1); -extern bool chfinalboss_turnTowardPlayer(Actor *this, f32 arg1); +extern bool chfinalboss_func_80386BEC(Actor *this, f32 arg1); extern bool chfinalboss_func_80386C68(Actor *this, f32 arg1); extern void chfinalboss_func_80386CF8(Actor *actor); extern void __chfinalboss_dropHealth(ActorMarker *arg0); @@ -137,9 +109,9 @@ extern void chfinalboss_func_80386EC0(s32 arg0); extern void chfinalboss_func_80386F5C(ActorMarker * arg0, f32 arg1[3], f32 arg2, f32 arg3); extern void chfinalboss_func_80386FD8(s32 arg0); extern void chfinalboss_func_80387074(s32 arg0); -extern void chfinalboss_throwObject(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3); -extern void chfinalboss_throwFinalSpell(Actor *arg0); -extern s32 chfinalboss_throwFireball(Actor *this, f32 arg1); +extern void chfinalboss_func_80387110(ActorMarker *marker, f32 arg1[3], f32 arg2, s32 arg3); +extern void chfinalboss_func_803872F8(Actor *arg0); +extern s32 chfinalboss_func_80387340(Actor *this, f32 arg1); extern void chfinalboss_func_803873DC(Actor *actor, f32 arg1, f32 arg2); extern bool chfinalboss_flyTo(Actor *this, f32 arg1[3], f32 v_max, f32 arg3, f32 arg4, f32 arg5, f32 arg6); extern void chfinalboss_func_8038770C(Actor *actor); diff --git a/src/FP/fpspawnqueue.c b/src/FP/actor_spawninit.c similarity index 99% rename from src/FP/fpspawnqueue.c rename to src/FP/actor_spawninit.c index bf98e1dec..119c2a794 100644 --- a/src/FP/fpspawnqueue.c +++ b/src/FP/actor_spawninit.c @@ -1,4 +1,4 @@ -// BanjoDecomp: FP/fpspawnqueue.c +// BanjoDecomp: code_ABD0.c #include #include "core1/core1.h" #include "functions.h" @@ -213,7 +213,7 @@ void func_80391744(Actor *this, Actor* other){ f32 tmp_f0; sp24 = nodeprop_findByActorIdAndActorPosition(0x22A, this); - tmp_f0 = (f32)nodeProp_getYaw(sp24); + tmp_f0 = (f32)nodeprop_getYaw(sp24); other->yaw = tmp_f0; this->yaw = tmp_f0; ml_vec3f_yaw_rotate_copy(sp28, sp34, tmp_f0); diff --git a/src/FP/bss_pad.c b/src/FP/bss_pad.c new file mode 100644 index 000000000..d073ba296 --- /dev/null +++ b/src/FP/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_FP_80392F10[0x10]; diff --git a/src/FP/ch/bearcub.c b/src/FP/ch/bearcub.c index 00b474eaf..d6ebfc6b6 100644 --- a/src/FP/ch/bearcub.c +++ b/src/FP/ch/bearcub.c @@ -3,9 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" -#include "port/Enhancements/Retention/Retention.h" - extern void func_8028E668(f32[3], f32, f32, f32); extern bool player_setCarryObjectPoseInHorizontalRadius(f32[3], f32, s32, Actor **); @@ -50,26 +47,6 @@ Struct_FP_3E00 D_80391E80[] ={ {LEVEL_FLAG_13_FP_UNKNOWN, MARKER_1FF_RED_PRESENT_COLLECTIBLE, ACTOR_1F1_RED_PRESENT_COLLECTIBLE, 0x1F2} }; -static const struct { - s32 bit; - s32 kind; - s32 item; -} sCubPresentSync[3] = { - { 0x1, ANCHOR_COLLECTIBLE_PRESENT_BLUE, ITEM_20_BLUE_PRESENT }, - { 0x2, ANCHOR_COLLECTIBLE_PRESENT_GREEN, ITEM_1F_GREEN_PRESENT }, - { 0x4, ANCHOR_COLLECTIBLE_PRESENT_RED, ITEM_21_RED_PRESENT }, -}; - -// D_80391E80 row for this cub, or -1. Same mapping the state machine derives inline (sp3C). -static s32 __chBearcub_cubIndex(Actor *this) { - switch (this->marker->id) { - case MARKER_1FA_POLAR_BEAR_CUB_BLUE: return 0; - case MARKER_1FB_POLAR_BEAR_CUB_GREEN: return 1; - case MARKER_1FC_POLAR_BEAR_CUB_RED: return 2; - } - return -1; -} - /* .code */ void func_8038A1F0(Actor **this_ptr, enum marker_e carried_obj_marker_id, enum actor_e actor_id, enum actor_e arg3){ player_setCarryObjectPoseInHorizontalRadius((*this_ptr)->position, 600.0f, actor_id, this_ptr); @@ -78,7 +55,7 @@ void func_8038A1F0(Actor **this_ptr, enum marker_e carried_obj_marker_id, enum a return; } - if (bacarry_getMarkerId() != carried_obj_marker_id) { + if (bacarry_get_markerId() != carried_obj_marker_id) { return; } @@ -102,7 +79,7 @@ void func_8038A274(Actor *this){ } void func_8038A318(ActorMarker *caller, enum asset_e text_id, s32 arg1){ - if(text_id == VER_SELECT(ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3, 0x993, 0, 0)){ + if(text_id == 0xc19){ gcStaticCamera_activate(0x25); jiggy_spawn(JIGGY_2E_FP_PRESENTS, FP_D_80391E74); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 32000); @@ -145,41 +122,12 @@ void func_8038A384(Actor *this){ ){ subaddie_set_state_with_direction(this, 2, randf2(0.0f, 0.9f), 1); } - - // Anchor: reconcile the shared present pool — carried = collected minus delivered. - { - s32 cubIdx = __chBearcub_cubIndex(this); - if (cubIdx >= 0) { - s32 netBits = port_puzzleStep_get(ANCHOR_PUZZLE_FP_PRESENTS); - s32 have = item_getCount(sCubPresentSync[cubIdx].item); - s32 pool = port_carriedSync_collectedCount(sCubPresentSync[cubIdx].kind) - - ((netBits & sCubPresentSync[cubIdx].bit) ? 1 : 0); - if (pool > have) { - item_adjustByDiffWithoutHud(sCubPresentSync[cubIdx].item, pool - have); - } - } - } }//L8038A4E4 - { - s32 cubIdx = __chBearcub_cubIndex(this); - if (cubIdx >= 0) { - s32 netBits; - if (levelSpecificFlags_get(D_80391E80[cubIdx].unk0)) { - port_puzzleStep_orBits(ANCHOR_PUZZLE_FP_PRESENTS, sCubPresentSync[cubIdx].bit); - } - netBits = port_puzzleStep_get(ANCHOR_PUZZLE_FP_PRESENTS); - if ((netBits & sCubPresentSync[cubIdx].bit) && !levelSpecificFlags_get(D_80391E80[cubIdx].unk0)) { - levelSpecificFlags_setEx(D_80391E80[cubIdx].unk0, 1, 0); - subaddie_set_state_with_direction(this, 2, 0.001f, 1); - } - } - } - sp34 = levelSpecificFlags_get(LEVEL_FLAG_11_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_12_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_13_FP_UNKNOWN); - sp38 = (sp34 == 1) ? VER_SELECT(ASSET_C17_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_1, 0x991, 0, 0) - : (sp34 == 2) ? VER_SELECT(ASSET_C18_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_2, 0x992, 0, 0) - : VER_SELECT(ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3, 0x993, 0, 0); + sp38 = (sp34 == 1) ? ASSET_C17_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_1 + : (sp34 == 2) ? ASSET_C18_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_2 + : ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3; this->yaw_ideal = (f32)subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 2.0f); @@ -193,8 +141,8 @@ void func_8038A384(Actor *this){ && !jiggyscore_isCollected(JIGGY_2C_FP_BOGGY_3) && !jiggyscore_isSpawned(JIGGY_2C_FP_BOGGY_3) ){ - if (gcdialog_showDialog(VER_SELECT(ASSET_C1A_DIALOG_BOGGY_KIDS_MEET, 0x994, 0, 0), 0x2a, NULL, NULL, NULL, NULL)) { - levelSpecificFlags_set(LEVEL_FLAG_19_FP_UNKNOWN, TRUE); + if (gcdialog_showDialog(ASSET_C1A_DIALOG_BOGGY_KIDS_MEET, 0x2a, NULL, NULL, NULL, NULL)) { + levelSpecificFlags_set(LEVEL_FLAG_19_FP_UNKNOWN, true); } } } @@ -216,7 +164,7 @@ void func_8038A384(Actor *this){ } if(levelSpecificFlags_get(D_80391E80[sp3C].unk0)){ subaddie_set_state_with_direction(this, 2, 0.001f, 1); - if (sp38 == VER_SELECT(ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3, 0x993, 0, 0)) { + if (sp38 == ASSET_C19_DIALOG_BOGGY_KIDS_PRESENT_RECEIVED_3) { gcdialog_showDialog(sp38, 0x2f, this->position, this->marker, func_8038A318, NULL); } else { diff --git a/src/FP/ch/boggy1.c b/src/FP/ch/boggy1.c index 9e2b5b0ff..7c8ff2353 100644 --- a/src/FP/ch/boggy1.c +++ b/src/FP/ch/boggy1.c @@ -38,8 +38,8 @@ Actor *func_803875E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(!this->unk38_31 || this->state == 5) return this; - modelRender_setAppendageVisibility(1, 0); - modelRender_setAppendageVisibility(3, 1); + func_8033A45C(1, 0); + func_8033A45C(3, 1); this = actor_draw(marker, gfx, mtx, vtx); if(marker->unk14_21){ vec3fArray_get_vec3f(func_80329934(), 5, this->velocity); @@ -86,8 +86,8 @@ void func_803877A8(ActorMarker *caller, enum asset_e text_id, s32 arg2){ void func_80387828(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this = marker_getActor(caller); - if (text_id == VER_SELECT(ASSET_C00_DIALOG_BOGGY_SAVED, 0x97A, 0, 0)) { - gcdialog_showDialog(VER_SELECT(ASSET_C2B_DIALOG_BOGGY_SAVED_2, 0x9A5, 0, 0), 0xf, NULL, this->marker, NULL, func_803877A8); + if (text_id == 0xc00) { + gcdialog_showDialog(ASSET_C2B_DIALOG_BOGGY_SAVED_2, 0xf, NULL, this->marker, NULL, func_803877A8); } } @@ -143,14 +143,14 @@ void func_8038794C(Actor *this){ if(mapSpecificFlags_get(0x1)){ func_8028F94C(1, this->position); timed_setStaticCameraToNode(0.0f, 0x12); - func_80324DBC(1.0f, VER_SELECT(ASSET_C00_DIALOG_BOGGY_SAVED, 0x97A, 0, 0), 0xe, NULL, this->marker, func_80387828, func_803877A8); + func_80324DBC(1.0f, 0xc00, 0xe, NULL, this->marker, func_80387828, func_803877A8); func_803876A4(this); break; }//L80387B38 if(!this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 0x1f4)){ if(!player_movementGroup() || player_movementGroup() == BSGROUP_8_TROT){ - if (gcdialog_showDialog(VER_SELECT(ASSET_BFF_DIALOG_BOGGY_MEET, 0x979, 0, 0), 0x2a, this->position, NULL, NULL, NULL)) { + if (gcdialog_showDialog(ASSET_BFF_DIALOG_BOGGY_MEET, 0x2a, this->position, NULL, NULL, NULL)) { for (i = 0; i < 5; i++) { timedFunc_set_1(D_80391BEC[i], (GenFunction_1) func_8038787C, (uintptr_t)this->marker); } diff --git a/src/FP/ch/boggy2.c b/src/FP/ch/boggy2.c index 776954a99..4b8110cd3 100644 --- a/src/FP/ch/boggy2.c +++ b/src/FP/ch/boggy2.c @@ -64,8 +64,8 @@ Actor *func_80388740(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ ActorLocal_FP_2350 * local = (ActorLocal_FP_2350 *) &this->local; f32 sp2C[3]; - modelRender_setAppendageVisibility(1, 1); - modelRender_setAppendageVisibility(3, 1); + func_8033A45C(1, 1); + func_8033A45C(3, 1); this = actor_draw(marker, gfx, mtx, vtx); if(this->volatile_initialized && marker->unk14_21){ if( this->state == 4 @@ -96,20 +96,20 @@ void FP_func_803888E4(Actor *this){ static f32 D_80391D18[3] = {1463.0f, 635.0f, 5193.0f}; subaddie_set_state_with_direction(this, 0xC, 0.0001f, 1); if(!jiggyscore_isSpawned(JIGGY_30_FP_BOGGY_2)){ - if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_5_WALRUS_RACE_FAILED)){ - func_80324DBC(0.1f, VER_SELECT(ASSET_C06_DIALOG_BOGGY_SLED_WALRUS_SECOND_START, 0x980, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(5)){ + func_80324DBC(0.1f, 0xc06, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } else{//L80388964 - func_80324DBC(0.1f, VER_SELECT(ASSET_C03_DIALOG_BOGGY_SLED_WALRUS_START, 0x97D, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + func_80324DBC(0.1f, 0xc03, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } } else{//L803889A0 func_8028F490(D_80391D0C); - if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_6_BANJO_RACE_FAILED)){ - func_80324DBC(0.1f, VER_SELECT(ASSET_C29_DIALOG_BOGGY_SLED_BEAR_SECOND_START, 0x9A3, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(6)){ + func_80324DBC(0.1f, 0xc29, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } else{ - func_80324DBC(0.1f, VER_SELECT(ASSET_C28_DIALOG_BOGGY_SLED_BEAR_START, 0x9A2, 0, 0), 0x2a, D_80391D18, this->marker, func_80388D70, NULL); + func_80324DBC(0.1f, 0xc28, 0x2a, D_80391D18, this->marker, func_80388D70, NULL); } }//L80388A30 mapSpecificFlags_set(5, true); @@ -126,11 +126,11 @@ void func_80388A50(Actor *this){ void func_80388A94(Actor *this){ func_80388A50(this); - if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_6_BANJO_RACE_FAILED)){ - gcdialog_showDialog(VER_SELECT(ASSET_C0A_DIALOG_BOGGY_SLED_BEAR_MISS_RETRY, 0x984, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(6)){ + gcdialog_showDialog(ASSET_C0A_DIALOG_BOGGY_SLED_BEAR_MISS_RETRY, 0xe, this->position, this->marker, func_80388D70, NULL); } else{ - gcdialog_showDialog(VER_SELECT(ASSET_C09_DIALOG_BOGGY_SLED_BEAR_ANSWER_TO_START, 0x983, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(ASSET_C09_DIALOG_BOGGY_SLED_BEAR_ANSWER_TO_START, 0xe, this->position, this->marker, func_80388D70, NULL); } } @@ -138,17 +138,17 @@ void func_80388B18(Actor *this, u8 arg1){ if(arg1 == true){ if(player_getTransformation() == TRANSFORM_4_WALRUS){ func_80388A50(this); - if(mapSpecificFlags_get(FP_SPECIFIC_FLAG_5_WALRUS_RACE_FAILED)){ - gcdialog_showDialog(VER_SELECT(ASSET_C05_DIALOG_BOGGY_SLED_WALRUS_MISS_RETRY, 0x97F, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); + if(mapSpecificFlags_get(5)){ + gcdialog_showDialog(ASSET_C05_DIALOG_BOGGY_SLED_WALRUS_MISS_RETRY, 0xf, this->position, this->marker, func_80388D70, NULL); } else{ - gcdialog_showDialog(VER_SELECT(ASSET_C02_DIALOG_BOGGY_SLED_WALRUS_MEET, 0x97C, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(ASSET_C02_DIALOG_BOGGY_SLED_WALRUS_MEET, 0xf, this->position, this->marker, func_80388D70, NULL); } } else{//L80388BB8 if(!volatileFlag_get(VOLATILE_FLAG_B3)){ - if(gcdialog_showDialog(VER_SELECT(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0x97B, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL)){ - volatileFlag_set(VOLATILE_FLAG_B3, TRUE); + if(gcdialog_showDialog(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0xe, this->position, this->marker, func_80388D70, NULL)){ + volatileFlag_set(VOLATILE_FLAG_B3, true); func_80388A50(this); } } @@ -157,8 +157,8 @@ void func_80388B18(Actor *this, u8 arg1){ else{//L80388C08 if(player_getTransformation() == TRANSFORM_4_WALRUS){ if(!volatileFlag_get(VOLATILE_FLAG_B4)){ - if(gcdialog_showDialog(VER_SELECT(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0x982, 0, 0), 0xe, this->position, this->marker, func_80388D70, NULL)){ - volatileFlag_set(VOLATILE_FLAG_B4, TRUE); + if(gcdialog_showDialog(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0xe, this->position, this->marker, func_80388D70, NULL)){ + volatileFlag_set(VOLATILE_FLAG_B4, true); func_80388A50(this); } } @@ -198,10 +198,10 @@ void func_80388D70(ActorMarker *caller, enum asset_e text_id, s32 arg2){ timed_exitStaticCamera(0.0f); switch(text_id){ - case VER_SELECT(ASSET_C03_DIALOG_BOGGY_SLED_WALRUS_START, 0x97D, 0, 0): - case VER_SELECT(ASSET_C06_DIALOG_BOGGY_SLED_WALRUS_SECOND_START, 0x980, 0, 0): - case VER_SELECT(ASSET_C28_DIALOG_BOGGY_SLED_BEAR_START, 0x9A2, 0, 0): - case VER_SELECT(ASSET_C29_DIALOG_BOGGY_SLED_BEAR_SECOND_START, 0x9A3, 0, 0)://L80388DC4 + case 0xc03: + case 0xc06: + case 0xc28: + case 0xc29://L80388DC4 coMusicPlayer_playMusic(COMUSIC_3A_FP_BOGGY_RACE, 25000); func_8025A58C(0, 4000); core1_ce60_incOrDecCounter(false); @@ -392,7 +392,7 @@ void func_803895E0(void){ : cubeList_findNodePropByActorIdAndPosition_s32(D_80391DB8[i].unk0, D_80391DAC); nodeprop_getPosition(s0, sp64); - f20 = (f32)nodeProp_getYaw(s0); + f20 = (f32)nodeprop_getYaw(s0); f8 = (f32)nodeprop_getScale(s0); f22 = f8*0.01; actor = actor_spawnWithYaw_f32(D_80391DB8[i].actor_id, sp64, (s32)f20); @@ -474,7 +474,7 @@ void func_803896FC(Actor *this){ } else if( subaddie_playerIsWithinSphereAndActive(this, 0x1C2) && player_movementGroup() == BSGROUP_0_NONE - && player_isStableWithExtraSteps() + && func_8028F20C() && func_8028EFC8() && sp3C[FACE_BUTTON(BUTTON_B)] == 1 && !gcdialog_hasCurrentTextId() @@ -483,13 +483,13 @@ void func_803896FC(Actor *this){ && player_getTransformation() != TRANSFORM_4_WALRUS && volatileFlag_get(VOLATILE_FLAG_B3) ){ - gcdialog_showDialog(VER_SELECT(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0x97B, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(ASSET_C01_DIALOG_BOGGY_SLED_BEAR_DENY, 0xf, this->position, this->marker, func_80388D70, NULL); } else if( local->unk19 == 2){ if( player_getTransformation() == TRANSFORM_4_WALRUS && volatileFlag_get(VOLATILE_FLAG_B4) ){ - gcdialog_showDialog(VER_SELECT(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0x982, 0, 0), 0xf, this->position, this->marker, func_80388D70, NULL); + gcdialog_showDialog(ASSET_C08_DIALOG_BOGGY_SLED_WALRUS_COMPLETE_RETRY, 0xf, this->position, this->marker, func_80388D70, NULL); } else if( player_getTransformation() != TRANSFORM_4_WALRUS){ func_80388A94(this); diff --git a/src/FP/ch/boggy3.c b/src/FP/ch/boggy3.c index 6e0e66200..a1e42df6a 100644 --- a/src/FP/ch/boggy3.c +++ b/src/FP/ch/boggy3.c @@ -27,11 +27,11 @@ Actor *func_80390290(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(this->unk38_31) return this; - if(gcdialog_getCurrentTextId() == VER_SELECT(ASSET_C1F_DIALOG_BOGGY_IGLOO_2, 0x999, 0, 0) || gcdialog_getCurrentTextId() == VER_SELECT(ASSET_C1E_DIALOG_BOGGY_IGLOO_1, 0x998, 0, 0)){ + if(gcdialog_getCurrentTextId() == 0xC1F || gcdialog_getCurrentTextId() == 0xC1E){ sp18 = 1; } - modelRender_setAppendageVisibility(1, 0); - modelRender_setAppendageVisibility(3, sp18); + func_8033A45C(1, 0); + func_8033A45C(3, sp18); return actor_draw(marker, gfx, mtx, vtx); } @@ -53,9 +53,7 @@ void func_80390388(Actor *this){ levelSpecificFlags_set(LEVEL_FLAG_12_FP_UNKNOWN, true); levelSpecificFlags_set(LEVEL_FLAG_13_FP_UNKNOWN, true); } - if(EventSystem_Should(VB_BOGGY_HOME_VISIBLE, - jiggyscore_isCollected(JIGGY_2C_FP_BOGGY_3) || jiggyscore_isSpawned(JIGGY_2C_FP_BOGGY_3), - this)){ + if(jiggyscore_isCollected(JIGGY_2C_FP_BOGGY_3) || jiggyscore_isSpawned(JIGGY_2C_FP_BOGGY_3)){ this->unk38_31 = false; this->marker->propPtr->unk8_3 = true; } @@ -80,15 +78,15 @@ void func_80390388(Actor *this){ && (player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT) ){ if(0.0f == this->unk1C[0] && func_80390334()){ - if(gcdialog_showDialog(VER_SELECT(ASSET_C1F_DIALOG_BOGGY_IGLOO_2, 0x999, 0, 0), 0xb, this->position, NULL, NULL, NULL)){ - this->has_met_before = TRUE; + if(gcdialog_showDialog(ASSET_C1F_DIALOG_BOGGY_IGLOO_2, 0xb, this->position, NULL, NULL, NULL)){ + this->has_met_before = true; this->unk1C[0] = 1.0f; } } else{ if( !this->has_met_before ){ - if(gcdialog_showDialog(VER_SELECT(ASSET_C1E_DIALOG_BOGGY_IGLOO_1, 0x998, 0, 0), 0x2b, this->position, NULL, NULL, NULL)){ - this->has_met_before = TRUE; + if(gcdialog_showDialog(ASSET_C1E_DIALOG_BOGGY_IGLOO_1, 0x2b, this->position, NULL, NULL, NULL)){ + this->has_met_before = true; } } } diff --git a/src/FP/ch/cavewozza.c b/src/FP/ch/cavewozza.c index d61c7dfe6..b41f13246 100644 --- a/src/FP/ch/cavewozza.c +++ b/src/FP/ch/cavewozza.c @@ -70,15 +70,15 @@ void chCaveWozza_update(Actor *this){ if (subaddie_playerIsWithinSphereAndActive(this, 350)) { if (player_getTransformation() == TRANSFORM_4_WALRUS) { if (!levelSpecificFlags_get(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED)) { - if (gcdialog_showDialog(VER_SELECT(ASSET_C27_DIALOG_WOZZA_CAVE_MEET_AS_WALRUS, 0x9A1, 0, 0), 0x23, NULL, NULL, NULL, NULL)) { - levelSpecificFlags_set(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED, TRUE); + if (gcdialog_showDialog(ASSET_C27_DIALOG_WOZZA_CAVE_MEET_AS_WALRUS, 0x23, NULL, NULL, NULL, NULL)) { + levelSpecificFlags_set(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED, true); } } } else { - if (!levelSpecificFlags_get(LEVEL_FLAG_32_FP_WOZZA_BEAR_TALKED)) { - if (gcdialog_showDialog(VER_SELECT(ASSET_C26_DIALOG_WOZZA_CAVE_MEET_AS_BEAR, 0x9A0, 0, 0), 0x23, NULL, NULL, NULL, NULL)) { - levelSpecificFlags_set(LEVEL_FLAG_32_FP_WOZZA_BEAR_TALKED, TRUE); + if (!levelSpecificFlags_get(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED)) { + if (gcdialog_showDialog(ASSET_C26_DIALOG_WOZZA_CAVE_MEET_AS_BEAR, 0x23, NULL, NULL, NULL, NULL)) { + levelSpecificFlags_set(LEVEL_FLAG_31_FP_WOZZA_WALRUS_TALKED, true); } } } diff --git a/src/FP/ch/racesled.c b/src/FP/ch/racesled.c index 7bff52d2f..083626892 100644 --- a/src/FP/ch/racesled.c +++ b/src/FP/ch/racesled.c @@ -56,7 +56,7 @@ void __chRaceSled_touch(ActorMarker *this_marker, ActorMarker *other_marker){ if(this->state == 2){ player_getPosition(plyr_pos); if( this->position_y + 20.0f < plyr_pos[1] - && player_isStableWithExtraSteps() + && func_8028F20C() && player_getTransformation() == TRANSFORM_4_WALRUS && func_8028F68C(BS_INTR_27_WALRUS_SLED, this->marker) ){ diff --git a/src/FP/ch/snowmanbutton.c b/src/FP/ch/snowmanbutton.c index 2f536cf12..08e55fab0 100644 --- a/src/FP/ch/snowmanbutton.c +++ b/src/FP/ch/snowmanbutton.c @@ -3,8 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - Actor *func_80386B80(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void FP_func_80386CF8(Actor *this); @@ -42,8 +40,8 @@ s32 D_80391B44[3] = {225, 225, 245}; /* .code */ Actor *func_80386B80(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - modelRender_setAppendageVisibility(1, this->state == 3); - modelRender_setAppendageVisibility(2, modelRender_func_8033A0F0(1) ^ 1); + func_8033A45C(1, this->state == 3); + func_8033A45C(2, modelRender_func_8033A0F0(1) ^ 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -91,18 +89,6 @@ void FP_func_80386CF8(Actor *this){ } } - { - s32 bit = 1 << (this->actorTypeSpecificField - 1); - if(this->state == 1 && (port_puzzleStep_get(ANCHOR_PUZZLE_FP_SNOWBUTTONS) & bit)){ - subaddie_set_state_with_direction(this, 2, 0.01f, 1); - actor_collisionOff(this); - maSnowButton_decRemaining(); - } - if(this->state != 1){ - port_puzzleStep_orBits(ANCHOR_PUZZLE_FP_SNOWBUTTONS, bit); - } - } - switch(this->state){ case 1: break; diff --git a/src/FP/ch/twinkly.c b/src/FP/ch/twinkly.c index ebdb1e130..d5fbd1238 100644 --- a/src/FP/ch/twinkly.c +++ b/src/FP/ch/twinkly.c @@ -85,8 +85,8 @@ Actor *func_8038C0B0(ActorMarker *marker, f32 arg1[3], f32 arg2, f32 arg3[3], s3 Actor *chTwinkly_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - modelRender_setAppendageVisibility(2, this->unk38_31); - modelRender_setAppendageVisibility(1, modelRender_func_8033A0F0(2) ^ 1); + func_8033A45C(2, this->unk38_31); + func_8033A45C(1, modelRender_func_8033A0F0(2) ^ 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -337,11 +337,11 @@ void chTwinkly_update(Actor *this){ if(this->unk1C[1] <= this->position_y){ this->position_y = this->unk1C[1]; if(!fileProgressFlag_get(FILEPROG_82_MET_TWINKLIES)){ - gcdialog_showDialog(VER_SELECT(ASSET_C12_DIALOG_TWINKLIE_MINIGAME_START, 0x98C, 0, 0), 0x2a, this->position, this->marker, chTwinkly_setUpMinigame, NULL); - fileProgressFlag_set(FILEPROG_82_MET_TWINKLIES, TRUE); + gcdialog_showDialog(0xc12, 0x2a, this->position, this->marker, chTwinkly_setUpMinigame, NULL); + fileProgressFlag_set(FILEPROG_82_MET_TWINKLIES, true); } else{ - gcdialog_showDialog(VER_SELECT(ASSET_C25_DIALOG_TWINKLIE_MINIGAME_RETRY, 0x99F, 0, 0), 0x2b, this->position, this->marker, chTwinkly_setUpMinigame, NULL); + gcdialog_showDialog(0xc25, 0x2b, this->position, this->marker, chTwinkly_setUpMinigame, NULL); } subaddie_set_state(this, 5); this->pitch -= 3.0f; diff --git a/src/FP/ch/twinklybox.c b/src/FP/ch/twinklybox.c index dc801194c..875777158 100644 --- a/src/FP/ch/twinklybox.c +++ b/src/FP/ch/twinklybox.c @@ -3,8 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - extern void func_80324CD8(f32); extern Actor *actor_spawnWithYaw_f32(enum actor_e, f32[3], s32); @@ -180,7 +178,7 @@ void chTwinklyBox_destroyBox(ActorMarker *marker){ chTwinklyBox_destroyBoxDust(this->position, 12, ASSET_700_SPRITE_DUST); this->velocity[1] = 0.0f; sfx_playFadeShorthandDefault(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, 1000, 3500); - gcdialog_showDialog(VER_SELECT(ASSET_C13_DIALOG_TWINKLIE_MINIGAME_COMPLETE, 0x98D, 0, 0), 0, NULL, NULL, NULL, NULL); + gcdialog_showDialog(0xc13, 0, NULL, NULL, NULL, NULL); } void chTwinklyBox_openBox(Actor *this){ @@ -241,8 +239,7 @@ void chTwinklyBox_spawnTwinkly(ActorMarker *marker){ void chTwinklyBox_completeMinigame(ActorMarker *marker){ Actor *this = marker_getActor(marker); - - port_fpTwinkly_release(); + item_set(ITEM_6_HOURGLASS, false); fileProgressFlag_set(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME, true); FUNC_8030E624(SFX_416_ELECTRIC_ZAP, 0.8f, 32000); @@ -260,10 +257,6 @@ void chTwinklyBox_activateBox(ActorMarker *this_marker, ActorMarker *other_marke Actor *this = marker_getActor(this_marker); if(this->state == 1 || this->state == 2){ - // Anchor: only one client may run this minigame at a time — claim it or block if already held. - if(!EventSystem_Should(VB_FP_TWINKLY_START, true)){ - return; - } actor_collisionOff(this); timed_setStaticCameraToNode(0.0f, 0xa); func_80324CD8(0.1f); @@ -372,8 +365,8 @@ void chTwinklyBox_update(Actor *this){ func_8028F784(0); subaddie_set_state_with_direction(this, 4, 0.999f, 1); actor_playAnimationOnce(this); - item_set(ITEM_0_HOURGLASS_TIMER, 80*FRAMERATE - 1); - item_set(ITEM_6_HOURGLASS, TRUE); + item_set(ITEM_0_HOURGLASS_TIMER, 80*60 - 1); + item_set(ITEM_6_HOURGLASS, true); this->unk38_31 = 0xA; item_set(ITEM_24_TWINKLY_SCORE, this->unk38_31); __spawnQueue_add_1((GenFunction_1)chTwinklyBox_spawnSecondAndThirdMuncher, (uintptr_t)this->marker); @@ -401,7 +394,6 @@ void chTwinklyBox_update(Actor *this){ } if(item_empty(ITEM_6_HOURGLASS)){ - port_fpTwinkly_release(); subaddie_set_state_with_direction(this, 1, 0.001f, 0); actor_playAnimationOnce(this); this->unk38_31 = 0; diff --git a/src/FP/ch/twinklymuncher.c b/src/FP/ch/twinklymuncher.c index 1f80cfac3..e35bf10db 100644 --- a/src/FP/ch/twinklymuncher.c +++ b/src/FP/ch/twinklymuncher.c @@ -128,7 +128,7 @@ void chTwinklyMuncher_update(Actor *this){ if(this->actorTypeSpecificField == 1 && !fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)){ if(this->state != 6 && this->state != 7 && 0.0f == this->velocity[0]){ timed_setStaticCameraToNode(0.5f, 0xd); - gcdialog_showDialog(VER_SELECT(ASSET_C15_DIALOG_TWINKLIE_MINIGAME_MISS, 0x98F, 0, 0), 0x2b, this->position, this->marker, chTwinklyMuncher_failMinigameExit, NULL); + gcdialog_showDialog(ASSET_C15_DIALOG_TWINKLIE_MINIGAME_MISS, 0x2b, this->position, this->marker, chTwinklyMuncher_failMinigameExit, NULL); this->velocity[0] = 1.0f; subaddie_set_state_with_direction(this, 6, 0.03f, 1); actor_loopAnimation(this); @@ -202,8 +202,8 @@ void chTwinklyMuncher_update(Actor *this){ sfx_playFadeShorthandDefault(SFX_27_JINJO_HI, 1.6f, 32000, this->position, 1250, 2500); func_80324D54(0.35f, SFX_110_TWINKLY_DEATH, 1.0f, 32000, this->position, 1250.0f, 2500.0f); marker_despawn(sp38->marker); - if( !mapSpecificFlags_get(FP_SPECIFIC_FLAG_A_FIRST_TWINKLY_EATEN) && gcdialog_showDialog(VER_SELECT(ASSET_C16_DIALOG_TWINKLIE_MINIGAME_EATEN, 0x990, 0, 0), 0, NULL, NULL, NULL, NULL)){ - mapSpecificFlags_set(FP_SPECIFIC_FLAG_A_FIRST_TWINKLY_EATEN, TRUE); + if( !mapSpecificFlags_get(0xa) && gcdialog_showDialog(0xc16, 0, NULL, NULL, NULL, NULL)){ + mapSpecificFlags_set(0xa, true); } } }//L8038E620 diff --git a/src/FP/ch/wozza.c b/src/FP/ch/wozza.c index 69dc4fb98..fefe57902 100644 --- a/src/FP/ch/wozza.c +++ b/src/FP/ch/wozza.c @@ -70,11 +70,11 @@ void chWozza_enterCaveFinal(Actor *this){ void chWozza_textCallback(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this = marker_getActor(caller); switch(text_id){ - case VER_SELECT(ASSET_C1B_DIALOG_WOZZA_MEET_AS_BEAR, 0x995, 0, 0): + case 0xC1B: timed_exitStaticCamera(0.0f); break; - case VER_SELECT(ASSET_C1C_DIALOG_WOZZA_MEET_AS_WALRUS, 0x996, 0, 0): + case 0xC1C: timed_exitStaticCamera(0.0f); chWozza_enterCaveFinal(this); break; @@ -107,8 +107,8 @@ void chWozza_firstContact(Actor *this){ subaddie_set_state(this, 2); actor_loopAnimation(this); timed_setStaticCameraToNode(0.0f, 0x2e); - func_80324DBC(0.0f, VER_SELECT(ASSET_C1B_DIALOG_WOZZA_MEET_AS_BEAR, 0x995, 0, 0), 0x2a, this->position, this->marker, chWozza_textCallback, NULL); - timedFunc_set_1(2.5f, (GenFunction_1)chWozza_delayedRetreatToCave, reinterpret_cast(uintptr_t, this->marker)); + func_80324DBC(0.0f, 0xc1b, 0x2a, this->position, this->marker, chWozza_textCallback, NULL); + timedFunc_set_1(2.5f, (GenFunction_1)chWozza_delayedRetreatToCave, (uintptr_t)this->marker); } else{ chWozza_retreatToCave(this); @@ -274,8 +274,8 @@ void chWozza_update(Actor *this){ chWozza_checkForPlayer(this); if(!local->unk30){ - if(gcdialog_showDialog(VER_SELECT(ASSET_C1D_DIALOG_WOZZA_RETURN, 0x997, 0, 0), 0x20, NULL, NULL, NULL, NULL)){ - local->unk30 = TRUE; + if(gcdialog_showDialog(0xc1d, 0x20, NULL, NULL, NULL, NULL)){ + local->unk30 = true; } } break; @@ -301,7 +301,7 @@ void chWozza_update(Actor *this){ } if(subaddie_playerIsWithinSphereAndActive(this, 500) && !this->has_met_before){ - if(gcdialog_showDialog(VER_SELECT(ASSET_C1C_DIALOG_WOZZA_MEET_AS_WALRUS, 0x996, 0, 0), 0xAA, this->position, this->marker, chWozza_textCallback, chWozza_checkCompletion)){ + if(gcdialog_showDialog(0xc1c, 0xAA, this->position, this->marker, chWozza_textCallback, chWozza_checkCompletion)){ timed_setStaticCameraToNode(0.0f, 0x2E); this->has_met_before = true; } diff --git a/src/FP/wozza_fire.c b/src/FP/ch/wozza_fire.c similarity index 100% rename from src/FP/wozza_fire.c rename to src/FP/ch/wozza_fire.c diff --git a/src/FP/ch/xmastree.c b/src/FP/ch/xmastree.c index f753e3c73..ea658f78c 100644 --- a/src/FP/ch/xmastree.c +++ b/src/FP/ch/xmastree.c @@ -3,8 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - Actor *chXmasTree_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chXmasTree_update(Actor *this); @@ -20,12 +18,12 @@ ActorInfo chXmasTree = { /* .code */ Actor *chXmasTree_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - modelRender_setAppendageVisibility(5, this->unk38_31); - modelRender_setAppendageVisibility(6, fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME) && !modelRender_func_8033A0F0(5)); + func_8033A45C(5, this->unk38_31); + func_8033A45C(6, fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME) && !modelRender_func_8033A0F0(5)); return actor_draw(marker, gfx, mtx, vtx); } -void chXmasTree_free(Actor *this){ +void __chXmasTree_free(Actor *this){ u8 tmp_a0; item_set(ITEM_6_HOURGLASS, false); @@ -36,30 +34,30 @@ void chXmasTree_free(Actor *this){ } } -void chXmasTree_setState(Actor *this, int arg1){ +void __chXmasTree_80386EF4(Actor *this, int arg1){ this->unk38_31 = arg1; mapSpecificFlags_set(0, this->unk38_31); } -void chXmasTree_swapCameraToIce(void){ +void __chXmasTree_80386F3C(void){ levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); musicKeepsPlaying(); volatileFlag_set(VOLATILE_FLAG_E, 1); transitionToMap(MAP_53_FP_CHRISTMAS_TREE, WARP_FP_CHRISTMAS_TREE_1_ENTRANCE, 0); } -void chXmasTree_setLightsOn(Actor * this){ +void __chXmasTree_80386F84(Actor * this){ subaddie_set_state(this, 2); - chXmasTree_setState(this, 0); + __chXmasTree_80386EF4(this, 0); } -void chXmasTree_spawnSwitch(void){ +void __chXmasTree_spawnSwitch(void){ static s32 chXmasTree_switch_spawn_position[3] = {-0x1220, 0x6A, 0x1945}; actor_spawnWithYaw_s32(ACTOR_338_XMAS_TREE_SWITCH, &chXmasTree_switch_spawn_position, 350); } -void chXmasTree_spawnStar(void *marker){ +void __chXmasTree_spawnStar(void *marker){ Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, marker)); Actor *child = spawn_child_actor(0x339, &this); s32 pad; @@ -68,22 +66,22 @@ void chXmasTree_spawnStar(void *marker){ child->position_z += 25.0f; } -void chXmasTree_lightsDeactivatedSounds(Actor *this){ +void __chXmasTree_80387038(Actor *this){ if(func_8030E3FC(this->unk44_31)) sfxSource_triggerCallbackByIndex(this->unk44_31); sfxsource_playSfxAtVolume(this->unk44_31, randf2(0.9f, 1.1f)); sfxSource_func_8030E2C4(this->unk44_31); } -void chXmasTree_setLightsOff(Actor *this){ +void __chXmasTree_8038709C(Actor *this){ if(this->state == 5){ if(!mapSpecificFlags_get(0)) - chXmasTree_lightsDeactivatedSounds(this); + __chXmasTree_80387038(this); return; } if(mapSpecificFlags_get(0) && !func_8030E3FC(this->unk44_31)) - chXmasTree_lightsDeactivatedSounds(this); + __chXmasTree_80387038(this); } void chXmasTree_update(Actor *this){ @@ -94,43 +92,33 @@ void chXmasTree_update(Actor *this){ this->volatile_initialized = true; this->marker->propPtr->unk8_3 = true; this->marker->collidable = false; - marker_setFreeMethod(this->marker, chXmasTree_free); + marker_setFreeMethod(this->marker, __chXmasTree_free); if(this->unk44_31 == 0){ this->unk44_31 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(this->unk44_31, SFX_415_XMAS_LIGHTS_FLICKERING); sfxSource_setunk43_7ByIndex(this->unk44_31, 3); sfxsource_setSampleRate(this->unk44_31, 28000); } - __spawnQueue_add_0(chXmasTree_spawnSwitch); - __spawnQueue_add_1((GenFunction_1)chXmasTree_spawnStar, (uintptr_t)this->marker); + __spawnQueue_add_0(__chXmasTree_spawnSwitch); + __spawnQueue_add_1((GenFunction_1)__chXmasTree_spawnStar, (uintptr_t)this->marker); if(fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)){ - chXmasTree_setLightsOn(this); + __chXmasTree_80386F84(this); mapSpecificFlags_set(2, false); } } this->depth_mode = 1; - // Anchor: teammate finished the star minigame — light the tree locally and stop our countdown if running. - if (!levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE) - && (port_puzzleStep_getForMap(MAP_53_FP_CHRISTMAS_TREE, ANCHOR_PUZZLE_FP_TREE_ICE) & 0x1)) { - levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); - if (this->state == 4) { - item_set(ITEM_6_HOURGLASS, false); - mapSpecificFlags_set(2, false); - } - } - if (jiggyscore_isCollected(JIGGY_2F_FP_XMAS_TREE) || levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { - chXmasTree_setState(this, 1); + __chXmasTree_80386EF4(this, 1); return; } switch(this->state){ case 1: // L80387268 - chXmasTree_setState(this, 0); + __chXmasTree_80386EF4(this, 0); if(fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)){ - chXmasTree_setLightsOn(this); + __chXmasTree_80386F84(this); } break; @@ -141,21 +129,21 @@ void chXmasTree_update(Actor *this){ this->lifetime_value = 2.0f; coMusicPlayer_playMusic(COMUSIC_61_XMAS_TREE_LIGHTS_UP, 28000); gcStaticCamera_activate(0x1A); - gcdialog_showDialog(VER_SELECT(ASSET_C14_DIALOG_TWINKLIE_MINIGAME_LIGHT_TREE, 0x98E, 0, 0), 0, NULL, NULL, NULL, NULL); + gcdialog_showDialog(0xC14, 0, NULL, NULL, NULL, NULL); break; case 3: // L803872F0 if(0.0 <= this->lifetime_value){ if( 1.8 < this->lifetime_value){ - chXmasTree_setState(this, 0); + __chXmasTree_80386EF4(this, 0); } else if(this->lifetime_value < 0.2){//L80387340 - chXmasTree_setState(this, 1); + __chXmasTree_80386EF4(this, 1); } else{ if(randf() < 0.2){ - chXmasTree_setState(this, this->unk38_31 ^ 1); - chXmasTree_setLightsOff(this); + __chXmasTree_80386EF4(this, this->unk38_31 ^ 1); + __chXmasTree_8038709C(this); } }//L803873AC this->lifetime_value -= sp2C; @@ -163,9 +151,9 @@ void chXmasTree_update(Actor *this){ else{//L803873BC if(func_802BB270()){ subaddie_set_state(this, 4); - chXmasTree_setState(this, 1); - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(3600, 3000, 0, 0) - 1); - item_set(ITEM_6_HOURGLASS, TRUE); + __chXmasTree_80386EF4(this, 1); + item_set(ITEM_0_HOURGLASS_TIMER, 3600 - 1); + item_set(ITEM_6_HOURGLASS, true); } } @@ -174,7 +162,7 @@ void chXmasTree_update(Actor *this){ case 4: // L80387400 if(mapSpecificFlags_get(3)){ subaddie_set_state(this, 6); - chXmasTree_setState(this, 1); + __chXmasTree_80386EF4(this, 1); item_set(ITEM_6_HOURGLASS, false); tmp_a0 = this->unk44_31; if(tmp_a0){ @@ -182,7 +170,7 @@ void chXmasTree_update(Actor *this){ this->unk44_31 = 0; } func_80324E38(0.0f, 3); - timedFunc_set_0(0.5f, chXmasTree_swapCameraToIce); + timedFunc_set_0(0.5f, __chXmasTree_80386F3C); } else{//L80387470 if(item_empty(ITEM_6_HOURGLASS)){ @@ -203,21 +191,21 @@ void chXmasTree_update(Actor *this){ case 5: // L803874EC if(0.0 <= this->lifetime_value){ if( 1.8 < this->lifetime_value){ - chXmasTree_setState(this, 1); + __chXmasTree_80386EF4(this, 1); } else if(this->lifetime_value < 0.2){ - chXmasTree_setState(this, 0); + __chXmasTree_80386EF4(this, 0); } else{ if(randf() < 0.2){ - chXmasTree_setState(this, this->unk38_31 ^ 1); - chXmasTree_setLightsOff(this); + __chXmasTree_80386EF4(this, this->unk38_31 ^ 1); + __chXmasTree_8038709C(this); } } this->lifetime_value -= sp2C; } else{ - chXmasTree_setLightsOn(this); + __chXmasTree_80386F84(this); } break; } diff --git a/src/FP/ch/xmastreeice.c b/src/FP/ch/xmastreeice.c index aa3cc1e63..beaaae180 100644 --- a/src/FP/ch/xmastreeice.c +++ b/src/FP/ch/xmastreeice.c @@ -3,12 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - -typedef struct { - u8 initShatter; // took the warped-in cutscene path at init; suppresses the live shatter -} ActorLocal_XmasTreeIce; - Actor *chXmasTreeIce_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chXmasTreeIce_update(Actor *this); @@ -74,8 +68,6 @@ void chXmasTreeIce_shatterIce(ActorMarker *marker){ func_8030E6D4(SFX_B6_GLASS_BREAKING_1); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); this->unk38_31 = 1; - // Anchor: broadcast the shatter; LEVEL_FLAG_29 stays local. - port_puzzleStep_orBits(ANCHOR_PUZZLE_FP_TREE_ICE, 0x1); } void chXmasTreeIce_returnCameraToBanjo(ActorMarker *marker){ @@ -93,12 +85,6 @@ void chXmasTreeIce_initiateShatter(Actor *this){ } void chXmasTreeIce_update(Actor *this) { - ActorLocal_XmasTreeIce *local = (ActorLocal_XmasTreeIce *)&this->local; - - if (!EventSystem_Should(VB_XMAS_TREE_ICE_UPDATE, true, this)) { - return; - } - this->marker->propPtr->unk8_3 = true; actor_collisionOff(this); @@ -108,22 +94,8 @@ void chXmasTreeIce_update(Actor *this) { if (jiggyscore_isCollected(JIGGY_2F_FP_XMAS_TREE)) { marker_despawn(this->marker); } - else if (port_puzzleStep_get(ANCHOR_PUZZLE_FP_TREE_ICE) & 0x1) { - if (!levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { - levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); - } - marker_despawn(this->marker); - } else if (levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { - local->initShatter = 1; chXmasTreeIce_initiateShatter(this); } } - else if (!local->initShatter && this->unk38_31 == 0 - && (port_puzzleStep_get(ANCHOR_PUZZLE_FP_TREE_ICE) & 0x1)) { - if (!levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { - levelSpecificFlags_set(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, true); - } - chXmasTreeIce_shatterIce(this->marker); - } } diff --git a/src/FP/ch/xmastreestar.c b/src/FP/ch/xmastreestar.c index a9b001885..a9cc9cddf 100644 --- a/src/FP/ch/xmastreestar.c +++ b/src/FP/ch/xmastreestar.c @@ -27,8 +27,8 @@ f32 D_803935D0[3]; /* .code */ Actor *chXmasTreeStar_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility( 2, mapSpecificFlags_get(0)); - modelRender_setAppendageVisibility( 1, mapSpecificFlags_get(0) ^ 1); + func_8033A45C( 2, mapSpecificFlags_get(0)); + func_8033A45C( 1, mapSpecificFlags_get(0) ^ 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/ch/xmastreeswitch.c b/src/FP/ch/xmastreeswitch.c index 1bb552b91..066f0a56e 100644 --- a/src/FP/ch/xmastreeswitch.c +++ b/src/FP/ch/xmastreeswitch.c @@ -22,8 +22,8 @@ ActorInfo D_80392420 = { 0x206, 0x338, 0x486, /* .code */ Actor *chXmasTreeSwitch_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility(1, 0); - modelRender_setAppendageVisibility(2, 1); + func_8033A45C(1, 0); + func_8033A45C(2, 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/checksums.c b/src/FP/checksums.c deleted file mode 100644 index b56783710..000000000 --- a/src/FP/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: FP/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsFP; diff --git a/src/FP/ma/slalom.c b/src/FP/mapstate/slalom.c similarity index 91% rename from src/FP/ma/slalom.c rename to src/FP/mapstate/slalom.c index 293d651c7..4f82d9f85 100644 --- a/src/FP/ma/slalom.c +++ b/src/FP/mapstate/slalom.c @@ -127,7 +127,7 @@ void __maSlalom_spawnGate(s32 indx, s32 arg1){ } void maSlalom_spawnGate(s32 indx, s32 arg1){ - __spawnQueue_add_2((GenFunction_2)__maSlalom_spawnGate, indx, arg1); + __spawnQueue_add_2((void (*)(void))__maSlalom_spawnGate, indx, arg1); } void __maSlalom_despawnGate(s32 indx){ @@ -250,23 +250,23 @@ void maSlalom_dialogCallback(ActorMarker *caller, enum asset_e text_id, s32 arg2 } switch(text_id){ - case VER_SELECT(ASSET_C04_DIALOG_BOGGY_SLED_WALRUS_MISS, 0x97E, 0, 0): //8038B318 + case 0xc04: //8038B318 __maSlalom_loseDialogCallback(); break; - case VER_SELECT(ASSET_C07_DIALOG_BOGGY_SLED_WALRUS_COMPLETE, 0x981, 0, 0): //8038B328 + case 0xc07: //8038B328 __maSlalom_winDialogCallback(JIGGY_30_FP_BOGGY_2); break; - case VER_SELECT(ASSET_C0B_DIALOG_BOGGY_SLED_BEAR_MISS, 0x985, 0, 0): //8038B338 + case 0xc0b: //8038B338 __maSlalom_loseDialogCallback(); break; - case VER_SELECT(ASSET_C0D_DIALOG_BOGGY_SLED_BEAR_COMPLETE, 0x987, 0, 0): //8038B348 + case 0xc0d: //8038B348 __maSlalom_winDialogCallback(JIGGY_2C_FP_BOGGY_3); break; - case VER_SELECT(ASSET_C10_DIALOG_BOGGY_SLED_EITHER_GIVE_UP, 0x98A, 0, 0): //8038B358 + case 0xc10: //8038B358 func_8038ABDC(); code_7060_setVoidOutLocation(gsworld_getMap(), 0x11); func_8028F66C(BS_INTR_2A); @@ -300,12 +300,12 @@ void maSlalom_lose(void){ if(!jiggyscore_isCollected(JIGGY_30_FP_BOGGY_2)){ timed_setStaticCameraToNode(0.0f, 1); timed_playSfx(1.0f, SFX_8C_BOGGY_WAHEY, 1.0f, 32000); - func_80324DBC(2.0f, VER_SELECT(ASSET_C04_DIALOG_BOGGY_SLED_WALRUS_MISS, 0x97E, 0, 0), 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, 0xC04, 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); }//L8038B4E0 else{ timed_setStaticCameraToNode(0.0f, 1); timed_playSfx(1.0f, SFX_8C_BOGGY_WAHEY, 1.0f, 32000); - func_80324DBC(2.0f, VER_SELECT(ASSET_C0B_DIALOG_BOGGY_SLED_BEAR_MISS, 0x985, 0, 0), 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, 0xC0b, 0x2b, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); } } @@ -359,10 +359,10 @@ void maSlalom_update(void){ pntBoggy->unk38_31 = 2; timed_playSfx(1.0f, SFX_8D_BOGGY_OHWW, 1.0f, 32000); if(jiggyscore_isCollected(JIGGY_30_FP_BOGGY_2) || jiggyscore_isSpawned(JIGGY_30_FP_BOGGY_2)){ - func_80324DBC(2.0f, VER_SELECT(ASSET_C0D_DIALOG_BOGGY_SLED_BEAR_COMPLETE, 0x987, 0, 0), 0x2a, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, 0xc0d, 0x2a, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); } else{ - func_80324DBC(2.0f, VER_SELECT(ASSET_C07_DIALOG_BOGGY_SLED_WALRUS_COMPLETE, 0x981, 0, 0), 0x22, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); + func_80324DBC(2.0f, 0xc07, 0x22, pntBoggy->position, NULL, maSlalom_dialogCallback, NULL); } Me.state = MA_SLALOM_STATE_4_LOSE; break; @@ -539,7 +539,7 @@ void maSlalom_setBoggyGate(s32 gate_num){ FP_func_8038AB60(0); if(!player_isDead()){ func_8028F918(2); - gcdialog_showDialog(VER_SELECT(ASSET_C10_DIALOG_BOGGY_SLED_EITHER_GIVE_UP, 0x98A, 0, 0), 0x20, NULL, NULL, maSlalom_dialogCallback, NULL); + gcdialog_showDialog(0xc10, 0x20, NULL, NULL, maSlalom_dialogCallback, NULL); }//L8038BD40 Me.state = MA_SLALOM_STATE_4_LOSE; break; @@ -547,7 +547,7 @@ void maSlalom_setBoggyGate(s32 gate_num){ case 3: if(!Me.hasBeenThreeBehind && !player_isDead()){ Me.hasBeenThreeBehind = 1; - gcdialog_showDialog(VER_SELECT(ASSET_C0F_DIALOG_BOGGY_SLED_EITHER_TAUNT_2, 0x989, 0, 0), 0x20, NULL, NULL, NULL, NULL); + gcdialog_showDialog(0xc0f, 0x20, NULL, NULL, NULL, NULL); }//L8038BD94 func_8025AEA0(0x3a, 0x411aa); break; @@ -555,7 +555,7 @@ void maSlalom_setBoggyGate(s32 gate_num){ case 2: if(!Me.hasBeenTwoBehind && !player_isDead()){ Me.hasBeenTwoBehind = 1; - gcdialog_showDialog(VER_SELECT(ASSET_C0E_DIALOG_BOGGY_SLED_EITHER_TAUNT_1, 0x988, 0, 0), 0x20, NULL, NULL, NULL, NULL); + gcdialog_showDialog(0xc0e, 0x20, NULL, NULL, NULL, NULL); }//L8038BDF0 func_8025AEA0(0x3a, 0x493e0); break; diff --git a/src/FP/ch/boggyraceflag2.c b/src/FP/mapstate/slalom2ctrl.c similarity index 89% rename from src/FP/ch/boggyraceflag2.c rename to src/FP/mapstate/slalom2ctrl.c index 795d3d2ab..2c768c47d 100644 --- a/src/FP/ch/boggyraceflag2.c +++ b/src/FP/mapstate/slalom2ctrl.c @@ -1,4 +1,4 @@ -// BanjoDecomp: FP/ch/boggyraceflag2.c +// BanjoDecomp: code_1FF0.c #include #include "functions.h" #include "variables.h" @@ -29,9 +29,9 @@ Actor *func_803883E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(this->velocity[0] == 0.0f || 0.0f != this->velocity[1]) return this; - modelRender_setAppendageVisibility(2, this->velocity[0] == 1.0f ? 1 : 0); - modelRender_setAppendageVisibility(3, this->velocity[0] == 3.0f ? 1 : 0); - modelRender_setAppendageVisibility(4, this->velocity[0] == 2.0f ? 1 : 0); + func_8033A45C(2, this->velocity[0] == 1.0f ? 1 : 0); + func_8033A45C(3, this->velocity[0] == 3.0f ? 1 : 0); + func_8033A45C(4, this->velocity[0] == 2.0f ? 1 : 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/ch/boggyraceflag1.c b/src/FP/mapstate/slalomctrl.c similarity index 94% rename from src/FP/ch/boggyraceflag1.c rename to src/FP/mapstate/slalomctrl.c index 12be9720e..559186760 100644 --- a/src/FP/ch/boggyraceflag1.c +++ b/src/FP/mapstate/slalomctrl.c @@ -1,4 +1,4 @@ -// BanjoDecomp: FP/ch/boggyraceflag1.c +// BanjoDecomp: code_19E0.c #include #include "functions.h" #include "variables.h" @@ -34,9 +34,9 @@ Actor *func_80387DD0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(this->velocity[0] == 0.0f || 0.0f != this->velocity[1]) return this; - modelRender_setAppendageVisibility(2, this->velocity[0] == 1.0f ? 1 : 0); - modelRender_setAppendageVisibility(3, this->velocity[0] == 3.0f ? 1 : 0); - modelRender_setAppendageVisibility(4, this->velocity[0] == 2.0f ? 1 : 0); + func_8033A45C(2, this->velocity[0] == 1.0f ? 1 : 0); + func_8033A45C(3, this->velocity[0] == 3.0f ? 1 : 0); + func_8033A45C(4, this->velocity[0] == 2.0f ? 1 : 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/FP/ma/snowbutton.c b/src/FP/mapstate/snowbutton.c similarity index 100% rename from src/FP/ma/snowbutton.c rename to src/FP/mapstate/snowbutton.c diff --git a/src/FP/ma/snowy.c b/src/FP/mapstate/snowy.c similarity index 100% rename from src/FP/ma/snowy.c rename to src/FP/mapstate/snowy.c diff --git a/src/GV/gvspawnqueue.c b/src/GV/actor_spawninit.c similarity index 84% rename from src/GV/gvspawnqueue.c rename to src/GV/actor_spawninit.c index 0b01ec333..f96c415f9 100644 --- a/src/GV/gvspawnqueue.c +++ b/src/GV/actor_spawninit.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/gvspawnqueue.c +// BanjoDecomp: code_7FF0.c #include #include "core1/core1.h" #include "functions.h" @@ -7,10 +7,8 @@ #include -#include "port/Patches/Patches.h" - extern void core1_7090_initSfxSource(s32, s32, s32, f32); -extern void chMMMBreakableWooden_update(Actor *this); +extern void func_802D3D54(Actor *this); extern void func_802D3D74(Actor *this); extern Actor *func_80325F2C(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); extern void func_8032BC3C(Actor *, f32); @@ -24,20 +22,20 @@ extern ActorInfo chGobiRock; extern ActorInfo chGobi2; extern ActorInfo chGobi3; extern ActorInfo chTrunker; -extern ActorInfo chMagicCarpetShadow; +extern ActorInfo GV_D_80390DD0; extern ActorInfo chSarcophagus; extern ActorInfo chSNSSarcophagus; -extern ActorInfo chRubee; +extern ActorInfo D_80390ED0; extern ActorInfo D_80390F00; -extern ActorInfo chMagicCarpet2; +extern ActorInfo D_80390FD0; extern ActorInfo D_80391010; extern ActorInfo chSlappa; extern ActorInfo chGrabba; extern ActorInfo D_803911C0; -extern ActorInfo chJinxyHeadSandybutt1; -extern ActorInfo chJinxyHeadSandybutt2; -extern ActorInfo chJinxyHeadSandybutt3; -extern ActorInfo chSandybuttEggToll; +extern ActorInfo D_803911F4; +extern ActorInfo D_80391218; +extern ActorInfo D_8039123C; +extern ActorInfo D_80391260; extern ActorInfo D_80391318; extern ActorInfo D_80391358; extern ActorInfo D_803912B8; @@ -111,13 +109,13 @@ ActorInfo D_80391494 = { MARKER_23C_GV_SNS_SWITCH, ACTOR_245_GV_SNS_SWITCH, ASSE ActorInfo D_803914B8 = { MARKER_EB_GV_BANJO_DOOR, ACTOR_6D_GV_BANJO_DOOR, ASSET_3D8_MODEL_GV_BANJO_DOOR, 0x1, 0x0, - chMMMBreakableWooden_update, func_8038E460, func_80325F2C, + func_802D3D54, func_8038E460, func_80325F2C, 0, 0, 0.0f, 0 }; ActorInfo D_803914DC = { MARKER_ED_GV_SUN_DOOR, ACTOR_140_GV_SUN_DOOR, ASSET_3FF_MODEL_GV_SUN_DOOR, 0x1, 0x0, - chMMMBreakableWooden_update, func_8038E4DC, func_80325F2C, + func_802D3D54, func_8038E4DC, func_80325F2C, 0, 0, 0.0f, 0 }; @@ -177,23 +175,12 @@ void func_8038E430(Actor *this){ void func_8038E460(Actor *this){//banjo_door func_802D3D74(this); - // Anchor: flag 0x10 is transient, doesn't survive reload. - if(mapSpecificFlags_get(0x10)){ - if(!(port_puzzleStep_get(ANCHOR_PUZZLE_GV_JINXY_DOOR) & 1)){ - port_puzzleStep_orBits(ANCHOR_PUZZLE_GV_JINXY_DOOR, 1); - } - } else if(port_puzzleStep_get(ANCHOR_PUZZLE_GV_JINXY_DOOR) & 1){ - mapSpecificFlags_set(0x10, true); - mapSpecificFlags_set(2, true); - } if(mapSpecificFlags_get(0x10)){ func_8038E430(this); if(!mapSpecificFlags_get(2)){ mapSpecificFlags_set(2, true); - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_JINXY)){ - func_8028F918(0); - func_80324DBC(4.0f, VER_SELECT(ASSET_A7D_DIALOG_JINXY_HELPED, 0x939, 0, 0), 4, NULL, NULL, NULL, NULL); - } + func_8028F918(0); + func_80324DBC(4.0f, ASSET_A7D_DIALOG_JINXY_HELPED, 4, NULL, NULL, NULL, NULL); } } } @@ -231,8 +218,7 @@ void func_8038E4DC(Actor *this){ else{ if(!mapSpecificFlags_get(4)){ mapSpecificFlags_set(4, true); - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_SUN)) - gcStaticCamera_activate(1); + gcStaticCamera_activate(1); } } } @@ -245,14 +231,13 @@ void func_8038E648(Actor *this){ case 1: //L8038E690 this->pitch = 0.0f; if(mapSpecificFlags_get(5)){ - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_STAR)) - gcStaticCamera_activate(2); + gcStaticCamera_activate(2); subaddie_set_state(this, 6); core1_7090_initSfxSource(0, 0x6A, 0x7ff8, 0.3f); s32 pyramidTimer = 25; CALL_EVENT(OnWaterPyramidTimer, &pyramidTimer); // [port] may extend timer this->unk38_31 = pyramidTimer * 24; // [port] door duration derived from HUD timer (vanilla ratio 600:25) - code_4C020_setHourglassTimer(pyramidTimer); + func_802D68F0(pyramidTimer); item_set(ITEM_6_HOURGLASS, 1); } break; @@ -262,7 +247,7 @@ void func_8038E648(Actor *this){ if(90.0f <= this->pitch){ subaddie_set_state(this, 7); this->pitch = 90.0f; - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); core1_7090_freeSfxSource(0); } break; @@ -280,10 +265,10 @@ void func_8038E648(Actor *this){ if(this->pitch <= 0.0f){ subaddie_set_state(this, 1); this->pitch = 0.0f; - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); mapSpecificFlags_set(5, false); core1_7090_freeSfxSource(0); - progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED); + volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED); } break; }//L8038E904: @@ -335,7 +320,7 @@ void func_8038E97C(Actor *this){ if(this->unk38_31 == 0){ subaddie_set_state(this, 1); core1_7090_freeSfxSource(1); - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); } } @@ -348,8 +333,7 @@ void chKazooieDoor_update(Actor *this){ case 1: //L8038EB98 if(mapSpecificFlags_get(6)){ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, -1); - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_KAZOOIE)) - gcStaticCamera_activate(3); + gcStaticCamera_activate(3); subaddie_set_state(this, 6); core1_7090_initSfxSource(1, 0x6a, 0x7ff8, 0.3f); this->unk1C[1] = this->position_y + 210.0f; @@ -362,7 +346,7 @@ void chKazooieDoor_update(Actor *this){ this->position_z -= 1.3319999999999999; if(this->unk1C[1] <= this->position_y){ subaddie_set_state(this, 7); - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); core1_7090_freeSfxSource(1); this->unk38_31 = 450; } @@ -382,7 +366,7 @@ void chKazooieDoor_update(Actor *this){ if(this->position_y <= this->unk1C[0]){ this->position_y = this->unk1C[0]; subaddie_set_state(this, 1); - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); core1_7090_freeSfxSource(1); mapSpecificFlags_set(6, false); } @@ -399,7 +383,7 @@ void chSunSwitch_update(Actor *this){ && func_802BB270() ){ this->velocity_x = 1.0f; - code_4C020_setHourglassTimer(10); + func_802D68F0(10); item_set(ITEM_6_HOURGLASS, 1); }//L8038EDC8 @@ -444,7 +428,7 @@ void chKazooieTarget_update(Actor *this){ && func_802BB270() ){ this->velocity_x = 1.0f; - code_4C020_setHourglassTimer(0x15); + func_802D68F0(0x15); item_set(ITEM_6_HOURGLASS, 1); }//L8038EDC8 @@ -496,20 +480,20 @@ void GV_func_8038F154(void) spawnableActorList_add(&chGobi2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); spawnableActorList_add(&chGobi3, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); spawnableActorList_add(&chTrunker, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chMagicCarpetShadow, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&GV_D_80390DD0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_14); spawnableActorList_add(&chSarcophagus, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10); spawnableActorList_add(&chSNSSarcophagus, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6); - spawnableActorList_add(&chRubee, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); + spawnableActorList_add(&D_80390ED0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&D_80390F00, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chMagicCarpet2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_80390FD0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_14); spawnableActorList_add(&D_80391010, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_14); spawnableActorList_add(&chSlappa, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_16); spawnableActorList_add(&chGrabba, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6); spawnableActorList_add(&D_803911C0, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chJinxyHeadSandybutt1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chJinxyHeadSandybutt2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chJinxyHeadSandybutt3, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); - spawnableActorList_add(&chSandybuttEggToll, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_803911F4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_80391218, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_8039123C, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_80391260, actor_new, ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&D_80391318, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10); spawnableActorList_add(&D_80391358, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_4 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10); // Big Jinxy Head ? spawnableActorList_add(&D_803912B8, actor_new, ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_10); diff --git a/src/GV/bss_pad.c b/src/GV/bss_pad.c new file mode 100644 index 000000000..4d37dc71d --- /dev/null +++ b/src/GV/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_GV_D_80391A20[0x10]; diff --git a/src/GV/ch/ancientone.c b/src/GV/ch/ancientone.c index 61fee9176..6301e28b7 100644 --- a/src/GV/ch/ancientone.c +++ b/src/GV/ch/ancientone.c @@ -1,10 +1,9 @@ -// BanjoDecomp: GV/ch/ancientone.c +// BanjoDecomp: CH/ancientone.c #include #include "functions.h" #include "variables.h" extern void core1_7090_initSfxSource(s32, s32, s32, f32); -extern s32 port_anchor_isWorldSyncActive(void); typedef struct { f32 unk0[3]; @@ -97,7 +96,7 @@ void func_803867F4(void){ void func_80386850(ActorMarker *caller_marker, enum asset_e text_id, s32 arg2){ Actor *caller = marker_getActor(caller_marker); - if(text_id == VER_SELECT(0xA80, 0x93C, 0, 0)){ + if(text_id == 0xA80){ subaddie_set_state_with_direction(caller, 2, 0.0f, 1); actor_playAnimationOnce(caller); coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7fff); @@ -121,48 +120,20 @@ void chAncientOne_update(Actor *this){ } } if(!this->initialized){ - if(D_80390C28[this->actorTypeSpecificField - 1] == NULL){ - LOCAL_CH_ANCIENT_ONE(this)->unk1C = this->position_y; - this->position_y -= 1100.0f; - D_80390C28[this->actorTypeSpecificField - 1] = this->marker; - if(this->actorTypeSpecificField != 1){ - this->marker->propPtr->isNotFeatherEggOrNote = false; - } - this->marker->propPtr->unk8_3 = true; - actor_collisionOff(this); - func_80386620(this); + if(D_80390C28[this->actorTypeSpecificField - 1]) return; + + LOCAL_CH_ANCIENT_ONE(this)->unk1C = this->position_y; + this->position_y -= 1100.0f; + D_80390C28[this->actorTypeSpecificField - 1] = this->marker; + if(this->actorTypeSpecificField != 1){ + this->marker->propPtr->isNotFeatherEggOrNote = false; } - // Anchor only. A statue that has not been drawn yet still has to run the - // body below so it can catch up to flags another client set. - if(!port_anchor_isWorldSyncActive()){ - return; - } - { - s32 fc = 0, fi; - for(fi = 7; fi < 0xC && mapSpecificFlags_get(fi); fi++) fc++; - if(fc == 0){ - return; - } - } + this->marker->propPtr->unk8_3 = true; + actor_collisionOff(this); + func_80386620(this); } - {//L803869B4 - if(jiggyscore_isSpawned(JIGGY_46_GV_ANCIENT_ONES)){ - marker_despawn(this->marker); - return; - } - // Anchor: ring order is randomized per-client; advance by synced-flag count. - if(port_anchor_isWorldSyncActive()){ - s32 fc = 0, fi; - for(fi = 7; fi < 0xC && mapSpecificFlags_get(fi); fi++) fc++; - if(this->state == 1 && this->actorTypeSpecificField <= fc){ - subaddie_set_state_with_direction(this, 2, 0.0f, 1); - actor_playAnimationOnce(this); - if(this->actorTypeSpecificField < 5 && D_80390C28[this->actorTypeSpecificField]){ - D_80390C28[this->actorTypeSpecificField]->propPtr->isNotFeatherEggOrNote = true; - } - } - } + else{//L803869B4 switch(this->state){ case 1: //L803869E4 player_getPosition(sp44); @@ -179,16 +150,16 @@ void chAncientOne_update(Actor *this){ mapSpecificFlags_set(sp38, true); if(sp38== 0xB){ if(!jiggyscore_isCollected(JIGGY_46_GV_ANCIENT_ONES)){ - gcdialog_showDialog(VER_SELECT(ASSET_A80_DIALOG_ANCIENT_ONES_DONE, 0x93C, 0, 0), 0xE, NULL, this->marker, func_80386850, NULL); + gcdialog_showDialog(ASSET_A80_DIALOG_ANCIENT_ONES_DONE, 0xE, NULL, this->marker, func_80386850, NULL); } else{ - func_80386850(this->marker, VER_SELECT(ASSET_A80_DIALOG_ANCIENT_ONES_DONE, 0x93C, 0, 0), -1); + func_80386850(this->marker, 0xA80, -1); } }//L80386B98 else { if(sp38== 7){ if(!jiggyscore_isCollected(JIGGY_46_GV_ANCIENT_ONES)){ - gcdialog_showDialog(VER_SELECT(ASSET_A7F_DIALOG_ANCIENT_ONES_MEET, 0x93B, 0, 0), 0x4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_A7F_DIALOG_ANCIENT_ONES_MEET, 0x4, NULL, NULL, NULL, NULL); } } @@ -254,8 +225,8 @@ Actor *chAncientOne_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **v s32 tmp_v0; sp58 = (this->state == 3) ? 0 : 1; - modelRender_setAppendageVisibility(3, sp58); - modelRender_setAppendageVisibility(4, sp58); + func_8033A45C(3, sp58); + func_8033A45C(4, sp58); actor_draw(this_marker, gfx, mtx, vtx); if( !this->initialized && this_marker->unk14_21){ vec3fArray_get_vec3i(func_80329934(), 5, sp4C); diff --git a/src/GV/ch/buriedpyramid.c b/src/GV/ch/buriedpyramid.c index 0d2634c79..42f705b88 100644 --- a/src/GV/ch/buriedpyramid.c +++ b/src/GV/ch/buriedpyramid.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/buriedpyramid.c +// BanjoDecomp: CH/buriedpyramid.c #include #include "functions.h" #include "variables.h" @@ -67,13 +67,6 @@ void chBuriedPyramid_update(Actor *this){ __chBuriedPyramid_setState(this, 1); }//L8038FE48 - if(this->state == 1){ - s32 flagState = fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2); - if(flagState > local->raised_state){ - chBuriedPyramid_setRaisedAmount(this->marker, flagState); - } - } - if(this->state == 2){ local->transistion_timer += time_getDelta()/3.0f; if(1.0f < local->transistion_timer) diff --git a/src/GV/cactus.c b/src/GV/ch/cactus.c similarity index 100% rename from src/GV/cactus.c rename to src/GV/ch/cactus.c diff --git a/src/GV/carpet1.c b/src/GV/ch/carpet1.c similarity index 100% rename from src/GV/carpet1.c rename to src/GV/ch/carpet1.c diff --git a/src/GV/carpet2.c b/src/GV/ch/carpet2.c similarity index 90% rename from src/GV/carpet2.c rename to src/GV/ch/carpet2.c index 6634a0bfc..0ddd062c0 100644 --- a/src/GV/carpet2.c +++ b/src/GV/ch/carpet2.c @@ -74,7 +74,7 @@ void func_8038D47C(Actor *this){ player_getPosition(sp3C); if(player_movementGroup() == BSGROUP_0_NONE){ if( ml_vec3f_distance(sp3C, this->unk1C) < 100.0f || ml_vec3f_distance(sp3C, this->velocity) < 100.0f){ - if(gcdialog_showDialog(VER_SELECT(ASSET_A7B_DIALOG_JINXY_MEET, 0x937, 0, 0), 0, NULL, NULL, NULL, NULL)){ + if(gcdialog_showDialog(ASSET_A7B_DIALOG_JINXY_MEET, 0, NULL, NULL, NULL, NULL)){ mapSpecificFlags_set(0x14, 1); } } @@ -89,11 +89,9 @@ void func_8038D47C(Actor *this){ } else if(!mapSpecificFlags_get(0xF) && mapSpecificFlags_get(0) + mapSpecificFlags_get(1) == 2){ mapSpecificFlags_set(0xF, true); - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, GV_DOOR_CAM_JINXY)){ - func_8028F918(2); - gcStaticCamera_activate(0); - } + func_8028F918(2); subaddie_set_state_forward(this, 3); + gcStaticCamera_activate(0); } break; case 2: //L8038D78C @@ -105,8 +103,8 @@ void func_8038D47C(Actor *this){ } if( actor_animationIsAt(this, 0.99f) ){ if(--this->unk38_31 == 0){ - gcdialog_showDialog(VER_SELECT(ASSET_A7C_DIALOG_JINXY_ONE_EGG, 0x938, 0, 0), 4, NULL, NULL, NULL, NULL); - mapSpecificFlags_set(0x14, TRUE); + gcdialog_showDialog(ASSET_A7C_DIALOG_JINXY_ONE_EGG, 4, NULL, NULL, NULL, NULL); + mapSpecificFlags_set(0x14, true); subaddie_set_state_forward(this, 1); } } diff --git a/src/GV/magiccarpetshadow.c b/src/GV/ch/carpet_shadow.c similarity index 61% rename from src/GV/magiccarpetshadow.c rename to src/GV/ch/carpet_shadow.c index 68429daac..b3fc76eb2 100644 --- a/src/GV/magiccarpetshadow.c +++ b/src/GV/ch/carpet_shadow.c @@ -1,26 +1,25 @@ -// BanjoDecomp: GV/magiccarpetshadow.c +// BanjoDecomp: code_2EE0.c #include #include "functions.h" #include "variables.h" -void chMagicCarpetShadow_update(Actor *this); -Actor *chMagicCarpetShadow_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_8038938C(Actor *this); +Actor *func_803892D0(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); /* .data */ -extern ActorAnimationInfo chMagicCarpetShadowAnimations[] = { +extern ActorAnimationInfo D_80390DC0[]={ {0, 0.0f}, {ASSET_F1_ANIM_MAGIC_CARPET, 2.0f} }; -extern ActorInfo chMagicCarpetShadow = { - MARKER_AF_MAGIC_CARPET_SHADOW, ACTOR_122_MAGIC_CARPET_SHADOW, ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW, - 0x1, chMagicCarpetShadowAnimations, - chMagicCarpetShadow_update, actor_update_func_80326224, chMagicCarpetShadow_draw, +extern ActorInfo GV_D_80390DD0 = { MARKER_AF_MAGIC_CARPET_SHADOW, ACTOR_122_MAGIC_CARPET_SHADOW, ASSET_3E7_MODEL_MAGIC_CARPET_SHADOW, + 0x1, D_80390DC0, + func_8038938C, actor_update_func_80326224, func_803892D0, 2500, 0, 0.0f, 0 }; /* .code */ -Actor *chMagicCarpetShadow_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *func_803892D0(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ f32 rotation[3]; f32 position[3]; Actor *this; @@ -37,7 +36,7 @@ Actor *chMagicCarpetShadow_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, return this; } -void chMagicCarpetShadow_update(Actor *this){ +void func_8038938C(Actor *this){ if(!this->initialized){ this->initialized = true; this->unk124_11 = 3; diff --git a/src/GV/ch/eggpot.c b/src/GV/ch/egg_pot.c similarity index 95% rename from src/GV/ch/eggpot.c rename to src/GV/ch/egg_pot.c index 05cc9baea..32ff46425 100644 --- a/src/GV/ch/eggpot.c +++ b/src/GV/ch/egg_pot.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/eggpot.c +// BanjoDecomp: code_3AA0.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/gobi1.c b/src/GV/ch/gobi1.c index fdcb99009..8c8ddc4ff 100644 --- a/src/GV/ch/gobi1.c +++ b/src/GV/ch/gobi1.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/gobi1.c +// BanjoDecomp: CH/gobi1.c #include #include "functions.h" #include "variables.h" @@ -159,7 +159,7 @@ void chGobi1_update(Actor *this){ timed_playSfx(1.0f, SFX_84_GOBI_CRYING, 1.1f, 30000); timed_playSfx(2.0f, SFX_84_GOBI_CRYING, 1.3f, 30000); timed_playSfx(2.5f, SFX_74_WALKING_NOISE_5, 0.5f, 30000); - func_80324DBC(3.0f, VER_SELECT(ASSET_A74_DIALOG_GOBI_HELPED, 0x930, 0, 0), 0x2a, this->position, NULL, NULL, NULL); + func_80324DBC(3.0f, ASSET_A74_DIALOG_GOBI_HELPED, 0x2a, this->position, NULL, NULL, NULL); timed_playSfx(5.0f, SFX_2E_BIGBUTT_RUNNING, 1.0f, 20000); timed_playSfx(5.6f, SFX_2E_BIGBUTT_RUNNING, 1.0f, 20000); timed_playSfx(6.5f, SFX_2E_BIGBUTT_RUNNING, 1.0f, 20000); @@ -181,7 +181,7 @@ void chGobi1_update(Actor *this){ && subaddie_playerIsWithinSphereAndActive(this, 250) && !subaddie_playerIsWithinSphereAndActive(this, 80) && func_8028F2A0() - && gcdialog_showDialog(VER_SELECT(0xa73, 0x92F, 0, 0), 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(0xa73, 0, NULL, NULL, NULL, NULL) ){ this->has_met_before = true; } diff --git a/src/GV/ch/gobi2.c b/src/GV/ch/gobi2.c index ad0fc87a5..4f72f936c 100644 --- a/src/GV/ch/gobi2.c +++ b/src/GV/ch/gobi2.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/gobi2.c +// BanjoDecomp: CH/gobi2.c #include #include "functions.h" #include "variables.h" @@ -86,7 +86,7 @@ void chGobi2_setState(Actor *this, s32 next_state){ timed_playSfx(0.8f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(1.4f, SFX_4B_GULPING, 0.8f, 28000); timed_playSfx(2.0f, SFX_4B_GULPING, 0.8f, 28000); - func_80324DBC(3.0f, VER_SELECT(ASSET_A72_DIALOG_TRUNKER_HELPED, 0x92E, 0, 0), 0x2A, D_80390CEC, this->marker, func_80387A2C, NULL); + func_80324DBC(3.0f, ASSET_A72_DIALOG_TRUNKER_HELPED, 0x2A, D_80390CEC, this->marker, func_80387A2C, NULL); }//L80387C94 if(next_state == 4){ @@ -204,8 +204,8 @@ void chGobi2_update(Actor *this){ if(!this->has_met_before){ if(subaddie_playerIsWithinSphereAndActive(this, 0xFA) && !subaddie_playerIsWithinSphereAndActive(this, 0x50)){ if(func_8028F2A0()){ - if(gcdialog_showDialog(VER_SELECT(ASSET_A75_DIALOG_GOBI2_MEET, 0x931, 0, 0), 0, this->position, NULL, NULL, NULL)) - this->has_met_before = TRUE; + if(gcdialog_showDialog(ASSET_A75_DIALOG_GOBI2_MEET, 0, this->position, NULL, NULL, NULL)) + this->has_met_before = true; } } } diff --git a/src/GV/ch/gobi3.c b/src/GV/ch/gobi3.c index c82666e66..98ab87eda 100644 --- a/src/GV/ch/gobi3.c +++ b/src/GV/ch/gobi3.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/gobi3.c +// BanjoDecomp: CH/gobi3.c #include "functions.h" #include "variables.h" #include @@ -28,7 +28,6 @@ void __chGobi3_spawnHoneyComb(Actor *this){ bundle_setYaw(this->yaw); func_802CA1CC(HONEYCOMB_C_GV_GOBI_3); bundle_spawn_f32(BUNDLE_D__EMPTY_HONEYCOMB, sp18); - CALL_EVENT(OnHoneycombDropSpawn, HONEYCOMB_C_GV_GOBI_3, BUNDLE_D__EMPTY_HONEYCOMB, sp18[0], sp18[1], sp18[2]); } void __chGobi3_runaway(ActorMarker *caller, enum asset_e text_id, s32 arg2){ @@ -76,7 +75,7 @@ void chGobi3_setState(Actor *this, s32 next_state){ if(next_state == 5){ skeletalAnim_set(this->unk148, 0xd9, 0.5f, 4.0f); - gcdialog_showDialog(VER_SELECT(ASSET_A77_DIALOG_GOBI3_DONE, 0x933, 0, 0), 0xe, this->position, this->marker, __chGobi3_runaway, NULL); + gcdialog_showDialog(ASSET_A77_DIALOG_GOBI3_DONE, 0xe, this->position, this->marker, __chGobi3_runaway, NULL); } if(next_state == 4){ diff --git a/src/GV/ch/gobirock.c b/src/GV/ch/gobirock.c index 29caebd52..9875f57a3 100644 --- a/src/GV/ch/gobirock.c +++ b/src/GV/ch/gobirock.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/gobirock.c +// BanjoDecomp: CH/gobirock.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/gobirope.c b/src/GV/ch/gobirope.c index e934d1f1d..1c2b5cb71 100644 --- a/src/GV/ch/gobirope.c +++ b/src/GV/ch/gobirope.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/gobirope.c +// BanjoDecomp: CH/gobirope.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/grabba.c b/src/GV/ch/grabba.c index c1886224b..7f04ea682 100644 --- a/src/GV/ch/grabba.c +++ b/src/GV/ch/grabba.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/grabba.c +// BanjoDecomp: code_5570.c #include #include "functions.h" #include "variables.h" @@ -64,7 +64,7 @@ void func_8038BA08(Actor *this){ if(player_movementGroup() == BSGROUP_6_TURBO_TALON_TRAINERS) player_stateTimer_set(STATE_TIMER_3_TURBO_TALON, 0.0f); - gcdialog_showDialog(VER_SELECT(ASSET_A79_DIALOG_GRABBA_DEFEAT, 0x935, 0, 0), 0xf, this->position, this->marker, func_8038B988, NULL); + gcdialog_showDialog(ASSET_A79_DIALOG_GRABBA_DEFEAT, 0xf, this->position, this->marker, func_8038B988, NULL); comusic_8025AB44(COMUSIC_57_TURBO_TRAINERS, 7000, 700); } @@ -246,8 +246,8 @@ void chGrabba_update(Actor *this){ } else{ if(!this->has_met_before){ - if(gcdialog_showDialog(VER_SELECT(ASSET_A78_DIALOG_GRABBA_MEET, 0x934, 0, 0), 0, NULL, NULL, NULL, NULL)){ - this->has_met_before = TRUE; + if(gcdialog_showDialog(ASSET_A78_DIALOG_GRABBA_MEET, 0, NULL, NULL, NULL, NULL)){ + this->has_met_before = true; } } } @@ -277,8 +277,8 @@ void chGrabba_update(Actor *this){ } if(!this->unk138_23){ - if(gcdialog_showDialog(VER_SELECT(ASSET_A7A_DIALOG_GRABBA_TOO_FAST, 0x936, 0, 0), 0, NULL, NULL, NULL, NULL)){ - this->unk138_23 = TRUE; + if(gcdialog_showDialog(ASSET_A7A_DIALOG_GRABBA_TOO_FAST, 0, NULL, NULL, NULL, NULL)){ + this->unk138_23 = true; } } } diff --git a/src/GV/handshadow.c b/src/GV/ch/handshadow.c similarity index 100% rename from src/GV/handshadow.c rename to src/GV/ch/handshadow.c diff --git a/src/GV/ch/histup.c b/src/GV/ch/histup.c index 34e9cda79..4ca545240 100644 --- a/src/GV/ch/histup.c +++ b/src/GV/ch/histup.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/histup.c +// BanjoDecomp: CH/histup.c #include #include "functions.h" #include "variables.h" @@ -28,10 +28,10 @@ ActorInfo D_80391318 = { MARKER_AA_HISTUP, ACTOR_11C_HISTUP, ASSET_3DE_MODEL_HIS /* .bss */ extern struct { - s32 eggCount; + s32 unk0; s32 unk4; s32 unk8; -} rubeeEggPot; +}GV_D_80391AB0; /* .code */ int func_8038D920(Actor *this, f32 arg1){ @@ -76,19 +76,19 @@ void GV_func_8038DB0C(Actor *this){ } void func_8038DB4C(s32 arg0){ - rubeeEggPot.eggCount = arg0; + GV_D_80391AB0.unk0 = arg0; } void func_8038DB58(s32 arg0){ - rubeeEggPot.unk4 = arg0; + GV_D_80391AB0.unk4 = arg0; } s32 func_8038DB64(void){ - return rubeeEggPot.unk4; + return GV_D_80391AB0.unk4; } void func_8038DB70(void){ - rubeeEggPot.unk4++; + GV_D_80391AB0.unk4++; } @@ -115,7 +115,7 @@ void func_8038DBDC(Actor *this){ actor_collisionOff(this); subaddie_set_state_with_direction(this, 1, 0.99f, 0); anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); - rubeeEggPot.unk8 = 0; + GV_D_80391AB0.unk8 = 0; func_8038DB4C(0); this->unk1C[0] = 0.0f; }//L8038DC90 @@ -135,7 +135,7 @@ void func_8038DBDC(Actor *this){ case 2: //8038DD3C if(!(func_8038E178() < 5)){ func_8038DB88(this); - if(rubeeEggPot.unk8){ + if(GV_D_80391AB0.unk8){ subaddie_set_state_with_direction(this, 3, 0.99f, 0); anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); this->unk1C[0] = 0.0f; @@ -197,7 +197,7 @@ void func_8038DBDC(Actor *this){ anctrl_setDuration(this->anctrl, 1.6f); func_80386608(); func_8038DB4C(0); - rubeeEggPot.unk8 = FALSE; + GV_D_80391AB0.unk8 = false; func_8025A58C(-1, 0x190); func_8025A7DC(COMUSIC_27_GV_RUBEES_SONG); if(!this->unk44_31){ diff --git a/src/GV/ch/jinxy.c b/src/GV/ch/jinxy.c new file mode 100644 index 000000000..949f52e6a --- /dev/null +++ b/src/GV/ch/jinxy.c @@ -0,0 +1,158 @@ +// BanjoDecomp: code_3D90.c +#include +#include "functions.h" +#include "variables.h" + +extern f32 mapModel_getFloorY(f32[3]); + +void func_8038A314(Actor *this); +void func_8038A31C(Actor *this); +Actor *func_8038A180(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); + +/* .data */ +ActorAnimationInfo D_80390FA0[] = { + {0, 0.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, + {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, +}; +ActorInfo D_80390FD0 = { MARKER_B0_MAGIC_CARPET_2, ACTOR_123_MAGIC_CARPET_2, ASSET_3DC_MODEL_MAGIC_CARPET, + 0x1, D_80390FA0, + func_8038A314, func_8038A31C, func_8038A180, + 0, 0, 0.0f, 0 +}; +u8 D_80390FF4[6] = {0,0,0,1,1,1}; + +/* .code */ +Actor *func_8038A180(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + Actor * this = marker_getActor(this_marker); + + if(this->unk1C[0] != 0.0f){ + this = actor_draw(this_marker, gfx, mtx, vtx); + + if( this->unk54 == 0.0f + && this->unk48 != this->unk1C[1] + && this_marker->unk14_21 + && subaddie_playerIsWithinSphereAndActive(this, 3000) + ){ + commonParticle_add(this->marker, 6, func_80329904); + commonParticle_new(0xc, this->marker->unk14_21); + } + } + return this; +} + + +f32 func_8038A264(Actor *shadow, Actor* this){ + if(this && shadow){ + return ml_map_f(this->position_y - shadow->position_y, 0.0f, 2200.0f, 1.0f, 0.35f); + } + else{ + return 0.0; + } +} + +void func_8038A2C0(void *this_marker){ + Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, this_marker)); + Actor *shadow = spawn_child_actor(ACTOR_122_MAGIC_CARPET_SHADOW, &this); + s32 pad; + + suSetSpriteScale(shadow, this->scale); + this->partnerActor = shadow->marker; +} + +void func_8038A314(Actor *this){} + +void func_8038A31C(Actor *this){ + Actor *sp24; + if(!this->volatile_initialized){ + this->volatile_initialized = true; + actor_collisionOff(this); + __spawnQueue_add_1((GenFunction_1)func_8038A2C0, (uintptr_t)this->marker); + this->velocity[0] = 0.0f; + } + + if(this->partnerActor) + sp24 = subaddie_getLinkedActor(this); + + this->unk1C[1] = this->unk48; + ; + + switch(code7FF0_getMagicCarpetState(this, 3)) + { + case 1: //L8038A3C0 + func_80343DEC(this); + this->marker->propPtr->unk8_3 = true; + this->unk1C[0] = 1.0; + this->alpha_124_19 = 0xff; + if(this->unk54 != 0.0f){ + subaddie_set_state_with_direction(this, 2, 0.02f, 1); + anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); + } + break; + case 2: //L8038A440 + this->marker->propPtr->unk8_3 = true; + this->unk1C[0] = 1.0; + if(45.0f <= this->velocity[0]){ + subaddie_set_state_with_direction(this, 3, 0.02f, 1); + this->velocity[0] = 0.0f; + } + else{ + if(D_80390FF4[((s32)this->velocity[0])%6] == 0){ + this->alpha_124_19 -= 0x55; + } + else{ + this->alpha_124_19 += 0x55; + } + this->velocity[0] += 1.0f; + } + break; + case 3: //L8038A534 + func_80343DEC(this); + this->marker->propPtr->unk8_3 = false; + this->unk1C[0] = 0.0; + this->alpha_124_19 = 0; + if(this->unk54 == 0.0f){ + subaddie_set_state_with_direction(this, 4, 0.02f, 1); + } + break; + + case 4: //L8038A5A4 + this->marker->propPtr->unk8_3 = true; + this->unk1C[0] = 1.0; + if(45.0f <= this->velocity[0]){ + subaddie_set_state_with_direction(this, 1, 0.02f, 1); + anctrl_setPlaybackType(this->anctrl, ANIMCTRL_LOOP); + this->velocity[0] = 0.0f; + } + else{ + if(D_80390FF4[5 - ((s32)this->velocity[0])%6 ] != 0){ + this->alpha_124_19 += 0x55; + } + else{ + this->alpha_124_19 -= 0x55; + } + this->velocity[0] += 1.0f; + } + + break; + }//L8038A6A4 + this->unk124_11 = 0x3; + this->pitch = 0.0f; + if(this->partnerActor && sp24 && this->partnerActor->id == MARKER_AF_MAGIC_CARPET_SHADOW){ + sp24->position_x = this->position_x; + sp24->position_y = mapModel_getFloorY(this->position) + 60.0f; + sp24->position_z = this->position_z; + sp24->unk1C[0] = func_8038A264(sp24, this); + sp24->yaw = this->yaw; + sp24->velocity[0] = 1.0; + sp24->velocity[1] = this->alpha_124_19; + if (0.0f != this->unk1C[0]) + sp24->unk1C[2] = 1.0; + else + sp24->unk1C[2] = 0.0f; + + }//L8038A780 +} diff --git a/src/GV/jinxy_head.c b/src/GV/ch/jinxy_head.c similarity index 100% rename from src/GV/jinxy_head.c rename to src/GV/ch/jinxy_head.c diff --git a/src/GV/ch/mummum.c b/src/GV/ch/mummum.c index dbc6ad01b..53c9a69ab 100644 --- a/src/GV/ch/mummum.c +++ b/src/GV/ch/mummum.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/ch/mummum.c +// BanjoDecomp: (core2 origin, not from GV overlay) #include #include "functions.h" #include "variables.h" diff --git a/src/GV/rubee.c b/src/GV/ch/rubee.c similarity index 56% rename from src/GV/rubee.c rename to src/GV/ch/rubee.c index 43befb426..6bdacb80d 100644 --- a/src/GV/rubee.c +++ b/src/GV/ch/rubee.c @@ -3,10 +3,10 @@ #include "functions.h" #include "variables.h" -void chRubee_update(Actor *this); +void func_80389B1C(Actor *this); /* .data */ -ActorAnimationInfo chRubeeAnimations[] = { +ActorAnimationInfo D_80390EA0[] = { {0x00, 0.0f}, {ASSET_DF_ANIM_RUBEE_PET_TOOTS, 4.5f}, {ASSET_E3_ANIM_RUBEE_IDLE, 2.0f}, @@ -15,38 +15,29 @@ ActorAnimationInfo chRubeeAnimations[] = { {ASSET_DF_ANIM_RUBEE_PET_TOOTS, 4.5f} }; -ActorInfo chRubee = { - MARKER_A9_RUBEE, ACTOR_11B_RUBEE, ASSET_3DD_MODEL_RUBEE, - 0x2, chRubeeAnimations, - chRubee_update, actor_update_func_80326224, actor_draw, +ActorInfo D_80390ED0 = { MARKER_A9_RUBEE, ACTOR_11B_RUBEE, ASSET_3DD_MODEL_RUBEE, + 0x2, D_80390EA0, + func_80389B1C, actor_update_func_80326224, actor_draw, 2500, 0, 1.6f, 0 }; -enum chrubee_state_e { - CH_RUBEE_STATE_0_NOT_INIT, - CH_RUBEE_STATE_1_IDLE, - CH_RUBEE_STATE_2_IDLE, - CH_RUBEE_STATE_3_PLAYING_SONG, - CH_RUBEE_STATE_4_UNK, - CH_RUBEE_STATE_5_UNK -}; /* .code */ void func_80389A20(ActorMarker *caller, enum asset_e text_id, s32 arg2){ Actor *this = marker_getActor(caller); func_8038E18C(); - subaddie_set_state_with_direction(this, CH_RUBEE_STATE_3_PLAYING_SONG, 0.0f, 1); + subaddie_set_state_with_direction(this, 3, 0.0f, 1); } void func_80389A60(Actor *this){ - gcdialog_showDialog(VER_SELECT(ASSET_A70_DIALOG_RUBEE_HELPED, 0x92C, 0, 0), 4, NULL, this->marker, func_80389A20, NULL); - this->has_met_before = TRUE; - subaddie_set_state(this, CH_RUBEE_STATE_5_UNK); + gcdialog_showDialog(ASSET_A70_DIALOG_RUBEE_HELPED, 4, NULL, this->marker, func_80389A20, NULL); + this->has_met_before = true; + subaddie_set_state(this, 5); } void func_80389ABC(Actor *this){ if(this->unk138_23){ - func_80389A20(this->marker, VER_SELECT(ASSET_A70_DIALOG_RUBEE_HELPED, 0x92C, 0, 0), -1); + func_80389A20(this->marker, ASSET_A70_DIALOG_RUBEE_HELPED, -1); } else{ this->unk138_23 = true; @@ -55,9 +46,9 @@ void func_80389ABC(Actor *this){ } } -void chRubee_update(Actor *this){ +void func_80389B1C(Actor *this){ if(!this->volatile_initialized){ - this->lifetime_value = (f32) rubeeEggPot_getEggGoal(); + this->lifetime_value = (f32) func_8038E184(); this->has_met_before = jiggyscore_isCollected(JIGGY_43_GV_HISTUP) || mapSpecificFlags_get(0); this->unk138_23 = jiggyscore_isCollected(JIGGY_43_GV_HISTUP) || mapSpecificFlags_get(2); this->volatile_initialized = true; @@ -71,26 +62,21 @@ void chRubee_update(Actor *this){ anctrl_setTransitionDuration(this->anctrl, 0.15f); - if(this->state == CH_RUBEE_STATE_1_IDLE - || this->state == CH_RUBEE_STATE_2_IDLE) - { - if(! this->has_met_before - && subaddie_playerIsWithinSphereAndActive(this, 250) - && !subaddie_playerIsWithinSphereAndActive(this, 0x50)) - { - gcdialog_showDialog(VER_SELECT(ASSET_A6F_DIALOG_RUBEE_MEET, 0x92B, 0, 0), 0xE, this->position, NULL, NULL, NULL); - this->has_met_before = TRUE; - mapSpecificFlags_set(0, TRUE); + if(this->state == 1 || this->state == 2){ + if(! this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 250) && !subaddie_playerIsWithinSphereAndActive(this, 0x50)){ + gcdialog_showDialog(ASSET_A6F_DIALOG_RUBEE_MEET, 0xe, this->position, NULL, NULL, NULL); + this->has_met_before = true; + mapSpecificFlags_set(0, true); } } switch(this->state){ - case CH_RUBEE_STATE_1_IDLE://L80389CC4 + case 1://L80389CC4 if(this->lifetime_value <= (f32)func_8038E178()){ func_80389ABC(this); } else if(actor_animationIsAt(this, 0.99f)){ - subaddie_maybe_set_state(this, CH_RUBEE_STATE_2_IDLE, 0.9f); + subaddie_maybe_set_state(this, 2, 0.9f); } if( actor_animationIsAt(this, 0.42f) @@ -106,27 +92,27 @@ void chRubee_update(Actor *this){ } break; - case CH_RUBEE_STATE_2_IDLE: //L80389DB0 + case 2: //L80389DB0 if(this->lifetime_value <= (f32)func_8038E178()){ func_80389ABC(this); } else if(actor_animationIsAt(this, 0.99f)){ - subaddie_maybe_set_state(this, CH_RUBEE_STATE_1_IDLE, 0.4f); + subaddie_maybe_set_state(this, 1, 0.4f); } break; - case CH_RUBEE_STATE_3_PLAYING_SONG: //L80389E14 + case 3: //L80389E14 if( actor_animationIsAt(this, 0.2f)){ func_8025A58C(500, 400); coMusicPlayer_playMusic(COMUSIC_27_GV_RUBEES_SONG, 28000); } if( actor_animationIsAt(this, 0.99f)){ - subaddie_set_state(this, CH_RUBEE_STATE_4_UNK); + subaddie_set_state(this, 4); } break; - case CH_RUBEE_STATE_4_UNK: //L80389E64 + case 4: //L80389E64 if(!func_8038E178()) - subaddie_set_state(this, CH_RUBEE_STATE_2_IDLE); + subaddie_set_state(this, 2); break; }//L80389E80 } diff --git a/src/GV/ch/sarcophagus.c b/src/GV/ch/sarcophagus.c index bc20521ce..260ffb7b4 100644 --- a/src/GV/ch/sarcophagus.c +++ b/src/GV/ch/sarcophagus.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/sarcophagus.c +// BanjoDecomp: CH/sarcophagus.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/slappa.c b/src/GV/ch/slappa.c index 5d8f275ce..e1423e092 100644 --- a/src/GV/ch/slappa.c +++ b/src/GV/ch/slappa.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/slappa.c +// BanjoDecomp: code_4740.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/toots.c b/src/GV/ch/toots.c index edeb96f8e..bf84aa0dd 100644 --- a/src/GV/ch/toots.c +++ b/src/GV/ch/toots.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/toots.c +// BanjoDecomp: CH/toots.c #include #include "functions.h" #include "variables.h" diff --git a/src/GV/ch/trunker.c b/src/GV/ch/trunker.c index 93e013092..d4a4b4958 100644 --- a/src/GV/ch/trunker.c +++ b/src/GV/ch/trunker.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/trunker.c +// BanjoDecomp: CH/trunker.c #include #include "functions.h" #include "variables.h" @@ -75,8 +75,8 @@ void chTrunker_update(Actor *this){ && !subaddie_playerIsWithinSphereAndActive(this, 80) && func_8028F2A0() ){ - gcdialog_showDialog(VER_SELECT(ASSET_A71_DIALOG_TRUNKER_MEET, 0x92D, 0, 0), 0xe, this->position, NULL, NULL, NULL); - this->has_met_before = TRUE; + gcdialog_showDialog(ASSET_A71_DIALOG_TRUNKER_MEET, 0xe, this->position, NULL, NULL, NULL); + this->has_met_before = true; }//L80389254 if(this->state == 1 && mapSpecificFlags_get(0xC)){ diff --git a/src/GV/checksums.c b/src/GV/checksums.c deleted file mode 100644 index a89de711c..000000000 --- a/src/GV/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: GV/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsGV; diff --git a/src/GV/crc.c b/src/GV/crc.c index 8ace3ef7a..22cff99bb 100644 --- a/src/GV/crc.c +++ b/src/GV/crc.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/crc.c +// BanjoDecomp: code_3B10.c #include #include "functions.h" #include "variables.h" @@ -7,9 +7,11 @@ extern void player_stateTimer_set(s32, f32); extern f32 player_stateTimer_get(enum state_timer_e); -s32 D_80390F30 = VER_SELECT(0x00274530, 0x002764CA, 0, 0); // GV_TEXT_CRC1 -s32 D_80390F34 = VER_SELECT(0xAA18BBF3, 0xFB1E80F4, 0, 0); // GV_TEXT_CRC2 -s32 D_80390F38 = VER_SELECT(0x0003031C, 0x00031973, 0, 0); // GV_DATA_CRC1 +/* .data */ +//TODO Implement CRC calculation in Makefile(?) +u32 D_80390F30 = 0x00274530; //GV.code CRC1 +u32 D_80390F34 = 0xAA18BBF3; //GV.code CRC2 +u32 D_80390F38 = 0x0003031C; //GV.data CRC1 (with this value = 0) /* .code */ diff --git a/src/GV/gv_helpers.c b/src/GV/gv_helpers.c index 0c40a25a4..fed404bb2 100644 --- a/src/GV/gv_helpers.c +++ b/src/GV/gv_helpers.c @@ -4,25 +4,25 @@ #include "variables.h" struct { - s32 eggCount; + s32 unk0; s32 unk4; s32 unk8; -} rubeeEggPot; +}GV_D_80391AB0; /* .code */ -void rubeeEggPot_addedEggToPot(void){ - rubeeEggPot.eggCount++; +void func_8038E140(void){ + GV_D_80391AB0.unk0++; coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 26000); } s32 func_8038E178(void){ - return rubeeEggPot.eggCount; + return GV_D_80391AB0.unk0; } -s32 rubeeEggPot_getEggGoal(void){ +s32 func_8038E184(void){ return 5; } void func_8038E18C(void){ - rubeeEggPot.unk8 = TRUE; + GV_D_80391AB0.unk8 = true; } diff --git a/src/GV/magiccarpet2.c b/src/GV/magiccarpet2.c deleted file mode 100644 index bbe7a21b2..000000000 --- a/src/GV/magiccarpet2.c +++ /dev/null @@ -1,171 +0,0 @@ -// BanjoDecomp: GV/magiccarpet2.c -#include -#include "functions.h" -#include "variables.h" - -extern f32 mapModel_getFloorY(f32[3]); - -// [port] func_80329904 is declared in functions.h with its real signature. -// void func_80329904(ActorMarker *, s32, void *); - -void chmagiccarpet2_emptyupdate(Actor *this); -void chmagiccarpet2_update(Actor *this); -Actor *chmagiccarpet2_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); - -/* .data */ -ActorAnimationInfo chMagicCarpet2Animations[] = { - {0, 0.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, - {ASSET_C9_ANIM_MAGIC_CARPET, 2.0f}, -}; - -ActorInfo chMagicCarpet2 = { - MARKER_B0_MAGIC_CARPET_2, ACTOR_123_MAGIC_CARPET_2, ASSET_3DC_MODEL_MAGIC_CARPET, - 0x1, chMagicCarpet2Animations, - chmagiccarpet2_emptyupdate, chmagiccarpet2_update, chmagiccarpet2_draw, - 0, 0, 0.0f, 0 -}; - -u8 D_80390FF4[6] = {0, 0, 0, 1, 1, 1}; - -enum chmagicarpet2_state_e { - CHMAGICCARPET2_STATE_0_NOT_INIT, - CHMAGICCARPET2_STATE_1_UNK, - CHMAGICCARPET2_STATE_2_UNK, - CHMAGICCARPET2_STATE_3_UNK, - CHMAGICCARPET2_STATE_4_UNK -}; - -/* .code */ -Actor *chmagiccarpet2_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - Actor * this = marker_getActor(this_marker); - - if(this->unk1C[0] != 0.0f){ - this = actor_draw(this_marker, gfx, mtx, vtx); - - if( this->unk54 == 0.0f - && this->unk48 != this->unk1C[1] - && this_marker->unk14_21 - && subaddie_playerIsWithinSphereAndActive(this, 3000) - ){ - commonParticle_add(this->marker, 6, func_80329904); - commonParticle_new(0xc, this->marker->unk14_21); - } - } - return this; -} - - -f32 func_8038A264(Actor *shadow, Actor* this){ - if(this && shadow){ - return ml_map_f(this->position_y - shadow->position_y, 0.0f, 2200.0f, 1.0f, 0.35f); - } - else{ - return 0.0; - } -} - -void func_8038A2C0(void *this_marker){ - Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, this_marker)); - Actor *shadow = spawn_child_actor(ACTOR_122_MAGIC_CARPET_SHADOW, &this); - s32 pad; - - suSetSpriteScale(shadow, this->scale); - this->partnerActor = shadow->marker; -} - -void chmagiccarpet2_emptyupdate(Actor *this){} - -void chmagiccarpet2_update(Actor *this){ - Actor *sp24; - - if(!this->volatile_initialized){ - this->volatile_initialized = TRUE; - actor_collisionOff(this); - __spawnQueue_add_1((GenFunction_1)func_8038A2C0, reinterpret_cast(uintptr_t, this->marker)); - this->velocity[0] = 0.0f; - } - - if(this->partnerActor) - sp24 = subaddie_getLinkedActor(this); - - this->unk1C[1] = this->unk48; - - switch(code7FF0_getMagicCarpetState(this, CHMAGICCARPET2_STATE_3_UNK)) - { - case CHMAGICCARPET2_STATE_1_UNK: //L8038A3C0 - func_80343DEC(this); - this->marker->propPtr->unk8_3 = TRUE; - this->unk1C[0] = 1.0; - this->alpha_124_19 = 0xff; - if(this->unk54 != 0.0f){ - subaddie_set_state_with_direction(this, 2, 0.02f, 1); - anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); - } - break; - case CHMAGICCARPET2_STATE_2_UNK: //L8038A440 - this->marker->propPtr->unk8_3 = TRUE; - this->unk1C[0] = 1.0; - if(45.0f <= this->velocity[0]){ - subaddie_set_state_with_direction(this, 3, 0.02f, 1); - this->velocity[0] = 0.0f; - } - else{ - if(D_80390FF4[((s32)this->velocity[0]) % 6] == 0){ - this->alpha_124_19 -= 0x55; - } - else{ - this->alpha_124_19 += 0x55; - } - this->velocity[0] += 1.0f; - } - break; - case CHMAGICCARPET2_STATE_3_UNK: //L8038A534 - func_80343DEC(this); - this->marker->propPtr->unk8_3 = FALSE; - this->unk1C[0] = 0.0; - this->alpha_124_19 = 0; - if(this->unk54 == 0.0f){ - subaddie_set_state_with_direction(this, 4, 0.02f, 1); - } - break; - - case CHMAGICCARPET2_STATE_4_UNK: //L8038A5A4 - this->marker->propPtr->unk8_3 = TRUE; - this->unk1C[0] = 1.0; - if(45.0f <= this->velocity[0]){ - subaddie_set_state_with_direction(this, 1, 0.02f, 1); - anctrl_setPlaybackType(this->anctrl, ANIMCTRL_LOOP); - this->velocity[0] = 0.0f; - } - else { - if(D_80390FF4[5 - ((s32)this->velocity[0])%6 ] != 0){ - this->alpha_124_19 += 0x55; - } - else{ - this->alpha_124_19 -= 0x55; - } - this->velocity[0] += 1.0f; - } - break; - }//L8038A6A4 - this->unk124_11 = 0x3; - this->pitch = 0.0f; - if(this->partnerActor && sp24 && this->partnerActor->id == MARKER_AF_MAGIC_CARPET_SHADOW){ - sp24->position_x = this->position_x; - sp24->position_y = mapModel_getFloorY(this->position) + 60.0f; - sp24->position_z = this->position_z; - sp24->unk1C[0] = func_8038A264(sp24, this); - sp24->yaw = this->yaw; - sp24->velocity[0] = 1.0; - sp24->velocity[1] = this->alpha_124_19; - if (0.0f != this->unk1C[0]) - sp24->unk1C[2] = 1.0; - else - sp24->unk1C[2] = 0.0f; - - }//L8038A780 -} diff --git a/src/GV/matchinggame.c b/src/GV/matchinggame.c index dc36b94f5..fea1e578d 100644 --- a/src/GV/matchinggame.c +++ b/src/GV/matchinggame.c @@ -71,9 +71,9 @@ void __matchingGame_setState(s32 next_state){ if(next_state == 2){ item_set(ITEM_6_HOURGLASS, 1); if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(4499, 0xea5, 0, 0)); + item_set(ITEM_0_HOURGLASS_TIMER, 4499); else - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(5999, 0x1387, 0, 0)); + item_set(ITEM_0_HOURGLASS_TIMER, 5999); } if(matchingGame.state == 2){ item_set(ITEM_6_HOURGLASS, 0); @@ -157,7 +157,7 @@ void gv_matchingGame_update(void){ } if(matchingGame.tile_a == NULL || matchingGame.tile_b == NULL){ - if( player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER && player_isStableWithExtraSteps()){ + if( player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER && func_8028F20C()){ player_getPosition(player_position); sp4C = model_func_8033F3E8(mapModel_getModel(0), player_position, 0x190, 0x1a0); if(sp4C){ diff --git a/src/GV/ch/mazectrl.c b/src/GV/mazectrl.c similarity index 90% rename from src/GV/ch/mazectrl.c rename to src/GV/mazectrl.c index 142e298a0..ffc5b2848 100644 --- a/src/GV/ch/mazectrl.c +++ b/src/GV/mazectrl.c @@ -1,4 +1,4 @@ -// BanjoDecomp: GV/ch/mazectrl.c +// BanjoDecomp: CH/mazectrl.c #include #include "functions.h" #include "variables.h" @@ -67,8 +67,8 @@ void __chMazeCtrl_setState(Actor *this, s32 next_state){ if(next_state == 2){ func_8025A58C(0, 4000); coMusicPlayer_playMusic(COMUSIC_26_GV_SANDYBUTT_DANGER, 30000); - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(0xdd3, 0xb85, 0, 0)); - item_set(ITEM_6_HOURGLASS, TRUE); + item_set(ITEM_0_HOURGLASS_TIMER, 0xdd3); + item_set(ITEM_6_HOURGLASS, true); func_8038F520(1.0f); FUNC_8030E624(SFX_3F6_RUBBING, 0.8f, 25000); FUNC_8030E624(SFX_3F6_RUBBING, 0.7f, 25000); @@ -86,8 +86,8 @@ void __chMazeCtrl_setState(Actor *this, s32 next_state){ } if (!levelSpecificFlags_get(LEVEL_FLAG_16_GV_UNKNOWN)) { - gcdialog_showDialog(VER_SELECT(ASSET_A82_DIALOG_SANDYBUTT_START_MAZE, 0x93E, 0, 0), 4, NULL, NULL, NULL, NULL); - levelSpecificFlags_set(LEVEL_FLAG_16_GV_UNKNOWN, TRUE); + gcdialog_showDialog(ASSET_A82_DIALOG_SANDYBUTT_START_MAZE, 4, NULL, NULL, NULL, NULL); + levelSpecificFlags_set(LEVEL_FLAG_16_GV_UNKNOWN, true); } }//L8038F794 @@ -136,8 +136,8 @@ void __chMazeCtrl_setState(Actor *this, s32 next_state){ coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7fff); if(!levelSpecificFlags_get(LEVEL_FLAG_17_GV_UNKNOWN)){ - gcdialog_showDialog(VER_SELECT(ASSET_A83_DIALOG_SANDYBUTT_DONE, 0x93F, 0, 0), 4, NULL, NULL, NULL, NULL); - levelSpecificFlags_set(LEVEL_FLAG_17_GV_UNKNOWN, TRUE); + gcdialog_showDialog(ASSET_A83_DIALOG_SANDYBUTT_DONE, 4, NULL, NULL, NULL, NULL); + levelSpecificFlags_set(LEVEL_FLAG_17_GV_UNKNOWN, true); } } @@ -179,7 +179,7 @@ void chMazeCtrl_update(Actor *this){ if (!levelSpecificFlags_get(LEVEL_FLAG_15_GV_UNKNOWN) && ml_timer_update(&local->unk8, sp34) - && gcdialog_showDialog(VER_SELECT(ASSET_A81_DIALOG_SANDYBUTT_ENTER, 0x93D, 0, 0), 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(ASSET_A81_DIALOG_SANDYBUTT_ENTER, 0, NULL, NULL, NULL, NULL) ) { levelSpecificFlags_set(LEVEL_FLAG_15_GV_UNKNOWN, true); } diff --git a/src/GV/pyramid_raise.c b/src/GV/pyramid_raise.c index c92504b67..355f171b7 100644 --- a/src/GV/pyramid_raise.c +++ b/src/GV/pyramid_raise.c @@ -17,49 +17,32 @@ typedef struct { f32 unk24; }ActorLocal_GV_6370; -void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state); -void chJinxyHeadSandybutt_update(Actor *this); -Actor *chJinxyHeadSandybutt_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_8038C8A0(Actor *this, s32 next_state); +void func_8038CC98(Actor *this); +Actor *func_8038CC40(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); /* .data */ -u8 chJinxyHeadSandybuttIndices[3] = {0, 1, 2}; - -// Jinxy Head 2 -ActorInfo chJinxyHeadSandybutt1 = { - MARKER_BB_JINXY_HEAD_SANDYBUTT, ACTOR_285_JINXY_HEAD_SANDYBUTT_1, ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, +u8 D_803911F0[3] = {0, 1, 2}; +ActorInfo D_803911F4 = { 0xBB, 0x285, 0x3E6, 0, NULL, - chJinxyHeadSandybutt_update, actor_update_func_80326224, chJinxyHeadSandybutt_draw, + func_8038CC98, actor_update_func_80326224, func_8038CC40, 0, 0, 0.0f, 0 }; -ActorInfo chJinxyHeadSandybutt2 = { - MARKER_BB_JINXY_HEAD_SANDYBUTT, ACTOR_286_JINXY_HEAD_SANDYBUTT_2, ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, +ActorInfo D_80391218 = { 0xBB, 0x286, 0x3E6, 0, NULL, - chJinxyHeadSandybutt_update, actor_update_func_80326224, chJinxyHeadSandybutt_draw, + func_8038CC98, actor_update_func_80326224, func_8038CC40, 0, 0, 0.0f, 0 }; -ActorInfo chJinxyHeadSandybutt3 = { - MARKER_BB_JINXY_HEAD_SANDYBUTT, ACTOR_287_JINXY_HEAD_SANDYBUTT_3, ASSET_3E6_JINXY_HEAD_KING_SANDYBUTT, +ActorInfo D_8039123C = { 0xBB, 0x287, 0x3E6, 0, NULL, - chJinxyHeadSandybutt_update, actor_update_func_80326224, chJinxyHeadSandybutt_draw, + func_8038CC98, actor_update_func_80326224, func_8038CC40, 0, 0, 0.0f, 0 }; -enum chjinxyheadsandybutt_state_e { - CHJINXYHEADSANDYBUTT_STATE_0_NOT_INIT, - CHJINXYHEADSANDYBUTT_STATE_1_UNK, - CHJINXYHEADSANDYBUTT_STATE_2_UNK, - CHJINXYHEADSANDYBUTT_STATE_3_UNK, - CHJINXYHEADSANDYBUTT_STATE_4_UNK, - CHJINXYHEADSANDYBUTT_STATE_5_UNK, - CHJINXYHEADSANDYBUTT_STATE_6_FED, - CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY, - CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED -}; - /* .code */ -void chJinxyHeadSandybutt_raisePyramid(Actor *this, s32 arg1){ +void func_8038C760(Actor *this, s32 arg1){ ActorLocal_GV_6370 *local = (ActorLocal_GV_6370 *)&this->local; chBuriedPyramid_setRaisedAmount(local->unk14, arg1); FUNC_8030E624(SFX_3F6_RUBBING, 0.7f, 28000); @@ -80,26 +63,21 @@ void chJinxyHeadSandybutt_raisePyramid(Actor *this, s32 arg1){ } } -void chJinxyHeadSandybutt_free(Actor *this){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_0_NOT_INIT); +void func_8038C880(Actor *this){ + func_8038C8A0(this, 0); } -void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state){ +void func_8038C8A0(Actor *this, s32 next_state){ ActorLocal_GV_6370 *local = (ActorLocal_GV_6370 *)&this->local; local->unk0 = 0; local->unk24 = 0.0f; - this->marker->propPtr->unk8_3 = (next_state == CHJINXYHEADSANDYBUTT_STATE_1_UNK) ? FALSE : TRUE; - this->marker->collidable = (next_state == CHJINXYHEADSANDYBUTT_STATE_1_UNK) ? FALSE : TRUE; - if(this->state == CHJINXYHEADSANDYBUTT_STATE_4_UNK - || this->state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) - { + this->marker->propPtr->unk8_3 = (next_state == 1) ? false : true; + this->marker->collidable = (next_state == 1) ? false : true; + if(this->state == 4 || this->state == 5) sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); - } - if(next_state == CHJINXYHEADSANDYBUTT_STATE_4_UNK - || next_state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) - { + if(next_state == 4 || next_state == 5){ local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(local->sfxsourceIdx, SFX_3EC_CCW_DOOR_OPENING); sfxSource_setunk43_7ByIndex(local->sfxsourceIdx, 3); @@ -108,7 +86,7 @@ void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state){ sfxSource_func_8030E2C4(local->sfxsourceIdx); }//L8038C9B8 - if(next_state == CHJINXYHEADSANDYBUTT_STATE_2_UNK){ + if(next_state == 2){ skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 1.0f, 3.0f); skeletalAnim_setProgress(this->unk148, 0.27f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); @@ -122,31 +100,28 @@ void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state){ } }//L8038CA6C - if(next_state == CHJINXYHEADSANDYBUTT_STATE_3_UNK){ + if(next_state == 3){ local->unk24 = 3.0f; skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 1.0f, 3.0f); skeletalAnim_setProgress(this->unk148, 0.27f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); }//L8038CAB4 - if(this->state == CHJINXYHEADSANDYBUTT_STATE_3_UNK){ + if(this->state == 3){ skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 0.5f, 3.0f); skeletalAnim_setProgress(this->unk148, 0.99f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - if(next_state == CHJINXYHEADSANDYBUTT_STATE_4_UNK - || next_state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) - { + if(next_state == 4 || next_state == 5) sfx_playFadeShorthandDefault(SFX_DE_WOOD_SQUEAK, 1.0f, 32675, this->position, 500, 1500); - } }//L8038CB20 - if(next_state == CHJINXYHEADSANDYBUTT_STATE_6_FED){ + if(next_state == 6){ func_80324E38(0.0f, 3); skeletalAnim_set(this->unk148, ASSET_F0_ANIM_MINI_SHPYNX_EATING, 0.0f, 3.0f); coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); } - if(next_state == CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY){ + if(next_state == 7){ local->unkC = 0.0f; local->unk18[0] = this->position_x; local->unk18[1] = this->position_y; @@ -155,26 +130,26 @@ void chJinxyHeadSandybutt_setState(Actor *this, s32 next_state){ FUNC_8030E624(SFX_3F6_RUBBING, 0.8f, 30000); } - if(next_state == CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED){ - if(this->state == CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY){ + if(next_state == 8){ + if(this->state == 7){ baMotor_80250D94(0.8f, 0.7f, 3.0f); - chJinxyHeadSandybutt_raisePyramid(this, *local->unk8 + 1); + func_8038C760(this, *local->unk8 + 1); } marker_despawn(this->marker); } this->state = next_state; } -Actor *chJinxyHeadSandybutt_draw(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *func_8038CC40(ActorMarker *this_marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(this_marker); - if(this->state == CHJINXYHEADSANDYBUTT_STATE_1_UNK) return this; + if(this->state == 1) return this; return actor_draw(this_marker, gfx, mtx, vtx); } -void chJinxyHeadSandybutt_update(Actor *this){ +void func_8038CC98(Actor *this){ ActorLocal_GV_6370 *local = (ActorLocal_GV_6370 *)&this->local; - f32 time_delta = time_getDelta(); - s32 pyramid_file_progress; + f32 sp80 = time_getDelta(); + s32 sp7C; f32 pad70; f32 sp6C[3]; f32 f12; @@ -184,24 +159,24 @@ void chJinxyHeadSandybutt_update(Actor *this){ f32 sp48[3]; if(!this->volatile_initialized){ - pyramid_file_progress = fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2); - this->volatile_initialized = TRUE; - this->marker->actorFreeFunc = chJinxyHeadSandybutt_free; - local->unk8 = &chJinxyHeadSandybuttIndices[this->modelCacheIndex - 0x285]; + sp7C = fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2); + this->volatile_initialized = true; + this->marker->actorFreeFunc = func_8038C880; + local->unk8 = &D_803911F0[this->modelCacheIndex - 0x285]; local->unk10 = 0; local->unk14 = 0; local->unkC = 0.0f; local->unk18[0] = this->position_x; local->unk18[1] = this->position_y; local->unk18[2] = this->position_z; - if(*local->unk8 < pyramid_file_progress){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED); + if(*local->unk8 < sp7C){ + func_8038C8A0(this, 8); } - else if(pyramid_file_progress == *local->unk8){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_2_UNK); + else if(sp7C == *local->unk8){ + func_8038C8A0(this, 2); } else{ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_1_UNK); + func_8038C8A0(this, 1); } return; } @@ -210,22 +185,17 @@ void chJinxyHeadSandybutt_update(Actor *this){ local->unk14 = actorArray_findActorFromActorId(ACTOR_31D_SANDYBUTT_PYRAMID)->marker; } - if(this->state != CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED && fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2) > *local->unk8){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED); - return; - } - - if(this->state == CHJINXYHEADSANDYBUTT_STATE_1_UNK){ + if(this->state == 1){ if(fileProgressFlag_getN(FILEPROG_F8_KING_SANDYBUTT_PYRAMID_STATE, 2) == *local->unk8){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_2_UNK); + func_8038C8A0(this, 2); } } - if(this->state == CHJINXYHEADSANDYBUTT_STATE_2_UNK){ - local->unkC += 0.5 * time_delta; + if(this->state == 2){ + local->unkC += 0.5*sp80; if(1.0f <= local->unkC){ local->unkC = 1.0f; - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_3_UNK); + func_8038C8A0(this, 3); } sp6C[0] = 0.0f; sp6C[1] = 0.0f; @@ -236,28 +206,26 @@ void chJinxyHeadSandybutt_update(Actor *this){ this->position_z = local->unk18[2] + sp6C[2]; }//L8038CECC - if(this->state == CHJINXYHEADSANDYBUTT_STATE_3_UNK){ + if(this->state == 3){ if(0.0f < local->unk24){ - local->unk24 -= time_delta; + local->unk24 -= sp80; } else{ if(func_8038D388()) - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_5_UNK); + func_8038C8A0(this, 5); } }//L8038CF1C - if(this->state == CHJINXYHEADSANDYBUTT_STATE_4_UNK - || this->state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) - { - local->unkC += ((this->state == 4)? -1 : 1) * time_delta; + if(this->state == 4 || this->state == 5){ + local->unkC += ((this->state == 4)? -1 : 1) * sp80; if(1.0f < local->unkC){ local->unkC = 1.0f; - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_4_UNK); + func_8038C8A0(this, 4); return; } else if(local->unkC < -1.0f){ local->unkC = -1.0f; - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_5_UNK); + func_8038C8A0(this, 5); return; } sp5C[0] = local->unkC*300.0f; @@ -268,21 +236,21 @@ void chJinxyHeadSandybutt_update(Actor *this){ this->position_y = local->unk18[1] + sp5C[1]; this->position_z = local->unk18[2] + sp5C[2]; if(0.8 <= local->unkC){ - f12 = 1.0 - (local->unkC - 0.8) / 0.2; + f12 = 1.0 - (local->unkC - 0.8)/0.2; } else if(local->unkC <= -0.8){ - f12 = 1.0 - (-local->unkC - 0.8) / 0.2; + f12 = 1.0 - (-local->unkC - 0.8)/0.2; } else{ f12 = 1.0f; } - func_8030DB04(local->sfxsourceIdx, f12 * 24000.0f, this->position, 200.0f, 1500.0f); + func_8030DB04(local->sfxsourceIdx, f12*24000.0f, this->position, 200.0f, 1500.0f); if(!func_8038D388()){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_3_UNK); + func_8038C8A0(this, 3); } }//L8038D110 - if(this->state == CHJINXYHEADSANDYBUTT_STATE_6_FED){ + if(this->state == 6){ skeletalAnim_getProgressRange(this->unk148, &sp58, &sp54); if(sp58 < 0.28 && 0.28 <= sp54){ FUNC_8030E624(SFX_4C_LIP_SMACK, 1.0f, 28000); @@ -295,18 +263,18 @@ void chJinxyHeadSandybutt_update(Actor *this){ } if(0.81 <= sp54){ FUNC_8030E624(SFX_97_BLUBBER_BURPS, 1.0f, 28000); - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY); + func_8038C8A0(this, 7); } }//L8038D228 - if(this->state == CHJINXYHEADSANDYBUTT_STATE_7_GO_AWAY){ - local->unkC += 0.5 * time_delta; + if(this->state == 7){ + local->unkC += 0.5*sp80; if(1.0f < local->unkC){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_8_COMPLETED); + func_8038C8A0(this, 8); } sp48[0] = 0.0f; sp48[1] = 0.0f; - sp48[2] = local->unkC * -600.0f; + sp48[2] = local->unkC*-600.0f; ml_vec3f_yaw_rotate_copy(sp48, sp48, this->yaw); this->position_x = local->unk18[0] + sp48[0]; this->position_y = local->unk18[1] + sp48[1]; @@ -314,13 +282,11 @@ void chJinxyHeadSandybutt_update(Actor *this){ }//L8038D2F0 if(local->unk0){ - if(this->state == CHJINXYHEADSANDYBUTT_STATE_4_UNK - || this->state == CHJINXYHEADSANDYBUTT_STATE_5_UNK) - { + if(this->state == 4 || this->state == 5){ local->unk0 = 0; local->unk10++; if(local->unk10 == 3){ - chJinxyHeadSandybutt_setState(this, CHJINXYHEADSANDYBUTT_STATE_6_FED); + func_8038C8A0(this, 6); } else{ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); diff --git a/src/GV/sandybutteggtoll.c b/src/GV/pyramid_trigger.c similarity index 69% rename from src/GV/sandybutteggtoll.c rename to src/GV/pyramid_trigger.c index cf82896bc..568c38890 100644 --- a/src/GV/sandybutteggtoll.c +++ b/src/GV/pyramid_trigger.c @@ -1,15 +1,14 @@ -// BanjoDecomp: GV/sandybutteggtoll.c +// BanjoDecomp: code_6F80.c #include #include "functions.h" #include "variables.h" -void chSandybuttEggToll_update(Actor *this); +void func_8038D3AC(Actor *this); /* .data */ -ActorInfo chSandybuttEggToll = { - MARKER_1A5_SANDYBUTT_EGG_TOLL, 0x288, ASSET_402_MODEL_EGG_TOLL, +ActorInfo D_80391260 = { 0x1A5, 0x288, 0x402, 0, NULL, - chSandybuttEggToll_update, NULL, func_80325340, + func_8038D3AC, NULL, func_80325340, 0, 0, 0.0f, 0 }; @@ -21,11 +20,11 @@ void func_8038D370(ActorMarker *this_marker, ActorMarker *other_marker){ D_80391AA0 = 5; } -bool func_8038D388(void){ +int func_8038D388(void){ return D_80391AA0 ? 1 : 0; } -void chSandybuttEggToll_update(Actor *this){ +void func_8038D3AC(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; marker_setCollisionScripts(this->marker, func_8038D370, NULL, NULL); diff --git a/src/GV/smoke_particle.c b/src/GV/smoke_particle.c index 371669359..41f471ae7 100644 --- a/src/GV/smoke_particle.c +++ b/src/GV/smoke_particle.c @@ -7,9 +7,7 @@ void GV_func_8038A084(Actor *this); /* .data */ -// Hot Sand Smoke Emitter? -ActorInfo D_80390F40 = { - 0x24F, 0x37C, 0x0, +ActorInfo D_80390F40 = { 0x24F, 0x37C, 0x0, 0, NULL, GV_func_8038A084, actor_update_func_80326224, func_80325340, 2000, 0, 0.0f, 0 diff --git a/src/GV/water_pyramidrot.c b/src/GV/water_pyramidrot.c index ec385dd8f..67dec578d 100644 --- a/src/GV/water_pyramidrot.c +++ b/src/GV/water_pyramidrot.c @@ -4,8 +4,6 @@ #include "variables.h" -static s32 sGvPyramidRaised = 0; - void func_8038FF60(void){} void func_8038FF68(void){ @@ -17,27 +15,11 @@ void func_8038FF68(void){ if(jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID)){ tmp_s70 = func_8034C528(0x190); if(tmp_s70) subaddie_positionMoveVertical(&tmp_s70->type_6D, 0.0f, 270.0f, 0.0f, 1); - sGvPyramidRaised = 1; } else{ tmp_s70 = func_8034C5AC(0x130); if(tmp_s70) func_8034E71C(&tmp_s70->type_73, -1500, 0.0f); - sGvPyramidRaised = 0; } } -void func_8038FFF4(void){ - Struct70s *tmp_s70; - - // LEVEL_FLAG_6 = local rise cutscene in progress. - if(sGvPyramidRaised) return; - if(gsworld_getMap() != MAP_12_GV_GOBIS_VALLEY) return; - if(levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN)) return; - if(!jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID)) return; - - tmp_s70 = func_8034C5AC(0x130); - if(tmp_s70) func_8034E71C(&tmp_s70->type_73, 0, 2.5f); - tmp_s70 = func_8034C528(0x190); - if(tmp_s70) subaddie_positionMoveVertical(&tmp_s70->type_6D, 0.0f, 270.0f, 2.5f, 1); - sGvPyramidRaised = 1; -} +void func_8038FFF4(void){} diff --git a/src/lair/lairspawnqueue.c b/src/LAIR/actor_spawninit.c similarity index 73% rename from src/lair/lairspawnqueue.c rename to src/LAIR/actor_spawninit.c index 32751345e..5679de22d 100644 --- a/src/lair/lairspawnqueue.c +++ b/src/LAIR/actor_spawninit.c @@ -1,4 +1,4 @@ -// BanjoDecomp: lair/lairspawnqueue.c +// BanjoDecomp: code_0.c #include #include "functions.h" #include "variables.h" @@ -10,14 +10,13 @@ extern void func_8028F918(s32); extern void func_802D2FB0(Actor *, s32, s32, s32, f32, s32, s32, s32); extern void func_802D3CE8(Actor *); -extern void chMMMBreakableWooden_update(Actor *); +extern void func_802D3D54(Actor *); extern void func_802D3D74(Actor *this); extern void func_802D4830(Actor *, s32, f32); extern void func_80324CFC(f32, enum comusic_e, s32); extern int actor_animationIsAt(Actor *, f32); extern void subaddie_set_state_with_direction(Actor *, s32, f32, s32); -extern void modelRender_setAppendageVisibility(s32, s32); -extern ActorArray *suBaddieActorArray; +extern void func_8033A45C(s32, s32); @@ -116,335 +115,53 @@ ActorAnimationInfo D_80392CB0[] = { {0x271, 3.0f}, {0x271, 1e+08f} }; -ActorInfo lair_D_80392D90 = { - MARKER_270_TWO_ICE_POLES_NEAR_CHEATO_3, ACTOR_2D8_TWO_ICE_POLES_NEAR_CHEATO_3, ASSET_3B2_MODEL_TWO_ICE_POLES_NEAR_CHEATO_3, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392DB4 = { - MARKER_110_RAISE_GRATE_TO_BGS_PUZZLE_SWITCH, ACTOR_214_RAISE_GRATE_TO_BGS_PUZZLE_SWITCH, ASSET_4AB_MODEL_RAISE_GRATE_TO_BGS_PUZZLE_SWITCH, - 0x1, D_80392CB0, - func_803896D4, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392DD8 = { - MARKER_113_RAISE_PIPE_TO_CC_ENTRANCE_SWITCH, ACTOR_217_RAISE_PIPE_TO_CC_ENTRANCE_SWITCH, ASSET_4A9_MODEL_RAISE_PIPE_TO_CC_ENTRANCE_SWITCH, - 0x1, D_80392CB0, - func_803896F4, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392DFC = { - MARKER_115_RAISE_PIPE_TO_BRENTILDA_SWITCH, ACTOR_219_RAISE_PIPE_TO_BRENTILDA_SWITCH, ASSET_4AA_MODEL_RAISE_PIPE_TO_BRENTILDA_SWITCH, - 0x1, D_80392CB0, - func_80389714, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392E20 = { - MARKER_11B_WATER_LEVEL_SWITCH_1, ACTOR_221_LEVEL_1_WATER_SWITCH, ASSET_4B5_MODEL_LEVEL_1_WATER_SWITCH, - 0x1, D_80392CB0, - func_80389734, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392E44 = { - MARKER_11C_WATER_LEVEL_SWITCH_2, ACTOR_222_LEVEL_2_WATER_SWITCH, ASSET_4B2_MODEL_LEVEL_2_WATER_SWITCH, - 0x1, D_80392CB0, - func_8038975C, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392E68 = { - MARKER_11D_WATER_LEVEL_SWITCH_3, ACTOR_223_LEVEL_3_WATER_SWITCH, ASSET_4B0_MODEL_LEVEL_3_WATER_SWITCH, - 0x1, D_80392CB0, - func_80389784, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392E8C = { - MARKER_232_CCW_PUZZLE_SWITCH, ACTOR_23C_CCW_PUZZLE_SWITCH, ASSET_4B8_MODEL_CCW_PUZZLE_SWITCH, - 0x1, D_80392CB0, - func_803897AC, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392EB0 = { - MARKER_23F_LAIR_FLIGHT_PAD_SWITCH, ACTOR_246_FLIGHT_PAD_SWITCH, ASSET_534_MODEL_FLIGHT_PAD_SWITCH, - 0x1, D_80392CB0, - func_80386D20, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392ED4 = { - MARKER_241_SHOCK_JUMP_PAD_SWITCH, ACTOR_248_SHOCK_JUMP_PAD_SWITCH, ASSET_540_MODEL_SHOCK_JUMP_PAD_SWITCH, - 0x1, D_80392CB0, - func_80386780, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392EF8 = { - MARKER_109_BREAKABLE_BRICK_WALL, ACTOR_20D_BREAKABLE_BRICK_WALL, ASSET_4A1_MODEL_BREAKABLE_BRICK_WALL, - 0x1, D_80392CB0, - lair_func_80386550, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0x85 -}; - -ActorInfo D_80392F1C = { - MARKER_264_LARGE_DOOR_TO_FINAL_BATTLE, ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE, ASSET_550_MODEL_LARGE_DOOR_TO_FINAL_BATTLE, - 0x19, D_80392CB0, - func_80388524, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392F40 = { - MARKER_224_BREAKABLE_FLOOR_COBWEB, ACTOR_230_BREAKABLE_FLOOR_COBWEB, ASSET_4BF_MODEL_FLOOR_COBWEB, - 0xB, D_80392CB0, - chFloorCobweb_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0x88 -}; - -ActorInfo D_80392F64 = { - MARKER_225_BREAKABLE_WALL_COBWEB, ACTOR_231_BREAKABLE_WALL_COBWEB, ASSET_4D5_MODEL_WALL_COBWEB, - 0xE, D_80392CB0, - chWallCobweb_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0x88 -}; - -ActorInfo D_80392F88 = { - MARKER_111_GL_CC_ENTRANCE_LONG_PIPE_GREEN, ACTOR_215_GL_CC_ENTRANCE_LONG_PIPE_GREEN, ASSET_4A4_MODEL_GL_CC_ENTRANCE_LONG_PIPE_GREEN, - 0x1, NULL, - func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392FAC = { - MARKER_112_GL_CC_ENTRANCE_LONG_PIPE_BLUE, ACTOR_216_GL_CC_ENTRANCE_LONG_PIPE_BLUE, ASSET_4A5_MODEL_GL_CC_ENTRANCE_LONG_PIPE_BLUE, - 0x1, NULL, - func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392FD0 = { - MARKER_114_GL_CC_ENTRANCE_SHORT_PIPE, ACTOR_218_GL_CC_ENTRANCE_SHORT_PIPE, ASSET_4A6_MODEL_GL_CC_ENTRANCE_SHORT_PIPE, - 0x1, NULL, - lair_func_80389204, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80392FF4 = { - MARKER_10D_TTC_ENTRANCE_CHEST_LID, ACTOR_211_TTC_ENTRANCE_CHEST_LID, ASSET_4A3_MODEL_GL_TTC_ENTRANCE_CHEST_LID, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80393018 = { - MARKER_22C_GL_ADVENT_CALENDAR_HATCH_DOOR, ACTOR_23A_GL_ADVENT_CALENDAR_HATCH_DOOR, ASSET_4D9_MODEL_GL_ADVENT_CALENDAR_HATCH_DOOR, - 0x1, NULL, - func_803882B0, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_8039303C = { - MARKER_164_GL_GRUNTY_FLOOR_PICTURE_EYE_1, ACTOR_259_GL_GRUNTY_FLOOR_PICTURE_EYE_1, ASSET_507_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_1, - 0x1, NULL, - func_803880BC, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80393060 = { - MARKER_165_GL_GRUNTY_FLOOR_PICTURE_EYE_2, ACTOR_25A_GL_GRUNTY_FLOOR_PICTURE_EYE_2, ASSET_508_MODEL_GL_GRUNTY_FLOOR_PICTURE_EYE_2, - 0x1, NULL, - func_8038824C, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80393084 = { - MARKER_240_LAIR_SWITCH_FLIGHT_PAD, ACTOR_247_LAIR_SWITCH_FLIGHT_PAD, ASSET_48A_MODEL_FLIGHT_PAD, - 0x1, NULL, - func_80386D78, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803930A8 = { - MARKER_242_LAIR_SWITCH_SHOCK_JUMP_PAD, ACTOR_249_LAIR_SWITCH_SHOCK_JUMP_PAD, ASSET_2DD_MODEL_SHOCK_JUMP_PAD, - 0x1, NULL, - func_803867A8, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803930CC = { - MARKER_11F_RAREWARE_BOX, ACTOR_225_RAREWARE_BOX, ASSET_4B3_MODEL_RAREWARE_BOX, - 0x1, NULL, - func_8038A064, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803930F0 = { - MARKER_10A_MM_ENTRANCE_DOOR, ACTOR_20E_MM_ENTRANCE_DOOR, ASSET_4A2_MODEL_GL_MM_DOOR_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80393114 = { - MARKER_11A_GRATE_TO_RBB_PUZZLE, ACTOR_220_GRATE_TO_RBB_PUZZLE, ASSET_4B7_MODEL_GRATE_TO_RBB_PUZZLE, - 0x1, NULL, - func_80389FF4, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x91 -}; - -ActorInfo D_80393138 = { - MARKER_11E_ICE_BALL_TO_CHEATO, ACTOR_224_ICE_BALL_TO_CHEATO, ASSET_4AF_MODEL_ICE_BALL_TO_CHEATO, - 0x1, NULL, - func_8038A014, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x83 -}; - -ActorInfo D_8039315C = { - MARKER_227_CCW_ENTRANCE_DOOR, ACTOR_234_CCW_ENTRANCE_DOOR, ASSET_4D6_MODEL_GL_CCW_DOOR_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x93 -}; - -ActorInfo D_80393180 = { - MARKER_228_FP_ENTRANCE_DOOR_LEFT, ACTOR_235_FP_ENTRANCE_DOOR_LEFT, ASSET_4D7_MODEL_GL_FP_DOOR_ENTRANCE_LEFT, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x8B -}; - -ActorInfo D_803931A4 = { - MARKER_229_FP_ENTRANCE_DOOR_RIGHT, ACTOR_236_FP_ENTRANCE_DOOR_RIGHT, ASSET_4D8_MODEL_GL_FP_DOOR_ENTRANCE_LEFT, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x8B -}; - -ActorInfo D_803931C8 = { - MARKER_121_GLASS_EYE, ACTOR_227_GLASS_EYE, ASSET_4BD_MODEL_GLASS_EYE, - 0x1, NULL, - func_8038A034, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0x89 -}; - -ActorInfo D_803931EC = { - MARKER_116_IRON_BARS_UNDER_GRUNTY_STATUE, ACTOR_21A_IRON_BARS_UNDER_GRUNTY_STATUE, ASSET_4AC_MODEL_IRON_BARS_UNDER_GRUNTY_STATUE, - 0x1, NULL, - func_803893B8, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x82 -}; - -ActorInfo D_80393210 = { - MARKER_117_GRUNTY_STATUE_BREAKABLE_HAT_TOP, ACTOR_21B_GRUNTY_STATUE_BREAKABLE_HAT_TOP, ASSET_4AD_MODEL_GRUNTY_STATUE_BREAKABLE_HAT_TOP, - 0x1, NULL, - lair_func_803894B0, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x82 -}; - -ActorInfo D_80393234 = { - MARKER_10B_RBB_ENTRANCE_DOOR, ACTOR_20F_RBB_ENTRANCE_DOOR, ASSET_4B4_MODEL_GL_RBB_DOOR_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x90 -}; - -ActorInfo D_80393258 = { - MARKER_10C_BGS_ENTRANCE_DOOR, ACTOR_210_BGS_ENTRANCE_DOOR, ASSET_4AE_MODEL_GL_BGS_DOOR_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x84 -}; - -ActorInfo D_8039327C = { - MARKER_10E_CC_ENTRANCE_DOOR, ACTOR_212_CC_ENTRANCE_BARS, ASSET_4A7_MODEL_GL_CC_IRON_BARS_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x7F -}; - -ActorInfo D_803932A0 = { - MARKER_120_GV_ENTRANCE, ACTOR_226_GV_ENTRANCE, ASSET_4BC_MODEL_GL_GV_DOOR_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x87 -}; - -ActorInfo D_803932C4 = { - MARKER_122_MMM_ENTRANCE_DOOR, ACTOR_228_MMM_ENTRANCE_DOOR, ASSET_4BE_MODEL_GL_MMM_DOOR_ENTRANCE, - 0x1, NULL, - func_80388524, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x8C -}; - -ActorInfo D_803932E8 = { - MARKER_10F_GL_BGS_PUZZLE_GRATE, ACTOR_213_GL_BGS_PUZZLE_GRATE, ASSET_4A8_MODEL_GL_BGS_PUZZLE_GRATE, - 0x1, NULL, - func_803875F0, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x80 -}; - -ActorInfo D_8039330C = { - MARKER_118_GRATE_TO_LEVEL_3_WATER_SWITCH, ACTOR_21E_GRATE_TO_LEVEL_3_WATER_SWITCH, ASSET_4B1_MODEL_GRATE_TO_LEVEL_3_WATER_SWITCH, - 0x1, NULL, - lair_func_8038A084, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x8F -}; - -ActorInfo D_80393330 = { - MARKER_119_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, ACTOR_21F_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, ASSET_4B6_MODEL_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, - 0x1, NULL, - func_8038A0A4, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0x92 -}; - -ActorInfo D_80393354 = { - MARKER_266_LEVEL_ENTRY_SIGNS, ACTOR_2E3_LEVEL_ENTRY_SIGNS, ASSET_563_MODEL_LEVEL_ENTRY_SIGNS, - 0x1, NULL, - func_803870DC, actor_update_func_80326224, lair_func_80387560, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80393378 = { - MARKER_17D_IRON_GATE_NO_LOCK, ACTOR_1E1_IRON_GATE_NO_LOCK, ASSET_517_MODEL_IRON_GATE_NO_LOCK, - 0x1, NULL, - func_80389D08, actor_update_func_80326224, func_80389E10, - 0, 0, 0.0f, 0x8D -}; - -ActorInfo D_8039339C = { - MARKER_234_GL_WOODEN_COFFIN_NO_LID, ACTOR_23E_GL_WOODEN_COFFIN_NO_LID, ASSET_4E1_MODEL_GL_WOODEN_COFFIN_NO_LID, - 0x12, D_80392CB0, - func_8038982C, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803933C0 = { - MARKER_163_CRYPT_COFFIN_LID, ACTOR_258_CRYPT_COFFIN_LID, ASSET_511_MODEL_CRYPT_COFFIN_LID, - 0x12, D_80392CB0, - func_80389898, actor_update_func_80326224, func_8038664C, - 0, 0, 0.0f, 0x8E -}; - -ActorInfo D_803933E4 = { - MARKER_160_GL_SARCOPHAGUS, ACTOR_255_GL_SARCOPHAGUS, ASSET_509_MODEL_GL_SARCOPHAGUS, - 0x15, D_80392CB0, - func_80389934, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80393408 = { - MARKER_102_NOTE_DOOR, ACTOR_203_NOTE_DOOR, ASSET_491_MODEL_NOTE_DOOR, - 0x1, D_80392CB0, - func_80387730, actor_update_func_80326224, func_80387DA8, - 0, 0, 0.0f, 0 -}; - +ActorInfo lair_D_80392D90 = { 0x270, 0x2D8, 0x3B2, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80392DB4 = { 0x110, 0x214, 0x4AB, 0x1, D_80392CB0, func_803896D4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392DD8 = { 0x113, 0x217, 0x4A9, 0x1, D_80392CB0, func_803896F4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392DFC = { 0x115, 0x219, 0x4AA, 0x1, D_80392CB0, func_80389714, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392E20 = { 0x11B, 0x221, 0x4B5, 0x1, D_80392CB0, func_80389734, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392E44 = { 0x11C, 0x222, 0x4B2, 0x1, D_80392CB0, func_8038975C, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392E68 = { 0x11D, 0x223, 0x4B0, 0x1, D_80392CB0, func_80389784, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392E8C = { 0x232, 0x23C, 0x4B8, 0x1, D_80392CB0, func_803897AC, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392EB0 = { 0x23F, 0x246, 0x534, 0x1, D_80392CB0, func_80386D20, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392ED4 = { 0x241, 0x248, 0x540, 0x1, D_80392CB0, func_80386780, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392EF8 = { MARKER_109_BREAKABLE_BRICK_WALL, ACTOR_20D_BREAKABLE_BRICK_WALL, ASSET_4A1_MODEL_BREAKABLE_BRICK_WALL, 0x1, D_80392CB0, lair_func_80386550, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x85}; +ActorInfo D_80392F1C = { 0x264, 0x2E5, 0x550, 0x19, D_80392CB0, func_80388524, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80392F40 = { MARKER_224_BREAKABLE_FLOOR_COBWEB, ACTOR_230_BREAKABLE_FLOOR_COBWEB, ASSET_4BF_MODEL_FLOOR_COBWEB, 0xB, D_80392CB0, chFloorCobweb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x88}; +ActorInfo D_80392F64 = { MARKER_225_BREAKABLE_WALL_COBWEB, ACTOR_231_BREAKABLE_WALL_COBWEB, ASSET_4D5_MODEL_WALL_COBWEB, 0xE, D_80392CB0, chWallCobweb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x88}; +ActorInfo D_80392F88 = { 0x111, 0x215, 0x4A4, 0x1, NULL, func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80392FAC = { 0x112, 0x216, 0x4A5, 0x1, NULL, func_80388FC8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80392FD0 = { 0x114, 0x218, 0x4A6, 0x1, NULL, lair_func_80389204, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80392FF4 = { 0x10D, 0x211, 0x4A3, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80393018 = { 0x22C, 0x23A, 0x4D9, 0x1, NULL, func_803882B0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_8039303C = { 0x164, 0x259, 0x507, 0x1, NULL, func_803880BC, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80393060 = { 0x165, 0x25A, 0x508, 0x1, NULL, func_8038824C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80393084 = { MARKER_240_LAIR_SWITCH_FLIGHT_PAD, 0x247, 0x48A, 0x1, NULL, func_80386D78, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_803930A8 = { 0x242, 0x249, 0x2DD, 0x1, NULL, func_803867A8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_803930CC = { 0x11F, 0x225, 0x4B3, 0x1, NULL, func_8038A064, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_803930F0 = { 0x10A, 0x20E, 0x4A2, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80393114 = { 0x11A, 0x220, 0x4B7, 0x1, NULL, func_80389FF4, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x91}; +ActorInfo D_80393138 = { 0x11E, 0x224, 0x4AF, 0x1, NULL, func_8038A014, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x83}; +ActorInfo D_8039315C = { 0x227, 0x234, 0x4D6, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x93}; +ActorInfo D_80393180 = { 0x228, 0x235, 0x4D7, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8B}; +ActorInfo D_803931A4 = { 0x229, 0x236, 0x4D8, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8B}; +ActorInfo D_803931C8 = { MARKER_121_GLASS_EYE, ACTOR_227_GLASS_EYE, ASSET_4BD_MODEL_GLASS_EYE, 0x1, NULL, func_8038A034, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0x89}; +ActorInfo D_803931EC = { 0x116, 0x21A, 0x4AC, 0x1, NULL, func_803893B8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x82}; +ActorInfo D_80393210 = { 0x117, 0x21B, 0x4AD, 0x1, NULL, lair_func_803894B0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x82}; +ActorInfo D_80393234 = { 0x10B, 0x20F, 0x4B4, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x90}; +ActorInfo D_80393258 = { 0x10C, 0x210, 0x4AE, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x84}; +ActorInfo D_8039327C = { 0x10E, 0x212, 0x4A7, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x7F}; +ActorInfo D_803932A0 = { 0x120, 0x226, 0x4BC, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x87}; +ActorInfo D_803932C4 = { 0x122, ACTOR_228_MMM_ENTRANCE_DOOR, 0x4BE, 0x1, NULL, func_80388524, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8C}; +ActorInfo D_803932E8 = { 0x10F, 0x213, 0x4A8, 0x1, NULL, func_803875F0, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x80}; +ActorInfo D_8039330C = { 0x118, 0x21E, 0x4B1, 0x1, NULL, lair_func_8038A084, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x8F}; +ActorInfo D_80393330 = { 0x119, 0x21F, 0x4B6, 0x1, NULL, func_8038A0A4, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0x92}; +ActorInfo D_80393354 = { 0x266, 0x2E3, 0x563, 0x1, NULL, func_803870DC, actor_update_func_80326224, lair_func_80387560, 0, 0, 0.0f, 0}; +ActorInfo D_80393378 = { 0x17D, 0x1E1, 0x517, 0x1, NULL, func_80389D08, actor_update_func_80326224, func_80389E10, 0, 0, 0.0f, 0x8D}; +ActorInfo D_8039339C = { 0x234, 0x23E, 0x4E1, 0x12, D_80392CB0, func_8038982C, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_803933C0 = { 0x163, 0x258, 0x511, 0x12, D_80392CB0, func_80389898, actor_update_func_80326224, func_8038664C, 0, 0, 0.0f, 0x8E}; +ActorInfo D_803933E4 = { 0x160, 0x255, 0x509, 0x15, D_80392CB0, func_80389934, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80393408 = { 0x102, 0x203, 0x491, 0x1, D_80392CB0, func_80387730, actor_update_func_80326224, func_80387DA8, 0, 0, 0.0f, 0}; ParticleScaleAndLifetimeRanges D_8039342C = { {0.31f, 0.37f}, {0.17f, 0.22f}, @@ -499,26 +216,11 @@ s32 D_80393504[4] = {0x87, 0x87, 0x87, 0xB4}; //chcobweb void chFloorCobweb_update(Actor *this) { - enum file_progress_e brokenFlag = (this->actorTypeSpecificField == 1) - ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN - : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN; - if(!this->initialized) { func_802D3CE8(this); - if (fileProgressFlag_get(brokenFlag)) - { - marker_despawn(this->marker); - return; - } - } - - // Anchor: re-check on scene-return restore, which resets volatile_initialized but not initialized. - if (!this->volatile_initialized) - { - this->volatile_initialized = true; - if (fileProgressFlag_get(brokenFlag)) + if (fileProgressFlag_get(this->actorTypeSpecificField == 1 ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN)) { marker_despawn(this->marker); return; @@ -549,17 +251,6 @@ void chWallCobweb_update(Actor *this) } } - // [port] Re-check on scene-return restore (see chFloorCobweb_update). - if (!this->volatile_initialized) - { - this->volatile_initialized = true; - if (fileProgressFlag_get(FILEPROG_CA_COBWEB_BLOCKING_PURPLE_CAULDRON_BROKEN)) - { - marker_despawn(this->marker); - return; - } - } - if (this->state == 0xF) { if (actor_animationIsAt(this, 0.9f)) @@ -572,26 +263,11 @@ void chWallCobweb_update(Actor *this) void lair_func_80386550(Actor *this) { - enum file_progress_e brokenFlag = (this->actorTypeSpecificField == 1) - ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN - : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN; - if (!this->initialized) { func_802D3CE8(this); - if (fileProgressFlag_get(brokenFlag)) - { - marker_despawn(this->marker); - return; - } - } - - // [port] Re-check on scene-return restore (see chFloorCobweb_update). - if (!this->volatile_initialized) - { - this->volatile_initialized = true; - if (fileProgressFlag_get(brokenFlag)) + if (fileProgressFlag_get(this->actorTypeSpecificField == 1 ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN)) { marker_despawn(this->marker); return; @@ -628,8 +304,8 @@ Actor *func_8038664C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) actor = marker_getActor(marker); val = actor->unk10_12; - modelRender_setAppendageVisibility(3, val == 1 ? 1 : 0); - modelRender_setAppendageVisibility(4, val == 0 ? 1 : 0); + func_8033A45C(3, val == 1 ? 1 : 0); + func_8033A45C(4, val == 0 ? 1 : 0); return actor_draw(marker, gfx, mtx, vtx); } @@ -769,7 +445,7 @@ void func_80386D20(Actor *this) void func_80386D40(void) { - code_4C020_setHourglassTimer(0xC); + func_802D68F0(0xC); item_set(ITEM_6_HOURGLASS, true); mapSpecificFlags_set(1, true); } @@ -917,7 +593,7 @@ Actor *lair_func_80387560(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) u32 i; for (i = 0; i != 10; i++) - modelRender_setAppendageVisibility(i + 1, actor->actorTypeSpecificField + 1 == i + 2); + func_8033A45C(i + 1, actor->actorTypeSpecificField + 1 == i + 2); return actor_drawFullDepth(marker, gfx, mtx, vtx); } @@ -929,25 +605,20 @@ void func_803875F0(Actor * this) if (!this->volatile_initialized) { - // [port] Anchor: a teammate's press delivers map flag 0 and FILEPROG_1E in the same - // packet drain, so check the switch flag first -- while we're here to watch, the rise - // animation should win over the already-open catch-up despawn. + if (fileProgressFlag_get(FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN)) + { + marker_despawn(this->marker); + return; + } + if (mapSpecificFlags_get(0)) { this->unk1C_y = this->position_y; - // A remote press shouldn't steal our camera. - if (!port_mapFlag_wasSetRemotely(0)) { - gcStaticCamera_activate(0x2A); - } + gcStaticCamera_activate(0x2A); fileProgressFlag_set(FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN, true); this->volatile_initialized = true; this->unk38_31 = 0x0C; } - else if (fileProgressFlag_get(FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN)) - { - marker_despawn(this->marker); - return; - } } else { @@ -987,7 +658,6 @@ void func_80387730(Actor *this) { s32 phi_s4; s32 sp6C[3]; f32 sp60[3]; - s32 forceOpen; func_802D3D74(this); if (!this->volatile_initialized) { @@ -1014,18 +684,15 @@ void func_80387730(Actor *this) { this->unk1C[1] = 0.0f; this->unk1C[2] = 3.5f; } - // Anchor: unk1C[0] set by port_notedoor_remoteOpen = a teammate opened this door. - forceOpen = (this->unk1C[0] != 0.0f); - if (forceOpen || - (!fileProgressFlag_get(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN) && ability_isUnlocked(ABILITY_13_1ST_NOTEDOOR))) { + if (!fileProgressFlag_get(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN) && ability_isUnlocked(ABILITY_13_1ST_NOTEDOOR)) { player_getPosition(spAC); - if (!forceOpen && (ml_vec3f_distance(spAC, this->position) < 500.0f) && (gcdialog_getCurrentTextId() != 0xF64)) { + if ((ml_vec3f_distance(spAC, this->position) < 500.0f) && (gcdialog_getCurrentTextId() != 0xF64)) { code_73640_printItemCount(0xC); } doorIdx = this->actorTypeSpecificField - 1; noteThreshold = port_getRomhackNoteDoor(doorIdx); if (noteThreshold < 0) { noteThreshold = D_8039347C[doorIdx]; } - if (forceOpen || itemscore_noteScores_getTotal() >= noteThreshold) { + if (itemscore_noteScores_getTotal() >= noteThreshold) { if (this->marker->unk14_21) { func_8032BC60(this, 5, sp90); func_8032BC60(this, 6, sp84); @@ -1038,13 +705,11 @@ void func_80387730(Actor *this) { phi_f20 = 290.0f; } sp9C[1] = this->position[1]; - if (forceOpen || (ml_vec3f_distance(spAC, sp9C) < phi_f20) || (this->alpha_124_19 != 0xFF)) { + if ((ml_vec3f_distance(spAC, sp9C) < phi_f20) || (this->alpha_124_19 != 0xFF)) { if (this->alpha_124_19 == 0xFF) { func_80324CFC(0.0f, COMUSIC_43_ENTER_LEVEL_GLITTER, 32700); func_80324D2C(2.4f, COMUSIC_43_ENTER_LEVEL_GLITTER); - if (!forceOpen) { - func_8028F918(2); - } + func_8028F918(2); } if (this->alpha_124_19 < 7U) { this->alpha_124_19 = 0; @@ -1052,14 +717,10 @@ void func_80387730(Actor *this) { this->alpha_124_19 -= 7; } if (this->alpha_124_19 == 0) { - if (!forceOpen) { - fileProgressFlag_set(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN, true); - } + fileProgressFlag_set(this->actorTypeSpecificField + FILEPROG_39_CCW_OPEN, true); marker_despawn(this->marker); - if (!forceOpen) { - func_8028F918(0); - func_8028F66C(BS_INTR_35); - } + func_8028F918(0); + func_8028F66C(BS_INTR_35); return; } if (this->marker->unk14_21) { @@ -1086,89 +747,9 @@ void func_80387730(Actor *this) { } } } else if ((this->actorTypeSpecificField >= 2) && (ml_vec3f_distance(spAC, this->position) < 290.0f)) { - progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES); - } - } -} - -// A live actor by id (and actorTypeSpecificField when >= 0), or NULL. -static Actor *__lair_findActor(s32 actorId, s32 typeField) { - s32 i; - - if (suBaddieActorArray == NULL) { - return NULL; - } - for (i = 0; i < suBaddieActorArray->cnt; i++) { - Actor *actor = &suBaddieActorArray->data[i]; - if (actor->marker != NULL && actor->modelCacheIndex == actorId && - (typeField < 0 || actor->actorTypeSpecificField == typeField)) { - return actor; + volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES); } } - return NULL; -} - -// [port] Anchor: one-shot cues for a teammate's file-progress flag. -void port_progressFlag_remoteCue(s32 progressFlag) { - Actor *actor; - - port_notedoor_remoteOpen(progressFlag); - port_leveldoor_remoteOpen(progressFlag); - port_breakable_remoteBreak(progressFlag); - - switch (progressFlag) { - // Circular grate over the BGS puzzle: rise + slam (func_803875F0). - case FILEPROG_1E_LAIR_GRATE_TO_BGS_PUZZLE_OPEN: - actor = __lair_findActor(ACTOR_213_GL_BGS_PUZZLE_GRATE, -1); - if (actor != NULL && !actor->volatile_initialized) { - actor->unk1C_y = actor->position_y; - actor->volatile_initialized = TRUE; - actor->unk38_31 = 0x0C; - } - break; - - // CC lobby pipes: rise + slam (func_80388FC8 / lair_func_80389204). - case FILEPROG_1F_CC_LOBBY_PIPE_1_RAISED: - case FILEPROG_20_CC_LOBBY_PIPE_2_RAISED: - case FILEPROG_21_CC_LOBBY_PIPE_3_RAISED: { - s32 pipeId = (progressFlag == FILEPROG_1F_CC_LOBBY_PIPE_1_RAISED) - ? ACTOR_215_GL_CC_ENTRANCE_LONG_PIPE_GREEN - : (progressFlag == FILEPROG_20_CC_LOBBY_PIPE_2_RAISED) - ? ACTOR_216_GL_CC_ENTRANCE_LONG_PIPE_BLUE - : ACTOR_218_GL_CC_ENTRANCE_SHORT_PIPE; - actor = __lair_findActor(pipeId, -1); - // initialized = rise base captured; lifetime_value != 0 = already raised. - if (actor != NULL && actor->initialized && actor->lifetime_value == 0.0f && - !actor->volatile_initialized) { - actor->volatile_initialized = TRUE; - actor->unk38_31 = 12; - } - break; - } - - // Grunty statue hat - case FILEPROG_A1_STATUE_HAT_OPEN: - actor = __lair_findActor(ACTOR_21B_GRUNTY_STATUE_BREAKABLE_HAT_TOP, -1); - if (actor != NULL && actor->volatile_initialized && actor->unk1C[0] == 0.0f) { - actor->unk1C[0] = 1.0f; - } - break; - - default: - break; - } -} - -void port_notedoor_remoteOpen(s32 progressFlag) { - Actor *actor; - - if (progressFlag < FILEPROG_3A_NOTE_DOOR_50_OPEN || progressFlag > FILEPROG_45_NOTE_DOOR_882_OPEN) { - return; - } - actor = __lair_findActor(ACTOR_203_NOTE_DOOR, progressFlag - FILEPROG_39_CCW_OPEN); - if (actor != NULL) { - actor->unk1C[0] = 1.0f; // picked up by func_80387730 next update - } } @@ -1206,11 +787,8 @@ Actor *func_80387DA8(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) * Hides all note door graphics that don't match this note door's index * e.g. for the 50 note door, hides 180, 260, etc. */ - // [port] Romhack gate: a listener may blank this door's baked number (the digits - // are a fixed mesh, so an overridden threshold would show the wrong one). - bool showNumber = EventSystem_Should(VB_NOTEDOOR_DRAW_NUMBER, true, actor->noteDoorIdx); for (i = 0; i != NUM_NOTE_DOORS; i++) - modelRender_setAppendageVisibility(i + 1, showNumber && (actor->noteDoorIdx + 1 == i + 2)); + func_8033A45C(i + 1, actor->noteDoorIdx + 1 == i + 2); /** * Draw the note door @@ -1372,10 +950,7 @@ void func_803882B0(Actor *this) this->lifetime_value = 0; } - // Anchor: also honor persistent FILEPROG_47; VOLATILE_FLAG_BB is transient. - if (this->pitch == 90.f - || !(volatileFlag_get(VOLATILE_FLAG_BB_WITCH_SWITCH_PRESSED_FP) - || fileProgressFlag_get(FILEPROG_47_FP_WITCH_SWITCH_JIGGY_PRESSED))) + if (this->pitch == 90.f || !volatileFlag_get(VOLATILE_FLAG_BB_WITCH_SWITCH_PRESSED_FP)) return; if (this->pitch == 0) @@ -1405,46 +980,12 @@ void func_80388404(enum file_progress_e progress_flag, enum sfx_e sfx, f32 a2, s fileProgressFlag_set(progress_flag, true); } -static s32 sRemoteOpenDoorActor = 0; - -static enum file_progress_e __leveldoor_persistentFlag(s32 actorId) { - switch (actorId) { - case ACTOR_20E_MM_ENTRANCE_DOOR: return FILEPROG_31_MM_OPEN; - case ACTOR_211_TTC_ENTRANCE_CHEST_LID: return FILEPROG_32_TTC_OPEN; - case ACTOR_212_CC_ENTRANCE_BARS: return FILEPROG_33_CC_OPEN; - case ACTOR_210_BGS_ENTRANCE_DOOR: return FILEPROG_34_BGS_OPEN; - case ACTOR_235_FP_ENTRANCE_DOOR_LEFT: return FILEPROG_35_FP_OPEN; - case ACTOR_226_GV_ENTRANCE: return FILEPROG_36_GV_OPEN; - case ACTOR_228_MMM_ENTRANCE_DOOR: return FILEPROG_37_MMM_OPEN; - case ACTOR_20F_RBB_ENTRANCE_DOOR: return FILEPROG_38_RBB_OPEN; - case ACTOR_234_CCW_ENTRANCE_DOOR: return FILEPROG_39_CCW_OPEN; - case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE: return FILEPROG_E2_DOOR_OF_GRUNTY_OPEN; - default: return 0; - } -} - -void port_leveldoor_remoteOpen(s32 progressFlag) { - switch (progressFlag) { - case 0x28: sRemoteOpenDoorActor = ACTOR_20E_MM_ENTRANCE_DOOR; break; - case 0x29: sRemoteOpenDoorActor = ACTOR_211_TTC_ENTRANCE_CHEST_LID; break; - case 0x2A: sRemoteOpenDoorActor = ACTOR_212_CC_ENTRANCE_BARS; break; - case 0x2B: sRemoteOpenDoorActor = ACTOR_210_BGS_ENTRANCE_DOOR; break; - case 0x2C: sRemoteOpenDoorActor = ACTOR_235_FP_ENTRANCE_DOOR_LEFT; break; - case 0x2D: sRemoteOpenDoorActor = ACTOR_226_GV_ENTRANCE; break; - case 0x2E: sRemoteOpenDoorActor = ACTOR_228_MMM_ENTRANCE_DOOR; break; - case 0x2F: sRemoteOpenDoorActor = ACTOR_20F_RBB_ENTRANCE_DOOR; break; - case 0x30: sRemoteOpenDoorActor = ACTOR_234_CCW_ENTRANCE_DOOR; break; - case 0xE2: sRemoteOpenDoorActor = ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE; break; - default: break; - } -} - void func_80388450(Actor *actor1, Actor *actor2) { f32 vec1[3]; f32 vec2[3]; void *actor3 = nodeprop_findByActorIdAndActorPosition(0x22A, actor1); - s32 val = nodeProp_getYaw(actor3); + s32 val = nodeprop_getYaw(actor3); actor2->yaw = val; actor1->yaw = val; @@ -1468,29 +1009,18 @@ void func_80388524(Actor *this) { ParticleEmitter *sp2C; Actor *sp28; - sp34 = func_802D677C(-1) + sp34 = func_802D677C(-1) && (func_802D677C(-1) == gsworld_getMap()) && (func_802D67AC(-1) >= 8) && (func_802D67AC(-1) < 0x12) && (func_802D67DC(-1) == this->modelCacheIndex) ; - if (!sp34 && this->modelCacheIndex == sRemoteOpenDoorActor) { - bool alreadyOpen = EventSystem_Should(VB_LEVELDOOR_REMOTE_OPEN_DONE, - fileProgressFlag_get(__leveldoor_persistentFlag(this->modelCacheIndex)) != 0, - this->modelCacheIndex, this->state); - if (alreadyOpen) { - sRemoteOpenDoorActor = 0; - } else { - sp34 = true; - } - } - func_802D3D74(this); if (!this->initialized) { if (!sp34) { switch(this->modelCacheIndex){ - case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE://L80388630 + case ACTOR_2E5_DOOR_OF_GRUNTY://L80388630 if (!fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) && jigsawPicture_isJigsawPictureComplete(0xA)) { fileProgressFlag_set(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN, true); } @@ -1556,7 +1086,7 @@ void func_80388524(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; switch(this->modelCacheIndex){ - case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE: //L80388880 + case ACTOR_2E5_DOOR_OF_GRUNTY: //L80388880 if (fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) && (this->state == 0x19)) { subaddie_set_state_with_direction(this, 0x1B, 0.999f, 1); } @@ -1796,8 +1326,7 @@ void func_80388FC8(Actor *this) if (mapSpecificFlags_get(1)) { - // [port] Anchor: a remote press shouldn't steal our camera. - if (this->modelCacheIndex == 0x215 && !port_mapFlag_wasSetRemotely(1)) + if (this->modelCacheIndex == 0x215) { gcStaticCamera_activate(0x2B); if (1); // oof @@ -1834,7 +1363,7 @@ void func_80388FC8(Actor *this) if (this->modelCacheIndex == 0x215) { func_802D48B8(this); - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); } this->lifetime_value = 1.f; @@ -1874,10 +1403,7 @@ void lair_func_80389204(Actor *this) if (mapSpecificFlags_get(2)) { - // [port] Anchor: a remote press shouldn't steal our camera. - if (!port_mapFlag_wasSetRemotely(2)) { - gcStaticCamera_activate(0x2C); - } + gcStaticCamera_activate(0x2C); fileProgressFlag_set(FILEPROG_21_CC_LOBBY_PIPE_3_RAISED, true); this->volatile_initialized = true; @@ -1903,7 +1429,7 @@ void lair_func_80389204(Actor *this) this->position_y = this->unk1C[1]; func_802D48B8(this); - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); this->lifetime_value = 1.f; } @@ -2282,16 +1808,7 @@ void func_80389FA8(Actor *this, enum file_progress_e flag) { if (!this->initialized) { - chMMMBreakableWooden_update(this); - - if (fileProgressFlag_get(flag)) - marker_despawn(this->marker); - } - - // Anchor: re-check on scene-return restore (see chFloorCobweb_update). - if (!this->volatile_initialized) - { - this->volatile_initialized = true; + func_802D3D54(this); if (fileProgressFlag_get(flag)) marker_despawn(this->marker); diff --git a/src/LAIR/bss_pad.c b/src/LAIR/bss_pad.c new file mode 100644 index 000000000..f0c8cfff4 --- /dev/null +++ b/src/LAIR/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +static char pad_lair_80395350[0x10]; //padding diff --git a/src/lair/ch/brentilda.c b/src/LAIR/ch/brentilda.c similarity index 95% rename from src/lair/ch/brentilda.c rename to src/LAIR/ch/brentilda.c index e5398be76..57e78e5c4 100644 --- a/src/lair/ch/brentilda.c +++ b/src/LAIR/ch/brentilda.c @@ -19,13 +19,13 @@ ActorAnimationInfo chBrentildaAnimations[] ={ ActorInfo chBrentilda = { 0x1E0, 0x348, 0x539, 0x1, chBrentildaAnimations, chBrentilda_update, actor_update_func_80326224, actor_draw, 2000, 0, 2.0f, 0}; /* .code */ -s32 func_8038BA30(ActorMarker *marker, enum asset_e text_id, s32 arg2){ +void func_8038BA30(ActorMarker *marker, enum asset_e text_id, s32 arg2){ Actor *this; s32 phi_v1; this = marker_getActor(marker); phi_v1 = this->unk10_12*2; - return volatileFlag_getN(VOLATILE_FLAG_20_BEGIN_CHARACTER_PARADE + this->actorTypeSpecificField*6 + phi_v1, 2); + volatileFlag_getN(VOLATILE_FLAG_20_BEGIN_CHARACTER_PARADE + this->actorTypeSpecificField*6 + phi_v1, 2); } void healDuoToFull(ActorMarker *marker, enum asset_e text_id, s32 arg2){ @@ -40,8 +40,7 @@ void func_8038BADC(ActorMarker *marker, enum asset_e text_id, s32 arg2) { Actor *this; this = marker_getActor(marker); - if (text_id == ((ActorLocal_lair_5640 *)&this->local)->unk0 + 2 - && EventSystem_Should(VB_BRENTILDA_HEAL_DIALOG, true)) { + if (text_id == ((ActorLocal_lair_5640 *)&this->local)->unk0 + 2) { if (!fileProgressFlag_get(this->actorTypeSpecificField - 1 + FILEPROG_E9_HEALED_BY_BRENTILDA_1)) { if (item_getCount(ITEM_14_HEALTH) < item_getCount(ITEM_15_HEALTH_TOTAL)) { gcdialog_showDialog(ASSET_10A2_DIALOG_BRENTILDA_HEAL, 0xF, this->position, this->marker, func_8038BADC, healDuoToFull); @@ -179,7 +178,7 @@ void chBrentilda_update(Actor *this) { } if( (phi_f2 < 300.0) && (player_movementGroup() == BSGROUP_0_NONE) - && player_isStableWithExtraSteps() + && func_8028F20C() && !gcdialog_hasCurrentTextId()) { if (!fileProgressFlag_get(FILEPROG_96_MET_BRENTILDA)) { gcdialog_showDialog(ASSET_10A1_DIALOG_BRENTILDA_MEET, 0xA, this->position, this->marker, func_8038BADC, NULL); diff --git a/src/lair/ch/cauldron.c b/src/LAIR/ch/cauldron.c similarity index 98% rename from src/lair/ch/cauldron.c rename to src/LAIR/ch/cauldron.c index e2e24e790..18ff35ec1 100644 --- a/src/lair/ch/cauldron.c +++ b/src/LAIR/ch/cauldron.c @@ -166,7 +166,7 @@ void func_8038AB90(Actor *this, s32 arg1, s32 arg2, enum sfx_e sfx_id, f32 sfx_t if (arg2 == 2) { coMusicPlayer_playMusicWeak(COMUSIC_3F_MAGIC_CARPET_RISING, 32000); func_80324D2C(2.6f, COMUSIC_3F_MAGIC_CARPET_RISING); - gcsfx_play(SFX_7C_CHEBOOF); + gcsfx_playAtSampleRate(SFX_7C_CHEBOOF); } } } @@ -351,7 +351,7 @@ void chWarpCauldron_update(Actor *this) { case 5: //L8038B48C func_8038A96C(this, 3); if (actor_animationIsAt(this, 0.01f)) { - gcsfx_play(SFX_7C_CHEBOOF); + gcsfx_playAtSampleRate(SFX_7C_CHEBOOF); } if (actor_animationIsAt(this, 0.63f)) { volatileFlag_set(VOLATILE_FLAG_1E, 0); @@ -435,8 +435,8 @@ Actor *chWarpCauldron_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) this = marker_getActor(marker); if(this->modelCacheIndex == ACTOR_23B_WARP_CAULDRON) { - modelRender_setAppendageVisibility(3, BOOL(this->unk38_0)); - modelRender_setAppendageVisibility(4, this->unk38_0 ? false : true); + func_8033A45C(3, BOOL(this->unk38_0)); + func_8033A45C(4, this->unk38_0 ? false : true); } this = actor_draw(marker, gfx, mtx, vtx); if (marker->unk14_21 && this->unk38_0 && (getGameMode() != GAME_MODE_4_PAUSED)) { diff --git a/src/lair/ch/cheato.c b/src/LAIR/ch/cheato.c similarity index 96% rename from src/lair/ch/cheato.c rename to src/LAIR/ch/cheato.c index 0b5388c37..bff79a50a 100644 --- a/src/lair/ch/cheato.c +++ b/src/LAIR/ch/cheato.c @@ -1,4 +1,4 @@ -// BanjoDecomp: lair/ch/cheato.c +// BanjoDecomp: code_9C40.c #include #include "functions.h" #include "variables.h" @@ -17,8 +17,8 @@ ActorInfo D_803948B8 = { 0x16F, 0x1D7, 0x54F, 0x1, D_80394860, func_803902B8, ac /* .code */ Actor *func_80390030(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility(3, 1); - modelRender_setAppendageVisibility(4, 1); + func_8033A45C(3, 1); + func_8033A45C(4, 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -94,7 +94,7 @@ void func_803902B8(Actor *this) { this->has_met_before = volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE); this->initialized = true; } - playerPosition_get(sp5C); + _player_getPosition(sp5C); sp58 = ml_vec3f_within_distance(this->position, sp5C, 1750.0f) && !this->has_met_before; if (sp58 && !this->unk38_0) { func_8032BB88(this, 0, 0x1F4); diff --git a/src/lair/fall_damagedetect.c b/src/LAIR/ch/fall_damagedetect.c similarity index 100% rename from src/lair/fall_damagedetect.c rename to src/LAIR/ch/fall_damagedetect.c diff --git a/src/lair/ff_lava_fireball.c b/src/LAIR/ch/ff_lava_fireball.c similarity index 100% rename from src/lair/ff_lava_fireball.c rename to src/LAIR/ch/ff_lava_fireball.c diff --git a/src/lair/ff_lava_fireball_actor.c b/src/LAIR/ch/ff_lava_fireball_actor.c similarity index 100% rename from src/lair/ff_lava_fireball_actor.c rename to src/LAIR/ch/ff_lava_fireball_actor.c diff --git a/src/lair/ch/gruntling.c b/src/LAIR/ch/gruntling.c similarity index 99% rename from src/lair/ch/gruntling.c rename to src/LAIR/ch/gruntling.c index ce3125ac1..353e13e31 100644 --- a/src/lair/ch/gruntling.c +++ b/src/LAIR/ch/gruntling.c @@ -1,4 +1,4 @@ -// BanjoDecomp: lair/ch/gruntling.c +// BanjoDecomp: code_A4A0.c #include #include "functions.h" #include "variables.h" diff --git a/src/lair/ch/lairgruntilda.c b/src/LAIR/ch/grunty_final.c similarity index 95% rename from src/lair/ch/lairgruntilda.c rename to src/LAIR/ch/grunty_final.c index f635457c9..4aad4aaa2 100644 --- a/src/lair/ch/lairgruntilda.c +++ b/src/LAIR/ch/grunty_final.c @@ -1,4 +1,4 @@ -// BanjoDecomp: lair/ch/lairgruntilda.c +// BanjoDecomp: code_C1C0.c #include #include "functions.h" #include "variables.h" @@ -21,9 +21,9 @@ ActorInfo D_80394CF0 = { 0x29B, 0x3C5, 0x53D, 0x1, D_80394CC0, func_80392700, fu /* .code */ Actor *func_803925B0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility(3, 0); - modelRender_setAppendageVisibility(4, 0); - modelRender_setAppendageVisibility(5, 0); + func_8033A45C(3, 0); + func_8033A45C(4, 0); + func_8033A45C(5, 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/lair/ch/refillpillow.c b/src/LAIR/ch/item_pillows.c similarity index 94% rename from src/lair/ch/refillpillow.c rename to src/LAIR/ch/item_pillows.c index e9b9f5d35..df541c8e5 100644 --- a/src/lair/ch/refillpillow.c +++ b/src/LAIR/ch/item_pillows.c @@ -1,4 +1,4 @@ -// BanjoDecomp: lair/ch/refillpillow.c +// BanjoDecomp: code_A170.c #include #include "functions.h" #include "variables.h" @@ -26,8 +26,8 @@ ActorInfo D_80394958 = { 0x172, 0x1DA, 0x549, 0x1, D_80394900, func_803906A0, ac /* .code */ Actor *func_80390560(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility(3, marker->collidable); - modelRender_setAppendageVisibility(4, marker->collidable); + func_8033A45C(3, marker->collidable); + func_8033A45C(4, marker->collidable); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/lair/ch/furnacefunprizes.c b/src/LAIR/ch/minigame_ffprize.c similarity index 97% rename from src/lair/ch/furnacefunprizes.c rename to src/LAIR/ch/minigame_ffprize.c index 66a69b41e..dde3d4b26 100644 --- a/src/lair/ch/furnacefunprizes.c +++ b/src/LAIR/ch/minigame_ffprize.c @@ -1,4 +1,4 @@ -// BanjoDecomp: lair/ch/furnacefunprizes.c +// BanjoDecomp: code_BBD0.c #include #include "functions.h" #include "variables.h" @@ -43,8 +43,8 @@ ActorInfo D_80394C94 = { MARKER_29A_FF_PRIZE, ACTOR_3C8_FF_PRIZE_TOOTY, ASSET_35 /* .code */ Actor *func_80391FC0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility(4, 1); - modelRender_setAppendageVisibility(5, 1); + func_8033A45C(4, 1); + func_8033A45C(5, 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/lair/tooty_parade.c b/src/LAIR/ch/tooty_parade.c similarity index 100% rename from src/lair/tooty_parade.c rename to src/LAIR/ch/tooty_parade.c diff --git a/src/lair/ff_manager.c b/src/LAIR/ff_manager.c similarity index 97% rename from src/lair/ff_manager.c rename to src/LAIR/ff_manager.c index fb12c5fd2..4f93e4c56 100644 --- a/src/lair/ff_manager.c +++ b/src/LAIR/ff_manager.c @@ -5,8 +5,9 @@ #include "model.h" #include "core2/gc/zoombox.h" +#include "core2/quiz_storage.h" #include "core2/nc/camera.h" -#include "core2/quiz/storage.h" + #define ARRLEN(x) ((s32)(sizeof(x) / sizeof(x[0]))) @@ -946,17 +947,17 @@ void ff_setState(enum FF_Action next_state) { if (((s32) ffStorage->currentBoardTile->tileType >= 7) && (quizQuestionAskedBitfield_get(func_8038D60C(ffStorage->currentTileId)) == 0)) { item_adjustByDiffWithHud(ITEM_27_JOKER_CARD, ffStorage->currentBoardTile->tileType - 6); quizQuestionAskedBitfield_set(func_8038D60C(ffStorage->currentTileId), true); - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A8_FF_GOT_JOKER); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A8_FF_GOT_JOKER); } if (ffStorage->currentTileId != 0x1EF) { gcsfx_playWithPitch(SFX_126_AUDIENCE_BOOING, 1.0f, 0x7FF8); if (ffStorage->currentBoardTile->tileType == FFTT_5_GRUNTY) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT); } if (volatileFlag_get(VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT)) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT); } - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT); } } else { if (ffStorage->currentBoardTile->tileType == FFTT_6_SKULL) { @@ -983,9 +984,9 @@ void ff_setState(enum FF_Action next_state) { lair_func_8038C640(ffStorage->currentTileId, ffStorage->currentBoardTile); } if (volatileFlag_get(VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG)) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG); } - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG); } break; @@ -1136,8 +1137,8 @@ void func_8038E070(void) void lair_func_8038E0B0(void) { s32 sp48[6]; //buttons s32 temp_v0; - s32 sp3C[3]; //side buttons (Z, L, R) - s32 ff_tile_type; + s32 sp3C[2]; //joystick + s32 sp38; s32 sp28; if( (gsworld_getMap() == MAP_8E_GL_FURNACE_FUN) @@ -1159,12 +1160,11 @@ void lair_func_8038E0B0(void) { ffStorage->currentTileId = temp_v0; ffStorage->currentBoardTile = ff_getCurrentBoardTile(ffStorage->currentTileId); } - // If you see FFTT_8_JOKER in the table, use FFTT_7_JOKER instead - ff_tile_type = MIN((ffStorage->currentTileId != 0) ? ffStorage->currentBoardTile->tileType : -1, FFTT_7_JOKER); - if ((ffStorage->currentTileId != 0) && (ffStorage->currentBoardTile->unk9 == 0) && player_isStableWithExtraSteps()) { + sp38 = MIN((ffStorage->currentTileId != 0) ? ffStorage->currentBoardTile->tileType : -1, FFTT_7_JOKER); + if ((ffStorage->currentTileId != 0) && (ffStorage->currentBoardTile->unk9 == 0) && func_8028F20C()) { ffStorage->currentBoardTile->unk9 = 2; if (ffStorage->unk11) { - switch(ff_tile_type){ + switch(sp38){ case FFTT_6_SKULL://L8038E26C comusic_playTrack(COMUSIC_7B_STEP_ON_SKULL_TILE); break; @@ -1220,23 +1220,23 @@ void lair_func_8038E0B0(void) { } code_73640_printItemCount(0x14); code_73640_printItemCount(0x16); - if (ff_tile_type != FFTT_0_NIL) { - sp28 = ff_tile_type - 1 + FILEPROG_55_FF_BK_SQUARE_INSTRUCTIONS; - if (!fileProgressFlag_get(sp28) && gcdialog_showDialog(ff_tile_type + 0x101E, 0, NULL, NULL, NULL, NULL)) { + if (sp38 != FFTT_0_NIL) { + sp28 = sp38 - 1 + FILEPROG_55_FF_BK_SQUARE_INSTRUCTIONS; + if (!fileProgressFlag_get(sp28) && gcdialog_showDialog(sp38 + 0x101E, 0, NULL, NULL, NULL, NULL)) { fileProgressFlag_set(sp28, true); } s32 ffLifeThreshold = 1; CALL_EVENT(OnFurnaceFunDialog, &ffLifeThreshold); - if ((ff_tile_type == FFTT_6_SKULL) && (item_getCount(ITEM_16_LIFE) == ffLifeThreshold)) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL); + if ((sp38 == FFTT_6_SKULL) && (item_getCount(ITEM_16_LIFE) == ffLifeThreshold)) { + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL); } else if (item_getCount(ITEM_14_HEALTH) == 1) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_AA_FF_LOW_HEALTH); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_AA_FF_LOW_HEALTH); } if ((ffStorage->currentBoardTile->unk9 == 2) && (player_movementGroup() == BSGROUP_0_NONE)) { if (func_8028EFEC() && (sp48[FACE_BUTTON(BUTTON_A)] == 1)) { func_803114D0(); player_getRotation(ffStorage->playerRotation); - ffStorage->ffQuestionType = ff_getQuestionType(ff_tile_type); + ffStorage->ffQuestionType = ff_getQuestionType(sp38); ff_prepareNextQuestion(ffStorage->ffQuestionType); ff_setState(3); return; @@ -1246,7 +1246,7 @@ void lair_func_8038E0B0(void) { lair_func_8038C640(ffStorage->currentTileId, ffStorage->currentBoardTile); item_dec(ITEM_27_JOKER_CARD); func_8030E6D4(SFX_3EA_BANJO_GUH_HUH); - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A9_FF_USED_JOKER); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A9_FF_USED_JOKER); if (ffStorage->currentTileId == 0x1EF) { ff_setState(8); } diff --git a/src/lair/jigsawpicture.c b/src/LAIR/jigsawpicture.c similarity index 79% rename from src/lair/jigsawpicture.c rename to src/LAIR/jigsawpicture.c index 12bc1aeae..da648a147 100644 --- a/src/lair/jigsawpicture.c +++ b/src/LAIR/jigsawpicture.c @@ -2,10 +2,7 @@ #include #include "functions.h" #include "variables.h" -#include "jigsawpicture.h" #include "port/Romhack/RomhackConfig.h" -#include "port/Network/Anchor/JigsawPedestal.h" -#include "port/Enhancements/Events/Hooks/Events.h" extern void player_walkToPosition(f32[3], f32, void(*)(ActorMarker *), ActorMarker *); extern void func_80324CFC(f32, enum comusic_e, s32); extern void rand_seed(s32); @@ -26,13 +23,10 @@ typedef struct { void jigsawPicture_setState(Actor *this, s32 next_state); void updateJigsawPictureActor(Actor *this); -Actor *jigsawPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); - -static s32 sBuzzedPedestalField = 0; /* .data */ -ActorInfo JIGSAW_PICTURE_ACTOR = { 0x1EB, 0x3B7, 0x48B, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, jigsawPicture_draw, 0, 0, 0.0f, 0}; -ActorInfo JIGSAW_PICTURE_ACTOR_2 = { 0x1EB, 0x3BC, 0x538, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, jigsawPicture_draw, 0, 0, 0.0f, 0}; +ActorInfo JIGSAW_PICTURE_ACTOR = { 0x1EB, 0x3B7, 0x48B, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo JIGSAW_PICTURE_ACTOR_2 = { 0x1EB, 0x3BC, 0x538, 0x1, NULL, updateJigsawPictureActor, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; Struct_lair_86F0_0 D_803947F8[0xb] ={ { 1, 0x1, FILEPROG_5D_MM_PUZZLE_PIECES_PLACED}, { 2, 0x2, FILEPROG_5E_TTC_PUZZLE_PIECES_PLACED}, @@ -61,19 +55,9 @@ s32 _puzzleCost(s32 index) { return (override >= 0) ? override : D_803947F8[index].cost; } -s32 _puzzleSize(s32 index) { - s32 override = port_getRomhackJiggyPuzzleSize(index); - return (override >= 0) ? override : D_803947F8[index].size_bits; -} - -s32 _puzzleFlag(s32 index) { - s32 override = port_getRomhackJiggyPuzzleFlag(index); - return (override >= 0) ? override : D_803947F8[index].progress_flag; -} - bool jigsawPicture_isJigsawPictureComplete(s32 arg0) { s32 cost = _puzzleCost(arg0 - 1); - return fileProgressFlag_getN(_puzzleFlag(arg0 - 1), _puzzleSize(arg0 - 1)) == cost; + return fileProgressFlag_getN(D_803947F8[arg0 -1].progress_flag, D_803947F8[arg0 -1].size_bits) == cost; } s32 getPictureCost(Actor *this){ @@ -129,7 +113,7 @@ void onJigsawPodiumCollide(ActorMarker *marker, ActorMarker *other_marker){ } bool isBanjoOnPodium(ActorMarker *marker) { - return player_isStableWithExtraSteps() && func_8028FB48(0x08000000) && marker->isBanjoOnTop; + return func_8028F20C() && func_8028FB48(0x08000000) && marker->isBanjoOnTop; } s32 isPicturePiecePlaced(Actor *this, s32 arg1){ @@ -318,7 +302,6 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ vec3fArray_get_vec3f(func_803097A0(), getUnknownJigsawPictureIndex(this), sp50); switch (next_state) { case 1: //L8038F3BC - port_jigsawPedestal_release(this->actorTypeSpecificField); func_8028F918(0); break; @@ -349,7 +332,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ addOrRemovePieceFromDisplay(this, temp_s1, 0); local->unk4--; local->unk0 &= ~(1 << temp_s1); - fileProgressFlag_setN(_puzzleFlag(this->actorTypeSpecificField - 1), local->unk4, _puzzleSize(this->actorTypeSpecificField - 1)); + fileProgressFlag_setN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, local->unk4, D_803947F8[this->actorTypeSpecificField - 1].size_bits); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, 1); } break; @@ -362,7 +345,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ temp_s1 = getPicturePiecePosition(this); addOrRemovePieceFromDisplay(this, temp_s1, 1); local->unk0 |= (1 << temp_s1); - fileProgressFlag_setN(_puzzleFlag(this->actorTypeSpecificField - 1), local->unk4, _puzzleSize(this->actorTypeSpecificField - 1)); + fileProgressFlag_setN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, local->unk4, D_803947F8[this->actorTypeSpecificField - 1].size_bits); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, -1); unlockAdditionalActions(this); } @@ -385,7 +368,7 @@ void jigsawPicture_setState(Actor *this, s32 next_state){ local->unk0 |= (1 << temp_s1); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, -1); } - fileProgressFlag_setN(_puzzleFlag(this->actorTypeSpecificField - 1), local->unk4, _puzzleSize(this->actorTypeSpecificField - 1)); + fileProgressFlag_setN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, local->unk4, D_803947F8[this->actorTypeSpecificField - 1].size_bits); unlockAdditionalActions(this); } break; @@ -431,44 +414,6 @@ void addPieces(Actor *this, s32 arg1) { fileProgressFlag_set(FILEPROG_DE_USED_ALL_YOUR_PUZZLE_PIECES, 1); } -// [port] unk38_31 marks a podium that is spawned but not yet revealed by its switch (see boggy3). -Actor *jigsawPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { - Actor *this = marker_getActor(marker); - - if (this->unk38_31) return this; - - return actor_draw(marker, gfx, mtx, vtx); -} - -static void revealCcwPuzzlePodium(Actor *this) { - this->unk38_31 = false; - this->marker->propPtr->unk8_3 = true; - if (!fileProgressFlag_get(FILEPROG_54_CCW_PUZZLE_PODIUM_ACTIVE)) { - __bundle_spawnFromFirstActor(BUNDLE_20__UNKNOWN, this); - func_80324CFC(0.0f, COMUSIC_43_ENTER_LEVEL_GLITTER, 0x7FFF); - func_80324D2C(2.1f, COMUSIC_43_ENTER_LEVEL_GLITTER); - func_8030E6D4(SFX_113_PAD_APPEARS); - } -} - -static s32 jigsawPicture_placedFromFlags(Actor *this) { - return fileProgressFlag_getN(_puzzleFlag(this->actorTypeSpecificField - 1), _puzzleSize(this->actorTypeSpecificField - 1)); -} - -static void jigsawPicture_resyncFromFlags(Actor *this) { - ActorLocal_lair_86F0 *local = (ActorLocal_lair_86F0*)&this->local; - s32 placed = jigsawPicture_placedFromFlags(this); - s32 i; - - local->unk0 = 0; - local->unk4 = 0; - for(i = 0; i < placed; i++){ - local->unk4++; - local->unk0 |= (1 << getPicturePiecePosition(this)); - } - setInitialJigsawPictureOpacity(this); -} - void updateJigsawPictureActor(Actor *this) { ActorLocal_lair_86F0 *local; s32 sp7C[6]; //buttons @@ -487,7 +432,7 @@ void updateJigsawPictureActor(Actor *this) { if (!this->volatile_initialized) { // temp_v0 = &D_803947F8[this->actorTypeSpecificField - 1]; - sp64 = fileProgressFlag_getN(_puzzleFlag(this->actorTypeSpecificField - 1), _puzzleSize(this->actorTypeSpecificField - 1)); + sp64 = fileProgressFlag_getN(D_803947F8[this->actorTypeSpecificField - 1].progress_flag, D_803947F8[this->actorTypeSpecificField - 1].size_bits); local->unk0 = 0; local->unk4 = 0; local->unk8 = (isBanjoOnPodium(this->marker)) ? 0xff : 1; @@ -503,26 +448,16 @@ void updateJigsawPictureActor(Actor *this) { if (this->actorTypeSpecificField == 9) { this->unk1C[0] = 8.0f; if (!fileProgressFlag_get(FILEPROG_53_CCW_PUZZLE_PODIUM_SWITCH_PRESSED)) { - // [port] Anchor suppresses the despawn: a despawned podium only comes back when the - // cube re-streams, which would strand a teammate standing here when the flag arrives. - if (EventSystem_Should(VB_CCW_PODIUM_DESPAWN, true, this)) { - marker_despawn(this->marker); - } else { - this->unk38_31 = true; - this->marker->propPtr->unk8_3 = false; - } + marker_despawn(this->marker); return; } - revealCcwPuzzlePodium(this); - } - } - - // [port] Waiting on the switch: reveal in place the moment the flag lands, ours or a teammate's. - if (this->unk38_31) { - if (!fileProgressFlag_get(FILEPROG_53_CCW_PUZZLE_PODIUM_SWITCH_PRESSED)) { - return; + if (!fileProgressFlag_get(FILEPROG_54_CCW_PUZZLE_PODIUM_ACTIVE)) { + __bundle_spawnFromFirstActor(BUNDLE_20__UNKNOWN, this); + func_80324CFC(0.0f, COMUSIC_43_ENTER_LEVEL_GLITTER, 0x7FFF); + func_80324D2C(2.1f, COMUSIC_43_ENTER_LEVEL_GLITTER); + func_8030E6D4(SFX_113_PAD_APPEARS); + } } - revealCcwPuzzlePodium(this); } if ((this->actorTypeSpecificField == 9) && !fileProgressFlag_get(FILEPROG_54_CCW_PUZZLE_PODIUM_ACTIVE)) { @@ -551,18 +486,10 @@ void updateJigsawPictureActor(Actor *this) { controller_copyFaceButtons(0, sp7C); controller_copySideButtons(0, sp6C); func_8038EDBC(this); - if (local->unk4 != jigsawPicture_placedFromFlags(this) && EventSystem_Should(VB_JIGSAW_PICTURE_RESYNC, false, this)) { - jigsawPicture_resyncFromFlags(this); - } - if (this->state != JIGSAW_PICTURE_LEAVE_PODIUM && !port_jigsawPedestal_isSelf(this->actorTypeSpecificField)) { - jigsawPicture_setState(this, JIGSAW_PICTURE_LEAVE_PODIUM); - return; - } - - switch (this->state) { - case JIGSAW_PICTURE_LEAVE_PODIUM: - if (!this->has_met_before && (!player_isStableWithExtraSteps() || !func_8028FB48(0x08000000))) { - this->has_met_before = TRUE; + switch(this->state){ + case 1://L8038FCD0 + if (!this->has_met_before && (!func_8028F20C() || !func_8028FB48(0x08000000))) { + this->has_met_before = true; } if (subaddie_playerIsWithinSphereAndActive(this, 300)) { if ((this->actorTypeSpecificField == 0xA) && !fileProgressFlag_get(FILEPROG_F6_SEEN_DOOR_OF_GRUNTY_PUZZLE_PODIUM)) { @@ -575,19 +502,11 @@ void updateJigsawPictureActor(Actor *this) { } } if (isBanjoOnPodium(this->marker) && this->has_met_before && !isPictureComplete(this) && (player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT)) { - if (port_jigsawPedestal_tryClaim(this->actorTypeSpecificField)) { - jigsawPicture_setState(this, 2); - } else if (sBuzzedPedestalField != this->actorTypeSpecificField) { - comusic_playTrack(COMUSIC_2C_BUZZER); - sBuzzedPedestalField = this->actorTypeSpecificField; - } - } else if (sBuzzedPedestalField == this->actorTypeSpecificField) { - sBuzzedPedestalField = 0; + jigsawPicture_setState(this, 2); } break; case 4: //L8038FE28 - { CALL_EVENT(OnJigsawPodiumInput, this->actorTypeSpecificField); } if ((gcdialog_getCurrentTextId() != 0xF7C) && (gcdialog_getCurrentTextId() != 0xF7D)) { if (sp7C[FACE_BUTTON(BUTTON_A)] == 1) { addPieces(this, 5); diff --git a/src/MM/mmspawnqueue.c b/src/MM/actor_spawninit.c similarity index 97% rename from src/MM/mmspawnqueue.c rename to src/MM/actor_spawninit.c index 2642fae14..e348cf674 100644 --- a/src/MM/mmspawnqueue.c +++ b/src/MM/actor_spawninit.c @@ -1,4 +1,4 @@ -// BanjoDecomp: MM/mmspawnqueue.c +// BanjoDecomp: code_24C0.c /*!!!DONE!!!*/ #include #include "functions.h" diff --git a/src/MM/ch/chimpystump.c b/src/MM/ch/chimpystump.c index 951a3a6a9..da6df06c0 100644 --- a/src/MM/ch/chimpystump.c +++ b/src/MM/ch/chimpystump.c @@ -33,12 +33,8 @@ void __chchimpystump_updateShaking(Actor *this) { if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_4_SHAKE)) { if (this->unk10_12 == 0) { this->unk10_12 = 1; - // [port] Vanilla replays Chimpy's walk-off, and with it this rise, on every entry to MM - // once his jiggy has spawned. Both halves are muted for those replays. - if (EventSystem_Should(VB_MM_CHIMPY_STUMP_RUMBLE, true)) { - func_802BB3DC(1, 3.0f, 1.0f); - core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.2f); - } + func_802BB3DC(1, 3.0f, 1.0f); + core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.2f); }//L80386D0C this->position_x = ((globalTimer_getTime() & 1) * 2) ^ (s32) this->position_x; @@ -51,11 +47,7 @@ void chchimpystump_update(Actor *this) { actor_collisionOff(this); this->initialized = true; this->actor_specific_1_f = this->position_y; - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_0_CHIMPY_STUMP_RAISED)) { - subaddie_set_state(this, CHIMPY_STUMP_STATE_3_RAISED); - } else { - this->position_y -= 134.0f; - } + this->position_y -= 134.0f; this->marker->propPtr->unk8_3 = 1; } diff --git a/src/MM/ch/conga.c b/src/MM/ch/conga.c index e3d799e09..fc6098492 100644 --- a/src/MM/ch/conga.c +++ b/src/MM/ch/conga.c @@ -1,13 +1,10 @@ -// BanjoDecomp: MM/ch/conga.c -#include -#include "rand.h" +// BanjoDecomp: conga.c #include "functions.h" +#include "rand.h" #include "variables.h" +#include +#include #include - -#include "bk_math.h" // [port] SQ macro -#include "conga.h" - #ifndef MIN #define MIN(s,t) ((s)<(t)?(s):(t)) #endif @@ -25,14 +22,14 @@ void MM_checkMMChecksums(void); void chConga_update(Actor *); -typedef struct chconga_s { +typedef struct chconga_s{ TUPLE(s32, orangeSpawnPosition); s32 unkC; s32 unk10; u8 pad14[0x4]; s32 unk18; s32 unk1C; -} ActorLocal_Conga; +}ActorLocal_Conga; /* .data */ @@ -61,26 +58,26 @@ bool __chConga_isPlayerNearCongaTree(Actor * this){ f32 unused_tmpz; if (gsworld_getMap() != MAP_2_MM_MUMBOS_MOUNTAIN) { - return FALSE; + return false; } if (!this->unk10_12) { - return FALSE; + return false; } player_getPosition(plyr_pos); if (plyr_pos[1] < 300.0f || 600.0f < plyr_pos[1]) { - return FALSE; + return false; } unused_tmpz = plyr_pos[2] - 5029.0f; if (52900.0f < (plyr_pos[0] - -5011.0f) * (plyr_pos[0] - -5011.0f) + (plyr_pos[2] - 5029.0f) * (plyr_pos[2] - 5029.0f)) { - return FALSE; + return false; } - return TRUE; + return true; } void func_80386FB0(Actor *this){ @@ -130,7 +127,7 @@ void func_80387168(ActorMarker *marker, ActorMarker *other_marker){ actorPtr->unk38_31++; actorPtr->unk10_12 = MIN(actorPtr->unk38_31, 0xA); - if( actorPtr->unk38_31 == 3 + if( actorPtr->unk38_31 == 3 && !jiggyscore_isCollected(JIGGY_A_MM_CONGA) ){ subaddie_set_state_with_direction(actorPtr, 8, 0 ,1); @@ -144,7 +141,7 @@ void func_80387168(ActorMarker *marker, ActorMarker *other_marker){ ){ func_8038708C(actorPtr, 2); if(actorPtr->unk38_31 == 1){ - gcdialog_showDialog(VER_SELECT(ASSET_B39_DIALOG_CONGA_HIT_BY_EGG, 0x957, 0, 0), 4, actorPtr->position, 0, 0, 0); + gcdialog_showDialog(ASSET_B39_DIALOG_CONGA_HIT_BY_EGG, 4, actorPtr->position, 0, 0, 0); } } } @@ -154,10 +151,10 @@ void func_80387168(ActorMarker *marker, ActorMarker *other_marker){ int func_803872EC(void){ s32 text_id = gcdialog_getCurrentTextId(); - return text_id == VER_SELECT(ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE, 0x955, 0, 0) - || text_id == VER_SELECT(ASSET_B38_DIALOG_CONGA_DEFEAT, 0x956, 0, 0) + return text_id == ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE + || text_id == ASSET_B38_DIALOG_CONGA_DEFEAT || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - || text_id == VER_SELECT(ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY, 0x959, 0, 0) + || text_id == ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY || text_id == ASSET_B45_DIALOG_JIGGY_COLLECT_10 || text_id == ASSET_B51_DIALOG_BOTTLES_HOW_TO_EXIT_LEVEL; } @@ -213,192 +210,169 @@ void __chConga_sendOrangeProjectile(ActorMarker *congaMarker){ } } -void chConga_update(Actor *this) { - +void chConga_update(Actor *this){ f32 unused; NodeProp *node_prop; s32 sp3C; - this->marker->propPtr->unk8_3 = timedFuncQueue_is_empty() ? 1 : 0; // [port] def takes no args - - if (!this->initialized) { + this->marker->propPtr->unk8_3 = (timedFuncQueue_is_empty())?1:0; + if(!this->initialized){ ((ActorLocal_Conga *)&this->local)->unkC = 1; this->unk16C_0 = 1; - this->initialized = TRUE; + this->initialized = true; this->velocity_x = 0.0f; this->actor_specific_1_f = 0.0f; node_prop = nodeprop_findByActorIdAndActorPosition(0x150, this); ((ActorLocal_Conga *)&this->local)->unk1C = nodeprop_getRadius(node_prop); nodeprop_getPosition_s32(node_prop, &((ActorLocal_Conga *)&this->local)->unk10); } - - if (0.0f == this->actor_specific_1_f) { + if(0.0f == this->actor_specific_1_f){ this->actor_specific_1_f = (actorArray_findActorFromMarkerId(MARKER_36_ORANGE_COLLECTIBLE) != NULL)? 2.0f: 1.0f; } - - if (0.0f != this->velocity_x) { + if(0.0f != this->velocity_x){ this->velocity_x -= 1.0f; if(0.0f == this->velocity_x){ - __spawnQueue_add_1((GenFunction_1)func_80387100, reinterpret_cast(uintptr_t, this->marker)); + __spawnQueue_add_1((GenFunction_1)func_80387100, (uintptr_t)this->marker); } } - marker_setCollisionScripts(this->marker, NULL, NULL, func_80387168); - - if (!subaddie_playerIsWithinSphereAndActive(this, 2100) + if( !subaddie_playerIsWithinSphereAndActive(this, 2100) && this->state != 2 - && this->state != 8) { - + && this->state != 8 + ){ if(this->state > 3 && this->state < 8){ actor_loopAnimation(this); subaddie_set_state_with_direction(this, 1, 0.76f, 1); } - return; } sp3C = subaddie_playerIsWithinSphereAndActive(this, 1000); - - if (func_8032A9E4(((ActorLocal_Conga *)&this->local)->unk10, ((ActorLocal_Conga *)&this->local)->unk18, ((ActorLocal_Conga *)&this->local)->unk1C) + if( func_8032A9E4(((ActorLocal_Conga *)&this->local)->unk10, ((ActorLocal_Conga *)&this->local)->unk18, ((ActorLocal_Conga *)&this->local)->unk1C) && !this->unk138_23 - && gcdialog_showDialog(VER_SELECT(ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE, 0x955, 0, 0), 0, 0, 0, 0, 0)) { + && gcdialog_showDialog(ASSET_B37_DIALOG_CONGA_SAFE_UP_HERE, 0, 0, 0, 0, 0) + ){ this->unk138_23 = 1; - mapSpecificFlags_set(MM_SPECIFIC_FLAG_A_UNKNOWN, TRUE); + mapSpecificFlags_set(MM_SPECIFIC_FLAG_A_UNKNOWN, true); }//L803878F8 - if (sp3C && !this->has_met_before) { - if (gcdialog_showDialog((player_getTransformation()== TRANSFORM_2_TERMITE) ? ASSET_B3E_DIALOG_CONGA_MEET_AS_TERMITE : VER_SELECT(ASSET_B3C_DIALOG_CONGA_MEET, 0x95A, 0, 0), 0, this->position, 0,0,0)) { - this->has_met_before = TRUE; + if( sp3C && !this->has_met_before){ + if(gcdialog_showDialog((player_getTransformation()== TRANSFORM_2_TERMITE) ? ASSET_B3E_DIALOG_CONGA_MEET_AS_TERMITE : ASSET_B3C_DIALOG_CONGA_MEET, 0, this->position, 0,0,0)){ + this->has_met_before = true; } } //L80387968 - switch (this->state) { - case CONGA_STATE_IDLE://80387990 + switch(this->state){ + case 1://80387990 actor_loopAnimation(this); func_80386FB0(this); __chConga_playRandomNoise(); - if(actor_animationIsAt(this, 0.0f) || actor_animationIsAt(this, 0.45f)){ if(randf() < 0.2){ anctrl_setDirection(this->anctrl, anctrl_isPlayedForwards(this->anctrl)?0:1); }; }//L80387A18 - - if (actor_animationIsAt(this, 0.66f)) { - subaddie_maybe_set_state_position_direction(this, CONGA_STATE_BEAT_CHEST_STOP, 0, 1, 0.38f); + if(actor_animationIsAt(this, 0.66f)){ + subaddie_maybe_set_state_position_direction(this, 6, 0, 1, 0.38f); } - - if (sp3C + if( sp3C && player_movementGroup() != BSGROUP_1_INTR && !__chConga_isPlayerNearCongaTree(this) && timedFuncQueue_is_empty() && !func_8032A9E4(((ActorLocal_Conga *)&this->local)->unk10, ((ActorLocal_Conga *)&this->local)->unk18, ((ActorLocal_Conga *)&this->local)->unk1C) - && !func_803872EC()) { - - subaddie_set_state_with_direction(this, CONGA_STATE_TARGET_GROUND, 0.0f, 1); + && !func_803872EC() + ){ + subaddie_set_state_with_direction(this, 4, 0.0f, 1); }//L80387AC0 - - if (player_movementGroup() != BSGROUP_1_INTR + if( player_movementGroup() != BSGROUP_1_INTR && __chConga_isPlayerNearCongaTree(this) && this->unk38_31 != 0 - && !func_803872EC()) { - - subaddie_set_state_with_direction(this, CONGA_STATE_TARGET_BANJO, 0.0f, 1); + && !func_803872EC() + ){ + subaddie_set_state_with_direction(this, 7, 0.0f, 1); } break; - case CONGA_STATE_BEAT_CHEST_STOP: //L80387B24 + case 6: //L80387B24 ((ActorLocal_Conga *)&this->local)->unkC = 1; actor_playAnimationOnce(this); __chConga_playRandomNoise(); - - if (anctrl_isPlayedForwards(this->anctrl) == TRUE - && actor_animationIsAt(this, 0.0f)) { - - subaddie_set_state_with_direction(this, CONGA_STATE_BEAT_CHEST, 0.0f, 1); - } else if (!anctrl_isPlayedForwards(this->anctrl) - && actor_animationIsAt(this, 0.001f)) { - subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.76f, 1); + if( anctrl_isPlayedForwards(this->anctrl) == true + && actor_animationIsAt(this, 0.0f) + ){ + subaddie_set_state_with_direction(this, 5, 0.0f, 1); + } + else if( !anctrl_isPlayedForwards(this->anctrl) + && actor_animationIsAt(this, 0.001f) + ){ + subaddie_set_state_with_direction(this, 1, 0.76f, 1); } - break; - case CONGA_STATE_BEAT_CHEST: //L80387BC0 + case 5: //L80387BC0 ((ActorLocal_Conga *)&this->local)->unkC = 1; actor_loopAnimation(this); __chConga_playRandomNoise(); - - if (actor_animationIsAt(this, 0.99f)) { - subaddie_maybe_set_state_position_direction(this, CONGA_STATE_BEAT_CHEST_STOP, 0.999f, 0, sp3C ? 1.0 : 0.4); + if( actor_animationIsAt(this, 0.99f)){ + subaddie_maybe_set_state_position_direction(this, 6, 0.999f, 0, sp3C ? 1.0 : 0.4); }//L80387C30 - - if (actor_animationIsAt(this, 0.9f) - || actor_animationIsAt(this, 0.4f)) { + if( actor_animationIsAt(this, 0.9f) + || actor_animationIsAt(this, 0.4f) + ){ func_8030E6D4(SFX_3FB_UNKNOWN); } - break; - case CONGA_STATE_TARGET_GROUND: //L80387C74 - if (actor_animationIsAt(this, 0.6f)) { + case 4: //L80387C74 + if(actor_animationIsAt(this, 0.6f)){ func_8030E58C(SFX_2_CLAW_SWIPE, 0.7f); } - func_80386FB0(this); - - if (!sp3C + if( !sp3C || player_is_in_jiggy_jig() || __chConga_isPlayerNearCongaTree(this) || !timedFuncQueue_is_empty() - || func_803872EC()) { - - subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.0f, 1); + || func_803872EC() + ){ + subaddie_set_state_with_direction(this, 1, 0.0f, 1); } - break; - case CONGA_STATE_HIT: //L80387D0C + case 2: //L80387D0C actor_playAnimationOnce(this); - if (actor_animationIsAt(this, 0.99f)) { - subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.0f, 1); + if(actor_animationIsAt(this, 0.99f)){ + subaddie_set_state_with_direction(this, 1, 0.0f, 1); } - break; - case CONGA_STATE_ROAR: //L80387D4C + case 8: //L80387D4C actor_playAnimationOnce(this); - - if (actor_animationIsAt(this, 0.99f)) { - subaddie_set_state_with_direction(this, CONGA_STATE_MOPEY, 0.0f, 1); - gcdialog_showDialog(VER_SELECT(ASSET_B38_DIALOG_CONGA_DEFEAT, 0x956, 0, 0), 0xe, this->position, this->marker, func_80387370, NULL); + if(actor_animationIsAt(this, 0.99f)){ + subaddie_set_state_with_direction(this, 3, 0.0f, 1); + gcdialog_showDialog(ASSET_B38_DIALOG_CONGA_DEFEAT, 0xe, this->position, this->marker, func_80387370, NULL); } - break; - case CONGA_STATE_MOPEY: //L80387DB8 + case 3: //L80387DB8 actor_loopAnimation(this); - - if (jiggyscore_isCollected(JIGGY_A_MM_CONGA)) { - subaddie_set_state_with_direction(this, CONGA_STATE_IDLE, 0.0f, 1); + if(jiggyscore_isCollected(JIGGY_A_MM_CONGA)){ + subaddie_set_state_with_direction(this, 1, 0.0f, 1); } - break; - case CONGA_STATE_TARGET_BANJO: //L80387DF0 - if (this->unk10_12 == 0) { - if (actor_animationIsAt(this, 0.97f)) { + case 7: //L80387DF0 + if(this->unk10_12 == 0){ + if(actor_animationIsAt(this, 0.97f)){ ((ActorLocal_Conga *)&this->local)->unkC = 1; - subaddie_set_state_with_direction(this, CONGA_STATE_BEAT_CHEST_STOP, 0.0f, 1); + subaddie_set_state_with_direction(this, 6, 0.0f, 1); } } - break; }//L80387E38 - - if ((this->state == CONGA_STATE_TARGET_GROUND && actor_animationIsAt(this, 0.56f)) - || (this->state == CONGA_STATE_TARGET_BANJO && actor_animationIsAt(this, 0.468f))) { - - vec3fArray_get_vec3i(this->marker->unk44, 5, (s32 *)&this->local); // [port] writes 3 s32 into actor local - __spawnQueue_add_1((GenFunction_1)__chConga_sendOrangeProjectile, reinterpret_cast(uintptr_t, this->marker)); //spawn orange + if( (this->state == 4 && actor_animationIsAt(this, 0.56f)) + || (this->state == 7 && actor_animationIsAt(this, 0.468f)) + ){ + vec3fArray_get_vec3i(this->marker->unk44, 5, (s32 *)this->local); + __spawnQueue_add_1((GenFunction_1)__chConga_sendOrangeProjectile, (uintptr_t)this->marker); //spawn orange } } diff --git a/src/MM/ch/conga.h b/src/MM/ch/conga.h deleted file mode 100644 index ede0eeddb..000000000 --- a/src/MM/ch/conga.h +++ /dev/null @@ -1,11 +0,0 @@ -// BanjoDecomp: MM/ch/conga.h -enum conga_state_s { - CONGA_STATE_IDLE = 1, - CONGA_STATE_HIT = 2, - CONGA_STATE_MOPEY = 3, // After defeat, waiting for Banjo to collect the jiggy - CONGA_STATE_TARGET_GROUND = 4, - CONGA_STATE_BEAT_CHEST = 5, - CONGA_STATE_BEAT_CHEST_STOP = 6, // Though depending on the animation, he'll go back to beating his chest - CONGA_STATE_TARGET_BANJO = 7, // Targeting Banjo when he's at eye level - CONGA_STATE_ROAR = 8 // When Conga is defeated -}; diff --git a/src/MM/ch/hut.c b/src/MM/ch/hut.c index f4925d563..1a2ad24d5 100644 --- a/src/MM/ch/hut.c +++ b/src/MM/ch/hut.c @@ -8,8 +8,6 @@ #include -#include "port/Patches/Patches.h" - /* extern function declarations */ void bundle_setYaw(f32); @@ -42,7 +40,7 @@ Actor *chhut_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 is_intact_or_destroyed = actorPtr->state == HUT_STATE_0_INTACT || actorPtr->state == HUT_STATE_2_DESTROYED; this->propPtr->unk8_3 = is_intact_or_destroyed; - modelRender_setAppendageVisibility(1, is_not_destroyed); + func_8033A45C(1, is_not_destroyed); return actor_draw(this, gfx, mtx, vtx); } @@ -54,43 +52,18 @@ void __chhut_spawnExplosion(ActorMarker *this) { if (this); } -static enum bundle_e mm_hut_bundles[6] = { - BUNDLE_0_MM_HUT_MUSIC_NOTE, - BUNDLE_1_MM_HUT_BLUE_EGG, - BUNDLE_2_MM_HUT_GRUBLIN, - BUNDLE_3_MM_HUT_JINJO_GREEN, - BUNDLE_6_MM_HUT_EXTRA_LIFE, - BUNDLE_4_MM_HUT_JIGGY -}; - -static void chhut_dropRecordedBundle(Actor *this, s32 loot, s32 fullBundle) { - f32 pos[3]; - if (loot < 0 || loot >= 5) { - return; // jiggy / out of range - } - if (!fullBundle && (loot == 0 || loot == 3)) { - return; // note / jinjo: skip on reload - } - pos[0] = this->position_x; - pos[1] = this->position_y + 125.0f; - pos[2] = this->position_z; - __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, mm_hut_bundles[loot], *(s32 *)(&pos[0]), *(s32 *)(&pos[1]), *(s32 *)(&pos[2])); -} - -static void chhut_replaySmash(Actor *this, s32 loot) { - sfxsource_playHighPriority(SFX_5B_HEAVY_STUFF_FALLING); - subaddie_set_state(this, HUT_STATE_1_DAMAGED); - actor_playAnimationOnce(this); - __spawnQueue_add_1((GenFunction_1) __chhut_spawnExplosion, (uintptr_t)this->marker); - bundle_setYaw(this->yaw); - chhut_dropRecordedBundle(this, loot, 1); -} - void chhut_update(Actor *this) { + static enum bundle_e D_803898D8[6] = { + BUNDLE_0_MM_HUT_MUSIC_NOTE, + BUNDLE_1_MM_HUT_BLUE_EGG, + BUNDLE_2_MM_HUT_GRUBLIN, + BUNDLE_3_MM_HUT_JINJO_GREEN, + BUNDLE_6_MM_HUT_EXTRA_LIFE, + BUNDLE_4_MM_HUT_JIGGY + }; + f32 diff_pos[3]; f32 plyr_pos[3]; - s32 loot; - s32 smashIndex; if (gsworld_getUnk0() != 2) { return; @@ -99,13 +72,6 @@ void chhut_update(Actor *this) { if (!this->initialized) { this->marker->collidable = false; this->initialized = true; - loot = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); - if (loot >= 0) { - chhut_dropRecordedBundle(this, loot, 0); - subaddie_set_state(this, HUT_STATE_2_DESTROYED); - this->position_y -= 160.0f; - return; - } } switch (this->state) { @@ -117,7 +83,7 @@ void chhut_update(Actor *this) { if (150.0f < diff_pos[1] && player_getActiveHitbox(this->marker) == HITBOX_1_BEAK_BUSTER - && player_isStableWithExtraSteps() + && func_8028F20C() && LENGTH_VEC3F(diff_pos) < 350.0f ){ diff_pos[0] = this->position_x; @@ -131,21 +97,14 @@ void chhut_update(Actor *this) { __spawnQueue_add_1((GenFunction_1) __chhut_spawnExplosion, (uintptr_t)this->marker); bundle_setYaw(this->yaw); - smashIndex = port_hutSmash_countForCurrentLevel(); - if (smashIndex < 5) { - __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, mm_hut_bundles[smashIndex], *(s32 * )(&diff_pos[0]), *(s32 * )(&diff_pos[1]), *(s32 * )(&diff_pos[2])); + if (mm_hut_smash_count < 5) { + __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, D_803898D8[mm_hut_smash_count], *(s32 * )(&diff_pos[0]), *(s32 * )(&diff_pos[1]), *(s32 * )(&diff_pos[2])); } else { jiggy_spawn(JIGGY_5_MM_HUTS, diff_pos); } - port_hutSmash_record((s32)this->position_x, (s32)this->position_y, (s32)this->position_z, smashIndex); - } - else { - loot = port_hutSmash_get((s32)this->position_x, (s32)this->position_y, (s32)this->position_z); - if (loot >= 0) { - chhut_replaySmash(this, loot); - } + mm_hut_smash_count = (mm_hut_smash_count + 1) % 6; } break; diff --git a/src/MM/ch/juju.c b/src/MM/ch/juju.c index 0dda2dd3c..992c8553f 100644 --- a/src/MM/ch/juju.c +++ b/src/MM/ch/juju.c @@ -20,6 +20,7 @@ void chjuju_update(Actor *this); Actor *chjuju_draw(ActorMarker *, Gfx **, Mtx **, Vtx **); /* .bss */ +u8 MM_pad_80389C80[0x10]; s32 mm_juju_count; /* .data */ @@ -209,7 +210,7 @@ void chjuju_update(Actor *this) { switch (jujuPtr->animation_state) { case JUJU_ANIMATION_STATE_1_YAWING: //L80389624 previous_yaw = this->yaw; - this->yaw += ((11 - mm_juju_count * 2) * time_getDelta() * (float)FRAMERATE) / 2; + this->yaw += ((11 - mm_juju_count * 2) * time_getDelta() * 60.0f) / 2; if (360.0f < this->yaw) { has_completed_full_turn = true; diff --git a/src/MM/ch/jujuhitbox.c b/src/MM/ch/jujuhitbox.c index 8fb9b5c0d..54fb88cc6 100644 --- a/src/MM/ch/jujuhitbox.c +++ b/src/MM/ch/jujuhitbox.c @@ -4,18 +4,11 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - /* extern functions */ void __chjujuhitbox_initialize_all(ActorMarker *, s32); s32 subaddie_getYawToPlayer(Actor *); void func_80353580(ActorMarker *); -static s32 mm_juju_sharedKnocked(void) { - s32 bits = port_puzzleStep_get(ANCHOR_PUZZLE_MM_JUJU) & 0xF; - return (bits & 1) + ((bits >> 1) & 1) + ((bits >> 2) & 1) + ((bits >> 3) & 1); -} - typedef struct juju_hitbox_s { u8 pad0[0x4]; s32 unk4; @@ -82,7 +75,6 @@ void func_80388BEC(NodeProp *node, ActorMarker *marker) { if (func_80388B30(temp_v0, 90.0f)) { closest_actor->state = 1; ((ActorLocal_JujuHitbox *) &closest_actor->local)->unk4++; - port_puzzleStep_orBits(ANCHOR_PUZZLE_MM_JUJU, (1 << ((ActorLocal_JujuHitbox *) &closest_actor->local)->unk4) - 1); func_803892A8(((ActorLocal_JujuHitbox *) &closest_actor->local)->jujus); func_80353580(marker); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, 0x58, *(s32 *)&position[0], *(s32 *)&position[1], *(s32 *)&position[2]); @@ -141,12 +133,7 @@ void chjujuhitbox_update(Actor *this) { if (!this->volatile_initialized) { this->volatile_initialized = true; - jujuCtlPtr->unk4 = mm_juju_sharedKnocked(); - if (jujuCtlPtr->unk4 >= 4) { - marker_despawn(this->marker); - return; - } - __spawnQueue_add_2((GenFunction_2) __chjujuhitbox_initialize_all, (uintptr_t)this->marker, jujuCtlPtr->unk4); + __spawnQueue_add_2((void (*)(void)) __chjujuhitbox_initialize_all, (uintptr_t)this->marker, jujuCtlPtr->unk4); __chjujuhitbox_playRubbingSfx(this); return; } @@ -174,12 +161,6 @@ void chjujuhitbox_update(Actor *this) { __chjuju_updateCount(jujuCtlPtr->jujus); } - if (this->state == 3 && jujuCtlPtr->unk4 < mm_juju_sharedKnocked()) { - this->state = 1; - jujuCtlPtr->unk4++; - func_803892A8(jujuCtlPtr->jujus); - } - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_9_JUJU_HAS_HALF_TURNED)) { __chjujuhitbox_playRubbingSfx(this); mapSpecificFlags_set(MM_SPECIFIC_FLAG_9_JUJU_HAS_HALF_TURNED, false); diff --git a/src/MM/ch/lmonkey.c b/src/MM/ch/lmonkey.c index 90f57159d..a44f276df 100644 --- a/src/MM/ch/lmonkey.c +++ b/src/MM/ch/lmonkey.c @@ -44,7 +44,7 @@ void __chlmonkey_updateBringOrange(Actor **this_ptr) { player_setCarryObjectPoseInHorizontalRadius((*this_ptr)->position, 800.0f, ACTOR_29_ORANGE_COLLECTIBLE, this_ptr); if (subaddie_playerIsWithinSphereAndActive(*this_ptr, 345) && - bacarry_getMarkerId() == MARKER_36_ORANGE_COLLECTIBLE && + bacarry_get_markerId() == MARKER_36_ORANGE_COLLECTIBLE && player_throwCarriedObject()) { func_8028FA34(0xc6, *this_ptr); @@ -98,22 +98,20 @@ void chlmonkey_update(Actor *this) { func_80343DEC(this); } else {//L80388630 - if (subaddie_playerIsWithinSphereAndActive(this, 700) && !gcdialog_hasCurrentTextId() && - EventSystem_Should(VB_MM_CHIMPY_NOISE, true)) { + if (subaddie_playerIsWithinSphereAndActive(this, 700) && !gcdialog_hasCurrentTextId()) { __chlmonkey_playRandomNoise(this); }//L8038865C switch (this->state) { case LMONKEY_STATE_1_IDLE://L80388690 - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED) || jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY)) { + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED)) { subaddie_set_state(this, LMONKEY_STATE_4_LEAVING); - if (jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY)) { - mapSpecificFlags_set(MM_SPECIFIC_FLAG_4_SHAKE, true); - subaddie_set_state(this, LMONKEY_STATE_3_WALKING); + if (!jiggyscore_isCollected(JIGGY_9_MM_CHIMPY)) { + gcdialog_showDialog(ASSET_B40_DIALOG_CHIMPY_COMPLETE, 0xE, this->position, this->marker, __chlmonkey_complete, NULL); } else {//L803886E8 - gcdialog_showDialog(ASSET_B40_DIALOG_CHIMPY_COMPLETE, 0xE, this->position, this->marker, __chlmonkey_complete, NULL); + __chlmonkey_complete(this->marker, ASSET_B40_DIALOG_CHIMPY_COMPLETE, -1); }//L80388898 } else { diff --git a/src/MM/ch/orange.c b/src/MM/ch/orange.c index 3260f8b81..b5ff73df1 100644 --- a/src/MM/ch/orange.c +++ b/src/MM/ch/orange.c @@ -31,7 +31,7 @@ f32 D_80389A00[3] = {0.0f, 0.0f, 0.0f}; void __chorange_collisionCallback(ActorMarker *marker, ActorMarker *other_marker) { if (!player_isDead() && !mapSpecificFlags_get(MM_SPECIFIC_FLAG_8_HIT_WITH_ORANGE) && - gcdialog_showDialog(VER_SELECT(ASSET_B3A_DIALOG_CONGA_HITS_PLAYER, 0x958, 0, 0), 0, 0, 0, NULL, NULL)) { + gcdialog_showDialog(ASSET_B3A_DIALOG_CONGA_HITS_PLAYER, 0, 0, 0, NULL, NULL)) { mapSpecificFlags_set(MM_SPECIFIC_FLAG_8_HIT_WITH_ORANGE, true); } diff --git a/src/MM/ch/orangepad.c b/src/MM/ch/orangepad.c index e87b5a5b6..cca3856a3 100644 --- a/src/MM/ch/orangepad.c +++ b/src/MM/ch/orangepad.c @@ -1,29 +1,28 @@ -// BanjoDecomp: MM/ch/orangepad.c -#include +// BanjoDecomp: orangepad.c #include "functions.h" #include "variables.h" -#include "bk_math.h" // [port] TUPLE_ASSIGN - -#include "core2/staticcamera.h" +#include -#include "conga.h" -#include "orangepad.h" +#include -extern void port_breakable_recordBreak(s32 markerId, s32 x, s32 y, s32 z); -extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); +/* extern functions */ +void actor_update_func_80326224(Actor *); +extern void particleEmitter_func_802EFA20(ParticleEmitter *, f32, f32); -void chOrangePad_update(Actor *); +/* public functions */ +void chorangepad_update(Actor *); +/* .data */ ActorInfo chOrangePadInfo = { MARKER_66_ORANGE_PAD, ACTOR_57_ORANGE_PAD, ASSET_2EB_MODEL_ORANGE_PAD, 0, NULL, - chOrangePad_update, actor_update_func_80326224, actor_draw, + chorangepad_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -void spawnJiggy(s32 x, s32 y, s32 z) { +/*.code */ +void __chorangepad_spawnJiggy(s32 x, s32 y, s32 z) { f32 pos[3]; - TUPLE_ASSIGN(pos, x, y, z); jiggy_spawn(JIGGY_8_MM_ORANGE_PADS, pos); } @@ -33,115 +32,101 @@ void handleOrangeCollision(ActorMarker *marker) { Actor *closest_orange_pad; f32 position[3]; ParticleEmitter *p_ctrl; - s32 camera_id; + s32 temp_a0; - position[0] = marker->propPtr->x; // [port] ActorProp uses x/y/z members + position[0] = marker->propPtr->x; position[1] = marker->propPtr->y; position[2] = marker->propPtr->z; - closest_orange_pad = actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, ORANGE_PAD_STATE_HIT, &distance_to_orange_pad); - - if (!closest_orange_pad || 500.0f < distance_to_orange_pad) { - return; - } - - closest_orange_pad->state = ORANGE_PAD_STATE_HIT; - port_breakable_recordBreak((s32)closest_orange_pad->marker->id, (s32)closest_orange_pad->position[0], (s32)closest_orange_pad->position[1], (s32)closest_orange_pad->position[2]); - - if (actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, ORANGE_PAD_STATE_HIT, &distance_to_orange_pad)) { - // There are still other pads on the ground, play progress ding - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 22000); - } else { // No more pads, dispense jiggy - camera_id = (closest_orange_pad->secondaryId == ORANGE_PAD_RIGHT) ? MM_ORANGE_PAD_JIGGY_SPAWN_RIGHT - : (closest_orange_pad->secondaryId == ORANGE_PAD_LEFT) ? MM_ORANGE_PAD_JIGGY_SPAWN_LEFT - : MM_ORANGE_PAD_JIGGY_SPAWN_TOP; - - gcStaticCamera_activate(camera_id); + closest_orange_pad = actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, 1, &distance_to_orange_pad); - position[1] += 50.0f; - timedFunc_set_3(0.6f, (GenFunction_3) spawnJiggy, (s32) position[0], (s32) position[1], (s32) position[2]); + if (closest_orange_pad && !(500.0f < distance_to_orange_pad)) { + closest_orange_pad->state = 1; - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - - if (!jiggyscore_isCollected(JIGGY_8_MM_ORANGE_PADS)) { - gcdialog_showDialog(VER_SELECT(ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY, 0x959, 0, 0), 4, NULL, NULL, NULL, NULL); + if (actorArray_findClosestActorFromActorId(position, ACTOR_57_ORANGE_PAD, 1, &distance_to_orange_pad)) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 22000); } + else { + temp_a0 = (closest_orange_pad->secondaryId == 0x106) ? 0x10 + : (closest_orange_pad->secondaryId == 0x76) ? 0xf + : 0xe; + + gcStaticCamera_activate(temp_a0); + position[1] += 50.0f; + timedFunc_set_3(0.6f, (GenFunction_3) __chorangepad_spawnJiggy, (s32) position[0], (s32) position[1], (s32) position[2]); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); + + if (!jiggyscore_isCollected(JIGGY_8_MM_ORANGE_PADS)) { + gcdialog_showDialog(ASSET_B3B_DIALOG_CONGA_ORANGE_PAD_JIGGY, 4, NULL, NULL, NULL, NULL); + } + }// L803865D8 + + // Emmit sparkles + p_ctrl = partEmitMgr_newEmitter(30); + particleEmitter_setPosition(p_ctrl, closest_orange_pad->position); + particleEmitter_setModel(p_ctrl, ASSET_89F_MODEL_ORANGE_PARTICLE); + particleEmitter_setStartingScaleRange(p_ctrl, 0.09f, 0.19f); + particleEmitter_setFinalScaleRange(p_ctrl, 0.0f, 0.0f); + particleEmitter_setParticleVelocityRange(p_ctrl, -200.0f, 500.0f, -200.0f, 200.0f, 700.0f, 200.0f); + particleEmitter_setAccelerationRange(p_ctrl, 0.0f, -1200.0f, 0.0f, 0.0f, -1200.0f, 0.0f); + particleEmitter_setAngularVelocityRange(p_ctrl, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f); + particleEmitter_setSpawnIntervalRange(p_ctrl, 0.0f, 0.01f); + particleEmitter_setParticleLifeTimeRange(p_ctrl, 4.0f, 4.0f); + particleEmitter_func_802EF9F8(p_ctrl, 0.01f); + particleEmitter_func_802EFA18(p_ctrl, 3); + particleEmitter_func_802EFA20(p_ctrl, 1.0f, 1.3f); + particleEmitter_emitN(p_ctrl, 30); } - - // Spawn orange particles - p_ctrl = partEmitMgr_newEmitter(ORANGE_PARTICLE_COUNT); - - particleEmitter_setPosition(p_ctrl, closest_orange_pad->position); - particleEmitter_setModel(p_ctrl, ASSET_89F_MODEL_ORANGE_PARTICLE); - particleEmitter_setStartingScaleRange(p_ctrl, 0.09f, 0.19f); - particleEmitter_setFinalScaleRange(p_ctrl, 0.0f, 0.0f); - particleEmitter_setParticleVelocityRange(p_ctrl, -200.0f, 500.0f, -200.0f, 200.0f, 700.0f, 200.0f); - particleEmitter_setAccelerationRange(p_ctrl, 0.0f, -1200.0f, 0.0f, 0.0f, -1200.0f, 0.0f); - particleEmitter_setAngularVelocityRange(p_ctrl, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f); - particleEmitter_setSpawnIntervalRange(p_ctrl, 0.0f, 0.01f); - particleEmitter_setParticleLifeTimeRange(p_ctrl, 4.0f, 4.0f); - particleEmitter_func_802EF9F8(p_ctrl, 0.01f); - particleEmitter_func_802EFA18(p_ctrl, 3); - particleEmitter_func_802EFA20(p_ctrl, 1.0f, 1.3f); - - particleEmitter_emitN(p_ctrl, ORANGE_PARTICLE_COUNT); } -void chOrangePad_handleOrangeCollision(s32 _, ActorMarker *marker) { - handleOrangeCollision(marker); +void chOrangePad_handleOrangeCollision(NodeProp *arg0, ActorMarker *arg1) { + handleOrangeCollision(arg1); } -void chOrangePad_update(Actor *this) { - Actor *conga; +void chorangepad_update(Actor *this) { + Actor *closest_actor; f32 unused; f32 min_distance; if (!this->initialized) { this->marker->propPtr->unk8_3 = 1; actor_collisionOff(this); - this->initialized = TRUE; - } + this->initialized = true; + }//L803867B0 if (!this->volatile_initialized) { - this->partnerActor = actorArray_findClosestActorFromActorId(this->position, ACTOR_8_CONGA, -1, &min_distance)->marker; - this->volatile_initialized = TRUE; - } - - // Anchor: a teammate already broke this pad — adopt the hit state. - if (this->state != ORANGE_PAD_STATE_HIT - && port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, - (s32)this->position[0], (s32)this->position[1], (s32)this->position[2])) { - this->state = ORANGE_PAD_STATE_HIT; - } + this->partnerActor = actorArray_findClosestActorFromActorId(this->position, 8, -1, &min_distance)->marker; + this->volatile_initialized = true; + }//L803867E0 if (this->partnerActor) { - conga = marker_getActor(this->partnerActor); + closest_actor = marker_getActor(this->partnerActor); } - if (subaddie_playerIsWithinSphereAndActive(this, CONGA_WARN_DISTANCE) - && !player_movementGroup() - && !mapSpecificFlags_get(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS) - && conga->state != CONGA_STATE_MOPEY) { + if (subaddie_playerIsWithinSphereAndActive(this, 0x28) && + !player_movementGroup() && + !mapSpecificFlags_get(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS) && + closest_actor->state != 3) { - if (gcdialog_showDialog(VER_SELECT(ASSET_B3D_DIALOG_CONGA_TOUCH_PAD, 0x95B, 0, 0), 0, NULL, NULL, NULL, NULL)) { - mapSpecificFlags_set(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS, TRUE); + if (gcdialog_showDialog(ASSET_B3D_DIALOG_CONGA_TOUCH_PAD, 0, NULL, NULL, NULL, NULL)) { + mapSpecificFlags_set(MM_SPECIFIC_FLAG_CONGA_WARNED_BLOCKS, true); } } - if (this->state == ORANGE_PAD_STATE_HIT) { + if (this->state == 1) { if (this->lifetime_value < 72.0f) { commonParticle_add(this->marker, 5, func_80329904); commonParticle_new(9, this->marker->unk14_21); } - // Tick up respawn by 7 every update - this->lifetime_value = MIN(ORANGE_PAD_HIT_LIFETIME, this->lifetime_value + ORANGE_PAD_LIFETIME_INCREMENT); + this->lifetime_value = MIN(255.0, this->lifetime_value + 7.0); - if (ORANGE_PAD_HIT_LIFETIME == this->lifetime_value) { + if (255.0 == this->lifetime_value) { marker_despawn(this->marker); } - } else { } // Can't remove the else ;.; + } + else { + }//L80386928 - // If hit, then fade out actor_setOpacity(this, 0xFF - (s32) this->lifetime_value); -} +}//*/ diff --git a/src/MM/ch/orangepad.h b/src/MM/ch/orangepad.h deleted file mode 100644 index 7bf31b536..000000000 --- a/src/MM/ch/orangepad.h +++ /dev/null @@ -1,14 +0,0 @@ -// BanjoDecomp: MM/ch/orangepad.h -#define ORANGE_PARTICLE_COUNT 30 -#define CONGA_WARN_DISTANCE 0x28 -#define ORANGE_PAD_HIT_LIFETIME 255.0 -#define ORANGE_PAD_LIFETIME_INCREMENT 7.0 - -enum orange_pad_state_e { - ORANGE_PAD_STATE_HIT = 1 -}; - -enum orange_pad_ids { - ORANGE_PAD_LEFT = 0x76, - ORANGE_PAD_RIGHT = 0x106 -}; diff --git a/src/MM/checksums.c b/src/MM/checksums.c deleted file mode 100644 index 4a743d96f..000000000 --- a/src/MM/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: MM/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsMM; diff --git a/src/MM/crc.c b/src/MM/crc.c index 585d2b88d..425dffd03 100644 --- a/src/MM/crc.c +++ b/src/MM/crc.c @@ -4,9 +4,11 @@ #include "functions.h" #include "variables.h" -s32 D_803899C0 = VER_SELECT(0x000C740C, 0x000C896A, 0, 0); // MM_TEXT_CRC1 -s32 D_803899C4 = VER_SELECT(0xCD249CB3, 0xED04CB8F, 0, 0); // MM_TEXT_CRC2 -s32 D_803899C8 = VER_SELECT(0x0000D44F, 0x0000D9E8, 0, 0); // MM_DATA_CRC1 +/* .data */ +//TODO Implement CRC calculation in Makefile(?) +u32 D_803899C0 = 0x000C740C; //MM.code CRC1 +u32 D_803899C4 = 0xCD249CB3; //MM.code CRC2 +u32 D_803899C8 = 0x0000D44F; //MM.data CRC1 (with this value = 0) void chmumbo_func_802D1724(void); diff --git a/src/MMM/mmmspawnqueue.c b/src/MMM/actor_spawninit.c similarity index 55% rename from src/MMM/mmmspawnqueue.c rename to src/MMM/actor_spawninit.c index 21ea8bf39..a8944bb97 100644 --- a/src/MMM/mmmspawnqueue.c +++ b/src/MMM/actor_spawninit.c @@ -1,26 +1,24 @@ -// BanjoDecomp: MMM/mmmspawnqueue.c +// BanjoDecomp: code_2040.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "actor.h" -#include "core2/dustemitter.h" - -extern ActorInfo chShackDoor; -extern ActorInfo chMansionDoor; -extern ActorInfo chCellarHatch; -extern ActorInfo chChuchGateLeftLock; -extern ActorInfo chHedgeGateRightLock1; -extern ActorInfo chHedgeGateRightLock2; -extern ActorInfo chChuchDoor; -extern ActorInfo ch1881BarrelTop; -extern ActorInfo chXBarrelTop; -extern ActorInfo chMMMWindow; -extern ActorInfo chMMMWideWindow; -extern ActorInfo chMMMTallWindow; -extern ActorInfo chDiningDoor; -extern ActorInfo chMMMClockSwitch; +extern ActorInfo D_8038BC28; +extern ActorInfo D_8038BCDC; +extern ActorInfo D_8038BC4C; +extern ActorInfo D_8038BDB4; +extern ActorInfo D_8038BDD8; +extern ActorInfo D_8038BDFC; +extern ActorInfo D_8038BC94; +extern ActorInfo D_8038BC70; +extern ActorInfo D_8038BD00; +extern ActorInfo D_8038BD24; +extern ActorInfo D_8038BD48; +extern ActorInfo D_8038BD6C; +extern ActorInfo D_8038BCB8; +extern ActorInfo D_8038BD90; extern ActorInfo chNapper; extern ActorInfo D_8038BA68; extern ActorInfo chMotzhand; @@ -34,20 +32,20 @@ extern ActorInfo chPortraitTeeHee; extern ActorInfo chPortraitMinion; extern ActorInfo D_80367E70; -extern ActorInfo chPurpleTeeHee; +extern ActorInfo D_80372C3C; extern void core1_7090_initSfxSource(s32, s32, s32, f32); extern void func_8025AE0C(s32, f32); extern BKCollisionTriangle *func_80309B48(f32[3], f32[3], f32[3], u32); -void chMMMBreakableWooden_update(Actor *this); -void chMMMGate_update(Actor *this); -Actor *chMMMGate_draw(ActorMarker *marker, Gfx ** gfx, Mtx **mtx, Vtx **vtx); -void chChurchDoor_update(Actor *this); -void chMMMClockSwitch_update(Actor *this); -void chMMMWoodenDoor_update(Actor *this); -void chXBarrelTop_update(Actor *this); -void chMMMWindow_update(Actor *this); +void func_802D3D54(Actor *this); +void func_803888B8(Actor *this); +Actor *func_80388994(ActorMarker *marker, Gfx ** gfx, Mtx **mtx, Vtx **vtx); +void func_80388BDC(Actor *this); +void func_80388FE4(Actor *this); +void func_80389004(Actor *this); +void func_80389060(Actor *this); +void func_803890B8(Actor *this); /* .data */ ActorAnimationInfo D_8038BBE0[] = { @@ -62,101 +60,101 @@ ActorAnimationInfo D_8038BBE0[] = { {0x00, 0.0f} }; -ActorInfo chShackDoor = { - MARKER_9C_SHACK_DOOR, ACTOR_109_SHACK_DOOR, ASSET_3CD_MODEL_SHACK_DOOR, +ActorInfo D_8038BC28 = { + 0x9C, 0x109, 0x3CD, 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chCellarHatch = { - MARKER_9E_CELLAR_HATCH, ACTOR_10B_CELLAR_HATCH, ASSET_3CF_MODEL_CELLAR_HATCH, +ActorInfo D_8038BC4C = { + 0x9E, 0x10B, 0x3CF, 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo ch1881BarrelTop = { - MARKER_9A_1881_BARREL_TOP, ACTOR_CB_1881_BARREL_TOP, ASSET_3CC_MODEL_1881_BARREL_TOP, +ActorInfo D_8038BC70 = { + 0x9A, 0xCB, 0x3CC, 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chChuchDoor = { - MARKER_A2_CHURCH_DOOR, ACTOR_114_CHURCH_DOOR, ASSET_3D3_MODEL_CHURCH_DOOR, +ActorInfo D_8038BC94 = { + 0xA2, 0x114, 0x3D3, 0x1, NULL, - chChurchDoor_update, actor_update_func_80326224, actor_drawFullDepth, + func_80388BDC, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chDiningDoor = { - MARKER_E7_DINING_DOOR, ACTOR_265_DINING_DOOR, ASSET_4DA_MODEL_DINING_DOOR, +ActorInfo D_8038BCB8 = { + 0xE7, 0x265, 0x4DA, 0x1, NULL, - chMMMWoodenDoor_update, actor_update_func_80326224, actor_drawFullDepth, + func_80389004, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chMansionDoor = { - MARKER_9D_MANSION_DOOR, ACTOR_10A_MANSION_DOOR, ASSET_3CE_MODEL_MANSION_DOOR, +ActorInfo D_8038BCDC = { + 0x9D, 0x10A, 0x3CE, 0x1, NULL, - chMMMWoodenDoor_update, actor_update_func_80326224, actor_drawFullDepth, + func_80389004, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chXBarrelTop = { - MARKER_D3_X_BARREL_TOP, ACTOR_191_X_BARREL_TOP, ASSET_50B_MODEL_X_BARREL_TOP, +ActorInfo D_8038BD00 = { + 0xD3, 0x191, 0x50B, 0x1, NULL, - chXBarrelTop_update, actor_update_func_80326224, actor_drawFullDepth, + func_80389060, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chMMMWindow = { - MARKER_123_WINDOW, ACTOR_2E8_WINDOW, ASSET_4C0_MODEL_WINDOW, +ActorInfo D_8038BD24 = { +0x123, 0x2E8, 0x4C0, 0x1, NULL, - chMMMWindow_update, actor_update_func_80326224, actor_drawFullDepth, + func_803890B8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chMMMWideWindow = { - MARKER_1F2_WIDE_WINDOW, ACTOR_2E9_WIDE_WINDOW, ASSET_4C1_MODEL_WIDE_WINDOW, +ActorInfo D_8038BD48 = { +0x1F2, 0x2E9, 0x4C1, 0x1, NULL, - chMMMWindow_update, actor_update_func_80326224, actor_drawFullDepth, + func_803890B8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chMMMTallWindow = { - MARKER_1F3_TALL_WINDOW, ACTOR_2EA_TALL_WINDOW, ASSET_4C2_MODEL_TALL_WINDOW, +ActorInfo D_8038BD6C = { +0x1F3, 0x2EA, 0x4C2, 0x1, NULL, - chMMMWindow_update, actor_update_func_80326224, actor_drawFullDepth, + func_803890B8, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; -ActorInfo chMMMClockSwitch = { - MARKER_FE_MMM_CLOCK_SWITCH, ACTOR_1FD_MMM_CLOCK_SWITCH, ASSET_43D_MODEL_MMM_CLOCK_SWITCH, +ActorInfo D_8038BD90 = { + 0xFE, 0x1FD, 0x43D, 0x1, D_8038BBE0, - chMMMClockSwitch_update, actor_update_func_80326224, actor_draw, + func_80388FE4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chChuchGateLeftLock = { - MARKER_9F_CHURCH_GATE_LEFT_LOCK, ACTOR_10C_CHURCH_GATE_LEFT_LOCK, ASSET_3D0_MODEL_CHURCH_GATE_LEFT_LOCK, +ActorInfo D_8038BDB4 = { + 0x9F, 0x10C, 0x3D0, 0x1, NULL, - chMMMGate_update, actor_update_func_80326224, chMMMGate_draw, + func_803888B8, actor_update_func_80326224, func_80388994, 0, 0, 0.0f, 0 }; -ActorInfo chHedgeGateRightLock1 = { - MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1, ACTOR_10D_HEDGE_GATE_RIGHT_LOCK_1, ASSET_3D1_MODEL_HEDGE_GATE_RIGHT_LOCK_1, +ActorInfo D_8038BDD8 = { + 0xA0, 0x10D, 0x3D1, 0x1, NULL, - chMMMGate_update, actor_update_func_80326224, chMMMGate_draw, + func_803888B8, actor_update_func_80326224, func_80388994, 0, 0, 0.0f, 0 }; -ActorInfo chHedgeGateRightLock2 = { - MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2, ACTOR_1FE_HEDGE_GATE_RIGHT_LOCK_2, ASSET_43E_MODEL_HEDGE_GATE_RIGHT_LOCK_2, +ActorInfo D_8038BDFC = { + 0xFF, 0x1FE, 0x43E, 0x1, NULL, - chMMMGate_update, actor_update_func_80326224, chMMMGate_draw, + func_803888B8, actor_update_func_80326224, func_80388994, 0, 0, 0.0f, 0 }; @@ -207,28 +205,25 @@ f32 MMM_func_80388430(Actor *this, s32 arg1, s32 arg2, f32 arg3) { s32 func_80388670(ActorMarker * this_marker, ActorMarker * other_marker){ Actor *this = marker_getActor(this_marker); - f32 player_position[3]; + f32 sp20[3]; - player_getPosition(player_position); + player_getPosition(sp20); switch(this->marker->id){ - case MARKER_9F_CHURCH_GATE_LEFT_LOCK: //L803886D0 - return (-335.0f < player_position[0] && player_position[0] < -200.0f) - && (-2730.0f < player_position[2] && player_position[2] < -2400.0f); + case 0x9f: //L803886D0 + return (-335.0f < sp20[0] && sp20[0] < -200.0f) && (-2730.0f < sp20[2] && sp20[2] < -2400.0f); - case MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1: //L80388770 - return (-2915.0f < player_position[0] && player_position[0] < -2584.0f) - && ( -500.0f < player_position[2] && player_position[2] < -355.0f); + case 0xa0: //L80388770 + return (-2915.0f < sp20[0] && sp20[0] < -2584.0f) && ( -500.0f < sp20[2] && sp20[2] < -355.0f); - case MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2: //L80388810 - return (5470.0f < player_position[0] && player_position[0] < 5920.0f) - && ( -850.0f < player_position[2] && player_position[2] < -780.0f); + case 0xFF: //L80388810 + return (5470.0f < sp20[0] && sp20[0] < 5920.0f) && ( -850.0f < sp20[2] && sp20[2] < -780.0f); default: return false; } } -void chMMMGate_update(Actor *this){ +void func_803888B8(Actor *this){ func_803300C0(this->marker, func_80388670); func_802D3CE8(this); this->lifetime_value = 0.0f; @@ -250,7 +245,7 @@ void chMMMGate_update(Actor *this){ } } -Actor *chMMMGate_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { +Actor *func_80388994(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { static s32 i; Actor *this; @@ -288,7 +283,7 @@ void func_80388B2C(Actor *this, f32 arg1) { } } -void chChurchDoor_update(Actor *this) { +void func_80388BDC(Actor *this) { f64 phi_f0; func_802D3D74(this); @@ -310,8 +305,7 @@ void chChurchDoor_update(Actor *this) { case 1: this->yaw = 0.0f; if(mapSpecificFlags_get(MMM_SPECIFIC_FLAG_0_UNKNOWN)) { - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, MMM_DOOR_CAM_CHURCH)) - gcStaticCamera_activate(0x21); + gcStaticCamera_activate(0x21); subaddie_set_state(this, 6); core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.3f); mapSpecificFlags_set(MMM_SPECIFIC_FLAG_2_UNKNOWN, false); @@ -325,9 +319,9 @@ void chChurchDoor_update(Actor *this) { if ((this->yaw <= 270.0f) && (this->yaw > 260.0f)) { subaddie_set_state(this, 7U); this->yaw = 270.0f; - gcsfx_play(0x7F); + gcsfx_playAtSampleRate(0x7F); core1_7090_freeSfxSource(0); - code_4C020_setHourglassTimer(0xE); + func_802D68F0(0xE); item_set(6, 1); } break; @@ -341,12 +335,10 @@ void chChurchDoor_update(Actor *this) { if( (!this->unk38_31 && item_empty(ITEM_0_HOURGLASS_TIMER)) || ((this->unk38_31) && (this->lifetime_value == 0.0f)) ) { - if(EventSystem_Should(VB_DOOR_OPEN_CAMERA, true, MMM_DOOR_CAM_CHURCH)){ - if (!this->unk38_31) { - gcStaticCamera_activate(0x22); - } else { - gcStaticCamera_activate(0x23); - } + if (!this->unk38_31) { + gcStaticCamera_activate(0x22); + } else { + gcStaticCamera_activate(0x23); } subaddie_set_state(this, 8); core1_7090_initSfxSource(0, 0x6A, 0x7FF8, 0.3f); @@ -357,7 +349,7 @@ void chChurchDoor_update(Actor *this) { if ((this->yaw >= 0.0f) && (this->yaw < 10.0f)) { subaddie_set_state(this, 1U); this->yaw = 0.0f; - gcsfx_play(SFX_7F_HEAVYDOOR_SLAM); + gcsfx_playAtSampleRate(SFX_7F_HEAVYDOOR_SLAM); mapSpecificFlags_set(MMM_SPECIFIC_FLAG_0_UNKNOWN, false); core1_7090_freeSfxSource(0); if (!this->unk38_31) { @@ -366,29 +358,30 @@ void chChurchDoor_update(Actor *this) { } this->unk38_31 = 0; this->lifetime_value = 0.0f; - progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED); + volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED); } break; } } -void chMMMClockSwitch_update(Actor *this) { +void func_80388FE4(Actor *this) { func_802D4A9C(this,0); } -void chMMMWoodenDoor_update(Actor *this){ +void func_80389004(Actor *this){ func_802D3CE8(this); if (!this->volatile_initialized) { this->volatile_initialized = true; - } - if (levelSpecificFlags_get(LEVEL_FLAG_2E_MMM_UNKNOWN)) { - marker_despawn(this->marker); + + if (levelSpecificFlags_get(LEVEL_FLAG_2E_MMM_UNKNOWN)) { + marker_despawn(this->marker); + } } } -void chXBarrelTop_update(Actor *this){ - if(!this->initialized && sns_get_item_state(SNS_ITEM_EGG_CYAN, TRUE)){ +void func_80389060(Actor *this){ + if(!this->initialized && sns_get_item_state(SNS_ITEM_EGG_CYAN, true)){ marker_despawn(this->marker); } else{ @@ -396,26 +389,26 @@ void chXBarrelTop_update(Actor *this){ } } -void chMMMWindow_update(Actor *this) { - chMMMBreakableWooden_update(this); +void func_803890B8(Actor *this) { + func_802D3D54(this); chTumblar_checkMMMChecksums(); } void MMM_func_803890E0(void){ - spawnableActorList_add(&chShackDoor, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chMansionDoor, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCellarHatch, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chChuchGateLeftLock, actor_new, ACTOR_FLAG_UNKNOWN_6); - spawnableActorList_add(&chHedgeGateRightLock1, actor_new, ACTOR_FLAG_UNKNOWN_6); - spawnableActorList_add(&chHedgeGateRightLock2, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chChuchDoor, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&ch1881BarrelTop, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chXBarrelTop, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chMMMWindow, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&chMMMWideWindow, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&chMMMTallWindow, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&chDiningDoor, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&chMMMClockSwitch, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&D_8038BC28, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038BCDC, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038BC4C, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038BDB4, actor_new, ACTOR_FLAG_UNKNOWN_6); + spawnableActorList_add(&D_8038BDD8, actor_new, ACTOR_FLAG_UNKNOWN_6); + spawnableActorList_add(&D_8038BDFC, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_8038BC94, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038BC70, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038BD00, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8038BD24, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_8038BD48, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_8038BD6C, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_8038BCB8, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_8038BD90, actor_new, ACTOR_FLAG_UNKNOWN_3); spawnableActorList_add(&chNapper, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_12); spawnableActorList_add(&D_8038BA68, actor_new, ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chMotzhand, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_17); @@ -428,5 +421,5 @@ void MMM_func_803890E0(void){ spawnableActorList_add(&chPortraitTreeAndMoon, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_23); spawnableActorList_add(&chPortraitTeeHee, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_23); spawnableActorList_add(&chPortraitMinion, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_23); - spawnableActorList_add(&chPurpleTeeHee, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_19); + spawnableActorList_add(&D_80372C3C, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_19); } diff --git a/src/MMM/bathroom_particles.c b/src/MMM/bathroom_particles.c index c8b3d68bf..5b528374f 100644 --- a/src/MMM/bathroom_particles.c +++ b/src/MMM/bathroom_particles.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/code_13A00.c +// BanjoDecomp: (core2 origin - unknown exact file) #include #include "functions.h" #include "variables.h" @@ -30,7 +30,7 @@ void func_8029A990(void){ else func_8029C304(1); - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); plyr_pos[1] = floor_getCurrentFloorYPosition(); pCtrl = func_802F4094(plyr_pos, 25.0f); particleEmitter_setParticleVelocityRange(pCtrl, @@ -119,7 +119,7 @@ void func_8029AC34(Struct5Ds *arg0, s32 arg1){ void func_8029ACD4(void){ f32 plyr_pos[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); func_802F4894(D_8037D190, plyr_pos); func_802F4884( D_8037D190, func_80294660(), floor_getCurrentFloorYPosition()); } diff --git a/src/MMM/bss_pad.c b/src/MMM/bss_pad.c new file mode 100644 index 000000000..dfa4ab11e --- /dev/null +++ b/src/MMM/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_D_8038C4C0[0x10]; diff --git a/src/MMM/ch/cemetarypot.c b/src/MMM/ch/flowerpot.c similarity index 73% rename from src/MMM/ch/cemetarypot.c rename to src/MMM/ch/flowerpot.c index 05989845a..f1b13f9df 100644 --- a/src/MMM/ch/cemetarypot.c +++ b/src/MMM/ch/flowerpot.c @@ -1,4 +1,4 @@ -// BanjoDecomp: MMM/ch/cemetarypot.c +// BanjoDecomp: code_DC0.c #include #include "functions.h" #include "variables.h" @@ -6,9 +6,6 @@ /* public functions */ void chFlowerpot_update(Actor *this); -extern void port_breakable_recordBreak(s32 markerId, s32 x, s32 y, s32 z); -extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); - /* .data */ enum chFlowerpot_state_e { FLOWER_POT_STATE_1_IDLE = 1, @@ -40,11 +37,11 @@ void chFlowerpot_setRemaining(s32 arg0) { void MMM_func_803871FC(Actor *this) { switch (this->state) { case FLOWER_POT_STATE_1_IDLE: - modelRender_setAppendageVisibility(3, false); + func_8033A45C(3, false); break; case FLOWER_POT_STATE_2_FLOWERED: - modelRender_setAppendageVisibility(3, true); + func_8033A45C(3, true); break; } @@ -63,14 +60,6 @@ void chFlowerpot_update(Actor *this) { this->unk130 = MMM_func_803871FC; } - // Anchor: teammate flowered this pot - match visually without decrementing the count. - if (this->state == FLOWER_POT_STATE_1_IDLE - && port_breakable_isBroken((s32)gsworld_getMap(), (s32)this->marker->id, - (s32)this->position[0], (s32)this->position[1], (s32)this->position[2])) { - subaddie_set_state(this, FLOWER_POT_STATE_2_FLOWERED); - anctrl_setPlaybackType(this->anctrl, ANIMCTRL_ONCE); - } - switch (this->state) { case FLOWER_POT_STATE_1_IDLE: anctrl_setPlaybackType(this->anctrl, ANIMCTRL_STOPPED); @@ -95,7 +84,6 @@ bool chFlowerpot_eggCollision(ActorMarker *marker) { subaddie_set_state(actor, FLOWER_POT_STATE_2_FLOWERED); anctrl_setPlaybackType(actor->anctrl, ANIMCTRL_ONCE); - port_breakable_recordBreak((s32)marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); remaining = chFlowerpot_getRemaining(); if (remaining != 0) { diff --git a/src/MMM/ch/skeleton.c b/src/MMM/ch/limbo.c similarity index 95% rename from src/MMM/ch/skeleton.c rename to src/MMM/ch/limbo.c index f0d6464fa..c07aee95d 100644 --- a/src/MMM/ch/skeleton.c +++ b/src/MMM/ch/limbo.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/ch/skeleton.c +// BanjoDecomp: (core2 origin - unknown exact file) #include #include "functions.h" #include "variables.h" @@ -41,7 +41,7 @@ void func_8035CCA0(ParticleEmitter *pCtrl, Actor *this, enum asset_e model_id) { } -void chLimbo_die(ActorMarker *marker, s32 arg1) { +void chskeleton_despawn(ActorMarker *marker, s32 arg1) { Actor *this; this = marker_getActor(marker); @@ -79,7 +79,7 @@ static void _chskeleton_init(Actor *this) { local->exitInvulnerableStateVolume = 1.0f; local->unkC_28 = true; local->hitFunction = (void (*)(ActorMarker *, ActorMarker *)) humanoidBaddie_enterInvulnerableState; - local->dieFunction = (void (*)(ActorMarker *, ActorMarker *)) chLimbo_die; + local->dieFunction = (void (*)(ActorMarker *, ActorMarker *)) chskeleton_despawn; } diff --git a/src/MMM/ch/loggo.c b/src/MMM/ch/loggo.c index b5fa97e95..c56424ce9 100644 --- a/src/MMM/ch/loggo.c +++ b/src/MMM/ch/loggo.c @@ -42,7 +42,7 @@ void __chLoggo_collide(ActorMarker *this_marker, ActorMarker *other_marker) { Actor *this = marker_getActor(this_marker); if ((player_getTransformation() == TRANSFORM_3_PUMPKIN) && !fileProgressFlag_get(FILEPROG_89_ENTERED_LOGGO_AS_PUMPKIN)) { - if (gcdialog_showDialog(VER_SELECT(ASSET_ADF_DIALOG_ENTER_LOGGO, 0x951, 0, 0), 0x2B, this->position, this->marker, &__chLoggo_textCallback, 0) != 0) { + if (gcdialog_showDialog(ASSET_ADF_DIALOG_ENTER_LOGGO, 0x2B, this->position, this->marker, &__chLoggo_textCallback, 0) != 0) { actor_collisionOff(this); fileProgressFlag_set(FILEPROG_89_ENTERED_LOGGO_AS_PUMPKIN, true); } @@ -56,8 +56,8 @@ void __chLoggo_collide(ActorMarker *this_marker, ActorMarker *other_marker) { } if ((player_getTransformation() == TRANSFORM_1_BANJO) && !fileProgressFlag_get(FILEPROG_88_TRIED_LOGGO_AS_BEAR)) { - if (gcdialog_showDialog(VER_SELECT(ASSET_ADE_DIALOG_LOGGO_AS_BEAR, 0x950, 0, 0), 0x2A, this->position, NULL, NULL, NULL)) { - fileProgressFlag_set(FILEPROG_88_TRIED_LOGGO_AS_BEAR, TRUE); + if (gcdialog_showDialog(ASSET_ADE_DIALOG_LOGGO_AS_BEAR, 0x2A, this->position, NULL, NULL, NULL)) { + fileProgressFlag_set(FILEPROG_88_TRIED_LOGGO_AS_BEAR, true); } } } @@ -82,8 +82,8 @@ void chLoggo_update(Actor *this) { this->lifetime_value = 0.0f; if (!fileProgressFlag_get(FILEPROG_8A_EXITED_LOGGO) && levelSpecificFlags_get(LEVEL_FLAG_33_MMM_UNKNOWN)) { - if (gcdialog_showDialog(VER_SELECT(ASSET_AE0_DIALOG_EXIT_LOGGO, 0x952, 0, 0), 4, NULL, NULL, NULL, NULL)) { - fileProgressFlag_set(FILEPROG_8A_EXITED_LOGGO, TRUE); + if (gcdialog_showDialog(ASSET_AE0_DIALOG_EXIT_LOGGO, 4, NULL, NULL, NULL, NULL)) { + fileProgressFlag_set(FILEPROG_8A_EXITED_LOGGO, true); } } } diff --git a/src/MMM/ch/napper.c b/src/MMM/ch/napper.c index 6497c4eb4..fc1e928c4 100644 --- a/src/MMM/ch/napper.c +++ b/src/MMM/ch/napper.c @@ -66,8 +66,8 @@ void func_80386ACC(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *this = marker_getActor(this_marker); if(!this->has_met_before){ - if(gcdialog_showDialog(VER_SELECT(0xAD8, 0x94A, 0, 0), 0, NULL, NULL, NULL, NULL)){ - this->has_met_before = TRUE; + if(gcdialog_showDialog(0xad8, 0, NULL, NULL, NULL, NULL)){ + this->has_met_before = true; } } } @@ -77,14 +77,14 @@ Actor *chnapper_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ ActorLocal_Napper *local = (ActorLocal_Napper *)&this->local; if(this->state == 1){ - modelRender_setAppendageVisibility(1, true); - modelRender_setAppendageVisibility(2, false); - modelRender_setAppendageVisibility(3, false); + func_8033A45C(1, true); + func_8033A45C(2, false); + func_8033A45C(3, false); } else { - modelRender_setAppendageVisibility(1, false); - modelRender_setAppendageVisibility(2, BOOL(local->unk10)); - modelRender_setAppendageVisibility(3, (local->unk10) ? false : true); + func_8033A45C(1, false); + func_8033A45C(2, BOOL(local->unk10)); + func_8033A45C(3, (local->unk10) ? false : true); } if(this->state == 1){ //set model alpha diff --git a/src/MMM/ch/portrait.c b/src/MMM/ch/portrait.c index f7e68c1a3..e7a7d9e9d 100644 --- a/src/MMM/ch/portrait.c +++ b/src/MMM/ch/portrait.c @@ -1,4 +1,4 @@ -// BanjoDecomp: MMM/ch/portrait.c +// BanjoDecomp: code_2F60.c #include #include "functions.h" #include "variables.h" @@ -63,7 +63,7 @@ ActorInfo chPortraitMinion = { /* .code */ Actor *chPortrait_draw(ActorMarker *marker, Gfx **graphics, Mtx **matrix, Vtx **vertex) { - modelRender_setAppendageVisibility(3, marker_getActor(marker)->unk38_31); + func_8033A45C(3, marker_getActor(marker)->unk38_31); return actor_draw(marker, graphics, matrix, vertex); } diff --git a/src/MMM/ch/portraitchompa.c b/src/MMM/ch/portrait_chompa.c similarity index 98% rename from src/MMM/ch/portraitchompa.c rename to src/MMM/ch/portrait_chompa.c index 788572ddf..6603137f1 100644 --- a/src/MMM/ch/portraitchompa.c +++ b/src/MMM/ch/portrait_chompa.c @@ -1,4 +1,4 @@ -// BanjoDecomp: MMM/ch/portraitchompa.c +// BanjoDecomp: code_16B0.c #include #include "functions.h" #include "variables.h" @@ -100,7 +100,7 @@ void __chChompa_die(ActorMarker *this_marker, ActorMarker *other_marker) { chChompa_setState(this, CHOMPA_STATE_5_DYING); } -void __chChompa_spawnPortrait(ActorMarker *marker) { +void __chChompa_spwanPortrait(ActorMarker *marker) { Actor *this = marker_getActor(reinterpret_cast(ActorMarker *, marker)); enum asset_e portrait_id; Actor *portrait; @@ -206,7 +206,7 @@ void chChompa_update(Actor *this) { this->volatile_initialized = true; this->unk16C_0 = true; marker_setCollisionScripts(this->marker, NULL, __chChompa_hit, __chChompa_die); - __spawnQueue_add_1((GenFunction_1) __chChompa_spawnPortrait, (uintptr_t)this->marker); + __spawnQueue_add_1((GenFunction_1) __chChompa_spwanPortrait, (uintptr_t)this->marker); chChompa_setState(this, this->state < CHOMPA_STATE_5_DYING ? CHOMPA_STATE_1_IDLE : CHOMPA_STATE_6_DEAD); }//L803880B4 diff --git a/src/MMM/ch/tumblar.c b/src/MMM/ch/tumblar.c index 6a234fe65..9a22036b5 100644 --- a/src/MMM/ch/tumblar.c +++ b/src/MMM/ch/tumblar.c @@ -1,4 +1,4 @@ -// BanjoDecomp: MMM/ch/tumblar.c +// BanjoDecomp: code_47D0.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -128,7 +128,7 @@ void __chTumblar_congratulationTextCallback(ActorMarker *marker, enum asset_e te void chTumblar_congratulate(void *arg0_, s32 arg1) { Struct_MMM_47D0_0 *arg0 = (Struct_MMM_47D0_0 *)arg0_; - gcdialog_showDialog(VER_SELECT(ASSET_ADB_DIALOG_TUMBLAR_COMPLETE, 0x94D, 0, 0), 4, NULL, arg0->jiggy_marker, __chTumblar_congratulationTextCallback, NULL); + gcdialog_showDialog(ASSET_ADB_DIALOG_TUMBLAR_COMPLETE, 4, NULL, arg0->jiggy_marker, __chTumblar_congratulationTextCallback, NULL); arg0->state = TUMBLAR_STATE_1_CONGRATULATING; } @@ -221,8 +221,8 @@ void chTumblar_update(Struct_MMM_47D0_0 *arg0, Struct68s *arg1, f32 tick) { func_8035179C_copyPosition(arg1, position); if (!mapSpecificFlags_get(MMM_SPECIFIC_FLAG_0_UNKNOWN) && arg0->state == TUMBLAR_STATE_0_IDLE && ml_vec3f_horizontal_distance_zero_likely(position, plyr_pos) < 250.0f) { - if (gcdialog_showDialog(VER_SELECT(ASSET_ADA_DIALOG_TUMBLAR_MEET, 0x94C, 0, 0), 0, NULL, NULL, NULL, NULL)) { - mapSpecificFlags_set(0, TRUE); + if (gcdialog_showDialog(ASSET_ADA_DIALOG_TUMBLAR_MEET, 0, NULL, NULL, NULL, NULL)) { + mapSpecificFlags_set(0, true); } } diff --git a/src/MMM/checksums.c b/src/MMM/checksums.c deleted file mode 100644 index d501a3cda..000000000 --- a/src/MMM/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: MMM/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsMMM; diff --git a/src/MMM/crc.c b/src/MMM/crc.c index f8aca93a3..2df0fe00e 100644 --- a/src/MMM/crc.c +++ b/src/MMM/crc.c @@ -1,8 +1,7 @@ // BanjoDecomp: crc.c #include -#include "checksums.h" -#include "version.h" -s32 D_8038C300 = VER_SELECT(0x00146061, 0x00148214, 0, 0); // MMM_TEXT_CRC1 -s32 D_8038C304 = VER_SELECT(0xEC79D7B4, 0xE11088CE, 0, 0); // MMM_TEXT_CRC2 -s32 D_8038C308 = VER_SELECT(0x0001B98D, 0x0001C16B, 0, 0); // MMM_DATA_CRC1 +u32 D_8038C300 = 0x00146061; +u32 D_8038C304 = 0xEC79D7B4; +u32 D_8038C308 = 0x0001B98D; +u32 D_8038C30C = 0x0; diff --git a/src/MMM/minigame_organ.c b/src/MMM/minigame_organ.c index 7333e0340..d9d1053d2 100644 --- a/src/MMM/minigame_organ.c +++ b/src/MMM/minigame_organ.c @@ -179,7 +179,7 @@ void func_803898EC() { } void func_80389910() { - gcdialog_showDialog(VER_SELECT(ASSET_AD5_DIALOG_MOTZAND_COMPLETE, 0x947, 0, 0), 0xE, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(ASSET_AD5_DIALOG_MOTZAND_COMPLETE, 0xE, NULL, NULL, MMM_func_80389810, NULL); timedFunc_set_2(0.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); timed_setStaticCameraToNode(2.0f, 0); timedFunc_set_0(2.1f, (GenFunction_0)MMM_func_803898A0); @@ -200,10 +200,10 @@ void organMinigame_setState(s32 next_state){ if (next_state == 2) { if (Me.pattern == 0) { Me.pattern = 1; - gcdialog_showDialog(VER_SELECT(ASSET_AD3_DIALOG_MOTZAND_MEET, 0x945, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(ASSET_AD3_DIALOG_MOTZAND_MEET, 4, NULL, NULL, MMM_func_80389810, NULL); } else {//L80389A84 - gcdialog_showDialog(VER_SELECT(ASSET_AD6_DIALOG_MOTZAND_RETRY, 0x948, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(ASSET_AD6_DIALOG_MOTZAND_RETRY, 4, NULL, NULL, MMM_func_80389810, NULL); } }//L80389A9C @@ -220,13 +220,13 @@ void organMinigame_setState(s32 next_state){ }//L80389AF4 if(next_state == 4){ - gcdialog_showDialog(VER_SELECT(ASSET_ADD_DIALOG_MOTZAND_MISS, 0x94F, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(ASSET_ADD_DIALOG_MOTZAND_MISS, 4, NULL, NULL, MMM_func_80389810, NULL); func_80387720(Me.motzhand_marker); } if(next_state == 5){ Me.pattern++; - gcdialog_showDialog(VER_SELECT(ASSET_AD4_DIALOG_MOTZAND_HALFWAY, 0x946, 0, 0), 4, NULL, NULL, MMM_func_80389810, NULL); + gcdialog_showDialog(ASSET_AD4_DIALOG_MOTZAND_HALFWAY, 4, NULL, NULL, MMM_func_80389810, NULL); func_80387720(Me.motzhand_marker); } diff --git a/src/MMM/minigame_shed.c b/src/MMM/minigame_shed.c index 83b217794..70ac8f5ea 100644 --- a/src/MMM/minigame_shed.c +++ b/src/MMM/minigame_shed.c @@ -84,7 +84,7 @@ void func_8038A140(s32 arg0) { if (MMM_D_8038C510.unk8 == 1) { mapSpecificFlags_set(MMM_SPECIFIC_FLAG_3_UNKNOWN, 1); } - item_set(ITEM_0_HOURGLASS_TIMER, 75*FRAMERATE - 1); + item_set(ITEM_0_HOURGLASS_TIMER, 75*60 - 1); item_set(6, 1); } if (MMM_D_8038C510.unk8 == 3) { diff --git a/src/MMM/napper_room.c b/src/MMM/napper_room.c index 17f2d4264..30603b795 100644 --- a/src/MMM/napper_room.c +++ b/src/MMM/napper_room.c @@ -55,7 +55,7 @@ void func_803895B0(s32 arg0) { } void func_803895D8(ActorMarker *caller, enum asset_e text_id, s32 arg2) { - if (text_id == VER_SELECT(ASSET_AD7_DIALOG_NAPPER_AWAKE, 0x949, 0, 0)) { + if (text_id == 0xAD7) { timed_playSfx(0.1f, SFX_3F5_UNKNOWN, 1.0f, 30000); timed_exitStaticCamera(1.5f); func_80324E38(1.5f, 0); @@ -82,7 +82,7 @@ void func_8038966C(void){ MMM_D_8038C4E0.unk2 = true; func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.2f, 1); - func_80324DBC(0.2f, VER_SELECT(ASSET_AD9_DIALOG_NAPPER_COMPLETE, 0x94B, 0, 0), 6, NULL, NULL, func_803895D8, NULL); + func_80324DBC(0.2f, 0xad9, 6, NULL, NULL, func_803895D8, NULL); }//L80389700 if(MMM_D_8038C4E0.unk1 != 1) @@ -109,8 +109,8 @@ void func_8038966C(void){ if (!levelSpecificFlags_get(LEVEL_FLAG_1B_MMM_UNKNOWN)) { func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.0f, 0); - func_80324DBC(0.0f, VER_SELECT(ASSET_AD7_DIALOG_NAPPER_AWAKE, 0x949, 0, 0), 6, NULL, NULL, func_803895D8, NULL); - levelSpecificFlags_set(LEVEL_FLAG_1B_MMM_UNKNOWN, TRUE); + func_80324DBC(0.0f, 0xad7, 6, NULL, NULL, func_803895D8, NULL); + levelSpecificFlags_set(LEVEL_FLAG_1B_MMM_UNKNOWN, true); } } } diff --git a/src/RBB/actor_spawninit.c b/src/RBB/actor_spawninit.c new file mode 100644 index 000000000..c7492be54 --- /dev/null +++ b/src/RBB/actor_spawninit.c @@ -0,0 +1,231 @@ +// BanjoDecomp: code_640.c +#include +#include "core1/core1.h" +#include "functions.h" +#include "variables.h" +#include "prop.h" +#include "actor.h" + +#include "port/Patches/Patches.h" + + +extern ActorInfo D_80390D20; +extern ActorInfo D_80390050; +extern ActorInfo D_80390200; +extern ActorInfo D_80390270; +extern ActorInfo D_80390D50; +extern ActorInfo D_803906E0; +extern ActorInfo D_80390738; +extern ActorInfo D_803907D0; +extern ActorInfo D_803907F4; +extern ActorInfo D_80390818; +extern ActorInfo D_8039083C; +extern ActorInfo D_803904C0; +extern ActorInfo D_803904E4; +extern ActorInfo D_80390508; +extern ActorInfo D_803903B0; +extern ActorInfo D_803903D4; +extern ActorInfo D_803903F8; +extern ActorInfo D_80390640; +extern ActorInfo D_80390664; +extern ActorInfo D_80390688; +extern ActorInfo D_803906B0; +extern ActorInfo D_803908C0; +extern ActorInfo D_803908E4; +extern ActorInfo D_80390908; +extern ActorInfo D_803909B0; +extern ActorInfo D_803909D4; +extern ActorInfo RBB_D_803909F8; +extern ActorInfo D_80390A50; +extern ActorInfo D_80390380; +extern ActorInfo D_80390A80; //anchorswitch +extern ActorInfo RBB_D_80390AB0; //dolphin +extern ActorInfo RBB_D_80390AE0; //anchor +extern ActorInfo RBB_D_80390B10; +extern ActorInfo D_80390B40; //rarewareflag +extern ActorInfo RBB_D_80390BD0; +extern ActorInfo D_80390BF4; +extern ActorInfo D_80390C18; +extern ActorInfo RBB_D_80390C3C; +extern ActorInfo RBB_D_80390CF0; +extern ActorInfo D_80390D88; +extern ActorInfo D_80390DAC; //TNTpart_IDStruct; +extern ActorInfo RBB_D_80390E00; +extern ActorInfo D_80390E34; +extern ActorInfo D_80390E58; +extern ActorInfo D_803900E0; +extern ActorInfo D_80390104; //captcabinwooddoor +extern ActorInfo D_80390128; +extern ActorInfo D_8039014C; +extern ActorInfo D_803901B8; +extern ActorInfo D_803901DC; +extern ActorInfo D_80390170;//skylight +extern ActorInfo D_80390194;//honeycombswitch + + + +extern void func_802D3D54(Actor *); + +void func_80386A7C(Actor *); +void func_80386BF8(Actor *arg0); +Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); + + +/* .data */ +ActorAnimationInfo D_803900C0[4] = { + {0, 0.0f}, + {0, 0.0f}, + {0xD4, 0.15f}, + {0xD5, 0.5f} +}; + +ActorInfo D_803900E0 = { + 0x107, 0x21D, 0x493, 0x1, NULL, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80390104 = { + 0x108, 0x21C, 0x492, 0x1, NULL, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80390128 = { + 0x22D, 0x266, 0x4BA, 0x1, NULL, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_8039014C = { + 0x22E, 0x267, 0x4BB, 0x1, NULL, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80390170 = { + 0x235, 0x23F, 0x4E2, 0x1, NULL, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_80390194 = { + 0x15F, 0x18F, 0x42F, 0x1, D_803900C0, + func_80386BF8, actor_update_func_80326224, actor_draw, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803901B8 = { + 0x22F, 0x263, 0x4DB, 0x1, NULL, + func_80386A7C, actor_update_func_80326224, func_80386B9C, + 0, 0, 0.0f, 0 +}; + +ActorInfo D_803901DC = { + 0x230, 0x264, 0x4DE, 0x1, NULL, + func_80386A7C, actor_update_func_80326224, func_80386B9C, + 0, 0, 0.0f, 0 +}; + + +/* .code */ +s32 func_80386A30(f32 arg0[3]){ + s32 r; + + r = (arg0[0] < 0.0f)? 0 : 1; + + return ((arg0[2] < 0.0f)? 0 : 2) + r; +} + +void func_80386A7C(Actor *this){ + f32 viewport[3]; + s32 sp28; + s32 temp_v0; + + func_802D3D74(this); + this->depth_mode = 1; + viewport_getPosition_vec3f(viewport); + sp28 = func_80386A30(this->position); + temp_v0 = func_80386A30(viewport); + this->unk38_0 = 0; + // [port] Extend the bespoke distance cull with draw distance; quadrant occlusion below stays. + f32 cull = 8000.0f * port_drawDistanceMul(); + if(viewport[0] + cull < this->position_x || this->position_x < viewport[0] - cull) + return; + + if( !( (sp28 ^ temp_v0) & 2 + && (-5000.0f < viewport[0] && viewport[0] < 6000.0f) + && (viewport[2] < -600.0f || 600.0f < viewport[2]) + ) + && ( sp28 ^ temp_v0) != 3 + ){ + this->unk38_0 = 1; + } +} + +Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ + Actor *actor = marker_getActor(marker); + + return (actor->unk38_0) ? actor_drawFullDepth(marker, gdl, mptr, arg3): NULL; +} + +void func_80386BF8(Actor *arg0){ + if(!mapSpecificFlags_get(0) && honeycombscore_get(HONEYCOMB_F_RBB_BOAT_HOUSE)) + mapSpecificFlags_set(0, true); + func_802D4A9C(arg0, 0); +} + +void RBB_func_80386C48(void){ + spawnableActorList_add(&D_80390D20, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_80390050, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_80390200, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390270, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390D50, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_27); + spawnableActorList_add(&D_803906E0, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390738, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_803907D0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_803907F4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_80390818, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_8039083C, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_803904C0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_803904E4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_80390508, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_803903B0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_803903D4, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_803903F8, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); + spawnableActorList_add(&D_80390640, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_80390664, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_80390688, actor_new, ACTOR_FLAG_UNKNOWN_10); + spawnableActorList_add(&D_803906B0, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_803908C0, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_803908E4, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390908, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_803909B0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_803909D4, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&RBB_D_803909F8, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_80390A50, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390380, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_80390A80, actor_new, ACTOR_FLAG_UNKNOWN_7); //anchorswitch + spawnableActorList_add(&RBB_D_80390AB0, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //dolphin + spawnableActorList_add(&RBB_D_80390AE0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); //anchor + spawnableActorList_add(&RBB_D_80390B10, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390B40, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //rarewareflag + spawnableActorList_add(&RBB_D_80390BD0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_80390BF4, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_80390C18, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&RBB_D_80390C3C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&RBB_D_80390CF0, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390D88, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&D_80390DAC, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&RBB_D_80390E00, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390E34, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80390E58, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_803900E0, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_80390104, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //captcabinwooddoor + spawnableActorList_add(&D_80390128, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_8039014C, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_803901B8, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_803901DC, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_80390170, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //skylight + spawnableActorList_add(&D_80390194, actor_new, ACTOR_FLAG_UNKNOWN_3); //honeycombswitch +} diff --git a/src/RBB/bss_pad.c b/src/RBB/bss_pad.c new file mode 100644 index 000000000..e0e22c075 --- /dev/null +++ b/src/RBB/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_RBB_80391270[0x10]; diff --git a/src/RBB/ch/anchor.c b/src/RBB/ch/anchor.c index 1072d5bb8..53acfa10c 100644 --- a/src/RBB/ch/anchor.c +++ b/src/RBB/ch/anchor.c @@ -3,35 +3,28 @@ #include "functions.h" #include "variables.h" -void chAnchor_update(Actor *this); +void func_8038BF28(Actor *this); /* .data */ -ActorInfo chAnchor = { - MARKER_31_ANCHOR, ACTOR_1C9_ANCHOR, ASSET_41D_MODEL_ANCHOR, - 0x0, NULL, - chAnchor_update, NULL, actor_draw, +ActorInfo RBB_D_80390AE0 = { + 0x31, 0x1C9, 0x41D, 0x0, NULL, + func_8038BF28, NULL, actor_draw, 0, 0, 0.0f, 0 }; -enum chanchor_state_e { - CH_ANCHOR_STATE_0_NOT_INIT, - CH_ANCHOR_STATE_1_LOWERED, - CH_ANCHOR_STATE_2_RAISED -}; - /* .code */ -void chAnchor_setState(Actor *this, s32 next_state){ - if(next_state == CH_ANCHOR_STATE_1_LOWERED) +void RBB_func_8038BEA0(Actor *this, s32 arg1){ + if(arg1 == 1) skeletalAnim_set(this->unk148, ASSET_141_ANIM_ANCHOR_LOWERED, 0.0f, 5.5f); - if(next_state == CH_ANCHOR_STATE_2_RAISED){ + if(arg1 == 2){ skeletalAnim_set(this->unk148, ASSET_142_ANIM_ANCHOR_RISING, 0.0f, 8.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } - this->state = next_state; + this->state = arg1; } -void chAnchor_update(Actor *this){ +void func_8038BF28(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; this->position_x = -5100.0f; @@ -39,16 +32,14 @@ void chAnchor_update(Actor *this){ this->position_z = 1460.0f; this->marker->propPtr->unk8_3 = 1; this->yaw = 0.0f; - chAnchor_setState(this, CH_ANCHOR_STATE_1_LOWERED); + RBB_func_8038BEA0(this, 1); if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)){ marker_despawn(this->marker); } } else{ - if(this->state == CH_ANCHOR_STATE_1_LOWERED - && mapSpecificFlags_get(8)) - { - chAnchor_setState(this, CH_ANCHOR_STATE_2_RAISED); + if(this->state == 1 && mapSpecificFlags_get(8)){ + RBB_func_8038BEA0(this, 2); } } } diff --git a/src/RBB/ch/anchorctrl.c b/src/RBB/ch/anchorctrl.c index 51d4fc3cc..3cc1bc66c 100644 --- a/src/RBB/ch/anchorctrl.c +++ b/src/RBB/ch/anchorctrl.c @@ -4,29 +4,21 @@ #include "variables.h" -void __chAnchorCtrl_setState(Actor *this, s32 next_state); +void __chAnchorCtrl_setState(Actor *this, s32 new_state); void chAnchorCtrl_update(Actor *this); /* .data */ -ActorInfo chAnchorCtrl = { - 0x199, 0x1CB, 0x0, - 0x0, NULL, +ActorInfo RBB_D_80390B10 = { + 0x199, 0x1CB, 0x0, 0x0, NULL, chAnchorCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; -enum chanchorctrl_state_e { - CH_ANCHOR_CTRL_STATE_0_NOT_INIT, - CH_ANCHOR_CTRL_STATE_1_LOWERED, - CH_ANCHOR_CTRL_STATE_2_RAISING, - CH_ANCHOR_CTRL_STATE_3_RAISED -}; - /* .code */ void func_8038C000(void){ s32 sp1C = func_802F9AA8(SFX_7D_ANCHOR_LIFTING); - func_802FA060(sp1C, 27000, 27000, 0.0f); + func_802FA060(sp1C, 0x6978, 0x6978, 0.0f); func_802F9F80(sp1C, 0.5f, 7.0f, 0.5f); } @@ -37,27 +29,26 @@ void func_8038C058(void){ } void __chAnchorCtrl_spawnJiggy(ActorMarker *marker, enum asset_e id, s32 arg2){ - static f32 chAnchorCtrlJiggyPosition[3] = {-5100.0f, -2550.0f, 1470.0f}; + static f32 D_80390B34[3] = {-5100.0f, -2550.0f, 1470.0f}; Actor *actor = marker_getActor(marker); - jiggy_spawn(JIGGY_53_RBB_SNORKEL, chAnchorCtrlJiggyPosition); - timed_setStaticCameraToNode(0.5f, 0xB); - __chAnchorCtrl_setState(actor, CH_ANCHOR_CTRL_STATE_3_RAISED); + jiggy_spawn(JIGGY_53_RBB_SNORKEL, D_80390B34); + timed_setStaticCameraToNode(0.5f, 0xb); + __chAnchorCtrl_setState(actor, 3); } -void __chAnchorCtrl_setState(Actor *this, s32 next_state){ - if(next_state == CH_ANCHOR_CTRL_STATE_2_RAISING) - { +void __chAnchorCtrl_setState(Actor *this, s32 new_state){ + if(new_state == 2){ ncStaticCamera_setToNode(0xC); func_80324E38(0.0f, 3); timedFunc_set_0(1.0f, func_8038C000); - timedFunc_set_2(1.0f, (GenFunction_2)mapSpecificFlags_set, RBB_MAIN_SPECIFIC_FLAG_8_UNK, true); + timedFunc_set_2(1.0f, (GenFunction_2)mapSpecificFlags_set, 8, true); timed_playSfx(2.1f, SFX_3F6_RUBBING, 0.6f, 32700); - timedFunc_set_2(2.7f, (GenFunction_2)mapSpecificFlags_set, RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING, true); + timedFunc_set_2(2.7f, (GenFunction_2)mapSpecificFlags_set, 4, true); timedFunc_set_0(3.0f, func_8038C058); - func_80324DBC(3.0f, VER_SELECT(ASSET_B9C_DIALOG_SNORKEL_COMPLETE, 0x971, 0, 0), 7, NULL, this->marker, __chAnchorCtrl_spawnJiggy, NULL); + func_80324DBC(3.0f, ASSET_B9C_DIALOG_SNORKEL_COMPLETE, 7, NULL, this->marker, __chAnchorCtrl_spawnJiggy, NULL); }//L8038C1D8 - this->state = next_state; + this->state = new_state; } void chAnchorCtrl_update(Actor *this){ @@ -65,19 +56,17 @@ void chAnchorCtrl_update(Actor *this){ this->volatile_initialized = true; if (levelSpecificFlags_getSet(LEVEL_FLAG_30_RBB_UNKNOWN, false)) { - __chAnchorCtrl_setState(this, CH_ANCHOR_CTRL_STATE_2_RAISING); + __chAnchorCtrl_setState(this, 2); } else { - __chAnchorCtrl_setState(this, CH_ANCHOR_CTRL_STATE_1_LOWERED); + __chAnchorCtrl_setState(this, 1); } if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)) marker_despawn(this->marker); }//L8038C27C - if(this->state == CH_ANCHOR_CTRL_STATE_3_RAISED - && !mapSpecificFlags_get(RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING)) - { + if(this->state == 3 && !mapSpecificFlags_get(4)){ timed_exitStaticCamera(0.0f); func_80324E38(0.0f, 0); timedFunc_set_0(0.0f, musicKeepsPlaying); diff --git a/src/RBB/ch/anchorswitch.c b/src/RBB/ch/anchorswitch.c index 0d3aa33e2..92754c457 100644 --- a/src/RBB/ch/anchorswitch.c +++ b/src/RBB/ch/anchorswitch.c @@ -6,40 +6,33 @@ void chAnchorSwitch_update(Actor *this); /* .data */ -ActorInfo chAnchorSwitch = { - MARKER_2F_ANCHOR_SWITCH, ACTOR_1C7_ANCHOR_SWITCH, ASSET_41B_MODEL_ANCHOR_SWITCH, - 0x0, NULL, +ActorInfo D_80390A80 = { + 0x2F, 0x1C7, 0x41B, 0x0, NULL, chAnchorSwitch_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -enum chanchorswitch_state_e { - CH_ANCHOR_SWITCH_STATE_0_NOT_INIT, - CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED, - CH_ANCHOR_SWITCH_STATE_2_PRESSED -}; - /* .code */ -void __chAnchorSwitch_setState(Actor *this, s32 next_state){ - if(next_state == CH_ANCHOR_SWITCH_STATE_2_PRESSED){ - if(this->state == CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED){ +void __chAnchorSwitch_setState(Actor *this, s32 arg1){ + if(arg1 == 2){ + if(this->state == 1){ func_8030E6D4(SFX_90_SWITCH_PRESS); } actor_collisionOff(this); this->position_y -= 35.0f; - if(this->state == CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED){ + if(this->state == 1){ levelSpecificFlags_set(LEVEL_FLAG_30_RBB_UNKNOWN, true); volatileFlag_set(VOLATILE_FLAG_E, 1); timedFunc_set_0(1.0f, musicKeepsPlaying); timedFunc_set_3(1.0f, (GenFunction_3)transitionToMap, MAP_31_RBB_RUSTY_BUCKET_BAY, 0, 0); } } - this->state = next_state; + this->state = arg1; } void __chAnchorSwitch_press(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - __chAnchorSwitch_setState(actor, CH_ANCHOR_SWITCH_STATE_2_PRESSED); + __chAnchorSwitch_setState(actor, 2); } void chAnchorSwitch_update(Actor *this){ @@ -48,8 +41,8 @@ void chAnchorSwitch_update(Actor *this){ this->marker->propPtr->unk8_3 = 1; marker_setCollisionScripts(this->marker, NULL, __chAnchorSwitch_press, NULL); if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)) - __chAnchorSwitch_setState(this, CH_ANCHOR_SWITCH_STATE_2_PRESSED); + __chAnchorSwitch_setState(this, 2); else - __chAnchorSwitch_setState(this, CH_ANCHOR_SWITCH_STATE_1_NOT_PRESSED); + __chAnchorSwitch_setState(this, 1); } } diff --git a/src/RBB/ch/axle.c b/src/RBB/ch/axle.c index 619da6ef7..da1f91bab 100644 --- a/src/RBB/ch/axle.c +++ b/src/RBB/ch/axle.c @@ -6,96 +6,73 @@ /* typedefs and declarations */ typedef struct { s16 unk0; - f32 position[3]; - f32 startingRoll; + f32 unk4[3]; + f32 unk10; f32 unk14; f32 unk18[3]; -} ActorLocal_ChSpinningFlatPlatform_0; +}ActorLocal_RBB_2A70_0; typedef struct { - ActorLocal_ChSpinningFlatPlatform_0 *unk0; - f32 currentRotation[3]; - f32 nextRotation[3]; + ActorLocal_RBB_2A70_0 *unk0; + f32 unk4[3]; + f32 unk10[3]; f32 unk1C; u8 pad20[0x4]; f32 unk24; -} ActorLocal_ChSpinningFlatPlatform; +}ActorLocal_RBB_2A70; -void chSpinningFlatPlatform_update(Actor *this); +void func_803890BC(Actor *this); /* .data */ -ActorLocal_ChSpinningFlatPlatform_0 chSpinningFlatPlatformTable[] = { - { - ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, - {0.0f, -60.0f, 2450.0f}, - 0.0f, - 6.0f, - {0.0f, -100.0f, 1900.0f} - }, - { - ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, - {-1600.0f, 730.0f, -700.0f}, - 270.0f, - 6.0f, - { -1600.0f, 810.0f, -1400.0f}}, - { - ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, - {1600.0f, 730.0f, -700.0f}, - 270.0f, - 5.0f, - {1600.0f, 810.0f, -1400.0f} - }, - { 0 } // [port] decomp uses NULL; actorId is s16 and clang errors on -Wint-conversion +ActorLocal_RBB_2A70_0 D_80390430[] = { + {ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, {0.0f, -60.0f, 2450.0f}, 0.0f, 6.0f, { 0.0f, -100.0f, 1900.0f}}, + {ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, {-1600.0f, 730.0f, -700.0f}, 270.0f, 6.0f, { -1600.0f, 810.0f, -1400.0f}}, + {ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, {1600.0f, 730.0f, -700.0f}, 270.0f, 5.0f, { 1600.0f, 810.0f, -1400.0f}}, + 0 }; -ActorInfo chSpinningFlatPlatform1 = { - MARKER_188_RBB_SPINNING_FLAT_PLATFORM_1, ACTOR_178_RBB_SPINNING_FLAT_PLATFORM_1, ASSET_40C_MODEL_RBB_SPINNING_FLAT_PLATFORM_1, 0x0, NULL, - chSpinningFlatPlatform_update, NULL, actor_draw, +ActorInfo D_803904C0 = { + 0x188, 0x178, 0x40C, 0x0, NULL, + func_803890BC, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chSpinningFlatPlatform2 = { - MARKER_189_RBB_SPINNING_FLAT_PLATFORM_2, ACTOR_179_RBB_SPINNING_FLAT_PLATFORM_2, ASSET_40D_MODEL_RBB_SPINNING_FLAT_PLATFORM_2, 0x0, NULL, - chSpinningFlatPlatform_update, NULL, actor_draw, +ActorInfo D_803904E4 = { + 0x189, 0x179, 0x40D, 0x0, NULL, + func_803890BC, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chSpinningFlatPlatform3 = { - MARKER_18A_RBB_SPINNING_FLAT_PLATFORM_3, ACTOR_17A_RBB_SPINNING_FLAT_PLATFORM_3, ASSET_40E_MODEL_RBB_SPINNING_FLAT_PLATFORM_3, 0x0, NULL, - chSpinningFlatPlatform_update, NULL, actor_draw, +ActorInfo D_80390508 = { + 0x18A, 0x17A, 0x40E, 0x0, NULL, + func_803890BC, NULL, actor_draw, 0, 0, 0.0f, 0 }; -enum chspinningflatplatform_state_e { - CH_SPINNING_FLAT_PLATFORM_STATE_0_NOT_INIT, - CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE, - CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING -}; - /* .code */ -ActorLocal_ChSpinningFlatPlatform_0 *func_80388E60(Actor *this){ - ActorLocal_ChSpinningFlatPlatform_0 * iPtr; - for(iPtr = chSpinningFlatPlatformTable; iPtr->unk0 != 0; iPtr++){ +ActorLocal_RBB_2A70_0 *func_80388E60(Actor *this){ + ActorLocal_RBB_2A70_0 * iPtr; + for(iPtr = D_80390430; iPtr->unk0 != 0; iPtr++){ if(iPtr->unk0 == this->modelCacheIndex) return iPtr; } return NULL; } -void chSpinningFlatPlatform_setState(Actor *this, s32 next_state){ - ActorLocal_ChSpinningFlatPlatform *local = (ActorLocal_ChSpinningFlatPlatform *)&this->local; +void func_80388EB8(Actor *this, s32 arg1){ + ActorLocal_RBB_2A70 *local = (ActorLocal_RBB_2A70 *)&this->local; s32 sp30; - if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING) + if(this->state == 2) sfx_playFadeShorthandDefault(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 32000, this->position, 1000, 2300); - this->state = next_state; + this->state = arg1; local->unk24 = 0.0f; - if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE) + if(this->state == 1) local->unk24 = local->unk0->unk14; - if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING){ + if(this->state == 2){ sp30 = func_802F9AA8(SFX_94_COGS_ROTATING); func_802F9DB8(sp30, 1.0f, 1.0f, 0.0f); func_802F9EC4(sp30, local->unk0->unk18, 1700, 2500); @@ -105,52 +82,49 @@ void chSpinningFlatPlatform_setState(Actor *this, s32 next_state){ this->yaw += ( 360.0f <= this->yaw) ? -360 : 0; this->roll += ( 360.0f <= this->roll) ? -360 : 0; - local->currentRotation[0] = this->pitch; - local->currentRotation[1] = this->yaw; - local->currentRotation[2] = this->roll; + local->unk4[0] = this->pitch; + local->unk4[1] = this->yaw; + local->unk4[2] = this->roll; - local->nextRotation[0] = this->pitch; - local->nextRotation[1] = this->yaw; - local->nextRotation[2] = this->roll + 360.0f; + local->unk10[0] = this->pitch; + local->unk10[1] = this->yaw; + local->unk10[2] = this->roll + 360.0f; local->unk1C = 0.0f; sfx_playFadeShorthandDefault(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 32000, this->position, 900, 1800); }//L803890A8 } -void chSpinningFlatPlatform_update(Actor *this){ - ActorLocal_ChSpinningFlatPlatform *local = (ActorLocal_ChSpinningFlatPlatform *)&this->local; - f32 time_delta = time_getDelta(); - f32 rotation[3]; - +void func_803890BC(Actor *this){ + ActorLocal_RBB_2A70 *local = (ActorLocal_RBB_2A70 *)&this->local; + f32 sp38 = time_getDelta(); + f32 sp2C[3]; if(!this->volatile_initialized){ actor_collisionOff(this); this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = func_80388E60(this); - this->position[0] = local->unk0->position[0]; - this->position[1] = local->unk0->position[1]; - this->position[2] = local->unk0->position[2]; - this->roll = local->unk0->startingRoll; - if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_0_NOT_INIT) - chSpinningFlatPlatform_setState(this, CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE); + this->position[0] = local->unk0->unk4[0]; + this->position[1] = local->unk0->unk4[1]; + this->position[2] = local->unk0->unk4[2]; + this->roll = local->unk0->unk10; + if(this->state == 0) + func_80388EB8(this, 1); }//L80389164 - if(ml_timer_update(&local->unk24, time_delta)) - chSpinningFlatPlatform_setState(this, - (this->state == CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE) ? - CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING : CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE); + if(ml_timer_update(&local->unk24, sp38)) + func_80388EB8(this, (this->state == 1) ? 2 : 1); //L803891A8 - if(this->state == CH_SPINNING_FLAT_PLATFORM_STATE_2_ROTATING){ - local->unk1C += 0.25 * time_delta; + if(this->state == 2){ + local->unk1C += 0.25 * sp38; if(1.0f < local->unk1C) local->unk1C = 1.0f; - ml_vec3f_interpolate_fast(rotation, local->currentRotation, local->nextRotation, local->unk1C); - this->pitch = rotation[0]; - this->yaw = rotation[1]; - this->roll = rotation[2]; + ml_vec3f_interpolate_fast(sp2C, local->unk4, local->unk10, local->unk1C); + this->pitch = sp2C[0]; + this->yaw = sp2C[1]; + this->roll = sp2C[2]; if(local->unk1C == 1.0f) - chSpinningFlatPlatform_setState(this, CH_SPINNING_FLAT_PLATFORM_STATE_1_IDLE); + func_80388EB8(this, 1); }//L80389264 } diff --git a/src/RBB/ch/bellbuoy.c b/src/RBB/ch/bellbuoy.c index 04937bccf..0ac91646b 100644 --- a/src/RBB/ch/bellbuoy.c +++ b/src/RBB/ch/bellbuoy.c @@ -8,127 +8,118 @@ /* typedefs and declarations */ typedef struct { f32 unk0; - ActorMarker *jinjoMarker; - f32 position[3]; - f32 rotation[3]; + ActorMarker *unk4; + f32 unk8[3]; + f32 unk14[3]; s32 unk20; - f32 timer[3]; -} ActorLocal_7B20; + f32 unk24[3]; +}ActorLocal_7B20; -void chBellBuoy_update(Actor* this); +void func_8038DF6C(Actor* this); /* .data */ -ActorInfo chBellBuoy = { - MARKER_1AA_BELL_BUOY, ACTOR_296_BELL_BUOY, ASSET_43B_MODEL_BELL_BUOY, - 0x0, NULL, - chBellBuoy_update, NULL, actor_draw, +ActorInfo D_80390D20 = { + 0x1AA, 0x296, 0x43B, 0x0, NULL, + func_8038DF6C, NULL, actor_draw, 0, 0, 0.0f, 0 }; -enum chbellbuoy_state_e { - CH_BELL_BUOY_STATE_0_NOT_INIT, - CH_BELL_BUOY_STATE_1_INIT -}; /*.code */ -void chBellBuoy_setState(Actor *this, int next_state){ - if(next_state == CH_BELL_BUOY_STATE_1_INIT){ - skeletalAnim_set(this->unk148, ASSET_16A_ANIM_BELL_BUOY, 0, 1.2f); +void func_8038DF10(Actor *this, int arg1){ + if(arg1 == 1){ + skeletalAnim_set(this->unk148, 0x16a, 0, 1.2f); } - this->state = next_state; + this->state = arg1; } -void chBellBuoy_update(Actor* this){ - f32 rotation_delta[3]; - f32 position_delta[3]; +void func_8038DF6C(Actor* this){ + f32 sp7C[3]; + f32 sp70[3]; f32 sp6C; - f32 time_delta = time_getDelta(); - f32 new_rotation[3]; - f32 distance; + f32 sp68 = time_getDelta(); + f32 sp5C[3]; + f32 sp58; ActorLocal_7B20 *local = (ActorLocal_7B20 *)&this->local; - Actor* jinjo; - int actor_id; + Actor* other; + int i; if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = randf2(80.0f, 100.0f); - local->jinjoMarker = NULL; + local->unk4 = NULL; local->unk20 = 0; - local->timer[0] = 0.0f; - local->timer[1] = 1.0f; - local->timer[2] = 0.5f; - local->position[0] = this->position_x; - local->position[1] = this->position_y; - local->position[2] = this->position_z; - local->rotation[0] = this->pitch; - local->rotation[1] = this->yaw; - local->rotation[2] = this->roll; - chBellBuoy_setState(this, CH_BELL_BUOY_STATE_1_INIT); + local->unk24[0] = 0.0f; + local->unk24[1] = 1.0f; + local->unk24[2] = 0.5f; + local->unk8[0] = this->position_x; + local->unk8[1] = this->position_y; + local->unk8[2] = this->position_z; + local->unk14[0] = this->pitch; + local->unk14[1] = this->yaw; + local->unk14[2] = this->roll; + func_8038DF10(this, 1); }//L8038E050 - if(++local->unk20 == 2){ - // Actor 0x5E through 0x62 are Jinjos - for(actor_id = 0x5E; actor_id < 0x63; actor_id++){ + for(i = 0x5e; i < 0x63; i++){ - jinjo = actorArray_findClosestActorFromActorId(this->position, actor_id, -1, &distance); - if(distance < 300.0f){ - local->jinjoMarker = jinjo->marker; - jinjo->position_x = this->position_x; - jinjo->position_y = this->position_y; - jinjo->position_z = this->position_z; + other = actorArray_findClosestActorFromActorId(this->position, i, -1, &sp58); + if(sp58 < 300.0f){ + local->unk4 = other->marker; + other->position_x = this->position_x; + other->position_y = this->position_y; + other->position_z = this->position_z; break; } } } - - if(ml_timer_update(&local->timer[1], time_delta)){ - local->timer[1] = randf2(1.5f, 2.5f); + if(ml_timer_update(&local->unk24[1], sp68)){ + local->unk24[1] = randf2(1.5f, 2.5f); sfx_playFadeShorthandDefault(SFX_40E_UNKNOWN, 1.5f, 20000, this->position, 500, 1500); }//L8038E118 - if(ml_timer_update(&local->timer[2], time_delta)){ - local->timer[2] = randf2(3.5f, 5.5f); - func_8030E878(SFX_69_WHIPCRACK_CREAKING, randf2(1.1f, 1.2f), 22000, this->position, 500.0f, 1500.0f); + if(ml_timer_update(&local->unk24[2], sp68)){ + local->unk24[2] = randf2(3.5f, 5.5f); + func_8030E878(SFX_69_WHIPCRACK_CREAKING, randf2(1.1f, 1.2f), 0x55f0, this->position, 500.0f, 1500.0f); }//L8038E184 - local->timer[0] += time_delta; - position_delta[0] = 0.0f; - position_delta[1] = sinf((local->timer[0] * local->unk0) / 180.0 * BAD_PI) * 10.0f; - position_delta[2] = 0.0f; + local->unk24[0] += sp68; + sp70[0] = 0.0f; + sp70[1] = sinf((local->unk24[0]*local->unk0)/ 180.0 * 3.141592654) * 10.0f; + sp70[2] = 0.0f; - rotation_delta[0] = cosf((local->timer[0] * local->unk0) / 180.0 * BAD_PI) * 7.5; - rotation_delta[1] = sinf((local->timer[0] * local->unk0) / 180.0 * BAD_PI) * 3.0; - rotation_delta[2] = 0.0f; + sp7C[0] = cosf((local->unk24[0]*local->unk0)/ 180.0 * 3.141592654)*7.5; + sp7C[1] = sinf((local->unk24[0]*local->unk0)/ 180.0 * 3.141592654)*3.0; + sp7C[2] = 0.0f; - this->position_x = local->position[0] + position_delta[0]; - this->position_y = local->position[1] + position_delta[1]; - this->position_z = local->position[2] + position_delta[2]; + this->position_x = local->unk8[0] + sp70[0]; + this->position_y = local->unk8[1] + sp70[1]; + this->position_z = local->unk8[2] + sp70[2]; - new_rotation[0] = local->rotation[0] + rotation_delta[0]; - new_rotation[1] = local->rotation[1] + rotation_delta[1]; - new_rotation[2] = local->rotation[2] + rotation_delta[2]; + sp5C[0] = local->unk14[0] + sp7C[0]; + sp5C[1] = local->unk14[1] + sp7C[1]; + sp5C[2] = local->unk14[2] + sp7C[2]; - this->pitch = new_rotation[0]; - this->yaw = new_rotation[1]; - this->roll = new_rotation[2]; + this->pitch = sp5C[0]; + this->yaw = sp5C[1]; + this->roll = sp5C[2]; - if(local->jinjoMarker){ - jinjo = marker_getActor(local->jinjoMarker); - // State 7-9 Are Collecting Jinjo States - if(!(jinjo->state < 7)){ - local->jinjoMarker = NULL; + if(local->unk4){ + other = marker_getActor(local->unk4); + if(!(other->state < 7)){ + local->unk4 = NULL; }else{ - jinjo->pitch = new_rotation[0]; - jinjo->roll = new_rotation[2]; - TUPLE_ASSIGN(new_rotation, 0.0f, 48.0f, 0.0f); - ml_vec3f_pitch_rotate_copy(new_rotation, new_rotation, this->pitch); - ml_vec3f_yaw_rotate_copy(new_rotation, new_rotation, this->yaw); + other->pitch = sp5C[0]; + other->roll = sp5C[2]; + TUPLE_ASSIGN(sp5C, 0.0f, 48.0f, 0.0f); + ml_vec3f_pitch_rotate_copy(sp5C, sp5C, this->pitch); + ml_vec3f_yaw_rotate_copy(sp5C, sp5C, this->yaw); - jinjo->position_x = new_rotation[0] + this->position_x; - jinjo->position_y = new_rotation[1] + this->position_y; - jinjo->position_z = new_rotation[2] + this->position_z; + other->position_x = sp5C[0] + this->position_x; + other->position_y = sp5C[1] + this->position_y; + other->position_z = sp5C[2] + this->position_z; } }//L8038E39C } diff --git a/src/RBB/ch/boombox.c b/src/RBB/ch/boombox.c index 4d9d66c83..c33cbace4 100644 --- a/src/RBB/ch/boombox.c +++ b/src/RBB/ch/boombox.c @@ -15,8 +15,8 @@ typedef struct { f32 *unk0; f32 unk4; f32 unk8[3]; - f32 currentPosition[3]; - f32 targetPosition[3]; + f32 unk14[3]; + f32 unk20[3]; f32 unk2C; f32 unk30; s32 unk34; @@ -24,38 +24,29 @@ typedef struct { u8 unk39; }ActorLocal_RBB_8520; -void chBoomBox_setState(Actor *this, s32 arg1); -Actor *chBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chBoomBox_update(Actor *this); +void func_8038F190(Actor *this, s32 arg1); +Actor *func_8038F4B0(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void func_8038F618(Actor *this); /* .data */ f32 D_80390D80[2] = {1.8f, 1.0f}; -ActorInfo chBoomBoxSlow = { - MARKER_1B7_BOOM_BOX, ACTOR_2A4_BOOM_BOX_SLOW, ASSET_48C_MODEL_BOOM_BOX, - 0x0, NULL, - chBoomBox_update, NULL, chBoomBox_draw, +ActorInfo D_80390D88 = { + MARKER_1B7_BOOM_BOX, ACTOR_2A4_BOOM_BOX_SLOW, ASSET_48C_MODEL_BOOM_BOX, 0x0, NULL, + func_8038F618, NULL, func_8038F4B0, 0, 0, 0.0f, 0 }; -ActorInfo chBoomBoxFast = { - MARKER_1B7_BOOM_BOX, ACTOR_30D_BOOM_BOX_FAST, ASSET_48C_MODEL_BOOM_BOX, - 0x0, NULL, - chBoomBox_update, NULL, chBoomBox_draw, +ActorInfo D_80390DAC = { + MARKER_1B7_BOOM_BOX, ACTOR_30D_BOOM_BOX_FAST, ASSET_48C_MODEL_BOOM_BOX, 0x0, NULL, + func_8038F618, NULL, func_8038F4B0, 0, 0, 0.0f, 0 }; s32 RBB_D_80390DD0[3] = {0xDE, 0xA7, 0x71}; s32 D_80390DDC[4] = {0xFF, 0xFF, 0xFF, 0xFF}; -f32 D_80390DEC[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - -enum chboombox_state_e { - CH_BOOM_BOX_STATE_0_NOT_INIT, - CH_BOOM_BOX_STATE_1_UNK, - CH_BOOM_BOX_STATE_2_UNK, - CH_BOOM_BOX_STATE_3_EXPLODE -}; +f32 D_80390DEC[4] = {0.0f, 0.0f , 0.0f, 0.0f}; /* .bss */ f32 D_803912A0[3]; @@ -74,13 +65,13 @@ void func_8038E920(Actor *this){ void func_8038E92C(Actor *this){ ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; - if(this->state == CH_BOOM_BOX_STATE_2_UNK && local->unk34 == 0) + if(this->state == 2 && local->unk34 == 0) return; if(ml_timer_update( &local->unk30, time_getDelta())) - chBoomBox_setState(this, CH_BOOM_BOX_STATE_3_EXPLODE); + func_8038F190(this, 3); } -void chBoomBox_emitSmokeBeforeExplosion(Actor *this){ +void func_8038E998(Actor *this){ ParticleEmitter *other = partEmitMgr_newEmitter(2); f32 temp_f0; @@ -96,7 +87,7 @@ void chBoomBox_emitSmokeBeforeExplosion(Actor *this){ particleEmitter_emitN(other, 2); } -void chBoomBox_emitExplosion(Actor *this){ +void func_8038EAB4(Actor *this){ ParticleEmitter *other; func_802BB3DC(0, 60.0f, 0.9f); other = partEmitMgr_newEmitter(1); @@ -114,7 +105,7 @@ void chBoomBox_emitExplosion(Actor *this){ particleEmitter_emitN(other, 1); } -void chBoomBox_emitSmokeAfterExplosion(Actor *this){ +void func_8038EC14(Actor *this){ ParticleEmitter *other; other = partEmitMgr_newEmitter(6); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); @@ -130,7 +121,7 @@ void chBoomBox_emitSmokeAfterExplosion(Actor *this){ particleEmitter_emitN(other, 6); } -void chBoomBox_emitModelsAfterExplosion(Actor * actor, s32 arg1){ +void func_8038ED3C(Actor * actor, s32 arg1){ ParticleEmitter *other = partEmitMgr_newEmitter(0xa); particleEmitter_setAccelerationRange(other, 0.0f, -800.0f, 0.0f, 0.0f, -800.0f, 0.0f); particleEmitter_func_802EF9F8(other, 0.6f); @@ -150,77 +141,77 @@ int func_8038EE90(Actor *this){ f32 sp20[3]; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; - sp2C[0] = local->currentPosition[0]; - sp2C[1] = local->currentPosition[1]; - sp2C[2] = local->currentPosition[2]; + sp2C[0] = local->unk14[0]; + sp2C[1] = local->unk14[1]; + sp2C[2] = local->unk14[2]; - sp20[0] = local->targetPosition[0]; - sp20[1] = local->targetPosition[1]; - sp20[2] = local->targetPosition[2]; + sp20[0] = local->unk20[0]; + sp20[1] = local->unk20[1]; + sp20[2] = local->unk20[2]; sp2C[1] += 75.0f; sp20[1] += 75.0f; return func_803342AC(&sp2C, &sp20, 100.0f); } -bool chBoombox_isValidMovePosition(Actor *this, f32 position[3], f32 speed_multiplier){ - f32 position_diff[3]; - bool ceiling_exists; +int func_8038EF08(Actor *this, f32 position[3], f32 arg2){ + f32 sp54[3]; + int sp50; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; - f32 ceiling_check_position[3]; - f32 collision_radius; - f32 ceiling_collision_output[3]; + f32 sp40[3]; + f32 sp3C; + f32 sp30[3]; - position_diff[0] = position[0] - this->position_x; - position_diff[1] = position[1] - this->position_y; - position_diff[2] = position[2] - this->position_z; - if(180.0 < LENGTH_VEC3F(position_diff)) - ml_vec3f_set_length(position_diff, 150.0f); + sp54[0] = position[0] - this->position_x; + sp54[1] = position[1] - this->position_y; + sp54[2] = position[2] - this->position_z; + if(180.0 < LENGTH_VEC3F(sp54)) + ml_vec3f_set_length(sp54, 150.0f); - local->targetPosition[0] = position_diff[0] + this->position_x; - local->targetPosition[1] = position_diff[1] + this->position_y; - local->targetPosition[2] = position_diff[2] + this->position_z; - - local->targetPosition[1] = mapModel_getFloorY(local->targetPosition); - - ceiling_check_position[0] = local->targetPosition[0]; - ceiling_check_position[1] = local->targetPosition[1] + this->scale * 100.0f; - ceiling_check_position[2] = local->targetPosition[2]; - collision_radius = this->scale * 60.0f; - if(func_80309EB0(&ceiling_check_position, collision_radius, &ceiling_collision_output, 0)){ - ceiling_exists = true; + local->unk20[0] = sp54[0] + this->position_x; + local->unk20[1] = sp54[1] + this->position_y; + local->unk20[2] = sp54[2] + this->position_z; + + local->unk20[1] = mapModel_getFloorY(local->unk20); + + sp40[0] = local->unk20[0]; + sp40[1] = local->unk20[1] + this->scale*100.0f; + sp40[2] = local->unk20[2]; + sp3C = this->scale*60.0f; + if(func_80309EB0(&sp40, sp3C, &sp30, 0)){ + sp50 = 1; }else{ - ceiling_exists = false; + sp50 = 0; } - if( !func_80329210(this, &local->targetPosition) - || ((local->unk2C + 30.0f) < local->targetPosition[1]) - || ceiling_exists + if( !func_80329210(this, &local->unk20) + || ((local->unk2C + 30.0f) < local->unk20[1]) + || sp50 ){ - local->targetPosition[0] = this->position_x; - local->targetPosition[1] = this->position_y; - local->targetPosition[2] = this->position_z; + local->unk20[0] = this->position_x; + local->unk20[1] = this->position_y; + local->unk20[2] = this->position_z; if(local->unk39 < 3 && ++local->unk39 == 3){ local->unk39 = 0; - return false; + return 0; } }else{ local->unk34 = func_8038EE90(this); if(local->unk34 == 0){ - local->targetPosition[0] = this->position_x; - local->targetPosition[1] = this->position_y; - local->targetPosition[2] = this->position_z; + local->unk20[0] = this->position_x; + local->unk20[1] = this->position_y; + local->unk20[2] = this->position_z; } } - skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.1f, randf2(-0.1f, 0.1f) + (1.0 / speed_multiplier) * 0.4); + skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.1f, randf2(-0.1f, 0.1f) + (1.0/arg2)*0.4); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - local->currentPosition[0] = this->position_x; - local->currentPosition[1] = this->position_y; - local->currentPosition[2] = this->position_z; - return true; + local->unk14[0] = this->position_x; + local->unk14[1] = this->position_y; + local->unk14[2] = this->position_z; + return 1; } -void chBoomBox_setState(Actor *this, s32 next_state){ +void func_8038F190(Actor *this, s32 arg1){ f32 player_position[3]; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; @@ -231,68 +222,68 @@ void chBoomBox_setState(Actor *this, s32 next_state){ local->unk34 = false; } - if(next_state == CH_BOOM_BOX_STATE_1_UNK){ + if(arg1 == 1){ skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); }//L8038F204 - if(next_state == CH_BOOM_BOX_STATE_2_UNK){ - bool is_valid_move_position = false; + if(arg1 == 2){ + int sp3C = 0; if(func_80329210(this, &player_position)){ local->unk4 += 0.3; if(*local->unk0 < local->unk4) local->unk4 = *local->unk0; - is_valid_move_position = chBoombox_isValidMovePosition(this, player_position, local->unk4); + sp3C = func_8038EF08(this, player_position, local->unk4); }//L8038F28C - if(!is_valid_move_position){ + if(!sp3C){ func_8038E920(this); local->unk4 -= 0.5; if(local->unk4 < 0.5) local->unk4 = 0.5f; - chBoombox_isValidMovePosition(this, local->unk8, local->unk4); + func_8038EF08(this, local->unk8, local->unk4); } }//L8038F2FC - if(next_state == CH_BOOM_BOX_STATE_3_EXPLODE){ - chBoomBoxMinigameCtrl_countDec(); + if(arg1 == 3){ + func_8038FB6C(); actor_collisionOff(this); func_80324D54(0.0f, SFX_1B_EXPLOSION_1, 1.0f, 0x7d00, this->position, 1000.0f, 2000.0f); skeletalAnim_set(this->unk148, ASSET_148_ANIM_BOOMBOX_DIE, 0.2f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - chBoomBox_emitExplosion(this); - chBoomBox_emitSmokeAfterExplosion(this); - chBoomBox_emitModelsAfterExplosion(this, ASSET_53A_MODEL_SHRAPNAL_PIECE_EYE); - chBoomBox_emitModelsAfterExplosion(this, ASSET_53B_MODEL_SHRAPNAL_PIECE_SPIKE); - chBoomBox_emitModelsAfterExplosion(this, ASSET_53C_MODEL_SHRAPNAL_PIECE_PLATE); + func_8038EAB4(this); + func_8038EC14(this); + func_8038ED3C(this, 0x53a); + func_8038ED3C(this, 0x53b); + func_8038ED3C(this, 0x53c); func_80326310(this); this->unk10_1 = 0; func_8038E920(this); }//L8038F3C8 - this->state = next_state; + this->state = arg1; } void func_8038F3F0(ActorMarker *marker, ActorMarker *arg1){ Actor* actor = marker_getActor(marker); if(actor->state < 3){ - chBoomBox_setState(actor, CH_BOOM_BOX_STATE_3_EXPLODE); + func_8038F190(actor, 3); } } void func_8038F430(ActorMarker *marker, ActorMarker *arg1){ Actor* actor = marker_getActor(marker); - f32 player_position[3]; + f32 sp18[3]; if(actor->state < 3){ - player_getPosition(player_position); - if(ml_vec3f_distance(actor->position, player_position) < 300.0f) + player_getPosition(sp18); + if(ml_vec3f_distance(actor->position, sp18) < 300.0f) func_8028F55C(5, actor->marker); - chBoomBox_setState(actor, CH_BOOM_BOX_STATE_3_EXPLODE); + func_8038F190(actor, 3); }//L8038F4A4 } -Actor * chBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ +Actor * func_8038F4B0(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ Actor *actor; ActorLocal_RBB_8520 *local; s32 sp28[4]; @@ -301,10 +292,10 @@ Actor * chBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ actor = marker_getActor(marker); local = (ActorLocal_RBB_8520 *)&actor->local; - modelRender_setAppendageVisibility(1,2); - modelRender_setAppendageVisibility(3,1); - modelRender_setAppendageVisibility(6,1); - modelRender_setAppendageVisibility(7,1); + func_8033A45C(1,2); + func_8033A45C(3,1); + func_8033A45C(6,1); + func_8033A45C(7,1); if(local->unk30 > 0.0f && local->unk30 <= 1.0){ temp_f2 = 2*(3*local->unk30 - (s32)(3*local->unk30)); if (temp_f2 > 1.0f) @@ -322,18 +313,18 @@ Actor * chBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ return actor_draw(marker, gdl, mptr, arg3); } -void chBoomBox_update(Actor *this){ - f32 player_position[3]; +void func_8038F618(Actor *this){ + f32 sp7C[3]; int sp78; ActorLocal_RBB_8520 *local = (ActorLocal_RBB_8520 *)&this->local; f32 sp70 = time_getDelta(); - f32 prev_anim_progress; - f32 curr_anim_progress; - f32 this_position[3]; + f32 sp6C; + f32 sp68; + f32 sp5C[3]; f32 sp50[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; + f32 sp4C; + f32 sp48; + f32 sp44; f32 pad0; @@ -345,33 +336,33 @@ void chBoomBox_update(Actor *this){ local->unk8[2] = this->position_z; local->unk38 = 0; local->unk39 = 0; - local->unk0 = &D_80390D80[(this->modelCacheIndex == ACTOR_30D_BOOM_BOX_FAST)? 1 : 0]; + local->unk0 = &D_80390D80[(this->modelCacheIndex == 0x30d)? 1 : 0]; local->unk2C = mapModel_getFloorY(this->position); local->unk34 = 0; local->unk4 = 0.5f; local->unk30 = 0.0f; marker_setCollisionScripts(this->marker, func_8038F430, func_8038F3F0, func_8038F430); - chBoomBox_setState(this, CH_BOOM_BOX_STATE_1_UNK); + func_8038F190(this, 1); return; }//L8038F714 - player_getPosition(player_position); - sp78 = func_80329210(this, &player_position); + player_getPosition(sp7C); + sp78 = func_80329210(this, &sp7C); if(!local->unk38){ local->unk38 = true; - chBoomBoxMinigameCtrl_countInc(); + func_8038FB54(); } func_8038E92C(this); - if(this->state == CH_BOOM_BOX_STATE_1_UNK){ - if(sp78 && ml_vec3f_distance(this->position, player_position) < 500.0f){ - chBoomBox_setState(this, CH_BOOM_BOX_STATE_2_UNK); + if(this->state == 1){ + if(sp78 && ml_vec3f_distance(this->position, sp7C) < 500.0f){ + func_8038F190(this, 2); } }//L8038F7A0 - if(this->state == CH_BOOM_BOX_STATE_2_UNK){ - this_position[0] = this->position_x; - this_position[1] = this->position_y; - this_position[2] = this->position_z; + if(this->state == 2){ + sp5C[0] = this->position_x; + sp5C[1] = this->position_y; + sp5C[2] = this->position_z; if(0.0f != local->unk30 && !sp78) func_8038E920(this); @@ -379,30 +370,28 @@ void chBoomBox_update(Actor *this){ if(0.0f == local->unk30 && sp78) func_8038E910(this); - skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress, &curr_anim_progress); + skeletalAnim_getProgressRange(this->unk148, &sp6C, &sp68); - if(0.1 <= curr_anim_progress && curr_anim_progress <= 0.6) - ml_vec3f_interpolate_fast(this->position, local->currentPosition, local->targetPosition, (curr_anim_progress - 0.1) / 0.5); - if(prev_anim_progress < 0.6 && 0.6 <= curr_anim_progress) + if(0.1 <= sp68 && sp68 <= 0.6) + ml_vec3f_interpolate_fast(this->position, local->unk14, local->unk20, (sp68 - 0.1) /0.5 ); + if(sp6C < 0.6 && 0.6 <= sp68) func_8030E878(SFX_6C_LOCKUP_CLOSING, 1.1 + randf2(-0.05f, 0.05f), 20000, this->position, 500.0f, 1000.0f); - if(prev_anim_progress < 0.1 && 0.1 <= curr_anim_progress) - chBoomBox_emitSmokeBeforeExplosion(this); + if(sp6C < 0.1 && 0.1 <= sp68) + func_8038E998(this); - sp50[0] = local->targetPosition[0] - local->currentPosition[0]; - sp50[1] = local->targetPosition[1] - local->currentPosition[1]; - sp50[2] = local->targetPosition[2] - local->currentPosition[2]; + sp50[0] = local->unk20[0] - local->unk14[0]; + sp50[1] = local->unk20[1] - local->unk14[1]; + sp50[2] = local->unk20[2] - local->unk14[2]; - func_80258A4C( - D_80390DEC, this->yaw - 90.0f, sp50, - &horizontal_distance, &distance_in_front, &side_angle_radian); + func_80258A4C(D_80390DEC, this->yaw - 90.0f, sp50, &sp4C, &sp48, &sp44); - this->yaw += (side_angle_radian * 400.0f) * sp70; + this->yaw += (sp44*400.0f)*sp70; if(skeletalAnim_getLoopCount(this->unk148) > 0){ if(ml_vec3f_distance(this->position, local->unk8) < 10.0f){ - chBoomBox_setState(this, CH_BOOM_BOX_STATE_1_UNK); + func_8038F190(this, 1); }else{ - chBoomBox_setState(this, CH_BOOM_BOX_STATE_2_UNK); + func_8038F190(this, 2); } } }//L8038FA50 diff --git a/src/RBB/ch/bossboombox.c b/src/RBB/ch/bossboombox.c index 65192fb93..0970b3ba9 100644 --- a/src/RBB/ch/bossboombox.c +++ b/src/RBB/ch/bossboombox.c @@ -10,78 +10,74 @@ extern int func_803342AC(f32 (*)[3], f32(*)[3], f32); typedef struct{ - s16 actorId; + s16 unk0; //u8 pad2[2]; - f32 spawnPositionDelta; + f32 unk4; f32 unk8; u8 unkC; u8 unkD; u8 unkE; //u8 padF[1]; f32 unk10; - f32 volume; -} ActorLocal_ChBossBoomBoxInfo; + f32 unk14; +} Struct_RBB_5F80; typedef struct{ - ActorLocal_ChBossBoomBoxInfo *unk0; + Struct_RBB_5F80 *unk0; u8 unk4; u8 pad5[3]; - f32 currentPosition[3]; - f32 spawnPosition[3]; + f32 unk8[3]; + f32 unk14[3]; s32 unk20; f32 unk24; - f32 turnAngle; -} ActorLocal_ChBossBoomBox; + f32 unk28; +} ActorLocal_RBB_5F80; -void chBossBoomBox_setState(Actor *this, s32 new_state); +void RBB_func_8038CC9C(Actor *this, s32 new_state); void func_8038D7E8(ActorMarker *marker, s32 arg1); -Actor *chBossBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3); -void chBossBoomBox_update(Actor *this); +Actor *func_8038D638(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3); +void func_8038D8BC(Actor *this); /* .data */ -ActorLocal_ChBossBoomBoxInfo chBossBoomBoxTable[4] = { +Struct_RBB_5F80 D_80390B70[4] = { {ACTOR_281_BOSS_BOOM_BOX_LARGEST, 1.1f, 1.0f, 0x14, 0x01, 0x5, 0.9f, 0.8f}, {ACTOR_282_BOSS_BOOM_BOX_LARGE, 0.75f, 1.0f, 0xF, 0x02, 0x4, 1.1f, 0.9f}, {ACTOR_283_BOSS_BOOM_BOX_MEDIUM, 0.5f, 2.0f, 0xA, 0x02, 0x3, 1.3f, 1.0f}, {ACTOR_284_BOSS_BOOM_BOX_SMALL, 0.25f, 2.0f, 0x5, 0x02, 0x2, 1.5f, 1.1f}, }; -ActorInfo chBossBoomBoxLargest = { - MARKER_1A1_BOSS_BOOM_BOX_LARGEST, ACTOR_281_BOSS_BOOM_BOX_LARGEST, ASSET_428_MODEL_BOSS_BOOM_BOX, - 0x0, NULL, - chBossBoomBox_update, NULL, chBossBoomBox_draw, +ActorInfo RBB_D_80390BD0 = { + MARKER_1A1_BOSS_BOOM_BOX_LARGEST, ACTOR_281_BOSS_BOOM_BOX_LARGEST, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, + func_8038D8BC, NULL, func_8038D638, 0, 0, 0.0f, 0 }; -ActorInfo chBossBoomBoxLarge = { - MARKER_1A2_BOSS_BOOM_BOX_LARGE, ACTOR_282_BOSS_BOOM_BOX_LARGE, ASSET_428_MODEL_BOSS_BOOM_BOX, - 0x0, NULL, - chBossBoomBox_update, NULL, chBossBoomBox_draw, +ActorInfo D_80390BF4 = { + MARKER_1A2_BOSS_BOOM_BOX_LARGE, ACTOR_282_BOSS_BOOM_BOX_LARGE, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, + func_8038D8BC, NULL, func_8038D638, 0, 0, 0.0f, 0 }; -ActorInfo chBossBoomBoxMedium = { - MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, ACTOR_283_BOSS_BOOM_BOX_MEDIUM, ASSET_428_MODEL_BOSS_BOOM_BOX, - 0x0, NULL, - chBossBoomBox_update, NULL, chBossBoomBox_draw, +ActorInfo D_80390C18 = { + MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, ACTOR_283_BOSS_BOOM_BOX_MEDIUM, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, + func_8038D8BC, NULL, func_8038D638, 0, 0, 0.0f, 0 }; -ActorInfo chBossBoomBoxSmall = { - MARKER_1A4_BOSS_BOOM_BOX_SMALL, ACTOR_284_BOSS_BOOM_BOX_SMALL, ASSET_428_MODEL_BOSS_BOOM_BOX, - 0x0, NULL, - chBossBoomBox_update, NULL, chBossBoomBox_draw, +ActorInfo RBB_D_80390C3C = { + MARKER_1A4_BOSS_BOOM_BOX_SMALL, ACTOR_284_BOSS_BOOM_BOX_SMALL, ASSET_428_MODEL_BOSS_BOOM_BOX, 0x0, NULL, + func_8038D8BC, NULL, func_8038D638, 0, 0, 0.0f, 0 }; -s32 ChBossBoomBoxSmoke1RGB[3] = {0xDE, 0xA7, 0x71}; +s32 D_80390C60[3] = {0xDE, 0xA7, 0x71}; ParticleSettingsVelocityAcceleration D_80390C6C = { { {-200.0f, 200.0f, -200.0f}, {200.0f, 500.0f, 200.0f} }, { {0.0f, -800.0f, 0.0f}, {0.0f, -800.0f, 0.0f} } }; -s32 ChBossBoomBoxSmoke2RGB[3] = {0xDE, 0xA7, 0x71}; +s32 D_80390C9C[3] = {0xDE, 0xA7, 0x71}; ParticleSettingsVelocityAccelerationPosition D_80390CA8 = { { {-200.0f, 0.0f, -200.0f}, {200.0f, -50.0f, 200.0f} }, @@ -89,42 +85,30 @@ ParticleSettingsVelocityAccelerationPosition D_80390CA8 = { { {-10.0f, -10.0f, -10.0f}, {10.0f, 10.0f, 10.0f} } }; -enum chbossboombox_state_e { - CH_BOSS_BOOM_BOX_STATE_0_NOT_INIT, - CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER, - CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY, - CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER, - CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK, - CH_BOSS_BOOM_BOX_STATE_5_BREAKING, - CH_BOSS_BOOM_BOX_STATE_6_COMPLETE, - CH_BOSS_BOOM_BOX_STATE_7_UNK, - CH_BOSS_BOOM_BOX_STATE_8_FF_TIMER_RUN_OUT -}; - /* .bss */ u8 D_80391280; s32 pad_80391284; -f32 chBossBoomBoxJiggyPosition[3]; +f32 D_80391288[3]; /* .code */ void RBB_func_8038C370(ActorMarker *marker, s32 arg1){ Actor *actor = marker_getActor(marker); - chBossBoomBox_setState(actor, arg1); + RBB_func_8038CC9C(actor, arg1); } void func_8038C39C(Actor *this){ - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(local->unk0->unkE); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setFade(other, 0.0f, 0.1f); particleEmitter_setStartingFrameRange(other, 0, 7); particleEmitter_setDrawMode(other, 4); particleEmitter_setPosition(other, this->position); - particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 1, local->unk0->spawnPositionDelta * 3.0f); - particleEmitter_setFinalScaleRange(other, 3.0f*local->unk0->spawnPositionDelta, local->unk0->spawnPositionDelta * 7.0f); + particleEmitter_setStartingScaleRange(other, local->unk0->unk4*1, local->unk0->unk4*3.0f); + particleEmitter_setFinalScaleRange(other, 3.0f*local->unk0->unk4, local->unk0->unk4*7.0f); particleEmitter_setSpawnPositionRange(other, - local->unk0->spawnPositionDelta * -200.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * -200.0f, - local->unk0->spawnPositionDelta * 200.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * 200.0f + local->unk0->unk4*-200.0f, local->unk0->unk4*100.0f, local->unk0->unk4*-200.0f, + local->unk0->unk4*200.0f, local->unk0->unk4*100.0f, local->unk0->unk4*200.0f ); particleEmitter_setParticleVelocityRange(other, -50.0f, 100.0f, -50.0f, @@ -135,42 +119,43 @@ void func_8038C39C(Actor *this){ } void RBB_func_8038C538(Actor *this){ - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(3*local->unk0->unkE); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setFade(other, 0.1f, 0.3f); particleEmitter_setDrawMode(other, 4); particleEmitter_setStartingFrameRange(other, 0, 7); particleEmitter_setPosition(other, this->position); - particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 1, local->unk0->spawnPositionDelta * 6.0f); - particleEmitter_setFinalScaleRange(other, 0.5*local->unk0->spawnPositionDelta, local->unk0->spawnPositionDelta * 3.0f); + particleEmitter_setStartingScaleRange(other, local->unk0->unk4*1, local->unk0->unk4*6.0f); + particleEmitter_setFinalScaleRange(other, 0.5*local->unk0->unk4, local->unk0->unk4*3.0f); particleEmitter_setSpawnPositionRange(other, - local->unk0->spawnPositionDelta * -300.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * -300.0f, - local->unk0->spawnPositionDelta * 300.0f, local->unk0->spawnPositionDelta * 300.0f, local->unk0->spawnPositionDelta * 300.0f + local->unk0->unk4*-300.0f, local->unk0->unk4*100.0f, local->unk0->unk4*-300.0f, + local->unk0->unk4*300.0f, local->unk0->unk4*300.0f, local->unk0->unk4*300.0f ); particleEmitter_setParticleVelocityRange(other, -70.0f, 50.0f, -70.0f, 70.0f, 100.0f, 70.0f ); - particleEmitter_setRGB(other, ChBossBoomBoxSmoke1RGB); + particleEmitter_setRGB(other, D_80390C60); particleEmitter_setParticleLifeTimeRange(other, 3.0f, 4.0f); - particleEmitter_emitN(other, 3 * local->unk0->unkE); + particleEmitter_emitN(other, 3*local->unk0->unkE); + } void RBB_func_8038C70C(Actor *this){ - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(0xa); particleEmitter_func_802EF9F8(other, 0.6f); particleEmitter_func_802EFA18(other, 3); particleEmitter_setDrawMode(other, 4); - particleEmitter_setModel(other, ASSET_427_MODEL_WOODEN_PLANK); + particleEmitter_setModel(other, 0x427); particleEmitter_setSpawnPositionRange(other, - local->unk0->spawnPositionDelta * -300.0f, local->unk0->spawnPositionDelta * 100.0f, local->unk0->spawnPositionDelta * -300.0f, - local->unk0->spawnPositionDelta * 300.0f, local->unk0->spawnPositionDelta * 200.0f, local->unk0->spawnPositionDelta * 300.0f + local->unk0->unk4 * -300.0f, local->unk0->unk4 * 100.0f, local->unk0->unk4 * -300.0f, + local->unk0->unk4 * 300.0f, local->unk0->unk4 * 200.0f, local->unk0->unk4 * 300.0f ); particleEmitter_setPosition(other, this->position); - particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 0.3, local->unk0->spawnPositionDelta*0.8); + particleEmitter_setStartingScaleRange(other, local->unk0->unk4*0.3, local->unk0->unk4*0.8); particleEmitter_setAngularVelocityRange(other, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f @@ -183,24 +168,24 @@ void RBB_func_8038C70C(Actor *this){ } void func_8038C8A8(Actor * this){ - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; ParticleEmitter *other = partEmitMgr_newEmitter(5); - f32 particle_position[3]; + f32 sp24[3]; - player_getPosition(particle_position); - particle_position[1] += 50.0f; + player_getPosition(sp24); + sp24[1] += 50.0f; particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setFade(other, 0.0, 0.5f); particleEmitter_setDrawMode(other, 4); particleEmitter_setStartingFrameRange(other, 0, 7); - particleEmitter_setPosition(other, particle_position); - particleEmitter_setStartingScaleRange(other, local->unk0->spawnPositionDelta * 1, local->unk0->spawnPositionDelta * 3.0f); - particleEmitter_setFinalScaleRange(other, local->unk0->spawnPositionDelta * 3.0f, local->unk0->spawnPositionDelta * 6.0f); + particleEmitter_setPosition(other, sp24); + particleEmitter_setStartingScaleRange(other, local->unk0->unk4*1, local->unk0->unk4*3.0f); + particleEmitter_setFinalScaleRange(other, local->unk0->unk4*3.0f, local->unk0->unk4*6.0f); particleEmitter_setVelocityAccelerationAndPositionRanges(other, &D_80390CA8); particleEmitter_setParticleLifeTimeRange(other, 1.0f, 2.0f); - particleEmitter_setRGB(other, ChBossBoomBoxSmoke2RGB); + particleEmitter_setRGB(other, D_80390C9C); particleEmitter_emitN(other, 5); } @@ -209,17 +194,17 @@ void chbossboombox_respawnJiggy(s32 position_x, s32 position_y, s32 position_z){ if(jiggy) marker_despawn(jiggy->marker); - chBossBoomBoxJiggyPosition[0] = (f32)position_x; - chBossBoomBoxJiggyPosition[1] = (f32)(position_y + 0x28); - chBossBoomBoxJiggyPosition[2] = (f32)position_z; - jiggy_spawn(JIGGY_56_RBB_BOSS_BOOM_BOX, chBossBoomBoxJiggyPosition); + D_80391288[0] = (f32)position_x; + D_80391288[1] = (f32)(position_y + 0x28); + D_80391288[2] = (f32)position_z; + jiggy_spawn(JIGGY_56_RBB_BOSS_BOOM_BOX, D_80391288); } void func_8038CA70(Actor *this, f32(*arg1)[3]){ f32 tmp_f; - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; - tmp_f = local->unk0->spawnPositionDelta * 300.0f; + tmp_f = local->unk0->unk4 * 300.0f; if( (*arg1)[0] - tmp_f < -1400.0f) (*arg1)[0] = -1400.0f + tmp_f; @@ -236,7 +221,7 @@ void func_8038CA70(Actor *this, f32(*arg1)[3]){ } void func_8038CB34(ActorMarker *marker, enum asset_e arg1, s32 arg2){ - comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, -1, 300); + comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, -1, 0x12C); } void func_8038CB68(ActorMarker *marker, enum asset_e arg1, s32 arg2){ @@ -255,52 +240,55 @@ void chbossboombox_hideJiggy(void){ int RBB_func_8038CBF0(Actor *this){ f32 sp2C[3]; f32 sp20[3]; - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; - sp2C[0] = local->currentPosition[0]; - sp2C[1] = local->currentPosition[1]; - sp2C[2] = local->currentPosition[2]; + sp2C[0] = local->unk8[0]; + sp2C[1] = local->unk8[1]; + sp2C[2] = local->unk8[2]; - sp20[0] = local->spawnPosition[0]; - sp20[1] = local->spawnPosition[1]; - sp20[2] = local->spawnPosition[2]; + sp20[0] = local->unk14[0]; + sp20[1] = local->unk14[1]; + sp20[2] = local->unk14[2]; + + sp2C[1] += 300.0f * local->unk0->unk4; + sp20[1] += 300.0f * local->unk0->unk4; + return func_803342AC(&sp2C, &sp20, local->unk0->unk4 * 400.0f); - sp2C[1] += 300.0f * local->unk0->spawnPositionDelta; - sp20[1] += 300.0f * local->unk0->spawnPositionDelta; - return func_803342AC(&sp2C, &sp20, local->unk0->spawnPositionDelta * 400.0f); } -void chBossBoomBox_setState(Actor *this, s32 new_state){ - f32 player_position[3]; +void RBB_func_8038CC9C(Actor *this, s32 new_state){ + f32 sp8C[3]; f32 sp80[3]; - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; int i; f32 pad; - f32 spawn_position[3]; - f32 position_delta; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; - - player_getPosition(player_position); + f32 sp68[3]; + f32 player_position; + f32 sp60; + f32 sp5C; + f32 sp58; + + + + player_getPosition(sp8C); - player_position[1] = 0.0f; + sp8C[1] = 0.0f; - sp80[0] = player_position[0] - this->position_x; - sp80[1] = player_position[1] - this->position_y; - sp80[2] = player_position[2] - this->position_z; - if(this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY){ + sp80[0] = sp8C[0] - this->position_x; + sp80[1] = sp8C[1] - this->position_y; + sp80[2] = sp8C[2] - this->position_z; + if(this->state == 2){ chbossboombox_hideJiggy(); } - if(this->state == CH_BOSS_BOOM_BOX_STATE_7_UNK){ + if(this->state == 7){ actor_collisionOn(this); } - local->currentPosition[0] = this->position_x; - local->currentPosition[1] = this->position_y; - local->currentPosition[2] = this->position_z; - local->unk24 = local->turnAngle = this->yaw; + local->unk8[0] = this->position_x; + local->unk8[1] = this->position_y; + local->unk8[2] = this->position_z; + local->unk24 = local->unk28 = this->yaw; this->state = new_state; if(local->unk20){ @@ -308,13 +296,13 @@ void chBossBoomBox_setState(Actor *this, s32 new_state){ local->unk20 = 0; } - if(this->state == CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER){ + if(this->state == 1){ skeletalAnim_set(this->unk148, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR, 0.0f, 2.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_4_STOPPED); } - if(this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY){ - func_8025A58C(0, 4000); + if(this->state == 2){ + func_8025A58C(0, 0xfa0); coMusicPlayer_playMusic(COMUSIC_62_RBB_BOOMBOX, -1); func_8025AABC(COMUSIC_62_RBB_BOOMBOX); skeletalAnim_set(this->unk148, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR, 0.0f, 2.4f); @@ -333,46 +321,44 @@ void chBossBoomBox_setState(Actor *this, s32 new_state){ timedFunc_set_2(2.4f, (GenFunction_2)RBB_func_8038C370, (uintptr_t)this->marker, 3); } else{//L8038CEFC - timedFunc_set_3(2.4f, (GenFunction_3)comusic_8025AB44, COMUSIC_62_RBB_BOOMBOX, 8000, 300); - func_80324DBC(2.4f, VER_SELECT(ASSET_B9E_DIALOG_BOSS_BOOM_BOX_MEET, 0x973, 0, 0), 4, NULL, this->marker, func_8038CB34, func_8038CB68); + timedFunc_set_3(2.4f, (GenFunction_3)comusic_8025AB44, COMUSIC_62_RBB_BOOMBOX, 0x1f40, 0x12C); + func_80324DBC(2.4f, ASSET_B9E_DIALOG_BOSS_BOOM_BOX_MEET, 4, NULL, this->marker, func_8038CB34, func_8038CB68); } }//L8038CF60 - if( this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER - || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK) - { - func_8030E878(SFX_3F2_BOING, local->unk0->volume, 28000, this->position, 500.0f, 1000.0f); - skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2f, (1.0 / (local->unk0->unk8) * randf2(1.0f, 1.1f))); + if(this->state == 3 || this->state == 4){ + func_8030E878(0x3f2, local->unk0->unk14, 0x6d60, this->position, 500.0f, 1000.0f); + skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2f, (1.0/(local->unk0->unk8)*randf2(1.0f, 1.1f))); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - ml_vec3f_set_length(sp80, (this->state == 4)? -0x32 * (2 + func_80326218()) : 300.0f / local->unk0->unk8); - local->spawnPosition[0] = sp80[0] + this->position_x; - local->spawnPosition[1] = sp80[1] + this->position_y; - local->spawnPosition[2] = sp80[2] + this->position_z; - local->spawnPosition[1] = 0.0f; - func_8038CA70(this, &local->spawnPosition); + ml_vec3f_set_length(sp80, (this->state == 4)? -0x32*(2 + func_80326218()) : 300.0f/local->unk0->unk8); + local->unk14[0] = sp80[0] + this->position_x; + local->unk14[1] = sp80[1] + this->position_y; + local->unk14[2] = sp80[2] + this->position_z; + local->unk14[1] = 0.0f; + func_8038CA70(this, &local->unk14); }//L8038D0B8 - if(this->state == CH_BOSS_BOOM_BOX_STATE_5_BREAKING){ + if(this->state == 5){ actor_collisionOff(this); - timed_playSfx(0.2f, SFX_D9_WOODEN_CRATE_BREAKING_1, 0.9f, 30000); + timed_playSfx(0.2f, SFX_D9_WOODEN_CRATE_BREAKING_1, 0.9f, 0x7530); skeletalAnim_set(this->unk148, ASSET_148_ANIM_BOOMBOX_DIE, 0.2f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); ml_vec3f_set_length(sp80, -300.f); - local->spawnPosition[0] = sp80[0] + this->position_x; - local->spawnPosition[1] = sp80[1] + this->position_y; - local->spawnPosition[2] = sp80[2] + this->position_z; - local->spawnPosition[1] = 0.0f; - func_8038CA70(this, &local->spawnPosition); + local->unk14[0] = sp80[0] + this->position_x; + local->unk14[1] = sp80[1] + this->position_y; + local->unk14[2] = sp80[2] + this->position_z; + local->unk14[1] = 0.0f; + func_8038CA70(this, &local->unk14); RBB_func_8038C70C(this); RBB_func_8038C538(this); }//L8038D17C - if(this->state == CH_BOSS_BOOM_BOX_STATE_6_COMPLETE){ + if(this->state == 6){ func_80326310(this); - if(local->unk0->actorId == ACTOR_284_BOSS_BOOM_BOX_SMALL){ + if(local->unk0->unk0 == ACTOR_284_BOSS_BOOM_BOX_SMALL){ if(++D_80391280 == 8){ - func_8025A58C(-1, 400); - comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, 0, 400); + func_8025A58C(-1, 0x190); + comusic_8025AB44(COMUSIC_62_RBB_BOOMBOX, 0, 0x190); func_8025AABC(COMUSIC_62_RBB_BOOMBOX); if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ item_set(ITEM_6_HOURGLASS, 0); @@ -381,116 +367,101 @@ void chBossBoomBox_setState(Actor *this, s32 new_state){ } else{//L8038D220 timedFunc_set_3(0.0f, (GenFunction_3)chbossboombox_respawnJiggy, (s32)this->position_x, (s32)this->position_y, (s32)this->position_z); - gcdialog_showDialog(VER_SELECT(ASSET_B9F_DIALOG_BOSS_BOOM_BOX_COMPLETE, 0x974, 0, 0), 4, 0, 0, 0, 0); + gcdialog_showDialog(ASSET_B9F_DIALOG_BOSS_BOOM_BOX_COMPLETE, 4, 0, 0, 0, 0); } }//L8038D278 } else{//L8038D28C - spawn_position[0] = this->position_x + 200.0f * local->unk0->spawnPositionDelta; - spawn_position[1] = this->position_y + 80.0f * local->unk0->spawnPositionDelta; - spawn_position[2] = this->position_z; - __spawnQueue_add_4( - (GenFunction_4)spawnQueue_actor_f32, - local->unk0->actorId + 1, - reinterpret_cast(s32, spawn_position[0]), - reinterpret_cast(s32, spawn_position[1]), - reinterpret_cast(s32, spawn_position[2])); - - spawn_position[0] = this->position_x - 200.0f * local->unk0->spawnPositionDelta; - spawn_position[1] = this->position_y + 80.0f * local->unk0->spawnPositionDelta; - spawn_position[2] = this->position_z; - __spawnQueue_add_4( - (GenFunction_4)spawnQueue_actor_f32, - local->unk0->actorId + 1, - reinterpret_cast(s32, spawn_position[0]), - reinterpret_cast(s32, spawn_position[1]), - reinterpret_cast(s32, spawn_position[2])); + sp68[0] = this->position_x + 200.0f*local->unk0->unk4; + sp68[1] = this->position_y + 80.0f*local->unk0->unk4; + sp68[2] = this->position_z; + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, local->unk0->unk0 + 1, reinterpret_cast(s32, sp68[0]), reinterpret_cast(s32, sp68[1]), reinterpret_cast(s32, sp68[2])); + + sp68[0] = this->position_x - 200.0f*local->unk0->unk4; + sp68[1] = this->position_y + 80.0f*local->unk0->unk4; + sp68[2] = this->position_z; + __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, local->unk0->unk0 + 1, reinterpret_cast(s32, sp68[0]), reinterpret_cast(s32, sp68[1]), reinterpret_cast(s32, sp68[2])); } }//L8038D378 - if(this->state == CH_BOSS_BOOM_BOX_STATE_7_UNK){ + if(this->state == 7){ actor_collisionOff(this); func_803262E4(this); skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.0f, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - local->currentPosition[0] = this->position_x; - local->currentPosition[1] = this->position_y; - local->currentPosition[2] = this->position_z; + local->unk8[0] = this->position_x; + local->unk8[1] = this->position_y; + local->unk8[2] = this->position_z; - local->spawnPosition[0] = this->position_x; - local->spawnPosition[1] = this->position_y; - local->spawnPosition[2] = this->position_z; + local->unk14[0] = this->position_x; + local->unk14[1] = this->position_y; + local->unk14[2] = this->position_z; local->unk20 = RBB_func_8038CBF0(this); }//L8038D3FC - if(this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER - || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK - || this->state == CH_BOSS_BOOM_BOX_STATE_5_BREAKING) - { + if(this->state == 3 || this->state == 4 || this->state == 5){ local->unk20 = RBB_func_8038CBF0(this); if( local->unk20 == 0){ - position_delta = local->unk0->spawnPositionDelta * 300.0f; + player_position = local->unk0->unk4*300.0f; for(i = 0; i < 10; i++){ - local->spawnPosition[0] = local->currentPosition[0] + randf2(-position_delta, position_delta); - local->spawnPosition[1] = local->spawnPosition[1]; - local->spawnPosition[2] = local->currentPosition[2] + randf2(-position_delta, position_delta); - func_8038CA70(this, &local->spawnPosition); + local->unk14[0] = local->unk8[0] + randf2(-player_position, player_position); + local->unk14[1] = local->unk14[1]; + local->unk14[2] = local->unk8[2] + randf2(-player_position, player_position); + func_8038CA70(this, &local->unk14); local->unk20 = RBB_func_8038CBF0(this); if(local->unk20) break; } - if(i == 10){ - local->spawnPosition[0] = local->currentPosition[0]; - local->spawnPosition[2] = local->currentPosition[2]; - local->spawnPosition[1] = 0.0f; + if(i == 0xa){ + local->unk14[0] = local->unk8[0]; + local->unk14[2] = local->unk8[2]; + local->unk14[1] = 0.0f; } } }//L8038D4DC - if(this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER){ - func_80258A4C( - this->position, this->yaw - 90.0f, player_position, - &horizontal_distance, &distance_in_front, &side_angle_radian); - if(0.7 < side_angle_radian) - local->turnAngle += 90.0f; - else if(side_angle_radian < -0.7){ - local->turnAngle -= 90.0f; + if(this->state == 3){ + func_80258A4C(this->position, this->yaw - 90.0f, sp8C, &sp60, &sp5C, &sp58); + if(0.7 < sp58) + local->unk28 += 90.0f; + else if(sp58 < -0.7){ + local->unk28 -= 90.0f; } } } -void chBossBoomBox_hitPlayer(ActorMarker *marker, ActorMarker *arg1){ +void func_8038D590(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK); + RBB_func_8038CC9C(actor, 4); } -void chBossBoomBox_ow(ActorMarker *marker, ActorMarker *arg1){ +void func_8038D5BC(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &actor->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &actor->local; - gcsfx_playWithPitch(SFX_3F5_UNKNOWN, local->unk0->unk10, 20000); - chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK); + gcsfx_playWithPitch(0x3f5, local->unk0->unk10, 0x4e20); + RBB_func_8038CC9C(actor, 4); func_8038C8A8(actor); } -void chBossBoomBox_die(ActorMarker *marker, ActorMarker *other){ +void func_8038D608(ActorMarker *marker, ActorMarker *other){ func_8038D7E8(marker, other->id == 1); } -Actor *chBossBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3){ +Actor *func_8038D638(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg3){ f32 sp3C[3]; Actor *actor = marker_getActorAndRotation(marker, sp3C); - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &actor->local; - modelRender_setAppendageVisibility(1, local->unk0->unkD); + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &actor->local; + func_8033A45C(1, local->unk0->unkD); if(local->unk0->unkD == 1){ - modelRender_setAppendageVisibility(2, (actor->state == 4)? 2: 1); - modelRender_setAppendageVisibility(4, (actor->state == 4)? 2: 1); - modelRender_setAppendageVisibility(5, (actor->state == 4)? 2: 1); + func_8033A45C(2, (actor->state == 4)? 2: 1); + func_8033A45C(4, (actor->state == 4)? 2: 1); + func_8033A45C(5, (actor->state == 4)? 2: 1); }//L8038D714 else{ - modelRender_setAppendageVisibility(3, (actor->state == 4)? 2: 1); - modelRender_setAppendageVisibility(6, (actor->state == 4)? 2: 1); - modelRender_setAppendageVisibility(7, (actor->state == 4)? 2: 1); + func_8033A45C(3, (actor->state == 4)? 2: 1); + func_8033A45C(6, (actor->state == 4)? 2: 1); + func_8033A45C(7, (actor->state == 4)? 2: 1); } modelRender_setPreDrawCallback( (model_render_pre_draw_callback_f)actor_predrawMethod, (void *)actor); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); @@ -501,15 +472,15 @@ Actor *chBossBoomBox_draw(ActorMarker *marker, Gfx **gdl, Mtx ** mptr, Vtx **arg void func_8038D7E8(ActorMarker *marker, s32 arg1){ Actor *actor = marker_getActor(marker); - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &actor->local; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &actor->local; sfx_playFadeShorthandDefault(SFX_1E_HITTING_AN_ENEMY_2, 1.0f, 20000, actor->position, 1000, 2000); gcsfx_playWithPitch(SFX_D7_GRABBA_DEATH, local->unk0->unk10, 0x7530); local->unk4 += (arg1) ? 1 : 5; if(local->unk4 >= local->unk0->unkC) - chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_5_BREAKING); + RBB_func_8038CC9C(actor, 5); else{ - chBossBoomBox_setState(actor, CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK); + RBB_func_8038CC9C(actor, 4); } if(!arg1) @@ -519,13 +490,13 @@ void func_8038D7E8(ActorMarker *marker, s32 arg1){ void func_8038D8B4(Actor *actor){} -void chBossBoomBox_update(Actor *this){ +void func_8038D8BC(Actor *this){ f32 player_position[3]; - ActorLocal_ChBossBoomBox *local = (ActorLocal_ChBossBoomBox *) &this->local; - f32 prev_anim_progress1; - f32 curr_anim_progress1; - f32 prev_anim_progress2; - f32 curr_anim_progress2; + ActorLocal_RBB_5F80 *local = (ActorLocal_RBB_5F80 *) &this->local; + f32 sp5C; + f32 sp58; + f32 sp54; + f32 sp50; f32 sp4C; f32 tmp_f2; f32 pad; @@ -533,23 +504,23 @@ void chBossBoomBox_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - local->unk0 = &chBossBoomBoxTable[this->marker->id - MARKER_1A1_BOSS_BOOM_BOX_LARGEST]; + local->unk0 = &D_80390B70[this->marker->id - 0x1A1]; local->unk4 = 0; local->unk20 = 0; this->marker->propPtr->unk8_3 = 0; - this->scale = local->unk0->spawnPositionDelta; - if(local->unk0 == chBossBoomBoxTable){ + this->scale = local->unk0->unk4; + if(local->unk0 == D_80390B70){ this->yaw = 270.0f; } - marker_setCollisionScripts(this->marker, chBossBoomBox_hitPlayer, chBossBoomBox_ow, chBossBoomBox_die); + marker_setCollisionScripts(this->marker, func_8038D590, func_8038D5BC, func_8038D608); marker_setFreeMethod(this->marker, func_8038D8B4); - if(local->unk0->actorId == ACTOR_281_BOSS_BOOM_BOX_LARGEST){ - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER); + if(local->unk0->unk0 == ACTOR_281_BOSS_BOOM_BOX_LARGEST){ + RBB_func_8038CC9C(this, 1); D_80391280 = 0; } else{ - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_7_UNK); + RBB_func_8038CC9C(this, 7); } if(jiggyscore_isSpawned(JIGGY_56_RBB_BOSS_BOOM_BOX) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) @@ -562,82 +533,79 @@ void chBossBoomBox_update(Actor *this){ chbossboombox_hideJiggy(); skeletalAnim_set(this->unk148, ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR, 0.0f, 2.4f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - this->state = CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY; + this->state = 2; } return; } player_getPosition(player_position); - if(this->state == CH_BOSS_BOOM_BOX_STATE_1_WAITING_FOR_PLAYER){ + if(this->state == 1){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(volatileFlag_get(VOLATILE_FLAG_3)){ - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY); + RBB_func_8038CC9C(this, 2); } } else{//L8038DAA8 if(ml_vec3f_distance(this->position, player_position) < 1200.0f){ - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY); + RBB_func_8038CC9C(this, 2); } } }//L8038DAD8 - if(this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY){ + if(this->state == 2){ if(skeletalAnim_getAnimId(this->unk148) == ASSET_146_ANIM_BOSS_BOOMBOX_APPEAR && skeletalAnim_getLoopCount(this->unk148) > 0){ skeletalAnim_set(this->unk148, ASSET_147_ANIM_BOOMBOX_MOVE, 0.2, 1.0f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); } }//L8038DB30 - if( this->state == CH_BOSS_BOOM_BOX_STATE_2_HIDES_JIGGY - || this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER - || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK){ + if( this->state == 2 || this->state == 3 || this->state == 4){ if(skeletalAnim_getAnimId(this->unk148) == ASSET_147_ANIM_BOOMBOX_MOVE){ - skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress1, &curr_anim_progress1); - if(prev_anim_progress1 < 0.6 && 0.6 <= curr_anim_progress1){ - func_8030E878(SFX_6C_LOCKUP_CLOSING, randf2(-0.05f, 0.05f) + local->unk0->volume, 20000, this->position, 500.0f, 1000.0f); + skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); + if(sp5C < 0.6 && 0.6 <= sp58){ + func_8030E878(SFX_6C_LOCKUP_CLOSING, randf2(-0.05f, 0.05f) + local->unk0->unk14, 20000, this->position, 500.0f, 1000.0f); }//L8038DC04 - if(prev_anim_progress1 < 0.1 && 0.1 <= curr_anim_progress1){ + if(sp5C < 0.1 && 0.1 <= sp58){ func_8038C39C(this); } } }//L8038DC48 - if(this->state == CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER - || this->state == CH_BOSS_BOOM_BOX_STATE_4_PUSH_BACK){ + if(this->state == 3 || this->state == 4){ if(volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ if(item_empty(ITEM_0_HOURGLASS_TIMER)){ volatileFlag_set(VOLATILE_FLAG_3, 0); volatileFlag_set(VOLATILE_FLAG_5_FF_MINIGAME_WON, 0); - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_8_FF_TIMER_RUN_OUT); + RBB_func_8038CC9C(this, 8); } } - skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress2, &curr_anim_progress2); - if(0.1 <= curr_anim_progress2 && curr_anim_progress2 <= 0.6){ - sp4C = (curr_anim_progress2 - 0.1) / 0.5; - ml_vec3f_interpolate_fast(this->position, local->currentPosition, local->spawnPosition, sp4C); - this->yaw = local->unk24 + sp4C * (local->turnAngle - local->unk24); + skeletalAnim_getProgressRange(this->unk148, &sp54, &sp50); + if(0.1 <= sp50 && sp50 <= 0.6){ + sp4C = (sp50 - 0.1)/0.5; + ml_vec3f_interpolate_fast(this->position, local->unk8, local->unk14, sp4C); + this->yaw = local->unk24 + sp4C*(local->unk28 - local->unk24); } if(skeletalAnim_getLoopCount(this->unk148) > 0) - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER); + RBB_func_8038CC9C(this, 3); }//L8038DD64 - if(this->state == CH_BOSS_BOOM_BOX_STATE_5_BREAKING){ + if(this->state == 5){ if(skeletalAnim_getLoopCount(this->unk148) > 0){ - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_6_COMPLETE); + RBB_func_8038CC9C(this, 6); }else{ tmp_f2 = skeletalAnim_getProgress(this->unk148); if(tmp_f2 <= 0.3) - tmp_f2 = tmp_f2 / 0.3; + tmp_f2 = tmp_f2/0.3; else tmp_f2 = 1.0f; - ml_vec3f_interpolate_fast(this->position, local->currentPosition, local->spawnPosition, tmp_f2); + ml_vec3f_interpolate_fast(this->position, local->unk8, local->unk14, tmp_f2); } }//L8038DE10 - if(this->state == CH_BOSS_BOOM_BOX_STATE_7_UNK){ + if(this->state == 7){ if(skeletalAnim_getLoopCount(this->unk148) > 0) - chBossBoomBox_setState(this, CH_BOSS_BOOM_BOX_STATE_3_ATTACK_PLAYER); + RBB_func_8038CC9C(this, 3); } } diff --git a/src/RBB/ch/bossboomboxctrl.c b/src/RBB/ch/bossboomboxctrl.c index c29948315..b81a46f76 100644 --- a/src/RBB/ch/bossboomboxctrl.c +++ b/src/RBB/ch/bossboomboxctrl.c @@ -7,18 +7,12 @@ void chBossBoomBoxCtrl_update(Actor *this); /* .data */ -ActorInfo chBossBoomBoxCtrl = { - MARKER_1C0_BOSS_BOOMBOX_CTRL, ACTOR_2AD_BOSS_BOOMBOX_CTRL, 0x0, - 0x0, NULL, +ActorInfo RBB_D_80390CF0 = { + 0x1C0, 0x2AD, 0x0, 0x0, NULL, chBossBoomBoxCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; -enum bossboomboxctrl_state_e { - BOSS_BOOM_BOX_CTRL_STATE_0_NOT_INIT, - BOSS_BOOM_BOX_CTRL_STATE_1_INIT -}; - /* .code */ void __chBossBoomBoxCtrl_setState(Actor *this, s32 new_state){ this->state = new_state; @@ -28,13 +22,11 @@ void chBossBoomBoxCtrl_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - if(jiggyscore_isSpawned(JIGGY_56_RBB_BOSS_BOOM_BOX) - && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) - { + if(jiggyscore_isSpawned(JIGGY_56_RBB_BOSS_BOOM_BOX) && !volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)){ marker_despawn(this->marker); - } else { + }else{ __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_281_BOSS_BOOM_BOX_LARGEST, reinterpret_cast(s32,this->position_x), reinterpret_cast(s32,this->position_y), reinterpret_cast(s32,this->position_z)); - __chBossBoomBoxCtrl_setState(this, BOSS_BOOM_BOX_CTRL_STATE_1_INIT); + __chBossBoomBoxCtrl_setState(this, 1); } }//L8038DEF4 } diff --git a/src/RBB/ch/cog.c b/src/RBB/ch/cog.c index e8dd085ac..38b43adca 100644 --- a/src/RBB/ch/cog.c +++ b/src/RBB/ch/cog.c @@ -10,61 +10,50 @@ typedef struct { u8 sfxsourceIdx; }ActorLocal_RBB_27E0; -void chRBBCog_update(Actor *this); +void func_80388C20(Actor *this); /* .data */ -ActorInfo chRBBSmallCog = { - MARKER_18B_RBB_SMALL_COG, ACTOR_17B_RBB_SMALL_COG, ASSET_409_MODEL_RBB_SMALL_COG, - 0x0, NULL, - chRBBCog_update, NULL, actor_draw, +ActorInfo D_803903B0 = { + 0x18B, 0x17B, 0x409, 0x0, NULL, + func_80388C20, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chRBBMediumCog = { - MARKER_18C_RBB_MEDIUM_COG, ACTOR_17C_RBB_MEDIUM_COG, ASSET_40A_MODEL_RBB_MEDIUM_COG, - 0x0, NULL, - chRBBCog_update, NULL, actor_draw, +ActorInfo D_803903D4 = { + 0x18C, 0x17C, 0x40A, 0x0, NULL, + func_80388C20, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chRBBLargeCog = { - MARKER_18D_RBB_LARGE_COG, ACTOR_17D_RBB_LARGE_COG, ASSET_40B_MODEL_RBB_LARGE_COG, - 0x0, NULL, - chRBBCog_update, NULL, actor_draw, +ActorInfo D_803903F8 = { + 0x18D, 0x17D, 0x40B, 0x0, NULL, + func_80388C20, NULL, actor_draw, 0, 0, 0.0f, 0 }; -f32 chRBBCogRotateRates[3] = {40.0f, -30.0f, 20.0f}; //rotation rates (deg/sec); - -enum chrbbcog_state_e { - CH_RBB_COG_STATE_0_NOT_INIT, - CH_RBB_COG_STATE_1_INIT -}; +f32 D_8039041C[3] = {40.0f, -30.0f, 20.0f}; //rotation rates (deg/sec); /* .code */ -void chRBBCog_setState(Actor *this, s32 next_state){ - this->state = next_state; +void func_80388BD0(Actor *this, s32 arg1){ + this->state = arg1; } -void chRBBCog_free(Actor *actor){ +void func_80388BE8(Actor *actor){ ActorLocal_RBB_27E0 *local = (ActorLocal_RBB_27E0 *)&actor->local; - - if(actor->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ + if(actor->modelCacheIndex == 0x17b){ sfxsource_freeSfxsourceByIndex(local->sfxsourceIdx); } } -void chRBBCog_update(Actor *this){ +void func_80388C20(Actor *this){ ActorLocal_RBB_27E0 *local = (ActorLocal_RBB_27E0 *)&this->local; - f32 time_delta = time_getDelta(); - + f32 sp28 = time_getDelta(); if(!this->volatile_initialized){ actor_collisionOff(this); this->marker->propPtr->unk8_3 = 1; - this->marker->actorFreeFunc = chRBBCog_free; + this->marker->actorFreeFunc = func_80388BE8; this->volatile_initialized = true; - - if(this->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ + if(this->modelCacheIndex == 0x17B){ local->sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_set_fade_distances(local->sfxsourceIdx, 1000.0f, 2000.0f); sfxsource_set_position(local->sfxsourceIdx, this->position); @@ -74,26 +63,24 @@ void chRBBCog_update(Actor *this){ sfxsource_setSampleRate(local->sfxsourceIdx, 0); sfxSource_func_8030E2C4(local->sfxsourceIdx); }//L80388CFC - - if(this->state == CH_RBB_COG_STATE_0_NOT_INIT){ - if(this->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ + if(this->state == 0){ + if(this->modelCacheIndex == 0x17B){ TUPLE_ASSIGN(this->position, 0.0f, -50.0f, 700.0f); } - else if(this->modelCacheIndex == ACTOR_17C_RBB_MEDIUM_COG){//L80388DA8 + else if(this->modelCacheIndex == 0x17C){//L80388DA8 TUPLE_ASSIGN(this->position, 0.0f, -50.0f, 500.0f); } - else if(this->modelCacheIndex == ACTOR_17D_RBB_LARGE_COG){ + else if(this->modelCacheIndex == 0x17D){ TUPLE_ASSIGN(this->position, 0.0f, -50.0f, 300.0f); } - chRBBCog_setState(this, CH_RBB_COG_STATE_1_INIT); + func_80388BD0(this, 1); } }//L80388DA8 - - if(this->state == CH_RBB_COG_STATE_1_INIT){ - this->roll += chRBBCogRotateRates[this->modelCacheIndex - ACTOR_17B_RBB_SMALL_COG] * time_delta; + if(this->state == 1){ + this->roll += D_8039041C[this->modelCacheIndex - 0x17B]*sp28; if(360.0f <= this->roll) this->roll -= 360.0f; - if(this->modelCacheIndex == ACTOR_17B_RBB_SMALL_COG){ + if(this->modelCacheIndex == 0x17B){ func_8030DB04(local->sfxsourceIdx, 25000, this->position, 1000.0f, 2000.0f); } } diff --git a/src/RBB/ch/dolphin.c b/src/RBB/ch/dolphin.c index 1f3bc6b15..8731b461f 100644 --- a/src/RBB/ch/dolphin.c +++ b/src/RBB/ch/dolphin.c @@ -8,56 +8,48 @@ ParticleEmitter *func_802EDD8C(f32 [3], f32, f32); void func_8038B900(Actor *this); /* .data */ -ActorInfo chSnorkel = { - MARKER_30_SNORKEL, ACTOR_1C8_SNORKEL, ASSET_41C_MODEL_SNORKEL, - 0x0, NULL, +ActorInfo RBB_D_80390AB0 = { + 0x30, 0x1C8, 0x41C, 0x0, NULL, NULL, func_8038B900, actor_draw, 0, 0, 0.0f, 0 }; -enum chsnorkel_state_e { - CH_SNORKEL_STATE_0_NOT_INIT, - CH_SNORKEL_STATE_1_TRAPPED, - CH_SNORKEL_STATE_2_FREED, - CH_SNORKEL_STATE_3_DESPAWN -}; - /* .code */ -void chSnorkel_setState(Actor *this, s32 new_state){ - if(new_state == CH_SNORKEL_STATE_1_TRAPPED) +void func_8038B880(Actor *this, s32 new_state){ + if(new_state == 1) skeletalAnim_set(this->unk148, ASSET_13F_ANIM_SNORKEL_STUCK, 0.0f, 5.5f); - if(new_state == CH_SNORKEL_STATE_2_FREED) + if(new_state == 2) skeletalAnim_swap(this->unk148, ASSET_13E_ANIM_SNORKEL_SWIM, 1.0f, 0.65f); this->state = new_state; } void func_8038B900(Actor *this){ - f32 prev_anim_progress; - f32 curr_anim_progress; - f32 anim_progress; + f32 sp5C; + f32 sp58; + f32 sp54; f32 sp48[3]; ParticleEmitter *other; this->marker->propPtr->unk8_3 = 1; if(this->marker->unk14_21){ - anim_progress = skeletalAnim_getProgress(this->unk148); + sp54 = skeletalAnim_getProgress(this->unk148); if( ( globalTimer_getTime() & (1 << 4) ) && ( globalTimer_getTime() & (1 << 2) ) && ( randf() < 0.90 ) ){ - if( ( this->state == CH_SNORKEL_STATE_3_DESPAWN - && (0.255 <= anim_progress && anim_progress <= 0.856) + if( ( this->state == 3 + && (0.255 <= sp54 && sp54 <= 0.856) ) - || ( this->state == CH_SNORKEL_STATE_1_TRAPPED - && ( (0.053 <= anim_progress && anim_progress <= 0.35) - || (0.39 <= anim_progress && anim_progress <= 0.44999999999999996) - || (0.45999999999999996 <= anim_progress && anim_progress <= 0.52) - || (0.54 <= anim_progress && anim_progress <= 0.73) - || (0.76 <= anim_progress && anim_progress <= 0.8200000000000001) - || (0.84 <= anim_progress && anim_progress <= 0.9) - || (0.94 <= anim_progress && anim_progress <= 1.0) + || ( this->state == 1 + && ( (0.053 <= sp54 && sp54 <= 0.35) + || (0.39 <= sp54 && sp54 <= 0.44999999999999996) + || (0.45999999999999996 <= sp54 && sp54 <= 0.52) + || (0.54 <= sp54 && sp54 <= 0.73) + || (0.76 <= sp54 && sp54 <= 0.8200000000000001) + || (0.84 <= sp54 && sp54 <= 0.9) + || (0.94 <= sp54 && sp54 <= 1.0) ) ) ){//L8038BB24 @@ -78,45 +70,45 @@ void func_8038B900(Actor *this){ this->position_y = -2600.0f; this->position_z = 1460.0f; this->yaw = 0.0f; - chSnorkel_setState(this, CH_SNORKEL_STATE_1_TRAPPED); + func_8038B880(this, 1); if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)){ marker_despawn(this->marker); } } else{//L8038BC74 - skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress, &curr_anim_progress); - if( prev_anim_progress < 0.22 && 0.22 <= curr_anim_progress ){ + skeletalAnim_getProgressRange(this->unk148, &sp5C, &sp58); + if( sp5C < 0.22 && 0.22 <= sp58 ){ func_8030E988(SFX_D1_SNORKEL_WAH, randf2(0.8f, 0.9f), 15000, this->position, 1500.0f, 2000.0f); } - if( prev_anim_progress < 0.54 && 0.54 <= curr_anim_progress ){ + if( sp5C < 0.54 && 0.54 <= sp58 ){ func_8030E988(SFX_D1_SNORKEL_WAH, randf2(0.9f, 1.0f), 19000, this->position, 1500.0f, 2000.0f); } - if(this->state == CH_SNORKEL_STATE_1_TRAPPED){ + if(this->state == 1){ if( !this->has_met_before - && subaddie_playerIsWithinSphereAndActive(this, 600) + && subaddie_playerIsWithinSphereAndActive(this, 0x258) && !player_movementGroup() ){ - gcdialog_showDialog(VER_SELECT(ASSET_B9B_DIALOG_SNORKEL_MEET, 0x970, 0, 0), 4, 0, 0, 0, 0); - this->has_met_before = TRUE; + gcdialog_showDialog(ASSET_B9B_DIALOG_SNORKEL_MEET, 4, 0, 0, 0, 0); + this->has_met_before = true; } } - if(this->state == CH_SNORKEL_STATE_1_TRAPPED){ - if(mapSpecificFlags_get(RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING)) - chSnorkel_setState(this, CH_SNORKEL_STATE_2_FREED); + if(this->state == 1){ + if(mapSpecificFlags_get(4)) + func_8038B880(this, 2); } - if(this->state == CH_SNORKEL_STATE_2_FREED){ + if(this->state == 2){ if(jiggyscore_isSpawned(JIGGY_53_RBB_SNORKEL)) - chSnorkel_setState(this, CH_SNORKEL_STATE_3_DESPAWN); + func_8038B880(this, 3); } - if(this->state == CH_SNORKEL_STATE_3_DESPAWN){ + if(this->state == 3){ actor_update_func_80326224(this); if(0.99 < this->unk48){ - mapSpecificFlags_set(RBB_MAIN_SPECIFIC_FLAG_4_ANCHOR_LIFTING, false); + mapSpecificFlags_set(4, false); marker_despawn(this->marker); } } diff --git a/src/RBB/ch/eggtoll1.c b/src/RBB/ch/eggtoll1.c index dbc55fd4c..d91f13410 100644 --- a/src/RBB/ch/eggtoll1.c +++ b/src/RBB/ch/eggtoll1.c @@ -5,99 +5,79 @@ extern void timed_exitStaticCamera(f32); -// Anchor: toll extension stage is actor-local (unk8), no flag; keyed by secondaryId. -extern void port_eggToll_onAdvance(s32 map, s32 secondaryId, s32 stage); -extern s32 port_eggToll_getStage(s32 map, s32 secondaryId); -extern ActorArray *suBaddieActorArray; - /* typedefs and declarations */ typedef struct { - s32 eggsPaid; - s32 tollId; - s32 tollNum; // 0 for first toll; 1 for second toll - s32 unkC; // Either 0 or 3? -} ActorLocal_ChRBBEggToll; + s32 unk0; + s32 unk4; + s32 unk8; + s32 unkC; +}ActorLocal_RBB_0; typedef struct { - u8 cameraNode; - u8 eggCost1; - u8 eggCost2; // Only used in Toll 2 + u8 unk0; + u8 unk1; + u8 unk2; //u8 pad3[1]; f32 unk4; s16 unk8; s16 unkA; s16 unkC; //u8 padE[2]; -} chRBBEggTollInfo; +}Struct_RBB_0_1; -void chRBBEggToll_setState(Actor *this, s32 next_state); -void chRBBEggToll_update(Actor* this); +void func_803866F4(Actor *this, s32 arg1); +void func_803868F0(Actor* this); /* .data */ -ActorInfo chRBBEggToll = { +ActorInfo D_80390050 = { MARKER_182_RBB_EGG_TOLL, ACTOR_172_RBB_EGG_TOLL, ASSET_402_MODEL_EGG_TOLL, 0x0, NULL, - chRBBEggToll_update, NULL, func_80325340, + func_803868F0, NULL, func_80325340, 0, 0, 0.0f, 0 }; -chRBBEggTollInfo chRBBEggTollInfoTable[4] = { +Struct_RBB_0_1 D_80390074[4] = { {0x0, 0x2, 0x4, 3.0f, 550, 200, -300}, {0x1, 0x4, 0x0, 4.0f, -600, 0, 0}, {0x2, 0x6, 0x0, 4.0f, -700, 0, 0}, {0x3, 0x8, 0x0, 4.0f, -1010, 0, 0} }; -enum chrbbeggtoll_state_e { - CH_RBB_EGG_TOLL_STATE_0_NOT_INIT, - CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL, - CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID, - CH_RBB_EGG_TOLL_STATE_3_TOLL_COMPLETE, - CH_RBB_EGG_TOLL_STATE_4_UNK -}; - /* .code */ -static s32 eggToll_countForStage(s32 tollIdx, s32 stage) { - s32 count = 0; - if (stage >= 1) count += chRBBEggTollInfoTable[tollIdx].eggCost1; - if (stage >= 2) count += chRBBEggTollInfoTable[tollIdx].eggCost2; - return count; -} - void RBB_func_803863F0(Actor *actor, s32 arg1){ - ActorLocal_ChRBBEggToll * local = (ActorLocal_ChRBBEggToll *) &actor->local; + ActorLocal_RBB_0 * local = (ActorLocal_RBB_0 *) &actor->local; void *temp_a0; f32 sp3C[3]; f32 sp30[3]; - temp_a0 = func_8034C528(local->tollId + 0x190); + temp_a0 = func_8034C528(local->unk4 + 0x190); if(temp_a0){ - if(local->tollNum == 0){ + if(local->unk8 == 0){ sp3C[2] = 0.0f; sp30[0] = 0.0f; sp30[1] = 0.0f; sp3C[0] = sp3C[1] = sp3C[2]; - sp30[2] = (f32) chRBBEggTollInfoTable[local->tollId].unk8; + sp30[2] = (f32) D_80390074[local->unk4].unk8; } - else if(local->tollNum == 1){ + else if(local->unk8 == 1){ sp3C[0] = 0.0f; sp3C[1] = 0.0f; - sp3C[2] = (f32) chRBBEggTollInfoTable[local->tollId].unk8; + sp3C[2] = (f32) D_80390074[local->unk4].unk8; sp30[1] = 0.0f; sp30[0] = 0.0f; - sp30[2] = (f32) chRBBEggTollInfoTable[local->tollId].unkA; + sp30[2] = (f32) D_80390074[local->unk4].unkA; } else{ sp3C[0] = 0.0f; sp3C[1] = 0.0f; - sp3C[2] = (f32) chRBBEggTollInfoTable[local->tollId].unkA; + sp3C[2] = (f32) D_80390074[local->unk4].unkA; sp30[1] = 0.0f; sp30[0] = 0.0f; - sp30[2] = (f32) chRBBEggTollInfoTable[local->tollId].unkC; + sp30[2] = (f32) D_80390074[local->unk4].unkC; } if(arg1){ - func_8034DDF0(temp_a0, sp3C, sp30, chRBBEggTollInfoTable[local->tollId].unk4, 1); + func_8034DDF0(temp_a0, sp3C, sp30, D_80390074[local->unk4].unk4, 1); func_8034E174(temp_a0); } else{ @@ -107,115 +87,84 @@ void RBB_func_803863F0(Actor *actor, s32 arg1){ } void func_803865A4(ActorMarker *marker, s32 arg1){ - chRBBEggToll_setState(marker_getActor(marker), arg1); + func_803866F4(marker_getActor(marker), arg1); } void func_803865D0(ActorMarker *marker){ Actor* actor = marker_getActor(marker); - ActorLocal_ChRBBEggToll * local = (ActorLocal_ChRBBEggToll *) &actor->local; + ActorLocal_RBB_0 * local = (ActorLocal_RBB_0 *) &actor->local; RBB_func_803863F0(actor, 1); - timed_setStaticCameraToNode(0.0f, chRBBEggTollInfoTable[local->tollId].cameraNode); - timedFunc_set_2(0.75 * chRBBEggTollInfoTable[local->tollId].unk4, (GenFunction_2) func_803865A4, (uintptr_t)actor->marker, 4); - timed_exitStaticCamera(0.75 * chRBBEggTollInfoTable[local->tollId].unk4); - func_80324E38(0.75 * chRBBEggTollInfoTable[local->tollId].unk4, 0); - timed_playSfx(chRBBEggTollInfoTable[local->tollId].unk4, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 0x7FD0); + timed_setStaticCameraToNode(0.0f, D_80390074[local->unk4].unk0); + timedFunc_set_2(0.75*D_80390074[local->unk4].unk4, (GenFunction_2) func_803865A4, (uintptr_t)actor->marker, 4); + timed_exitStaticCamera(0.75*D_80390074[local->unk4].unk4); + func_80324E38(0.75*D_80390074[local->unk4].unk4, 0); + timed_playSfx(D_80390074[local->unk4].unk4, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 0x7fd0); } -void chRBBEggToll_setState(Actor *this, s32 next_state){ - ActorLocal_ChRBBEggToll *local = (ActorLocal_ChRBBEggToll *) &this->local; +void func_803866F4(Actor *this, s32 arg1){ + ActorLocal_RBB_0 *local = (ActorLocal_RBB_0 *) &this->local; - if(next_state == CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID){ + if(arg1 == 2){ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - local = (ActorLocal_ChRBBEggToll *) &this->local; + local = (ActorLocal_RBB_0 *) &this->local; local->unkC = 3; } - if(next_state == CH_RBB_EGG_TOLL_STATE_3_TOLL_COMPLETE){ - local->tollNum++; - port_eggToll_onAdvance((s32)gsworld_getMap(), this->secondaryId, local->tollNum); + if(arg1 == 3){ + local->unk8++; coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); func_80324E38(0.0f, 3); timedFunc_set_2(0.5f, (GenFunction_2) coMusicPlayer_playMusic, COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 28000); timedFunc_set_1(1.0f, (GenFunction_1) func_803865D0, (uintptr_t)this->marker); }//L803867D4 - - if(next_state == CH_RBB_EGG_TOLL_STATE_4_UNK){ - if(local->tollNum == 1 && chRBBEggTollInfoTable[local->tollId].eggCost2 > 0){ - chRBBEggToll_setState(this, CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL); + if(arg1 == 4){ + if(local->unk8 == 1 && D_80390074[local->unk4].unk2 > 0){ + func_803866F4(this, 1); return; } } - this->state = next_state; + this->state = arg1; } void func_8038685C(ActorMarker *marker){ Actor *actor = marker_getActor(marker); - ActorLocal_ChRBBEggToll *local = (ActorLocal_ChRBBEggToll *) &actor->local; + ActorLocal_RBB_0 *local = (ActorLocal_RBB_0 *) &actor->local; - if(actor->state == CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL){ - local->eggsPaid++; - if( chRBBEggTollInfoTable[local->tollId].eggCost1 == local->eggsPaid - || chRBBEggTollInfoTable[local->tollId].eggCost1 + chRBBEggTollInfoTable[local->tollId].eggCost2 == local->eggsPaid + if(actor->state == 1){ + local->unk0++; + if( D_80390074[local->unk4].unk1 == local->unk0 + || D_80390074[local->unk4].unk1 + D_80390074[local->unk4].unk2 == local->unk0 ){ - chRBBEggToll_setState(actor, CH_RBB_EGG_TOLL_STATE_3_TOLL_COMPLETE); + func_803866F4(actor, 3); }else{ - chRBBEggToll_setState(actor, CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID); + func_803866F4(actor, 2); } } } -void chRBBEggToll_update(Actor *this){ - ActorLocal_ChRBBEggToll *local = (ActorLocal_ChRBBEggToll *) &this->local; +void func_803868F0(Actor *this){ + ActorLocal_RBB_0 *local = (ActorLocal_RBB_0 *) &this->local; if(!this->volatile_initialized){ this->volatile_initialized = true; - if(this->state == CH_RBB_EGG_TOLL_STATE_0_NOT_INIT){ - local->eggsPaid = 0; - local->tollId = 0; - local->tollNum = 0; + if(this->state == 0){ + local->unk0 = 0; + local->unk4 = 0; + local->unk8 = 0; local->unkC = 0; - local->tollId = (this->secondaryId == 0x15)? 0: local->tollId; - local->tollId = (this->secondaryId == 0x13)? 1: local->tollId; - local->tollId = (this->secondaryId == 0x14)? 2: local->tollId; - local->tollId = (this->secondaryId == 0x0B)? 3: local->tollId; - local->tollNum = port_eggToll_getStage((s32)gsworld_getMap(), this->secondaryId); - local->eggsPaid = eggToll_countForStage(local->tollId, local->tollNum); - chRBBEggToll_setState(this, CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL); + local->unk4 = (this->secondaryId == 0x15)? 0: local->unk4; + local->unk4 = (this->secondaryId == 0x13)? 1: local->unk4; + local->unk4 = (this->secondaryId == 0x14)? 2: local->unk4; + local->unk4 = (this->secondaryId == 0xB)? 3: local->unk4; + func_803866F4(this, 1); } RBB_func_803863F0(this, 0); }//L803869F4 - if(this->state == CH_RBB_EGG_TOLL_STATE_2_FIRST_EGG_PAID){ + if(this->state == 2){ if(--local->unkC <= 0){ - chRBBEggToll_setState(this, CH_RBB_EGG_TOLL_STATE_1_AWAITING_TOLL); + func_803866F4(this, 1); } } } - -void port_eggToll_remoteApply(s32 map, s32 secondaryId, s32 stage) { - s32 i; - (void)map; - - if (suBaddieActorArray == NULL) { - return; - } - for (i = 0; i < suBaddieActorArray->cnt; i++) { - Actor *actor = &suBaddieActorArray->data[i]; - ActorLocal_ChRBBEggToll *local; - if (actor->marker == NULL || actor->marker->id != MARKER_182_RBB_EGG_TOLL) { - continue; - } - if (actor->secondaryId != secondaryId) { - continue; - } - local = (ActorLocal_ChRBBEggToll *) &actor->local; - if (stage > local->tollNum) { - local->tollNum = stage; - local->eggsPaid = eggToll_countForStage(local->tollId, stage); - RBB_func_803863F0(actor, 1); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - } - return; - } -} diff --git a/src/RBB/ch/enginefan.c b/src/RBB/ch/enginefan.c index 86c251635..6c9e30265 100644 --- a/src/RBB/ch/enginefan.c +++ b/src/RBB/ch/enginefan.c @@ -22,7 +22,7 @@ typedef struct { f32 unk28; }ActorLocal_RBB_2E90; -void chEngineRoomPropeller_update(Actor *this); +void func_8038944C(Actor *this); /* .data */ @@ -57,35 +57,24 @@ Struct_RBB_2E90_0 D_80390530[] = { {0} }; -ActorInfo chEngineRoomPropeller1 = { - MARKER_191_ENGINE_ROOM_PROPELLOR_1, ACTOR_1BB_ENGINE_ROOM_PROPELLOR_1, ASSET_40F_MODEL_ENGINE_ROOM_PROPELLER_1, - 0x0, NULL, - chEngineRoomPropeller_update, NULL, actor_draw, +ActorInfo D_80390640 = { + MARKER_191_ENGINE_ROOM_PROPELLOR_1, ACTOR_1BB_ENGINE_ROOM_PROPELLOR_1, ASSET_40F_MODEL_ENGINE_ROOM_PROPELLER_1, 0x0, NULL, + func_8038944C, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chEngineRoomPropeller2 = { - MARKER_192_ENGINE_ROOM_PROPELLOR_2, ACTOR_1BC_ENGINE_ROOM_PROPELLOR_2, ASSET_410_MODEL_ENGINE_ROOM_PROPELLER_2, - 0x0, NULL, - chEngineRoomPropeller_update, NULL, actor_draw, +ActorInfo D_80390664 = { + MARKER_192_ENGINE_ROOM_PROPELLOR_2, ACTOR_1BC_ENGINE_ROOM_PROPELLOR_2, ASSET_410_MODEL_ENGINE_ROOM_PROPELLER_2, 0x0, NULL, + func_8038944C, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chEngineRoomPropeller3 = { - MARKER_193_ENGINE_ROOM_PROPELLOR_3, ACTOR_1BD_ENGINE_ROOM_PROPELLOR_3, ASSET_411_MODEL_ENGINE_ROOM_PROPELLER_3, - 0x0, NULL, - chEngineRoomPropeller_update, NULL, actor_draw, +ActorInfo D_80390688 = { + MARKER_193_ENGINE_ROOM_PROPELLOR_3, ACTOR_1BD_ENGINE_ROOM_PROPELLOR_3, ASSET_411_MODEL_ENGINE_ROOM_PROPELLER_3, 0x0, NULL, + func_8038944C, NULL, actor_draw, 0, 0, 0.0f, 0 }; -enum chengineroompropeller_state_e { - CH_ENGINE_ROOM_PROPELLER_STATE_0_NOT_INIT, - CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK, - CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK, - CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK, - CH_ENGINE_ROOM_PROPELLER_STATE_4_UNK -}; - /* .code */ Struct_RBB_2E90_0 * func_80389280(Actor *this){ Struct_RBB_2E90_0 * iPtr; @@ -96,13 +85,13 @@ Struct_RBB_2E90_0 * func_80389280(Actor *this){ return NULL; } -void chEngineRoomPropeller_setState(Actor *this, s32 next_state){ +void func_803892D8(Actor *this, s32 arg1){ f32 pad; ActorLocal_RBB_2E90 *local = (ActorLocal_RBB_2E90 *)&this->local; - this->state = next_state; + this->state = arg1; local->unk28 = 0.0f; - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK){ + if(this->state == 1){ local->unk0[2] = 0.0f; local->unk0[1] = 0.0f; local->unk0[0] = 0.0f; @@ -110,19 +99,19 @@ void chEngineRoomPropeller_setState(Actor *this, s32 next_state){ ml_vec3f_copy(local->unk1C, local->unkC->unk1C); }//L8038935C - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK){ + if(this->state == 2){ ml_vec3f_copy(local->unk0, local->unkC->unk28); ml_vec3f_copy(local->unk1C, local->unkC->unk10); local->unk28 = local->unkC->unk40; }//L803893A8 - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK){ + if(this->state == 3){ ml_vec3f_copy(local->unk0, local->unkC->unk28); ml_vec3f_copy(local->unk1C, local->unkC->unk1C); local->unk28 = local->unkC->unk40; }//L803893F4 - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_4_UNK){ + if(this->state == 4){ ml_vec3f_copy(local->unk0, local->unkC->unk34); ml_vec3f_copy(local->unk10, local->unkC->unk1C); local->unk1C[2] = 0.0f; @@ -131,12 +120,12 @@ void chEngineRoomPropeller_setState(Actor *this, s32 next_state){ } } -void chEngineRoomPropeller_update(Actor *this){ +void func_8038944C(Actor *this){ ActorLocal_RBB_2E90 *local = (ActorLocal_RBB_2E90 *)&this->local; f32 tick; int i; - f32 current_rotation[3]; - f32 next_rotation[3]; + f32 sp50[3]; + f32 sp44[3]; tick = time_getDelta(); @@ -144,72 +133,69 @@ void chEngineRoomPropeller_update(Actor *this){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unkC = func_80389280(this); - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_0_NOT_INIT){ + if(this->state == 0){ ml_vec3f_copy(this->position, local->unkC->unk4); local->unk0[0] = local->unk0[1] = local->unk0[2] = 0.0f; local->unk10[0] = local->unk10[1] = local->unk10[2] = 0.0f; local->unk1C[0] = local->unk1C[1] = local->unk1C[2] = 0.0f; local->unk28 = 0.0f; - chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK); + func_803892D8(this, 1); } }//L80389508 if(ml_timer_update(&local->unk28, tick)){ - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK) - chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK); - else if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK) - chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK); + if(this->state == 2) + func_803892D8(this, 3); + else if(this->state == 3) + func_803892D8(this, 2); }//L80389568 switch (this->state) { - case CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK: - case CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK: - case CH_ENGINE_ROOM_PROPELLER_STATE_3_UNK: - case CH_ENGINE_ROOM_PROPELLER_STATE_4_UNK: - current_rotation[0] = this->pitch; - current_rotation[1] = this->yaw; - current_rotation[2] = this->roll; - - this->pitch += local->unk10[0] * tick; - this->yaw += local->unk10[1] * tick; - this->roll += local->unk10[2] * tick; - - next_rotation[0] = this->pitch; - next_rotation[1] = this->yaw; - next_rotation[2] = this->roll; - - for(i = 0; i < 3; i++){ - if( (current_rotation[i] < 90.0f && 90.0f <= next_rotation[i]) - || (current_rotation[i] < 270.0f && 270.0f <= next_rotation[i]) - || (current_rotation[i] < 180.0f && 180.0f <= next_rotation[i]) - || (current_rotation[i] < 360.0f && 360.0f <= next_rotation[i]) - ){ - sfx_playFadeShorthandDefault(SFX_2_CLAW_SWIPE, 0.4f, 23000, this->position, 50, 1000); - } + case 1: + case 2: + case 3: + case 4: + sp50[0] = this->pitch; + sp50[1] = this->yaw; + sp50[2] = this->roll; + this->pitch += local->unk10[0]*tick ; + this->yaw += local->unk10[1]*tick ; + this->roll += local->unk10[2]*tick ; + + sp44[0] = this->pitch; + sp44[1] = this->yaw; + sp44[2] = this->roll; + + for(i = 0; i < 3; i++){ + if( (sp50[i] < 90.0f && 90.0f <= sp44[i]) + || (sp50[i] < 270.0f && 270.0f <= sp44[i]) + || (sp50[i] < 180.0f && 180.0f <= sp44[i]) + || (sp50[i] < 360.0f && 360.0f <= sp44[i]) + ){ + sfx_playFadeShorthandDefault(SFX_2_CLAW_SWIPE, 0.4f, 23000, this->position, 50, 1000); + } + } + this->pitch += (360.0f <= this->pitch)? -360 : 0; + this->yaw += (360.0f <= this->yaw)? -360 : 0; + this->roll += (360.0f <= this->roll)? -360 : 0; + + for(i = 0; i < 3; i++){//L803897B8 + if( local->unk10[i] < local->unk1C[i] ){ + local->unk10[i] += local->unk0[i]*tick; + local->unk10[i] = MIN(local->unk1C[i] , local->unk10[i]); } - this->pitch += (360.0f <= this->pitch)? -360 : 0; - this->yaw += (360.0f <= this->yaw)? -360 : 0; - this->roll += (360.0f <= this->roll)? -360 : 0; - - for(i = 0; i < 3; i++){//L803897B8 - if( local->unk10[i] < local->unk1C[i] ){ - local->unk10[i] += local->unk0[i] * tick; - local->unk10[i] = MIN(local->unk1C[i] , local->unk10[i]); - } - else if( local->unk1C[i] < local->unk10[i]){ - local->unk10[i] -= local->unk0[i] * tick; - local->unk10[i] = MAX(local->unk1C[i] , local->unk10[i]); - } + else if( local->unk1C[i] < local->unk10[i]){ + local->unk10[i] -= local->unk0[i]*tick; + local->unk10[i] = MAX(local->unk1C[i] , local->unk10[i]); } - break; + } + break; }//L80389860 - if(this->state == CH_ENGINE_ROOM_PROPELLER_STATE_1_UNK - && mapSpecificFlags_get(RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER)) - { - chEngineRoomPropeller_setState(this, CH_ENGINE_ROOM_PROPELLER_STATE_2_UNK); + if(this->state == 1 && mapSpecificFlags_get(0)){ + func_803892D8(this, 2); } if(tick); } diff --git a/src/RBB/ch/enginefanswitch.c b/src/RBB/ch/enginefanswitch.c index 8b0937b79..7238b2b36 100644 --- a/src/RBB/ch/enginefanswitch.c +++ b/src/RBB/ch/enginefanswitch.c @@ -3,37 +3,28 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - void chEngineFanSwitch_update(Actor *this); /* .data */ -ActorInfo chRBBGreyPropellerSwitch = { - MARKER_194_RBB_GREY_PROPELLER_SWITCH, ACTOR_1BE_RBB_GREY_PROPELLOR_SWITCH, ASSET_412_MODEL_RBB_GREY_PROPELLER_SWITCH, - 0x0, NULL, +ActorInfo D_803906B0 = { + 0x194, 0x1BE, 0x412, 0x0, NULL, chEngineFanSwitch_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -enum chrbbgreypropellerswitch_state_e { - CH_RBB_GREY_PROPELLER_SWITCH_STATE_0_NOT_INIT, - CH_RBB_GREY_PROPELLER_SWITCH_STATE_1_NOT_PRESSED, - CH_RBB_GREY_PROPELLER_SWITCH_STATE_2_PRESSED -}; - /* .code */ -void chEngineFanSwitch_setPressedFlag(void){ - mapSpecificFlags_set(RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER, true); +void RBB_func_803898A0(void){ + mapSpecificFlags_set(0, 1); } void chEngineFanSwitch_setState(Actor * this, s32 arg1){ this->state = arg1; - if(this->state == CH_RBB_GREY_PROPELLER_SWITCH_STATE_2_PRESSED){ + if(this->state == 2){ func_8030E6D4(SFX_90_SWITCH_PRESS); this->position_y -= 35.0f; func_80324E38(1.0f, 3); timed_setStaticCameraToNode(1.0f, 0); - timedFunc_set_0(1.0f, chEngineFanSwitch_setPressedFlag); + timedFunc_set_0(1.0f, RBB_func_803898A0); timed_exitStaticCamera(5.0f); func_80324E38(5.0f, 0); } @@ -41,8 +32,8 @@ void chEngineFanSwitch_setState(Actor * this, s32 arg1){ void __chEngineFanSwitch_pressCallback(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - if(actor->state == CH_RBB_GREY_PROPELLER_SWITCH_STATE_1_NOT_PRESSED){ - chEngineFanSwitch_setState(actor, CH_RBB_GREY_PROPELLER_SWITCH_STATE_2_PRESSED); + if(actor->state == 1){ + chEngineFanSwitch_setState(actor, 2); } } @@ -50,23 +41,14 @@ void chEngineFanSwitch_update(Actor *this){ if(!this->volatile_initialized){ //initialize this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; - mapSpecificFlags_set(RBB_MAIN_SPECIFIC_FLAG_0_PROPELLER, false); + mapSpecificFlags_set(0, 0); marker_setCollisionScripts(this->marker, NULL, __chEngineFanSwitch_pressCallback, NULL); - if(this->state == CH_RBB_GREY_PROPELLER_SWITCH_STATE_0_NOT_INIT){ + if(this->state == 0){ this->position_x = -3209.95f; this->position_y = 1164.5f; this->position_z = -2649.95f; this->yaw = -90.0f; - chEngineFanSwitch_setState(this, CH_RBB_GREY_PROPELLER_SWITCH_STATE_1_NOT_PRESSED); + chEngineFanSwitch_setState(this, 1); } } - // [port] Anchor temp-persist: the fan slowdown is transient map flag 0, set by pressing this - // switch (RBB_func_803898A0). It syncs live but resets on reload, so persist it - if(mapSpecificFlags_get(0)){ - port_puzzleStep_orBits(ANCHOR_PUZZLE_RBB_ENGINE_FANS, 1); - } else if((this->state == 1) && (port_puzzleStep_get(ANCHOR_PUZZLE_RBB_ENGINE_FANS) & 1)){ - this->position_y -= 35.0f; - this->state = 2; - mapSpecificFlags_set(0, 1); - } } diff --git a/src/RBB/ch/engineparts.c b/src/RBB/ch/engineparts.c index 6515a0881..59ffc0855 100644 --- a/src/RBB/ch/engineparts.c +++ b/src/RBB/ch/engineparts.c @@ -22,7 +22,7 @@ typedef struct { f32 unk1C; }ActorLocal_RBB_40F0; -void chRBBSpinningPipe_update(Actor *this); +void func_8038A724(Actor *this); /* .data */ Struct_RBB_40F0 D_80390760[4] = { @@ -32,75 +32,65 @@ Struct_RBB_40F0 D_80390760[4] = { {{ -300.0f, 641.5f, -400.0f}, {-500.0f, 0.0f, 0.0f}, 0x28, 1}, }; -ActorInfo chRBBSpinningSinglePipe1 = { - MARKER_187_RBB_SPINNING_SINGLE_PIPE_1, ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1, ASSET_406_MODEL_RBB_SPINNING_SINGLE_PIPE, 0x0, NULL, - chRBBSpinningPipe_update, NULL, actor_draw, +ActorInfo D_803907D0 = { + 0x187, 0x177, 0x406, 0x0, NULL, + func_8038A724, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chRBBSpinningSinglePipe2 = { - MARKER_18E_RBB_SPINNING_SINGLE_PIPE_2, ACTOR_17E_RBB_SPINNING_SINGLE_PIPE_2, ASSET_406_MODEL_RBB_SPINNING_SINGLE_PIPE, - 0x0, NULL, - chRBBSpinningPipe_update, NULL, actor_draw, +ActorInfo D_803907F4 = { + 0x18E, 0x17E, 0x406, 0x0, NULL, + func_8038A724, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chRBBSpinningDoublePipe1 = { - MARKER_18F_RBB_SPINNING_DOUBLE_PIPE_1, ACTOR_17F_RBB_SPINNING_DOUBLE_PIPE_1, ASSET_407_MODEL_RBB_SPINNING_DOUBLEE_PIPE_RIGHT, - 0x0, NULL, - chRBBSpinningPipe_update, NULL, actor_draw, +ActorInfo D_80390818 = { + 0x18F, 0x17F, 0x407, 0x0, NULL, + func_8038A724, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chRBBSpinningDoublePipe2 = { - MARKER_190_RBB_SPINNING_DOUBLE_PIPE_2, ACTOR_180_RBB_SPINNING_DOUBLE_PIPE_2, ASSET_408_MODEL_RBB_SPINNING_DOUBLEE_PIPE_LEFT, - 0x0, NULL, - chRBBSpinningPipe_update, NULL, actor_draw, +ActorInfo D_8039083C = { + 0x190, 0x180, 0x408, 0x0, NULL, + func_8038A724, NULL, actor_draw, 0, 0, 0.0f, 0 }; f32 D_80390860[3] = {1.0f, 0.5f, 0.5f}; -enum chrbbspinningpipe_state_e { - CH_RBB_SPINNING_PIPE_STATE_0_NOT_INIT, - CH_RBB_SPINNING_PIPE_STATE_1_UNK, - CH_RBB_SPINNING_PIPE_STATE_2_UNK, - CH_RBB_SPINNING_PIPE_STATE_3_UNK -}; - /* .code */ f32 func_8038A4E0(void) { return D_80390860[2 * levelSpecificFlags_get(LEVEL_FLAG_27_RBB_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_28_RBB_UNKNOWN)]; } -void chRBBSpinningPipe_setState(Actor *this, s32 next_state){ +void func_8038A524(Actor *this, s32 arg1){ ActorLocal_RBB_40F0 *local = (ActorLocal_RBB_40F0 *)&this->local; local->unk1C = 0.0f; - if(next_state == CH_RBB_SPINNING_PIPE_STATE_1_UNK){ + if(arg1 == 1){ if(D_80390760[local->unk0].unk1A){ - chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_2_UNK); + func_8038A524(this, 2); return; } - local->unk10[0] = D_80390760[local->unk0].unkC[0] * func_8038A4E0(); - local->unk10[1] = D_80390760[local->unk0].unkC[1] * func_8038A4E0(); - local->unk10[2] = D_80390760[local->unk0].unkC[2] * func_8038A4E0(); + local->unk10[0] = D_80390760[local->unk0].unkC[0]*func_8038A4E0(); + local->unk10[1] = D_80390760[local->unk0].unkC[1]*func_8038A4E0(); + local->unk10[2] = D_80390760[local->unk0].unkC[2]*func_8038A4E0(); } - if(next_state == CH_RBB_SPINNING_PIPE_STATE_2_UNK){ - local->unk10[0] = D_80390760[local->unk0].unkC[0] * func_8038A4E0(); - local->unk10[1] = D_80390760[local->unk0].unkC[1] * func_8038A4E0(); - local->unk10[2] = D_80390760[local->unk0].unkC[2] * func_8038A4E0(); + if(arg1 == 2){ + local->unk10[0] = D_80390760[local->unk0].unkC[0]*func_8038A4E0(); + local->unk10[1] = D_80390760[local->unk0].unkC[1]*func_8038A4E0(); + local->unk10[2] = D_80390760[local->unk0].unkC[2]*func_8038A4E0(); } - if(next_state == CH_RBB_SPINNING_PIPE_STATE_3_UNK){ + if(arg1 == 3){ local->unk10[2] = 0.0f; local->unk10[1] = 0.0f; local->unk10[0] = 0.0f; } - this->state = next_state; + this->state = arg1; } f32 func_8038A6B8(ActorMarker *marker){ @@ -112,13 +102,13 @@ f32 func_8038A6B8(ActorMarker *marker){ for(i = 0; i < 3; i++){ f12 += ABS(local->unk4[i]); } - return f12 / 500.0f; + return f12/500.0f; } -void chRBBSpinningPipe_update(Actor *this){ +void func_8038A724(Actor *this){ ActorLocal_RBB_40F0 *local = (ActorLocal_RBB_40F0 *)&this->local; int i; - f32 time_delta = time_getDelta(); + f32 sp1C = time_getDelta(); if(!this->volatile_initialized){ @@ -126,41 +116,41 @@ void chRBBSpinningPipe_update(Actor *this){ this->volatile_initialized = true; actor_collisionOff(this); local->unk0 = 0; - local->unk0 = (this->modelCacheIndex == ACTOR_17E_RBB_SPINNING_SINGLE_PIPE_2) ? 1: local->unk0; - local->unk0 = (this->modelCacheIndex == ACTOR_17F_RBB_SPINNING_DOUBLE_PIPE_1) ? 2: local->unk0; - local->unk0 = (this->modelCacheIndex == ACTOR_180_RBB_SPINNING_DOUBLE_PIPE_2) ? 3: local->unk0; + local->unk0 = (this->modelCacheIndex == 0x17E) ? 1: local->unk0; + local->unk0 = (this->modelCacheIndex == 0x17F) ? 2: local->unk0; + local->unk0 = (this->modelCacheIndex == 0x180) ? 3: local->unk0; this->position_x = D_80390760[local->unk0].unk0[0]; this->position_y = D_80390760[local->unk0].unk0[1]; this->position_z = D_80390760[local->unk0].unk0[2]; - chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_1_UNK); + func_8038A524(this, 1); }//L8038A884 - this->pitch += local->unk4[0] * time_delta; - this->yaw += local->unk4[1] * time_delta; - this->roll += local->unk4[2] * time_delta; + this->pitch += local->unk4[0]*sp1C; + this->yaw += local->unk4[1]*sp1C; + this->roll += local->unk4[2]*sp1C; for(i = 0; i < 3; i++){//L8038A8D4 if(local->unk10[i] < local->unk4[i]){ - local->unk4[i] -= 75.0f * time_delta; + local->unk4[i] -= 75.0f*sp1C; local->unk4[i] = MAX(local->unk10[i], local->unk4[i]); }//L8038A924 else if(local->unk4[i] < local->unk10[i]){ - local->unk4[i] += 75.0f * time_delta; + local->unk4[i] += 75.0f*sp1C; local->unk4[i] = MIN(local->unk10[i], local->unk4[i]); } } - if(this->state == CH_RBB_SPINNING_PIPE_STATE_1_UNK){ - local->unk10[0] = D_80390760[local->unk0].unkC[0] * func_8038A4E0(); - local->unk10[1] = D_80390760[local->unk0].unkC[1] * func_8038A4E0(); - local->unk10[2] = D_80390760[local->unk0].unkC[2] * func_8038A4E0(); + if(this->state == 1){ + local->unk10[0] = D_80390760[local->unk0].unkC[0]*func_8038A4E0(); + local->unk10[1] = D_80390760[local->unk0].unkC[1]*func_8038A4E0(); + local->unk10[2] = D_80390760[local->unk0].unkC[2]*func_8038A4E0(); } - if(this->state == CH_RBB_SPINNING_PIPE_STATE_2_UNK){ + if(this->state == 2){ if(0.0f < local->unk1C){ - if(ml_timer_update(&local->unk1C, time_delta)){ - chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_3_UNK); + if(ml_timer_update(&local->unk1C, sp1C)){ + func_8038A524(this, 3); }//L8038AA8C }else{ if( local->unk4[0] == local->unk10[0] @@ -172,10 +162,10 @@ void chRBBSpinningPipe_update(Actor *this){ } }//L8038AB04 - if(this->state == CH_RBB_SPINNING_PIPE_STATE_3_UNK){ + if(this->state == 3){ if(0.0f < local->unk1C){ - if(ml_timer_update(&local->unk1C, time_delta)){ - chRBBSpinningPipe_setState(this, CH_RBB_SPINNING_PIPE_STATE_2_UNK); + if(ml_timer_update(&local->unk1C, sp1C)){ + func_8038A524(this, 2); }//L8038AA8C }else{ if( local->unk4[0] == local->unk10[0] diff --git a/src/RBB/ch/grimlet.c b/src/RBB/ch/grimlet.c index 194a093b8..8005b2884 100644 --- a/src/RBB/ch/grimlet.c +++ b/src/RBB/ch/grimlet.c @@ -14,34 +14,27 @@ typedef struct { f32 unk14; }ActorLocal_RBB_1FC0; -Actor *chGrimlet_draw(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chGrimlet_update(Actor *this); +Actor *func_8038846C(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void func_80388620(Actor *this); /* .data */ -ActorInfo chGrimlet = { - MARKER_2E_GRIMLET, ACTOR_1C6_GRIMLET, ASSET_419_MODEL_GRIMLET, - 0x0, NULL, - chGrimlet_update, NULL, chGrimlet_draw, +ActorInfo D_80390380 = { + MARKER_2E_GRIMLET, ACTOR_1C6_GRIMLET, ASSET_419_MODEL_GRIMLET, 0x0, NULL, + func_80388620, NULL, func_8038846C, 0, 0, 0.0f, 0 }; -enum chgrimlet_state_e { - CH_GRIMLET_STATE_0_NOT_INIT, - CH_GRIMLET_STATE_1_UNK, - CH_GRIMLET_STATE_2_UNK -}; - /* .code */ -void chGrimlet_setState(Actor *this, s32 next_state){ +void func_803883B0(Actor *this, s32 arg1){ ActorLocal_RBB_1FC0 *local = (ActorLocal_RBB_1FC0 *)&this->local; local->unk5 = 0; - if(next_state == CH_GRIMLET_STATE_2_UNK){ + if(arg1 == 2){ FUNC_8030E624(SFX_66_BIRD_AUUGHH, 0.6f, 32675); - skeletalAnim_set(this->unk148, ASSET_137_ANIM_GRIMLET_ATTACK, 0.0f, 0.8f); + skeletalAnim_set(this->unk148, 0x137, 0.0f, 0.8f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } - this->state = next_state; + this->state = arg1; } void RBB_func_80388430(ActorMarker * marker, ActorMarker *other_marker){ @@ -51,7 +44,7 @@ void RBB_func_80388430(ActorMarker * marker, ActorMarker *other_marker){ local->unk5 = 1; } -Actor *chGrimlet_draw(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ +Actor *func_8038846C(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ Actor *actor = marker_getActor(marker); ActorLocal_RBB_1FC0 *local = (ActorLocal_RBB_1FC0 *) &actor->local; BoneTransformList *sp5C; @@ -60,7 +53,7 @@ Actor *chGrimlet_draw(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ f32 sp40[3]; f32 sp34[3]; - if(actor->state == CH_GRIMLET_STATE_0_NOT_INIT){ + if(actor->state == 0){ return actor; } @@ -84,22 +77,22 @@ Actor *chGrimlet_draw(ActorMarker * marker, Gfx **gdl, Mtx **mptr, Vtx **vtx){ func_8033A968(sp5C, 0x12, sp34); skeletalAnim_func_80335918(actor->unk148); } - modelRender_setAppendageVisibility(3, (0.0f < local->unk8)? 1 : 0); - modelRender_setAppendageVisibility(4, (0.0f < local->unk8)? 1 : 0); + func_8033A45C(3, (0.0f < local->unk8)? 1 : 0); + func_8033A45C(4, (0.0f < local->unk8)? 1 : 0); actor_draw(marker, gdl, mptr, vtx); local->unk4 = actor->marker->unk14_21; return actor; } -void chGrimlet_update(Actor *this){ +void func_80388620(Actor *this){ f32 plyr_pos[3]; - f32 horizontal_distance; - f32 distance_in_front; - f32 side_angle_radian; + f32 sp60; + f32 sp5C; + f32 sp58; ActorLocal_RBB_1FC0 *local = (ActorLocal_RBB_1FC0 *)&this->local; - f32 time_delta = time_getDelta(); - f32 prev_anim_progress; - f32 curr_anim_progress; + f32 sp50 = time_getDelta(); + f32 sp4C; + f32 sp48; f32 tmp_f2; if(!this->volatile_initialized){ @@ -112,84 +105,80 @@ void chGrimlet_update(Actor *this){ local->unkC = 0.0f; local->unk10 = 0.0f; local->unk14 = 0.0f; - chGrimlet_setState(this, CH_GRIMLET_STATE_1_UNK); + func_803883B0(this, 1); } player_getPosition(plyr_pos); - func_80258A4C( - this->position, this->yaw + -90.0f, plyr_pos, - &horizontal_distance, &distance_in_front, &side_angle_radian); - if(horizontal_distance < 600.0f) + func_80258A4C(this->position, this->yaw + -90.0f, plyr_pos, &sp60, &sp5C, &sp58); + if(sp60 < 600.0f) local->unk8 = 1.0f; else{ - local->unk8 -= time_delta; + local->unk8 -= sp50; local->unk8 = MAX(0.0f, local->unk8); } if( 500.0f <= local->unk10 - && horizontal_distance < 500.0f - && (side_angle_radian < -0.2 || 0.2 < side_angle_radian) + && sp60 < 500.0f + && (sp58 < -0.2 || 0.2 < sp58) ){ FUNC_8030E624(SFX_C4_TWINKLY_MUNCHER_GRR, 0.8f, 32675); } - local->unk10 = horizontal_distance; - local->unk14 = local->unk14 + time_delta; + local->unk10 = sp60; + local->unk14 = local->unk14 + sp50; - if( horizontal_distance < 600.0f - && -1.0f < side_angle_radian - && side_angle_radian < 1.0f + if( sp60 < 600.0f + && -1.0f < sp58 + && sp58 < 1.0f && plyr_pos[1] < this->position_y + this->scale*200.0f ){ - func_80258A4C( - this->position, (this->yaw + -90.0f) + local->unk0, plyr_pos, - &horizontal_distance, &distance_in_front, &side_angle_radian); - local->unk0 += (side_angle_radian * 200.0f) * time_delta; - if(1.0f < local->unk14 && (side_angle_radian < -0.1 || 0.1 < side_angle_radian)){ - gcsfx_playWithPitch(SFX_D0_GRIMLET_SQUEAK, mlAbsF(side_angle_radian) * 0.1 + 0.9, 0x4e20); + func_80258A4C(this->position, (this->yaw + -90.0f) + local->unk0, plyr_pos, &sp60, &sp5C, &sp58); + local->unk0 += (sp58*200.0f)*sp50; + if(1.0f < local->unk14 && (sp58 < -0.1 || 0.1 < sp58)){ + gcsfx_playWithPitch(SFX_D0_GRIMLET_SQUEAK, mlAbsF(sp58) * 0.1 + 0.9, 0x4e20); local->unk14 = 0.0f; } } else{//L80388964 if(0.0f < local->unk0){ - local->unk0 -= 30.0f * time_delta; + local->unk0 -= 30.0f*sp50; local->unk0 = MAX(0.0f, local->unk0); }//L803889B4 else{ if(local->unk0 < 0.0f){ - local->unk0 += 30.0f * time_delta; + local->unk0 += 30.0f*sp50; local->unk0 = MIN(0.0f, local->unk0); } } }//L803889F8 - if(this->state == CH_GRIMLET_STATE_1_UNK){ - if( horizontal_distance < 400.0f - && -0.8 <= side_angle_radian - && side_angle_radian <= 0.8 + if(this->state == 1){ + if( sp60 < 400.0f + && -0.8 <= sp58 + && sp58 <= 0.8 && (plyr_pos[1] - this->position_y) < 100.0f && -100.0f < (plyr_pos[1] - this->position_y) ){ - chGrimlet_setState(this, CH_GRIMLET_STATE_2_UNK); + func_803883B0(this, 2); } }//L80388AB8 - if(this->state == CH_GRIMLET_STATE_2_UNK){ - skeletalAnim_getProgressRange(this->unk148, &prev_anim_progress, &curr_anim_progress); - if(0.6 <= curr_anim_progress) - tmp_f2 = 1.0 - 2 * (curr_anim_progress - 0.6); + if(this->state == 2){ + skeletalAnim_getProgressRange(this->unk148, &sp4C, &sp48); + if(0.6 <= sp48) + tmp_f2 = 1.0 - 2*(sp48 - 0.6); else - tmp_f2 = curr_anim_progress * 1.6666666666666667; + tmp_f2 = sp48*1.6666666666666667; //L80388B34 - local->unkC = tmp_f2 * horizontal_distance; + local->unkC = tmp_f2*sp60; - if( prev_anim_progress < 0.55 - && 0.55 <= curr_anim_progress + if( sp4C < 0.55 + && 0.55 <= sp48 && !local->unk5 ){ sfx_playFadeShorthandDefault(SFX_20_METAL_CLANK_1, 1.0f, 32000, this->position, 500, 2500); } if(skeletalAnim_getLoopCount(this->unk148) > 0) - chGrimlet_setState(this, CH_GRIMLET_STATE_1_UNK); + func_803883B0(this, 1); }//L80388BB0 } diff --git a/src/RBB/ch/propellor.c b/src/RBB/ch/propellor.c index 4cbff4e22..881cefc31 100644 --- a/src/RBB/ch/propellor.c +++ b/src/RBB/ch/propellor.c @@ -14,32 +14,27 @@ typedef struct { void chPropellor_update(Actor *this); /* .data */ -ActorInfo chRBBRearPropeller = { - MARKER_185_RBB_REAR_PROPELLER, ACTOR_175_RUSTY_BUCKET_REAR_PROPELLER, ASSET_403_MODEL_RUSTY_BUCKET_REAR_PROPELLER, +ActorInfo D_803906E0 = { + MARKER_185_RBB_REAR_PROPELLER, ACTOR_175_MODEL_RUSTY_BUCKET_REAR_PROPELLER, ASSET_403_MODEL_RUSTY_BUCKET_REAR_PROPELLER, 0x0, NULL, chPropellor_update, NULL, actor_draw, 0, 0, 0.0f, 0 }; -s32 chRBBRearPropellerSpeed[4] = {600, 300, 300, 0}; - -enum chrbbrearpropeller_state_e { - CH_RBB_REAR_PROPELLER_STATE_0_NOT_INIT, - CH_RBB_REAR_PROPELLER_STATE_1_UNK -}; +s32 D_80390704[4] = {0x258, 0x12C, 0x12C, 0}; /*.code */ f32 __chPropellor_getSpeed(void) { - return (f32) chRBBRearPropellerSpeed[2 * levelSpecificFlags_get(LEVEL_FLAG_27_RBB_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_28_RBB_UNKNOWN)]; + return (f32) D_80390704[2 * levelSpecificFlags_get(LEVEL_FLAG_27_RBB_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_28_RBB_UNKNOWN)]; } -void __chPropellor_setState(Actor *this, s32 next_state){ +void __chPropellor_setState(Actor *this, s32 arg1){ ActorLocal_RBB_36A0 * local = (ActorLocal_RBB_36A0 *)&this->local; - if(next_state == CH_RBB_REAR_PROPELLER_STATE_1_UNK){ + if(arg1 == 1){ local->unkC = __chPropellor_getSpeed(); local->unk4 = __chPropellor_getSpeed(); } - this->state = next_state; + this->state = arg1; } int func_80389B44(ActorMarker* marker, s32 arg1){ @@ -55,10 +50,10 @@ void func_80389B80(Actor *this, f32 arg1){ local->unk0 = func_802F9AA8(0x400); func_802F9DB8(local->unk0, arg1, arg1, 0.0f); func_802F9F80(local->unk0, 0.0f, 8999999488.0f, 0.0f); - func_802FA060(local->unk0, 18000, 18000, 0.0f); + func_802FA060(local->unk0, 0x4650, 0x4650, 0.0f); if (!levelSpecificFlags_get(LEVEL_FLAG_3_RBB_UNKNOWN) && !levelSpecificFlags_get(LEVEL_FLAG_4_RBB_UNKNOWN)) { - func_802F9EC4(local->unk0, this->position, 500, 2000); + func_802F9EC4(local->unk0, this->position, 0x1f4, 0x7d0); func_802FA0B0(local->unk0, 1); } } @@ -70,10 +65,10 @@ void __chPropellor_free(Actor *actor){ } -void chPropellor_update(Actor *this){ +void chPropellor_update(Actor *this){ ActorLocal_RBB_36A0 * local = (ActorLocal_RBB_36A0 *)&this->local; - f32 prev_pitch; - f32 time_delta = time_getDelta(); + f32 tmp; + f32 sp34 = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = true; @@ -96,7 +91,7 @@ void chPropellor_update(Actor *this){ }//L80389D7C local->unk4 = 0.0f; local->unkC = 0.0f; - __chPropellor_setState(this, CH_RBB_REAR_PROPELLER_STATE_1_UNK); + __chPropellor_setState(this, 1); if (levelSpecificFlags_get(local->unk8 ? LEVEL_FLAG_4_RBB_UNKNOWN : LEVEL_FLAG_3_RBB_UNKNOWN)) { ncStaticCamera_setToNode(9); @@ -110,10 +105,10 @@ void chPropellor_update(Actor *this){ } }//L80389EA8 - prev_pitch = this->pitch; - this->pitch -= local->unkC * time_delta; - if( (0.0f < prev_pitch && this->pitch <= 0.0f) - || (180.0f < prev_pitch && this->pitch <= 180.0f) + tmp = this->pitch; + this->pitch -= local->unkC*sp34; + if( (0.0f < tmp && this->pitch <= 0.0f) + || (180.0f < tmp && this->pitch <= 180.0f) ){ if (levelSpecificFlags_get(LEVEL_FLAG_3_RBB_UNKNOWN) || levelSpecificFlags_get(LEVEL_FLAG_4_RBB_UNKNOWN)) { func_8030E760(SFX_2_CLAW_SWIPE, 0.4f, 20000); @@ -128,11 +123,11 @@ void chPropellor_update(Actor *this){ if(this->state == 1){ local->unk4 = __chPropellor_getSpeed(); if(local->unkC < local->unk4){ - local->unkC += 75 * time_delta; + local->unkC += 75*sp34; local->unkC = MIN(local->unk4, local->unkC); }//L8038A03C if(local->unk4 < local->unkC){ - local->unkC -= 75 * time_delta; + local->unkC -= 75*sp34; local->unkC = MAX(local->unk4, local->unkC); } }//L8038A08C diff --git a/src/RBB/ch/propellorswitch.c b/src/RBB/ch/propellorswitch.c index e81a65107..e536c2023 100644 --- a/src/RBB/ch/propellorswitch.c +++ b/src/RBB/ch/propellorswitch.c @@ -28,32 +28,25 @@ Struct_RBB_3CB0 D_80390720[2] = { {{0xF9C0, 0x324, 0xF6A0}, 0x405, 4, 0x28} }; -ActorInfo chRBBGreenPropellerSwitch = { - MARKER_186_RBB_GREEN_PROPELLER_SWITCH, ACTOR_176_RBB_GREEN_PROPELLOR_SWITCH, ASSET_404_MODEL_RBB_GREEN_PROPELLER_SWITCH, - 0x0, NULL, +ActorInfo D_80390738 = { + 0x186, 0x176, 0x404, 0x0, NULL, chPropellorSwitch_update, NULL, chPropellorSwitch_draw, 0, 0, 0.0f, 0 }; -enum chrbbgreenpropellerswitch_state_e { - CH_RBB_GREEN_PROPELLER_SWITCH_STATE_0_NOT_INIT, - CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED, - CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED -}; - /* .code */ -void __chPropellorSwitch_setState(Actor *this, s32 next_state){ +void __chPropellorSwitch_setState(Actor *this, s32 arg1){ ActorLocal_RBB_3CB0 *local = (ActorLocal_RBB_3CB0 *)&this->local; - if(next_state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED) - if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED) + if(arg1 == 1) + if(this->state == 2) this->position_y += 40.0f; - if(next_state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED){ - if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED) + if(arg1 == 2){ + if(this->state == 1) func_8030E6D4(SFX_90_SWITCH_PRESS); this->position_y -= 40.0f; - if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED){ + if(this->state == 1){ levelSpecificFlags_set(local->unk0->unk8, 1); musicKeepsPlaying(); timedFunc_set_1(1.1f, (GenFunction_1)func_8028F9DC, 2); @@ -63,13 +56,13 @@ void __chPropellorSwitch_setState(Actor *this, s32 next_state){ } }//L8038A1A0 - this->state = next_state; + this->state = arg1; } void func_8038A1C8(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); if(actor->state == 1){ - __chPropellorSwitch_setState(actor, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED); + __chPropellorSwitch_setState(actor, 2); } else if(actor->state == 2){ rbb_propellorCtrl_start(); @@ -116,16 +109,16 @@ void chPropellorSwitch_update(Actor *this){ this->position_y = (f32)local->unk0->unk0[1]; this->position_z = (f32)local->unk0->unk0[2]; if(levelSpecificFlags_get(local->unk0->unkA)) - __chPropellorSwitch_setState(this, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED); + __chPropellorSwitch_setState(this, 2); else - __chPropellorSwitch_setState(this, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED); + __chPropellorSwitch_setState(this, 1); }//L8038A47C - if(this->state == CH_RBB_GREEN_PROPELLER_SWITCH_STATE_2_PRESSED){ + if(this->state == 2){ if( !levelSpecificFlags_get(local->unk0->unkA) && !levelSpecificFlags_get(LEVEL_FLAG_3_RBB_UNKNOWN) && !levelSpecificFlags_get(LEVEL_FLAG_4_RBB_UNKNOWN) ){ - __chPropellorSwitch_setState(this, CH_RBB_GREEN_PROPELLER_SWITCH_STATE_1_NOT_PRESSED); + __chPropellorSwitch_setState(this, 1); } } } diff --git a/src/RBB/ch/rarewareflag.c b/src/RBB/ch/rarewareflag.c index 9dace4041..6cb471e19 100644 --- a/src/RBB/ch/rarewareflag.c +++ b/src/RBB/ch/rarewareflag.c @@ -3,19 +3,18 @@ #include "functions.h" #include "variables.h" -void chRarewareFlag_update(Actor *this); +void func_8038C300(Actor *this); -ActorInfo chRarewareFlag = { - MARKER_198_RAREWARE_FLAG, ACTOR_1CA_RAREWARE_FLAG, ASSET_41E_MODEL_RAREWARE_FLAG, - 0x0, NULL, - chRarewareFlag_update, NULL, actor_draw, +ActorInfo D_80390B40 = { + 0x198, 0x1ca, 0x41e, 0x0, NULL, + func_8038C300, NULL, actor_draw, 0, 0, 0.0f, 0 }; -void chRarewareFlag_update(Actor *this){ +void func_8038C300(Actor *this){ if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; - skeletalAnim_set(this->unk148, ASSET_140_ANIM_RAREWARE_FLAG, 0.0f, 1.0f); + skeletalAnim_set(this->unk148, 0x140, 0.0f, 1.0f); } } diff --git a/src/RBB/ch/rowboat.c b/src/RBB/ch/rowboat.c index a1f30e8f1..871f28c15 100644 --- a/src/RBB/ch/rowboat.c +++ b/src/RBB/ch/rowboat.c @@ -6,20 +6,19 @@ /* typedefs and declarations */ typedef struct { f32 unk0; - f32 playerInfluencedRotationDelta[3]; // something about rotation - f32 position[3]; - f32 rotation[3]; - f32 timeDelta; - f32 creakingSFXTimer; + f32 unk4[3]; + f32 unk10[3]; + f32 unk1C[3]; + f32 unk28; + f32 unk2C; }ActorLocal_RBB_7FD0; -void chRowboat_update(Actor *this); +void func_8038E3D8(Actor *this); /* .data */ -ActorInfo chRowboat = { - MARKER_1AB_ROWBOAT, ACTOR_297_ROWBOAT, ASSET_43C_MODEL_ROWBOAT, - 0x0, NULL, - chRowboat_update, NULL, actor_draw, +ActorInfo D_80390D50 = { + 0x1ab, 0x297, 0x43C, 0x0, NULL, + func_8038E3D8, NULL, actor_draw, 0, 0, 0.0f, 0 }; @@ -29,86 +28,84 @@ void func_8038E3C0(Actor *this, s32 arg1){ this->state = arg1; } -void chRowboat_update(Actor *this){ - f32 rotation_delta[3]; - f32 position_delta[3]; +void func_8038E3D8(Actor *this){ + f32 sp74[3]; + f32 sp68[3]; ActorLocal_RBB_7FD0 *local = (ActorLocal_RBB_7FD0 *) &this->local; - int rotation_parameter; - f32 time_delta = time_getDelta(); - f32 new_rotation[3]; - f32 player_position[3]; + int i; + f32 sp5C = time_getDelta(); + f32 sp50[3]; + f32 sp44[3]; if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = randf2(80.0f, 100.0f); - local->timeDelta = 0.0f; - local->creakingSFXTimer = 0.5f; + local->unk28 = 0.0f; + local->unk2C = 0.5f; this->position_y -= 10.0f; - local->playerInfluencedRotationDelta[0] = 0.0f; - local->playerInfluencedRotationDelta[1] = 0.0f; - local->playerInfluencedRotationDelta[2] = 0.0f; - local->position[0] = this->position_x; - local->position[1] = this->position_y; - local->position[2] = this->position_z; - local->rotation[0] = this->pitch; - local->rotation[1] = this->yaw; - local->rotation[2] = this->roll; + local->unk4[0] = 0.0f; + local->unk4[1] = 0.0f; + local->unk4[2] = 0.0f; + local->unk10[0] = this->position_x; + local->unk10[1] = this->position_y; + local->unk10[2] = this->position_z; + local->unk1C[0] = this->pitch; + local->unk1C[1] = this->yaw; + local->unk1C[2] = this->roll; func_8038E3C0(this, 1); }//L8038E4C8 - if(ml_timer_update(&local->creakingSFXTimer, time_delta)){ - local->creakingSFXTimer = randf2(3.5f, 5.5f); + if(ml_timer_update(&local->unk2C, sp5C)){ + local->unk2C = randf2(3.5f, 5.5f); func_8030E878(SFX_69_WHIPCRACK_CREAKING, randf2(1.1f, 1.2f), 22000, this->position, 500.0f, 1500.0f); }//L8038E544 - if(func_8032DCAC() == this->marker && player_isStableWithExtraSteps()){ - player_getPosition(player_position); - if(player_position[0] < this->position_x - 10.0f && local->playerInfluencedRotationDelta[2] < 3.0f) - local->playerInfluencedRotationDelta[2] += 5.0f * time_delta; + if(func_8032DCAC() == this->marker && func_8028F20C()){ + player_getPosition(sp44); + if(sp44[0] < this->position_x - 10.0f && local->unk4[2] < 3.0f) + local->unk4[2] += 5.0f*sp5C; - if(this->position_x + 10.0f < player_position[0] && -3.0f < local->playerInfluencedRotationDelta[2]) - local->playerInfluencedRotationDelta[2] -= 5.0f * time_delta; + if(this->position_x + 10.0f < sp44[0] && -3.0f < local->unk4[2]) + local->unk4[2] -= 5.0f*sp5C; - if(this->position_z + 10.0f < player_position[2] && local->playerInfluencedRotationDelta[0] < 5.0f) - local->playerInfluencedRotationDelta[0] += 5.0f * time_delta; + if(this->position_z + 10.0f < sp44[2] && local->unk4[0] < 5.0f) + local->unk4[0] += 5.0f*sp5C; - if(player_position[2] < this->position_z - 10.0f && -5.0f < local->playerInfluencedRotationDelta[0]) - local->playerInfluencedRotationDelta[0] -= 5.0f * time_delta; + if(sp44[2] < this->position_z - 10.0f && -5.0f < local->unk4[0]) + local->unk4[0] -= 5.0f*sp5C; } else{ - for(rotation_parameter = 0; rotation_parameter < 3; rotation_parameter++){ - if(0.0f < local->playerInfluencedRotationDelta[rotation_parameter]){ - local->playerInfluencedRotationDelta[rotation_parameter] -= 2.5 * time_delta; - if(local->playerInfluencedRotationDelta[rotation_parameter] < 0.0f) - local->playerInfluencedRotationDelta[rotation_parameter] = 0.0f; - } else if(local->playerInfluencedRotationDelta[rotation_parameter] < 0.0f) { //L8038E710 - local->playerInfluencedRotationDelta[rotation_parameter] += 2.5 * time_delta; - if(0.0f < local->playerInfluencedRotationDelta[rotation_parameter]) - local->playerInfluencedRotationDelta[rotation_parameter] = 0.0f; + for(i= 0; i< 3; i++){ + if(0.0f < local->unk4[i]){ + local->unk4[i] -= 2.5*sp5C; + if(local->unk4[i] < 0.0f) + local->unk4[i] = 0.0f; + } else if(local->unk4[i] < 0.0f) { //L8038E710 + local->unk4[i] += 2.5*sp5C; + if(0.0f < local->unk4[i]) + local->unk4[i] = 0.0f; }//L8038E74C } }//L8038E754 - local->timeDelta += time_delta; - - position_delta[0] = 0.0f; - position_delta[1] = 5.0f * sinf((((local->timeDelta * 0.8) * local->unk0) / 180.0) * BAD_PI); - position_delta[2] = 0.0f; - - rotation_delta[0] = 4.5 * cosf(((local->timeDelta * local->unk0) / 180.0) * BAD_PI); - rotation_delta[1] = 1.5 * sinf((((local->timeDelta * 0.9) * local->unk0) / 180.0) * BAD_PI); - rotation_delta[2] = 0.0f; - - this->position_x = local->position[0] + position_delta[0]; - this->position_y = local->position[1] + position_delta[1]; - this->position_z = local->position[2] + position_delta[2]; - - new_rotation[0] = local->rotation[0] + rotation_delta[0]; - new_rotation[1] = local->rotation[1] + rotation_delta[1]; - new_rotation[2] = local->rotation[2] + rotation_delta[2]; - - this->pitch = new_rotation[0] + local->playerInfluencedRotationDelta[0]; - this->yaw = new_rotation[1] + local->playerInfluencedRotationDelta[1]; - this->roll = new_rotation[2] + local->playerInfluencedRotationDelta[2]; + local->unk28 += sp5C; + sp68[0] = 0.0f; + sp68[1] = 5.0f * sinf((((local->unk28*0.8)*local->unk0)/180.0)*3.141592654); + sp68[2] = 0.0f; + sp74[0] = 4.5 * cosf(((local->unk28*local->unk0)/180.0) * 3.141592654); + sp74[1] = 1.5 * sinf((((local->unk28*0.9)*local->unk0)/180.0)*3.141592654); + sp74[2] = 0.0f; + + this->position_x = local->unk10[0] + sp68[0]; + this->position_y = local->unk10[1] + sp68[1]; + this->position_z = local->unk10[2] + sp68[2]; + + sp50[0] = local->unk1C[0] + sp74[0]; + sp50[1] = local->unk1C[1] + sp74[1]; + sp50[2] = local->unk1C[2] + sp74[2]; + + this->pitch = sp50[0] + local->unk4[0]; + this->yaw = sp50[1] + local->unk4[1]; + this->roll = sp50[2] + local->unk4[2]; } diff --git a/src/RBB/ch/seamangrublin.c b/src/RBB/ch/seaman_grublin.c similarity index 97% rename from src/RBB/ch/seamangrublin.c rename to src/RBB/ch/seaman_grublin.c index ece17410d..ae6adc460 100644 --- a/src/RBB/ch/seamangrublin.c +++ b/src/RBB/ch/seaman_grublin.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/ch/seamangrublin.c +// BanjoDecomp: (core2 origin - unknown exact file) #include #include "functions.h" #include "variables.h" diff --git a/src/RBB/ch/siren.c b/src/RBB/ch/siren.c new file mode 100644 index 000000000..b876dbea4 --- /dev/null +++ b/src/RBB/ch/siren.c @@ -0,0 +1,61 @@ +// BanjoDecomp: code_9840.c +#include +#include "functions.h" +#include "variables.h" + +void func_8038FC48(Actor *this); + +/* typedefs and declarations */ +typedef struct { + s32 unk0; + s16 *unk4; + ActorMarker *unk8; +}ActorLocal_RBB_9840; + +/* .data */ +s16 RBB_D_80390E30[2] = {0x177, 0x17F}; +ActorInfo D_80390E34 = { + 0x1D2, 0x31B, 0x0, 0x0, NULL, + func_8038FC48, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; +ActorInfo D_80390E58 = { + 0x1D3, 0x31C, 0x0, 0x0, NULL, + func_8038FC48, NULL, func_80325340, + 0, 0, 0.0f, 0 +}; + +/*.code */ +void func_8038FC30(Actor *this, s32 arg1){ + this->state = arg1; +} + +void func_8038FC48(Actor *this){ + ActorLocal_RBB_9840 *local = (ActorLocal_RBB_9840 *)&this->local; + f32 sp20; + f32 tmp_f2; + s32 tmp_a1; + + if(!this->volatile_initialized){ + this->volatile_initialized = true; + actor_collisionOff(this); + local->unk4 = RBB_D_80390E30 + (this->marker->id - 0x1d2); + local->unk8 = NULL; + + local->unk0 = func_802F9AA8(0x400); + func_802F9DB8(local->unk0, 1.0f, 1.0f, 0.0f); + func_802F9EC4(local->unk0, this->position, 0x1f4, 0x3e8); + func_802F9F80(local->unk0, 0.0f, 8999999488.0f, 0.0f); + func_802FA060(local->unk0, 22000, 22000, 0.0f); + func_8038FC30(this, 1); + } + else{//L8038FD34 + if(local->unk8 == NULL) + local->unk8 = actorArray_findActorFromActorId(*local->unk4)->marker; + sp20 = func_8038A6B8(local->unk8); + tmp_f2 = 1.5* sp20 + 0.5; + func_802F9DB8(local->unk0, tmp_f2, tmp_f2, 0.0f); + tmp_a1 = (s32) (sp20*32000.0f); + func_802FA060(local->unk0, tmp_a1, tmp_a1, 0.0f); + } +} diff --git a/src/RBB/ch/whistle.c b/src/RBB/ch/whistle.c index 8b55fc1a7..4517e787e 100644 --- a/src/RBB/ch/whistle.c +++ b/src/RBB/ch/whistle.c @@ -5,48 +5,45 @@ /* typedefs and declarations */ typedef struct { - s16 actorId; - f32 position[3]; + s16 unk0; + f32 unk4[3]; s16 unk10; s16 unk12; s16 unk14; //u8 pad16[2]; -} ActorLocal_ChRBBWhistleInfo; +}Struct_RBB_4C70; typedef struct { - ActorLocal_ChRBBWhistleInfo *unk0; - f32 particlePosition[3]; + Struct_RBB_4C70 *unk0; + f32 unk4[3]; }ActorLocal_RBB_4C70; -Actor *chRBBWhistle_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); -void chRBBWhistle_update(Actor *this); +Actor *func_8038B230(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); +void func_8038B340(Actor *this); /* .data */ -ActorLocal_ChRBBWhistleInfo chRBBWhistleInfo[] = { - { ACTOR_1C2_WHISTLE_1, {-3720.0f, 800.0f, -350.0f}, 0x1, 0x136, 0x3FF}, - { ACTOR_1C3_WHISTLE_2, {-3720.0f, 800.0f, 0.0f}, 0x2, 0x135, 0x3FE}, - { ACTOR_1C4_WHISTLE_3, {-3720.0f, 800.0f, 350.0f}, 0x3, 0x134, 0x3FD}, - { 0 } // [port] decomp uses NULL; actorId is s16 and clang errors on -Wint-conversion +Struct_RBB_4C70 D_80390950[] = { + { 0x1C2, {-3720.0f, 800.0f, -350.0f}, 0x1, 0x136, 0x3FF}, + { 0x1C3, {-3720.0f, 800.0f, 0.0f}, 0x2, 0x135, 0x3FE}, + { 0x1C4, {-3720.0f, 800.0f, 350.0f}, 0x3, 0x134, 0x3FD}, + 0 }; -ActorInfo chRBBWhistle1 = { - MARKER_2A_WHISTLE_1_YELLOW, ACTOR_1C2_WHISTLE_1, ASSET_416_MODEL_WHISTLE, - 0x0, NULL, - chRBBWhistle_update, NULL, chRBBWhistle_draw, +ActorInfo D_803909B0 = { + 0x2A, 0x1C2, 0x416, 0x0, NULL, + func_8038B340, NULL, func_8038B230, 0, 0, 0.0f, 0 }; -ActorInfo chRBBWhistle2 = { - MARKER_2B_WHISTLE_2_YELLOW, ACTOR_1C3_WHISTLE_2, ASSET_416_MODEL_WHISTLE, - 0x0, NULL, - chRBBWhistle_update, NULL, chRBBWhistle_draw, +ActorInfo D_803909D4 = { + 0x2B, 0x1C3, 0x416, 0x0, NULL, + func_8038B340, NULL, func_8038B230, 0, 0, 0.0f, 0 }; -ActorInfo chRBBWhistle3 = { - MARKER_2C_WHISTLE_3_YELLOW, ACTOR_1C4_WHISTLE_3, ASSET_416_MODEL_WHISTLE, - 0x0, NULL, - chRBBWhistle_update, NULL, chRBBWhistle_draw, +ActorInfo RBB_D_803909F8 = { + 0x2C, 0x1C4, 0x416, 0x0, NULL, + func_8038B340, NULL, func_8038B230, 0, 0, 0.0f, 0 }; @@ -59,32 +56,26 @@ ParticleScaleAndLifetimeRanges D_80390A1C = { 0.5f }; -enum chrbbwhistle_state_e { - CH_RBB_WHISTLE_STATE_0_NOT_INIT, - CH_RBB_WHISTLE_STATE_1_IDLE, - CH_RBB_WHISTLE_STATE_2_BLOWING -}; - /* .code */ -ActorLocal_ChRBBWhistleInfo *func_8038B060(Actor *this){ - ActorLocal_ChRBBWhistleInfo * iPtr; - for(iPtr = chRBBWhistleInfo; iPtr->actorId != NULL; iPtr++){ - if(iPtr->actorId == this->modelCacheIndex) +Struct_RBB_4C70 *func_8038B060(Actor *this){ + Struct_RBB_4C70 * iPtr; + for(iPtr = D_80390950; iPtr->unk0 != 0; iPtr++){ + if(iPtr->unk0 == this->modelCacheIndex) return iPtr; } return NULL; } -void chRBBWhistle_setState(Actor *this, s32 next_state){ +void RBB_func_8038B0B8(Actor *this, s32 arg1){ ActorLocal_RBB_4C70 *local = (ActorLocal_RBB_4C70 *)&this->local; ParticleEmitter *other; - this->state = next_state; + this->state = arg1; - if(this->state == CH_RBB_WHISTLE_STATE_2_BLOWING){ + if(this->state == 2){ skeletalAnim_set(this->unk148, local->unk0->unk12, 0.0f, 0.5f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); - timed_playSfx(0.1f, local->unk0->unk14, 1.0f, 32000); + timed_playSfx(0.1f, local->unk0->unk14, 1.0f, 0x7d00); other = partEmitMgr_newEmitter(0xa); particleEmitter_setSprite(other, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setAccelerationRange(other, @@ -96,7 +87,7 @@ void chRBBWhistle_setState(Actor *this, s32 next_state){ -5.0f, -5.0f, 0.0f, 5.0f, 5.0f, 0.0f ); - particleEmitter_setPosition(other, local->particlePosition); + particleEmitter_setPosition(other, local->unk4); particleEmitter_setParticleVelocityRange(other, -400.0f, 0.0f, -30.0f, -800.0f, 0.0f, 30.0f @@ -106,10 +97,10 @@ void chRBBWhistle_setState(Actor *this, s32 next_state){ } } -Actor *chRBBWhistle_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3){ +Actor *func_8038B230(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3){ Actor *actor = marker_getActor(marker); ActorLocal_RBB_4C70 *local = (ActorLocal_RBB_4C70 *)&actor->local; - f32 actor_rotation[3]; + f32 sp3C[3]; if(actor->state == 0) return actor; @@ -118,45 +109,45 @@ Actor *chRBBWhistle_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3) modelRender_setBoneTransformList(skeletalAnim_getBoneTransformList(actor->unk148)); } - actor_rotation[0] = actor->pitch; - actor_rotation[1] = actor->yaw; - actor_rotation[2] = actor->roll; + sp3C[0] = actor->pitch; + sp3C[1] = actor->yaw; + sp3C[2] = actor->roll; modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)actor); modelRender_setRefPoints(func_80329934()); - modelRender_draw(gdl, mptr, actor->position, actor_rotation, actor->scale, NULL, marker_loadModelBin(marker)); - vec3fArray_get_vec3f(func_80329934(), 5, local->particlePosition); - local->particlePosition[0] -= 60.0f; + modelRender_draw(gdl, mptr, actor->position, sp3C, actor->scale, NULL, marker_loadModelBin(marker)); + vec3fArray_get_vec3f(func_80329934(), 5, local->unk4); + local->unk4[0] -= 60.0f; return actor; } -void chRBBWhistle_update(Actor * this){ +void func_8038B340(Actor * this){ ActorLocal_RBB_4C70 *local = (ActorLocal_RBB_4C70 *)&this->local; if(!this->volatile_initialized){ this->marker->propPtr->unk8_3 = 1; this->volatile_initialized = true; local->unk0 = func_8038B060(this); - local->particlePosition[2] = 0.0f; - local->particlePosition[1] = 0.0f; - local->particlePosition[0] = 0.0f; + local->unk4[2] = 0.0f; + local->unk4[1] = 0.0f; + local->unk4[0] = 0.0f; - this->position_x = local->unk0->position[0]; - this->position_y = local->unk0->position[1]; - this->position_z = local->unk0->position[2]; + this->position_x = local->unk0->unk4[0]; + this->position_y = local->unk0->unk4[1]; + this->position_z = local->unk0->unk4[2]; this->yaw = -90.0f; this->scale = 0.25f; - chRBBWhistle_setState(this, CH_RBB_WHISTLE_STATE_1_IDLE); + RBB_func_8038B0B8(this, 1); }//L8038B3E4 - if(this->state == CH_RBB_WHISTLE_STATE_1_IDLE){ + if(this->state == 1){ if(mapSpecificFlags_get(local->unk0->unk10)) - chRBBWhistle_setState(this, CH_RBB_WHISTLE_STATE_2_BLOWING); + RBB_func_8038B0B8(this, 2); } - if(this->state == CH_RBB_WHISTLE_STATE_2_BLOWING){ + if(this->state == 2){ if( skeletalAnim_getLoopCount(this->unk148) > 0 ) - chRBBWhistle_setState(this, CH_RBB_WHISTLE_STATE_1_IDLE); + RBB_func_8038B0B8(this, 1); } } diff --git a/src/RBB/ch/whistlectrl.c b/src/RBB/ch/whistlectrl.c index 3cde18b54..76d6dc6e7 100644 --- a/src/RBB/ch/whistlectrl.c +++ b/src/RBB/ch/whistlectrl.c @@ -3,31 +3,24 @@ #include "functions.h" #include "variables.h" +extern ActorInfo D_80390FD0; + typedef struct { - s16 currentIndex; + s16 unk0; s16 unk2; - u8 *codeString; + u8 *unk4; }ActorLocal_RBB_5060; void chWhistleCtrl_update(Actor * this); /* .data */ -ActorInfo chRBBWhistleCtrl = { - MARKER_2D_WHISTLE_CTRL, ACTOR_1C5_WHISTLE_CTRL, 0x0, - 0x0, NULL, +ActorInfo D_80390A50 = { + 0x2D, 0x1C5, 0x0, 0x0, NULL, chWhistleCtrl_update, NULL, func_80325340, 0, 0, 0.0f, 0 }; -f32 chRBBWhistleCtrlJiggyPosition[3] = {-3820.0f, 850.0f, 0.0f}; - -enum chrbbwhistlectrl_state_e { - CH_RBB_WHISTLE_CTRL_STATE_0_NOT_INIT, - CH_RBB_WHISTLE_CTRL_STATE_1_AWAITING_PLAYER, - CH_RBB_WHISTLE_CTRL_STATE_2_COMPLETE -}; - -#define RBB_WHISTLE_CODE "312111" +f32 D_80390A74[3] = {-3820.0f, 850.0f, 0.0f}; //whistle jiggy spawn position /* .code */ void __chWhistleCtrl_setState(Actor *actor, s32 arg1){ @@ -36,7 +29,7 @@ void __chWhistleCtrl_setState(Actor *actor, s32 arg1){ void __chWhistleCtrl_soundWhistle(void){ bundle_setYaw(225.0f); - jiggy_spawn(JIGGY_54_RBB_WHISTLE, chRBBWhistleCtrlJiggyPosition); + jiggy_spawn(JIGGY_54_RBB_WHISTLE, D_80390A74); } void __chWhistleCtrl_correct(void){ @@ -60,13 +53,13 @@ void __chWhistleCtrl_complete(void){ s32 chWhistleCtrl_newEvent(Actor *this, s32 whistle_id, Actor *other){ ActorLocal_RBB_5060 *local = (ActorLocal_RBB_5060 *)&this->local; - if(this->state != CH_RBB_WHISTLE_CTRL_STATE_1_AWAITING_PLAYER) + if(this->state != 1) return 0; - if(whistle_id + 0x30 == local->codeString[local->currentIndex]){ //correct - if(local->codeString[++local->currentIndex] == 0){ //end of string + if(whistle_id + 0x30 == local->unk4[local->unk0]){ //correct + if(local->unk4[++local->unk0] == 0){ //end of string timedFunc_set_0(0.6f, __chWhistleCtrl_complete); //spawn jiggy - __chWhistleCtrl_setState(this, CH_RBB_WHISTLE_CTRL_STATE_2_COMPLETE); + __chWhistleCtrl_setState(this, 2); return 3; }else{ timedFunc_set_0(0.6f, __chWhistleCtrl_correct); @@ -75,7 +68,7 @@ s32 chWhistleCtrl_newEvent(Actor *this, s32 whistle_id, Actor *other){ } else{ //wrong timedFunc_set_1(1.0f, (GenFunction_1)__chWhistleCtrl_wrong, (uintptr_t)other->marker); - local->currentIndex = 0; + local->unk0 = 0; return 2; } } @@ -86,10 +79,10 @@ void chWhistleCtrl_update(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; local->unk2 = 1; - local->codeString = RBB_WHISTLE_CODE; + local->unk4 = "312111"; if(jiggyscore_isSpawned(JIGGY_54_RBB_WHISTLE)) - __chWhistleCtrl_setState(this, CH_RBB_WHISTLE_CTRL_STATE_2_COMPLETE); + __chWhistleCtrl_setState(this, 2); else - __chWhistleCtrl_setState(this, CH_RBB_WHISTLE_CTRL_STATE_1_AWAITING_PLAYER); + __chWhistleCtrl_setState(this, 1); } } diff --git a/src/RBB/ch/whistleswitch.c b/src/RBB/ch/whistleswitch.c index 0305f4fdc..443d4206f 100644 --- a/src/RBB/ch/whistleswitch.c +++ b/src/RBB/ch/whistleswitch.c @@ -3,139 +3,111 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - void vtxList_tintColorsFrom(BKVertexList *dst, s32 target_color[3], f32 amount, BKVertexList *src); BKVertexList *vtxList_clone(BKVertexList *); /* typedefs and declarations */ typedef struct { - s16 actorId; - f32 position[3]; - s16 mapSpecificFlag; -} Struct_ChWhistleSwitchInfo; + s16 unk0; + f32 unk4[3]; + s16 unk10; + u8 pad12[2]; +}Struct_RBB_47D0; typedef struct { u8 unk0; u8 pad1[3]; - Struct_ChWhistleSwitchInfo *whistleSwitchInfo; + Struct_RBB_47D0 *unk4; f32 unk8; BKVertexList *unkC; - // [port] Back buffer for unkC. See chRBBWhistleSwitch_draw. - BKVertexList *portVtxBack; -} ActorLocal_RBB_47D0; +}ActorLocal_RBB_47D0; -Actor *chRBBWhistleSwitch_draw(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); -void chRBBWhistleSwitch_update(Actor *this); +Actor *func_8038AD9C(ActorMarker *marker, Gfx** gdl, Mtx** mptr, Vtx **arg3); +void func_8038AEB8(Actor *this); /* .data */ -Struct_ChWhistleSwitchInfo chWhistleSwitchTable[4] = { - {ACTOR_1BF_WHISTLE_SWITCH_1, {-3950.0f, 690.0f, -350.0f}, RBB_MAIN_SPECIFIC_FLAG_1_WHISTLE_SWITCH_1}, - {ACTOR_1C0_WHISTLE_SWITCH_2, {-3950.0f, 690.0f, 0.0f}, RBB_MAIN_SPECIFIC_FLAG_2_WHISTLE_SWITCH_2}, - {ACTOR_1C1_WHISTLE_SWITCH_3, {-3950.0f, 690.0f, 350.0f}, RBB_MAIN_SPECIFIC_FLAG_3_WHISTLE_SWITCH_3}, - { 0 } // [port] decomp uses NULL; actorId is s16 and clang errors on -Wint-conversion +Struct_RBB_47D0 D_80390870[4] = { + {0x1BF, {-3950.0f, 690.0f, -350.0f}, 1}, + {0x1C0, {-3950.0f, 690.0f, 0.0f}, 2}, + {0x1C1, {-3950.0f, 690.0f, 350.0f}, 3}, + 0 }; -extern ActorInfo chRBBWhistleSwitch1 = { - MARKER_195_WHISTLE_SWITCH_1, ACTOR_1BF_WHISTLE_SWITCH_1, ASSET_413_MODEL_WHISTLE_SWITCH_1, - 0x0, NULL, - chRBBWhistleSwitch_update, NULL, chRBBWhistleSwitch_draw, +extern ActorInfo D_803908C0 = { + 0x195, 0x1BF, 0x413, 0x0, NULL, + func_8038AEB8, NULL, func_8038AD9C, 0, 0, 0.0f, 0 }; - -extern ActorInfo chRBBWhistleSwitch2 = { - MARKER_196_WHISTLE_SWITCH_2, ACTOR_1C0_WHISTLE_SWITCH_2, ASSET_414_MODEL_WHISTLE_SWITCH_2, - 0x0, NULL, - chRBBWhistleSwitch_update, NULL, chRBBWhistleSwitch_draw, +extern ActorInfo D_803908E4 = { + 0x196, 0x1C0, 0x414, 0x0, NULL, + func_8038AEB8, NULL, func_8038AD9C, 0, 0, 0.0f, 0 }; -extern ActorInfo chRBBWhistleSwitch3 = { - MARKER_197_WHISTLE_SWITCH_3, ACTOR_1C1_WHISTLE_SWITCH_3, ASSET_415_MODEL_WHISTLE_SWITCH_3, - 0x0, NULL, - chRBBWhistleSwitch_update, NULL, chRBBWhistleSwitch_draw, +extern ActorInfo D_80390908 = { + 0x197, 0x1C1, 0x415, 0x0, NULL, + func_8038AEB8, NULL, func_8038AD9C, 0, 0, 0.0f, 0 }; s32 D_8039092C[3] = { 0, 0xFF, 0}; s32 D_80390938[3] = { 0xFF, 0, 0}; -enum chrbbwhistleswitch_state_e { - CH_RBB_WHISTLE_SWITCH_STATE_0_NOT_INIT, - CH_RBB_WHISTLE_SWITCH_STATE_1_UNK, - CH_RBB_WHISTLE_SWITCH_STATE_2_UNK -}; - /* .code */ -Struct_ChWhistleSwitchInfo *chWhistleSwitch_getInfoPointer(Actor *this){ - Struct_ChWhistleSwitchInfo *iPtr = chWhistleSwitchTable; - while(iPtr->actorId != NULL){ - if(iPtr->actorId == this->modelCacheIndex) +Struct_RBB_47D0 *RBB_func_8038ABC0(Actor *arg0){ + Struct_RBB_47D0 *iPtr = D_80390870; + while(iPtr->unk0 != 0){ + if(iPtr->unk0 == arg0->modelCacheIndex) return iPtr; iPtr++; } return NULL; } -void chRBBWhistleSwitch_setState(Actor *this, s32 new_state){ +void func_8038AC18(Actor *this, s32 new_state){ ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&this->local; Actor *whistle_ctrl; local->unk8 = 0.0f; - if(new_state == CH_RBB_WHISTLE_SWITCH_STATE_2_UNK){ + if(new_state == 2){ func_8030E6D4(SFX_90_SWITCH_PRESS); - // [port] Clone once and keep it. Freeing on release hands the buffer back - // while a display list built from this tick may still be queued for the - // render thread. - if(local->unkC == NULL){ - BKVertexList *src = modelbin_getVtxList(marker_loadModelBin(this->marker)); - local->unkC = vtxList_clone(src); - local->portVtxBack = vtxList_clone(src); - } + local->unkC = vtxList_clone(modelbin_getVtxList(marker_loadModelBin(this->marker))); - mapSpecificFlags_set(local->whistleSwitchInfo->mapSpecificFlag, true); + mapSpecificFlags_set(local->unk4->unk10, true); this->position_y -= 30.0f; local->unk8 = 1.0f; - whistle_ctrl = actorArray_findActorFromActorId(ACTOR_1C5_WHISTLE_CTRL); + whistle_ctrl = actorArray_findActorFromActorId(0x1c5); if(whistle_ctrl){ - local->unk0 = chWhistleCtrl_newEvent(whistle_ctrl, this->modelCacheIndex - ACTOR_1BE_RBB_GREY_PROPELLOR_SWITCH, this); + local->unk0 = chWhistleCtrl_newEvent(whistle_ctrl, this->modelCacheIndex - 0x1be, this); } }//L8038ACD0 - if(this->state == CH_RBB_WHISTLE_SWITCH_STATE_2_UNK){ - this->position_x = local->whistleSwitchInfo->position[0]; - this->position_y = local->whistleSwitchInfo->position[1]; - this->position_z = local->whistleSwitchInfo->position[2]; + if(this->state == 2){ + this->position_x = local->unk4->unk4[0]; + this->position_y = local->unk4->unk4[1]; + this->position_z = local->unk4->unk4[2]; + vtxList_free(local->unkC); } this->state = new_state; } -void chRBBWhistleSwitch_press(ActorMarker *marker, ActorMarker *arg1){ +void func_8038AD3C(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); if(actor->state == 1) - chRBBWhistleSwitch_setState(actor, 2); + func_8038AC18(actor, 2); } -void chRBBWhistleSwitch_free(Actor *this){ - ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&this->local; - chRBBWhistleSwitch_setState(this, CH_RBB_WHISTLE_SWITCH_STATE_0_NOT_INIT); - if(local->unkC != NULL){ - // [port] No queued display list may still reference these vertices once - // they are handed back to the heap. - port_pipelineSyncPoint(); - vtxList_free(local->unkC); - vtxList_free(local->portVtxBack); - local->unkC = NULL; - local->portVtxBack = NULL; - } +void func_8038AD7C(Actor *this){ + func_8038AC18(this, 0); } -Actor *chRBBWhistleSwitch_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ +Actor *func_8038AD9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ Actor * actor = marker_getActor(marker); ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&actor->local; BKModelBin *temp_v0; f32 pad0; s32 *sp1C; + if(actor->state == 0) return actor; @@ -143,62 +115,48 @@ Actor *chRBBWhistleSwitch_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx * if( actor->state == 2 && local->unk0 != 0 ){ - BKVertexList *swap; - temp_v0 = marker_loadModelBin(marker); sp1C = (local->unk0 == 2) ? D_80390938 : D_8039092C; - - // [port] Alternate between two clones. - swap = local->unkC; - local->unkC = local->portVtxBack; - local->portVtxBack = swap; - vtxList_tintColorsFrom(local->unkC, sp1C, - (local->whistleSwitchInfo->position[1] - actor->position_y) / 30.0, + (local->unk4->unk4[1] - actor->position_y)/30.0, modelbin_getVtxList(temp_v0) ); modelRender_setVertexList(local->unkC); } - return actor_draw(marker, gdl, mptr, arg3); } -void chRBBWhistleSwitch_update(Actor *this){ +void func_8038AEB8(Actor *this){ ActorLocal_RBB_47D0 *local = (ActorLocal_RBB_47D0 *)&this->local; - f32 time_delta = time_getDelta(); - s32 y_position; + f32 sp20 = time_getDelta(); + s32 tmp; if(!this->volatile_initialized){ this->volatile_initialized = true; - // [port] The map savestate memcpys `local` wholesale and only nulls the - // Actor's own heap pointers, so these two come back pointing at freed - // vertices. Drop them before anything can reuse or free them again. - local->unkC = NULL; - local->portVtxBack = NULL; this->marker->propPtr->unk8_3 = 1; - this->marker->actorFreeFunc = chRBBWhistleSwitch_free; - marker_setCollisionScripts(this->marker, NULL, chRBBWhistleSwitch_press, NULL); - local->whistleSwitchInfo = chWhistleSwitch_getInfoPointer(this); - mapSpecificFlags_set(local->whistleSwitchInfo->mapSpecificFlag, false); - this->position_x = local->whistleSwitchInfo->position[0]; - this->position_y = local->whistleSwitchInfo->position[1]; - this->position_z = local->whistleSwitchInfo->position[2]; + this->marker->actorFreeFunc = func_8038AD7C; + marker_setCollisionScripts(this->marker, NULL, func_8038AD3C, NULL); + local->unk4 = RBB_func_8038ABC0(this); + mapSpecificFlags_set(local->unk4->unk10, false); + this->position_x = local->unk4->unk4[0]; + this->position_y = local->unk4->unk4[1]; + this->position_z = local->unk4->unk4[2]; this->yaw = -90.0f; - chRBBWhistleSwitch_setState(this, CH_RBB_WHISTLE_SWITCH_STATE_1_UNK); + func_8038AC18(this, 1); }//L8038AF88 - if(ml_timer_update(&local->unk8, time_delta)) - chRBBWhistleSwitch_setState(this, CH_RBB_WHISTLE_SWITCH_STATE_1_UNK); + if(ml_timer_update(&local->unk8, sp20)) + func_8038AC18(this, 1); - if(this->state == CH_RBB_WHISTLE_SWITCH_STATE_2_UNK){ - y_position = (s32)this->position_y; - if(this->position_y < local->whistleSwitchInfo->position[1]) - this->position_y += 60.0f * time_delta; + if(this->state == 2){ + tmp = (s32)this->position_y; + if(this->position_y < local->unk4->unk4[1]) + this->position_y += 60.0f*sp20; - if( y_position < local->whistleSwitchInfo->position[1] - 15.0f - && local->whistleSwitchInfo->position[1] - 15.0f <= this->position_y + if( tmp < local->unk4->unk4[1] - 15.0f + && local->unk4->unk4[1] - 15.0f <= this->position_y ){ - mapSpecificFlags_set(local->whistleSwitchInfo->mapSpecificFlag, false); + mapSpecificFlags_set(local->unk4->unk10, false); } }//L8038B044 } diff --git a/src/RBB/checksums.c b/src/RBB/checksums.c deleted file mode 100644 index 37275e9d0..000000000 --- a/src/RBB/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: RBB/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsRBB; diff --git a/src/RBB/crane_boombox.c b/src/RBB/crane_boombox.c index d3bc55879..326281704 100644 --- a/src/RBB/crane_boombox.c +++ b/src/RBB/crane_boombox.c @@ -6,16 +6,14 @@ #include - /* typedefs and declarations */ -void chTNTDownSwitch_setState(Actor *this, s32 arg1); -void chTNTDownSwitch_update(Actor *this); +void func_803881E8(Actor *this, s32 arg1); +void RBB_func_803882F4(Actor *this); /* .data */ -ActorInfo chTNTDownSwitch = { - MARKER_184_RBB_TNT_DOWN_SWITCH, ACTOR_174_RBB_TNT_DOWN_SWITCH, ASSET_402_MODEL_EGG_TOLL, - 0x0, NULL, - chTNTDownSwitch_update, NULL, func_80325340, +ActorInfo D_80390270 = { + 0x184, 0x174, 0x402, 0x0, NULL, + RBB_func_803882F4, NULL, func_80325340, 0, 0, 0.0f, 0 }; @@ -24,11 +22,11 @@ s32 D_803902A4[4] = { 0x76, 0, 0, 0xff}; s32 D_803902B4[4] = { 0x76, 0, 0, 0xff}; s32 D_803902C4[4] = { 0xff, 0, 0, 0xff}; + f32 D_803902D4[3] = {4500.0f, 0.0f, 500.0f}; f32 D_803902E0[3] = {4500.0f, 0.0f, 500.0f}; f32 D_803902EC[3] = {4000.0f, -600.0f, 0.0f}; f32 D_803902F8[3] = {4500.0f, 0.0f, 500.0f}; - ParticleScaleAndLifetimeRanges D_80390304 = { { 5.0f, 5.0f}, { 5.0f, 5.0f}, @@ -40,18 +38,11 @@ ParticleScaleAndLifetimeRanges D_80390304 = { f32 D_8039032C[3] = {3700.0f, -300.0f, -300.0f}; f32 D_80390338[3] = {4500.0f, 100.0f, 400.0f}; - ParticleSettingsVelocityAcceleration D_80390344= { {{-700.0f, 200.0f, -700.0f}, {700.0f, 500.0f, 700.0f}}, {{ 0.0f, -800.0f, 0.0f}, { 0.0f, -800.0f, 0.0f}} }; -enum chtntdownswitch_state_e { - CH_TNT_DOWN_SWITCH_STATE_0_NOT_INIT, - CH_TNT_DOWN_SWITCH_STATE_1_NOT_PRESSED, - CH_TNT_DOWN_SWITCH_STATE_2_PRESSED -}; - /*.code */ void RBB_func_80387960(f32 arg0){ f32 sp34[3]; @@ -123,7 +114,7 @@ void func_80387B8C(s32 arg0, s32 arg1){ Struct70s *tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *v0 = &tmp_s70->type_6D; - func_8034DFB0(v0, D_80390294, D_803902A4, (f64)arg1 / 1000.0); + func_8034DFB0(v0, D_80390294, D_803902A4, (f64)arg1/1000.0); } } @@ -133,11 +124,11 @@ void func_80387BEC(s32 arg0, s32 arg1){ tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *v0 = &tmp_s70->type_6D; - func_8034DFB0(v0, D_803902B4, D_803902C4, (f64)arg1 / 1000.0); + func_8034DFB0(v0, D_803902B4, D_803902C4, (f64)arg1/1000.0); } } -void chTNTDownSwitch_emitExplosion(void){ +void func_80387C5C(void){ ParticleEmitter *actor; func_802BB3DC(0, 60.0f, 0.9f); @@ -154,7 +145,7 @@ void chTNTDownSwitch_emitExplosion(void){ particleEmitter_emitInVolume(actor, D_803902D4, D_803902E0, 1); } -void chTNTDownSwitch_emitSmoke(void){ +void func_80387D80(void){ ParticleEmitter *actor = partEmitMgr_newEmitter(3); particleEmitter_setSprite(actor, ASSET_70E_SPRITE_SMOKE_2); particleEmitter_setStartingFrameRange(actor, 0, 7); @@ -163,11 +154,11 @@ void chTNTDownSwitch_emitSmoke(void){ particleEmitter_emitInVolume(actor, D_803902EC, D_803902F8, 3); } -void chTNTDownSwitch_emitWoodenPlank(void){ +void func_80387E20(void){ ParticleEmitter *actor = partEmitMgr_newEmitter(0x19); particleEmitter_func_802EF9F8(actor, 0.6f); particleEmitter_func_802EFA18(actor, 3); - particleEmitter_setModel(actor, ASSET_427_MODEL_WOODEN_PLANK); + particleEmitter_setModel(actor, 0x427); particleEmitter_setStartingScaleRange(actor, 0.05f, 0.4f); particleEmitter_setAngularVelocityRange(actor, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f); particleEmitter_setSpawnIntervalRange(actor, 0.0f, 0.01f); @@ -176,67 +167,67 @@ void chTNTDownSwitch_emitWoodenPlank(void){ particleEmitter_emitInVolume(actor, D_8039032C, D_80390338, 0x19); } -void chTNTDownSwitch_setStateByMarker(ActorMarker *marker, s32 next_state){ - chTNTDownSwitch_setState(marker_getActor(marker), next_state); +void RBB_func_80387F18(ActorMarker *marker, s32 arg1){ + func_803881E8(marker_getActor(marker), arg1); } void RBB_func_80387F44(void){ baMotor_80250E94(0.5f, 1.0f, 1.5f, 0.0f, 1.0f, 1.5f); } -void chTNTDownSwitch_emits(ActorMarker *marker){ +void func_80387F88(ActorMarker *marker){ Actor *actor = marker_getActor(marker); - timedFunc_set_0(0.0f, chTNTDownSwitch_emitExplosion); + timedFunc_set_0(0.0f, func_80387C5C); timed_playSfx(0.1f, SFX_1B_EXPLOSION_1, 1.0f, 22000); timed_playSfx(0.1f, SFX_1B_EXPLOSION_1, 1.0f, 22000); - timedFunc_set_0(0.3f, chTNTDownSwitch_emitWoodenPlank); + timedFunc_set_0(0.3f, func_80387E20); timedFunc_set_0(0.5f, func_80387A54); timedFunc_set_0(0.4f, func_80387B24); timed_playSfx(0.41f, SFX_1B_EXPLOSION_1, 0.8f, 22000); timed_playSfx(0.41f, SFX_1B_EXPLOSION_1, 0.8f, 22000); - timedFunc_set_0(0.55f, chTNTDownSwitch_emitSmoke); + timedFunc_set_0(0.55f, func_80387D80); timed_playSfx(0.71f, SFX_1B_EXPLOSION_1, 0.6f, 22000); timed_playSfx(0.71f, SFX_1B_EXPLOSION_1, 0.6f, 22000); - timedFunc_set_0(0.8f, chTNTDownSwitch_emitSmoke); + timedFunc_set_0(0.8f, func_80387D80); timed_playSfx(1.0f, SFX_1A_BIG_THINGS_FALL_OVER, 1.0f, 22000); timed_playSfx(2.0f, SFX_1A_BIG_THINGS_FALL_OVER, 0.8f, 22000); timed_playSfx(3.0f, SFX_1A_BIG_THINGS_FALL_OVER, 0.6f, 22000); timed_exitStaticCamera(4.0f); func_80324E38(4.0f, 0); - timedFunc_set_2(4.0f, (GenFunction_2) chTNTDownSwitch_setStateByMarker, (uintptr_t)actor->marker, 3); + timedFunc_set_2(4.0f, (GenFunction_2) RBB_func_80387F18, (uintptr_t)actor->marker, 3); } -void chTNTDownSwitch_dropTNTActions(ActorMarker *marker){ +void func_80388154(ActorMarker *marker){ Actor *actor = marker_getActor(marker); func_803879F0(); timedFunc_set_0(0.0f, (GenFunction_0) RBB_func_80387F44); - timed_playSfx(0.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 32710); + timed_playSfx(0.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 0x7fc6); timedFunc_set_2(1.2f, (GenFunction_2) func_80387B8C, 0x19f, 0); timed_setStaticCameraToNode(1.2f, 8); - timedFunc_set_1(1.5f, (GenFunction_1) chTNTDownSwitch_emits, (uintptr_t)actor->marker); + timedFunc_set_1(1.5f, (GenFunction_1) func_80387F88, (uintptr_t)actor->marker); } -void chTNTDownSwitch_setState(Actor *this, s32 next_state){ - this->state = next_state; - if(this->state == CH_TNT_DOWN_SWITCH_STATE_2_PRESSED){ +void func_803881E8(Actor *this, s32 arg1){ + this->state = arg1; + if(this->state == 2){ RBB_func_80387960(0.05f); timedFunc_set_2(0.05f, (GenFunction_2)func_80387BEC, 0x19f, 0x1f4); timedFunc_set_2(0.1f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2B_DING_B, 28000); func_80324E38(0.2f, 3); timed_setStaticCameraToNode(1.1f, 7); - timedFunc_set_1(1.6f, (GenFunction_1)chTNTDownSwitch_dropTNTActions, (uintptr_t)this->marker); + timedFunc_set_1(1.6f, (GenFunction_1)func_80388154, (uintptr_t)this->marker); levelSpecificFlags_set(LEVEL_FLAG_2D_RBB_UNKNOWN, true); } } -void chTNTDownSwitch_pushSwitch(ActorMarker *marker, ActorMarker *arg1){ +void func_803882B4(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - if(actor->state == CH_TNT_DOWN_SWITCH_STATE_1_NOT_PRESSED) - chTNTDownSwitch_setState(actor, CH_TNT_DOWN_SWITCH_STATE_2_PRESSED); + if(actor->state == 1) + func_803881E8(actor, 2); } -void chTNTDownSwitch_update(Actor *this){ +void RBB_func_803882F4(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; @@ -244,19 +235,12 @@ void chTNTDownSwitch_update(Actor *this){ func_80387AC0(); RBB_func_80387960(0.0f); func_80387B24(); - chTNTDownSwitch_setState(this, 3); + func_803881E8(this, 3); } else { - marker_setCollisionScripts(this->marker, NULL, chTNTDownSwitch_pushSwitch, NULL); + marker_setCollisionScripts(this->marker, NULL, func_803882B4, NULL); suSetSpriteScale(this, 1.1f); - chTNTDownSwitch_setState(this, 1); + func_803881E8(this, 1); } } - // Anchor: teammate opened the entrance (LEVEL_FLAG_2D) - snap to opened state. - else if (this->state == 1 && levelSpecificFlags_get(LEVEL_FLAG_2D_RBB_UNKNOWN)) { - func_80387AC0(); - RBB_func_80387960(0.0f); - func_80387B24(); - chTNTDownSwitch_setState(this, 3); - } } diff --git a/src/RBB/crane_jiggycage.c b/src/RBB/crane_jiggycage.c index 3be35a292..a42412af0 100644 --- a/src/RBB/crane_jiggycage.c +++ b/src/RBB/crane_jiggycage.c @@ -6,19 +6,13 @@ #include /* typedefs and declarations */ -void chCageUpSwitch_update(Actor *this); -void chCageUpSwitch_setState(Actor *this, s32 arg1); - -// Anchor: set while replaying a teammate's crane action; suppresses camera pans and auto-raise. -static s32 sCraneRemote = 0; -extern void port_jiggyCrane_broadcast(s32 stage); -extern ActorArray *suBaddieActorArray; +void func_803878B0(Actor *this); +void func_8038756C(Actor *this, s32 arg1); /* .data */ -ActorInfo chCageUpSwitch = { - MARKER_183_RBB_CAGE_UP_SWITCH, ACTOR_173_RBB_CAGE_UP_SWITCH, ASSET_402_MODEL_EGG_TOLL, - 0x0, NULL, - chCageUpSwitch_update, NULL, func_80325340, +ActorInfo D_80390200 = { + 0x183, 0x173, 0x402, 0x0, NULL, + func_803878B0, NULL, func_80325340, 0, 0, 0.0f, 0 }; @@ -29,24 +23,16 @@ s32 D_80390254[4] = { 0xff, 0, 0, 0xff}; f32 D_80390264[3] = {-4900.0f, 0.0f, 0.0f}; -enum chcageupswitch_state_e { - CH_CAGE_UP_SWITCH_STATE_0_NOT_INIT, - CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED, - CH_CAGE_UP_SWITCH_STATE_2_RAISING_CAGE, - CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE, - CH_CAGE_UP_SWITCH_STATE_4_LOWER_CAGE -}; - /* .code */ -void chCageUpSwitch_setStateByMarker(ActorMarker *marker, s32 next_state){ - chCageUpSwitch_setState(marker_getActor(marker), next_state); +void func_80387090(ActorMarker *marker, s32 arg1){ + func_8038756C(marker_getActor(marker), arg1); } void func_803870BC(s32 arg0, s32 arg1){ Struct70s *tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *temp_v0 = &tmp_s70->type_6D; - func_8034DFB0(temp_v0, D_80390224, D_80390234, (f64)arg1 / 1000.0); + func_8034DFB0(temp_v0, D_80390224, D_80390234, (f64)arg1/1000.0); } } @@ -56,7 +42,7 @@ void func_8038711C(s32 arg0, s32 arg1){ tmp_s70 = func_8034C528(arg0); if(tmp_s70){ Struct6Ds *temp_v0 = &tmp_s70->type_6D; - func_8034DFB0(temp_v0, D_80390244, D_80390254, (f64)arg1 / 1000.0); + func_8034DFB0(temp_v0, D_80390244, D_80390254, (f64)arg1/1000.0); } } @@ -73,21 +59,17 @@ void func_8038718C(ActorMarker *marker){ func_8034DDF0(sp44, sp38, sp2C, 4.0f, 1); func_8034E1A4(sp44, SFX_D8_CRANE, 1.0f, 1.0f); } - if (!sCraneRemote) { - timed_setStaticCameraToNode(0.0f, 4); - timed_setStaticCameraToNode(2.5f, 5); - } + timed_setStaticCameraToNode(0.0f, 4); + timed_setStaticCameraToNode(2.5f, 5); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.5f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.6f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.7f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 0.9f, 19000); timed_playSfx(4.0f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 19000);\ - if (!sCraneRemote) { - timed_exitStaticCamera(5.0f); - func_80324E38(5.0f, 0); - } - timedFunc_set_2(5.0f, (GenFunction_2) chCageUpSwitch_setStateByMarker, (uintptr_t)marker, CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE); + timed_exitStaticCamera(5.0f); + func_80324E38(5.0f, 0); + timedFunc_set_2(5.0f, (GenFunction_2) func_80387090, (uintptr_t) marker, 3); } void func_80387308(ActorMarker *marker){ @@ -109,35 +91,32 @@ void func_80387308(ActorMarker *marker){ timed_playSfx(0.5f, SFX_7F_HEAVYDOOR_SLAM, 0.8f, 19000); timed_playSfx(0.5f, SFX_7F_HEAVYDOOR_SLAM, 0.9f, 19000); timed_playSfx(0.5f, SFX_7F_HEAVYDOOR_SLAM, 1.0f, 19000); - timedFunc_set_2(0.5f, (GenFunction_2) chCageUpSwitch_setStateByMarker, (uintptr_t)actor->marker, CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED); + timedFunc_set_2(0.5f, (GenFunction_2) func_80387090, (uintptr_t)actor->marker, 1); timedFunc_set_2(1.5f, (GenFunction_2) func_803870BC, 0x19d, 0x1f4); - if (!sCraneRemote) { - timed_exitStaticCamera(1.5f); - func_80324E38(1.5f, 0); - } + timed_exitStaticCamera(1.5f); + func_80324E38(1.5f, 0); + } void func_80387488(ActorMarker *marker){ - f32 player_position[3]; + f32 sp1C[3]; Actor *actor = marker_getActor(marker); - player_getPosition(player_position); - if(-50.0f < player_position[1] && player_position[1] < 600.0f){ - player_position[1] = 0; - if(ml_vec3f_distance(player_position, D_80390264) < 500.0f){ + player_getPosition(sp1C); + if(-50.0f < sp1C[1] && sp1C[1] < 600.0f){ + sp1C[1] = 0; + if(ml_vec3f_distance(sp1C, D_80390264) < 500.0f){ timedFunc_set_1(1.0f, (GenFunction_1) func_80387488, (uintptr_t)actor->marker); return; } } - if (!sCraneRemote) { - func_80324E38(0.0f, 3); - timed_setStaticCameraToNode(0.0f, 6); - } + func_80324E38(0.0f, 3); + timed_setStaticCameraToNode(0.0f, 6); timedFunc_set_1(0.5f, (GenFunction_1) func_80387308, (uintptr_t)actor->marker); } -void chCageUpSwitch_setState(Actor *this, s32 next_state){ +void func_8038756C(Actor *this, s32 arg1){ f32 sp6C[3]; f32 sp60[3]; void * temp_v0; @@ -148,8 +127,7 @@ void chCageUpSwitch_setState(Actor *this, s32 next_state){ f32 sp30[3]; f32 sp24[3]; - if(next_state == CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED){ - sCraneRemote = 0; + if(arg1 == 1){ if(this->state != 0){ sp6C[0] = 0.0f; sp6C[1] = 0.0f; @@ -164,10 +142,7 @@ void chCageUpSwitch_setState(Actor *this, s32 next_state){ } }//L80387610 - if(next_state == CH_CAGE_UP_SWITCH_STATE_2_RAISING_CAGE){ - if (!sCraneRemote) { - port_jiggyCrane_broadcast(2); - } + if(arg1 == 2){ sp50[0] = sp50[1] = sp50[2] = 0.0f; sp44[0] = 0.0f; sp44[1] = 0.0f; @@ -181,25 +156,20 @@ void chCageUpSwitch_setState(Actor *this, s32 next_state){ timedFunc_set_2(0.1f, (GenFunction_2)func_8038711C, 0x19d, 0x1f4); timedFunc_set_2(0.1f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2B_DING_B, 28000); - if (!sCraneRemote) { - func_80324E38(0.2f, 3); - } + func_80324E38(0.2f, 3); timedFunc_set_1(1.1f, (GenFunction_1)func_8038718C, (uintptr_t)this->marker); }//L80387704 - if(next_state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE){ + if(arg1 == 3){ item_set(ITEM_6_HOURGLASS, 1); - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(0x3bf, 0x31f, 0, 0)); + item_set(ITEM_0_HOURGLASS_TIMER, 0x3bf); } - if(this->state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE){ + if(this->state == 3){ item_set(ITEM_6_HOURGLASS, 0); } - if(next_state == CH_CAGE_UP_SWITCH_STATE_4_LOWER_CAGE){ - if (!sCraneRemote) { - port_jiggyCrane_broadcast(4); - } + if(arg1 == 4){ sp3C = func_8034C528(0x19a); if(sp3C){ sp30[0] = 0.0f; @@ -218,52 +188,32 @@ void chCageUpSwitch_setState(Actor *this, s32 next_state){ timedFunc_set_1(4.0f, (GenFunction_1)func_80387488, (uintptr_t)this->marker); }//L80387828 - this->state = next_state; + this->state = arg1; } -void chCageUpSwitch_pushSwitch(ActorMarker *marker, ActorMarker *arg1){ +void func_80387850(ActorMarker *marker, ActorMarker *arg1){ Actor *actor = marker_getActor(marker); - if(actor->state == CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED){ - chCageUpSwitch_setState(actor, CH_CAGE_UP_SWITCH_STATE_2_RAISING_CAGE); + if(actor->state == 1){ + func_8038756C(actor, 2); } } -void chCageUpSwitch_free(Actor *this){ - chCageUpSwitch_setState(this, CH_CAGE_UP_SWITCH_STATE_0_NOT_INIT); +void func_80387890(Actor *this){ + func_8038756C(this, 0); } -void chCageUpSwitch_update(Actor *this){ +void func_803878B0(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - this->marker->actorFreeFunc = chCageUpSwitch_free; - marker_setCollisionScripts(this->marker, NULL, chCageUpSwitch_pushSwitch, NULL); + this->marker->actorFreeFunc = func_80387890; + marker_setCollisionScripts(this->marker, NULL, func_80387850, NULL); suSetSpriteScale(this, 1.1f); - chCageUpSwitch_setState(this, CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED); + func_8038756C(this, 1); } - if(this->state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE && !sCraneRemote){ + if(this->state == 3){ if(item_empty(ITEM_0_HOURGLASS_TIMER)){ - chCageUpSwitch_setState(this, CH_CAGE_UP_SWITCH_STATE_4_LOWER_CAGE); - } - } -} - -void port_jiggyCrane_remoteApply(s32 stage) { - s32 i; - - if (suBaddieActorArray == NULL) { - return; - } - for (i = 0; i < suBaddieActorArray->cnt; i++) { - Actor *actor = &suBaddieActorArray->data[i]; - if (actor->marker == NULL || actor->marker->id != MARKER_183_RBB_CAGE_UP_SWITCH) { - continue; - } - if ((stage == 2 && actor->state == CH_CAGE_UP_SWITCH_STATE_1_NOT_PRESSED) - || (stage == 4 && actor->state == CH_CAGE_UP_SWITCH_STATE_3_TIMED_RAISED_CAGE)) { - sCraneRemote = 1; - chCageUpSwitch_setState(actor, stage); + func_8038756C(this, 4); } - return; } } diff --git a/src/RBB/miniboombox_container.c b/src/RBB/miniboombox_container.c index f997a4634..0fb74ee1d 100644 --- a/src/RBB/miniboombox_container.c +++ b/src/RBB/miniboombox_container.c @@ -5,67 +5,59 @@ extern -void chBoomBoxMinigameCtrl_update(Actor *this); +void RBB_func_8038FB84(Actor *this); /* .data */ -ActorInfo chBoomBoxMinigameCtrl = { - MARKER_1B8_BOOM_BOX_MINIGAME_CTRL, ACTOR_2A5_BOOM_BOX_MINIGAME_CTRL, 0x0, - 0x0, NULL, - chBoomBoxMinigameCtrl_update, NULL, func_80325340, +ActorInfo RBB_D_80390E00 = { + 0x1B8, 0x2A5, 0x0, 0x0, NULL, + RBB_func_8038FB84, NULL, func_80325340, 0, 0, 0.0f, 0 }; -enum chboomboxminigamectrl_state_e { - CH_BOOMBOX_MINIGAME_CTRL_STATE_0_NOT_INIT, - CH_BOOMBOX_MINIGAME_CTRL_STATE_1_INIT, - CH_BOOMBOX_MINIGAME_CTRL_STATE_2_PARTIAL_COMPLETE, - CH_BOOMBOX_MINIGAME_CTRL_STATE_3_COMPLETE -}; - /* .bss */ -u8 chBoomBoxMinigameRemainingCount; +u8 D_803912B0; /* .code */ -void chBoomBoxMinigameCtrl_spawnExtraLife(ActorMarker *marker){ +void RBB_func_8038FA60(ActorMarker *marker){ Actor *actor = marker_getActor(marker); bundle_setYaw(actor->yaw); bundle_spawn_f32(BUNDLE_6_MM_HUT_EXTRA_LIFE, actor->position); } -void chBoomBoxMinigameCtrl_setState(Actor *this, s32 next_state){ - if(next_state == CH_BOOMBOX_MINIGAME_CTRL_STATE_3_COMPLETE){ +void func_8038FA9C(Actor *this, s32 arg1){ + if(arg1 == 3){ func_80324E38(0.0f, 3); timedFunc_set_2(1.0f, (GenFunction_2)coMusicPlayer_playMusic, COMUSIC_2B_DING_B, 28000); timed_setStaticCameraToNode(1.8f, 1); - timedFunc_set_1(2.0f, (GenFunction_1) chBoomBoxMinigameCtrl_spawnExtraLife, (uintptr_t)this->marker); + timedFunc_set_1(2.0f, (GenFunction_1) RBB_func_8038FA60, (uintptr_t)this->marker); timed_exitStaticCamera(5.0f); func_80324E38(5.0f, 0); } - this->state = next_state; + this->state = arg1; } -void chBoomBoxMinigameCtrl_countInc(void){ - chBoomBoxMinigameRemainingCount++; +void func_8038FB54(void){ + D_803912B0++; } -void chBoomBoxMinigameCtrl_countDec(void){ - chBoomBoxMinigameRemainingCount--; +void func_8038FB6C(void){ + D_803912B0--; } -void chBoomBoxMinigameCtrl_update(Actor *this){ +void RBB_func_8038FB84(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; - chBoomBoxMinigameRemainingCount = 0; - chBoomBoxMinigameCtrl_setState(this, CH_BOOMBOX_MINIGAME_CTRL_STATE_1_INIT); + D_803912B0 = 0; + func_8038FA9C(this, 1); } - if(this->state == CH_BOOMBOX_MINIGAME_CTRL_STATE_1_INIT){ - if(chBoomBoxMinigameRemainingCount > 0) - chBoomBoxMinigameCtrl_setState(this, CH_BOOMBOX_MINIGAME_CTRL_STATE_2_PARTIAL_COMPLETE); + if(this->state == 1){ + if(D_803912B0 > 0) + func_8038FA9C(this, 2); } - if(this->state == CH_BOOMBOX_MINIGAME_CTRL_STATE_2_PARTIAL_COMPLETE){ - if(chBoomBoxMinigameRemainingCount == 0) - chBoomBoxMinigameCtrl_setState(this, CH_BOOMBOX_MINIGAME_CTRL_STATE_3_COMPLETE); + if(this->state == 2){ + if(D_803912B0 == 0) + func_8038FA9C(this, 3); } } diff --git a/src/RBB/propellorctrl.c b/src/RBB/propellorctrl.c index ec2f6f6e8..e9ae4c96d 100644 --- a/src/RBB/propellorctrl.c +++ b/src/RBB/propellorctrl.c @@ -17,7 +17,7 @@ void __propellorCtrl_setState(s32 arg0){ } if(arg0 == 2){ - item_set(ITEM_3_PROPELLOR_TIMER, VER_SELECT(3900, 3250, 0, 0) - 1); + item_set(ITEM_3_PROPELLOR_TIMER, 3900 - 1); item_set(ITEM_9_PROPELLOR, 1); } @@ -27,7 +27,7 @@ void __propellorCtrl_setState(s32 arg0){ item_set(ITEM_9_PROPELLOR,0); if(arg0 == 3 && !jiggyscore_isCollected(JIGGY_57_RBB_PROPELLOR)){ timedFunc_set_1(0.5f, (GenFunction_1)func_802FAD64, 3); - func_80324DBC(1.0f, VER_SELECT(ASSET_B9D_DIALOG_GRUNTY_PROPELLER_MISS, 0x972, 0, 0), 4, NULL, NULL, NULL, NULL); + func_80324DBC(1.0f, ASSET_B9D_DIALOG_GRUNTY_PROPELLER_MISS, 4, NULL, NULL, NULL, NULL); } else{ func_802FAD64(3); diff --git a/src/RBB/rbbspawnqueue.c b/src/RBB/rbbspawnqueue.c deleted file mode 100644 index 211b30172..000000000 --- a/src/RBB/rbbspawnqueue.c +++ /dev/null @@ -1,241 +0,0 @@ -// BanjoDecomp: RBB/rbbspawnqueue.c -#include -#include "core1/core1.h" -#include "functions.h" -#include "variables.h" -#include "prop.h" -#include "actor.h" - -#include "port/Patches/Patches.h" - - -extern ActorInfo chBellBuoy; -extern ActorInfo chRBBEggToll; -extern ActorInfo chCageUpSwitch; -extern ActorInfo chTNTDownSwitch; -extern ActorInfo chRowboat; -extern ActorInfo chRBBRearPropeller; -extern ActorInfo chRBBGreenPropellerSwitch; -extern ActorInfo chRBBSpinningSinglePipe1; -extern ActorInfo chRBBSpinningSinglePipe2; -extern ActorInfo chRBBSpinningDoublePipe1; -extern ActorInfo chRBBSpinningDoublePipe2; -extern ActorInfo chSpinningFlatPlatform1; -extern ActorInfo chSpinningFlatPlatform2; -extern ActorInfo chSpinningFlatPlatform3; -extern ActorInfo chRBBSmallCog; -extern ActorInfo chRBBMediumCog; -extern ActorInfo chRBBLargeCog; -extern ActorInfo chEngineRoomPropeller1; -extern ActorInfo chEngineRoomPropeller2; -extern ActorInfo chEngineRoomPropeller3; -extern ActorInfo chRBBGreyPropellerSwitch; -extern ActorInfo chRBBWhistleSwitch1; -extern ActorInfo chRBBWhistleSwitch2; -extern ActorInfo chRBBWhistleSwitch3; -extern ActorInfo chRBBWhistle1; -extern ActorInfo chRBBWhistle2; -extern ActorInfo chRBBWhistle3; -extern ActorInfo chRBBWhistleCtrl; -extern ActorInfo chGrimlet; -extern ActorInfo chAnchorSwitch; //anchorswitch -extern ActorInfo chSnorkel; //dolphin -extern ActorInfo chAnchor; //anchor -extern ActorInfo chAnchorCtrl; -extern ActorInfo chRarewareFlag; //rarewareflag -extern ActorInfo chBossBoomBoxLargest; -extern ActorInfo chBossBoomBoxLarge; -extern ActorInfo chBossBoomBoxMedium; -extern ActorInfo chBossBoomBoxSmall; -extern ActorInfo chBossBoomBoxCtrl; -extern ActorInfo chBoomBoxSlow; -extern ActorInfo chBoomBoxFast; //TNTpart_IDStruct; -extern ActorInfo chBoomBoxMinigameCtrl; -extern ActorInfo chRBBSpinningSinglePipeSfxCtrl; -extern ActorInfo chRBBSpinningDoublePipeSfxCtrl; -extern ActorInfo chEngineRoomDoor; -extern ActorInfo chCabinClosetDoor; //captcabinwooddoor -extern ActorInfo chShipShadowWindow; -extern ActorInfo chShipSunnyWindow; -extern ActorInfo chSunnyLifeboat; -extern ActorInfo chShadowLifeboat; -extern ActorInfo chCrackedSkylight;//skylight -extern ActorInfo chRbbHoneycombSwitch;//honeycombswitch - - - -extern void chMMMBreakableWooden_update(Actor *); - -void func_80386A7C(Actor *); -void func_80386BF8(Actor *arg0); -Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3); - - -/* .data */ -ActorAnimationInfo D_803900C0[4] = { - {0, 0.0f}, - {0, 0.0f}, - {0xD4, 0.15f}, - {0xD5, 0.5f} -}; - -ActorInfo chEngineRoomDoor = { - MARKER_107_ENGINE_ROOM_DOOR, ACTOR_21D_ENGINE_ROOM_DOOR, ASSET_493_MODEL_ENGINE_ROOM_DOOR, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCabinClosetDoor = { - MARKER_108_CABIN_CLOSET_DOOR, ACTOR_21C_CABIN_CLOSET_DOOR, ASSET_492_MODEL_CABIN_CLOSET_DOOR, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chShipShadowWindow = { - MARKER_22D_SHIP_SHADOW_WINDOW, ACTOR_266_SHIP_SHADOW_WINDOW, ASSET_4BA_MODEL_SHIP_SHADOW_WINDOW, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chShipSunnyWindow = { - MARKER_22E_SHIP_SUNNY_WINDOW, ACTOR_267_SHIP_SUNNY_WINDOW, ASSET_4BB_MODEL_SHIP_SUNNY_WINDOW, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chCrackedSkylight = { - MARKER_235_CRACKED_SKYLIGHT, ACTOR_23F_CRACKED_SKYLIGHT, ASSET_4E2_MODEL_CRACKED_SKYLIGHT, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chRbbHoneycombSwitch = { - MARKER_15F_RBB_HONEYCOMB_SWITCH, ACTOR_18F_RBB_HONEYCOMB_SWITCH, ASSET_42F_MODEL_RBB_HONEYCOMB_SWITCH, - 0x1, D_803900C0, - func_80386BF8, actor_update_func_80326224, actor_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chSunnyLifeboat = { - MARKER_22F_SUNNY_LIFEBOAT, ACTOR_263_SUNNY_LIFEBOAT, ASSET_4DB_MODEL_SUNNY_LIFEBOAT, - 0x1, NULL, - func_80386A7C, actor_update_func_80326224, func_80386B9C, - 0, 0, 0.0f, 0 -}; - -ActorInfo chShadowLifeboat = { - MARKER_230_SHADOW_LIFEBOAT, ACTOR_264_SHADOW_LIFEBOAT, ASSET_4DE_MODEL_SHADOW_LIFEBOAT, - 0x1, NULL, - func_80386A7C, actor_update_func_80326224, func_80386B9C, - 0, 0, 0.0f, 0 -}; - - -/* .code */ -s32 func_80386A30(f32 arg0[3]){ - s32 r; - - r = (arg0[0] < 0.0f)? 0 : 1; - - return ((arg0[2] < 0.0f)? 0 : 2) + r; -} - -void func_80386A7C(Actor *this){ - f32 viewport[3]; - s32 sp28; - s32 temp_v0; - - func_802D3D74(this); - this->depth_mode = 1; - viewport_getPosition_vec3f(viewport); - sp28 = func_80386A30(this->position); - temp_v0 = func_80386A30(viewport); - this->unk38_0 = 0; - // [port] Extend the bespoke distance cull with draw distance; quadrant occlusion below stays. - f32 cull = 8000.0f * port_drawDistanceMul(); - if(viewport[0] + cull < this->position_x || this->position_x < viewport[0] - cull) - return; - - if( !( (sp28 ^ temp_v0) & 2 - && (-5000.0f < viewport[0] && viewport[0] < 6000.0f) - && (viewport[2] < -600.0f || 600.0f < viewport[2]) - ) -#if 0 - && ( sp28 ^ temp_v0) != 3 -#endif - ){ - this->unk38_0 = 1; - } -} - -Actor *func_80386B9C(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **arg3){ - Actor *actor = marker_getActor(marker); - - return (actor->unk38_0) ? actor_drawFullDepth(marker, gdl, mptr, arg3): NULL; -} - -void func_80386BF8(Actor *arg0){ - if(!mapSpecificFlags_get(RBB_BOAT_ROOM_SPECIFIC_FLAG_0_HONEYCOMB_SPAWNED) && honeycombscore_get(HONEYCOMB_F_RBB_BOAT_HOUSE)) - mapSpecificFlags_set(RBB_BOAT_ROOM_SPECIFIC_FLAG_0_HONEYCOMB_SPAWNED, true); - func_802D4A9C(arg0, 0); -} - -void RBB_func_80386C48(void){ - spawnableActorList_add(&chBellBuoy, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBEggToll, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCageUpSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chTNTDownSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRowboat, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_14 | ACTOR_FLAG_UNKNOWN_27); - spawnableActorList_add(&chRBBRearPropeller, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBGreenPropellerSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBSpinningSinglePipe1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBSpinningSinglePipe2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBSpinningDoublePipe1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBSpinningDoublePipe2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chSpinningFlatPlatform1, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chSpinningFlatPlatform2, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chSpinningFlatPlatform3, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBSmallCog, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBMediumCog, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chRBBLargeCog, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_13 | ACTOR_FLAG_UNKNOWN_14); - spawnableActorList_add(&chEngineRoomPropeller1, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chEngineRoomPropeller2, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chEngineRoomPropeller3, actor_new, ACTOR_FLAG_UNKNOWN_10); - spawnableActorList_add(&chRBBGreyPropellerSwitch, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chRBBWhistleSwitch1, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBWhistleSwitch2, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBWhistleSwitch3, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBWhistle1, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chRBBWhistle2, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chRBBWhistle3, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chRBBWhistleCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chGrimlet, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chAnchorSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7); //anchorswitch - spawnableActorList_add(&chSnorkel, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //dolphin - spawnableActorList_add(&chAnchor, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); //anchor - spawnableActorList_add(&chAnchorCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRarewareFlag, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); //rarewareflag - spawnableActorList_add(&chBossBoomBoxLargest, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chBossBoomBoxLarge, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chBossBoomBoxMedium, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chBossBoomBoxSmall, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chBossBoomBoxCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chBoomBoxSlow, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&chBoomBoxFast, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&chBoomBoxMinigameCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBSpinningSinglePipeSfxCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chRBBSpinningDoublePipeSfxCtrl, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chEngineRoomDoor, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chCabinClosetDoor, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //captcabinwooddoor - spawnableActorList_add(&chShipShadowWindow, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chShipSunnyWindow, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chSunnyLifeboat, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&chShadowLifeboat, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&chCrackedSkylight, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //skylight - spawnableActorList_add(&chRbbHoneycombSwitch, actor_new, ACTOR_FLAG_UNKNOWN_3); //honeycombswitch -} diff --git a/src/RBB/siren.c b/src/RBB/siren.c deleted file mode 100644 index a829ce4ae..000000000 --- a/src/RBB/siren.c +++ /dev/null @@ -1,81 +0,0 @@ -// BanjoDecomp: code_9840.c -#include -#include "functions.h" -#include "variables.h" - -void chRBBSpinningPipeSfxCtrl_update(Actor *this); - -/* typedefs and declarations */ -typedef struct { - s32 unk0; - s16 *actorId; - ActorMarker *marker; -}ActorLocal_RBB_9840; - -/* -These objects only exist in RBB's engine room. -As the spinning pipes rotate, these controllers -create sound effects based off of the rotation speed. -*/ - -/* .data */ -s16 chRBBSpinningPipeSfxCtrlPipeActors[2] = { - ACTOR_177_RBB_SPINNING_SINGLE_PIPE_1, - ACTOR_17F_RBB_SPINNING_DOUBLE_PIPE_1 -}; - -ActorInfo chRBBSpinningSinglePipeSfxCtrl = { - MARKER_1D2_SPINNING_SINGLE_PIPE_SFX_CTRL, ACTOR_31B_SPINNING_SINGLE_PIPE_SFX_CTRL, 0x0, - 0x0, NULL, - chRBBSpinningPipeSfxCtrl_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo chRBBSpinningDoublePipeSfxCtrl = { - MARKER_1D3_DOUBLE_SINGLE_PIPE_SFX_CTRL, ACTOR_31C_DOUBLE_SINGLE_PIPE_SFX_CTRL, 0x0, - 0x0, NULL, - chRBBSpinningPipeSfxCtrl_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -enum chrbbspinningdoublepipesfxctrl_state_e { - CH_RBB_SPINNING_PIPE_SFX_CTRL_STATE_0_NOT_INIT, - CH_RBB_SPINNING_PIPE_SFX_CTRL_STATE_1_INIT -}; - -/*.code */ -// set state -void chRBBSpinningPipeSfxCtrl_setState(Actor *this, s32 next_state){ - this->state = next_state; -} - -// update -void chRBBSpinningPipeSfxCtrl_update(Actor *this){ - ActorLocal_RBB_9840 *local = (ActorLocal_RBB_9840 *)&this->local; - f32 sp20; - f32 tmp_f2; - s32 tmp_a1; - - if(!this->volatile_initialized){ - this->volatile_initialized = true; - actor_collisionOff(this); - local->actorId = chRBBSpinningPipeSfxCtrlPipeActors + (this->marker->id - 0x1D2); - local->marker = NULL; - - local->unk0 = func_802F9AA8(0x400); - func_802F9DB8(local->unk0, 1.0f, 1.0f, 0.0f); - func_802F9EC4(local->unk0, this->position, 500, 1000); - func_802F9F80(local->unk0, 0.0f, 8999999488.0f, 0.0f); - func_802FA060(local->unk0, 22000, 22000, 0.0f); - chRBBSpinningPipeSfxCtrl_setState(this, CH_RBB_SPINNING_PIPE_SFX_CTRL_STATE_1_INIT); - } - else{//L8038FD34 - if(local->marker == NULL) - local->marker = actorArray_findActorFromActorId(*local->actorId)->marker; - sp20 = func_8038A6B8(local->marker); - tmp_f2 = 1.5 * sp20 + 0.5; - func_802F9DB8(local->unk0, tmp_f2, tmp_f2, 0.0f); - tmp_a1 = (s32) (sp20 * 32000.0f); - func_802FA060(local->unk0, tmp_a1, tmp_a1, 0.0f); - } -} diff --git a/src/SM/ch/ambient_fish.c b/src/SM/ch/ambient_fish.c index 79a113b1c..e3ed73d93 100644 --- a/src/SM/ch/ambient_fish.c +++ b/src/SM/ch/ambient_fish.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/code_C89C0.c +// BanjoDecomp: (unknown origin) #include #include "functions.h" #include "variables.h" diff --git a/src/SM/ch/attacktutorial.c b/src/SM/ch/attacktutorial.c index 79911a42c..4fb42b15f 100644 --- a/src/SM/ch/attacktutorial.c +++ b/src/SM/ch/attacktutorial.c @@ -8,10 +8,6 @@ extern void timed_exitStaticCamera(f32 time); extern void func_8028F918(s32); -// [port] Spare actor bit repurposed: the claw/roll/rap trio was already known when this -// actor spawned (or a local opt-out just unlocked it). -#define movesKnownAtSpawn unk38_0 - enum ch_attack_tutorial_states { CH_ATTACK_TUTORIAL_STATE_1_UNKNOWN = 0x1, // L80387610 CH_ATTACK_TUTORIAL_STATE_2_APPLY_LEARNED_MOVE, // L803873E0 @@ -63,7 +59,7 @@ static s32 __chAttackTutorial_spawnEnemyActor(Actor *this, s32 already_killed_en : ACTOR_164_COLLYWOBBLE_THE_CAULIFLOWER_A; } - __spawnQueue_add_2((GenFunction_2)__chAttackTutorial_spawnEnemyActorForMarker, (uintptr_t)this->marker, sp1C); + __spawnQueue_add_2((void (*)(void))__chAttackTutorial_spawnEnemyActorForMarker, (uintptr_t)this->marker, sp1C); return 0; } @@ -136,16 +132,6 @@ static bool __chAttackTutorial_areLearnableAbilitiesUnlocked() { && ability_isUnlocked(ABILITY_B_RATATAT_RAP); } -// [port] A local tutorial opt-out unlocks every move mid-session; re-arm the spawn latch. -bool func_802E4A08(void); // non-interactive demo/playback modes - -void chAttackTutorial_onTutorialSkipped(void) { - Actor *tutorial = actorArray_findActorFromActorId(ACTOR_167_ATTACK_TUTORIAL); - if (tutorial != NULL) { - tutorial->movesKnownAtSpawn = 1; - } -} - static void __chAttackTutorial_update(Actor *this) { f32 minimum_distance; Actor *bottles; @@ -167,9 +153,6 @@ static void __chAttackTutorial_update(Actor *this) { ? 1 : 0; - // [port] Latch "moves already known" at spawn. - this->movesKnownAtSpawn = __chAttackTutorial_areLearnableAbilitiesUnlocked(); - this->initialized = true; } @@ -177,9 +160,8 @@ static void __chAttackTutorial_update(Actor *this) { case CH_ATTACK_TUTORIAL_STATE_1_UNKNOWN: if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_4)) __chAttackTutorial_setState(this, CH_ATTACK_TUTORIAL_STATE_5_SHOW_LEARN_MOVE_DIALOG); - if (this->movesKnownAtSpawn - || (func_802E4A08() && __chAttackTutorial_areLearnableAbilitiesUnlocked()) - || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)) + + if (__chAttackTutorial_areLearnableAbilitiesUnlocked() || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)) __chAttackTutorial_setState(this, CH_ATTACK_TUTORIAL_STATE_4_TUTORIAL_COMPLETED); break; diff --git a/src/SM/bottles_movecheck.c b/src/SM/ch/bottles_movecheck.c similarity index 100% rename from src/SM/bottles_movecheck.c rename to src/SM/ch/bottles_movecheck.c diff --git a/src/SM/furniture.c b/src/SM/ch/furniture.c similarity index 100% rename from src/SM/furniture.c rename to src/SM/ch/furniture.c diff --git a/src/SM/ch/jumptutorial.c b/src/SM/ch/jumptutorial.c index fd704405b..d8cb0862b 100644 --- a/src/SM/ch/jumptutorial.c +++ b/src/SM/ch/jumptutorial.c @@ -57,8 +57,8 @@ void chJumpTutorial_setState(Actor *this, s32 state) { ability_unlock(ABILITY_A_HOLD_A_JUMP_HIGHER); gcdialog_showDialog(ASSET_DF6_DIALOG_BOTTLES_HIGH_JUMP_LEARN, 0xe, this->unk1C, this->marker, __chJumpTutorial_textCallback, NULL); - this->sm_4070.dialog_id = VER_SELECT(ASSET_E1A_DIALOG_BOTTLES_UNKNOWN, 0xA5C, 0, 0); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, FALSE); + this->sm_4070.dialog_id = ASSET_E1A_DIALOG_BOTTLES_UNKNOWN; + mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, false); } break; @@ -113,8 +113,8 @@ void chJumpTutorial_update(Actor *this) { ability_unlock(ABILITY_7_FEATHERY_FLAP); gcdialog_showDialog(ASSET_DF7_DIALOG_BOTTLES_FEATHERY_FLAP_LEARN, 0xa, this->unk1C, this->marker, __chJumpTutorial_textCallback, NULL); - this->sm_4070.dialog_id = VER_SELECT(ASSET_E1B_DIALOG_BOTTLES_UNKNOWN, 0xA5D, 0, 0); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, FALSE); + this->sm_4070.dialog_id = ASSET_E1B_DIALOG_BOTTLES_UNKNOWN; + mapSpecificFlags_set(SM_SPECIFIC_FLAG_8_ABILITY_HOLD_A_JUMP_HIGHER_UNLOCKED, false); }//L8038A730 if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_9_ABILITY_FEATHERY_UNLOCKED)) { @@ -122,8 +122,8 @@ void chJumpTutorial_update(Actor *this) { ability_unlock(ABILITY_8_FLAP_FLIP); gcdialog_showDialog(ASSET_DF8_DIALOG_BOTTLES_FLAP_FLIP_LEARN, 0xa, this->unk1C, this->marker, __chJumpTutorial_textCallback, NULL); - this->sm_4070.dialog_id = VER_SELECT(ASSET_E1C_DIALOG_BOTTLES_UNKNOWN, 0xA5E, 0, 0); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_9_ABILITY_FEATHERY_UNLOCKED, FALSE); + this->sm_4070.dialog_id = ASSET_E1C_DIALOG_BOTTLES_UNKNOWN; + mapSpecificFlags_set(SM_SPECIFIC_FLAG_9_ABILITY_FEATHERY_UNLOCKED, false); }//L8038A794 if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_A_ABILITY_FLIP_UNLOCKED)) { @@ -149,7 +149,7 @@ void chJumpTutorial_update(Actor *this) { plyr_pos[2] = this->velocity_z; func_8028FAB0(plyr_pos); - if (func_8028EFC8() && face_buttons[FACE_BUTTON(BUTTON_B)] == TRUE && player_isStableWithExtraSteps()) { + if (func_8028EFC8() && face_buttons[FACE_BUTTON(BUTTON_B)] == true && func_8028F20C()) { if (this->sm_4070.dialog_id) { gcdialog_showDialog(dialog_id = this->sm_4070.dialog_id, 0, NULL, NULL, NULL, NULL); } diff --git a/src/SM/quarrie.c b/src/SM/ch/quarrie.c similarity index 94% rename from src/SM/quarrie.c rename to src/SM/ch/quarrie.c index 83d9c4006..d60843118 100644 --- a/src/SM/quarrie.c +++ b/src/SM/ch/quarrie.c @@ -112,12 +112,9 @@ void SM_func_80386D68(Actor *this){ func_80386B04(partEmitMgr_newEmitter(0xA), this->position, 0xA, this->scale); func_80386C2C(partEmitMgr_newEmitter(0x10), this->position, 0x10, this->scale); - // [port] Anchor: skip the drop if a teammate's synced drop already put one here. - if (this->partnerActor && codeBF0_shouldSpawnQuarrieHoneyComb(this->partnerActor) && - !actorArray_findHoneycombMarkerById(HONEYCOMB_18_SM_QUARRIES)) { + if (this->partnerActor && codeBF0_shouldSpawnQuarrieHoneyComb(this->partnerActor)) { func_802CA1CC(HONEYCOMB_18_SM_QUARRIES); __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, BUNDLE_1F_SM_EMPTY_HONEYCOMB, reinterpret_cast(s32, this->position[0]), reinterpret_cast(s32, this->position[1]), reinterpret_cast(s32, this->position[2])); - CALL_EVENT(OnHoneycombDropSpawn, HONEYCOMB_18_SM_QUARRIES, BUNDLE_1F_SM_EMPTY_HONEYCOMB, this->position[0], this->position[1], this->position[2]); } marker_despawn(this->marker); diff --git a/src/SM/ch/smbottles.c b/src/SM/ch/smbottles.c index cfc4e046f..301806e00 100644 --- a/src/SM/ch/smbottles.c +++ b/src/SM/ch/smbottles.c @@ -3,10 +3,7 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - /* extern functions */ -void chAttackTutorial_onTutorialSkipped(void); Actor *func_802D94B4(ActorMarker *, Gfx **, Mtx **, Vtx **); void func_8028E668(f32 *, f32, f32, f32); void subaddie_turnToYaw(Actor *, f32); @@ -113,19 +110,6 @@ void __chSmBottles_skipIntroTutorial(void) { ability_unlock(ABILITY_5_CLIMB); __chSmBottles_setHasUsedSpiralMountainAbilities(); mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, true); - // [port] Vanilla parity: a local opt-out pops the bonus Collywobble this session. - chAttackTutorial_onTutorialSkipped(); -} - -// [port] Anchor: a remote unlock completed the SM move set mid-session. Apply the same -// completion state the init block derives from abilities at map load. -void chSmBottles_netApplyTutorialComplete(void) { - mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, true); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_2, true); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_C, true); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_F, true); - chAttackTutorial_onTutorialSkipped(); } /** @@ -512,27 +496,13 @@ void chSmBottles_update(Actor *this) { this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); - // [port] Anchor: ability molehills stay inert until the team's tutorial choice - // is made, so nobody can start a tutorial the pending decision would invalidate. - if (this->actorTypeSpecificField != 1 && this->actorTypeSpecificField != 8 && - !EventSystem_Should(VB_SM_MOLEHILL_ACTIVE, true, this)) { - break; - } - if ((this->actorTypeSpecificField == 1 && !mapSpecificFlags_get(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES)) || (this->actorTypeSpecificField == 8 && !mapSpecificFlags_get(SM_SPECIFIC_FLAG_2)) || (this->actorTypeSpecificField == 8 && mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED) && !mapSpecificFlags_get(SM_SPECIFIC_FLAG_F)) ) {//L80389C50 - if (((ml_vec3f_distance(plyr_pos, this->unk1C) < this->actor_specific_1_f) && player_isStableWithExtraSteps()) || + if (((ml_vec3f_distance(plyr_pos, this->unk1C) < this->actor_specific_1_f) && func_8028F20C()) || mapSpecificFlags_get(SM_SPECIFIC_FLAG_10) ) {//L80389C8C - // [port] Anchor: the intro tutorial offer is a team decision. - if (this->actorTypeSpecificField == 1 && - !EventSystem_Should(VB_SM_TUTORIAL_CHOICE_OPEN, true, this)) { - mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); - break; - } - if (subaddie_playerIsWithinSphereAndActive(this, 0x96)) { func_8028F45C(9, this->position); } @@ -542,7 +512,7 @@ void chSmBottles_update(Actor *this) { } } else {//L80389CBC - if (!subaddie_playerIsWithinSphereAndActive(this, 250) || player_movementGroup() || !player_isStableWithExtraSteps() || func_8028EC04()) { + if (!subaddie_playerIsWithinSphereAndActive(this, 0xfa) || player_movementGroup() || !func_8028F20C() || func_8028EC04()) { break; } @@ -644,14 +614,6 @@ void chSmBottles_update(Actor *this) { }//L8038A218 if (bakey_pressed != -1) { - // [port] Anchor: if the tutorial decision belongs to a teammate (or moves - // are already being learned), fold a local opt-out into an opt-in. - if (bakey_pressed == 0 && !EventSystem_Should(VB_SM_TUTORIAL_CHOICE_OPEN, true, this)) { - bakey_pressed = 1; - } - // Record the answer team-wide the moment it lands, so a second pending - // offer folds even before any move is learned. - port_puzzleStep_orBits(ANCHOR_PUZZLE_SM_TUTORIAL, 1); fileProgressFlag_set(FILEPROG_DB_SKIPPED_TUTORIAL, bakey_pressed ? 0 : 1); gcdialog_showDialog(bakey_pressed ? ASSET_E07_DIALOG_BOTTLES_UNKNOWN : ASSET_E09_DIALOG_BOTTLES_SKIPPED_TUTORIAL, 0xe, this->position, this->marker, __chSmBottles_textCallback,__chSmBottles_textActions); diff --git a/src/SM/ch/vegetables.c b/src/SM/ch/vegetables.c index 7a0f3a919..67dbcda32 100644 --- a/src/SM/ch/vegetables.c +++ b/src/SM/ch/vegetables.c @@ -50,7 +50,7 @@ ActorInfo gChVegetablesTopperA = { }; ActorInfo gChVegetablesTopperB = { - MARKER_1E6_TOPPER_THE_CARROT_B, ACTOR_36F_TOPPER_THE_CARROT_B, ASSET_4ED_MODEL_TOPPER, + MARKER_1E6_TOPPER_THE_CARROT_B, ACTOR_TOPPER_THE_CARROT_B, ASSET_4ED_MODEL_TOPPER, 1, sChCarrotAnimations, __chVegetables_update, actor_update_func_80326224, __chVegetables_draw, 2000, 0, 1.0f, 0 }; @@ -70,7 +70,7 @@ ActorInfo gChVegetablesBawlA = { }; ActorInfo gChVegetablesBawlB = { - MARKER_1E7_BAWL_THE_ONION_B, ACTOR_36E_BAWL_THE_ONION_B, ASSET_4EF_MODEL_BAWL, + MARKER_1E7_BAWL_THE_ONION_B, ACTOR_BAWL_THE_ONION_B, ASSET_4EF_MODEL_BAWL, 1, sChOnionAnimations, __chVegetables_update, actor_update_func_80326224, __chVegetables_draw, 0, 0, 1.0f, 0 }; @@ -90,7 +90,7 @@ ActorInfo gChVegetablesCollywobbleA = { }; ActorInfo gChVegetablesCollywobbleB = { - MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, ACTOR_36D_COLLYWOBBLE_B, ASSET_4EE_MODEL_COLLYWOBBLE, + MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, ACTOR_COLLYWOBBLE_B, ASSET_4EE_MODEL_COLLYWOBBLE, 1, sChCauliflowerAnimations, __chVegetables_update, actor_update_func_80326224, __chVegetables_draw, 0, 0, 2.0f, 0 }; @@ -218,12 +218,10 @@ static void __chVegetables_vegetableDeathParticles(Actor* this) { __chVegetables_setSpriteDustParticles(partEmitMgr_newEmitter(8), particles_position, 8); } - // [port] Anchor: skip the drop if a teammate's synced drop already put one here. - if (this->unk38_31 && !actorArray_findHoneycombMarkerById(HONEYCOMB_17_SM_COLLIWOBBLE)) { + if (this->unk38_31) { this->position_y += 100.0f; func_802CA1CC(HONEYCOMB_17_SM_COLLIWOBBLE); __spawnQueue_add_4((GenFunction_4) spawnQueue_bundle_f32, BUNDLE_1F_SM_EMPTY_HONEYCOMB, reinterpret_cast(s32, this->position_x), reinterpret_cast(s32, this->position_y), reinterpret_cast(s32, this->position_z)); - CALL_EVENT(OnHoneycombDropSpawn, HONEYCOMB_17_SM_COLLIWOBBLE, BUNDLE_1F_SM_EMPTY_HONEYCOMB, this->position_x, this->position_y, this->position_z); } timed_mapSpecificFlags_setTrue(1.5f, SM_SPECIFIC_FLAG_7); @@ -246,7 +244,7 @@ static Actor* __chVegetables_draw(ActorMarker* marker, Gfx **gdl, Mtx **mptr, Vt if (actor->has_met_before) modelRender_func_8033A470(3, 7); else - modelRender_setAppendageVisibility(3, 0); + func_8033A45C(3, 0); return actor_draw(marker, gdl, mptr, arg3); } diff --git a/src/SM/checksums.c b/src/SM/checksums.c deleted file mode 100644 index 52758c905..000000000 --- a/src/SM/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: SM/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsSM; diff --git a/src/SM/smspawnqueue.c b/src/SM/crc.c similarity index 80% rename from src/SM/smspawnqueue.c rename to src/SM/crc.c index 45e81f3b1..0bd8884db 100644 --- a/src/SM/smspawnqueue.c +++ b/src/SM/crc.c @@ -1,12 +1,11 @@ -// BanjoDecomp: SM/smspawnqueue.c +// BanjoDecomp: code_F0.c #include #include "functions.h" #include "variables.h" #include "prop.h" #include "actor.h" -#include "checksums.h" - +extern s32 D_80275650; extern ActorInfo gQuarrie; @@ -26,11 +25,27 @@ extern ActorInfo gBanjosChair; extern ActorInfo gBanjosStove; extern ActorInfo gRockTrappingGrunty; -s32 D_8038AAE0 = VER_SELECT(0x000FE2C1, 0x00109339, 0, 0); // SM_TEXT_CRC1 -s32 D_8038AAE4 = VER_SELECT(0x8C0992D1, 0xC3A58E96, 0, 0); // SM_TEXT_CRC2 -s32 D_8038AAE8 = VER_SELECT(0x0001EB56, 0x00020B4D, 0, 0); // SM_DATA_CRC1 +extern u32 gCore1CRCs[4]; + +/* .data */ +s32 D_8038AAE0 = 0x000FE2C1; //compiled SM_code_crc_1 +s32 D_8038AAE4 = 0x8C0992D1; //compiled SM_code_crc_2 +union { + u8 byte[4]; + s32 word; +} D_8038AAE8 = {0x00, 0x01, 0xEB, 0x56}; //compiled SM_data_crc_1 (with this disabled out) s32 D_8038AAEC = 0; +/* .bss */ +struct { + s32 unk0; //calculated SM_code_crc1 + s32 unk4; //calculated SM_code_crc2 + s32 unk8; //calculated SM_data_crc1 + s32 unkC; //calculated SM_data_crc2 +} D_8038B320; + +static bool __codeF0_areRomCrcsCorrect(); +static bool __codeF0_areCrcsValid(); /* .code */ static u32 *__codeF0_getLearnedAbilitiesAddress(){ @@ -100,14 +115,16 @@ void __codeF0_pad_func_80386614(u8 *arg0, u8 *arg1, s32 *arg2, s32 *arg3){ *arg3 = temp_v1; } +extern u8 crc_ROM_START[]; + static bool __codeF0_areRomCrcsCorrect(){ #if ANTI_TAMPER u32 sp24; - if( (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_TEXT_CHECKSUM1, &sp24), sp24 == gChecksumsCore1.text_checksum1) - && (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_TEXT_CHECKSUM2, &sp24), sp24 == gChecksumsCore1.text_checksum2) - && (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_DATA_CHECKSUM1, &sp24), sp24 == gChecksumsCore1.data_checksum1) - && (osPiReadIo((u32)crc_ROM_START + CRC_CORE1_DATA_CHECKSUM2, &sp24), sp24 == gChecksumsCore1.data_checksum2) + if( (osPiReadIo((u32)crc_ROM_START + 8, &sp24), sp24 == gCore1CRCs[0]) + && (osPiReadIo((u32)crc_ROM_START + 12, &sp24), sp24 == gCore1CRCs[1]) + && (osPiReadIo((u32)crc_ROM_START + 16, &sp24), sp24 == gCore1CRCs[2]) + && (osPiReadIo((u32)crc_ROM_START + 20, &sp24), sp24 == gCore1CRCs[3]) ){ return true; } @@ -119,10 +136,10 @@ static bool __codeF0_areRomCrcsCorrect(){ static bool __codeF0_areCrcsValid(){ #if ANTI_TAMPER - if( gChecksumsSM.text_checksum1 == D_8038AAE0 - && gChecksumsSM.text_checksum2 == D_8038AAE4 - && gChecksumsSM.data_checksum2 == D_80275650 - && gChecksumsSM.data_checksum1 == D_8038AAE8 + ((u8 *) &D_8038AAE8)[0] + ((u8 *) &D_8038AAE8)[1] + ((u8 *) &D_8038AAE8)[2] + ((u8 *) &D_8038AAE8)[3] + if( D_8038B320.unk0 == D_8038AAE0 + && D_8038B320.unk4 == D_8038AAE4 + && D_8038B320.unkC == D_80275650 + && D_8038B320.unk8 == D_8038AAE8.word + D_8038AAE8.byte[0] + D_8038AAE8.byte[1] + D_8038AAE8.byte[2] + D_8038AAE8.byte[3] ){ return true; } diff --git a/src/SM/version_compat.c b/src/SM/version_compat.c index 4765cf76a..7b9d27953 100644 --- a/src/SM/version_compat.c +++ b/src/SM/version_compat.c @@ -3,111 +3,65 @@ #include "functions.h" #include "variables.h" -#if VERSION == VERSION_USA_1_0 - -int func_8038AAB0(void) { - return 0; -} - -#elif VERSION == VERSION_PAL - -struct language_selection_screen_s { - u8 *unk0; - u8 *unk4; - u64 unk8; - - u8 *unk10; - u32 unk14; - u64 unk18; - - u8 *unk20; - u32 unk24; - u64 unk28; - - u8 *unk30; - u32 unk34; - u64 unk38; -}; - -/* data */ -u32 D_8038BD30_pal = 0x0C68696A; -u32 D_8038BD34_pal = 0x02010101; -u8 *D_8038BD38_pal = "WHICH LANGUAGE WOULD"; -u8 *D_8038BD3C_pal = "YOU LIKE TO USE?"; -u8 *D_8038BD40_pal = "ENGLISH"; -u8 *D_8038BD44_pal = "FRANaAIS"; -u8 *D_8038BD48_pal = "DEUTSCH"; - -/* bss */ -u8 D_8038BFC0_pal; -u8 D_8038BFC1_pal; -u8 D_8038BFC2_pal; -struct language_selection_screen_s D_8038BFC8_pal; - -/* text */ -void func_8038B4D0_pal(s32 arg0); - -void func_8038B490_pal(s32 arg0, s32 arg1) { - if (arg1 < 0) { - /*func_8031A844_pal*/gcquiz_func_8031A48C(); - return; - } - D_8038BFC2_pal = arg1; - func_8038B4D0_pal(3); -} - -void func_8038B4D0_pal(s32 arg0) { - switch (arg0) { /* irregular */ - case 1: - D_8038BFC1_pal = 1; - /*func_80319400_pal*/gcquiz_init(); - break; - case 2: - D_8038BFC8_pal.unk0 = D_8038BD38_pal; - D_8038BFC8_pal.unk4 = D_8038BD3C_pal; - D_8038BFC8_pal.unk10 = D_8038BD40_pal; - D_8038BFC8_pal.unk20 = D_8038BD44_pal; - D_8038BFC8_pal.unk30 = D_8038BD48_pal; - /*func_8031A5E4_pal*/__gcquiz_unused(&D_8038BD30_pal, &D_8038BD34_pal, &D_8038BFC8_pal, 0xA, &func_8038B490_pal); - break; - case 3: - if (D_8038BFC2_pal) { - func_8031B5C4(D_8038BFC2_pal - 1); - } - func_802FAD64(ITEM_0_HOURGLASS_TIMER); - D_8038BFC1_pal = 0; - break; - } - D_8038BFC0_pal = (s8) arg0; -} - -void func_8038B5C4_pal(void) { - if (gsworld_getMap() == MAP_91_FILE_SELECT) { - func_8038B4D0_pal(func_8031B638() ? 3 : 1); - } -} - -void func_8038B610_pal(void) { - if (gsworld_getMap() == MAP_91_FILE_SELECT) { - /*func_80319540_pal*/gcquiz_free(); - } -} - -void func_8038B644_pal(s32 arg0, s32 arg1, s32 arg2) { -} - -void func_8038B654_pal(void) { - if ((D_8038BFC1_pal) && (getGameMode() == 3)) { - /*func_8031A25C_pal*/gcquiz_func_80319EA4(); - if (D_8038BFC0_pal == 1) { - timedFunc_set_1(1.0f, func_8038B4D0_pal, 2); - func_8038B4D0_pal(0); - } - } -} - -u8 func_8038B6C8_pal(void) { - return D_8038BFC1_pal; -} - +#define US_1_0 0 +#define PAL 1 + +u8 D_8038BFC2; + + +#if VERSION == US_1_0 +int func_8038AAB0(void){return 0;} + +#elif VERSION == PAL +#if 0 +void func_8038AAB0(s32 arg0, s32 arg1){ + if(arg1 < 0){ + func_8031A844(); + } + else{ + D_8038BFC2 = arg1; + func_8038B4D0(3); + } + } + + #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038A8F0.s") + void func_8038A8F0(s32 arg0) { + u8 temp_v0; + + switch (arg0) { /* irregular */ + case 1: + D_8038BFC1 = 1; + func_80319400(); + break; + case 2: + D_8038BFC8->unk0 = (s32) D_8038BD38; + D_8038BFC8->unk4 = (s32) D_8038BD3C; + D_8038BFC8->unk10 = (s32) D_8038BD40; + D_8038BFC8->unk20 = (s32) D_8038BD44; + D_8038BFC8->unk30 = (s32) D_8038BD48; + func_8031A5E4(&D_8038BD30, &D_8038BD34, (void *)0x8038BFC8, 0xA, &D_8038B490); + break; + case 3: + temp_v0 = *(u8 *)0x8038BFC2; + if (temp_v0 != 0) { + func_8031B9A4(temp_v0 - 1, 0x80390000); + } + func_802FAF44(0); + D_8038BFC1 = 0; + break; + } + D_8038BFC0 = (s8) arg0; + } + + + #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038A9E4.s") + + #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AA30.s") + + #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AA64.s") + + #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AA74.s") + + #pragma GLOBAL_ASM("asm/nonmatchings/SM/code_46C0/func_8038AAE8.s") +#endif #endif diff --git a/src/TTC/actor_spawninit.c b/src/TTC/actor_spawninit.c index ea46aa3ec..d6b94daf3 100644 --- a/src/TTC/actor_spawninit.c +++ b/src/TTC/actor_spawninit.c @@ -26,7 +26,7 @@ extern ActorInfo gChTreasurehuntRedQuestionMark; extern ActorInfo gChTreasurehuntRedX; extern ActorInfo gChTreasure; -extern void chMMMBreakableWooden_update(Actor *this); +extern void func_802D3D54(Actor *this); static void __code26D0_genericUpdateFunc(Actor *this); static void __code26D0_palmTreeUpdateFunc(Actor *this); @@ -37,14 +37,14 @@ static void __code26D0_sharkfoodIslandUpdateFunc(Actor *this); ActorInfo gBlubberShipTopHatch = { MARKER_A1_BLUBBER_SHIP_TOP_HATCH, ACTOR_10E_BLUBBER_SHIP_TOP_HATCH, ASSET_3D2_MODEL_BLUBBER_SHIP_TOP_HATCH, 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; ActorInfo gLighthouseDoor = { MARKER_EA_LIGHTHOUSE_DOOR, ACTOR_13E_LIGHTHOUSE_DOOR, ASSET_3D6_MODEL_LIGHTHOUSE_DOOR, 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, + func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 }; @@ -77,7 +77,7 @@ ActorInfo gStairs1 = { }; ActorInfo gStairs2 = { - MARKER_269_STAIRS_2, ACTOR_2E1_TTC_STAIRS_2, ASSET_3B7_MODEL_TTC_STAIRS_2, + MARKER_269_STAIRS_2, ACTOR_2E1_TTC_STAIRS_2, ASSET_3B7_MODEL_TTC_STAIRS_1, 0x1, NULL, __code26D0_genericUpdateFunc, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0 diff --git a/src/TTC/ma/castle.c b/src/TTC/castle.c similarity index 98% rename from src/TTC/ma/castle.c rename to src/TTC/castle.c index 11e5c35cb..13902c4df 100644 --- a/src/TTC/ma/castle.c +++ b/src/TTC/castle.c @@ -170,12 +170,12 @@ static void __maCastle_setupCheatCodeTimer(s32 new_timer_state) if (volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME)) { // set timer to 50 seconds - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(2999, 2499, 0, 0)); + item_set(ITEM_0_HOURGLASS_TIMER, 2999); } else { // set timer to 100 seconds - item_set(ITEM_0_HOURGLASS_TIMER, VER_SELECT(5999, 4999, 0, 0)); + item_set(ITEM_0_HOURGLASS_TIMER, 5999); } item_set(ITEM_6_HOURGLASS, true); @@ -332,11 +332,11 @@ static u32 __maCastle_cheatoCodeUnlocked(s32 cheato_code_index) static void __maCastle_setVolatileFlags(u32 arg0) { int i; - progressDialog_setAndTriggerDialog_0(VOLATILE_FLAG_C2_NOBONUS_TEXT); + volatileFlag_setAndTriggerDialog_0(VOLATILE_FLAG_C2_NOBONUS_TEXT); // wish washy banjo cheat code if (arg0 & 0x400) { - progressDialog_setAndTriggerDialog_E(VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT); + volatileFlag_setAndTriggerDialog_E(VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT); } volatileFlag_set(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS, 0); for (i = 4; i < 11; i++) @@ -623,7 +623,7 @@ void maCastle_update(void) } if ((sMapState.banjoKazooieCodeEnteredState == 0) || (sMapState.banjoKazooieCodeEnteredState == 3)) { - if ((levelSpecificFlags_get(LEVEL_FLAG_2_TTC_UNKNOWN) || volatileFlag_get(VOLATILE_FLAG_3)) && (player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER) && player_isStableWithExtraSteps()) + if ((levelSpecificFlags_get(LEVEL_FLAG_2_TTC_UNKNOWN) || volatileFlag_get(VOLATILE_FLAG_3)) && (player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER) && func_8028F20C()) { mesh_id_closest_to_player = model_func_8033F3C0(sMapState.model1, player_position); if (mesh_id_closest_to_player != 0) @@ -1038,7 +1038,7 @@ static void __maCastle_eraseGameplayDialogCallback(ActorMarker *caller, enum ass { __maCastle_setNumberOfBannedCheatcodesEntered(3); __maCastle_checkSecretCheatCodeIndex(sThirdForbiddenSecretCheatCodeIndex); - gcdialog_showDialog(VER_SELECT(ASSET_FBF_DIALOG_ERASED_SAVE, 0xB25, 0, 0), 0xC, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_FBF_DIALOG_ERASED_SAVE, 0xC, NULL, NULL, NULL, NULL); gameFile_clear(gameSelect_getGameNumber()); gameFile_8033CFD4(gameSelect_getGameNumber()); gameSelect_setGameNumber(-1); @@ -1073,11 +1073,11 @@ static void __maCastle_checkIfBannedCheatCodeEntered(s32 secret_cheat_code_index __maCastle_setNumberOfBannedCheatcodesEntered(2); __maCastle_checkSecretCheatCodeIndex(secret_cheat_code_index); __maCastle_resetSecretCheatCodeProgress(); - gcdialog_showDialog(VER_SELECT(ASSET_FBE_DIALOG_CHEATING_ERASE_SAVE_WARNING, 0xB24, 0, 0), 0xC, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_FBE_DIALOG_CHEATING_ERASE_SAVE_WARNING, 0xC, NULL, NULL, NULL, NULL); return; case 2: sThirdForbiddenSecretCheatCodeIndex = secret_cheat_code_index; - gcdialog_showDialog(VER_SELECT(ASSET_E38_DIALOG_CHEATING_ERASE_SAVE_CONFIRMATION, 0xA7A, 0, 0), 0xC, NULL, NULL, __maCastle_eraseGameplayDialogCallback, NULL); + gcdialog_showDialog(ASSET_E38_DIALOG_CHEATING_ERASE_SAVE_CONFIRMATION, 0xC, NULL, NULL, __maCastle_eraseGameplayDialogCallback, NULL); return; } return; diff --git a/src/TTC/ch/blubber.c b/src/TTC/ch/blubber.c index e71349ade..9f6fe29a3 100644 --- a/src/TTC/ch/blubber.c +++ b/src/TTC/ch/blubber.c @@ -3,9 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" -#include "port/Enhancements/Retention/Retention.h" - extern void func_8028E668(f32 arg0[3], f32 arg1, f32 arg2, f32 arg3); extern s32 func_802E0970(s32, f32, f32, f32, s32, s32, f32[3]); @@ -66,7 +63,7 @@ static void __chBlubber_showTextCallback(ActorMarker *caller, enum asset_e text_ Actor *this = marker_getActor(caller); ActorLocal_Blubber *local = (ActorLocal_Blubber*)&this->local; - if(text_id == VER_SELECT(ASSET_A0D_DIALOG_BLUBBER_COMPLETE, 0x90D, 0, 0) || text_id == ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED){ + if(text_id == ASSET_A0D_DIALOG_BLUBBER_COMPLETE || text_id == ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED){ local->unk24 = 0; } else{ @@ -92,7 +89,7 @@ static void __chBlubber_showJiggySpawnedText(ActorMarker *marker){ this->actor_specific_1_f = 0.0f; if(!mapSpecificFlags_get(TTC_SPECIFIC_FLAG_2_BLUBBER_JIGGY_SPAWNED_TEXT_SHOWN)) { - text_id = jiggyscore_isCollected(JIGGY_14_TTC_BLUBBER) ? ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED : VER_SELECT(ASSET_A0D_DIALOG_BLUBBER_COMPLETE, 0x90D, 0, 0); + text_id = jiggyscore_isCollected(JIGGY_14_TTC_BLUBBER) ? ASSET_A2A_DIALOG_BLUBBER_COMPLETE_JIGGY_COLLECTED : ASSET_A0D_DIALOG_BLUBBER_COMPLETE; gcdialog_showDialog(text_id, 0xf, this->position, this->marker, __chBlubber_showTextCallback, __chBlubber_showTextCallback2); mapSpecificFlags_set(TTC_SPECIFIC_FLAG_2_BLUBBER_JIGGY_SPAWNED_TEXT_SHOWN, true); } @@ -124,7 +121,7 @@ static void __func_80387774(Actor **this_ptr){ player_setCarryObjectPoseInCylinder(local->throw_target_position, local->throw_target_radius, 100.0f, ACTOR_2A_GOLD_BULLION, this_ptr); if( subaddie_playerIsWithinSphereAndActive(*this_ptr, 200) - && bacarry_getMarkerId() == MARKER_37_GOLD_BULLION + && bacarry_get_markerId() == MARKER_37_GOLD_BULLION && player_throwCarriedObject() ) { func_8028FA34(!mapSpecificFlags_get(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN) ? ACTOR_149_TTC_BLUBBER_UNKNOWN : ACTOR_14A_TTC_BLUBBER_UNKNOWN, *this_ptr); @@ -143,49 +140,13 @@ static void __func_80387830(Actor *this , f32 arg1, f32 arg2){ static void __chBlubber_updateFunc(Actor *this){ ActorLocal_Blubber *local; - s32 netBits; this->marker->propPtr->unk8_3 = true; func_8028E668(this->position, 90.0f, -10.0f, 110.0f); - - netBits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_BLUBBER); - if (mapSpecificFlags_get(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN)) { - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_BLUBBER, 0x1); - } - if (mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN)) { - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_BLUBBER, 0x3); - } - if (!this->volatile_initialized && (netBits & 0x2) && !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN)) { - marker_despawn(this->marker); - return; - } - if ((netBits & 0x1) && !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN)) { - mapSpecificFlags_set(TTC_SPECIFIC_FLAG_0_BLUBBER_UNKNOWN, true); - this->unk138_23 = true; // half-gold dialog belongs to the deliverer - this->has_met_before = true; - } - if (this->initialized && (netBits & 0x2) && !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN)) { - local = (ActorLocal_Blubber *)&this->local; - mapSpecificFlags_set(TTC_SPECIFIC_FLAG_1_UNKNOWN, true); - mapSpecificFlags_set(TTC_SPECIFIC_FLAG_2_BLUBBER_JIGGY_SPAWNED_TEXT_SHOWN, true); - mapSpecificFlags_set(TTC_SPECIFIC_FLAG_3_BLUBBER_SHOW_JIGGY_SPAWNED_TEXT_FLAG, true); - subaddie_set_state(this, CH_BLUBBER_STATE_4_UNKNOWN); - actor_loopAnimation(this); - this->actor_specific_1_f = 0.0f; - local->unk24 = 0; - } - if(!mapSpecificFlags_get(TTC_SPECIFIC_FLAG_1_UNKNOWN) && !subaddie_playerIsWithinSphereAndActive(this, 2500)) return; if(!this->volatile_initialized){ - // Anchor: rebuild local gold count as collected - delivered (carried gold is transient). - s32 goldBits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_BLUBBER); - s32 delivered = ((goldBits & 0x1) ? 1 : 0) + ((goldBits & 0x2) ? 1 : 0); - s32 pool = port_carriedSync_collectedCount(ANCHOR_COLLECTIBLE_GOLD) - delivered; - if (pool > item_getCount(ITEM_18_GOLD_BULLIONS)) { - item_adjustByDiffWithoutHud(ITEM_18_GOLD_BULLIONS, pool - item_getCount(ITEM_18_GOLD_BULLIONS)); - } if(this->state == CH_BLUBBER_STATE_3_UNKNOWN){ subaddie_set_state_with_direction(this, CH_BLUBBER_STATE_2_UNKNOWN, 0.0f, 1); } @@ -196,8 +157,8 @@ static void __chBlubber_updateFunc(Actor *this){ && !this->has_met_before && item_getCount(ITEM_18_GOLD_BULLIONS) == 0 ){ - gcdialog_showDialog(VER_SELECT(ASSET_A0B_DIALOG_BLUBBER_FIRST_MEET, 0x90B, 0, 0), 0xe, this->position, this->marker, __chBlubber_showTextCallback, NULL); - this->has_met_before = TRUE; + gcdialog_showDialog(ASSET_A0B_DIALOG_BLUBBER_FIRST_MEET, 0xe, this->position, this->marker, __chBlubber_showTextCallback, NULL); + this->has_met_before = true; subaddie_set_state_forward(this, CH_BLUBBER_STATE_3_UNKNOWN); } @@ -205,7 +166,7 @@ static void __chBlubber_updateFunc(Actor *this){ && !this->unk138_23 ){ if (item_getCount(ITEM_18_GOLD_BULLIONS) == 0) { - gcdialog_showDialog(VER_SELECT(ASSET_A0C_DIALOG_BLUBBER_HALF_GOLD, 0x90C, 0, 0), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_A0C_DIALOG_BLUBBER_HALF_GOLD, 4, NULL, NULL, NULL, NULL); } this->unk138_23 = true; @@ -295,6 +256,6 @@ static void __chBlubber_update2Func(Actor *this){ } static Actor *__chBlubber_drawFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - modelRender_setAppendageVisibility(4, 0); + func_8033A45C(4, 0); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/TTC/ch/clam.c b/src/TTC/ch/clam.c index ba46220e0..30e8cec20 100644 --- a/src/TTC/ch/clam.c +++ b/src/TTC/ch/clam.c @@ -101,7 +101,7 @@ static bool __chClam_rotateTowardTarget(Actor *this, s32 arg1) { anctrl_setDuration(this->anctrl, 1.0f); - sp2C = (s32) ((f64) ((float)FRAMERATE / (f32) time_getDeltaReal_frames()) * 0.5); + sp2C = (s32) ((f64) (60.0f / (f32) time_getDeltaReal_frames()) * 0.5); if ((this->unk1C[0] != 0.0f) || !__chClam_updateFuncTarget(this, sp2C)) { if (((f64) anctrl_getAnimTimer(this->anctrl) < 0.1) && ((f64) randf() < 0.5)) { if (this->unk1C[0] != 0.0f) { @@ -230,7 +230,7 @@ static void __chClam_takeDamage(ActorMarker *this_marker, ActorMarker *other_mar __chClam_emitLargeShellParticles(this->position, 2); __chClam_emitEyeParticles(this->position, 2); __chClam_emitSmallShellParticles(this->position, 0xC); - func_803115C4(VER_SELECT(ASSET_A14_DIALOG_CLAM_TAUNT, 0x914, 0, 0)); + func_803115C4(0xa14); marker_despawn(this->marker); } @@ -247,8 +247,8 @@ static void __chClam_attackOther(ActorMarker *this_marker, ActorMarker *other_ma if(baiFrame_getState() == 3) return; - if( !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN) && gcdialog_showDialog(VER_SELECT(ASSET_A14_DIALOG_CLAM_TAUNT, 0x914, 0, 0), 0, NULL, NULL, NULL, NULL)){ - mapSpecificFlags_set(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN, TRUE); + if( !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN) && gcdialog_showDialog(ASSET_A14_DIALOG_CLAM_TAUNT, 0, NULL, NULL, NULL, NULL)){ + mapSpecificFlags_set(TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN, true); } // [port] Match JP: only drop while fewer than 8 eggs / 5 red feathers are on the diff --git a/src/TTC/ch/leaky.c b/src/TTC/ch/leaky.c index 20002471d..567414556 100644 --- a/src/TTC/ch/leaky.c +++ b/src/TTC/ch/leaky.c @@ -57,21 +57,11 @@ static void __chLeaky_updateFunc(Actor *this) { } } - // Anchor: teammate finished feeding Leaky (LEVEL_FLAG_2) - lower water here too. - if (this->state == 1 && this->unk38_31 < 2 && levelSpecificFlags_get(LEVEL_FLAG_2_TTC_UNKNOWN)) { - Struct70s *water = func_8034C5AC(300); - if (water != NULL) { - func_8034E7B8(&water->type_73, -600, 4.0f, 2, 10.0f); - } - timedFunc_set_0(1.0f, __func_80388F88); - subaddie_set_state(this, 2); - } - - if( this->state == 1 + if( this->state == 1 && !this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 250) && !subaddie_playerIsWithinSphereAndActive(this, 160) - && !player_movementGroup() - && gcdialog_showDialog(VER_SELECT(ASSET_A1A_DIALOG_LEAKY_FIRST_MEET, 0x91A, 0, 0), 0, NULL, NULL, NULL, NULL) + && !player_movementGroup() + && gcdialog_showDialog(ASSET_A1A_DIALOG_LEAKY_FIRST_MEET, 0, NULL, NULL, NULL, NULL) ){ this->has_met_before = true; } @@ -127,8 +117,8 @@ bool chLeaky_eggCollision(ActorMarker *marker){ return true; } - levelSpecificFlags_set(2, TRUE); - levelSpecificFlags_set(5, TRUE); - gcdialog_showDialog(VER_SELECT(ASSET_A28_DIALOG_LEAKY_DONE, 0x928, 0, 0), 0x2a, this->position, this->marker, __chLeaky_showDoneText, NULL); - return TRUE; + levelSpecificFlags_set(2, true); + levelSpecificFlags_set(5, true); + gcdialog_showDialog(ASSET_A28_DIALOG_LEAKY_DONE, 0x2a, this->position, this->marker, __chLeaky_showDoneText, NULL); + return true; } diff --git a/src/TTC/ch/lockup.c b/src/TTC/ch/lockup.c index ab8f0467b..6ead9bebb 100644 --- a/src/TTC/ch/lockup.c +++ b/src/TTC/ch/lockup.c @@ -57,8 +57,8 @@ static s32 sLockup_CloseVelocity[3] = {0,0,0}; /* .code */ static Actor *__chLockup_drawFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor * actor = marker_getActor(marker); - modelRender_setAppendageVisibility(3, actor->unk38_31); - modelRender_setAppendageVisibility(4, actor->unk38_31); + func_8033A45C(3, actor->unk38_31); + func_8033A45C(4, actor->unk38_31); return actor_draw(marker, gfx, mtx, vtx); } @@ -87,9 +87,9 @@ static void __chLockup_updateFunc(Actor *this){ && subaddie_playerIsWithinSphereAndActive(this, 320) && !subaddie_playerIsWithinSphereAndActive(this, 160) && !player_movementGroup() - && gcdialog_showDialog(VER_SELECT(ASSET_A15_DIALOG_LOCKUP_SPAWNED, 0x915, 0, 0), 0, NULL, NULL, NULL, NULL)) { - - this->has_met_before = TRUE; + && gcdialog_showDialog(ASSET_A15_DIALOG_LOCKUP_SPAWNED, 0, NULL, NULL, NULL, NULL) + ){ + this->has_met_before = true; } if(!this->volatile_initialized){ diff --git a/src/TTC/ch/lockup.h b/src/TTC/ch/lockup.h deleted file mode 100644 index dc17d5d73..000000000 --- a/src/TTC/ch/lockup.h +++ /dev/null @@ -1,23 +0,0 @@ -// BanjoDecomp: TTC/ch/lockup.h -#define LOCKUP_WITH_JIGGY_ID 0xA - -#define LOCKUP_CYCLE_TICKS_SLOW 0x1E -#define LOCKUP_CYCLE_TICKS_MEDIUM 0x14 -#define LOCKUP_CYCLE_TICKS_FAST 0xA -#define LOCKUP_CYCLE_TICKS_DEFAULT 10000 - -typedef struct { - s32 closedTicksCounter; - s32 openTicksCounter; -} ActorLocal_Lockup; - -static Actor *chLockup_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx); -static void chLockup_update(Actor *this); - -enum ch_lockup_states_e { - CH_LOCKUP_STATE_CLOSED = 1, - CH_LOCKUP_STATE_OPENING = 2, - CH_LOCKUP_STATE_OPEN = 3, - CH_LOCKUP_STATE_CLOSING = 4, - CH_LOCKUP_STATE_CLOSING2 = 5 -}; diff --git a/src/TTC/ch/nipper.c b/src/TTC/ch/nipper.c index c9f0a2da3..a214258db 100644 --- a/src/TTC/ch/nipper.c +++ b/src/TTC/ch/nipper.c @@ -3,8 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - static void __chNipper_updateFunc(Actor *this); static Actor *__chNipper_animFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); @@ -18,24 +16,6 @@ enum ch_nipper_states_e { CH_NIPPER_STATE_7_UNKNOWN // already dead? L80388A20 }; -static s32 __chNipper_sharedHits(void) { - s32 bits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_NIPPER) & 0x7; - return (bits & 1) + ((bits >> 1) & 1) + ((bits >> 2) & 1); -} - -static s32 __chNipper_localHits(Actor *this) { - if (this->state == CH_NIPPER_STATE_6_DEAD || this->state == CH_NIPPER_STATE_7_UNKNOWN) { - return 3; - } - if (this->lifetime_value == 80.0f) { - return 1; - } - if (this->lifetime_value == 40.0f) { - return 2; - } - return 0; -} - /* .data */ ActorAnimationInfo gChNipperAnimations[8] = { {0, 0.0}, @@ -89,7 +69,7 @@ static Actor *__chNipper_animFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx Actor *this; this = marker_getActor(marker); - modelRender_setAppendageVisibility(3, (this->state == 7)? 0 : 1); + func_8033A45C(3, (this->state == 7)? 0 : 1); return actor_draw(marker, gfx, mtx, vtx); } @@ -157,7 +137,6 @@ static void __chNipper_dieFunc(ActorMarker *this_marker, ActorMarker *other_mark func_8032B4DC(this, other_marker, 7); if (this->lifetime_value == 40.0f) { - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_NIPPER, 0x7); subaddie_set_state_with_direction(this, CH_NIPPER_STATE_6_DEAD, 0.01f, 1); actor_playAnimationOnce(this); for(i = 0; i < 3; i++){ @@ -169,18 +148,16 @@ static void __chNipper_dieFunc(ActorMarker *this_marker, ActorMarker *other_mark gcStaticCamera_activate(0x1C); return; } - + if (this->lifetime_value == 80.0f) { - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_NIPPER, 0x3); __chNipper_playDeathAnimation(this); this->lifetime_value = 40.0f; return; } - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_NIPPER, 0x1); __chNipper_playDeathAnimation(this); this->lifetime_value = 80.0f; - gcdialog_showDialog(VER_SELECT(ASSET_A10_DIALOG_NIPPER_HURT, 0x910, 0, 0), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_A10_DIALOG_NIPPER_HURT, 4, NULL, NULL, NULL, NULL); return; } @@ -201,7 +178,7 @@ static void __chNipper_ow2Func(ActorMarker * this_marker, ActorMarker *other_mar this = marker_getActor(this_marker); if( !mapSpecificFlags_get(TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN) && this->has_met_before - && gcdialog_showDialog(VER_SELECT(ASSET_A0F_DIALOG_NIPPER_HIT_BY_EGG, 0x90F, 0, 0), 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(ASSET_A0F_DIALOG_NIPPER_HIT_BY_EGG, 0, NULL, NULL, NULL, NULL) ){ mapSpecificFlags_set(TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN, true); } @@ -212,7 +189,7 @@ static void __chNipper_owFunc(ActorMarker * this_marker, ActorMarker *other_mark Actor *this = marker_getActor(this_marker); if( !this->unk138_23 && this->has_met_before - && gcdialog_showDialog(VER_SELECT(ASSET_A11_DIALOG_NIPPER_ATTACK, 0x911, 0, 0), 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(ASSET_A11_DIALOG_NIPPER_ATTACK, 0, NULL, NULL, NULL, NULL) ){ this->unk138_23 = true; } @@ -224,7 +201,6 @@ static void __chNipper_updateFunc(Actor *this){ s32 xVelocity; f32 playerPosition[3]; enum bsgroup_e player_movement_group; - s32 sharedHits; player_getPosition(playerPosition); xVelocity = func_80309D58(playerPosition, 1); @@ -249,24 +225,6 @@ static void __chNipper_updateFunc(Actor *this){ this->velocity_x = xVelocity; } - if (this->initialized && this->state != CH_NIPPER_STATE_4_DIEING && this->state != CH_NIPPER_STATE_6_DEAD && - this->state != CH_NIPPER_STATE_7_UNKNOWN) { - sharedHits = __chNipper_sharedHits(); - if (__chNipper_localHits(this) < sharedHits) { - if (sharedHits >= 3) { - this->lifetime_value = 40.0f; - subaddie_set_state_with_direction(this, CH_NIPPER_STATE_6_DEAD, 0.01f, 1); - actor_playAnimationOnce(this); - sfx_playFadeShorthandDefault(SFX_78_EAGLECRY, 0.7f, 20000, this->position, 1500, 3000); - comusic_8025AB44(COMUSIC_12_TTC_NIPPER, 0, 300); - func_8025AABC(COMUSIC_12_TTC_NIPPER); - func_8032BB88(this, -1, 300); - } else { - this->lifetime_value = (sharedHits == 1) ? 80.0f : 40.0f; - } - } - } - switch(this->state){ case CH_NIPPER_STATE_1_UNKNOWN: if(!this->initialized){ @@ -286,8 +244,8 @@ static void __chNipper_updateFunc(Actor *this){ && player_movement_group != BSGROUP_A_FLYING ){ subaddie_set_state_with_direction(this, CH_NIPPER_STATE_5_SPAWNED, 0.01f, 1); - if(gcdialog_showDialog(VER_SELECT(ASSET_A0E_DIALOG_NIPPER_SPAWNED, 0x90E, 0, 0), 0xf, this->position, this->marker, __chNipper_spawnedShowTextCallback, NULL)){ - this->has_met_before = TRUE; + if(gcdialog_showDialog(ASSET_A0E_DIALOG_NIPPER_SPAWNED, 0xf, this->position, this->marker, __chNipper_spawnedShowTextCallback, NULL)){ + this->has_met_before = true; } comusic_8025AB44(COMUSIC_12_TTC_NIPPER, 5000, 300); ncStaticCamera_setToNode(11); diff --git a/src/TTC/ch/treasure.c b/src/TTC/ch/treasure.c index 3ae54cf0d..018059318 100644 --- a/src/TTC/ch/treasure.c +++ b/src/TTC/ch/treasure.c @@ -25,7 +25,7 @@ static void __chTreasure_die(ActorMarker *marker, ActorMarker *otherMarker){ Actor *this = marker_getActor(marker); __spawnQueue_add_4((GenFunction_4) spawnQueue_actor_f32, 0x4C, reinterpret_cast(s32, this->position[0]), reinterpret_cast(s32, this->position[1]), reinterpret_cast(s32, this->position[2])); func_802EE278(this, 3, 0xf, 0x3C, 0.2f, 1.2f); - func_803115C4(VER_SELECT(0xA19, 0x919, 0, 0)); + func_803115C4(0xA19); jiggy_spawn(JIGGY_11_TTC_RED_X, this->position); marker_despawn(marker); } diff --git a/src/TTC/ch/treasurehunt.c b/src/TTC/ch/treasurehunt.c index ca861780c..d7379f5d3 100644 --- a/src/TTC/ch/treasurehunt.c +++ b/src/TTC/ch/treasurehunt.c @@ -3,8 +3,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - extern f32 mapModel_getFloorY(f32[3]); // func_8028F45C declared in port_prototypes.h (returns bool) @@ -15,7 +13,7 @@ typedef struct { static void __chTreasurehunt_updateFunc(Actor *this); static Actor *__chTreasurehunt_animFunc(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -extern u32 chtreasureHunt_puzzleCurrentStep; +extern u32 CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; /* .data */ static f32 sChTreasurehunt_stepPositions[6][3] = { @@ -82,7 +80,7 @@ static bool __chTreasurehunt_isActiveHitboxBeakBusterHitbox(void) { if (player_getActiveHitbox(0) == HITBOX_1_BEAK_BUSTER) { comusic_id = COMUSIC_2B_DING_B; music_volume = 28000; - if (chtreasureHunt_puzzleCurrentStep == 5) { + if (CH_TREASUREHUNT_PUZZLE_CURRENT_STEP == 5) { comusic_id = COMUSIC_2D_PUZZLE_SOLVED_FANFARE; music_volume = 0x7FFF; } @@ -96,10 +94,10 @@ static void __chTreasurehunt_spawnRedXForNextStep(void) { Actor *actor; ActorLocal_TreasureHunt *local; - actor = actor_spawnWithYaw_f32(ACTOR_55_RED_X, sChTreasurehunt_stepPositions[chtreasureHunt_puzzleCurrentStep], 0); + actor = actor_spawnWithYaw_f32(ACTOR_55_RED_X, sChTreasurehunt_stepPositions[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP], 0); local = (ActorLocal_TreasureHunt *)&actor->local; - actor->yaw = sChTreasurehunt_StepRedXYaws[chtreasureHunt_puzzleCurrentStep]; - local->unk0 = chtreasureHunt_puzzleCurrentStep; + actor->yaw = sChTreasurehunt_StepRedXYaws[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP]; + local->unk0 = CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; actor->lifetime_value = 0.0f; actor->state = 0; } @@ -108,25 +106,24 @@ static void __chTreasurehunt_spawnActorForNextStep(void) { Actor *actor; ActorLocal_TreasureHunt *local; - actor = actor_spawnWithYaw_f32((sChTreasurehunt_StepActors - 1)[chtreasureHunt_puzzleCurrentStep], sChTreasurehunt_stepPositions[chtreasureHunt_puzzleCurrentStep - 1], 0); + actor = actor_spawnWithYaw_f32((sChTreasurehunt_StepActors - 1)[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP], sChTreasurehunt_stepPositions[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP - 1], 0); local = (ActorLocal_TreasureHunt *)&actor->local; - actor->yaw = sChTreasurehunt_StepYaws[chtreasureHunt_puzzleCurrentStep - 1]; - local->unk0 = chtreasureHunt_puzzleCurrentStep; + actor->yaw = sChTreasurehunt_StepYaws[CH_TREASUREHUNT_PUZZLE_CURRENT_STEP - 1]; + local->unk0 = CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; actor->lifetime_value = 0.0f; actor->state = 0; } static void __chTreasurehunt_checkStepProgress(s32 currentStep){ - if(chtreasureHunt_puzzleCurrentStep == currentStep && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ + if(CH_TREASUREHUNT_PUZZLE_CURRENT_STEP == currentStep && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ if(currentStep == 0 && !jiggyscore_isCollected(JIGGY_11_TTC_RED_X)){ - gcdialog_showDialog(VER_SELECT(ASSET_A18_DIALOG_TREASUREHUNT_FOLLOW_CLUES, 0x918, 0, 0), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_A18_DIALOG_TREASUREHUNT_FOLLOW_CLUES, 4, NULL, NULL, NULL, NULL); } else if(currentStep == 4){ - gcdialog_showDialog(VER_SELECT(ASSET_A19_DIALOG_TREASUREHUNT_SECOND_STEP, 0x919, 0, 0), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(ASSET_A19_DIALOG_TREASUREHUNT_SECOND_STEP, 4, NULL, NULL, NULL, NULL); } - chtreasureHunt_puzzleCurrentStep++; - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_XHUNT, (1 << chtreasureHunt_puzzleCurrentStep) - 1); + CH_TREASUREHUNT_PUZZLE_CURRENT_STEP++; __spawnQueue_add_0(__chTreasurehunt_spawnActorForNextStep); __spawnQueue_add_0(__chTreasurehunt_spawnRedXForNextStep); } @@ -156,7 +153,7 @@ void chTreasurehunt_checkStepProgress5(NodeProp *this, ActorMarker *arg1){ static ParticleEmitter *particleEmitter; static f32 particleTargetPosition[3]; - if(chtreasureHunt_puzzleCurrentStep == 5 && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ + if(CH_TREASUREHUNT_PUZZLE_CURRENT_STEP == 5 && __chTreasurehunt_isActiveHitboxBeakBusterHitbox()){ particleTargetPosition[0] = (f32)this->x; particleTargetPosition[1] = (f32)this->y; particleTargetPosition[2] = (f32)this->z; @@ -174,48 +171,13 @@ void chTreasurehunt_checkStepProgress5(NodeProp *this, ActorMarker *arg1){ gcpausemenu_80314AC8(0); timedFunc_set_2(0.1f, (GenFunction_2) func_8028F45C, 9, (uintptr_t)&particleTargetPosition); timedFunc_set_1(0.1f, (GenFunction_1) gcpausemenu_80314AC8, 1); - gcdialog_showDialog(VER_SELECT(ASSET_A17_DIALOG_BURIED_TREASURE_SPAWNED, 0x917, 0, 0), 4, NULL, NULL, NULL, NULL); - chtreasureHunt_puzzleCurrentStep++; - port_puzzleStep_orBits(ANCHOR_PUZZLE_TTC_XHUNT, 0x3F); + gcdialog_showDialog(ASSET_A17_DIALOG_BURIED_TREASURE_SPAWNED, 4, NULL, NULL, NULL, NULL); + CH_TREASUREHUNT_PUZZLE_CURRENT_STEP++; } } void chTreasurehunt_resetProgress(void){ - chtreasureHunt_puzzleCurrentStep = 0; -} - -// Anchor: replay teammates' hunt steps, one per frame; called each frame in TTC (PuzzleStep.cpp). -void chTreasurehunt_netTick(void){ - static f32 sNetTreasurePosition[3]; - s32 bits = port_puzzleStep_get(ANCHOR_PUZZLE_TTC_XHUNT) & 0x3F; - s32 sharedStep = 0; - - while(bits & 1){ - sharedStep++; - bits >>= 1; - } - if((s32)chtreasureHunt_puzzleCurrentStep >= sharedStep){ - return; - } - - if(chtreasureHunt_puzzleCurrentStep < 5){ - chtreasureHunt_puzzleCurrentStep++; - __spawnQueue_add_0(__chTreasurehunt_spawnActorForNextStep); - __spawnQueue_add_0(__chTreasurehunt_spawnRedXForNextStep); - } - else{ - chtreasureHunt_puzzleCurrentStep++; - if(!jiggyscore_isSpawned(JIGGY_11_TTC_RED_X) && !jiggyscore_isCollected(JIGGY_11_TTC_RED_X)){ - sNetTreasurePosition[0] = sChTreasurehunt_stepPositions[5][0]; - sNetTreasurePosition[1] = sChTreasurehunt_stepPositions[5][1]; - sNetTreasurePosition[2] = sChTreasurehunt_stepPositions[5][2]; - sNetTreasurePosition[1] = mapModel_getFloorY(sNetTreasurePosition); - __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_F4_BURIED_TREASURE, - reinterpret_cast(s32, sNetTreasurePosition[0]), - reinterpret_cast(s32, sNetTreasurePosition[1]), - reinterpret_cast(s32, sNetTreasurePosition[2])); - } - } + CH_TREASUREHUNT_PUZZLE_CURRENT_STEP = 0; } static void __chTreasurehunt_updateFunc(Actor *this){ @@ -237,7 +199,7 @@ static void __chTreasurehunt_updateFunc(Actor *this){ } break; case 1: - if(local->unk0 < chtreasureHunt_puzzleCurrentStep){ + if(local->unk0 < CH_TREASUREHUNT_PUZZLE_CURRENT_STEP){ this->state = 2; } break; diff --git a/src/TTC/checksums.c b/src/TTC/checksums.c deleted file mode 100644 index d920d19ab..000000000 --- a/src/TTC/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: TTC/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsTTC; diff --git a/src/TTC/crc.c b/src/TTC/crc.c index 74fbbf619..9ee04e8bb 100644 --- a/src/TTC/crc.c +++ b/src/TTC/crc.c @@ -2,11 +2,24 @@ #include #include "functions.h" #include "variables.h" -#include "checksums.h" -s32 D_8038C750 = VER_SELECT(0x0016D2FD, 0x0016D2D7, 0, 0); // TTC_TEXT_CRC1 -s32 D_8038C754 = VER_SELECT(0xFB70B01D, 0xFCA4DD1E, 0, 0); // TTC_TEXT_CRC2 -s32 D_8038C758 = VER_SELECT(0x0004EFAC, 0x0004FD17, 0, 0); // TTC_DATA_CRC1 +extern s32 D_80276CB0; + +/* .data */ +// code crc0 +s32 D_8038C750 = 0x0016D2FD; +// code crc1 +s32 D_8038C754 = 0xFB70B01D; +// data crc +s32 D_8038C758 = 0x0004EFAC; + +/* .bss */ +struct { + u8 pad0[4]; + s32 unk4; + u8 pad8[4]; + s32 unkC; +} sD_8038D6F0; /* .code */ void __code3040_makeBanjoAlwaysSlippery(){ @@ -18,7 +31,7 @@ void __code3040_makeBanjoAlwaysSlippery(){ void code3040_checkTTCChecksums(void){ // [port] This crc check makes the ground in TTC slippery #if ANTI_TAMPER - if(gChecksumsTTC.text_checksum2 != D_8038C754 || gChecksumsTTC.data_checksum2 != D_80276CB0){ + if(sD_8038D6F0.unk4 != D_8038C754 || sD_8038D6F0.unkC != D_80276CB0){ __code3040_makeBanjoAlwaysSlippery(); } #endif diff --git a/src/boot/bk_boot_1050.c b/src/boot/bk_boot_1050.c index d2e5b21af..837606bb7 100644 --- a/src/boot/bk_boot_1050.c +++ b/src/boot/bk_boot_1050.c @@ -2,7 +2,6 @@ #include "boot/overlaytable.h" #include "boot/rarezip.h" #include "core1/main.h" -#include "checksums.h" #define ENTRY_STACK_LEN 0x2000 @@ -10,6 +9,7 @@ u8 gEntryStack[ENTRY_STACK_LEN]; extern u8 gHeapBase[]; extern u8 core1_VRAM[]; +extern u32 gCore1CRCs[4]; /// @brief Entry point of the game /// @param arg0 unused/unknown parameter @@ -34,12 +34,12 @@ void func_80000450(s32 arg0) { rarezip_init(); rarezip_uncompress_file_and_update_pointers(&in, &out); - gChecksumsCore1.text_checksum1 = inflate_crc1; - gChecksumsCore1.text_checksum2 = inflate_crc2; + gCore1CRCs[0] = inflate_crc1; + gCore1CRCs[1] = inflate_crc2; rarezip_uncompress_file_and_update_pointers(&in, &out); - gChecksumsCore1.data_checksum1 = inflate_crc1; - gChecksumsCore1.data_checksum2 = inflate_crc2; + gCore1CRCs[2] = inflate_crc1; + gCore1CRCs[3] = inflate_crc2; overlaytable_init(); diff --git a/src/core1/audio_instruments.c b/src/core1/audio_instruments.c index b7830b253..e30440c74 100644 --- a/src/core1/audio_instruments.c +++ b/src/core1/audio_instruments.c @@ -3,7 +3,6 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "port/ShipUtils.h" // gPortResetPending #include "music.h" #include @@ -17,6 +16,11 @@ extern void func_8025F570(ALCSPlayer *, u8); extern void func_8025F510(ALCSPlayer *, u8, u8); extern void func_8025F5C0(ALCSPlayer *, u8); +extern OSIoMesg *func_802405D0(void); +extern OSMesgQueue *func_802405C4(void); +extern ALHeap *func_802405B8(void); +extern void func_8023FA64(ALSeqpConfig *arg0); + extern u8 *soundfont2ctl_ROM_START; extern u8 *soundfont2ctl_ROM_END; extern u8 *soundfont2tbl_ROM_START; @@ -253,11 +257,11 @@ void musicInstruments_init(void){ D_802820E8.maxVoices = 0x18; D_802820E8.maxEvents = 0x55; D_802820E8.maxChannels = 0x10; - D_802820E8.heap = audioManager_getALHeapInfo(); + D_802820E8.heap = func_802405B8(); D_802820E8.initOsc = NULL; D_802820E8.updateOsc = NULL; D_802820E8.stopOsc = NULL; - audioManager_setupSeqp(&D_802820E8); + func_8023FA64(&D_802820E8); for(i = 0; i < 6; i++){ n_alCSPNew((N_ALCSPlayer *)&D_80281720[i].cseqp, &D_802820E8); } @@ -511,14 +515,14 @@ s32 gcMusic_getDefaultVolumeForTrack(s32 track_id){ return 0; } -void gcMusic_setDefaultVolumeForTrack(s32 track_id, u16 arg1){ +void func_80250048(s32 track_id, u16 arg1){ if (track_id >= 0 && track_id < 0xB0) { D_80275D40[track_id].volume = arg1; } } //song_getName -char *gcMusic_getNameForTrack(s32 track_id){ +char *func_80250060(s32 track_id){ if (track_id >= 0 && track_id < 0xB0) { return D_80275D40[track_id].name; } diff --git a/src/core1/audio_manager.c b/src/core1/audio_manager.c index 091412825..711a203b1 100644 --- a/src/core1/audio_manager.c +++ b/src/core1/audio_manager.c @@ -7,13 +7,8 @@ //#include "PR/sched.h" #include "n_audio/PR/n_libaudio.h" //#include "PR/os_system.h" -#include "port/DevTools/ThreadWatchdog.h" -#include "port/OS/OS.h" -#include "port/Patches/Patches.h" #include "port/ShipUtils.h" -#define DMA_BLOCK_SIZE VER_SELECT(0x200, 0x270, 0x200, 0x200) - // [port] BK audio - SDK calls stubbed, functions preserved for game code // [port] 64-bit structs with pointers are larger — double the heap @@ -22,58 +17,70 @@ #else #define AUDIO_HEAP_SIZE VER_SELECT(0x21000, 0x23A00, 0x21000, 0x21000) #endif -#define AUDIOMANAGER_THREAD_STACK_SIZE 3704 -#define NUM_SAMPLES 184 // n_audio has fixed sample count of 184 -#define NUM_OSC_STATES 48 -#define NUM_AUDIO_CMDS_PER_SECOND 150000 - -struct audio_info_mesg_data_s { - s16 unk0; - struct audio_info_s *audio_info_ptr; -}; +#define AUDIOMANAGER_THREAD_STACK_SIZE 0xE78 + +extern void n_alInit(N_ALGlobals *, ALSynConfig *); -typedef struct audio_info_s { - s16 *data; /* Output data pointer */ - s16 frame_samples; /* number of samples synthesized in this frame */ - struct audio_info_mesg_data_s reply_mesg_data; + +typedef struct AudioInfo_s { + short *data; /* Output data pointer */ + short frameSamples; /* # of samples synthesized in this frame */ + u8 pad4[2]; + s16 unk8; + u8 padA[2]; + struct AudioInfo_s *unkC; } AudioInfo; -struct dma_state_data_s { - ALLink link; - uintptr_t unk8; // device address +typedef struct Struct_1D00_1_s{ + void *unk0; + u8 pad4[4]; + s16 unk8; + u8 pada[2]; + struct Struct_1D00_1_s *unkC; +} Struct_1D00_1; + +typedef struct { + u8 pad0[4]; + AudioInfo *unk4; +} Struct_1D00_2; + +typedef struct Struct_1D00_3_s{ + ALLink unk0; + uintptr_t unk8; uintptr_t unkC; - uintptr_t heap; -}; + uintptr_t unk10; +} Struct_1D00_3; typedef struct{ u8 pad0[0x18]; }Struct_core1_1D00_4; -typedef struct osc_state_s { - struct osc_state_s *next; +typedef struct struct_core1_1D00_5_s{ + struct struct_core1_1D00_5_s * next; u8 type; - u16 unk6; // current value - u16 unk8; // max value - union { - struct { u8 unk0; u8 unk1; } type1; - struct { f32 cents; } type80; - } unkC; -} OscState; + // u8 pad5[1]; + u16 unk6; + u16 unk8; + union{ + struct{u8 unk0; u8 unk1;}type1; + struct{f32 unk0;}type80; + }unkC; +}OscState; void audioManager_create(void); void audioManagerThread_entry(void *arg); +// void func_802403B8(void); void audioManager_handleDoneMsg(AudioInfo *info); -ALDMAproc audioManager_DMAInitProc(void *state); -void audioManager_func_802403F0(void); +void *func_802403B8(void *state); +void func_802403F0(void); void audioManager_startThread(void); bool audioManager_handleFrameMsg(AudioInfo *info, AudioInfo *prev_info); s32 D_80275770 = 0; -bool sAudioManagerThreadStarted = false; +s32 D_80275774 = 0; u8 D_80275778 = 0; - -s32 sEffectsChain[] = { +s32 D_8027577C[] = { 6, /* number of sections in this effect */ 0x1900, /* total allocated memory */ /* SECTION 1 */ @@ -132,47 +139,57 @@ s32 sEffectsChain[] = { 0x4500 /* low-pass filter */ }; -struct audio_info_mesg_data_s *D_80275844 = NULL; -AudioInfo *sPrevFinishedAudioInfo = NULL; +Struct_1D00_2 *D_80275844 = NULL; +AudioInfo *D_80275848 = NULL; +// extern int D_8027584C;//static int D_8027584C = 0; + +extern s32 osViClock; //0x80277128 -extern s32 osViClock; +extern f32 D_80277620; +extern f64 D_80277628; +extern f64 D_80277630; +extern f32 D_80277638; struct { - Acmd *ACMDList[2]; - AudioInfo *audio_info[3]; + Acmd* ACMDList[2]; + AudioInfo *audioInfo[3]; OSThread thread; OSMesgQueue audioFrameMsgQ; OSMesg audioFrameMsgBuf[8]; OSMesgQueue audioReplyMsgQ; OSMesg audioReplyMsgBuf[8]; - u8 thread_stack[AUDIOMANAGER_THREAD_STACK_SIZE]; } audioManager; -ALHeap sALHeapInfo; -u8 *sALHeapBuffer; -s32 pad_8027D004; -OSMesgQueue audioDMANotifyMsgQ; -OSMesg audioDMANotifyMsgBuf[3000 / FRAMERATE]; -OSIoMesg sExtraDMAMesg; -Struct_core1_1D00_4 sDMAMesgBlocks[3000 / FRAMERATE]; +u8 sAudioManagerThreadStack[AUDIOMANAGER_THREAD_STACK_SIZE]; +ALHeap D_8027CFF0; +u8 * D_8027D000; +s32 D_8027D004; +OSMesgQueue D_8027D008; +OSMesg D_8027D020[3000/FRAMERATE]; +OSIoMesg D_8027D0E8; +Struct_core1_1D00_4 D_8027D100[3000/FRAMERATE]; struct { - u8 initialized; - struct dma_state_data_s *unk4; - struct dma_state_data_s *unk8; -} sDMAState; -struct dma_state_data_s sDMAStateData[90]; -s32 sAudioInfoID; -s32 sNumDMATransfers; // DMA IO Message blocks index -s32 sCmdBufferIndex; -N_ALGlobals sn_alGlobals; -ALSynConfig sn_alConfig; -s32 sFrameSize; -s32 sMinFrameSize; -s32 sMaxFrameSize; -s32 sNumAudioCmdsPerFrame; + u8 unk0; + Struct_1D00_3 *unk4; + Struct_1D00_3 *unk8; + u8 padC[0x4]; +} D_8027D5B0; +Struct_1D00_3 D_8027D5C0[90]; +s32 D_8027DCC8; +s32 D_8027DCCC; +s32 D_8027DCD0; +N_ALGlobals D_8027DCD8; +ALSynConfig D_8027DD50; +s32 D_8027DD74; +s32 D_8027DD78; +s32 D_8027DD7C; +s32 D_8027DD80; OscState *freeOscStateList; -OscState oscStates[NUM_OSC_STATES]; +OscState oscStates[48]; + -f32 depth2Cents(u8 depth) { +/* .code */ +f32 _depth2Cents(u8 depth) +{ f32 x = 1.03099298f; f32 cents = 1.0f; @@ -188,7 +205,8 @@ f32 depth2Cents(u8 depth) { return cents; } -ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 oscDepth, u8 oscDelay) { +ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 oscDepth, u8 oscDelay, u8 arg6) +{ OscState *state; ALMicroTime result = 0; @@ -200,99 +218,97 @@ ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 os result = oscDelay << 14; switch (oscType) { - case 1: - state->unk8 = 0; - state->unk6 = 259 - oscRate; - state->unkC.type1.unk0 = oscDepth >> 1; - state->unkC.type1.unk1 = 127 - state->unkC.type1.unk0; - *initVal = state->unkC.type1.unk1; - break; - - case 0x80: - state->unkC.type80.cents = depth2Cents(oscDepth); - state->unk8 = 0; - state->unk6 = 259 - oscRate; - *initVal = 1.0f; - break; - - default: - break; + case 1: + state->unk8 = 0; + state->unk6 = 259 - oscRate; + state->unkC.type1.unk0 = oscDepth >> 1; + state->unkC.type1.unk1 = 127 - state->unkC.type1.unk0; + *initVal = state->unkC.type1.unk1; + break; + case 0x80: + state->unkC.type80.unk0 = _depth2Cents(oscDepth); + state->unk8 = 0; + state->unk6 = 259 - oscRate; + *initVal = 1.0f; + break; + default: + break; } } return result; } -ALMicroTime updateOsc(void *oscState, f32 *updateVal) { +ALMicroTime updateOsc(void *oscState, f32 *updateVal) +{ f32 sp2c; OscState *state = oscState; ALMicroTime result = AL_USEC_PER_FRAME; switch (state->type) { - case 0x01: - state->unk8++; + case 0x01: + state->unk8++; - if (state->unk8 >= state->unk6) { - state->unk8 = 0; - } + if (state->unk8 >= state->unk6) { + state->unk8 = 0; + } - sp2c = (f32)state->unk8 / (f32)state->unk6; - sp2c = sinf(sp2c * BAD_TAU); - sp2c = sp2c * state->unkC.type1.unk0; - *updateVal = state->unkC.type1.unk1 + sp2c; - break; + sp2c = (f32)state->unk8 / (f32)state->unk6; + sp2c = sinf(sp2c * BAD_TAU); + sp2c = sp2c * state->unkC.type1.unk0; + *updateVal = state->unkC.type1.unk1 + sp2c; + break; - case 0x80: - state->unk8++; + case 0x80: + state->unk8++; - if (state->unk8 >= state->unk6) { - state->unk8 = 0; - } + if (state->unk8 >= state->unk6) { + state->unk8 = 0; + } - sp2c = (f32)state->unk8 / (f32)state->unk6; - sp2c = sinf(sp2c * BAD_TAU) * state->unkC.type80.cents; - *updateVal = alCents2Ratio(sp2c); - break; - default: - break; + sp2c = (f32)state->unk8 / (f32)state->unk6; + sp2c = sinf(sp2c * BAD_TAU) * state->unkC.type80.unk0; + *updateVal = alCents2Ratio(sp2c); + break; + default: + break; } return result; } -void stopOsc(OscState *oscState) { +void stopOsc(OscState *oscState){ oscState->next = freeOscStateList; freeOscStateList = oscState; } -void audioManager_setupSeqp(ALSeqpConfig *config) { +void func_8023FA64(ALSeqpConfig *arg0) { OscState *item; - int i; + s32 i; - freeOscStateList = &oscStates[0]; + freeOscStateList = &oscStates[0]; item = &oscStates[0]; - for (i = 0; i < NUM_OSC_STATES - 1; i++) { - item->next = &oscStates[i + 1]; + for(i = 0; i< 0x2F; i++){ + item->next = &oscStates[i+1]; item = item->next; } item->next = NULL; - - config->initOsc = initOsc; - config->updateOsc = updateOsc; - config->stopOsc = stopOsc; + arg0->initOsc = initOsc; + arg0->updateOsc = updateOsc; + arg0->stopOsc = stopOsc; } extern s32 osTvType; -void audioManager_init(void) { - sALHeapBuffer = (u8 *) bk_malloc(AUDIO_HEAP_SIZE); - bzero(sALHeapBuffer, AUDIO_HEAP_SIZE); - alHeapInit(&sALHeapInfo, sALHeapBuffer, AUDIO_HEAP_SIZE); +void audioManager_init(void){ + D_8027D000 = (u8 *) bk_malloc(AUDIO_HEAP_SIZE); + bzero(D_8027D000, AUDIO_HEAP_SIZE); + alHeapInit(&D_8027CFF0, D_8027D000, AUDIO_HEAP_SIZE); #if VERSION == VERSION_USA_1_0 - if (osTvType != OS_TV_NTSC) - osViClock = VI_MPAL_CLOCK; + if(osTvType != OS_TV_NTSC) + osViClock = 0x2e6025c; #elif VERSION == VERSION_PAL - osViClock = VI_PAL_CLOCK; + osViClock = 0x2f5b2d2; #endif audioManager_create(); sfxInstruments_init(); @@ -302,346 +318,351 @@ void audioManager_init(void) { void audioManager_create(void) { int i; - f32 fsize; + f32 var_f0; - osCreateMesgQueue(&audioDMANotifyMsgQ, audioDMANotifyMsgBuf, 3000 / FRAMERATE); - osCreateMesgQueue(&audioManager.audioReplyMsgQ, audioManager.audioReplyMsgBuf, 8); + osCreateMesgQueue(&D_8027D008, D_8027D020, 3000/FRAMERATE); + osCreateMesgQueue(&audioManager.audioReplyMsgQ, audioManager.audioReplyMsgBuf, 8); //audioReplyMesgQueue osCreateMesgQueue(&audioManager.audioFrameMsgQ, audioManager.audioFrameMsgBuf, 8); - - fsize = 44000.0f / FRAMERATE; - sFrameSize = fsize; - if (sFrameSize < fsize) { - sFrameSize++; + var_f0 = 44000.0f/FRAMERATE; + D_8027DD74 = (s32)var_f0; + if ((f32) D_8027DD74 < var_f0) { + D_8027DD74++; } - sFrameSize = ((sFrameSize / NUM_SAMPLES) + 1) * NUM_SAMPLES; - sMinFrameSize = sFrameSize - NUM_SAMPLES; - sMaxFrameSize = sFrameSize; - - sn_alConfig.maxVVoices = 24; - sn_alConfig.maxPVoices = 24; - sn_alConfig.maxUpdates = 0x100; // [port] doubled — 64-bit param slots are larger, demand-based audio may call n_alAudioFrame multiple times per game frame - sn_alConfig.dmaproc = (void *) audioManager_DMAInitProc; - sn_alConfig.fxType = AL_FX_CUSTOM; - sn_alConfig.params = sEffectsChain; - sn_alConfig.heap = &sALHeapInfo; - sn_alConfig.outputRate = osAiSetFrequency(22000); - n_alInit(&sn_alGlobals, &sn_alConfig); - - sDMAStateData[0].link.prev = NULL; - sDMAStateData[0].link.next = NULL; - - for (i = 0; i < 89; i++) { - alLink(&sDMAStateData[i + 1].link, &sDMAStateData[i].link); - sDMAStateData[i].heap = (uintptr_t)alHeapDBAlloc(0, 0, sn_alConfig.heap, 1, DMA_BLOCK_SIZE); + D_8027DD74 = ((D_8027DD74 / 0xB8) * 0xB8) + 0xB8; + D_8027DD78 = D_8027DD74 - 0xB8; + D_8027DD7C = D_8027DD74; + D_8027DD50.maxVVoices = 0x18; + D_8027DD50.maxPVoices = 0x18; + D_8027DD50.maxUpdates = 0x100; // [port] doubled — 64-bit param slots are larger, demand-based audio may call n_alAudioFrame multiple times per game frame + D_8027DD50.dmaproc = (void*)func_802403B8; + D_8027DD50.fxType = AL_FX_CUSTOM; + D_8027DD50.params = (void*) &D_8027577C; + D_8027DD50.heap = &D_8027CFF0; + D_8027DD50.outputRate = osAiSetFrequency(22000); + n_alInit(&D_8027DCD8, &D_8027DD50); + D_8027D5C0[0].unk0.prev = NULL; + D_8027D5C0[0].unk0.next = NULL; + for(i = 0; i < 89; i++){ + alLink((ALLink *)&D_8027D5C0[i+1], (ALLink *)&D_8027D5C0[i]); + D_8027D5C0[i].unk10 = (uintptr_t)alHeapDBAlloc(0, 0, D_8027DD50.heap, 1, VER_SELECT(0x200, 0x270, 0x200, 0x200)); } - - sDMAStateData[i].heap = (uintptr_t)alHeapDBAlloc(0, 0, sn_alConfig.heap, 1, DMA_BLOCK_SIZE); - - for (i = 0; i < 2; i++) { - audioManager.ACMDList[i] = bk_malloc(NUM_AUDIO_CMDS_PER_SECOND * sizeof(Acmd) / FRAMERATE); + D_8027D5C0[i].unk10 = (uintptr_t)alHeapDBAlloc(0, 0, D_8027DD50.heap, 1, VER_SELECT(0x200, 0x270, 0x200, 0x200)); + for(i = 0; i < 2; i++){ + audioManager.ACMDList[i] = bk_malloc(1200000/FRAMERATE); } - sNumAudioCmdsPerFrame = NUM_AUDIO_CMDS_PER_SECOND / FRAMERATE; - - for (i = 0; i < 3; i++) { - audioManager.audio_info[i] = alHeapDBAlloc(0, 0, sn_alConfig.heap, 1, sizeof(AudioInfo)); - audioManager.audio_info[i]->reply_mesg_data.unk0 = 0; - audioManager.audio_info[i]->reply_mesg_data.audio_info_ptr = audioManager.audio_info[i]; - audioManager.audio_info[i]->data = bk_malloc(4 * sMaxFrameSize); + D_8027DD80 = 150000/FRAMERATE; + for(i = 0; i < 3; i++){ + audioManager.audioInfo[i] = alHeapDBAlloc(0, 0, D_8027DD50.heap, 1, 0x10); + audioManager.audioInfo[i]->unk8 = 0; + audioManager.audioInfo[i]->unkC = audioManager.audioInfo[i]; + audioManager.audioInfo[i]->data = bk_malloc(D_8027DD7C * 4); } - osCreateThread(&audioManager.thread, 4, &audioManagerThread_entry, 0, audioManager.thread_stack + AUDIOMANAGER_THREAD_STACK_SIZE, 50); + osCreateThread(&audioManager.thread, 4, &audioManagerThread_entry, 0, sAudioManagerThreadStack + AUDIOMANAGER_THREAD_STACK_SIZE, 50); } void audioManagerThread_entry(void *arg) { - s32 skip_handle_done_mesg = 1; + s32 phi_s1; - while (true) { + phi_s1 = 1; + while(1){ osRecvMesg(&audioManager.audioFrameMsgQ, NULL, OS_MESG_BLOCK); - if (OS_ThreadShouldExit()) { // [port] cooperative shutdown - return; - } - ThreadWatchdog_Beat(WATCHDOG_AUDIO_MANAGER); // [port] one beat per audio frame - // [port] Pump messages backlog while a stall blocks this thread - // and then burst. - if (osAiGetLength() / 4 >= sMaxFrameSize) { - continue; - } - if (audioManager_handleFrameMsg(audioManager.audio_info[sAudioInfoID % 3], sPrevFinishedAudioInfo)) { - if (skip_handle_done_mesg == 0) { - osRecvMesg(&audioManager.audioReplyMsgQ, (OSMesg *) &D_80275844, OS_MESG_BLOCK); - audioManager_handleDoneMsg(D_80275844->audio_info_ptr); - sPrevFinishedAudioInfo = D_80275844->audio_info_ptr; - } else { - skip_handle_done_mesg--; + if (audioManager_handleFrameMsg(audioManager.audioInfo[D_8027DCC8 % 3], D_80275848)){ + if(phi_s1 == 0){ + osRecvMesg(&audioManager.audioReplyMsgQ, (OSMesg *)&D_80275844, OS_MESG_BLOCK); + audioManager_handleDoneMsg(D_80275844->unk4); + D_80275848 = D_80275844->unk4; + }else{ + phi_s1 += -1; } } - // [port] The N64 pacing is open-loop (pump cadence x frame size vs the - // DAC, same crystal), so a pump missed on PC drains the playback - // cushion for tens of seconds. Self-post one extra frame at a time, - // re-deciding on the fresh buffer level after each push, until the - // cushion is rebuilt. - if (port_audioCatchupFrames() > 0) { - osSendMesgPtr(&audioManager.audioFrameMsgQ, NULL, OS_MESG_NOBLOCK); - } } } -void audioManager_func_8023FFAC(void) { - D_80275770 = osAiGetLength() / 4; +void func_8023FFAC(void){ + D_80275770 = osAiGetLength()/4; } -void audioManager_func_8023FFD4(s32 arg0, s32 arg1, s32 arg2) {} +void func_8023FFD4(s32 arg0, s32 arg1, s32 arg2){ + return; +} bool audioManager_handleFrameMsg(AudioInfo *info, AudioInfo *prev_info){ s16 *outbuffer; - Acmd *command_list_end; - s32 command_list_len; - s32 ret; - f32 pad; - + Acmd *sp38; + s32 sp34; #if VERSION == VERSION_USA_1_0 - ret = 0; + s32 sp30 = 0; +#else + s32 sp30; #endif + f32 pad; - // [port] On N64 nothing could run concurrently with this thread: one core, - // and the game brackets its audio writes with osSetIntMask, which blocks - // preemption. On PC those brackets map to a lock, and the engine advance - // here has to take the same one. - port_lockAudio(); - - outbuffer = (s16 *) osVirtualToPhysical(info->data); - audioManager_func_802403F0(); - audioManager_func_8023FFAC(); - if (prev_info) { - ret = osAiSetNextBuffer(prev_info->data, 4 * prev_info->frame_samples); - } + outbuffer = (s16 *)osVirtualToPhysical(info->data); + func_802403F0(); + func_8023FFAC(); + if(prev_info){ + sp30 = osAiSetNextBuffer(prev_info->data, prev_info->frameSamples*4); + }//L8024003C #if VERSION == VERSION_USA_1_0 - if (ret == -1) { - gcdebugText_showLargeValue(2, 2002); - func_80247F9C(prev_info->frame_samples); - func_80247F9C(info->frame_samples); + if(sp30 == -1){ + func_80247F24(2, 0x7d2); + func_80247F9C(prev_info->frameSamples); + func_80247F9C(info->frameSamples); gcdebugText_pauseThread(); - } + } #endif - if ((D_80275770 > 312) & !D_80275778) { - info->frame_samples = sMinFrameSize; + if((D_80275770 >= 0x139) & !D_80275778){ + info->frameSamples = D_8027DD78; D_80275778 = 2; - } else { - info->frame_samples = sFrameSize; - if (D_80275778) + } + else{ + info->frameSamples = D_8027DD74; + if(D_80275778) D_80275778--; } - if (info->frame_samples < sMinFrameSize) { - info->frame_samples = sMinFrameSize; + if(info->frameSamples < D_8027DD78){ + info->frameSamples = D_8027DD78; } - command_list_end = n_alAudioFrame(audioManager.ACMDList[sCmdBufferIndex], &command_list_len, outbuffer, info->frame_samples); + sp38 = n_alAudioFrame(audioManager.ACMDList[D_8027DCD0], &sp34, outbuffer, info->frameSamples); #if VERSION == VERSION_USA_1_0 - if (sNumAudioCmdsPerFrame < command_list_len) { - gcdebugText_showLargeValue(2, 2000); - func_80247F9C(command_list_len); - func_80247F9C(sNumAudioCmdsPerFrame); + if(D_8027DD80 < sp34){ + func_80247F24(2, 2000); + func_80247F9C(sp34); + func_80247F9C(D_8027DD80); gcdebugText_pauseThread(); } #endif - if (command_list_len == 0) { - port_unlockAudio(); // [port] - return false; - } else { - core1_15B30_addAudioTaskData(audioManager.ACMDList[sCmdBufferIndex], command_list_end, &audioManager.audioReplyMsgQ, OS_MESG_PTR(&info->reply_mesg_data)); // [port] OSMesg is a union on PC + if(sp34 == 0){ + return 0; + }else{ + core1_15B30_addAudioTaskData((Gfx **)audioManager.ACMDList[D_8027DCD0], (Gfx **)sp38, &audioManager.audioReplyMsgQ, &info->unk8); func_80250650(); - port_unlockAudio(); // [port] - sCmdBufferIndex ^= 1; - return true; + D_8027DCD0 ^= 1; + return 1; } } -void audioManager_handleDoneMsg(AudioInfo *info) { - static bool debug_var = true; - - if ((osAiGetLength() / 4) == 0 && (!debug_var)) { - debug_var = false; +void audioManager_handleDoneMsg(AudioInfo *info) +{ + static int D_8027584C = true; + if (osAiGetLength() >> 2 == 0 && D_8027584C == false) { + D_8027584C = false; } } -uintptr_t func_80240204(uintptr_t addr, s32 len, void *state) { // [port] pointer-width for 64-bit ALDMAproc - void *dest_vaddr; - uintptr_t dev_addr_low_bit; - uintptr_t dev_addr_end; - struct dma_state_data_s *phi_s0, *phi_v0, *sp30; - -#if VERSION == VERSION_PAL - phi_v0 = sDMAState.unk4; -#endif +#if VERSION == VERSION_USA_1_0 +uintptr_t func_80240204(uintptr_t addr, s32 len, void *state) +{ + void *sp44; + uintptr_t sp40; + Struct_1D00_3 *phi_s0; + Struct_1D00_3 *phi_v0; + uintptr_t new_var; + Struct_1D00_3 *sp30; + + phi_s0 = D_8027D5B0.unk4; sp30 = NULL; + while (phi_s0 != NULL ) { + new_var = (phi_s0->unk8 + 0x200); + if ((phi_s0->unk8 > addr)) break; -#if VERSION == VERSION_USA_1_0 - for (phi_s0 = sDMAState.unk4; phi_s0 != NULL; phi_s0 = (struct dma_state_data_s *) phi_s0->link.next) { -#elif VERSION == VERSION_PAL - for (phi_s0 = phi_v0; phi_s0 != NULL; phi_s0 = (struct dma_state_data_s *) phi_s0->link.next) { -#endif - dev_addr_end = phi_s0->unk8 + DMA_BLOCK_SIZE; + sp30 = phi_s0; + if ((addr + len) <= new_var) { + phi_s0->unkC = (uintptr_t) D_8027DCC8; + return osVirtualToPhysical((void*)(phi_s0->unk10 + (addr - phi_s0->unk8))); + } + phi_s0 = (Struct_1D00_3 *)phi_s0->unk0.next; - if (phi_s0->unk8 > addr) { - break; + } + phi_s0 = D_8027D5B0.unk8; + if (phi_s0 == NULL) { + func_80247F24(2, 0x7D1); + gcdebugText_pauseThread(); + return osVirtualToPhysical(D_8027D5B0.unk4); + } + D_8027D5B0.unk8 = (Struct_1D00_3 *)phi_s0->unk0.next; + alUnlink((ALLink *)phi_s0); + if (sp30 != NULL) { + alLink((ALLink *)phi_s0, (ALLink *)sp30); + } else { + phi_v0 = D_8027D5B0.unk4; + if (phi_v0 != NULL) { + D_8027D5B0.unk4 = phi_s0; + phi_s0->unk0.next = (ALLink *)phi_v0; + phi_s0->unk0.prev = NULL; + phi_v0->unk0.prev = (ALLink *)phi_s0; + } else { + D_8027D5B0.unk4 = phi_s0; + phi_s0->unk0.next = NULL; + phi_s0->unk0.prev = NULL; } + } + sp44 = (void*)phi_s0->unk10; + sp40 = addr & 1; + addr -= sp40; + phi_s0->unk8 = addr; + phi_s0->unkC = (uintptr_t) D_8027DCC8; + osPiStartDma((OSIoMesg *)&D_8027D100[D_8027DCCC++], 1, 0, addr, sp44, 0x200U, &D_8027D008); + return osVirtualToPhysical(sp44) + sp40; +} +#elif VERSION == VERSION_PAL +#ifndef NONMATCHING +uintptr_t func_80240204(uintptr_t addr, s32 len, void *state); +#pragma GLOBAL_ASM("asm/nonmatchings/core1/code_1D00/func_80240204.s") +#else +uintptr_t func_80240204(uintptr_t addr, s32 len, void *state){ + void *sp44; + uintptr_t sp40; + Struct_1D00_3 *phi_s0; + Struct_1D00_3 *phi_v0; + uintptr_t new_var; + Struct_1D00_3 *sp30; + + phi_v0 = D_8027D5B0.unk4; + sp30 = NULL; + for(phi_s0 = phi_v0; phi_s0 != NULL; phi_s0 = (Struct_1D00_3 *)phi_s0->unk0.next) { + sp40 = (phi_s0->unk8 + 0x270); + if ((phi_s0->unk8 > addr)) break; sp30 = phi_s0; - - if ((addr + len) <= dev_addr_end) { - phi_s0->unkC = sAudioInfoID; -#if VERSION == VERSION_USA_1_0 - return osVirtualToPhysical((u8 *) phi_s0->heap + (addr - phi_s0->unk8)); -#elif VERSION == VERSION_PAL - dev_addr_low_bit = (s32) (u8 *) phi_s0->heap + (addr - phi_s0->unk8); - return osVirtualToPhysical((void *) dev_addr_low_bit); -#endif + if ((addr + len) <= sp40) { + phi_s0->unkC = (uintptr_t) D_8027DCC8; + return osVirtualToPhysical((void*)(phi_s0->unk10 + (addr - phi_s0->unk8))); } } - - phi_s0 = sDMAState.unk8; + phi_s0 = D_8027D5B0.unk8; if (phi_s0 == NULL) { -#if VERSION == VERSION_USA_1_0 - gcdebugText_showLargeValue(2, 2001); - gcdebugText_pauseThread(); - return osVirtualToPhysical(sDMAState.unk4); -#elif VERSION == VERSION_PAL return osVirtualToPhysical(phi_v0); -#endif } - - sDMAState.unk8 = (struct dma_state_data_s *) phi_s0->link.next; - alUnlink((ALLink *) phi_s0); - + D_8027D5B0.unk8 = (Struct_1D00_3 *)phi_s0->unk0.next; + alUnlink((ALLink *)phi_s0); if (sp30 != NULL) { - alLink((ALLink *) phi_s0, (ALLink *) sp30); + alLink((ALLink *)phi_s0, (ALLink *)sp30); } else { - phi_v0 = sDMAState.unk4; + phi_v0 = D_8027D5B0.unk4; if (phi_v0 != NULL) { - sDMAState.unk4 = phi_s0; - phi_s0->link.next = (ALLink *) phi_v0; - phi_s0->link.prev = NULL; - phi_v0->link.prev = (ALLink *) phi_s0; + D_8027D5B0.unk4 = phi_s0; + phi_s0->unk0.next = (ALLink *)phi_v0; + phi_s0->unk0.prev = NULL; + phi_v0->unk0.prev = (ALLink *)phi_s0; } else { - sDMAState.unk4 = phi_s0; - phi_s0->link.next = NULL; - phi_s0->link.prev = NULL; + D_8027D5B0.unk4 = phi_s0; + phi_s0->unk0.next = NULL; + phi_s0->unk0.prev = NULL; } } - dest_vaddr = (void *) phi_s0->heap; - dev_addr_low_bit = addr & 1; - addr -= dev_addr_low_bit; + new_var = addr & 1; + addr = addr - new_var; phi_s0->unk8 = addr; - phi_s0->unkC = (uintptr_t) sAudioInfoID; - osPiStartDma((OSIoMesg *)&sDMAMesgBlocks[sNumDMATransfers++], OS_MESG_PRI_HIGH, OS_READ, addr, dest_vaddr, DMA_BLOCK_SIZE, &audioDMANotifyMsgQ); - return osVirtualToPhysical(dest_vaddr) + dev_addr_low_bit; + phi_s0->unkC = (uintptr_t) D_8027DCC8; + sp44 = (void*)phi_s0->unk10; + osPiStartDma((OSIoMesg *)&D_8027D100[D_8027DCCC++], 1, 0, phi_s0->unk8, (void*)phi_s0->unk10, 0x270U, &D_8027D008); + return osVirtualToPhysical(sp44) + new_var; } +#endif +#endif -ALDMAproc audioManager_DMAInitProc(void *state) { - if (!sDMAState.initialized) { - sDMAState.unk4 = NULL; - sDMAState.unk8 = sDMAStateData; - sDMAState.initialized = true; +void *func_802403B8(void *state) { + if (D_8027D5B0.unk0 == 0) { + D_8027D5B0.unk4 = NULL; + D_8027D5B0.unk8 = &D_8027D5C0[0]; + D_8027D5B0.unk0 = 1; } - *(void **)state = (void *) &sDMAState; - return func_80240204; + *(void **)state = &D_8027D5B0; + return &func_80240204; } -void audioManager_func_802403F0(void) { - u32 i; - OSMesg temp_mesg; - struct dma_state_data_s *phi_s1; - struct dma_state_data_s *phi_s0_2; +void func_802403F0(void) { + u32 phi_s0; + OSMesg sp40; + Struct_1D00_3 *phi_s1; + Struct_1D00_3 *phi_s0_2; + + sp40.ptr = NULL; + for(phi_s0 = 0; phi_s0 < D_8027DCCC; phi_s0++){ - temp_mesg.ptr = NULL; - for (i = 0; i < sNumDMATransfers; i++) { #if VERSION == VERSION_USA_1_0 - if (osRecvMesg(&audioDMANotifyMsgQ, &temp_mesg, OS_MESG_NOBLOCK) == -1) { + if (osRecvMesg(&D_8027D008, &sp40, 0) == -1) { #if 0 // [port] DMA is synchronous on PC (memcpy), no completion messages to drain - gcdebugText_showLargeValue(2, 2005); - func_80247F9C(sNumDMATransfers); - func_80247F9C(i); + func_80247F24(2, 0x7D5); + func_80247F9C(D_8027DCCC); + func_80247F9C(phi_s0); gcdebugText_pauseThread(); #else break; #endif } #else - osRecvMesg(&audioDMANotifyMsgQ, &temp_mesg, OS_MESG_NOBLOCK); + osRecvMesg(&D_8027D008, &sp40, 0); #endif } - - phi_s0_2 = sDMAState.unk4; - - while (phi_s0_2 != NULL) { - phi_s1 = (struct dma_state_data_s *) phi_s0_2->link.next; - if (phi_s0_2->unkC + 1 < sAudioInfoID) { - if (phi_s0_2 == sDMAState.unk4) { - sDMAState.unk4 = (struct dma_state_data_s *)phi_s0_2->link.next; + phi_s0_2 = D_8027D5B0.unk4; + while(phi_s0_2 != NULL){ + phi_s1 = (Struct_1D00_3 *)phi_s0_2->unk0.next; + if (phi_s0_2->unkC + 1 < D_8027DCC8) { + if (phi_s0_2 == D_8027D5B0.unk4) { + D_8027D5B0.unk4 = (Struct_1D00_3 *)phi_s0_2->unk0.next; } - alUnlink(&phi_s0_2->link); - if (sDMAState.unk8 != NULL) { - alLink(&phi_s0_2->link, &sDMAState.unk8->link); + alUnlink((ALLink *)phi_s0_2); + if (D_8027D5B0.unk8 != NULL) { + alLink(&phi_s0_2->unk0, &D_8027D5B0.unk8->unk0); } else { - sDMAState.unk8 = phi_s0_2; - phi_s0_2->link.next = NULL; - phi_s0_2->link.prev = NULL; + D_8027D5B0.unk8 = phi_s0_2; + phi_s0_2->unk0.next = NULL; + phi_s0_2->unk0.prev = NULL; } } phi_s0_2 = phi_s1; } - - sNumDMATransfers = 0; - sAudioInfoID++; + D_8027DCCC = 0; + D_8027DCC8 += 1; } #if VERSION == VERSION_PAL -OSThread *audioManager_getThread_PAL(void) { +void *audioManager_getThread_PAL(void){ return &audioManager.thread; } #endif -void audioManager_stopThread(void) { - if (sAudioManagerThreadStarted) { - sAudioManagerThreadStarted = false; +void audioManager_stopThread(void){ + if(D_80275774){ + D_80275774 = 0; osStopThread(&audioManager.thread); } } -void audioManager_startThread(void) { - if (!sAudioManagerThreadStarted) { - sAudioManagerThreadStarted = true; - osStartThread(&audioManager.thread); +void audioManager_startThread(void){ + if(D_80275774 == 0){ + D_80275774 = 1; + port_audioStartThread(); } } -OSMesgQueue *audioManager_getReplyMesgQueue(void) { - return &audioManager.audioReplyMsgQ; -} - -OSThread *audioManager_getThread(void) { +OSThread * audioManager_getThread(void){ return &audioManager.thread; } -ALHeap *audioManager_getALHeapInfo(void) { - return &sALHeapInfo; +ALHeap * func_802405B8(void){ + return &D_8027CFF0; } -OSMesgQueue *audioManager_getDMANotifyMesgQueue(void) { - return &audioDMANotifyMsgQ; +OSMesgQueue * func_802405C4(void){ + return &D_8027D008; } -OSIoMesg *audioManager_getExtraDMAMesg(void) { - return &sExtraDMAMesg; +OSIoMesg * func_802405D0(void){ + return &D_8027D0E8; } -OSMesgQueue *audioManager_getFrameMesgQueue(void) { +OSMesgQueue * audioManager_getFrameMesgQueue(void){ return &audioManager.audioFrameMsgQ; } diff --git a/src/core1/debugtext.c b/src/core1/debugtext.c index 36a329bc1..5babb3b1c 100644 --- a/src/core1/debugtext.c +++ b/src/core1/debugtext.c @@ -253,7 +253,7 @@ void func_80247D80(s32 arg0, s32 arg1, s32 arg2) { } } -void gcdebugText_showLargeValue(s32 arg0, s32 arg1) { +void func_80247F24(s32 arg0, s32 arg1) { D_80275BD0 = 0; D_80275BCC = arg0; D_80275BBC = 0xE; diff --git a/src/core1/defragmanager.c b/src/core1/defragmanager.c index 3aa61c63c..85585d207 100644 --- a/src/core1/defragmanager.c +++ b/src/core1/defragmanager.c @@ -28,13 +28,13 @@ void defragManager_free(void){ osDestroyThread(&sDefragThread); } -void defragManager_resume(void){ +void defragManager_80240874(void){ if(func_8023E000() == 3){ osSendMesgPtr(&sDefragThreadResumeSyncQueue, NULL, OS_MESG_BLOCK); } } -void defragManager_pause(void){ +void defragManager_802408B0(void){ if(func_8023E000() == 3){ osSendMesgPtr(&sDefragThreadPauseSyncQueue, NULL, OS_MESG_BLOCK); } diff --git a/src/core1/depthbuffer.c b/src/core1/depthbuffer.c index 2fc2381a5..dc2db7807 100644 --- a/src/core1/depthbuffer.c +++ b/src/core1/depthbuffer.c @@ -7,69 +7,67 @@ #include struct { - u16 *data; - bool unk4; + void *data; + int unk4; } sDepthBuffer; -void depthbuffer_clear(Gfx **gfx) { - depthbuffer_clearRegion(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, gFramebuffers[getActiveFramebuffer()]); +void func_80253190(Gfx **gfx) { + func_80253208(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, gFramebuffers[getActiveFramebuffer()]); } -void depthbuffer_clearRegion(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer) { - if ((sDepthBuffer.data != NULL) && ((getGameMode() != GAME_MODE_4_PAUSED) || gsworld_getEnableDraw())) { +void func_80253208(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, void *color_buffer){ + if( sDepthBuffer.data != NULL && (getGameMode() != GAME_MODE_4_PAUSED || gsworld_getEnableDraw())){ + //draw z_buffer gDPPipeSync((*gfx)++); gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(sDepthBuffer.data)); gDPSetCycleType((*gfx)++, G_CYC_FILL); gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2); - gDPSetFillColor((*gfx)++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16) | GPACK_ZDZ(G_MAXFBZ, 0)); + gDPSetFillColor((*gfx)++, 0xFFFCFFFC); gDPScisFillRectangle((*gfx)++, x, y, x + w - 1, y + h - 1); - + + //draw color_buffer gDPPipeSync((*gfx)++); gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(color_buffer)); } } -bool depthbuffer_getUnk4(void) { +int func_80253400(void){ return sDepthBuffer.unk4; } -bool depthbuffer_isDataPtrSet(void) { +bool depthBuffer_isPointerSet(void) { return sDepthBuffer.data != NULL; } -void depthbuffer_stub(void) {} +void depthBuffer_stub(void) {} -void depthbuffer_enable(bool enable) { +void func_80253428(int arg0) { u16 *var_v0; - - if (enable) { - sDepthBuffer.data = (u16 *) D_8000E800; - - var_v0 = sDepthBuffer.data; - while (((uintptr_t) sDepthBuffer.data) % 64) { // [port] pointer-width - sDepthBuffer.data = var_v0 + 1; - var_v0 = sDepthBuffer.data; + int new_var; + if (arg0) { + var_v0 = (sDepthBuffer.data = &D_8000E800); + while (((uintptr_t) sDepthBuffer.data) % 0x40) { + var_v0 = (sDepthBuffer.data = var_v0 + 1); } - do { } while ((D_8000E800 && 1) * 0); //remove this - } else { + (void)&D_8000E800; // decomp match + }else{ sDepthBuffer.data = NULL; } - - sDepthBuffer.unk4 = FALSE; + sDepthBuffer.unk4 = false; } -void depthbuffer_setUnk4(bool value) { - sDepthBuffer.unk4 = sDepthBuffer.data && value; +void func_802534A8(int arg0) { + sDepthBuffer.unk4 = (sDepthBuffer.data != NULL && arg0); } -void depthbuffer_set(Gfx **gfx) { +void zBuffer_set(Gfx **gfx) { if (sDepthBuffer.data && getGameMode() != GAME_MODE_4_PAUSED) { gDPPipeSync((*gfx)++); gDPSetDepthImage((*gfx)++, sDepthBuffer.data); } } -void *depthbuffer_getDataPtr(void) { +void *zBuffer_get(void) { return sDepthBuffer.data; } diff --git a/src/core1/display_list.c b/src/core1/display_list.c index 49d18e32e..4305dba31 100644 --- a/src/core1/display_list.c +++ b/src/core1/display_list.c @@ -2,7 +2,6 @@ #include "core1/core1.h" #include #include "functions.h" -#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "port/Engine.h" #include @@ -21,7 +20,7 @@ static s32 sStackSelector; #define MTX_STACK_COUNT 2100 #define VTX_STACK_COUNT 1290 -bool sUseTexturePointFilter; +s32 gTextureFilterPoint; struct ucode_task_data_s sUcodeTaskData[20]; s32 sCurrentUcodeTaskDataID; OSMesgQueue sTaskDataListLockMesgQueue; @@ -30,7 +29,7 @@ u16 gScissorBoxLeft; u16 gScissorBoxRight; u16 gScissorBoxTop; u16 gScissorBoxBottom; -Gfx *D_80283214; // never used +Gfx *D_80283214; void core1_15B30_requestLockForTaskDataID(void) { osRecvMesg(&sTaskDataListLockMesgQueue, NULL, OS_MESG_BLOCK); @@ -40,7 +39,7 @@ void core1_15B30_requestReleaseForTaskDataID(void) { osSendMesgPtr(&sTaskDataListLockMesgQueue, NULL, OS_MESG_BLOCK); } -void core1_15B30_addAudioTaskData(Acmd *arg0, Acmd *arg1, OSMesgQueue *arg2, OSMesg arg3) { +void core1_15B30_addAudioTaskData(Gfx **arg0, Gfx **arg1, void *arg2, void *arg3) { struct ucode_task_data_s *task_data; core1_15B30_requestLockForTaskDataID(); @@ -50,53 +49,60 @@ void core1_15B30_addAudioTaskData(Acmd *arg0, Acmd *arg1, OSMesgQueue *arg2, OSM task_data->task_type = UCODE_TASK_TYPE_AUDIO; task_data->data_ptr = arg0; task_data->data_ptr_end = arg1; - task_data->audio_mesg_queue = arg2; - task_data->audio_mesg = arg3; + task_data->unk10 = arg2; + task_data->unk14 = (s32)(intptr_t)arg3; thread5_sendTaskToQueue(OS_MESG_PTR(task_data)); } -void setupFramebuffer(Gfx **gfx, void *color_buffer) { - D_80283214 = *gfx; - gSPSegment((*gfx)++, 0x00, 0x00000000); - gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2); - gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); - gDPPipeSync((*gfx)++); - gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE); - gDPSetAlphaCompare((*gfx)++, G_AC_NONE); - gDPSetColorDither((*gfx)++, G_CD_MAGICSQ); - gDPSetScissor((*gfx)++, G_SC_NON_INTERLACE, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom); - depthbuffer_clearRegion(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, color_buffer); - gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(color_buffer)); - gDPSetCycleType((*gfx)++, G_CYC_1CYCLE); - gDPSetTextureConvert((*gfx)++, G_TC_FILT); - gDPSetTextureDetail((*gfx)++, G_TD_CLAMP); - if (sUseTexturePointFilter) { - gDPSetTextureFilter((*gfx)++, G_TF_POINT); + +void func_80253640(Gfx ** gdl, void *arg1){ + D_80283214 = *gdl; + gSPSegment((*gdl)++, 0x00, 0x00000000); + gDPSetRenderMode((*gdl)++, G_RM_NOOP, G_RM_NOOP2); + gSPClearGeometryMode((*gdl)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); + gDPPipeSync((*gdl)++); + gDPPipelineMode((*gdl)++, G_PM_NPRIMITIVE); + gDPSetAlphaCompare((*gdl)++, G_AC_NONE); + gDPSetColorDither((*gdl)++, G_CD_MAGICSQ); + gDPSetScissor((*gdl)++, G_SC_NON_INTERLACE, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom); + func_80253208(gdl, 0, 0, gFramebufferWidth, gFramebufferHeight, arg1); + gDPSetColorImage((*gdl)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_K0_TO_PHYSICAL(arg1)); + gDPSetCycleType((*gdl)++, G_CYC_1CYCLE); + gDPSetTextureConvert((*gdl)++, G_TC_FILT); + gDPSetTextureDetail((*gdl)++, G_TD_CLAMP); + if(gTextureFilterPoint){ + gDPSetTextureFilter((*gdl)++, G_TF_POINT); }else{ - gDPSetTextureFilter((*gfx)++, G_TF_BILERP); + gDPSetTextureFilter((*gdl)++, G_TF_BILERP); } - gDPSetTextureLOD((*gfx)++, G_TL_TILE); - gDPSetTextureLUT((*gfx)++, G_TT_NONE); - gDPSetTexturePersp((*gfx)++, G_TP_PERSP); - depthbuffer_set(gfx); + gDPSetTextureLOD((*gdl)++, G_TL_TILE); + gDPSetTextureLUT((*gdl)++, G_TT_NONE); + gDPSetTexturePersp((*gdl)++, G_TP_PERSP); + zBuffer_set(gdl); } -void setupFramebufferForGamemode(Gfx **gdl, s32 framebuffer_idx) { +void scissorBox_SetForGameMode(Gfx **gdl, s32 framebuffer_idx) { if(getGameMode() == GAME_MODE_8_BOTTLES_BONUS || getGameMode() == GAME_MODE_A_SNS_PICTURE) { - EventSystem_Should(VB_PICTUREBOX_TARGET_FB, true, gdl); - picturebox_setScissorBox(); - setupFramebuffer(gdl, picturebox_getColorBuffer()); + // [port] Redirect rendering to GPU-side aux FB via gsSPSetFB. + // On N64, gDPSetColorImage pointed to D_80382450 (CPU buffer). + // gsSPResetFB is emitted in func_802E39D0 after the scene draw. + s32 auxFb = port_getAuxGpuFbId(); + if (auxFb >= 0) { + gsSPSetFB((*gdl)++, auxFb); + } + scissorBox_setSmall(); + func_80253640(gdl, func_8030C704()); } else{ scissorBox_setDefault(); - setupFramebuffer(gdl, gFramebuffers[framebuffer_idx]); + func_80253640(gdl, gFramebuffers[framebuffer_idx]); } } -void setupScissorBoxAndFramebuffer(Gfx **gfx, void *color_buffer) { +void setupScissorBoxAndFramebuffer(Gfx **gfx, uintptr_t framebuffer_address){ gSPSegment((*gfx)++, 0x00, 0x00000000); - gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_PHYSICAL_TO_K0(color_buffer)); + gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_PHYSICAL_TO_K0(framebuffer_address)); gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); gSPTexture((*gfx)++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); gSPSetGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH); @@ -113,7 +119,7 @@ void setupScissorBoxAndFramebuffer(Gfx **gfx, void *color_buffer) { void setupDefaultScissorBoxAndFramebuffer(Gfx **gfx, s32 framebuffer_idx){ scissorBox_setDefault(); - setupScissorBoxAndFramebuffer(gfx, gFramebuffers[framebuffer_idx]); + setupScissorBoxAndFramebuffer(gfx, (uintptr_t)gFramebuffers[framebuffer_idx]); } void core1_15B30_finishDList_renderThread(Gfx **gfx) { @@ -191,13 +197,13 @@ void core1_15B30_init(void) { scissorBox_setDefault(); } -void drawRectangle2D(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, s32 r, s32 g, s32 b) { +void drawRectangle2D(Gfx **gfx, s32 x, s32 y, s32 w, s32 h, s32 r, s32 g, s32 b){ gDPPipeSync((*gfx)++); gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE); gDPSetCycleType((*gfx)++, G_CYC_FILL); gDPSetFillColor((*gfx)++, GPACK_RGBA5551(r, g, b, 1) << 16 | GPACK_RGBA5551(r, g, b, 1)); gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2); - gDPScisFillRectangle((*gfx)++, x, y, x + w - 1, y + h - 1); + gDPScisFillRectangle((*gfx)++, x, y, x + w -1, y + h -1); } void graphicsCache_release(void) { @@ -212,16 +218,8 @@ void graphicsCache_release(void) { } } -void graphicsCache_init(void) { - if (sGfxStack[0] == NULL) { -#if 0 - sGfxStack[0] = (Gfx *)malloc(29600); // 3700 dlist commands - sGfxStack[1] = (Gfx *)malloc(29600); - sMtxStack[0] = (Mtx *)malloc(44800); // 700 matrices - sMtxStack[1] = (Mtx *)malloc(44800); - sVtxStack[0] = (Vtx *)malloc(6880); // 430 vertices - sVtxStack[1] = (Vtx *)malloc(6880); -#endif +void graphicsCache_init(void){ + if(sGfxStack[0] == NULL){ sGfxStack[0] = (Gfx *)GameEngine_Malloc(GFX_STACK_COUNT * sizeof(Gfx)); sGfxStack[1] = (Gfx *)GameEngine_Malloc(GFX_STACK_COUNT * sizeof(Gfx)); sMtxStack[0] = (Mtx *)GameEngine_Malloc(MTX_STACK_COUNT * sizeof(Mtx)); @@ -230,13 +228,15 @@ void graphicsCache_init(void) { sVtxStack[1] = (Vtx *)GameEngine_Malloc(VTX_STACK_COUNT * sizeof(Vtx)); dummy_func_80254464(); } - - sStackSelector = 0; - sUseTexturePointFilter = FALSE; + gTextureFilterPoint = 0; } -// [port] Verify the frame's dlist emission fit within the static stack capacities. +// [port] Verify the frame's dlist emission fit within the static stack +// capacities. If it didn't, we've already written past the buffer and +// corrupted the heap, but logging it loudly (instead of silently deferring +// to a CRT debug-heap break at the next malloc/free) makes the root cause +// obvious. Mirrors Shipwright's THGA_IsCrash() canary pattern. void graphicsCache_checkFrame(Gfx *gfxStart, Gfx *gfxEnd, Mtx *mtxStart, Mtx *mtxEnd, Vtx *vtxStart, Vtx *vtxEnd) { s32 gfxUsed = (s32)(gfxEnd - gfxStart); s32 mtxUsed = (s32)(mtxEnd - mtxStart); @@ -279,11 +279,12 @@ void core1_15B30_addTask7TaskData(s32 framebuffer_id) { thread5_sendTaskToQueue(OS_MESG_PTR(task_data)); } -void core1_15B30_toggleTexturePointFilter(void) { - sUseTexturePointFilter = !sUseTexturePointFilter; +void toggleTextureFilterPoint(void){ + u32 ret_val = gTextureFilterPoint; + gTextureFilterPoint = ret_val < 1; } -void graphicscache_swapAndGetStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void getGraphicsStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx){ sStackSelector = (1 - sStackSelector); *gfx = sGfxStack[sStackSelector]; *mtx = sMtxStack[sStackSelector]; diff --git a/src/core1/graphics_thread.c b/src/core1/graphics_thread.c index 63e6ba620..3c6de06b4 100644 --- a/src/core1/graphics_thread.c +++ b/src/core1/graphics_thread.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/code_8C50.c +// BanjoDecomp: thread5 (osCreateThread OSId 5) // Needs to be included here because interrupt.h contains: // typedef u32 OSIntMask; and u32 isn't defined before that. @@ -7,9 +7,6 @@ #include #include "core1/core1.h" #include "functions.h" -#include "port/DevTools/ThreadWatchdog.h" -#include "port/OS/OS.h" -#include "port/Patches/Patches.h" #include "libultraship/libultra/rcp.h" #include "libultraship/libultra/sptask.h" #include "libultraship/libultra/types.h" @@ -93,24 +90,11 @@ static OSTimer sControllerTimer; static bool sEnableControllerTimer; void thread5_startNextAudioTask(void); -void osSpTaskLoad(OSTask* task); -void osSpTaskStartGo(OSTask* task); /* .code */ - -// [port] The queues are static; Game.cpp opts them into blocking before -// thread5_create runs. -OSMesgQueue* thread5_getTaskQueue(void) { - return &sThread5MesgQueue; -} -OSMesgQueue* thread5_getSyncQueue(void) { - return &sThread5SyncMesgQueue; -} - void thread5_sendTaskToQueue(OSMesg arg0) { static bool clear_freeze = true; - port_thread5_onSubmit(arg0.ptr); // [port] carry the interpolation pair with the task osSendMesg(&sThread5MesgQueue, arg0, 1); // Lighthouse [port] Adjustment here to account for our OSMesg union definition if (arg0.data32 == THREAD5_MESSAGE_EVENT_SYNC) { @@ -141,29 +125,28 @@ void thread5_insertGfxTaskData(OSMesg arg0) { } void thread5_startAudioTask(struct ucode_task_data_s *task_data) { -#if 0 // [port] microcode boot pointers, there is no RSP to load them into +#if 0 ucode_getPtrAndSize(&sAudTask.t.ucode_boot, &sAudTask.t.ucode_boot_size); sAudTask.t.ucode = n_aspMainTextStart; sAudTask.t.ucode_data = n_aspMainDataStart; -#endif sAudTask.t.data_ptr = (void*) task_data->data_ptr; - sAudTask.t.data_size = ((u8 *)task_data->data_ptr_end - (u8 *)task_data->data_ptr) >> 3 << 3; + sAudTask.t.data_size = (task_data->data_ptr_end - task_data->data_ptr) >> 3 << 3; osWritebackDCache(sAudTask.t.data_ptr , sAudTask.t.data_size); osWritebackDCache(&sAudTask, sizeof(OSTask)); sActiveAudioTaskDataPtr = task_data; osSpTaskLoad(&sAudTask); osSpTaskStartGo(&sAudTask); sUnkFlag1 = UNKFLAG1_AUDIO_TASK; +#endif } void thread5_startF3DEXTask(struct ucode_task_data_s *task_data) { -#if 0 // [port] microcode boot pointers, there is no RSP to load them into +#if 0 ucode_getPtrAndSize(&sGfxTask.t.ucode_boot, &sGfxTask.t.ucode_boot_size); sGfxTask.t.ucode = gSPF3DEX_fifoTextStart; sGfxTask.t.ucode_data = gSPF3DEX_fifoDataStart; -#endif sGfxTask.t.data_ptr = (void*) task_data->data_ptr; - sGfxTask.t.data_size = ((u8 *)task_data->data_ptr_end - (u8 *)task_data->data_ptr) >> 3 << 3; + sGfxTask.t.data_size = (task_data->data_ptr_end - task_data->data_ptr) >> 3 << 3; osWritebackDCache(sGfxTask.t.data_ptr , sGfxTask.t.data_size); osWritebackDCache(&sGfxTask, sizeof(OSTask)); osSpTaskLoad(&sGfxTask); @@ -174,16 +157,16 @@ void thread5_startF3DEXTask(struct ucode_task_data_s *task_data) { sUnkFlag2_Saved = sUnkFlag2; sUnkCounter3 = 30; } +#endif } void thread5_startL3DEXTask(struct ucode_task_data_s *task_data) { -#if 0 // [port] microcode boot pointers, there is no RSP to load them into +#if 0 ucode_getPtrAndSize(&sGfxTask.t.ucode_boot, &sGfxTask.t.ucode_boot_size); sGfxTask.t.ucode = gSPL3DEX_fifoTextStart; sGfxTask.t.ucode_data = gSPL3DEX_fifoDataStart; -#endif sGfxTask.t.data_ptr = (void*) task_data->data_ptr; - sGfxTask.t.data_size = ((u8 *)task_data->data_ptr_end - (u8 *)task_data->data_ptr) >> 3 << 3; + sGfxTask.t.data_size = (task_data->data_ptr_end - task_data->data_ptr) >> 3 << 3; osWritebackDCache(sGfxTask.t.data_ptr , sGfxTask.t.data_size); osWritebackDCache(&sGfxTask, sizeof(OSTask)); osSpTaskLoad(&sGfxTask); @@ -194,9 +177,11 @@ void thread5_startL3DEXTask(struct ucode_task_data_s *task_data) { sUnkFlag2_Saved = sUnkFlag2; sUnkCounter3 = 30; } +#endif } void thread5_startGfxTask(struct ucode_task_data_s *task_data) { +#if 0 switch (task_data->task_type) { case 1: thread5_startF3DEXTask(task_data); @@ -206,15 +191,11 @@ void thread5_startGfxTask(struct ucode_task_data_s *task_data) { thread5_startL3DEXTask(task_data); break; } +#endif } void thread5_handleAudioTaskMesg(OSMesg msg) { thread5_insertAudioTaskData(msg); - if ((sUnkFlag1 == UNKFLAG1_NO_TASK) && (sActiveAudioTaskDataID != sSelectedAudioTaskDataID)) { - struct ucode_task_data_s *ptr = sAudioTaskDataList[sActiveAudioTaskDataID]; - sActiveAudioTaskDataID = (sActiveAudioTaskDataID + 1) % 20; - thread5_startAudioTask(ptr); - } } void thread5_handleF3DEXTaskMesg(OSMesg msg) { @@ -234,6 +215,7 @@ void thread5_handleL3DEXTaskMesg(OSMesg msg) { } void thread5_handleSyncEvent(void) { +#if 0 if ((sUnkFlag1 == UNKFLAG1_NO_TASK) && (sUnkFlag2_Saved == 2) && (sActiveGfxTaskDataID == sSelectedGfxTaskDataID) @@ -244,11 +226,13 @@ void thread5_handleSyncEvent(void) { else { sSyncCounter++; } +#endif } extern u64 osClockRate; void thread5_handleDPEvent(void) { +#if 0 if ((sUnkFlag2 << 1) < 0) { osDpSetStatus(DPC_SET_FREEZE); sCurrentFramebuffer = osViGetCurrentFramebuffer(); @@ -266,9 +250,12 @@ void thread5_handleDPEvent(void) { sSyncCounter--; } } +#endif } void thread5_handleVIRetraceEvent(void) { +#if 0 + static s32 audiotimer_trigger = 0; s32 sp2C = (sSyncCounter != 0) && (sActiveGfxTaskDataID == sSelectedGfxTaskDataID) && (sUnkFlag2 == 2) && (sUnkFlag1 == UNKFLAG1_NO_TASK); volatile s32 sp30; @@ -278,7 +265,7 @@ void thread5_handleVIRetraceEvent(void) { osDpSetStatus(DPC_CLR_FREEZE); sUnkFlag2_Saved = sUnkFlag2; - // dummy_func_8025AFB8(); + dummy_func_8025AFB8(); if (sUnkFlag2_Saved & 1) { sUnkCounter3 = 30; @@ -308,23 +295,25 @@ void thread5_handleVIRetraceEvent(void) { } } sTask7Handled = false; - static s32 audiotimer_trigger = 0; audiotimer_trigger++; if (!(audiotimer_trigger & 1)) { osStopTimer(&sAudioTimer); osSetTimer(&sAudioTimer, 280000, 0, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_AUDIO_TIMER)); } - if (sEnableControllerTimer && OS_SiPumpLive()) { + + if (sEnableControllerTimer) { osStopTimer(&sControllerTimer); #if VERSION == VERSION_USA_1_0 osSetTimer(&sControllerTimer, ((osClockRate / 60)* 2) / 3, 0, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_CONT_TIMER)); #elif VERSION == VERSION_PAL - osSetTimer(&sControllerTimer, ((osClockRate / 60.0)* 2) / 3, 0, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_CONT_TIMER)); + osSetTimer(&sControllerTimer, ((osClockRate / 60.0)* 2) / 3, 0, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_CONT_TIMER); #endif } +#endif } void thread5_handleSPEvent(void) { +#if 0 struct ucode_task_data_s *active_audio_task; s32 temp_v1; @@ -339,10 +328,7 @@ void thread5_handleSPEvent(void) { } if (sUnkFlag1 == UNKFLAG1_AUDIO_TASK) { - // [port] The raw decomp sends through the first two struct fields; - // with the struct typed, these are the reply queue and message set by - // core1_15B30_addAudioTaskData. - osSendMesg(sActiveAudioTaskDataPtr->audio_mesg_queue, sActiveAudioTaskDataPtr->audio_mesg, 0); + osSendMesg(&sActiveAudioTaskDataPtr->task_type, sActiveAudioTaskDataPtr->unk4, 0); } if ((sUnkFlag1 == UNKFLAG1_AUDIO_TASK) && (sGfxTaskYielded != 0)) { @@ -364,6 +350,7 @@ void thread5_handleSPEvent(void) { osSendMesgPtr(&sThread5SyncMesgQueue, NULL, 0); sSyncCounter--; } +#endif } void thread5_handleTask7Mesg(OSMesg arg0) { @@ -371,11 +358,6 @@ void thread5_handleTask7Mesg(OSMesg arg0) { } void thread5_handleAudioTimerEvent(void) { - // [port] While the demo audio hold is up, skip the frame message so the - // engine does not consume sfx cues queued for the demo's first frame. - if (port_audioHeld() || port_audioStallHold()) { - return; - } osSendMesgPtr(audioManager_getFrameMesgQueue(), NULL, OS_MESG_NOBLOCK); thread5_startNextAudioTask(); } @@ -484,48 +466,40 @@ void thread5_checkAndExecutePreNMI(void) { //thread5 entry void thread5_entry(void *arg) { - // [port] Only adjustment: OSMesg is a union here, - // so event words read through .data32 and tasks through .ptr - OSMesg msg; - msg.ptr = NULL; +#if 0 + OSMesg msg = NULL; do { osRecvMesg(&sThread5MesgQueue, &msg, OS_MESG_BLOCK); - // [port] Shutdown released the queue rather than delivering anything, so msg - // holds nothing worth dispatching. Leave before the engine goes away. - if (OS_ThreadShouldExit()) { - return; - } - ThreadWatchdog_Beat(WATCHDOG_THREAD5); // [port] one beat per serviced message thread5_checkAndExecutePreNMI(); - if ((uintptr_t)msg.ptr < 100) { - if (msg.data32 == THREAD5_MESSAGE_EVENT_SYNC) { thread5_handleSyncEvent(); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_VI_RETRACE) { thread5_handleVIRetraceEvent(); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_DP) { thread5_handleDPEvent(); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_SP) { thread5_handleSPEvent(); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_AUDIO_TIMER) { thread5_handleAudioTimerEvent(); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_FAULT) { do{}while(1); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_PRENMI) { thread5_handlePreNMIEvent(); } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_DEBUG) { } - else if (msg.data32 == THREAD5_MESSAGE_EVENT_CONT_TIMER) { pfsManager_getStartReadData(); } - } - else { - if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_AUDIO) { thread5_handleAudioTaskMesg(msg); } - else if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_F3DEX) { thread5_handleF3DEXTaskMesg(msg); } - else if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_L3DEX) { thread5_handleL3DEXTaskMesg(msg); } - else if (((struct ucode_task_data_s *)msg.ptr)->task_type == UCODE_TASK_TYPE_FRAMEBUFFER_CHANGED) { thread5_handleTask7Mesg(msg); } + if ((s32)msg == THREAD5_MESSAGE_EVENT_SYNC) { thread5_handleSyncEvent(); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_VI_RETRACE) { thread5_handleVIRetraceEvent(); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_DP) { thread5_handleDPEvent(); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_SP) { thread5_handleSPEvent(); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_AUDIO_TIMER) { thread5_handleAudioTimerEvent(); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_FAULT) { do{}while(1); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_PRENMI) { thread5_handlePreNMIEvent(); } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_DEBUG) { } + else if ((u32)msg == THREAD5_MESSAGE_EVENT_CONT_TIMER) { pfsManager_getStartReadData(); } + else if ((u32)msg >= 100) { + if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_AUDIO) { thread5_handleAudioTaskMesg(msg); } + else if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_F3DEX) { thread5_handleF3DEXTaskMesg(msg); } + else if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_L3DEX) { thread5_handleL3DEXTaskMesg(msg); } + else if (((struct ucode_task_data_s *)msg)->task_type == UCODE_TASK_TYPE_FRAMEBUFFER_CHANGED) { thread5_handleTask7Mesg(msg); } } } while (1); +#endif } //thread5 create void thread5_create(void) { +#if 0 u8 *yield_data_ptr; - osCreateMesgQueue(&sThread5MesgQueue, sThread5MesgBuffer, 20); - osCreateMesgQueue(&sThread5SyncMesgQueue, sThread5SyncMesgBufer, 10); - osSetEventMesg(OS_EVENT_DP, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_DP)); - osSetEventMesg(OS_EVENT_SP, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_SP)); - osSetEventMesg(OS_EVENT_FAULT, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_FAULT)); - osSetEventMesg(OS_EVENT_PRENMI, &sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_PRENMI)); + osCreateMesgQueue(&sThread5MesgQueue, &sThread5MesgBuffer, 20); + osCreateMesgQueue(&sThread5SyncMesgQueue, &sThread5SyncMesgBufer, 10); + osSetEventMesg(OS_EVENT_DP, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_DP); + osSetEventMesg(OS_EVENT_SP, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_SP); + osSetEventMesg(OS_EVENT_FAULT, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_FAULT); + osSetEventMesg(OS_EVENT_PRENMI, &sThread5MesgQueue, THREAD5_MESSAGE_EVENT_PRENMI); viMgr_registerSignalMesg(&sThread5MesgQueue, OS_MESG_32(THREAD5_MESSAGE_EVENT_VI_RETRACE)); sSyncCounter = 0; sTask7Handled = 0; @@ -542,6 +516,7 @@ void thread5_create(void) { sGfxTask.t.yield_data_ptr = (u64 *) yield_data_ptr; osCreateThread(&sThread5, THREAD5_ID, thread5_entry, NULL, &sThread5Stack[2048], THREAD5_PRI); osStartThread(&sThread5); +#endif } void thread5_enableControllerTimer(void) { @@ -564,20 +539,3 @@ OSMesgQueue *__thread5_getMessageQueue(void) { OSThread *__thread5_getThreadObject(void) { return &sThread5; } - -// [port] Watchdog diagnostics: unsynchronized snapshot of the pipeline state. -void thread5_getWatchdogState(Thread5WatchdogState *out) { - out->unkFlag1 = sUnkFlag1; - out->unkFlag2 = sUnkFlag2; - out->unkFlag2Saved = sUnkFlag2_Saved; - out->syncCounter = sSyncCounter; - out->task7Handled = sTask7Handled; - out->gfxActiveId = sActiveGfxTaskDataID; - out->gfxSelectedId = sSelectedGfxTaskDataID; - out->audioActiveId = sActiveAudioTaskDataID; - out->audioSelectedId = sSelectedAudioTaskDataID; - out->taskQueueCount = sThread5MesgQueue.validCount; - out->taskQueueCap = sThread5MesgQueue.msgCount; - out->syncQueueCount = sThread5SyncMesgQueue.validCount; - out->syncQueueCap = sThread5SyncMesgQueue.msgCount; -} diff --git a/src/core1/init.c b/src/core1/init.c index e7073d9df..9686e2ad1 100644 --- a/src/core1/init.c +++ b/src/core1/init.c @@ -3,22 +3,23 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "port/ShipUtils.h" // gPortResetPending #include "version.h" #include "gc/gctransition.h" #define MAIN_THREAD_STACK_SIZE 0x17F0 +extern void audioManager_init(void); + #if VERSION == VERSION_PAL extern s32 D_80000300; #endif s32 D_80275610 = 0; s32 D_80275614 = 0; -s32 gGlobalTimer = 0; +u32 gGlobalTimer = 0; u32 sDebugVar_8027561C[] = { 0x9, 0x4, 0xA, 0x3, 0xB, 0x2, 0xC, 0x5, 0x0, 0x1, 0x6, 0xD, -1 }; // never used -s32 D_80275650 = VER_SELECT(0xAD019D3C, 0xA371A8F3, 0, 0); //SM_DATA_CRC2 -s32 D_80275654 = VER_SELECT(0xD381B72F, 0xD0709154, 0, 0); //MM_DATA_CRC2 +u32 D_80275650 = VER_SELECT(0xAD019D3C, 0xA371A8F3, 0, 0); //SM_DATA_CRC_1 +u32 D_80275654 = VER_SELECT(0xD381B72F, 0xD0709154, 0, 0); //SM_DATA_CRC_2 char sDebugVar_80275658[] = VER_SELECT("HjunkDire:218755", "HjunkDire:300875", "HjunkDire:", "HjunkDire:"); /* .bss */ @@ -70,7 +71,7 @@ void func_8023DA9C(s32 arg0){ ucode_stub1(); } -s32 globalTimer_getTimeMasked(s32 mask) { +u32 globalTimer_getTimeMasked(u32 mask){ return gGlobalTimer & mask; } @@ -117,7 +118,7 @@ void core1_init(void) { // [port] Irrelevant and replaced with system malloc // heap_init(); core1_15B30_init(); - // dummy_func_8025AFB0(); + dummy_func_8025AFB0(); // [port] Irrelevant and replaced with system malloc // allocUnusedBlock(); assetCache_init(); @@ -158,7 +159,7 @@ void mainLoop(void){ // [port] Don't need this #if 0 if(!mapSpecificFlags_validateCRC1()){ - eeprom_writeBlocks(0, 0, (void *) PHYS_TO_K0(0x00397AD0), EEPROM_MAXBLOCKS); + eeprom_writeBlocks(0, 0, 0x80397AD0, 0x40); } #endif @@ -171,7 +172,7 @@ void mainLoop(void){ func_80255ACC(); spawnQueue_func_802C3A18(); if(func_802E4424()) - game_draw(FALSE); + game_draw(0); spawnQueue_flush(); break; }//L8023DE34 @@ -192,7 +193,7 @@ void mainLoop(void){ //render weird CRC failure image for(y= 0x1e; y < gFramebufferHeight - 0x1e; y++){//L8023DEB4 for(x = 0x14; x < 0xeb; x++){ - tmp = ((globalTimer_getTime() << 3) + x * x + y * y); + tmp = ((8 * globalTimer_getTime()) + ((x*x) + (y*y))); r = _SHIFTL(x>>3, 11, 5); g = _SHIFTL(y>>3, 6, 5); @@ -209,12 +210,10 @@ void mainLoop(void){ }//L8023DF70 #endif - port_actorDespawn_beginDefer(); CALL_EVENT(GameFrameUpdate); - port_actorDespawn_endDefer(); } -void mainThread_entry(void *arg) { +void mainThread_entry(void *arg) { core1_init(); sns_write_payload_over_heap(); diff --git a/src/core1/bamotor.c b/src/core1/io/bamotor.c similarity index 78% rename from src/core1/bamotor.c rename to src/core1/io/bamotor.c index 84111a3a3..8d5a23acc 100644 --- a/src/core1/bamotor.c +++ b/src/core1/io/bamotor.c @@ -5,10 +5,10 @@ #include "variables.h" #include "version.h" -#include "port/DevTools/ThreadWatchdog.h" -#include "port/OS/OS.h" #include "port/Patches/Patches.h" +//#include + #define RUMBLE_THREAD_STACK_SIZE 0x200 void func_8024F35C(s32); @@ -75,10 +75,6 @@ void rumbleThread_entry(void *arg) { do{ osRecvMesg(&D_80282390, NULL, 1); - if (OS_ThreadShouldExit()) { // [port] cooperative shutdown - return; - } - ThreadWatchdog_Beat(WATCHDOG_RUMBLE); // [port] one beat per retrace signal D_802827E0++; if (!D_802823B0 && ((D_802827E0 % FRAMERATE) == 0)) { func_80250930(); @@ -113,12 +109,43 @@ void __baMotor_80250BA4(s32 arg0, s32 arg1, s32 arg2){ } void baMotor_80250C08(void) { + // [port] Rumble thread logic inlined — N64 thread/VBlank model replaced by per-frame update + static s32 sFrameCounter; + static s32 sRumbleState; + if (D_802823AC != 0) { + s32 prev_state; + D_80282424 = MIN(D_80282420, D_80282424 + time_getDelta()); + + prev_state = sRumbleState; + sFrameCounter++; + + if (D_80282424 != D_80282420) { + f32 temp_f2 = D_80282428 + ((D_8028242C - D_80282428) * D_80282424 / D_80282420); + s32 var_v0 = (s32)(((1.0 - temp_f2) * 8.0) + 1); + if (var_v0 < 2) { + sRumbleState = var_v0; + } else { + sRumbleState = (sFrameCounter % var_v0) == 0; + } + } else { + sRumbleState = 0; + } + + if (sRumbleState != prev_state) { + if (sRumbleState) { + __baMotor_startRumble(); + } else { + __baMotor_stopRumble(); + } + } } } void baMotor_init(void) { + // [port] Bypass N64 PFS probing and rumble thread — LUS handles motor directly. +#if 0 s32 pfs_status; func_8024F35C(4); @@ -132,20 +159,14 @@ void baMotor_init(void) { D_802823B0 = D_802823AC; if(D_802823AC){ osCreateMesgQueue(&D_80282390, &D_802823A8, 1); - // [port] The thread parks on that queue between retraces, so it has to - // block on it, and its entry needs allowlisting before osStartThread - // will really launch it. - OS_SetQueueBlocking(&D_80282390, 1); - OS_EnableThreadEntry((void*)rumbleThread_entry); osCreateThread(&sRumbleThread, 8, rumbleThread_entry, NULL, sRumbleThreadStack + RUMBLE_THREAD_STACK_SIZE, 25); osStartThread(&sRumbleThread); - viMgr_registerSignalMesg(&D_80282390, OS_MESG_32(0)); + viMgr_registerSignalMesg(&D_80282390, OS_MESG_32(NULL)); } -} - -// [port] Watchdog diagnostics -OSMesgQueue *baMotor_getRetraceQueue(void){ - return &D_80282390; +#endif + osMotorInit(NULL, &D_802823B8, 0); + D_802823AC = 1; + D_802823B0 = 1; } void __baMotor_80250D8C(void){} @@ -155,7 +176,9 @@ void baMotor_80250D94(f32 arg0, f32 arg1, f32 arg2){ if(arg2 != 0.0f && D_802823AC){ if(func_802E4A08() == 0){ if(!(0.1 < D_80282420 - D_80282424) || !(arg0 + arg1 < D_80282428 + D_8028242C)){ - f32 scale = port_getRumbleScale(); + // [port] Scale intensity by ImGui rumble setting. + // Original N64 values are ~50% of max (duty cycling a binary motor). + f32 scale = port_getRumbleScale() * 2.0f; D_80282420 = arg2; D_80282424 = 0.0f; D_80282428 = MIN(arg0 * scale, 1.0f); diff --git a/src/core1/pfsmanager.c b/src/core1/io/pfsmanager.c similarity index 93% rename from src/core1/pfsmanager.c rename to src/core1/io/pfsmanager.c index 8d87bdebb..0c56322bc 100644 --- a/src/core1/pfsmanager.c +++ b/src/core1/io/pfsmanager.c @@ -2,24 +2,33 @@ #include #include "core1/core1.h" #include "functions.h" -#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "core1/pfsmanager.h" #include "version.h" -#include "checksums.h" -#include "port/DevTools/ThreadWatchdog.h" -#include "port/OS/OS.h" #include "port/Patches/Patches.h" #define PFSMANAGER_THREAD_STACK_SIZE 0x200 +extern struct { + u8 pad0[4]; + s32 unk4; + u8 pad8[4]; + s32 unkC; +} D_80379B90; + extern s32 D_803727F4; extern s32 D_80276574; -s32 D_80275D30 = VER_SELECT(0xC3A68832, 0xED7BCDB7, 0, 0); // CCW_DATA_CRC2 -s32 D_80275D34 = VER_SELECT(0xDDC3A724, 0xF82DC7AC, 0, 0); // FIGHT_DATA_CRC2 +/* .data */ +#if VERSION == VERSION_USA_1_0 + s32 D_80275D30 = 0xC3A68832; //WHAT IS THIS? + s32 D_80275D34 = 0xDDC3A724; //WHAT IS THIS? +#elif VERSION == VERSION_PAL + s32 D_80275D30 = 0xED7BCDB7; //WHAT IS THIS? + s32 D_80275D34 = 0xF82DC7AC; //WHAT IS THIS? +#endif static s32 D_80275D38 = 0; @@ -56,7 +65,7 @@ f32 func_8024E420(s32 arg0, s32 arg1, s32 arg2) { // instead of 1.0), making it impossible to reach the 0.7 threshold used by // gameSelect.c and other input consumers. Bypassed. #if ANTI_TAMPER - if ((gChecksumsCore2.text_checksum2 != D_803727F4) || (gChecksumsCore2.data_checksum2 != D_80276574)) { + if ((D_80379B90.unk4 != D_803727F4) || (D_80379B90.unkC != D_80276574)) { phi_f2 = 0.00625f; } #endif @@ -167,9 +176,10 @@ void pfsManager_update(void) { osSetThreadPri(0, 0x29); - // [port] Re-read the latched transaction so the pad data is stable for the - // whole tick; the SI completes reads at its own cadence, and the shaping - // below rewrites this buffer in place. + // [port] On N64, pfsManager_getStartReadData() is called from the RSP/GFX thread + // (code_8C50.c:490) which is #if 0'd on PC. Without it, pfsManagerBusy is never set, + // pfsManager_readData() never fires, and osContGetReadData() never fills the pad data. + // Poll LUS input directly here each frame instead. osContGetReadData(pfsManagerContPadData); // [port] Control-scheme input shaping: right stick -> C-button conversion, @@ -296,22 +306,19 @@ void pfsManager_update(void) { } } - CALL_EVENT(OnControllerUpdate); osSetThreadPri(0, 0x14); } void pfsManager_readData(){ func_8024F35C(0); + if(!pfsManagerContStatus.err_no) + osContGetReadData(pfsManagerContPadData); } void pfsManager_entry(void *arg) { do { osRecvMesg(&pfsManagerContPollingMsqQ, 0, 1); - if (OS_ThreadShouldExit()) { // [port] cooperative shutdown - return; - } - ThreadWatchdog_Beat(WATCHDOG_PFSMANAGER); // [port] one beat per SI completion if(pfsManagerBusy == true){ pfsManager_readData(); } @@ -401,12 +408,6 @@ OSMesgQueue *pfsManager_getFrameMesgQ(void){ return &pfsManagerContPollingMsqQ; } -// [port] Watchdog diagnostics: the SI event-registration lock queue -// (func_8024F450 parks here), so blocked waits get a name. -OSMesgQueue *pfsManager_getSiLockQueue(void){ - return &D_802816E8; -} - void func_8024F35C(s32 arg0) { if(!arg0) func_8024F4AC(); @@ -414,7 +415,7 @@ void func_8024F35C(s32 arg0) { func_8024F450(); if(arg0 || D_802816E8.validCount == 1){ - pfsManagerBusy = arg0; + pfsManagerBusy = arg0; } } @@ -434,7 +435,6 @@ OSContPad *func_8024F3F4(void){ void func_8024F400(void) { D_80275D38 = true; osCreateMesgQueue(&D_802816E8, D_80281700, 5); - OS_SetQueueBlocking(&D_802816E8, 1); osSendMesgPtr(&D_802816E8, NULL, OS_MESG_NOBLOCK); } diff --git a/src/core1/math/longlong_arith.c b/src/core1/math/longlong_arith.c new file mode 100644 index 000000000..a3cff6547 --- /dev/null +++ b/src/core1/math/longlong_arith.c @@ -0,0 +1,63 @@ +// BanjoDecomp: (unknown decomp origin) +/* MSVC provides these as compiler intrinsics, so only define them for other compilers */ +#ifndef _MSC_VER + +unsigned long long __ull_rshift(unsigned long long a0, unsigned long long a1) +{ + return a0 >> a1; +} + +unsigned long long __ll_lshift(unsigned long long a0, unsigned long long a1) +{ + return a0 << a1; +} + +long long __ll_rshift(long long a0, long long a1) +{ + return a0 >> a1; +} + +#endif /* _MSC_VER */ + +/* These are not MSVC intrinsics, so define them for all compilers */ +unsigned long long __ull_rem(unsigned long long a0, unsigned long long a1) +{ + return a0 % a1; +} + +unsigned long long __ull_div(unsigned long long a0, unsigned long long a1) +{ + return a0 / a1; +} + +long long __ll_rem(unsigned long long a0, long long a1) +{ + return a0 % a1; +} + +long long __ll_div(long long a0, long long a1) +{ + return a0 / a1; +} + +unsigned long long __ll_mul(unsigned long long a0, unsigned long long a1) +{ + return a0 * a1; +} + +void __ull_divremi(unsigned long long *div, unsigned long long *rem, unsigned long long a2, unsigned short a3) +{ + *div = a2 / a3; + *rem = a2 % a3; +} + +long long __ll_mod(long long a0, long long a1) +{ + long long tmp = a0 % a1; + if ((tmp < 0 && a1 > 0) || (tmp > 0 && a1 < 0)) + { + + tmp += a1; + } + return tmp; +} diff --git a/src/core1/math/longlong_convert.c b/src/core1/math/longlong_convert.c new file mode 100644 index 000000000..8fe014dbe --- /dev/null +++ b/src/core1/math/longlong_convert.c @@ -0,0 +1,40 @@ +// BanjoDecomp: (unknown decomp origin) +long long __d_to_ll(double a0) +{ + return a0; +} + +long long __f_to_ll(float a0) +{ + return a0; +} + +unsigned long long __d_to_ull(double a0) +{ + return a0; +} + +unsigned long long __f_to_ull(float a0) +{ + return a0; +} + +double __ll_to_d(long long a0) +{ + return a0; +} + +float __ll_to_f(long long a0) +{ + return a0; +} + +double __ull_to_d(unsigned long long a0) +{ + return a0; +} + +float __ull_to_f(unsigned long long a0) +{ + return a0; +} diff --git a/src/core1/mlmtx.c b/src/core1/math/matrix_stack.c similarity index 95% rename from src/core1/mlmtx.c rename to src/core1/math/matrix_stack.c index b2f8a9101..ba78ce751 100644 --- a/src/core1/mlmtx.c +++ b/src/core1/math/matrix_stack.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/mlmtx.c +// BanjoDecomp: (unknown decomp origin) #include #include "core1/core1.h" @@ -12,9 +12,13 @@ void _guRotateF(f32 mf[4][4], f32, f32, f32, f32); f32 func_80263FF0(f32); f32 cosf(f32); -s32 D_80276570 = VER_SELECT(0xFF62C2B8, 0xF71CBE76, 0, 0); // CC_DATA_CRC2 -s32 D_80276574 = VER_SELECT(0x84D7B4F8, 0xA2B6F47C, 0, 0); // CORE2_DATA_CRC2 - +#if VERSION == VERSION_USA_1_0 + s32 D_80276570 = 0xFF62C2B8; //WHAT IS THIS? + s32 D_80276574 = 0x84D7B4F8; //CORE2_DATA_CRC2 +#elif VERSION == VERSION_PAL + s32 D_80276570 = 0xF71CBE76; //WHAT IS THIS? + s32 D_80276574 = 0xA2B6F47C; //CORE2_DATA_CRC2 +#endif f32 D_80276578 = BAD_DTOR; f32 D_8027657C = BAD_DTOR; @@ -217,6 +221,7 @@ void mlMtx_push_multiplied_2(MtxF * l_mtx, MtxF * r_mtx) { } } s_mtx_stack = (dst + 0); + FrameInterpolation_RecordMatrixMult(l_mtx->mf, r_mtx->mf); } //mlMtx @@ -232,6 +237,7 @@ void mlMtxIdent(void){ v0 += 5; } v0[0] = 1.0f; + FrameInterpolation_RecordMatrixIdent(); } void func_80251B5C(f32 x, f32 y, f32 z){ @@ -254,6 +260,7 @@ void mlMtxSet(MtxF* arg0) { *dst++ = *src++; } } + FrameInterpolation_RecordMatrixSet(arg0->mf); } void mlMtxRotate(f32 a, f32 x, f32 y, f32 z) { @@ -267,6 +274,7 @@ void mlMtxRotPitch(f32 arg0) { f32 var_f10; f32 var_f18; + FrameInterpolation_RecordMatrixRotPitch(arg0); if (arg0 != 0.0f) { arg0 *= D_80276578; sin = sinf(arg0); @@ -295,6 +303,7 @@ void mlMtxRotYaw(f32 arg0) { f32 var_f18; s32 i; + FrameInterpolation_RecordMatrixRotYaw(arg0); if (arg0 != 0.0f) { arg0 *= BAD_DTOR; sin = sinf(arg0); @@ -314,6 +323,7 @@ void mlMtxRotRoll(f32 arg0) { f32 var_f10; f32 var_f18; + FrameInterpolation_RecordMatrixRotRoll(arg0); if (arg0 != 0.0f) { arg0 *= D_8027657C; sin = sinf(arg0); @@ -385,6 +395,7 @@ void mlMtxRotatePYR(f32 pitch, f32 yaw, f32 roll){ void mlMtxScale_xyz(f32 x, f32 y, f32 z){ int i; + FrameInterpolation_RecordMatrixScale(x, y, z); for(i = 0; i < 3; i++){ s_mtx_stack->mf[0][i] *= x; s_mtx_stack->mf[1][i] *= y; @@ -394,6 +405,7 @@ void mlMtxScale_xyz(f32 x, f32 y, f32 z){ void mlMtxScale(f32 scale){ int i; + FrameInterpolation_RecordMatrixScale(scale, scale, scale); for(i = 0; i < 3; i++){ s_mtx_stack->mf[0][i] *= scale; s_mtx_stack->mf[1][i] *= scale; @@ -508,6 +520,7 @@ void mlMtxTranslate(f32 x, f32 y, f32 z) { f32 phi_f16; s32 phi_v1; + FrameInterpolation_RecordMatrixTranslate(x, y, z); for(phi_v1 = 0; phi_v1 < 3; phi_v1++){ phi_f18 = s_mtx_stack->mf[0][phi_v1] * x; phi_f16 = s_mtx_stack->mf[1][phi_v1] * y; diff --git a/src/core1/gu_matrix.c b/src/core1/math/ml.c similarity index 99% rename from src/core1/gu_matrix.c rename to src/core1/math/ml.c index acf6c05fd..79eec3915 100644 --- a/src/core1/gu_matrix.c +++ b/src/core1/math/ml.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/code_3250.c +// BanjoDecomp: ml.c #include "core1/core1.h" #include #include diff --git a/src/core1/gu_perspective.c b/src/core1/math/mlmtx.c similarity index 93% rename from src/core1/gu_perspective.c rename to src/core1/math/mlmtx.c index d17f00c60..b04304b3c 100644 --- a/src/core1/gu_perspective.c +++ b/src/core1/math/mlmtx.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/code_7F60.c +// BanjoDecomp: mlmtx.c #include #include #include "core1/core1.h" @@ -8,12 +8,11 @@ static void _guMtxIdentF(float mf[4][4]); -s32 D_802758F0 = VER_SELECT(0xAD7FF2F3, 0xB585BADA, 0, 0); // BGS_DATA_CRC2 -s32 D_802758F4 = VER_SELECT(0xD884D8AC, 0xD731B7E2, 0, 0); // FP_DATA_CRC2 -s32 D_802758F8 = 0; -s32 D_802758FC = 0; -s32 D_80275900 = VER_SELECT(0xCFADA290, 0xD39EA620, 0, 0); // LAIR_DATA_CRC2 -s32 D_80275904 = VER_SELECT(0x934A83F1, 0xC77ED5C6, 0, 0); // GV_DATA_CRC2 +#if VERSION == VERSION_USA_1_0 +u8 D_80275900[8] = {0xCF, 0xAD, 0xA2, 0x90, 0x93, 0x4A, 0x83, 0xF1}; +#elif VERSION == VERSION_PAL +u8 D_80275900[8] = {0xD3, 0x9E, 0xA6, 0x20, 0xC7, 0x7E, 0xD5, 0xC6}; +#endif f32 D_80275908 = BAD_DTOR; diff --git a/src/core1/ml.c b/src/core1/math/vector.c similarity index 88% rename from src/core1/ml.c rename to src/core1/math/vector.c index 72e4be8ee..6b2302e1d 100644 --- a/src/core1/ml.c +++ b/src/core1/math/vector.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/ml.c +// BanjoDecomp: (unknown decomp origin) #include #include "core1/core1.h" #include "functions.h" @@ -6,8 +6,13 @@ #include "version.h" #include "bk_math.h" -s32 D_80276CB0 = VER_SELECT(0xD22FFFD8, 0x90FA97CB, 0, 0); // TTC_DATA_CRC2 -s32 D_80276CB4 = VER_SELECT(0xDEFEF692, 0x8D96D002, 0, 0); // RBB_DATA_CRC2 +#if VERSION == VERSION_USA_1_0 +u32 D_80276CB0 = 0xD22FFFD8; //WHAT IS THIS? +u32 D_80276CB4 = 0xDEFEF692; //WHAT IS THIS? +#elif VERSION == VERSION_PAL +u32 D_80276CB0 = 0x90FA97CB; //WHAT IS THIS? +u32 D_80276CB4 = 0x8D96D002; //WHAT IS THIS? +#endif u16 *D_80276CB8 = NULL; //! ml_acosPrecValTblPtr @@ -117,39 +122,37 @@ f32 ml_vec3f_distance(f32 vec1[3], f32 vec2[3]) { return LENGTH_VEC3F(diff); } -f32 ml_vec3f_distance_to_point(f32 line_start_position[3], f32 line_end_position[3], f32 point_position[3]) { - f32 closestPointOnLine[3]; - f32 pad48; // unused - f32 pointOffsetFromLineStart[3]; - f32 pointDistanceFromLineStart; - f32 projectionFactor; - f32 projectionDistance; - f32 lineDirection[3]; - f32 lineLength; - f32 pad58; // unused +f32 ml_func_802560D0(f32 arg0[3], f32 arg1[3], f32 arg2[3]) { + f32 sp4C[3]; + f32 pad48; + f32 sp3C[3]; + f32 sp38; + f32 sp34; + f32 sp30; + f32 sp24[3]; + f32 sp20; + f32 pad58; - TUPLE_DIFF_COPY(lineDirection, line_end_position, line_start_position) - lineLength = LENGTH_VEC3F(lineDirection); + TUPLE_DIFF_COPY(sp24, arg1, arg0) + sp20 = LENGTH_VEC3F(sp24); - if (lineLength < 0.01) { - return ml_vec3f_distance(line_start_position, point_position); + if (sp20 < 0.01) { + return ml_vec3f_distance(arg0, arg2); } - TUPLE_DIFF_COPY(pointOffsetFromLineStart, point_position, line_start_position) - pointDistanceFromLineStart = LENGTH_VEC3F(pointOffsetFromLineStart); + TUPLE_DIFF_COPY(sp3C, arg2, arg0) + sp38 = LENGTH_VEC3F(sp3C); - if (pointDistanceFromLineStart < 0.01) { - return pointDistanceFromLineStart; + if (sp38 < 0.01) { + return sp38; } - projectionFactor = ((lineDirection[0] * pointOffsetFromLineStart[0] - + lineDirection[1] * pointOffsetFromLineStart[1] - + lineDirection[2] * pointOffsetFromLineStart[2]) / (lineLength * pointDistanceFromLineStart)); - projectionDistance = (projectionFactor * pointDistanceFromLineStart) / lineLength; - closestPointOnLine[0] = line_start_position[0] + (lineDirection[0] * projectionDistance); - closestPointOnLine[1] = line_start_position[1] + (lineDirection[1] * projectionDistance); - closestPointOnLine[2] = line_start_position[2] + (lineDirection[2] * projectionDistance); - return ml_vec3f_distance(closestPointOnLine, point_position); + sp34 = ((sp24[0]*sp3C[0] + sp24[1]*sp3C[1] + sp24[2]*sp3C[2]) / (sp20 * sp38)); + sp30 = (sp34 *sp38) / sp20; + sp4C[0] = arg0[0] + (sp24[0] * sp30); + sp4C[1] = arg0[1] + (sp24[1] * sp30); + sp4C[2] = arg0[2] + (sp24[2] * sp30); + return ml_vec3f_distance(sp4C, arg2); } f32 ml_distanceSquared_vec3f(f32 vec1[3], f32 vec2[3]) @@ -235,14 +238,16 @@ void ml_vec3f_set_length_copy(f32 dst[3], f32 src[3], f32 len) ml_vec3f_copy(dst, src); } -void ml_vec3f_clamp_deg360(f32 ptr[3]) { - int i; +void func_80256664(f32 ptr[3]) +{ + u32 i; - for (i = 0; i < 3; i++) { + for (i = 0; i < 3; i++) + { if (ptr[i] >= 0) - ptr[i] = (s32) ptr[i] % 360; + ptr[i] = (s32)ptr[i] % 360; else - ptr[i] += ((360 - (s32) ptr[i]) / 360) * 360; + ptr[i] += ((360 - (s32)ptr[i]) / 360) * 360; } } @@ -457,7 +462,7 @@ f32 func_80257248(f32 vec1[3], f32 vec2[3]) return func_8025715C(vec2[0] - vec1[0], vec2[2] - vec1[2]); } -void ml_horizontal_and_vertical_angles(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2) +void func_8025727C(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2, f32 *o1, f32 *o2) { f32 dz; f32 dy; // unused @@ -1188,15 +1193,15 @@ void func_8025901C(f32 arg0, f32 arg1[3], f32 arg2[3], f32 arg3){ }//L80259184 } -f32 ml_clamp_abs_f(f32 value, f32 max_abs_value) +f32 func_80259198(f32 arg0, f32 arg1) { - if (value > max_abs_value) - return max_abs_value; + if (arg0 > arg1) + return arg1; - if (value < -max_abs_value) - return -max_abs_value; + if (arg0 < -arg1) + return -arg1; - return value; + return arg0; } f32 mlDiffDegF(f32 arg0, f32 arg1) @@ -1264,51 +1269,48 @@ void ml_sub_delta_time(f32 *x) { *x = 0; } -// Perpendicular projection of point onto line using xz coordinates -void ml_project_point_onto_vecf3( - f32 closest_point_on_line[3], f32 line_start_position[3], - f32 line_end_position[3], f32 point_to_project[3]) +void func_8025947C(f32 a0[3], f32 a1[3], f32 a2[3], f32 a3[3]) { - f32 line_dx_xz; - f32 line_dz_xz; - f32 line_slope_xz; - f32 intersection_x_xz; - f32 line_intercept_xz; - f32 perpendicular_intercept_xz; + f32 f0; + f32 f12; + f32 f16; + f32 f8; + f32 f18; + f32 f4; - closest_point_on_line[1] = line_start_position[1]; + a0[1] = a1[1]; - line_dx_xz = line_end_position[0] - line_start_position[0]; + f0 = a2[0] - a1[0]; - if (line_dx_xz == 0) + if (f0 == 0) { - closest_point_on_line[0] = line_start_position[0]; - closest_point_on_line[2] = point_to_project[2]; + a0[0] = a1[0]; + a0[2] = a3[2]; return; } - line_dz_xz = line_end_position[2] - line_start_position[2]; + f12 = a2[2] - a1[2]; - if (line_dz_xz == 0) + if (f12 == 0) { - closest_point_on_line[0] = point_to_project[0]; - closest_point_on_line[2] = line_start_position[2]; + a0[0] = a3[0]; + a0[2] = a1[2]; return; } - line_slope_xz = line_dz_xz / line_dx_xz; - line_intercept_xz = line_start_position[2] - (line_start_position[0] * line_slope_xz); + f16 = f12 / f0; + f18 = a1[2] - (a1[0] * f16); - intersection_x_xz = -1.0 / line_slope_xz; + f8 = -1.0 / f16; - perpendicular_intercept_xz = point_to_project[2] - (point_to_project[0] * intersection_x_xz); + f4 = a3[2] - (a3[0] * f8); - intersection_x_xz = (perpendicular_intercept_xz - line_intercept_xz) / (line_slope_xz - intersection_x_xz); + f8 = (f4 - f18) / (f16 - f8); - closest_point_on_line[0] = intersection_x_xz; - closest_point_on_line[2] = intersection_x_xz * line_slope_xz + line_intercept_xz; + a0[0] = f8; + a0[2] = f8 * f16 + f18; } diff --git a/src/core1/musicplayer.c b/src/core1/musicplayer.c index ba238ec90..d7ff3d29b 100644 --- a/src/core1/musicplayer.c +++ b/src/core1/musicplayer.c @@ -3,7 +3,6 @@ #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "musicplayer.h" #include "version.h" @@ -16,7 +15,7 @@ void musicTrack_setVolume(u8, s32); void func_8024FC1C(u8, s32); void func_8025AC20(enum comusic_e, s32, s32, f32, char*, s32); void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void *arg4, char *arg5, s32 arg6); -void coMusicPlayer_free(void); +void comusicPlayer_free(void); void func_8025A55C(s32, s32, s32); void func_8025A7DC(enum comusic_e); void func_8025ABB8(enum comusic_e, s32, s32, s32); @@ -33,7 +32,7 @@ int D_80276E34 = 0; * @param track_id * @return CoMusic* */ -CoMusic *findTrack(enum comusic_e track_id) { +CoMusic *__find_track(enum comusic_e track_id) { CoMusic *iMusPtr; CoMusic *freeSlotPtr; @@ -77,12 +76,12 @@ void func_802599B4(CoMusic *this){ func_8024FC1C(this - D_80276E30, -1); } -void coMusicPlayer_init(void){ +void comusicPlayer_init(void){ CoMusic * iPtr; s32 i; if(D_80276E30 != NULL) - coMusicPlayer_free(); + comusicPlayer_free(); D_80276E30 = (CoMusic *) bk_malloc(6*sizeof(CoMusic)); for(iPtr = D_80276E30; iPtr < D_80276E30 + 6; iPtr++){ @@ -102,7 +101,7 @@ void coMusicPlayer_init(void){ } //comusic_freeAll -void coMusicPlayer_free(void){ +void comusicPlayer_free(void){ CoMusic *iPtr; func_8024FB8C(); func_8024F83C(); @@ -114,7 +113,7 @@ void coMusicPlayer_free(void){ D_80276E30 = NULL; } -s32 coMusicPlayer_getTrackCount(void){ +s32 comusic_active_track_count(void){ CoMusic * iPtr; s32 cnt = 0; for(iPtr = D_80276E30; iPtr < D_80276E30 + 6; iPtr++){ @@ -124,7 +123,7 @@ s32 coMusicPlayer_getTrackCount(void){ return cnt; } -void coMusicPlayer_update(void) { +void comusicPlayer_update(void) { s32 temp_lo; CoMusic *var_s0; f32 dt; @@ -367,7 +366,7 @@ void func_8025A58C(u32 arg0, u32 arg1){ } -void playMusic(enum comusic_e comusic_id, s32 volume, s32 arg2){ +void func_8025A5AC(enum comusic_e comusic_id, s32 volume, s32 arg2){ CoMusic *tmp_a2; s32 sp20; @@ -375,7 +374,7 @@ void playMusic(enum comusic_e comusic_id, s32 volume, s32 arg2){ volume = gcMusic_getDefaultVolumeForTrack(comusic_id); } - tmp_a2 = findTrack(comusic_id); + tmp_a2 = __find_track(comusic_id); if(tmp_a2 == NULL) return; @@ -403,11 +402,11 @@ void playMusic(enum comusic_e comusic_id, s32 volume, s32 arg2){ } void coMusicPlayer_playMusicWeak(enum comusic_e track_id, s32 volume){ - playMusic(track_id, volume, 0); + func_8025A5AC(track_id, volume, 0); } void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume){ - playMusic(track_id, volume, 1); + func_8025A5AC(track_id, volume, 1); } //comusic_queueTrack @@ -415,7 +414,7 @@ void comusic_playTrack(enum comusic_e track_id){ CoMusic *trackPtr; s32 indx; - trackPtr = findTrack(track_id); + trackPtr = __find_track(track_id); if(trackPtr == NULL) return; @@ -438,7 +437,7 @@ void func_8025A788(enum comusic_e comusic_id, f32 delay1, f32 delay2){ void func_8025A7DC(enum comusic_e track_id){ CoMusic *trackPtr; - trackPtr = findTrack(track_id); + trackPtr = __find_track(track_id); if (trackPtr != NULL && trackPtr->track_id >= 0){ func_802599B4(trackPtr); } @@ -455,7 +454,7 @@ s32 func_8025A818(void){ s32 func_8025A864(enum comusic_e track_id){ CoMusic *trackPtr; - trackPtr = findTrack(track_id); + trackPtr = __find_track(track_id); if (trackPtr != NULL && trackPtr->unkC == 0 && trackPtr->volume <= 0){ func_802599B4(trackPtr); return 1; @@ -466,7 +465,7 @@ s32 func_8025A864(enum comusic_e track_id){ void func_8025A8B8(enum comusic_e track_id, s32 arg1){ CoMusic *trackPtr; - trackPtr = findTrack(track_id); + trackPtr = __find_track(track_id); if (trackPtr != NULL){ trackPtr->unk14 = arg1; } @@ -526,7 +525,7 @@ void func_8025AA48(void){ void func_8025AABC(enum comusic_e track_id){ CoMusic *trackPtr; - if(trackPtr = findTrack(track_id)){ + if(trackPtr = __find_track(track_id)){ trackPtr->unk15 = 1; if(!trackPtr->volume) func_802599B4(trackPtr); @@ -546,17 +545,17 @@ void comusic_8025AB44(enum comusic_e comusic_id, s32 arg1, s32 arg2){ } void comusic_8025AB78(enum comusic_e comusic_id, s32 arg1, s32 arg2, s32 arg3){ - CoMusic *track = findTrack(comusic_id); + CoMusic *track = __find_track(comusic_id); if (!track) return; func_8025AC7C(comusic_id, arg1, arg2, 0.0f, &track->unk1C[arg3], "comusic.c", VER_SELECT(0x3a3, 0x3a4, 0, 0)); } void func_8025ABB8(enum comusic_e comusic_id, s32 arg1, s32 arg2, s32 arg3){ - func_8025AC7C(comusic_id, arg1, arg2, 0.0f, &(findTrack(comusic_id)->unk1C[arg3]), "comusic.c", VER_SELECT(0x3aa, 0x3ab,0,0)); + func_8025AC7C(comusic_id, arg1, arg2, 0.0f, &(__find_track(comusic_id)->unk1C[arg3]), "comusic.c", VER_SELECT(0x3aa, 0x3ab,0,0)); } void func_8025AC20(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, char* arg4, s32 char5){ - func_8025AC7C(comusic_id, arg1, arg2, 0.0f, findTrack(comusic_id)->unk1C, "comusic.c", VER_SELECT(0x3b1, 0x3b2,0,0)); + func_8025AC7C(comusic_id, arg1, arg2, 0.0f, __find_track(comusic_id)->unk1C, "comusic.c", VER_SELECT(0x3b1, 0x3b2,0,0)); } void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void *arg4, char* arg5, s32 arg6){ @@ -565,7 +564,7 @@ void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void s32 *fadeSlot = (s32 *)arg4; //get track location - trackPtr = findTrack(comusic_id); + trackPtr = __find_track(comusic_id); if(trackPtr == NULL) return; @@ -591,7 +590,7 @@ void func_8025AC7C(enum comusic_e comusic_id, s32 arg1, s32 arg2, f32 arg3, void //comusic_trackQueued int func_8025AD7C(enum comusic_e arg0){ - CoMusic * trackPtr = findTrack(arg0); + CoMusic * trackPtr = __find_track(arg0); return (trackPtr == NULL || trackPtr->track_id == -1)? 0 : 1; } @@ -601,7 +600,7 @@ int func_8025ADBC(enum comusic_e arg0){ } s32 func_8025ADD4(enum comusic_e id){ - CoMusic * ptr = findTrack(id); + CoMusic * ptr = __find_track(id); return ptr - D_80276E30; } @@ -616,7 +615,7 @@ void func_8025AE50(s32 arg0, f32 arg1){ } void func_8025AEA0(enum comusic_e track_id, s32 arg1){ - CoMusic *ptr = findTrack(track_id); + CoMusic *ptr = __find_track(track_id); if(!ptr) return; func_8024FDDC(ptr - D_80276E30, arg1); diff --git a/src/core1/musicplayer.h b/src/core1/musicplayer.h deleted file mode 100644 index 1fd913058..000000000 --- a/src/core1/musicplayer.h +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: core1/musicplayer.h -#ifndef BANJO_KAZOOIE_MUSICPLAYER_H -#define BANJO_KAZOOIE_MUSICPLAYER_H - -#define MAX_MUSIC_STRUCT_COUNT 6 - -#endif // BANJO_KAZOOIE_MUSICPLAYER_H diff --git a/src/core1/n_audio/n_csplayer.c b/src/core1/n_audio/n_csplayer.c index a92c0852d..7a2cf5eda 100644 --- a/src/core1/n_audio/n_csplayer.c +++ b/src/core1/n_audio/n_csplayer.c @@ -9,7 +9,7 @@ #include #include -//extern void __assert(const char *, const char *, int); +extern void __assert(const char *, const char *, int); void n_alSynSetVol( N_ALVoice *v, s16 volume, ALMicroTime t); s16 __n_vsVol(ALVoiceState *voice, ALSeqPlayer *seqp); ALVoiceState *__n_lookupVoice(ALSeqPlayer *, u8, u8); diff --git a/src/core1/n_audio/n_env.c b/src/core1/n_audio/n_env.c index c1671f37b..aafaea970 100644 --- a/src/core1/n_audio/n_env.c +++ b/src/core1/n_audio/n_env.c @@ -3,7 +3,7 @@ #include "n_synth.h" #include "functions.h" #include "variables.h" -#include "ultra_assert.h" +#include "assert.h" Acmd *n_alResamplePull(N_PVoice *e, s16 *outp, Acmd *p); diff --git a/src/core1/n_audio/n_seqplayer.c b/src/core1/n_audio/n_seqplayer.c index 71735dac4..5577b44de 100644 --- a/src/core1/n_audio/n_seqplayer.c +++ b/src/core1/n_audio/n_seqplayer.c @@ -2,7 +2,7 @@ #include #include "n_synth.h" #include "file_and_line.h" -#include "ultra_assert.h" +#include "assert.h" //#include #include // #include "functions.h" diff --git a/src/core1/overlay.c b/src/core1/overlay.c index c5a76f83e..a727190ae 100644 --- a/src/core1/overlay.c +++ b/src/core1/overlay.c @@ -2,7 +2,8 @@ #include #include "boot/overlaytable.h" #include "core1/core1.h" -#include "checksums.h" +#include "functions.h" +#include "variables.h" extern u8 gHeapBase; extern u32 D_8027BF2C; @@ -19,7 +20,7 @@ void overlay_load( #if 0 void *compressed_buffer; u32 crc2, crc1; - struct overlay_checksums_s *checksums; + u32 *tmp; osWritebackDCacheAll(); osInvalDCache(ram_start, ram_end - ram_start); @@ -49,11 +50,11 @@ void overlay_load( bzero(bss_start, bss_end - bss_start); osWritebackDCacheAll(); - checksums = (struct overlay_checksums_s *) bss_start; - checksums->text_checksum1 = crc1; - checksums->text_checksum2 = crc2; - checksums->data_checksum1 = D_8027BF2C; - checksums->data_checksum2 = D_8027BF30; + tmp = (u32*) bss_start; + tmp[0] = crc1; + tmp[1] = crc2; + tmp[2] = D_8027BF2C; + tmp[3] = D_8027BF30; } #endif } diff --git a/src/core1/stopnswop.c b/src/core1/stopnswop.c index e5165fac8..4564357f4 100644 --- a/src/core1/stopnswop.c +++ b/src/core1/stopnswop.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/code_1D5D0.c +// BanjoDecomp: sns.c #include #include "core1/core1.h" #include "functions.h" @@ -217,7 +217,7 @@ void sns_generate_payload(struct SnsPayload *payload) void sns_write_payload_over_heap(void) { // [port] SNS writes payload to hardcoded N64 RDRAM for cartridge-swap. - // Non-functional on PC. + // Non-functional on PC — all base payload pointers are NULL. #if 0 s32 val2; u32 i; diff --git a/src/core1/sns.c b/src/core1/stopnswop_payload.c similarity index 99% rename from src/core1/sns.c rename to src/core1/stopnswop_payload.c index 6c0e115c9..2168c8848 100644 --- a/src/core1/sns.c +++ b/src/core1/stopnswop_payload.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/sns.c +// BanjoDecomp: sns.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core1/syncprintf.c b/src/core1/syncprintf.c new file mode 100644 index 000000000..ae7baf1de --- /dev/null +++ b/src/core1/syncprintf.c @@ -0,0 +1,17 @@ +// BanjoDecomp: (unknown decomp origin) +#include +// Lighthouse [port] These functions aren't used so we can remove these includes +//#include +//#include + +void osSyncPrintf(const char *fmt, ...) +{ + int ans; + va_list ap; + // these functions intentionally left blank. ifdeffed out in rom release +} +void rmonPrintf(const char *fmt, ...) +{ + int ans; + va_list ap; +} diff --git a/src/core1/viewport.c b/src/core1/viewport.c index 04a1e2976..bf5591aed 100644 --- a/src/core1/viewport.c +++ b/src/core1/viewport.c @@ -45,7 +45,7 @@ f32 viewport_getDistance(f32 arg0[3]) { return ml_vec3f_distance(arg0, sViewportPosition); } -void viewport_getLookVector(f32 arg0[3]) { +void viewport_getLookbk_vector(f32 arg0[3]) { ml_vec3f_copy(arg0, sViewportLookbk_vector); } @@ -100,12 +100,12 @@ void viewport_setRenderPerspectiveMatrix(Gfx **gfx, Mtx **mtx, f32 near, f32 far near = MAX(sViewportNear, near); far = MIN(sViewportFar, far); -#if ANTI_TAMPER - if ((*(u32*) OS_PHYSICAL_TO_K1(0x000001D8)) + 0x53D4FFF0) { - near = 750.0f; - far = 1250.0f; - } -#endif + // [port] This is either anti-tamper or a legit camera adjustment + // based on NTSC or PAL, because PAL runs at 50Hz instead of 60Hz + // if(*(u32*)OS_PHYSICAL_TO_K1(0x1D8) + 0x53D4FFF0) { + // near = 750.0f; + // far = 1250.0f; + // } guPerspective(*mtx, &perspNorm, sViewportFOVy, sViewportAspect, near, far, 0.5f); gSPPerspNormalize((*gfx)++, perspNorm); @@ -490,7 +490,7 @@ f32 viewport_transformCoordinate(f32 x, f32 y, f32 viewport_translation[3], f32 f32 sViewportBackupPosition[3]; f32 sViewportBackupRotation[3]; f32 sViewportBackupFrustumPlanes[4][4]; -f32 sViewportBackupLookVector[3]; +f32 sViewportBackupLookbk_vector[3]; MtxF sViewportBackupMatrix; // ?? @@ -537,7 +537,7 @@ void viewport_backupState(void) { viewport_getPosition_vec3f(sViewportBackupPosition); viewport_getRotation_vec3f(sViewportBackupRotation); viewport_getFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]); - viewport_getLookVector(sViewportBackupLookVector); + viewport_getLookbk_vector(sViewportBackupLookbk_vector); for(i = 0; i < 4; i++){ for(j = 0; j < 4; j++){ @@ -552,7 +552,7 @@ void viewport_restoreState(void) { viewport_setPosition_vec3f(sViewportBackupPosition); viewport_setRotation_vec3f(sViewportBackupRotation); viewport_setFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]); - ml_vec3f_copy(sViewportLookbk_vector, sViewportBackupLookVector); + ml_vec3f_copy(sViewportLookbk_vector, sViewportBackupLookbk_vector); for(i = 0; i < 4; i++){ for(j = 0; j < 4; j++){ diff --git a/src/core1/vimgr.c b/src/core1/vimgr.c index 257477efd..dec23b0aa 100644 --- a/src/core1/vimgr.c +++ b/src/core1/vimgr.c @@ -6,9 +6,7 @@ #include "version.h" #include "libultraship/libultra/rcp.h" -#include "port/DevTools/ThreadWatchdog.h" #include "port/Patches/Patches.h" -#include "port/OS/OS.h" #define VIMANAGER_THREAD_STACK_SIZE 0x400 @@ -141,9 +139,6 @@ void viMgr_init(void) { osCreateMesgQueue(&sMesgQueue2, sMesgBuffer2, 1); osCreateMesgQueue(&sMesgQueue3, sMesgBuffer3, FRAMERATE); osViSetEvent(&sMesgQueue1, OS_MESG_PTR(NULL), 1); - OS_SetQueueBlocking(&sMesgQueue1, 1); // viMgr_entry parks here between retraces - OS_SetQueueBlocking(&sMesgQueue2, 1); // the tick parks here for the frame token - OS_SetQueueBlocking(&sMesgQueue3, 1); // and here for its retraces sActiveFramebuffer = 0; D_80280724 = 1; @@ -174,42 +169,47 @@ void viMgr_func_8024BFAC(void){ void viMgr_func_8024BFD8(s32 arg0){ // [port] Set D_80280724 to the actual VI count so time_func_8033DDB8() returns - // the correct delta for demo/playback zoomboxes. + // the correct delta for demo/playback zoomboxes. On N64 this was set from the + // VI wait loop counter which reflected real rendering time (including lag). + // During demo playback, sDemoViCount includes the N64's original rendering lag + // for maps that ran slow, which the zoombox dialog system needs to pace text. s32 demoVi = port_getDemoViCount(); + D_80280724 = (demoVi > 0) ? demoVi : time_getDeltaReal_frames(); +#if 0 static s32 D_80280E90; - s32 viBudget = (demoVi > 2) ? demoVi : 2; - + osSetThreadPri(NULL, 0x7f); defragManager_setPriority(DEFRAGMANAGER_THREAD_PRIORITY_HIGH); - defragManager_resume(); + defragManager_80240874(); if(arg0){ osRecvMesg(&sMesgQueue2, NULL, OS_MESG_BLOCK); } - while(D_802808D8 < viBudget - D_80280E90){ + while(D_802808D8 < viMgr_func_8024BFA0() - D_80280E90){ osRecvMesg(&sMesgQueue3, NULL, OS_MESG_BLOCK); } while(sMesgQueue3.validCount){ osRecvMesg(&sMesgQueue3, NULL, OS_MESG_NOBLOCK); } - + osViSwapBuffer(gFramebuffers[sActiveFramebuffer = getOtherFramebuffer()]); D_80280E90 = 0; while(!(osDpGetStatus() & 2) && osViGetCurrentFramebuffer() != osViGetNextFramebuffer()){ osRecvMesg(&sMesgQueue3, NULL, OS_MESG_BLOCK); D_80280E90++; }//L8024C178 - D_80280724 = (demoVi > 0) ? demoVi : D_802808D8; + D_80280724 = D_802808D8; D_802808D8 = 0; - defragManager_pause(); + defragManager_802408B0(); osSetThreadPri(NULL, 0x14); defragManager_setPriority(DEFRAGMANAGER_THREAD_PRIORITY); +#endif } void viMgr_func_8024C1B4(void){ viMgr_func_8024BFD8(0); - // dummy_func_8025AFB8(); + dummy_func_8025AFB8(); } void viMgr_func_8024C1DC(void){ @@ -237,10 +237,6 @@ void viMgr_entry(void *arg0){ OSMesg sp48; do{ osRecvMesg(&sMesgQueue1, &sp48, OS_MESG_BLOCK); - if (OS_ThreadShouldExit()) { // [port] cooperative shutdown - return; - } - ThreadWatchdog_Beat(WATCHDOG_VIMGR); // [port] one beat per retrace thread5_checkAndExecutePreNMI(); D_802808D8++; if(D_802808D8 == 420){ @@ -260,6 +256,7 @@ void viMgr_entry(void *arg0){ void viMgr_setScreenBlack(s32 active) { osViBlack(active); + port_setViBlack(active); } void viMgr_clearFramebuffers(void) { @@ -274,25 +271,6 @@ s32 viMgr_func_8024C4E8(void) { return D_802808D8; } -// [port] Watchdog diagnostics: unsynchronized snapshot of the pacing state. -void viMgr_getWatchdogState(ViMgrWatchdogState *out) { - out->retraceCount = D_802808D8; - out->q1Count = sMesgQueue1.validCount; - out->q2Count = sMesgQueue2.validCount; - out->q3Count = sMesgQueue3.validCount; -} - -// [port] Watchdog diagnostics: queue identities, so blocked waits get names. -OSMesgQueue *viMgr_getRetraceQueue(void) { - return &sMesgQueue1; -} -OSMesgQueue *viMgr_getFrameTokenQueue(void) { - return &sMesgQueue2; -} -OSMesgQueue *viMgr_getTickRetraceQueue(void) { - return &sMesgQueue3; -} - void viMgr_func_8024C4F8(s32 arg0) { D_802808D8 = arg0; } diff --git a/src/core2/abilityprogress.c b/src/core2/abilityprogress.c index 5d08de3a5..a79fc8c97 100644 --- a/src/core2/abilityprogress.c +++ b/src/core2/abilityprogress.c @@ -14,12 +14,6 @@ static struct { #define abilityprogress_learnedAbilities abilityprogress.learned #define abilityprogress_usedAbilities abilityprogress.used -// [port] The tutorial's flags and dialogs belong to Spiral Mountain, but a romhack may -// place it in any map of that level, so gate on the level rather than one map id. -static s32 inSpiralMountain(void){ - return map_getLevel(gsworld_getMap()) == LEVEL_B_SPIRAL_MOUNTAIN; -} - void ability_use(s32 arg0){ s32 sp2C; s32 sp28; @@ -33,32 +27,32 @@ void ability_use(s32 arg0){ switch(arg0){ case ABILITY_USED_JUMP: // [port] guard with SM check — flags collide with map-specific usage in other worlds (e.g. BGS switches) - if (inSpiralMountain()) + if (gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) mapSpecificFlags_set(8, true); sp28 = 1; break; case ABILITY_USED_FLAP: - if (inSpiralMountain()) + if (gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) mapSpecificFlags_set(9, true); sp28 = 1; break; case ABILITY_USED_FLIP: - if (inSpiralMountain()) + if (gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) mapSpecificFlags_set(0xa, true); sp28 = 1; break; case ABILITY_USED_SWIM: - if(inSpiralMountain()){ + if(gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN){ sp2C = ASSET_DFC_BOTTLES_UNDERWATER_TUTORIAL; } break; case ABILITY_USED_CLIMB: - if(inSpiralMountain()){ + if(gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN){ sp2C = ASSET_E02_DIALOG_BOTTLES_CLIMB_OTHER; } break; case ABILITY_USED_BEAK_BARGE: - if(inSpiralMountain()){ + if(gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN){ sp2C = ASSET_E05_DIALOG_BOTTLES_KAZOOIE_BARGE; } break; @@ -121,20 +115,12 @@ void ability_clearAll(void){ abilityprogress_usedAbilities = 0; } -void ability_setLearnedEx(s32 move, s32 val, s32 triggerEvent){ - s32 prev = (abilityprogress_learnedAbilities >> move) & 1; +void ability_setLearned(s32 move, s32 val){ if(val){ abilityprogress_learnedAbilities |= (1 << move); }else{ abilityprogress_learnedAbilities &= ~(1 << move); } - if(triggerEvent && prev != (val ? 1 : 0)){ - CALL_EVENT(OnAbilityLearned, move, val ? 1 : 0); - } -} - -void ability_setLearned(s32 move, s32 val){ - ability_setLearnedEx(move, val, 1); } void ability_setAllLearned(s32 val){ diff --git a/src/core2/actor_array.c b/src/core2/actor_array.c index 7c6aa9ee8..e681a9dab 100644 --- a/src/core2/actor_array.c +++ b/src/core2/actor_array.c @@ -1,14 +1,11 @@ -// BanjoDecomp: core2/code_9E370.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" #include "actor.h" #include "prop.h" -#include "port/Enhancements/Retention/Retention.h" -#include "port/Patches/Patches.h" +#include "port/Enhancements/NoteRetention/NoteRetention.h" extern s32 D_80370990; extern f32 GameEngine_GetAspectRatio(void); @@ -31,6 +28,7 @@ f32 player_getYaw(void); extern void func_8032B3A0(Actor *, ActorMarker *); extern void func_8032EE0C(GenFunction_2, uintptr_t); extern void func_8032EE20(void); +extern void __spawnQueue_add_5(GenFunction_5, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); void func_8032A6A8(Actor *arg0); @@ -55,12 +53,6 @@ typedef struct { s16 unkE; }Actorlocal_Core2_9E370; -// [port] Sized ahead of demand so actor_new never bk_reallocs (relocates) the array mid-map. -// The marker pool is the binding limit (see ACTOR_POOL_SIZE); the grow chunk only exists so -// the array stays large enough to hold whatever the pool handed out, never the other way round. -#define ACTOR_ARRAY_INITIAL_CAP ACTOR_POOL_SIZE -#define ACTOR_ARRAY_GROW_CHUNK 128 - /* .data */ ActorArray *suBaddieActorArray = NULL; //actorArrayPtr s32 D_8036E564 = 0; @@ -195,13 +187,13 @@ void func_803255FC(Actor *this) { } break; } - modelRender_setAppendageVisibility(1, this->unk124_3 + 1); - modelRender_setAppendageVisibility(2, this->unk124_3 + 1); + func_8033A45C(1, this->unk124_3 + 1); + func_8033A45C(2, this->unk124_3 + 1); } void func_80325760(Actor *this) { - modelRender_setAppendageVisibility(1, 4); - modelRender_setAppendageVisibility(2, 4); + func_8033A45C(1, 4); + func_8033A45C(2, 4); } // [port] In widescreen, actors outside the 4:3 frustum are still drawn but @@ -379,7 +371,6 @@ Actor *func_80325F2C(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { return actor_drawFullDepth(marker, gfx, mtx, vtx); } -// CCW Unknown Update Function void func_80325F84(Actor *this){} void func_80325F8C(void) { @@ -446,8 +437,6 @@ void actorArray_free(void) { // [port] Note retention: every note actor is about to be freed, so drop our // live-actor tracking (markers are being released here). port_noteRetention_onActorsFreed(); - port_remoteCarry_reset(); - port_anchorDummies_onActorsFreed(); if (suBaddieActorArray != NULL) { for(var_s0 = suBaddieActorArray->data; var_s0 < &suBaddieActorArray->data[suBaddieActorArray->cnt]; var_s0++){ @@ -579,15 +568,12 @@ void func_803268B4(void) { if (!actor->despawn_flag) { if (marker->unk2C_2) { marker->actorUpdate2Func(actor); - // [port] Update may have spawned actors, reallocating the array; re-fetch the slot. - actor = &suBaddieActorArray->data[temp_v1]; if (anim_ctrl != NULL) { actor->sound_timer = anctrl_getAnimTimer(anim_ctrl); } } else if (!temp_s1 || (temp_s1 && func_803296D8(actor, temp_s1))) { if ( marker->actorUpdateFunc != NULL) { marker->actorUpdateFunc(actor); - actor = &suBaddieActorArray->data[temp_v1]; // [port] re-fetch: see above if (anim_ctrl != NULL) { actor->sound_timer = anctrl_getAnimTimer(anim_ctrl); } @@ -802,8 +788,6 @@ void func_803272D0(f32 arg0[3], f32 arg1, s32 arg2, int (*arg3)(Actor *)){ } Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ - // [port] Romhacks rewrite spawn args per actor id before the real work - romhack_RewriteActorSpawn(actorInfo, &flags); ActorAnimationInfo * sp54; s32 i; f32 sp44[3]; @@ -817,13 +801,13 @@ Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ s32 pos_copy[3] = { pos_x, pos_y, pos_z }; if(suBaddieActorArray == NULL){ - suBaddieActorArray = (ActorArray *)bk_malloc(sizeof(ActorArray) + ACTOR_ARRAY_INITIAL_CAP*sizeof(Actor)); + suBaddieActorArray = (ActorArray *)bk_malloc(sizeof(ActorArray) + 20*sizeof(Actor)); suBaddieActorArray->cnt = 0; - suBaddieActorArray->max_cnt = ACTOR_ARRAY_INITIAL_CAP; + suBaddieActorArray->max_cnt = 20; } if(suBaddieActorArray->cnt + 1 > suBaddieActorArray->max_cnt){ - suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + ACTOR_ARRAY_GROW_CHUNK; + suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 5; suBaddieActorArray = (ActorArray *)bk_realloc(suBaddieActorArray, sizeof(ActorArray) + suBaddieActorArray->max_cnt*sizeof(Actor)); } @@ -1100,7 +1084,11 @@ static void __actor_free(ActorMarker *arg0, Actor *arg1){ //remove last actor from actor array suBaddieActorArray->cnt--; - // [port] Never shrink the array; keeps the pre-sized headroom from actor_new so pointers stay stable. + //shrink actor array capacity + if(suBaddieActorArray->cnt + 8 <= suBaddieActorArray->max_cnt){ + suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 4; + suBaddieActorArray = (ActorArray *)bk_realloc(suBaddieActorArray, suBaddieActorArray->max_cnt*sizeof(Actor) + sizeof(ActorArray)); + } marker_free(arg0); } @@ -1170,38 +1158,13 @@ void marker_despawn(ActorMarker *marker){ } } else{ - // [port] Shadow-link cleanup for immediate-mode despawns. - if(actor->unk104){ - if(actor->modelCacheIndex != 0x108){ - // Freeing a shadow-owner: unlink and free its shadow too. - ActorMarker *shadowMarker = actor->unk104; - Actor *shadow = marker_getActor(shadowMarker); - shadow->unk104 = NULL; - actor->unk104 = NULL; - __actor_free(shadowMarker, shadow); - // Swap-remove may have relocated this actor; re-fetch through the marker. - actor = marker_getActor(marker); - } - else{ - // Freeing a shadow directly: sever the owner's link too. - marker_getActor(actor->unk104)->unk104 = NULL; - actor->unk104 = NULL; - } - } __actor_free(marker, actor); } } void func_803283BC(void){ D_8036E574 = 1; -} - -void port_actorDespawn_beginDefer(void){ - D_8036E574 = 1; -} - -void port_actorDespawn_endDefer(void){ - D_8036E574 = 0; + D_8036E578 = 0; } //actorArray_flushDespawns @@ -1546,14 +1509,14 @@ bool func_803292E0(Actor *this){ return 1; } - playerPosition_get(player_position); + _player_getPosition(player_position); return func_80307258(player_position, this->unk10_25 - 1, this->unk10_18 - 1) != -1; } bool func_80329354(Actor *this){ f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); return func_80329260(this, sp1C); } @@ -1563,7 +1526,7 @@ bool func_80329384(Actor *this, f32 arg1){ if(this->unk10_25 == 0) return true; - playerPosition_get(sp1C); + _player_getPosition(sp1C); return func_80307258(sp1C, this->unk10_25 - 1, this->unk10_18 - 1) != -1 && (sp1C[1] < (this->position[1] + arg1)) @@ -1610,14 +1573,14 @@ bool subaddie_playerIsWithinSphereAndActive(Actor *this, s32 dist){ bool subaddie_playerIsWithinSphere(Actor *this, s32 dist){ f32 sp24[3]; - f32 player_position[3]; + f32 sp18[3]; func_8028E964(sp24); - playerPosition_get(player_position); - sp24[1] = player_position[1]; - if( ( (this->position_x - sp24[0]) * (this->position_x - sp24[0]) - + (this->position_y - sp24[1]) * (this->position_y - sp24[1]) - + (this->position_z - sp24[2]) * (this->position_z - sp24[2]) + _player_getPosition(sp18); + sp24[1] = sp18[1]; + if( ( (this->position_x - sp24[0])*(this->position_x - sp24[0]) + + (this->position_y - sp24[1])*(this->position_y - sp24[1]) + + (this->position_z - sp24[2])*(this->position_z - sp24[2]) ) < dist*dist ){ return true; @@ -1656,7 +1619,7 @@ s32 func_8032970C(Actor *this){ f32 plyr_pos[3]; func_8028E964(sp24); - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); sp24[1] = plyr_pos[1]; return (s32) DIST_SQ_VEC3F(this->position, sp24); } @@ -1673,12 +1636,12 @@ s32 subaddie_getYawToPosition(Actor *arg0, f32 arg1[3]){ } void func_803297FC(Actor *arg0, f32 *o1, f32 *o2){ - f32 player_pos[3]; + f32 sp2C[3]; - playerPosition_get(player_pos); - ml_horizontal_and_vertical_angles( + _player_getPosition(sp2C); + func_8025727C( arg0->position[0], arg0->position[1], arg0->position[2], - player_pos[0], player_pos[1], player_pos[2], + sp2C[0], sp2C[1], sp2C[2], o1, o2 ); *o1 = 360.0f - *o1; @@ -1938,13 +1901,9 @@ void actors_applyFromSavestate(void *savestate_ptr, ActorListSaveState *savestat pad = savestate_actor->yaw; CALL_CANCELLABLE_EVENT(OnLoadActorSaveState, savestate_actor, sp50[0], sp50[1], sp50[2]) { temp_v0_6 = actor_spawnWithYaw_s32(savestate_actor->modelCacheIndex, &sp50, pad); - // [port] The spawn is nullable: the id may not be spawnable here, and a - // cancelled OnActorSpawn returns whatever the listener supplied, including NULL. - if (temp_v0_6 != NULL) { - actor_copy(savestate_actor, temp_v0_6); - func_80329B68(temp_v0_6); - func_803299B4(temp_v0_6); - } + actor_copy(savestate_actor, temp_v0_6); + func_80329B68(temp_v0_6); + func_803299B4(temp_v0_6); } } savestate_actor++; @@ -2018,7 +1977,7 @@ void func_8032A82C(Actor *arg0, s32 arg1) { sp1C = (Actorlocal_Core2_9E370 *)arg0->local; sp24 = nodeprop_findByActorIdAndActorPosition(arg1, arg0); if (sp24 != NULL) { - sp1C->unkC = nodeProp_getYaw(sp24); + sp1C->unkC = nodeprop_getYaw(sp24); nodeprop_getPosition(sp24, sp1C->unk0); sp1C->unkE = func_80341EC4(sp1C->unk0); } @@ -2259,36 +2218,6 @@ ActorMarker *func_8032B16C(enum jiggy_e jiggy_id) { } } -ActorMarker *actorArray_findHoneycombMarkerById(enum honeycomb_e id) { - Actor* base; - Actor* var_s0; - - if (suBaddieActorArray != NULL) { - base = &suBaddieActorArray->data[0]; - for (var_s0 = base; (var_s0 - base) < suBaddieActorArray->cnt; var_s0++) { - if ((var_s0->marker->id == MARKER_53_EMPTY_HONEYCOMB) && (func_802CA1C4(var_s0) == id)) { - return var_s0->marker; - } - } - } - return NULL; -} - -ActorMarker *actorArray_findMumboTokenMarkerById(enum mumbotoken_e id) { - Actor* base; - Actor* var_s0; - - if (suBaddieActorArray != NULL) { - base = &suBaddieActorArray->data[0]; - for (var_s0 = base; (var_s0 - base) < suBaddieActorArray->cnt; var_s0++) { - if ((var_s0->marker->id == MARKER_39_MUMBO_TOKEN) && (func_802E0CB0(var_s0) == id)) { - return var_s0->marker; - } - } - } - return NULL; -} - void func_8032B258(Actor *this, enum collision_e arg1) { f32 sp44; f32 sp38[3]; diff --git a/src/core2/actor_cleanup.c b/src/core2/actor_cleanup.c index 8b0a8f89d..152b831b7 100644 --- a/src/core2/actor_cleanup.c +++ b/src/core2/actor_cleanup.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_DC4B0.c #include #include "functions.h" #include "variables.h" @@ -6,9 +5,7 @@ void func_80363500(Actor *this); /* .data */ -// Next To SM Bridge Bottles -// Gets removed when player learns all SM Moves -ActorInfo D_80373DC0 = { +ActorInfo D_80373DC0= { 0x1EE, ACTOR_3BA_UNKNOWN, 0, 0, NULL, func_80363500, actor_update_func_80326224, func_80325340, diff --git a/src/core2/gccube.c b/src/core2/actor_cubebounds.c similarity index 99% rename from src/core2/gccube.c rename to src/core2/actor_cubebounds.c index d67d989a6..24f96b19f 100644 --- a/src/core2/gccube.c +++ b/src/core2/actor_cubebounds.c @@ -1,12 +1,10 @@ -// BanjoDecomp: core2/gccube.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "bk_math.h" // [port] TUPLE macros #include -#include "math.h" +#include "bk_math.h" #include "prop.h" #include "port/Patches/Patches.h" @@ -52,7 +50,7 @@ void func_80308EC8(void); bool func_80308F54(s32 cube_index); extern ActorInfo D_803675F0; -extern ActorInfo gWorldExitPad; +extern ActorInfo D_80367838; /* .data */ s32 sSpawnableActorSize = 0; //0x8036A9B0 @@ -390,19 +388,19 @@ void func_80302C94(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 sp38[3]; f32 temp_f18; -#if ANTI_TAMPER if (!mapSpecificFlags_validateCRC1()) return; -#endif func_8032D3A8(); viewport_getPosition_vec3f(vp_position); viewport_getRotation_vec3f(vp_rotation); - ml_vec3f_clamp_deg360(vp_rotation); + func_80256664(vp_rotation); cube_positionToIndices(vp_cube_indices, vp_position); - TUPLE_DIFF(vp_cube_indices, sCubeList.min) + vp_cube_indices[0] -= sCubeList.min[0];\ + vp_cube_indices[1] -= sCubeList.min[1];\ + vp_cube_indices[2] -= sCubeList.min[2]; func_80308EC8(); - TUPLE_SET(sp44, 0) + sp44[0] = sp44[1] = sp44[2] = 0; sp38[0] = sCubeList.width[0] - 1;\ sp38[1] = sCubeList.width[1] - 1;\ sp38[2] = sCubeList.width[2] - 1; @@ -541,7 +539,7 @@ static Cube *__code7AF80_getCubeAtPosition(s32 position[3]) { (position[2] - sCubeList.min[2]) * sCubeList.stride[1]; } -Cube *cubeList_GetCubeAtPosition_s32(s32 position[3]) { +Cube *cube_atPosition_s32(s32 position[3]) { s32 sp1C[3]; s32 i; // Cube *out; @@ -565,13 +563,13 @@ Cube *cubeList_GetCubeAtPosition_s32(s32 position[3]) { + diff[2]*sCubeList.stride[1]; } -Cube *cubeList_GetCubeAtPosition_f32(f32 position[3]){ +Cube *cube_atPosition_f32(f32 position[3]){ s32 pos_s32[3]; pos_s32[0] = (s32)position[0]; pos_s32[1] = (s32)position[1]; pos_s32[2] = (s32)position[2]; - return cubeList_GetCubeAtPosition_s32(pos_s32); + return cube_atPosition_s32(pos_s32); } Cube *func_8030364C(void){ @@ -1084,7 +1082,7 @@ void nodeprop_getPosition(NodeProp *nodeProp, f32 dst[3]) { TUPLE_ASSIGN(dst, nodeProp->x, nodeProp->y, nodeProp->z) } -u32 nodeProp_getYaw(NodeProp *nodeProp) { +u32 nodeprop_getYaw(NodeProp *nodeProp) { return nodeProp->yaw; } @@ -1331,7 +1329,7 @@ void func_8030578C(void){ && (sSpawnableActorList != NULL) ){ for(i = 0; i < sSpawnableActorSize - 1; i++){ - if(sSpawnableActorList[i].infoPtr == &gWorldExitPad){ + if(sSpawnableActorList[i].infoPtr == &D_80367838){ sSpawnableActorList[i].infoPtr = &D_803675F0; sSpawnableActorList[i].spawnFunc = actor_new; sSpawnableActorList[i].unk8 = 0; @@ -2064,8 +2062,8 @@ void func_80307CA0(ActorMarker *marker) { for(i = 0; cubePtrList[i] != NULL; i++) { for(node_idx = 0; node_idx < cubePtrList[i]->unk0_4; node_idx++){ node = codeA5BC0_getPropNodeAtIndex(cubePtrList[i], node_idx); - if (codeA5BC0_getNodePropMarkerId(node) == marker_bitfield) { - node_radius = codeA5BC0_getPositionAndSelectorOrRadius(node, node_position); + if (codeA5BC0_getNodePropUnkA(node) == marker_bitfield) { + node_radius = codeA5BC0_getPositionAndReturnRadius(node, node_position); if( ((node_position[0] - node_radius) < marker_position[0]) && (marker_position[0] < (node_position[0] + node_radius)) && ((node_position[1] - node_radius) < marker_position[1]) && (marker_position[1] < (node_position[1] + node_radius)) && ((node_position[2] - node_radius) < marker_position[2]) && (marker_position[2] < (node_position[2] + node_radius)) @@ -2480,7 +2478,7 @@ void func_80308D2C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { cube = &sCubeList.cubes[D_80382150[phi_s4]]; if (viewport_cube_isInFrustum(cube)) { viewport_getPosition_vec3w(vp_pos); - vp_cube_index = cubeList_GetCubeAtPosition_s32(vp_pos) - sCubeList.cubes; + vp_cube_index = cube_atPosition_s32(vp_pos) - sCubeList.cubes; for(phi_s0 = 0; (phi_s0 < D_80382150[phi_s4 + 1]) && (vp_cube_index != D_80382150[phi_s0 + 2]); phi_s0++) { } if (phi_s0 < D_80382150[phi_s4 + 1]) { diff --git a/src/core2/actor_cubepropsystem.c b/src/core2/actor_cubepropsystem.c index 4f778b6f4..466e31455 100644 --- a/src/core2/actor_cubepropsystem.c +++ b/src/core2/actor_cubepropsystem.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/code_A5BC0.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "enums.h" -#include "actor.h" #include #include "port/Patches/Patches.h" @@ -14,8 +12,8 @@ extern int ResourceMgr_IsModelAsset(uint32_t assetId); #define AssetCacheSize 0x3D5 -// [port] Expand Marker Pool for Rando Allocation -#define MARKER_POOL_SIZE ACTOR_POOL_SIZE +// Port Expand Marker Pool for Rando Allocation +#define MARKER_POOL_SIZE 0x1C0 #define MARKER_BITMAP_BYTES (MARKER_POOL_SIZE / 8) extern bool func_802E74A0(f32[3], f32, f32[3], f32[3]); @@ -30,7 +28,7 @@ extern BKCollisionTriangle *collisionList_func_802E805C(BKCollisionList *, BKVer extern NodeProp *func_803080C8(s32 arg0); extern Cube *func_80308224(void); extern Cube *func_8030364C(void); -extern Cube *cubeList_GetCubeAtPosition_s32(s32 position[3]); +extern Cube *cube_atPosition_s32(s32 position[3]); extern f32 propModelList_getScale(Prop *); extern void propModelList_setScale(Prop *, f32); @@ -120,7 +118,7 @@ BKCollisionTriangle *D_80383420; u8 D_80383428[MARKER_BITMAP_BYTES]; s32 D_80383444; int D_80383448; -s32 D_80383450[CUBE_SORT_SCRATCH_SIZE]; +s32 D_80383450[0x40]; bk_vector(ActorMarker *) *D_80383550; bk_vector(ActorMarker *) *D_80383554; Method_Core2_A5BC0 D_80383558; @@ -139,11 +137,6 @@ void __cube_sort(Cube *cube, bool global) { s32 i; Prop *new_var; - // [port] Sorting is only draw order; skip rather than overrun the scratch. - if (cube->prop2Cnt > CUBE_SORT_SCRATCH_SIZE) { - return; - } - if (cube->prop2Cnt >= 2) { if (global == 0) { viewport_getPosition_vec3w(ref_position); //distance from viewport @@ -162,9 +155,6 @@ void __cube_sort(Cube *cube, bool global) { } //sort prop list - // [port] Cancelled by PerfPatches.cpp, which sorts the same distances - // with a stable insertion sort instead of this exchange sort. - if (EventSystem_Should(VB_CUBE_PROP_SORT, true, cube)) { start_prop = cube->prop2Ptr; var_t0 = cube->prop2Ptr + (cube->prop2Cnt - 1); do { @@ -203,7 +193,6 @@ void __cube_sort(Cube *cube, bool global) { i++; } } while (start_prop != NULL); - } code_A5BC0_initCubePropActorProp(cube); } } @@ -286,7 +275,8 @@ void func_8032CD60(Prop *prop) { } else { sp3C = prop->spriteProp.isMirrored; } - if (1) break; + if (1); + break; } break; @@ -324,7 +314,7 @@ static void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx){ f32 draw_dist_f; f32 percentage; - FrameInterpolation_RecordOpenChildHash3("marker", (uintptr_t)this, (uintptr_t)this->actrArrayIdx, 0); + FrameInterpolation_RecordOpenChild(this, this->actrArrayIdx); if(!this->unk3E_0){ this->drawFunc(this, gfx, mtx, vtx); @@ -374,19 +364,17 @@ void func_8032D3A8(void){ bk_vector_clear(D_80383554); } -void core2_A5BC0_drawUnknownMarkers(Gfx **gfx, Mtx **mtx, Vtx **vtx) { // further investigation needed what's drawn here +void func_8032D3D8(Gfx **gdl, Mtx **mptr, Vtx **vptr){ int i; - - for (i = 0; i < bk_vector_size(D_80383550); i++) { - __marker_draw(*(ActorMarker **) bk_vector_at(D_80383550, i), gfx, mtx, vtx); + for(i = 0; i < bk_vector_size(D_80383550); i++){ + __marker_draw(*(ActorMarker **) bk_vector_at(D_80383550, i), gdl, mptr, vptr); } } -void core2_A5BC0_drawScreenOverlayMarkers(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void func_8032D474(Gfx **gdl, Mtx **mptr, Vtx **vptr){ int i; - - for (i = 0; i < bk_vector_size(D_80383554); i++) { - __marker_draw(*(ActorMarker **) bk_vector_at(D_80383554, i), gfx, mtx, vtx); + for(i = 0; i < bk_vector_size(D_80383554); i++){ + __marker_draw(*(ActorMarker **) bk_vector_at(D_80383554, i), gdl, mptr, vptr); } } @@ -521,20 +509,14 @@ s32 func_8032D9C0(Cube *cube, Prop* prop){ s32 tmp; sp24 = 0; - if(cube != NULL && cube->prop2Cnt != 0 && prop != NULL && cube->prop2Ptr != NULL){ - ptrdiff_t index = prop - cube->prop2Ptr; - // [port] A stale propPtr makes elementsAfter enormous; drop the removal instead. - if (index < 0 || index >= (ptrdiff_t)cube->prop2Cnt) { - port_warnPropNotInCube((s32)index, (s32)cube->prop2Cnt); - return sp24; - } - + if(cube->prop2Cnt != 0){ sp24 = prop->unk8_1; if(func_80305D14()){ func_80305CD8(func_803058C0(prop->unk4[1]), -1); } // port - Rando manipulation of prop2Ptr results in mismatched data, this corrects that. + ptrdiff_t index = prop - cube->prop2Ptr; ptrdiff_t elementsAfter = (cube->prop2Cnt - 1) - index; if (elementsAfter > 0) { memmove(prop, prop + 1, elementsAfter * sizeof(Prop)); @@ -957,11 +939,6 @@ static void __codeA5BC0_initPropPointerForCube(NodeProp *node, Cube *cube, s32 c } } - // [port] unk0_4 is the front index of this partition; :5 wrapped it here. - if(cube->unk0_4 > 31){ - port_warnNodePropSplit(cube->unk0_4, cnt); - } - bk_free(node); for(i = 0; i < cnt; i++){ @@ -1022,9 +999,6 @@ void code7AF80_initCubeFromFile(File *file_ptr, Cube *cube) { // bitfield structs across endianness boundaries. if (file_isNextByteExpected(file_ptr, CUBE_PROP_2_LIST_START_INDICATOR)) { s32 i; - // [port] A vetoed prop must not keep its slot. Compact - // instead, writing only the props we keep. - s32 writeIdx = 0; memset(cube->prop2Ptr, 0, sp47 * sizeof(Prop)); for (i = 0; i < sp47; i++) { u8 raw[12]; @@ -1055,60 +1029,58 @@ void code7AF80_initCubeFromFile(File *file_ptr, Cube *cube) { bool b4 = (flags >> 4) & 1; // unk8_4 bool b5 = (flags >> 5) & 1; // unk8_5 // Set position and flags via anonymous struct - cube->prop2Ptr[writeIdx].unk4[0] = pos[0]; - cube->prop2Ptr[writeIdx].unk4[1] = pos[1]; - cube->prop2Ptr[writeIdx].unk4[2] = pos[2]; - cube->prop2Ptr[writeIdx].markerFlag = mf; - cube->prop2Ptr[writeIdx].unk8_1 = b1; - cube->prop2Ptr[writeIdx].unk8_2 = b2; - cube->prop2Ptr[writeIdx].unk8_3 = b3; - cube->prop2Ptr[writeIdx].unk8_4 = b4; - cube->prop2Ptr[writeIdx].unk8_5 = b5; + cube->prop2Ptr[i].unk4[0] = pos[0]; + cube->prop2Ptr[i].unk4[1] = pos[1]; + cube->prop2Ptr[i].unk4[2] = pos[2]; + cube->prop2Ptr[i].markerFlag = mf; + cube->prop2Ptr[i].unk8_1 = b1; + cube->prop2Ptr[i].unk8_2 = b2; + cube->prop2Ptr[i].unk8_3 = b3; + cube->prop2Ptr[i].unk8_4 = b4; + cube->prop2Ptr[i].unk8_5 = b5; if (mf) { // ActorProp: marker=NULL (set at actor spawn), position - cube->prop2Ptr[writeIdx].actorProp.marker = NULL; - cube->prop2Ptr[writeIdx].actorProp.x = pos[0]; - cube->prop2Ptr[writeIdx].actorProp.y = pos[1]; - cube->prop2Ptr[writeIdx].actorProp.z = pos[2]; + cube->prop2Ptr[i].actorProp.marker = NULL; + cube->prop2Ptr[i].actorProp.x = pos[0]; + cube->prop2Ptr[i].actorProp.y = pos[1]; + cube->prop2Ptr[i].actorProp.z = pos[2]; // SpriteProp unk8_10/unk8_15 overlap anonymous pad8_15 - cube->prop2Ptr[writeIdx].actorProp.frame = (flags >> 11) & 0x1F; - cube->prop2Ptr[writeIdx].actorProp.unk8_10 = (flags >> 6) & 0x1F; + cube->prop2Ptr[i].actorProp.frame = (flags >> 11) & 0x1F; + cube->prop2Ptr[i].actorProp.unk8_10 = (flags >> 6) & 0x1F; } else if (b1) { // ModelProp: word0 = { u16 unk0, u8 unk0_15, u8 unk0_7 } // [port] Set through bitfield accessor, not raw u16, for LE correctness - cube->prop2Ptr[writeIdx].modelProp.modelId = (word0 >> 20) & 0xFFF; - cube->prop2Ptr[writeIdx].modelProp.pad0_19 = (word0 >> 16) & 0xF; - cube->prop2Ptr[writeIdx].modelProp.yaw = (u8)(word0 >> 8); - cube->prop2Ptr[writeIdx].modelProp.roll = (u8)(word0); + cube->prop2Ptr[i].modelProp.modelId = (word0 >> 20) & 0xFFF; + cube->prop2Ptr[i].modelProp.pad0_19 = (word0 >> 16) & 0xF; + cube->prop2Ptr[i].modelProp.yaw = (u8)(word0 >> 8); + cube->prop2Ptr[i].modelProp.roll = (u8)(word0); // ModelProp flags at offset 10-11 - cube->prop2Ptr[writeIdx].modelProp.scale = (u8)(flags >> 8); - cube->prop2Ptr[writeIdx].modelProp.unkB_5 = (flags >> 5) & 1; - cube->prop2Ptr[writeIdx].modelProp.unkB_4 = (flags >> 4) & 1; + cube->prop2Ptr[i].modelProp.scale = (u8)(flags >> 8); + cube->prop2Ptr[i].modelProp.unkB_5 = (flags >> 5) & 1; + cube->prop2Ptr[i].modelProp.unkB_4 = (flags >> 4) & 1; } else { // SpriteProp: word0 is a u32 with bitfields - cube->prop2Ptr[writeIdx].spriteProp.spriteId = (word0 >> 20) & 0xFFF; - cube->prop2Ptr[writeIdx].spriteProp.unk0_19 = (word0 >> 19) & 1; - cube->prop2Ptr[writeIdx].spriteProp.rgb_remove_red = (word0 >> 16) & 7; - cube->prop2Ptr[writeIdx].spriteProp.rgb_remove_green = (word0 >> 13) & 7; - cube->prop2Ptr[writeIdx].spriteProp.rgb_remove_blue = (word0 >> 10) & 7; - cube->prop2Ptr[writeIdx].spriteProp.scale = (word0 >> 2) & 0xFF; - cube->prop2Ptr[writeIdx].spriteProp.isMirrored = (word0 >> 1) & 1; - cube->prop2Ptr[writeIdx].spriteProp.pad0_0 = word0 & 1; + cube->prop2Ptr[i].spriteProp.spriteId = (word0 >> 20) & 0xFFF; + cube->prop2Ptr[i].spriteProp.unk0_19 = (word0 >> 19) & 1; + cube->prop2Ptr[i].spriteProp.rgb_remove_red = (word0 >> 16) & 7; + cube->prop2Ptr[i].spriteProp.rgb_remove_green = (word0 >> 13) & 7; + cube->prop2Ptr[i].spriteProp.rgb_remove_blue = (word0 >> 10) & 7; + cube->prop2Ptr[i].spriteProp.scale = (word0 >> 2) & 0xFF; + cube->prop2Ptr[i].spriteProp.isMirrored = (word0 >> 1) & 1; + cube->prop2Ptr[i].spriteProp.pad0_0 = word0 & 1; // SpriteProp flags - cube->prop2Ptr[writeIdx].spriteProp.frame = (flags >> 11) & 0x1F; - cube->prop2Ptr[writeIdx].spriteProp.unk8_10 = (flags >> 6) & 0x1F; + cube->prop2Ptr[i].spriteProp.frame = (flags >> 11) & 0x1F; + cube->prop2Ptr[i].spriteProp.unk8_10 = (flags >> 6) & 0x1F; } } //Prop* ptr = cube->prop2Ptr + i * sizeof(Prop); - CALL_EVENT(OnPropInit, &cube->prop2Ptr[writeIdx]); - writeIdx++; + CALL_EVENT(OnPropInit, &cube->prop2Ptr[i]); } } - cube->prop2Cnt = writeIdx; } - for(var_v1_2 = cube->prop2Ptr; var_v1_2 < cube->prop2Ptr + cube->prop2Cnt; var_v1_2++){ + for(var_v1_2 = cube->prop2Ptr; var_v1_2 < cube->prop2Ptr + sp47; var_v1_2++){ var_v1_2->unk8_4 = 1; if (var_v1_2->unk8_1) { var_v1_2->unk8_5 = 0; @@ -1248,7 +1220,7 @@ void func_8032F21C(Cube *cube, s32 position[3], ActorMarker *marker, bool arg3) } void func_8032F3D4(s32 arg0[3], ActorMarker *marker, s32 arg2){ - func_8032F21C((marker->unk40_23)? func_8030364C() : cubeList_GetCubeAtPosition_s32(arg0), arg0, marker, arg2); + func_8032F21C((marker->unk40_23)? func_8030364C() : cube_atPosition_s32(arg0), arg0, marker, arg2); } void marker_free(ActorMarker *this){ @@ -1263,7 +1235,7 @@ void func_8032F464(bool arg0){ void func_8032F470(s32 *pos, ActorMarker *arg1){ Cube *cubePtr; - cubePtr = (arg1->unk40_23)? func_8030364C(): cubeList_GetCubeAtPosition_s32(pos); + cubePtr = (arg1->unk40_23)? func_8030364C(): cube_atPosition_s32(pos); if(cubePtr == arg1->cubePtr){ arg1->propPtr->x = pos[0]; @@ -1813,7 +1785,7 @@ BKSpriteDisplayData *func_80330E54(ActorMarker *marker, BKSprite **sprite_ptr) { return 0; } model_cache_ptr = &modelCache[marker_getActor(marker)->modelCacheIndex]; - if (model_cache_ptr->unk4 == 00 || marker->id == MARKER_300_CUSTOM_COLLECTIBLE) { + if (model_cache_ptr->unk4 == 0) { model_cache_ptr->unk4 = codeB3A80_getSprite(marker->modelId, &model_cache_ptr->unk8); } model_cache_ptr->unk10 = globalTimer_getTime(); @@ -1833,19 +1805,19 @@ BKSprite *func_80330F50(ActorMarker * marker){ return sp1C; } -s32 codeA5BC0_getNodePropMarkerId(NodeProp *arg0){ +s32 codeA5BC0_getNodePropUnkA(NodeProp *arg0){ return arg0->unkA; //marker_id } -s32 codeA5BC0_getNodePropCategory(NodeProp *arg0){ +s32 codeA5BC0_getNodePropBit6(NodeProp *arg0){ return arg0->bit6; } -s32 codeA5BC0_getNodePropActorId(NodeProp *arg0){ +s32 codeA5BC0_getNodePropUnk8(NodeProp *arg0){ return arg0->unk8; } -s32 codeA5BC0_getPositionAndSelectorOrRadius(void *arg0_, s32 arg1[3]){ +s32 codeA5BC0_getPositionAndReturnRadius(void *arg0_, s32 arg1[3]){ NodeProp *arg0 = (NodeProp *)arg0_; arg1[0] = arg0->x; arg1[1] = arg0->y; @@ -2231,9 +2203,6 @@ f32 func_80331E64(ActorMarker *marker) { if (marker->modelId == 0) { return 0.0f; } - if (marker->id == MARKER_300_CUSTOM_COLLECTIBLE) { - return 150.0f; - } sp24 = func_80331D20(func_80330F50(marker)); marker->unk38[1] = (s16) (sp24 / 2); if (marker->unk3E_0) { @@ -2457,8 +2426,8 @@ void func_80332894(void) { s32 size; s32 i; - size = VER_SELECT(0x579, 0x391, 0, 0); - D_8036E7C4 = malloc(size); + size = 0x579; + D_8036E7C4 = bk_malloc(size); i = 0; do{ D_8036E7C4[i] = 0; diff --git a/src/core2/actor_motioncurve.c b/src/core2/actor_motioncurve.c index eb3518980..a914ff3a3 100644 --- a/src/core2/actor_motioncurve.c +++ b/src/core2/actor_motioncurve.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_EF50.c #include #include "functions.h" #include "variables.h" @@ -83,15 +82,15 @@ enum bs_e func_80295EE0(enum bs_e arg0){ enum bs_e __get_rebound_state_id(void){ switch(bsStoredState_getTransformation()){ case TRANSFORM_3_PUMPKIN:// L8029606C - return BS_A0_ANT_BOUNCE; + return BS_PUMPKIN_BOUNCE; case TRANSFORM_2_TERMITE:// L80296074 - return BS_9F_ANT_BOUNCE; + return BS_ANT_BOUNCE; case TRANSFORM_5_CROC:// L8029607C - return BS_A1_CROC_BOUNCE; + return BS_CROC_BOUNCE; case TRANSFORM_4_WALRUS:// L80296084 - return BS_A2_WALRUS_BOUNCE; + return BS_WALRUS_BOUNCE; case TRANSFORM_6_BEE:// L8029608C - return BS_A3_BEE_BOUNCE; + return BS_BEE_BOUNCE; case TRANSFORM_1_BANJO:// L80296094 default: if(player_movementGroup() == BSGROUP_A_FLYING) @@ -148,7 +147,7 @@ void func_8029622C(void){ f32 sp34[3]; f32 sp28[3]; - playerPosition_get(sp28); + _player_getPosition(sp28); func_80256E24(sp34, 0.0f, yaw_get(), 0.0f, 0.0f, 100.0f); sp28[0] += sp34[0]; sp28[1] += sp34[1]; @@ -176,29 +175,29 @@ enum bs_e func_802962BC(u32 arg0){ return BS_4E_PUMPKIN_DIE; case TRANSFORM_5_CROC: //L80296344 if(sp1C) - return BS_63_CROC_OW; + return BS_CROC_OW; else - return BS_63_CROC_OW; + return BS_CROC_OW; case TRANSFORM_4_WALRUS: //L8029635C if(sp1C) - return BS_6C_WALRUS_OW; + return BS_WALRUS_OW; else - return BS_6D_WALRUS_DIE; + return BS_WALRUS_DIE; case TRANSFORM_6_BEE: //L80296374 if(sp1C) - return BS_89_BEE_OW; - return BS_8A_BEE_DIE; + return BS_BEE_OW; + return BS_BEE_DIE; case TRANSFORM_1_BANJO: //L8029638C default: if(sp1C){ if(bsbtrot_inSet(bs_getState())) - return BS_7B_BTROT_OW; + return BS_BTROT_OW; if(player_getWaterState() == BSWATERGROUP_2_UNDERWATER) return BS_7F_DIVE_OW; if(player_movementGroup() == BSGROUP_A_FLYING) - return BS_91_FLY_OW; + return BS_FLY_OW; return BS_E_OW; } return BS_41_DIE; @@ -428,10 +427,7 @@ void func_80296608(void){ break; case BS_INTR_35: //L80296984 baflag_set(BA_FLAG_1A_OPEN_NOTEDOOR); - // The dance masks the fall/land this normally forces; when it's skipped - // (listener clears the flag here), leave the state unchanged so Banjo keeps moving. - if(EventSystem_Should(VB_PLAY_NOTEDOOR_DANCE, true)) - next_state = func_8029B504(); + next_state = func_8029B504(); sp2C = 2; break; case BS_INTR_34: //L802969A4 diff --git a/src/core2/actor_updatestub.c b/src/core2/actor_updatestub.c index d9717b32e..7a58ba2f1 100644 --- a/src/core2/actor_updatestub.c +++ b/src/core2/actor_updatestub.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_4BE10.c #include #include "functions.h" #include "variables.h" @@ -7,23 +6,13 @@ void func_802D2DA0(Actor *this); /* .data */ ActorInfo D_803675F0 = { - MARKER_16_UNKNOWN, ACTOR_6A_UNKNOWN, 0x0, + 0x16, 0x6A, 0x0, 0x1, NULL, func_802D2DA0, func_80326244, func_80325340, 0, 0, 0.0f, 0 }; - s16 D_80367614[] = {3,2,3,4,3,5,3,0}; - -ParticleScaleAndLifetimeRanges D_80367624 = { - {0.7f, 0.3f}, // particle_starting_scale_range - {0.01f, 0.01f}, // particle_starting_scale_range - {0.05f, 0.05f}, // particle_spawn_interval_range - {0.2f, 0.2f}, // particle_lifetime_range - 0.0f, // particle_fade_in - 0.01f // particle_fade_in -}; - +ParticleScaleAndLifetimeRanges D_80367624 = {{0.7f, 0.3f}, {0.01f, 0.01f}, {0.05f, 0.05f}, {0.2f, 0.2f}, 0.0f, 0.01f}; ParticleSettingsVelocityPosition D_8036764C = { {{-100.0f, 400.0f, -100.0f}, { 100.0f, 800.0f, 100.0f}}, {{-100.0f, 0.0f, -100.0f}, { 100.0f, 0.0f, 100.0f}} diff --git a/src/core2/anim/anim_bonetransform.c b/src/core2/anim/anim_bonetransform.c index f9a2d5f62..6cda545db 100644 --- a/src/core2/anim/anim_bonetransform.c +++ b/src/core2/anim/anim_bonetransform.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B3A80.c #include #include "functions.h" #include "variables.h" @@ -231,13 +230,8 @@ void func_8033B1BC(void){ } void func_8033B268(void){ -#if VERSION == VERSION_USA_1_0 D_80383CE0[0] = (bk_vector(struct21s) *)defrag(D_80383CE0[0]); D_80383CE0[1] = (bk_vector(struct21s) *)defrag(D_80383CE0[1]); -#else - D_80383CE0[0] = (bk_vector(struct21s) *)bk_vector_defrag(D_80383CE0[0]); - D_80383CE0[1] = (bk_vector(struct21s) *)bk_vector_defrag(D_80383CE0[1]); -#endif } void func_8033B2A4(s32 arg0) { diff --git a/src/core2/anim/anim_buffer.c b/src/core2/anim/anim_buffer.c index 563e0aeca..97b3f4933 100644 --- a/src/core2/anim/anim_buffer.c +++ b/src/core2/anim/anim_buffer.c @@ -1,7 +1,5 @@ -// BanjoDecomp: core2/code_2240.c #include #include "functions.h" -#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "animation.h" diff --git a/src/core2/anim/animcache.c b/src/core2/anim/anim_cache.c similarity index 98% rename from src/core2/anim/animcache.c rename to src/core2/anim/anim_cache.c index ee7d459d5..b617f2341 100644 --- a/src/core2/anim/animcache.c +++ b/src/core2/anim/anim_cache.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/animcache.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anim_defrag.c b/src/core2/anim/anim_defrag.c index 33b82d692..a700817d9 100644 --- a/src/core2/anim/anim_defrag.c +++ b/src/core2/anim/anim_defrag.c @@ -1,7 +1,5 @@ -// BanjoDecomp: core2/code_630D0.c #include #include "functions.h" -#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "animation.h" @@ -33,7 +31,7 @@ MtxF *animMtxList_get(AnimMtxList *this, s32 arg1){ } // [port] bounds check - on N64 this never happens but corrupt data can cause OOB if (arg1 < 0 || arg1 >= this->size) { - BK_LOG_WARN("animMtxList_get: OOB index %d (size=%d)", arg1, this->size); + BK_LOG_WARN("[port] animMtxList_get: OOB index %d (size=%d)", arg1, this->size); return &this->default_matrix; // fallback to identity } return &this->data[arg1]; diff --git a/src/core2/anim/anim_driver.c b/src/core2/anim/anim_driver.c index 7baf7ebe9..fdba789b0 100644 --- a/src/core2/anim/anim_driver.c +++ b/src/core2/anim/anim_driver.c @@ -1,88 +1,66 @@ -// BanjoDecomp: core2/code_DA760.c #include #include "functions.h" #include "variables.h" -void lairBottlesDialog_update(Actor *this); +void func_80361870(Actor *this); /* .data */ -ActorInfo lairBottlesDialog = { +ActorInfo D_803731B0 = { 0x1E4, 0x373, 0, 0, NULL, - lairBottlesDialog_update, actor_update_func_80326224, func_80325340, + func_80361870, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 -}; - -enum lairbottlesdialog_specificfield_e { - LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_1_MM = 1, - LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_2_TTC, - LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_3_CC, - LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_4_BGS, - LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_5_FP, - LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_6_GV -}; +}; /* .code */ -bool lairBottlesDialog_levelOpenedAndNotLearnedAllMoves(Actor *this){ +int func_803616F0(Actor *this){ switch(this->actorTypeSpecificField){ - case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_1_MM:// L80361728 + case 1:// L80361728 return fileProgressFlag_get(FILEPROG_31_MM_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_1_MUMBOS_MOUNTAIN); - case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_2_TTC:// L80361750 + case 2:// L80361750 return fileProgressFlag_get(FILEPROG_32_TTC_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_2_TREASURE_TROVE_COVE); - case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_3_CC:// L80361778 + case 3:// L80361778 return fileProgressFlag_get(FILEPROG_33_CC_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_3_CLANKERS_CAVERN); - case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_4_BGS:// L803617A0 + case 4:// L803617A0 return fileProgressFlag_get(FILEPROG_34_BGS_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_4_BUBBLEGLOOP_SWAMP); - case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_5_FP:// L803617C8 + case 5:// L803617C8 return fileProgressFlag_get(FILEPROG_35_FP_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_5_FREEZEEZY_PEAK); - case LAIR_BOTTLES_DIALOG_SPECIFIC_FIELD_6_GV:// L803617F0 + case 6:// L803617F0 return fileProgressFlag_get(FILEPROG_36_GV_OPEN) && !chmole_learnedAllLevelAbilities(LEVEL_7_GOBIS_VALLEY); default: return false; } } -void lairBottlesDialog_free(Actor *this){ - if(volatileFlag_get(VOLATILE_FLAG_16) - && level_get() == LEVEL_6_LAIR) - { +void func_80361828(Actor *this){ + if(volatileFlag_get(VOLATILE_FLAG_16) && level_get() == LEVEL_6_LAIR){ volatileFlag_set(VOLATILE_FLAG_16, 0); } } -void lairBottlesDialog_update(Actor *this){ - s32 podium_text_id; - s32 didnt_learn_moves_text_id; +void func_80361870(Actor *this){ + s32 text_id; + s32 sp28; if(!this->volatile_initialized){ - marker_setFreeMethod(this->marker, lairBottlesDialog_free); - this->volatile_initialized = TRUE; + marker_setFreeMethod(this->marker, func_80361828); + this->volatile_initialized = true; } - if(!this->has_met_before - && subaddie_playerIsWithinSphereAndActive(this, 400) - && !subaddie_playerIsWithinSphereAndActive(this, 50)) - { - if(this->actorTypeSpecificField == 1 - && !fileProgressFlag_get(FILEPROG_31_MM_OPEN) - && level_get() == LEVEL_6_LAIR) - { - podium_text_id = fileProgressFlag_get(FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT) ? - VER_SELECT(ASSET_F80_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_AFTER_PODIUM, 0x0AE6, 0, 0) : VER_SELECT(ASSET_F7F_DIALOG_BOTTLES_MM_ENTRANCE_BEFORE_OPENING_BEFORE_PODIUM, 0x0AE5, 0, 0); - if(gcdialog_showDialog(podium_text_id, 0, 0, 0, 0, 0)){ - this->has_met_before = TRUE; + if(!this->has_met_before && subaddie_playerIsWithinSphereAndActive(this, 400) && !subaddie_playerIsWithinSphereAndActive(this, 50)){ + if(this->actorTypeSpecificField == 1 && !fileProgressFlag_get(FILEPROG_31_MM_OPEN) && level_get() == LEVEL_6_LAIR){ + text_id = fileProgressFlag_get(FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT)? 0xF80 : 0xF7F; + if(gcdialog_showDialog(text_id, 0, 0, 0, 0, 0)){ + this->has_met_before = true; } } - else if(lairBottlesDialog_levelOpenedAndNotLearnedAllMoves(this)){ - didnt_learn_moves_text_id = (volatileFlag_get(VOLATILE_FLAG_16) ? VER_SELECT(ASSET_F6E_DIALOG_DIDNT_LEARN_ALL_MOVES_FROM_MM, 0xAD4, 0, 0) : VER_SELECT(ASSET_F68_DIALOG_MM_THREE_NEW_MOVES_TO_LEARN, 0x0ACE, 0, 0)) + this->actorTypeSpecificField - 1; - if(!volatileFlag_get(VOLATILE_FLAG_16) - && level_get() == LEVEL_6_LAIR) - { - this->has_met_before = TRUE; + else if(func_803616F0(this)){ + sp28 = (volatileFlag_get(VOLATILE_FLAG_16)?0xf6e:0xf68) + this->actorTypeSpecificField - 1; + if(!volatileFlag_get(VOLATILE_FLAG_16) && level_get() == LEVEL_6_LAIR){ + this->has_met_before = true; } - else{ - if(gcdialog_showDialog(didnt_learn_moves_text_id, 0, 0, 0, 0, 0)) - { - this->has_met_before = TRUE; + else{ + if(gcdialog_showDialog(sp28, 0, 0, 0, 0, 0)){ + this->has_met_before = true; volatileFlag_set(VOLATILE_FLAG_16, 0); } } diff --git a/src/core2/anim/anim_sequencehandler.c b/src/core2/anim/anim_sequencehandler.c index 77a79ed2d..f82bb92a9 100644 --- a/src/core2/anim/anim_sequencehandler.c +++ b/src/core2/anim/anim_sequencehandler.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_DAAA0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/anim/betavent.c b/src/core2/anim/anim_sequencestruct.c similarity index 88% rename from src/core2/anim/betavent.c rename to src/core2/anim/anim_sequencestruct.c index 823d85860..197d87cd7 100644 --- a/src/core2/anim/betavent.c +++ b/src/core2/anim/anim_sequencestruct.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/betavent.c #include #include "core1/core1.h" #include "functions.h" @@ -9,22 +8,22 @@ typedef struct { f32 unk4; } ActorLocal_Core2_DA3A0; -void chBetaVent_update(Actor *this); +void func_8036158C(Actor *this); /* .data */ u8 D_80373130[] = {0, 1, 0, 0}; -ActorInfo chBetaVent1 = { - MARKER_1A6_BETA_VENT, ACTOR_289_BETA_VENT, ASSET_431_MODEL_BETA_VENT, +ActorInfo D_80373134 = { + 0x1a6, 0x289, 0x431, 0x0, NULL, - chBetaVent_update, NULL, actor_draw, + func_8036158C, NULL, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chBetaVent2 = { - MARKER_1A6_BETA_VENT, ACTOR_28F_BETA_VENT, ASSET_431_MODEL_BETA_VENT, +ActorInfo D_80373158 = { + 0x1a6, 0x28f, 0x431, 0x0, NULL, - chBetaVent_update, NULL, actor_draw, + func_8036158C, NULL, actor_draw, 0, 0, 0.0f, 0 }; @@ -77,7 +76,7 @@ void func_80361330(Actor *this, s32 next_state){ this->state = next_state; } -void chBetaVent_update(Actor *this){ +void func_8036158C(Actor *this){ ActorLocal_Core2_DA3A0 *local = (ActorLocal_Core2_DA3A0 *)&this->local; f32 sp30; f32 sp24[3]; diff --git a/src/core2/anim/chumpfish.c b/src/core2/anim/anim_spriteframe.c similarity index 99% rename from src/core2/anim/chumpfish.c rename to src/core2/anim/anim_spriteframe.c index ca6bdc710..92872bd6c 100644 --- a/src/core2/anim/chumpfish.c +++ b/src/core2/anim/anim_spriteframe.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/chumpfish.c #include #include "functions.h" #include "variables.h" @@ -28,7 +27,7 @@ ActorAnimationInfo D_80372EA0[] = { {0x2C0, 1.5f} }; -ActorInfo chChumpFish = { +ActorInfo D_80372EE0 = { MARKER_69_CHUMP_FISH, ACTOR_A_CHUMP_FISH, ASSET_36B_CHUMP_FISH, 0x2, D_80372EA0, chchumpfish_update, actor_update_func_80326224, actor_draw, diff --git a/src/core2/anim/animtexturecache.c b/src/core2/anim/anim_texturecache.c similarity index 98% rename from src/core2/anim/animtexturecache.c rename to src/core2/anim/anim_texturecache.c index 268aa0270..306efc82c 100644 --- a/src/core2/anim/animtexturecache.c +++ b/src/core2/anim/anim_texturecache.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/animtexturecache.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/bonetransformlist.c b/src/core2/anim/bonetransformlist.c index 1465fbc12..011bc75a4 100644 --- a/src/core2/anim/bonetransformlist.c +++ b/src/core2/anim/bonetransformlist.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B3580.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anctrl.c b/src/core2/anim/controller.c similarity index 99% rename from src/core2/anim/anctrl.c rename to src/core2/anim/controller.c index 0f6a95404..ddfe5013a 100644 --- a/src/core2/anim/anctrl.c +++ b/src/core2/anim/controller.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/anctrl.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/anseq.c b/src/core2/anim/sequence.c similarity index 99% rename from src/core2/anim/anseq.c rename to src/core2/anim/sequence.c index cd53ced72..b686aaba4 100644 --- a/src/core2/anim/anseq.c +++ b/src/core2/anim/sequence.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/anseq.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/skeletalanim.c b/src/core2/anim/skeletal.c similarity index 99% rename from src/core2/anim/skeletalanim.c rename to src/core2/anim/skeletal.c index 493db4e50..04cbd309f 100644 --- a/src/core2/anim/skeletalanim.c +++ b/src/core2/anim/skeletal.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/skeletalanim.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/anim/sprite.c b/src/core2/anim/sprite.c index 778bbd349..eb0542a28 100644 --- a/src/core2/anim/sprite.c +++ b/src/core2/anim/sprite.c @@ -3,11 +3,11 @@ #include "functions.h" #include "variables.h" -#include "checksums.h" /* .bss */ +u8 D_80379B90[0x10]; static AnimSprite s_animsprite_list[40]; /* .code */ diff --git a/src/core2/ba/anim.c b/src/core2/ba/ba_anim.c similarity index 88% rename from src/core2/ba/anim.c rename to src/core2/ba/ba_anim.c index c0fe50101..a96e5912d 100644 --- a/src/core2/ba/anim.c +++ b/src/core2/ba/ba_anim.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/anim.c #include #include "functions.h" #include "variables.h" @@ -75,67 +74,60 @@ void __baanim_oscillateScale(f32 dst[3], f32 x, f32 min, f32 osc_size) { }; } -void baanim_applyBottlesBonusMask(uintptr_t arg0, s32 mask) { +void __baanim_applyBottlesBonus(uintptr_t arg0, uintptr_t arg1) { f32 scale[3]; - f32 sp28 = func_802E4B38(); + f32 sp28; + s32 phi_s0; + static s32 D_8037BF4C; + - if (mask & 1) {//either big hands or big feet + sp28 = func_802E4B38(); + if (volatileFlag_get(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS) == 0) { + D_8037BF4C = 0; + } else { + for(phi_s0 = 0; phi_s0 < 7; phi_s0++){ + if (volatileFlag_get(phi_s0 + VOLATILE_FLAG_97_SANDCASTLE_BOTTLES_BONUS_1)) { + D_8037BF4C = D_803635EC[phi_s0]; + } + } + } + if ((D_8037BF4C & 1)) {//either big hands or big feet __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 6, scale); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x14, scale); } - if (mask & 2) {//either big hands or big feet + if (D_8037BF4C & 2) {//either big hands or big feet __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x10, scale); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x1E, scale); } - if (mask & BAANIM_BIGHEAD) { + if (D_8037BF4C & BAANIM_BIGHEAD) { __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x12, scale); } - if (mask & BAANIM_SMALLHEAD) { + if (D_8037BF4C & BAANIM_SMALLHEAD) { __baanim_oscillateScale(scale, sp28, 0.2f, 0.5f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x12, scale); } - if (mask & BAANIM_LONGBODY) { + if (D_8037BF4C & BAANIM_LONGBODY) { func_8033A968((BoneTransformList *)arg0, 1, D_803635E0); } - if (mask & BAANIM_BIGKAZOOIEHEAD) { + if (D_8037BF4C & BAANIM_BIGKAZOOIEHEAD) { __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x6C, scale); } - if (mask & BAANIM_BIGWINGS) { + if (D_8037BF4C & BAANIM_BIGWINGS) { __baanim_oscillateScale(scale, sp28, 2.0f, 1.0f); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x64, scale); boneTransformList_setBoneScale((BoneTransformList *)arg0, 0x67, scale); } -} - -s32 baanim_getActiveBottlesBonusMask(void) { - s32 mask = 0; - s32 i; - - if (volatileFlag_get(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS) == 0) { - return 0; - } - for (i = 0; i < 7; i++) { - if (volatileFlag_get(i + VOLATILE_FLAG_97_SANDCASTLE_BOTTLES_BONUS_1)) { - mask = D_803635EC[i]; + if (gsworld_getMap() == MAP_A_TTC_SANDCASTLE) { + if ((D_8037BF4C & BAANIM_WISHYWASHY) && (player_getTransformation() != TRANSFORM_7_WISHWASHY)) { + func_8028FB88(TRANSFORM_7_WISHWASHY); + } + if (!(D_8037BF4C & BAANIM_WISHYWASHY) && (player_getTransformation() == TRANSFORM_7_WISHWASHY)) { + func_8028FB88(TRANSFORM_1_BANJO); } - } - return mask; -} - -void __baanim_applyBottlesBonus(uintptr_t arg0, uintptr_t arg1) { - s32 mask = baanim_getActiveBottlesBonusMask(); - - baanim_applyBottlesBonusMask(arg0, mask); - - if ((mask & BAANIM_WISHYWASHY) && (player_getTransformation() == TRANSFORM_1_BANJO)) { - player_transform(TRANSFORM_7_WISHWASHY); - } - if (!(mask & BAANIM_WISHYWASHY) && (player_getTransformation() == TRANSFORM_7_WISHWASHY)) { - player_transform(TRANSFORM_1_BANJO); } if (baAnimModifyFunction != NULL) { baAnimModifyFunction(arg0, arg1); @@ -237,7 +229,7 @@ void baanim_setUpdateType(enum baanim_update_type_e arg0){ void baanim_80289F30(void){ f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); anctrl_drawSetup(playerAnimCtrl, sp1C, 1); } @@ -278,7 +270,7 @@ void baanim_playForDuration_loop(enum asset_e anim_id, f32 duration){ anctrl_start(playerAnimCtrl, "baanim.c", 0x193); } -void baanim_playForDuration_loopSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ +void baanim_playForDuration_loopStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ anctrl_reset(playerAnimCtrl); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); @@ -287,15 +279,17 @@ void baanim_playForDuration_loopSmoothStartingAt(enum asset_e anim_id, f32 durat anctrl_start(playerAnimCtrl, "baanim.c", 0x19e); } -void baanim_playForDuration_onceSmooth(enum asset_e anim_id, f32 duration){ +void baanim_playForDuration_once(enum asset_e anim_id, f32 duration){ anctrl_reset(playerAnimCtrl); + // [port] smooth should be off, isn't in decomp + anctrl_setSmoothTransition(playerAnimCtrl, false); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); anctrl_setPlaybackType(playerAnimCtrl, ANIMCTRL_ONCE); anctrl_start(playerAnimCtrl, "baanim.c", 0x1a8); } -void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ +void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ anctrl_reset(playerAnimCtrl); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); @@ -304,16 +298,17 @@ void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 durat anctrl_start(playerAnimCtrl, "baanim.c", 0x1b3); } -void baanim_playForDuration_once(enum asset_e anim_id, f32 duration){ +void baanim_playForDuration_onceSmooth(enum asset_e anim_id, f32 duration){ anctrl_reset(playerAnimCtrl); - anctrl_setSmoothTransition(playerAnimCtrl, false); + // [port] possible decomp/src bug? smooth should be on here, and off above + // anctrl_setSmoothTransition(playerAnimCtrl, false); anctrl_setIndex(playerAnimCtrl, anim_id); anctrl_setDuration(playerAnimCtrl, duration); anctrl_setPlaybackType(playerAnimCtrl, ANIMCTRL_ONCE); anctrl_start(playerAnimCtrl, "baanim.c", 0x1bd); } -void baanim_playForDuration_onceStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ +void baanim_playForDuration_onceSmoothStartingAt(enum asset_e anim_id, f32 duration, f32 start_position){ anctrl_reset(playerAnimCtrl); anctrl_setSmoothTransition(playerAnimCtrl, false); anctrl_setIndex(playerAnimCtrl, anim_id); diff --git a/src/core2/ba/ba_animcache.c b/src/core2/ba/ba_animcache.c index feebc996a..ee2f4f126 100644 --- a/src/core2/ba/ba_animcache.c +++ b/src/core2/ba/ba_animcache.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_1550.c /** * @file anim/commoncache.c * @brief This file controls a cache of common animations consisting of diff --git a/src/core2/ba/ba_animstate.c b/src/core2/ba/ba_animstate.c new file mode 100644 index 000000000..9b5527b17 --- /dev/null +++ b/src/core2/ba/ba_animstate.c @@ -0,0 +1,197 @@ +#include +#include "functions.h" +#include "variables.h" + +void func_8029E070(bool); +void func_8029E064(bool); +void func_8029E058(bool); +void func_8029E0C4(f32); +void func_8029E0D0(f32); +void func_8029E0DC(bool); +void func_8029E0F4(bool); +void func_8029E0E8(bool); + +/* .bss */ +f32 D_8037D230; +u8 D_8037D234; +u8 D_8037D235; +u8 D_8037D236; +u8 D_8037D237; +u8 D_8037D238; +u8 D_8037D239; +u8 D_8037D23A; +f32 D_8037D23C; +f32 D_8037D240; + +/* .code */ +void func_8029DBF0(void){ + s32 temp_s0; + switch(baModel_getModelId()){ + case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: //L8029DC24 + case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: //L8029DC24 + temp_s0 = (s32) ml_interpolate_f(D_8037D23C, 1.0f, 8.0f); + func_8033A45C(0x1B, temp_s0); + func_8033A45C(0x1D, temp_s0); + func_8033A45C(0x1F, temp_s0); + func_8033A45C(0x21, temp_s0); + temp_s0 = (s32) ml_interpolate_f(D_8037D240, 1.0f, 8.0f); + func_8033A45C(0x1A, temp_s0); + func_8033A45C(0x1C, temp_s0); + func_8033A45C(0x1E, temp_s0); + func_8033A45C(0x20, temp_s0); + break; + + case ASSET_34F_MODEL_BANJO_TERMITE: //L8029DCCC + case ASSET_359_MODEL_BANJO_WALRUS: //L8029DCCC + case ASSET_36F_MODEL_BANJO_PUMPKIN: //L8029DCCC + case ASSET_374_MODEL_BANJO_CROC: //L8029DCCC + func_8033A45C(0x1B, (s32) ml_interpolate_f(D_8037D23C, 1.0f, 6.0f)); + func_8033A45C(0x1A, (s32) ml_interpolate_f(D_8037D240, 1.0f, 6.0f)); + break; + + case ASSET_356_MODEL_BANJO_WISHYWASHY: //L8029DD2C + func_8033A45C(1, (s32) ml_interpolate_f(D_8037D240, 1.0f, 4.0f)); + break; + } +} + +void func_8029DD6C(void) { + s32 temp_s0; // [port] must hold values > 1 for geo selector branches + + modelRender_func_8033A1FC(); + switch (baModel_getModelId()) { + case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: + case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: + func_8033A45C(1, D_8037D238); + func_8033A45C(9, D_8037D238); + func_8033A45C(0xC, D_8037D238); + func_8033A45C(0xF, D_8037D238); + func_8033A45C(2, D_8037D236); + func_8033A45C(0xA, D_8037D236); + func_8033A45C(0xD, D_8037D236); + func_8033A45C(0x10, D_8037D236); + func_8033A45C(8, D_8037D235); + func_8033A45C(0xB, D_8037D235); + func_8033A45C(0xE, D_8037D235); + func_8033A45C(0x11, D_8037D235); + temp_s0 = D_8037D237 + 1; + func_8033A45C(0x12, temp_s0); + func_8033A45C(0x14, temp_s0); + func_8033A45C(0x16, temp_s0); + func_8033A45C(0x18, temp_s0); + func_8033A45C(0x13, temp_s0); + func_8033A45C(0x15, temp_s0); + func_8033A45C(0x17, temp_s0); + func_8033A45C(0x19, temp_s0); + temp_s0 = D_8037D239 + 1; + func_8033A45C(0x22, temp_s0); + func_8033A45C(0x24, temp_s0); + func_8033A45C(0x26, temp_s0); + func_8033A45C(0x28, temp_s0); + func_8033A45C(0x23, temp_s0); + func_8033A45C(0x25, temp_s0); + func_8033A45C(0x27, temp_s0); + func_8033A45C(0x29, temp_s0); + break; + case ASSET_359_MODEL_BANJO_WALRUS: + func_8033A45C(3, D_8037D23A); + break; + case ASSET_374_MODEL_BANJO_CROC: + temp_s0 = D_8037D237 + 1; + func_8033A45C(4, temp_s0); + func_8033A45C(5, temp_s0); + func_8033A45C(6, temp_s0); + func_8033A45C(7, temp_s0); + break; + } + func_8029DBF0(); +} + +bool func_8029DFA4(void){ + return D_8037D235; +} + +bool func_8029DFB0(void){ + return D_8037D236; +} + +bool func_8029DFBC(void){ + return D_8037D238; +} + +f32 func_8029DFC8(void){ + return D_8037D23C; +} + +f32 func_8029DFD4(void){ + return D_8037D240; +} + +bool func_8029DFE0(void){ + return D_8037D237; +} + +bool func_8029DFEC(void){ + return D_8037D239; +} + +void func_8029DFF8(void) { + func_8029E070(0); + func_8029E064(0); + func_8029E058(0); + func_8029E0C4(0.0f); + func_8029E0D0(0.0f); + func_8029E0DC(0); + func_8029E0F4(0); + func_8029E0E8(0); + CALL_EVENT(OnPlayerAnimReset); +} + +void func_8029E058(bool arg0){ + D_8037D235 = arg0; +} + +void func_8029E064(bool arg0){ + D_8037D236 = arg0; +} + +void func_8029E070(bool arg0) { + func_8029E090(arg0, 0.0f); +} + +void func_8029E090(bool arg0, f32 arg1) { + D_8037D230 = arg1; + D_8037D234 = arg0; + if (arg1 == 0.0f) { + D_8037D238 = arg0; + } +} + +void func_8029E0C4(f32 arg0){ + D_8037D23C = arg0; +} + +void func_8029E0D0(f32 arg0){ + D_8037D240 = arg0; +} + +void func_8029E0DC(bool arg0){ + D_8037D237 = arg0; +} + +void func_8029E0E8(bool arg0){ + D_8037D23A = arg0; +} + +void func_8029E0F4(bool arg0){ + D_8037D239 = arg0; +} + +void func_8029E100(void) { + if (D_8037D230 != 0.0f) { + D_8037D230 -= time_getDelta(); + if (D_8037D230 <= 0.0f) { + D_8037D238 = D_8037D234; + } + } +} diff --git a/src/core2/ba/babounds.c b/src/core2/ba/ba_bounds.c similarity index 93% rename from src/core2/ba/babounds.c rename to src/core2/ba/ba_bounds.c index 45bdd0a39..ebf619b7e 100644 --- a/src/core2/ba/babounds.c +++ b/src/core2/ba/ba_bounds.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/babounds.c #include #include "functions.h" #include "variables.h" @@ -33,7 +32,7 @@ void babounds_init(void){ void babounds_update(void){ f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); if(!ml_vec3f_inside_box_vec3f(sp1C, D_8037C3C0.unkC, D_8037C3C0.unk0)){ if(D_8037C3C0.unk18 == 0){ D_8037C3C0.unk18 = 1; diff --git a/src/core2/ba/babuzz.c b/src/core2/ba/ba_buzz.c similarity index 98% rename from src/core2/ba/babuzz.c rename to src/core2/ba/ba_buzz.c index 87e6371cb..216cf5abb 100644 --- a/src/core2/ba/babuzz.c +++ b/src/core2/ba/ba_buzz.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/babuzz.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_camera.c b/src/core2/ba/ba_camera.c index d91fcd45b..71bf5d378 100644 --- a/src/core2/ba/ba_camera.c +++ b/src/core2/ba/ba_camera.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9BD0.c #include #include "functions.h" #include "variables.h" @@ -113,7 +112,7 @@ int func_80290E8C(void){ ncDynamicCamera_setState(3); func_80291488(0xB); if( gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN - && playerPosition_getY() < 1201.0f + && player_getYPosition() < 1201.0f ){ func_802C1B20(1100.0f); } diff --git a/src/core2/ba/carriedobj.c b/src/core2/ba/ba_carriedobj.c similarity index 93% rename from src/core2/ba/carriedobj.c rename to src/core2/ba/ba_carriedobj.c index 3d666a454..9d39a7c57 100644 --- a/src/core2/ba/carriedobj.c +++ b/src/core2/ba/ba_carriedobj.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/carriedobj.c #include #include "functions.h" #include "variables.h" @@ -10,7 +9,7 @@ bool player_setCarryObjectPose(enum actor_e actor_id, Actor **arg1){ Actor *actor; m1 = (*arg1)->marker; - m2 = bacarry_getMarker(); + m2 = bacarry_get_marker(); if(m2){ actor = marker_getActor(m2); } @@ -41,7 +40,7 @@ void bacarriedobj_spawn(enum actor_e actor_id){ ActorMarker *marker; Actor *actor; - marker = bacarry_getMarker(); + marker = bacarry_get_marker(); if(marker){ actor = marker_getActor(marker); } @@ -69,7 +68,7 @@ void bacarriedobj_dec(enum actor_e actor_id){ ActorMarker *marker; Actor* actor; - marker = bacarry_getMarker(); + marker = bacarry_get_marker(); if(marker) actor = marker_getActor(marker); diff --git a/src/core2/ba/carry.c b/src/core2/ba/ba_carry.c similarity index 95% rename from src/core2/ba/carry.c rename to src/core2/ba/ba_carry.c index d15cff986..3f71a39a8 100644 --- a/src/core2/ba/carry.c +++ b/src/core2/ba/ba_carry.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/carry.c #include "functions.h" #include "core2/ba/carry.h" @@ -62,7 +61,7 @@ void bacarry_reset_marker(void){ baCarry_marker = NULL; } -ActorMarker *bacarry_getMarker(void){ +ActorMarker *bacarry_get_marker(void){ return baCarry_marker; } diff --git a/src/core2/ba/iFrame.c b/src/core2/ba/ba_eyeblink.c similarity index 92% rename from src/core2/ba/iFrame.c rename to src/core2/ba/ba_eyeblink.c index ed3bd4e9d..33803e3ee 100644 --- a/src/core2/ba/iFrame.c +++ b/src/core2/ba/ba_eyeblink.c @@ -1,8 +1,6 @@ -// BanjoDecomp: core2/ba/iFrame.c #include #include "functions.h" #include "variables.h" -#include "iFrame.h" #include "core2/statetimer.h" /* .bss */ diff --git a/src/core2/ba/ba_eyeblink_data.c b/src/core2/ba/ba_eyeblink_data.c index 7d4179659..0c959a60f 100644 --- a/src/core2/ba/ba_eyeblink_data.c +++ b/src/core2/ba/ba_eyeblink_data.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_90E0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_eyemouth_data.c b/src/core2/ba/ba_eyemouth_data.c index bbc2c81ca..4d9c9b6f7 100644 --- a/src/core2/ba/ba_eyemouth_data.c +++ b/src/core2/ba/ba_eyemouth_data.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_400F0.c #include #include "functions.h" #include "variables.h" @@ -102,16 +101,16 @@ void func_802C71F0(Actor *actor){ case 0x8E: case 0xAC: case 0xB8://L802C7254 - modelRender_setAppendageVisibility(0x1, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 6.0f)); - modelRender_setAppendageVisibility(0x2, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 6.0f)); + func_8033A45C(0x1, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 6.0f)); + func_8033A45C(0x2, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 6.0f)); break; case 0x195: case 0x196: case 0x197://L802C72B0 case 0x2FB://L802C72B4 - modelRender_setAppendageVisibility(0x1C, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 8.0f)); - modelRender_setAppendageVisibility(0x1D, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 8.0f)); + func_8033A45C(0x1C, (s32)ml_interpolate_f(local->unk0[0], 1.0f, 8.0f)); + func_8033A45C(0x1D, (s32)ml_interpolate_f(local->unk0[1], 1.0f, 8.0f)); break; } } diff --git a/src/core2/ba/baeyes.c b/src/core2/ba/ba_eyes.c similarity index 88% rename from src/core2/ba/baeyes.c rename to src/core2/ba/ba_eyes.c index ac8d357e0..18e972bd4 100644 --- a/src/core2/ba/baeyes.c +++ b/src/core2/ba/ba_eyes.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/baeyes.c #include #include "functions.h" #include "variables.h" @@ -14,9 +13,9 @@ BaEyes baEyes[4]; f32 baeyes_getEyePosition(s32 id){ switch (id) { case 0: - return modelAppendages_showBanjosLeftEye(); + return func_8029DFC8(); case 1: - return modelAppendages_showBanjosRightEye(); + return func_8029DFD4(); case 2: return 0.0f; case 3: @@ -30,10 +29,10 @@ f32 baeyes_getEyePosition(s32 id){ void baeyes_setEyePosition(s32 id, f32 position){ switch(id){ case 0: - modelAppendages_setBanjosLeftEyeVisibility(position); + func_8029E0C4(position); break; case 1: - modelAppendages_setBanjosRightEyeVisibility(position); + func_8029E0D0(position); break; case 2: break; @@ -100,7 +99,7 @@ void baeyes_update(void){ break; case 3://L80292FBC case 4://L80292FBC - eye_position -= dt / baEyes[i].duration; + eye_position -= dt/baEyes[i].duration; if(eye_position < 0.0){ eye_position = 0.0f; baEyes[i].state = 0; diff --git a/src/core2/ba/falldamage.c b/src/core2/ba/ba_falldamage.c similarity index 96% rename from src/core2/ba/falldamage.c rename to src/core2/ba/ba_falldamage.c index a39d52212..0b17f17ab 100644 --- a/src/core2/ba/falldamage.c +++ b/src/core2/ba/ba_falldamage.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/falldamage.c #include #include "functions.h" #include "variables.h" @@ -115,7 +114,7 @@ void bafalldamage_set_start_position(f32 arg0[3]){ } void bafalldamage_init(void){ - playerPosition_get(bafalldamage_start_position); + _player_getPosition(bafalldamage_start_position); bafalldamage_state = 0; bafalldamage_set_state(1); D_8037C1C0.damage = 0; @@ -135,6 +134,6 @@ void bafalldamage_update(void){ void bafalldamage_start(void){ f32 player_position[3]; - playerPosition_get(player_position); + _player_getPosition(player_position); bafalldamage_set_start_position(player_position); } diff --git a/src/core2/ba/ba_falling.c b/src/core2/ba/ba_falling.c index ed93cf78f..4c7df9dc4 100644 --- a/src/core2/ba/ba_falling.c +++ b/src/core2/ba/ba_falling.c @@ -1,8 +1,8 @@ -// BanjoDecomp: core2/code_C97F0.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" + #include "port/Interpolation/FrameInterpolation.h" @@ -211,7 +211,7 @@ void func_80350CA4(void) { sp24[0] = sp30[0] + sp48[0]; sp24[1] = sp30[1] + sp48[1]; sp24[2] = sp30[2] + sp48[2]; - if (player_isInFirstPersonView()) { // [port] decomp passes sp48[1],sp48[2]; actual def takes none + if (func_8028F170()) { // [port] decomp passed sp48[1],sp48[2] but actual def is (void) var_v0 = func_80320B98(sp30, sp24, sp3C, 0x01000000); } else { var_v0 = func_80309B48(sp30, sp24, sp3C, 0x01000000); diff --git a/src/core2/ba/baflag.c b/src/core2/ba/ba_flag.c similarity index 95% rename from src/core2/ba/baflag.c rename to src/core2/ba/ba_flag.c index 64dc73ede..0ada884b8 100644 --- a/src/core2/ba/baflag.c +++ b/src/core2/ba/ba_flag.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/baflag.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/flap.c b/src/core2/ba/ba_flap.c similarity index 98% rename from src/core2/ba/flap.c rename to src/core2/ba/ba_flap.c index 5647fae92..c35f93134 100644 --- a/src/core2/ba/flap.c +++ b/src/core2/ba/ba_flap.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/flap.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/hazards.c b/src/core2/ba/ba_groundsurface.c similarity index 96% rename from src/core2/ba/hazards.c rename to src/core2/ba/ba_groundsurface.c index 8b70a882a..506846ce4 100644 --- a/src/core2/ba/hazards.c +++ b/src/core2/ba/ba_groundsurface.c @@ -1,8 +1,6 @@ -// BanjoDecomp: core2/hazards.c #include #include "functions.h" #include "variables.h" -#include "iFrame.h" #include "core2/ba/timer.h" #include "core2/statetimer.h" @@ -16,7 +14,7 @@ f32 D_8037D224; /*.code */ bool isOnFloor(void){ - return floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > playerPosition_getY(); + return floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > player_getYPosition(); } void freeHazardSfxId(void){ @@ -187,10 +185,7 @@ bool isPlayerInHazard(void){ case MAP_6E_GL_GV_LOBBY: case MAP_72_GL_BGS_LOBBY: case MAP_8E_GL_FURNACE_FUN://L8029D6FC - // [port] Default is the vanilla hazard-collision-flag check; a romhack - // whose hazard-flagged collision was stripped on export can force it. - return EventSystem_Should(VB_GROUND_HAZARD_ACTIVE, func_80294610(0xE000) != 0, gsworld_getMap()) && - player_isStable(); + return func_80294610(0xE000) && player_isStable(); case MAP_31_RBB_RUSTY_BUCKET_BAY: player_getPosition(sp2C); diff --git a/src/core2/ba/ba_health.c b/src/core2/ba/ba_health.c index 31f21e56f..0e8864f5d 100644 --- a/src/core2/ba/ba_health.c +++ b/src/core2/ba/ba_health.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9290.c #include #include "functions.h" #include "variables.h" @@ -16,7 +15,7 @@ void func_80290220(void){ D_8037C010 = D_8037C014 = -1; D_8037C02C = 0; D_8037C018 = -1; - playerPosition_get(D_8037C020); + _player_getPosition(D_8037C020); } void func_8029026C(s32 arg0, s32 arg1){ @@ -37,7 +36,7 @@ void func_80290298(void) { sp30 = (func_8028B528() && !is_pumpkin) ? 6 : 1; sp24 = func_8028B528() && !is_pumpkin; if (D_8037C02C || player_isStable() || sp24 || player_movementGroup() == BSGROUP_5_CLIMB || bs_getState() == BS_B_UNKOWN) { - playerPosition_get(D_8037C020); + _player_getPosition(D_8037C020); } if (player_movementGroup() == BSGROUP_A_FLYING) { diff --git a/src/core2/ba/ba_hitbox.c b/src/core2/ba/ba_hitbox.c index 74f7889f0..56c0c35a0 100644 --- a/src/core2/ba/ba_hitbox.c +++ b/src/core2/ba/ba_hitbox.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6B30.c #include #include "functions.h" #include "variables.h" @@ -37,19 +36,19 @@ enum hitbox_e hitbox_getHitboxForActor(ActorMarker *arg0){ switch(bs_getState()){ case BS_F_BBUSTER: //8028DBA4 - return __maybe(bsbbuster_hitboxActive(), HITBOX_1_BEAK_BUSTER); + return __maybe(bsbbuster_hitboxActive(),HITBOX_1_BEAK_BUSTER); break; - case BS_13_BBARGE://8028DBC0 - return __maybe(bsbbarge_hitboxActive(), HITBOX_2_BEAK_BARGE); + case BS_BBARGE://8028DBC0 + return __maybe(bsbbarge_hitboxActive(),HITBOX_2_BEAK_BARGE); break; - case BS_2A_BOMB://8028DBDC - return __maybe(bsbfly_bombHitboxActive(), HITBOX_3_BEAK_BOMB); + case BS_BOMB://8028DBDC + return __maybe(bsbfly_bombHitboxActive(),HITBOX_3_BEAK_BOMB); break; - case BS_6_CLAW://8028DBF8 + case BS_CLAW://8028DBF8 if(arg0 && !func_8028AED4(marker_getActor(arg0)->position, 90.0f)) return HITBOX_0_NONE; - retVal = __maybe(bsclaw_hitboxActive(), HITBOX_4_CLAW); + retVal = __maybe(bsclaw_hitboxActive(),HITBOX_4_CLAW); if(retVal != 0) return retVal; return HITBOX_8_CLAW_DOWN; @@ -69,7 +68,7 @@ enum hitbox_e hitbox_getHitboxForActor(ActorMarker *arg0){ return HITBOX_6_WONDERWING; break; //8028DCA0 - case BS_31_ROLL: + case BS_ROLL: return __maybe(bstwirl_hitboxActive(),HITBOX_7_ROLL); break; case BS_6E_CROC_BITE://L8028DCBC diff --git a/src/core2/ba/bainput.c b/src/core2/ba/ba_input.c similarity index 98% rename from src/core2/ba/bainput.c rename to src/core2/ba/ba_input.c index b85165166..e87349cb0 100644 --- a/src/core2/ba/bainput.c +++ b/src/core2/ba/ba_input.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bainput.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_intensity.c b/src/core2/ba/ba_intensity.c index bb0f5d7d7..a09751769 100644 --- a/src/core2/ba/ba_intensity.c +++ b/src/core2/ba/ba_intensity.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_A600.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/bakey.c b/src/core2/ba/ba_key.c similarity index 98% rename from src/core2/ba/bakey.c rename to src/core2/ba/ba_key.c index 605791360..2100bb0eb 100644 --- a/src/core2/ba/bakey.c +++ b/src/core2/ba/ba_key.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bakey.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/balookat.c b/src/core2/ba/ba_lookat.c similarity index 98% rename from src/core2/ba/balookat.c rename to src/core2/ba/ba_lookat.c index ba4281efa..afd917717 100644 --- a/src/core2/ba/balookat.c +++ b/src/core2/ba/ba_lookat.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/balookat.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_lookdir.c b/src/core2/ba/ba_lookdir.c index 0a30418f7..d78aea99a 100644 --- a/src/core2/ba/ba_lookdir.c +++ b/src/core2/ba/ba_lookdir.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_7060.c #include #include "functions.h" #include "variables.h" @@ -12,10 +11,10 @@ #include "core2/snackerctl.h" -extern bool player_isInHorizontalRadius(f32[3], f32); +extern int player_isInHorizontalRadius(f32[3], f32); extern bool player_isInVerticalRange(f32[3], f32); extern void func_80295A8C(void); -extern void climb_set(f32[3], f32[3], f32, u32); +extern void climbSet(f32[3], f32[3], f32, u32); extern void func_80296C90(f32); extern void func_80296C9C(f32); extern void func_8029B73C(f32 arg0[3], f32 arg1, f32 arg2, f32 arg3, f32 arg4); @@ -186,10 +185,10 @@ void func_8028E4B0(void) { D_8037BFBA = true; D_8037BFB9 = false; - bsmethods_reset(); + func_80295914(); sp20 = gsworld_getExit(); D_8037BFB8 = 0; - playerPosition_set(D_803636C0); + player_setPosition(D_803636C0); if (volatileFlag_get(VOLATILE_FLAG_E) || func_802D686C() || (sp20 == 0x65)){ return; } @@ -271,7 +270,7 @@ u32 player_getTransformation(void){ } void func_8028E7EC(f32 arg0[3]){ - climb_getBottom(arg0); + climbGetBottom(arg0); } f32 player_stateTimer_get(enum state_timer_e timer_id){ @@ -286,14 +285,14 @@ void func_8028E84C(f32 arg0[3]){ func_80294480(arg0); } -ActorMarker *bacarry_getMarkerWithExtraSteps(void){ - return bacarry_getMarker(); +ActorMarker *func_8028E86C(void){ + return bacarry_get_marker(); } -enum marker_e bacarry_getMarkerId(void){ +enum marker_e bacarry_get_markerId(void){ ActorMarker *marker; - marker = bacarry_getMarker(); + marker = bacarry_get_marker(); if(marker){ return marker->id; } @@ -304,7 +303,7 @@ enum actor_e carriedObj_getActorId(void){ ActorMarker *marker; Actor *actor; - marker = bacarry_getMarker(); + marker = bacarry_get_marker(); if(marker != NULL){ actor = marker_getActor(marker); @@ -334,7 +333,7 @@ f32 func_8028E984(void){ } void player_getPosition(f32 dst[3]){ - playerPosition_get(dst); + _player_getPosition(dst); } void func_8028E9C4(s32 arg0, f32 arg1[3]) { @@ -356,7 +355,7 @@ void func_8028E9C4(s32 arg0, f32 arg1[3]) { break; case 5: //L8028EA2C - playerPosition_get(arg1); + _player_getPosition(arg1); switch(bsStoredState_getTransformation()){ case TRANSFORM_3_PUMPKIN: //L8028EA68 if(gsworld_getMap() == MAP_1B_MMM_MAD_MONSTER_MANSION){ @@ -398,12 +397,12 @@ void func_8028E9C4(s32 arg0, f32 arg1[3]) { } -void player_getPosition_s32(s32 position_s32[3]){ +void player_getPosition_s32(s32 arg0[3]){ f32 plyr_pos[3]; player_getPosition(plyr_pos); - position_s32[0] = (s32)plyr_pos[0]; - position_s32[1] = (s32)plyr_pos[1]; - position_s32[2] = (s32)plyr_pos[2]; + arg0[0] = (s32)plyr_pos[0]; + arg0[1] = (s32)plyr_pos[1]; + arg0[2] = (s32)plyr_pos[2]; } f32 player_getYaw(void){ @@ -432,7 +431,7 @@ f32 func_8028EC64(f32 arg0[3]){ f32 sp1C; f32 sp18; func_80293D2C(&sp18, &sp1C); - playerPosition_get(arg0); + _player_getPosition(arg0); arg0[1] += sp18; return sp1C; } @@ -467,7 +466,7 @@ enum bsgroup_e player_movementGroup(void) { case BS_E_OW: //L8028EE00 case BS_34_JIG_NOTEDOOR: //L8028EE00 case BS_3C_TALK: //L8028EE00 - case BS_3F_UNKNOWN: //L8028EE00 + case BS_3F: //L8028EE00 case BS_41_DIE: //L8028EE00 case BS_44_JIG_JIGGY: //L8028EE00 return BSGROUP_1_INTR; @@ -549,7 +548,7 @@ f32 func_8028EF88(void){ if(floor_isCurrentFloorunk59()){ return floor_getCurrentFloorYPosition(); } - return playerPosition_getY(); + return player_getYPosition(); } bool func_8028EFC8(void){ @@ -560,15 +559,15 @@ bool func_8028EFEC(void){ return bakey_getAndSetState(BUTTON_A, 2); } -void bacarriedobj_decWithExtraSteps(enum actor_e actor_id){ +void func_8028F010(enum actor_e actor_id){ bacarriedobj_dec(actor_id); } -void bacarriedobj_incWithExtraSteps(enum actor_e actor_id){ +void func_8028F030(enum actor_e actor_id){ bacarriedobj_inc(actor_id); } -void bacarriedobj_displayOnHudWithExtraSteps(enum actor_e actor_id){ +void func_8028F050(enum actor_e actor_id){ bacarriedobj_displayOnHud(actor_id); } @@ -589,7 +588,7 @@ bool func_8028F098(void){ } } -bool player_isBanjoOrWishywashy(void){ +bool func_8028F0D4(void){ enum transformation_e xform_id; xform_id = bsStoredState_getTransformation(); @@ -609,11 +608,11 @@ bool func_8028F150(void){ return baModel_isVisible(); } -bool player_isInFirstPersonView(void){ +bool func_8028F170(void){ return baflag_isTrue(BA_FLAG_17_FIRST_PERSON_VIEW); } -bool ability_isUnlocked(enum ability_e uid){ +int ability_isUnlocked(enum ability_e uid){ return ability_hasLearned(uid); } @@ -629,7 +628,7 @@ bool func_8028F1E0(void){ return bsList_getInterruptMethod(bs_getState()) != NULL; } -bool player_isStableWithExtraSteps(void){ +bool func_8028F20C(void){ return player_isStable(); } @@ -690,13 +689,9 @@ void func_8028F408(f32 arg0[3]){ } bool func_8028F428(s32 arg0, ActorMarker *marker) { - s32 handled = 2; func_80296CB4(arg0); func_80296CA8(marker); - if (EventSystem_Should(VB_BUMP_REBOUNDS_PLAYER, true, marker)) { - handled = bs_checkInterrupt(BS_INTR_24); - } - return handled == 2; + return bs_checkInterrupt(BS_INTR_24) == 2; } bool func_8028F45C(s32 arg0, f32 arg1[3]) { @@ -781,7 +776,7 @@ void player_stateTimer_set(enum state_timer_e timer_id, f32 value){ } void player_setClimbParams(f32 bottom[3], f32 top[3], f32 radius, u32 arg3){ - climb_set(bottom, top, radius, arg3); + climbSet(bottom, top, radius, arg3); } void func_8028F760(s32 arg0, f32 arg1, f32 arg2){ @@ -889,7 +884,7 @@ void func_8028FA74(f32 dst[3]){ f32 plyr_pos[3]; f32 sp18[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); playerPosition_getOffset(sp18); ml_vec3f_add(dst, plyr_pos, sp18); } @@ -898,7 +893,7 @@ void func_8028FAB0(f32 arg0[3]){ f32 plyr_pos[3]; f32 diff[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); ml_vec3f_diff_copy(diff, arg0, plyr_pos); playerPosition_setOffset(diff); } @@ -921,7 +916,7 @@ void func_8028FB68(void){ func_80295D74(); } -bool player_transform(enum transformation_e xform_id) { +bool func_8028FB88(enum transformation_e xform_id) { if (wishyWashyFlag_get() && xform_id == TRANSFORM_1_BANJO) { xform_id = TRANSFORM_7_WISHWASHY; } @@ -940,7 +935,7 @@ bool func_8028FBD4(f32 arg0[3]) { } bool player_throwCarriedObject(void){ - if (bacarry_getMarkerWithExtraSteps() && bscarry_inSet(bs_getState())) { + if (func_8028E86C() && bscarry_inSet(bs_getState())) { return bs_checkInterrupt(BS_INTR_16_THROW_CARRIED_OBJ) == 2; } @@ -969,9 +964,3 @@ void func_8028FCE8(void) { D_8037BFCC = yaw_get(); D_8037BFD0 = D_8037BFBC; } - -void player_setWarpDestination(f32 position[3], f32 yaw, s32 exit_id) { - ml_vec3f_copy(D_8037BFC0, position); - D_8037BFCC = yaw; - D_8037BFD0 = (f32) exit_id; -} diff --git a/src/core2/ba/marker.c b/src/core2/ba/ba_marker.c similarity index 95% rename from src/core2/ba/marker.c rename to src/core2/ba/ba_marker.c index 81c8e406b..843b4a6a8 100644 --- a/src/core2/ba/marker.c +++ b/src/core2/ba/ba_marker.c @@ -1,16 +1,15 @@ -// BanjoDecomp: core2/ba/marker.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "port/Romhack/RomhackConfig.h" -#include "port/Enhancements/Retention/Retention.h" #include "core2/ba/physics.h" #include "version.h" #include "prop.h" extern void func_803012F8(void); extern void __baMarker_8028BA00(s32); +extern Actor *spawnQueue_actor_s16(uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern void func_802A6388(f32); extern f32 chwadingboots_802D6E4C(Actor *); extern void set_turbo_duration(f32); @@ -157,36 +156,16 @@ void __baMarker_8028B904(s32 arg0, s32 arg1, s32 arg2, s32 arg3){ } -extern ActorArray *suBaddieActorArray; -extern enum honeycomb_e D_8037DDC0; // honeycomb.c: pending uid for the next spawned honeycomb - -static bool __baMarker_honeycombPresent(s32 uid){ - s32 i; - s32 actorUid; - Actor *actor; - - if(suBaddieActorArray == NULL) return false; - for(i = 0; i < suBaddieActorArray->cnt; i++){ - actor = &suBaddieActorArray->data[i]; - if(actor->marker == NULL || actor->marker->id != MARKER_53_EMPTY_HONEYCOMB) continue; - actorUid = func_802CA1C4(actor); - if(actorUid == uid || (actorUid == 0 && D_8037DDC0 == uid)) return true; - } - return false; -} - void __baMarker_8028B9A8(uintptr_t arg0){ NodeProp *tmp_v0; s32 ideal_yaw[3]; - if(__baMarker_honeycombPresent(arg0)) return; - tmp_v0 = cubeList_findNodePropByActorIdAndPosition_s32(0x1F6, NULL); nodeprop_getPosition_s32(tmp_v0, ideal_yaw); func_802CA1CC(arg0); actor_spawnWithYaw_s32(ACTOR_47_EMPTY_HONEYCOMB, &ideal_yaw, 0); coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - + } void __baMarker_8028BA00(s32 arg0){ @@ -576,12 +555,11 @@ void __baMarker_resolveCollision(Prop *other_prop){ || (player_isStable() && !(3600.0f < ml_distanceSquared_vec3f(actor->position, spA0))) ) { jiggyscore_setCollected(jiggy_id, true); - CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_JIGGY, jiggy_id); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, 1); if (jiggy_id == JIGGY_20_BGS_ELEVATED_WALKWAY || jiggy_id == JIGGY_25_BGS_MAZE) { func_802D6924(); } - if (jiggyscore_total() < 3 && EventSystem_Should(VB_JIGGY_COLLECT_TUTORIAL, true)) { + if (jiggyscore_total() < 3) { __baMarker_8028B848(); } @@ -600,11 +578,9 @@ void __baMarker_resolveCollision(Prop *other_prop){ if (__baMarker_8028BC20(marker)) return; sp98 = func_802CA1C4(marker_getActor(marker)); - if (sp98 != HONEYCOMB_12_MMM_FLOORBOARD || player_getTransformation() == TRANSFORM_3_PUMPKIN - || !EventSystem_Should(VB_HONEYCOMB_PUMPKIN_REQUIREMENT, true)) + if (sp98 != HONEYCOMB_12_MMM_FLOORBOARD || player_getTransformation() == TRANSFORM_3_PUMPKIN) { honeycombscore_set(sp98, 1); - CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_HONEYCOMB, sp98); coMusicPlayer_playMusic(COMUSIC_17_EMPTY_HONEYCOMB_COLLECTED, 28000); timedFunc_set_1(2.0f, (GenFunction_1)progressDialog_showDialogMaskZero, FILEPROG_B_EMPTY_HONEYCOMB_TEXT); item_inc(ITEM_13_EMPTY_HONEYCOMB); @@ -632,7 +608,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ && volatileFlag_get(VOLATILE_FLAG_0_IN_FURNACE_FUN_QUIZ) && !fileProgressFlag_get(FILEPROG_A6_FURNACE_FUN_COMPLETE) ) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB); func_8030E6D4(SFX_126_AUDIENCE_BOOING); } @@ -722,7 +698,6 @@ void __baMarker_resolveCollision(Prop *other_prop){ return; __baMarker_resolveMusicNoteCollision(other_prop); - port_noteRetention_onLocalNoteCollected(marker); marker_despawn(marker); break; @@ -747,7 +722,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ && volatileFlag_get(VOLATILE_FLAG_0_IN_FURNACE_FUN_QUIZ) && !fileProgressFlag_get(FILEPROG_A6_FURNACE_FUN_COMPLETE) ) { - progressDialog_setAndTriggerDialog_4(VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE); + volatileFlag_setAndTriggerDialog_4(VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE); func_8030E6D4(SFX_127_AUDIENCE_MIXED); } coMusicPlayer_playMusic(COMUSIC_15_EXTRA_LIFE_COLLECTED, 0x7FFF); @@ -787,7 +762,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ return; if (bsStoredState_getTransformation() != TRANSFORM_1_BANJO) return; - if(player_isInFirstPersonView()) + if (func_8028F170()) return; if (func_8028F25C()) return; @@ -812,7 +787,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ if (func_8028F25C()) return; - if(player_isInFirstPersonView()) + if (func_8028F170()) return; if (!chtrainers_canUse(actor)) @@ -843,9 +818,6 @@ void __baMarker_resolveCollision(Prop *other_prop){ if (plyr_hitbox_type == HITBOX_1_BEAK_BUSTER) obj_collision_type = MARKER_COLLISION_FUNC_1; break; - case MARKER_300_CUSTOM_COLLECTIBLE: - marker_callCollisionFunc(playerMarker, marker, plyr_collision_type); - break; }//L8028D034 if (baiFrame_getState() == 3) { plyr_collision_type = MARKER_COLLISION_FUNC_0; @@ -913,7 +885,7 @@ void __baMarker_resolveCollision(Prop *other_prop){ void baMarker_init(void){ f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); playerMarker = func_8032FBE4(sp1C, baModel_80291AAC, 1, 0); playerMarker->unk2C_1 = 1; marker_setCollisionScripts(playerMarker, NULL, func_80291634, func_80291610); @@ -946,7 +918,7 @@ void baMarker_update(void){ if ((D_8037BF88 != 0)){ temp_s0 = func_8024FEEC(func_8025ADD4(COMUSIC_30_5TH_JINJO_COLLECTED) & 0xFF); - if((coMusicPlayer_getTrackCount() < 4 && temp_s0 >= 0xBB9) || !func_8025AD7C(COMUSIC_30_5TH_JINJO_COLLECTED)){ + if((comusic_active_track_count() < 4 && temp_s0 >= 0xBB9) || !func_8025AD7C(COMUSIC_30_5TH_JINJO_COLLECTED)){ func_8028F918(0); D_8037BF88 = 0; } @@ -956,7 +928,7 @@ void baMarker_update(void){ temp_s0_2 = __baMarker_8028B750(); baflag_clear(BA_FLAG_1_ON_FLIGHT_PAD); baflag_clear(BA_FLAG_2_ON_SPRING_PAD); - playerPosition_get(sp168); + _player_getPosition(sp168); func_8032F64C(sp168, playerMarker); for(D_8037BF8C = NULL, i = 0, temp_s2 = 0; i < 2;i++){//L8028D3DC D_8037BF90 = i; diff --git a/src/core2/ba/model.c b/src/core2/ba/ba_model.c similarity index 94% rename from src/core2/ba/model.c rename to src/core2/ba/ba_model.c index 286240997..4c2fc13d1 100644 --- a/src/core2/ba/model.c +++ b/src/core2/ba/ba_model.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/model.c #include #include "functions.h" #include "variables.h" @@ -7,8 +6,6 @@ #include "core2/ba/physics.h" #include "bk_math.h" -#include "port/Enhancements/Cosmetics/PlayerColors.h" - void assetcache_release(void *); //assetcache_free void modelRender_func_8033A280(f32); @@ -57,7 +54,7 @@ static void _baModel_updateModelYaw(void){ void baModel_80291A50(s32 arg0, f32 dst[3]){ vec3fArray_get_vec3f(D_80363780, arg0, dst); if(ml_isZero_vec3f(dst)){ - playerPosition_get(dst); + _player_getPosition(dst); } } @@ -81,7 +78,7 @@ void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ _baModel_updateModelYaw(); baModelRoll = roll_get(); baModelPitch = pitch_get(); - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); plyr_pos[1] += 2.0f; ml_vec3f_assign(rotation, baModelPitch, baModelYaw, baModelRoll); func_8029A47C(env_color); @@ -97,14 +94,12 @@ void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ if(baModelBin){ baanim_80289F30(); - modelAppendages_loadAppendage(); + func_8029DD6C(); modelRender_setEnvColor(env_color[0], env_color[1], env_color[2], baModelEnvAlpha); modelRender_func_8033A280(2.0f); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)_baModel_preDraw, 0); modelRender_setRefPoints(D_80363780); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); - // [port] Swap in this player's recoloured palettes/vertex colours for this draw. - PlayerColors_applyLocalForDraw(baModel_getModelId(), baModelBin); if(D_8037C150.unk0){ D_8037C150.unk0 = 0; modelRender_draw(gfx, mtx, D_8037C150.unk4, rotation, baModelScale, sp38, baModelBin); @@ -120,7 +115,7 @@ void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ } void baModel_updateModel(void){ - baModel_set(playerModel_get()); + baModel_set(func_802985F0()); } void baModel_reset(void){ @@ -309,7 +304,7 @@ void baModel_80292284(f32 arg0[3], s32 arg1){ case ASSET_374_MODEL_BANJO_CROC: vec3fArray_get_vec3f(D_80363780, arg1 + 1, arg0); if(ml_isZero_vec3f(arg0)){ - playerPosition_get(arg0); + _player_getPosition(arg0); } arg0[1] += D_8037C130[arg1][0]; @@ -325,12 +320,12 @@ void baModel_80292284(f32 arg0[3], s32 arg1){ arg0[2] = arg0[2] + sp38[2]; break; default: ////80292400 - playerPosition_get(arg0); + _player_getPosition(arg0); break; } } else{//L80292410 - playerPosition_get(arg0); + _player_getPosition(arg0); if(arg1){ arg0[1] += 33.0f; } diff --git a/src/core2/ba/playermodel.c b/src/core2/ba/ba_modelselect.c similarity index 87% rename from src/core2/ba/playermodel.c rename to src/core2/ba/ba_modelselect.c index 7c05e884c..eeedd3ccb 100644 --- a/src/core2/ba/playermodel.c +++ b/src/core2/ba/ba_modelselect.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/playermodel.c #include #include "functions.h" #include "variables.h" @@ -6,10 +5,10 @@ #include "port/Patches/Patches.h" /* .bss */ -void *PlayerModelAssetId; +void *D_8037C5D0; /* .code */ -enum asset_e playerModel_get(void){ +s32 func_802985F0(void){ switch(bsStoredState_getTransformation()) { case TRANSFORM_2_TERMITE: //80298624 @@ -76,22 +75,21 @@ enum asset_e playerModel_get(void){ } } -void playerModel_free(void){ - if(PlayerModelAssetId){ - assetcache_release(PlayerModelAssetId); +void func_802986D0(void){ + if(D_8037C5D0){ + assetcache_release(D_8037C5D0); } } -void playerModel_set(void){ - enum asset_e model_id = playerModel_get(); - +void func_80298700(void){ + s32 sp1C = func_802985F0(); if(func_8028ADB4()){ - PlayerModelAssetId = 0; + D_8037C5D0 = 0; } - else if(model_id){ - PlayerModelAssetId = assetcache_get(model_id); + else if(sp1C){ + D_8037C5D0 = assetcache_get(sp1C); } else{ - PlayerModelAssetId = NULL; + D_8037C5D0 = NULL; } } diff --git a/src/core2/ba/ba_momentum.c b/src/core2/ba/ba_momentum.c index 1ba3f16cf..8d005015a 100644 --- a/src/core2/ba/ba_momentum.c +++ b/src/core2/ba/ba_momentum.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9450.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_musicstate.c b/src/core2/ba/ba_musicstate.c index b6dcfd3bf..825ff4e2c 100644 --- a/src/core2/ba/ba_musicstate.c +++ b/src/core2/ba/ba_musicstate.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9A9D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/physics.c b/src/core2/ba/ba_physics.c similarity index 96% rename from src/core2/ba/physics.c rename to src/core2/ba/ba_physics.c index c5ff222b4..b61b4c703 100644 --- a/src/core2/ba/physics.c +++ b/src/core2/ba/ba_physics.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/physics.c #include "core2/ba/physics.h" #include "functions.h" #include "variables.h" @@ -6,7 +5,7 @@ #include -extern f32 climb_getRadius(void); +extern f32 climbGetRadius(void); extern f32 func_8029CED0(void); /* .data */ @@ -154,10 +153,10 @@ void __baphysics_update_climb(void){ f32 sp34[3]; f32 sp28[3]; - climb_getBottom(sp28); + climbGetBottom(sp28); s_next_position[0] = sp28[0]; s_next_position[2] = sp28[2]; - func_80256E24(sp34, 0.0f, yaw_get(), 0.0f, 0.0f, -climb_getRadius()); + func_80256E24(sp34, 0.0f, yaw_get(), 0.0f, 0.0f, -climbGetRadius()); s_player_velocity[2] = 0.0f; s_next_position[0] += sp34[0];\ @@ -198,7 +197,7 @@ void __baphysics_update_goto(void){ break; case 1: //L802974E8 baphysics_goto.state = 2; - playerPosition_get(baphysics_goto.start_position); + _player_getPosition(baphysics_goto.start_position); baphysics_goto.elapsed_time = 0.0f; baphysics_set_velocity(0); break; @@ -226,8 +225,8 @@ void __baphysics_update_transform(void){ D_8037C500 += time_getDelta(); temp_f0 = func_80257A44(D_8037C500, 1.2f); - temp_f0 = ml_sin_deg(temp_f0 * 360.0f); - s_next_position[1] = 5.0 * temp_f0 + D_8037C4FC; + temp_f0 = ml_sin_deg(temp_f0*360.0f); + s_next_position[1] = 5.0*temp_f0 + D_8037C4FC; } void baphysics_get_position_change(f32 arg0[3]){ @@ -245,7 +244,7 @@ void baphysics_init(void){ } void baphysics_update(void){ - playerPosition_get(s_next_position); + _player_getPosition(s_next_position); switch(baphysics_type){ case BA_PHYSICS_GOTO: //L80297780 __baphysics_update_goto(); @@ -290,7 +289,7 @@ void baphysics_update(void){ default: break; } - playerPosition_set(s_next_position); + player_setPosition(s_next_position); } void baphysics_reset_horizontal_velocity(void){ diff --git a/src/core2/ba/playerposition.c b/src/core2/ba/ba_position.c similarity index 87% rename from src/core2/ba/playerposition.c rename to src/core2/ba/ba_position.c index 95c04692c..ff7109717 100644 --- a/src/core2/ba/playerposition.c +++ b/src/core2/ba/ba_position.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/playerposition.c #include #include "functions.h" #include "variables.h" @@ -25,19 +24,19 @@ void playerPosition_func_80298464(f32 arg0[3]){ ml_vec3f_copy(D_8037C5B0, arg0); } -void playerPosition_set(f32 arg0[3]){ +void player_setPosition(f32 arg0[3]){ ml_vec3f_copy(player_position, arg0); } -void playerPosition_setY(f32 arg0){ +void player_setYPosition(f32 arg0){ player_position[1] = arg0; } -void playerPosition_get(f32 arg0[3]){ +void _player_getPosition(f32 arg0[3]){ ml_vec3f_copy(arg0, player_position); } -f32 playerPosition_getY(void){ +f32 player_getYPosition(void){ return player_position[1]; } diff --git a/src/core2/ba/ba_recoil.c b/src/core2/ba/ba_recoil.c index ed23a9804..db60a03ea 100644 --- a/src/core2/ba/ba_recoil.c +++ b/src/core2/ba/ba_recoil.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_D9B0.c #include #include "functions.h" #include "variables.h" @@ -102,7 +101,7 @@ void func_80294B00(int arg0){ } void func_80294B0C(void){ - f32 sp1C = playerPosition_getY(); + f32 sp1C = player_getYPosition(); enum bsgroup_e player_movement_group = player_movementGroup(); if( player_isStable() || player_inWater() @@ -174,12 +173,12 @@ void func_80294BDC(void) { void func_80294DD8(void){ ml_vec3f_clear(D_8037C2A0); ml_vec3f_clear(D_8037C2B0); - playerPosition_get(D_8037C2D8); + _player_getPosition(D_8037C2D8); D_8037C2ED = 0; D_8037C2E4 = 0.0f; D_8037C2EC = 1; D_8037C2F0.unk8 = 0; - D_8037C2F0.unk4 = D_8037C2F0.unk0 = playerPosition_getY(); + D_8037C2F0.unk4 = D_8037C2F0.unk0 = player_getYPosition(); } void func_80294E54(int arg0){ @@ -188,7 +187,7 @@ void func_80294E54(int arg0){ void func_80294E60(void){ if(player_isStable()){ - playerPosition_get(D_8037C2D8); + _player_getPosition(D_8037C2D8); } if(player_isStable() || bsclimb_inSet(bs_getState())){ diff --git a/src/core2/ba/drone.c b/src/core2/ba/ba_scripted.c similarity index 98% rename from src/core2/ba/drone.c rename to src/core2/ba/ba_scripted.c index 9ebae29a8..403b48de5 100644 --- a/src/core2/ba/drone.c +++ b/src/core2/ba/ba_scripted.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ba/drone.c #include #include "functions.h" diff --git a/src/core2/ba/basfx.c b/src/core2/ba/ba_sfx.c similarity index 99% rename from src/core2/ba/basfx.c rename to src/core2/ba/ba_sfx.c index d091e2a98..c7c10fe34 100644 --- a/src/core2/ba/basfx.c +++ b/src/core2/ba/ba_sfx.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/basfx.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_state.c b/src/core2/ba/ba_state.c new file mode 100644 index 000000000..43a6c6abe --- /dev/null +++ b/src/core2/ba/ba_state.c @@ -0,0 +1,331 @@ +#include +#include "functions.h" +#include "variables.h" +#include "bsint.h" +#include "bs_funcs.h" +#include "core2/statetimer.h" +#include "core2/ba/physics.h" +#include "core2/snackerctl.h" + +u8 D_80363820 = 0; +bsMap D_80363824[] ={ + {BS_1_IDLE, bsstand_init, bsstand_update, bsstand_end, func_802B5350}, + {BS_2_WALK_SLOW, bswalk_slow_init, bswalk_slow_upate, NULL, func_802B5350}, + {BS_WALK, bswalk_init, bswalk_update, NULL, func_802B5350}, + {BS_4_WALK_FAST, bswalk_fast_init, bswalk_fast_update, bswalk_fast_end, func_802B5350}, + {BS_5_JUMP, bsjump_init, bsjump_update, bsjump_end, func_80296608}, + {BS_CLAW, bsclaw_init, bsclaw_update, bsclaw_end, func_80296608}, + {BS_CROUCH, bscrouch_init, bscrouch_update, bscrouch_end, func_802B5350}, + {BS_8_BTROT_JUMP, bsbtrot_jump_init, bsbtrot_jump_update,bsbtrot_jump_end, func_802B5350}, + {BS_SKID, bsturn_init, bsturn_update, bsturn_end, func_802B5350}, + {BS_D_TIMEOUT, func_802B63F8, func_802B64D0, func_802B6500, func_80296590}, + {BS_E_OW, bsow_init, bsow_update, bsow_end, func_80296590}, + {BS_F_BBUSTER, bsbbuster_init, bsbbuster_update, bsbbuster_end, func_80296608}, + {BS_BFLAP, bsbflap_init, bsbflap_update, bsbflap_end, func_80296608}, + {BS_11_BPECK, bsbpeck_init, bsbpeck_update, bsbpeck_end, func_80296608}, + {BS_12_BFLIP, bsbflip_init, bsbflip_update, bsbflip_end, func_80296608}, + {BS_BBARGE, bsbarge_init, bsbarge_update, bsbarge_end, func_80296608}, + {BS_14_BTROT_ENTER, bsbtrot_enter_init, bsbtrot_enter_update, bsbtrot_enter_end, func_802B5350}, + {BS_15_BTROT_IDLE, bsbtrot_stand_init, bsbtrot_stand_update, bsbtrot_stand_end, func_802B5350}, + {BS_16_BTROT_WALK, bsbtrot_walk_init, bsbtrot_walk_update, bsbtrot_walk_end, func_802B5350}, + {BS_17_BTROT_EXIT, bsbtrot_exit_init, bsbtrot_exit_update, bsbtrot_exit_end, func_802B5350}, + {BS_18_FLY_KNOCKBACK, func_802A4D90, func_802A4EC8, func_802A4F44, func_80296608}, + {BS_1A_WONDERWING_ENTER, bsbwhirl_enter_init, bsbwhirl_enter_update, bsbwhirl_enter_end, func_80296608}, + {BS_1B_WONDERWING_IDLE, bsbwhirl_stand_init, bsbwhirl_stand_update, bsbwhirl_stand_end, func_80296608}, + {BS_1C_WONDERWING_WALK, bsbwhirl_walk_init, bsbwhirl_walk_update, bsbwhirl_walk_end, func_80296608}, + {BS_1D_WONDERWING_JUMP, bsbwhirl_jump_init, bsbwhirl_jump_update, bsbwhirl_jump_end, func_80296608}, + {BS_1E_WONDERWING_EXIT, bsbwhirl_exit_init, bsbwhirl_exit_update, bsbwhirl_exit_end, func_80296608}, + {BS_9_EGG_HEAD, bsegghead_init, bsegghead_update, bsegghead_end, func_802B5350}, + {BS_A_EGG_ASS, bseggass_init, bseggass_update, bseggass_end, func_802B5350}, + {BS_WALK_CREEP, bswalk_creep_init, bswalk_creep_update, NULL, func_802B5350}, + {BS_20_LANDING, bsstand_landing_init, bsstand_landing_update, NULL, func_802B5350}, + {BS_BSHOCK_CHARGE, bsbshock_charge_init, bsbshock_charge_update, bsbshock_charge_end, func_80296608}, + {BS_BSHOCK_JUMP, bsbshock_init, bsbshock_update, bsbshock_end, func_80296608}, + {BS_23_FLY_ENTER, bsbfly_enter_init, bsbfly_enter_update, bsbfly_enter_end, func_802A505C}, + {BS_24_FLY, bsbfly_init, bsbfly_update, func_802A3F70, func_802A505C}, + {BS_25_LONGLEG_ENTER, bsblongleg_enter_init, bsblongleg_enter_update, bsblongleg_enter_end, func_802B5350}, + {BS_26_LONGLEG_IDLE, bsblongleg_stand_enter, bsblongleg_stand_update, bsblongleg_stand_end, func_802B5350}, + {BS_LONGLEG_WALK, bsblongleg_walk_init, bsblongleg_walk_update, bsblongleg_walk_end, func_802B5350}, + {BS_LONGLEG_JUMP, bsblongleg_jump_init, bsblongleg_jump_update, bsblongleg_jump_end, func_80296608}, + {BS_LONGLEG_EXIT, bsblongleg_exit_init, bsblongleg_exit_update, bsblongleg_exit_end, func_802B5350}, + {BS_BOMB, func_802A3F9C, func_802A411C, func_802A4404, func_802A505C}, + {BS_2B_DIVE_IDLE, func_802A762C, func_802A7674, func_802A7718, func_80296608}, + {BS_2C_DIVE_B, func_802A7738, func_802A7838, func_802A7A2C, func_80296608}, + {BS_2D_SWIM_IDLE, bsswim_idle_init, bsswim_idle_update, bsswim_idle_end, func_80296608}, + {BS_2E_SWIM, bsswim_swim_init, bsswim_swim_update, bsswim_swim_end, func_80296608}, + {BS_2F_FALL, bsjump_fall_init, bsjump_fall_update, bsjump_fall_end, func_80296608}, + {BS_30_DIVE_ENTER, bsSwim_dive_init, func_802A7E2C, func_802A7F4C, func_80296608}, + {BS_ROLL, bstwirl_init, bstwirl_update, bstwirl_end, func_802B5350}, + {BS_SLIDE, bsslide_init, bsslide_update, bsslide_end, func_802B5350}, + {0x33, func_802B9ACC, func_802B9B14, func_802B9AAC, func_802B9D00}, + {BS_34_JIG_NOTEDOOR, bsjig_notedoor_init, bsjig_notedoor_update, bsjig_notedoor_end, func_80296590}, + {BS_35_ANT_IDLE, bsant_idle_init, bsant_idle_update, bsant_idle_end, func_802B5350}, + {BS_ANT_WALK, bsant_walk_init, bsant_walk_update, bsant_walk_end, func_802B5350}, + {BS_ANT_JUMP, bsant_jump_init, bsant_jump_update, bsant_jump_end, func_802B5350}, + {BS_39_DIVE_A, func_802A7A54, func_802A7AB0, func_802A7BA8, func_80296608}, + {BS_3A_CARRY_IDLE, bscarry_idle_init, bscarry_idle_update, bscarry_idle_end, bscarry_interrupt}, + {BS_3B_CARRY_WALK, bscarry_walk_init, bscarry_walk_update, bscarry_walk_end, bscarry_interrupt}, + {BS_3C_TALK, bstalk_init, bstalk_update, bstalk_end, bstalk_interrupt}, + {BS_3D_FALL_TUMBLING, bsjump_tumble_init, bsjump_tumble_update, bsjump_tumble_end, func_80296608}, + {BS_38_ANT_FALL, bsant_fall_init, bsant_fall_update, bsant_fall_end, func_80296590}, + {BS_3E_ANT_OW, bsant_ow_init, bsant_ow_update, bsant_ow_end, func_80296590}, + {0x3F, func_802B1BF4, func_802B1CF8, func_802B1DA4, func_80296590}, + {BS_40_PUMPKIN_FLUSH, func_802B2BF0, func_802B2C58, func_802B2D50, func_80296590}, + {BS_41_DIE, bsdie_init, bsdie_update, bsdie_end, func_80296590}, + {BS_42_DINGPOT, func_802A5120, func_802A5190, func_802A51C0, func_80296590}, + {BS_43_ANT_DIE, bsant_die_init, bsant_die_update, bsant_die_end, func_80296590}, + {BS_44_JIG_JIGGY, bsjig_jiggy_init, bsjig_jiggy_update, bsjig_jiggy_end, bsjig_jiggy_interrupt}, + {BS_45_BTROT_SLIDE, bsbtrot_slide_init, bsbtrot_slide_update, bsbtrot_slide_end, func_802B5350}, + {0x46, func_802A2098, func_802A2130, func_802A2054, func_80296590}, + {BS_48_PUMPKIN_IDLE, bspumpkin_idle_init, bspumpkin_idle_update, bspumpkin_idle_end, func_802B5350}, + {BS_49_PUMPKIN_WALK, bspumpkin_walk_init, bspumpkin_walk_update, bspumpkin_walk_end, func_802B5350}, + {BS_4A_PUMPKIN_JUMP, bspumpkin_jump_init, bspumpkin_jump_update, bspumpkin_jump_end, func_802B5350}, + {BS_4B_PUMPKIN_FALL, bspumpkin_fall_init, bspumpkin_fall_update, bspumpkin_fall_end, func_802B5350}, + {BS_4C_LANDING_IN_WATER, func_802A846C, func_802A85EC, func_802A872C, func_80296608}, + {BS_4D_PUMPKIN_OW, __bspumpkin_ow_init, __bspumpkin_ow_update, __bspumpkin_ow_end, func_80296590}, + {BS_4E_PUMPKIN_DIE, bspumpkin_die_init, bspumpkin_die_update, bspumpkin_die_end, func_80296590}, + {BS_4F_CLIMB_IDLE, bsclimb_idle_init, bsclimb_idle_update, bsclimb_idle_end, func_802ABD60}, + {BS_50_CLIMB_MOVE, bsclimb_move_init, bsclimb_move_update, bsclimb_move_end, func_802ABD60}, + {BS_51_CLIMB_EXIT, func_802B1928, func_802B1A54, func_802B1BCC, func_80296608}, + {0x52, func_802B5FD0, func_802B6064, func_802B60D0, func_802B60D8}, + {BS_53_TIMEOUT, func_802B6270, func_802B6314, func_802B63C8, func_80296590}, + {BS_LONGLEG_SLIDE, bsblongleg_slide_init, bsblongleg_slide_update, bsblongleg_slide_end, func_802B5350}, + {BS_56_RECOIL, func_802B3868, func_802B3954, func_802B3A20, func_80296590}, + {BS_57_BOMB_END, func_802A4430, func_802A4548, func_802A4664, func_802A505C}, + {BS_58_BEAKBOMB_CRASH, bsbfly_beakbomb_crash_init, func_802A48B4, func_802A4A40, func_80296590}, + {0x59, func_802A4CD0, func_802A4CF0, func_802A4D10, func_802A505C}, + {BS_54_SWIM_DIE, func_802A7F6C, func_802A8098, func_802A82D4, func_80296590}, + {BS_CARRY_THROW, bsthrow_init, bsthrow_update, bsthrow_end, bsthrow_interrupt}, + {BS_5E_CROC_IDLE, bscroc_idle_init, bscroc_idle_update, bscroc_idle_end, func_802B5350}, + {BS_CROC_WALK, bscroc_walk_init, bscroc_walk_update, bscroc_walk_end, func_802B5350}, + {BS_CROC_JUMP, bscroc_jump_init, bscroc_jump_update, bscroc_jump_end, func_802B5350}, + {BS_61_CROC_FALL, bscroc_fall_init, bscroc_fall_update, bscroc_fall_end, func_802B5350}, + {BS_62_LONGLEG_LOCKED, func_802A6394, func_802A63F0, func_802A6450, func_80296608}, + {BS_CROC_OW, bscroc_ow_init, bscroc_ow_update, bscroc_ow_end, func_80296590}, + {BS_CROC_OW, bscroc_die_init, bscroc_die_update, bscroc_die_end, func_80296590}, + {BS_67_WALRUS_IDLE, bswalrus_idle_init, bswalrus_idle_update, bswalrus_idle_end, func_802B5350}, + {BS_WALRUS_WALK, bswalrus_walk_init, bswalrus_walk_update, bswalrus_walk_end, func_802B5350}, + {BS_WALRUS_JUMP, bswalrus_jump_init, bswalrus_jump_update, bswalrus_jump_end, func_802B5350}, + {BS_6A_WALRUS_FALL, bswalrus_fall_init, bswalrus_fall_update, bswalrus_fall_end, func_802B5350}, + {0x6B, func_802A1F6C, func_802A1FC8, func_802A2014, func_80296608}, + {BS_WALRUS_OW, bswalrus_ow_init, bswalrus_ow_update, bswalrus_ow_end, func_80296590}, + {BS_WALRUS_DIE, bswalrus_die_init, bswalrus_die_update, bswalrus_die_end, func_80296590}, + {BS_6E_CROC_BITE, bscroc_bite_init, bscroc_bite_update, bscroc_bite_end, func_802B5350}, + {BS_CROC_EAT_BAD, bscroc_eat_bad_init, bscroc_eat_bad_update, bscroc_eat_bad_end, func_802B5350}, + {BS_70_CROC_EAT_GOOD, bscroc_eat_good_init, bscroc_eat_good_update, bscroc_eat_good_end, func_802B5350}, + {BS_71_BTROT_FALL, bsbtrot_fall_init, bsbtrot_fall_update, bsbtrot_fall_end, func_80296608}, + {BS_SPLAT, bssplat_init, bssplat_update, bssplat_end, func_80296590}, + {0x00000073, func_802B3CEC, func_802B3D1C, func_802B3D6C, func_80296608}, + {0x00000074, func_802B3E2C, func_802B3E64, func_802B3EF4, func_80296608}, + {0x00000075, func_802B3D8C, func_802B3DBC, func_802B3E0C, func_80296608}, + {0x00000076, func_802A4F74, func_802A4FC8, func_802A503C, func_80296608}, + {0x00000077, bsswim_lookat_init, bsswim_lookat_update, bsswim_lookat_end, func_80296608}, + {0x00000078, bsbswim_lookat_init, bsbswim_lookat_update, bsbswim_lookat_end, func_80296608}, + {0x00000079, bsbtrot_unk79_init, bsbtrot_unk79_update, bsbtrot_unk79_end, func_80296608}, + {BS_WALK_MUD, bswalk_mud_init, bswalk_mud_update, NULL, func_80296608}, + {BS_BTROT_OW, bsbtrot_ow_init, bsbtrot_ow_update, bsbtrot_ow_end, func_80296590}, + {BS_7C_SLED, bssled_init, bssled_update, bssled_end, bssled_interrupt}, + {BS_7D_WALRUS_SLED, bswalrus_sled_init, bswalrus_sled_update, bswalrus_sled_end, func_802B98C0}, + {BS_7E_WALRUS_SLED, bswalrus_sled_jump_init, bswalrus_sled_jump_update, bswalrus_sled_jump_end, func_802B98C0}, + {BS_7F_DIVE_OW, func_802A7BD0, func_802A7CA8, func_802A7D74, func_80296590}, + {0x00000080, bswalrus_timeout_init, func_802B9830, func_802B9880, func_80296590}, + {0x00000081, func_802B90D0, func_802B9130, func_802B917C, func_802B98C0}, + {0x00000082, func_802B95A0, func_802B963C, func_802B976C, func_802B98C0}, + {BS_85_BEE_IDLE, func_802A1080, func_802A10D4, func_802A117C, func_802B5350}, + {BS_BEE_WALK, func_802A11A4, func_802A1214, func_802A12D4, func_802B5350}, + {BS_BEE_JUMP, func_802A12FC, func_802A1438, func_802A163C, func_802B5350}, + {BS_88_BEE_FALL, func_802A1664, func_802A170C, func_802A18C8, func_802B5350}, + {BS_BEE_OW, func_802A1B68, func_802A1B88, func_802A1BA8, func_802B5350}, + {BS_BEE_DIE, bsbeemain_die_init, func_802A1DD8, func_802A1F2C, func_80296590}, + {0x0000008B, func_802A0590, func_802A0630, func_802A0704, func_802B5350}, + {BS_BEE_FLY, bsbeefly_enter, bsbeefly_update, bsbeefly_end, func_802B5350}, + {BS_8D_CROC_LOCKED, bscroc_locked_enter, bscroc_locked_update, bscroc_locked_end, func_802B5350}, + {0x0000008E, func_8029F398, func_8029F3F4, func_8029F440, func_802B5350}, + {BS_8F_PUMPKIN_LOCKED, func_802B34A0, func_802B34F8, func_802B353C, func_802B5350}, + {BS_FLY_OW, func_802A4D30, func_802A4D50, func_802A4D70, func_802A505C}, + {BS_92_ANT_DRONE, bsant_drone_init, bsant_drone_update, bsant_drone_end, bsdrone_interrupt}, + {BS_93_PUMPKIN_DRONE, bspumpkin_drone_init, bspumpkin_drone_update, bspumpkin_drone_end, bsdrone_interrupt}, + {BS_94_CROC_DRONE, bscroc_drone_init, bscroc_drone_update, bscroc_drone_end, bsdrone_interrupt}, + {BS_95_WALRUS_DRONE, bswalrus_drone_init, bswalrus_drone_update, bswalrus_drone_end, bsdrone_interrupt}, + {BS_96_SWIM_DRONE, bsswim_drone_init, bsswim_drone_update, bsswim_drone_end, bsdrone_interrupt}, + {BS_97_DIVE_DRONE, bsbswim_drone_init, bsbswim_drone_update, bsbswim_drone_end, bsdrone_interrupt}, + {BS_98_WALK_DRONE, bswalk_drone_init, bswalk_drone_update, bswalk_drone_end, bsdrone_interrupt}, + {0x00000099, func_802A50B0, func_802A50D8, func_802A50F8, bsdrone_interrupt}, + {BS_9A_BTROT_DRONE, bsbtrot_drone_init, bsbtrot_drone_update, bsbtrot_drone_end, bsdrone_interrupt}, + {BS_9B_LONGLEG_DRONE, bsblongleg_drone_init, bsblongleg_drone_update, bsblongleg_drone_end, bsdrone_interrupt}, + {0x0000009C, bswalrus_sled_drone_init, bswalrus_sled_drone_update, bswalrus_sled_drone_end, bsdrone_interrupt}, + {BS_9D_BEE_DRONE, bsbee_drone_init, bsbee_drone_update, bsbee_drone_end, bsdrone_interrupt}, + {0x0000009E, func_802ABCCC, func_802ABD0C, func_802ABD40, func_802ABD60}, + {BS_ANT_BOUNCE, bsant_bounce_init, bsant_bounce_update, bsant_bounce_end, func_80296590}, + {BS_PUMPKIN_BOUNCE, bspumpkin_rebound_init, bspumpkin_rebound_update, bspumpkin_rebound_end, func_80296590}, + {BS_CROC_BOUNCE, bscroc_bounce_init, bscroc_bounce_update, bscroc_bounce_end, func_80296590}, + {BS_WALRUS_BOUNCE, bswalrus_bounce_init, bswalrus_bounce_update, bswalrus_bounce_end, func_80296590}, + {BS_BEE_BOUNCE, func_802A1BC8, func_802A1BE8, func_802A1C08, func_80296590}, + {BS_A4_WONDERWING_DRONE, bsbwhirl_drone_init, bsbwhirl_drone_update, bsbwhirl_drone_end, func_80296608}, + {BS_A5_WONDERWING_UNKA5, func_802AADBC, func_802AAE08, func_802AAE4C, func_80296608}, + {0} +}; + +/* .bss */ +void (*D_8037C3B0)(); + +/* .code */ +void func_802958A0(void){ + s32 i; + bsMap *iPtr; + + for(i = 0; D_80363824[i].uid != 0; i++){ + bsList_setInitMethod(D_80363824[i].uid, D_80363824[i].behavior.init_func); + bsList_setUpdateMethod(D_80363824[i].uid, D_80363824[i].behavior.update_func); + bsList_setEndMethod(D_80363824[i].uid, D_80363824[i].behavior.end_func); + bsList_setInterruptMethod(D_80363824[i].uid, D_80363824[i].behavior.interrupt_func); + } +} + +void func_80295914(void){ + D_80363820 = 1; + D_8037C3B0 = NULL; + update_void_return_Location(); + playerPosition_init(); + snackerctl_reset(); + func_80291910(); + badrone_init(); + bafalldamage_init(); + baflag_clearAll(); + func_8028B6FC(); + func_80291590(); + bakey_reset(); + bastick_reset(); + bainput_reset(); + bsList_clearAll(); + bs_clearState(); + babounds_init(); + func_80296C30(); + baphysics_init(); + baiFrame_reset(); + pitch_reset(); + climbClear(); + balookat_init(); + roll_reset(); + func_802992F0(); + func_80294DD8(); + func_8029CF6C(); + func_8029DFF8(); + func_80290B6C(); + baeyes_reset(); + func_80290070(); + func_80290664(); + stateTimer_init(); + eggShatter_init(); + bacarry_init(); + func_80293DA4(); + baAnim_init(); + baModel_reset(); + baMarker_init(); + basfx_reset(); + func_8029A4D0(); + func_8029ADCC(); + hazards_reset(); + func_802958A0(); +} + +void func_80295A8C(void){ + + stateTimer_set(STATE_TIMER_2_LONGLEG, bsStoredState_getLongLegTimer()); + stateTimer_set(STATE_TIMER_3_TURBO_TALON, bsStoredState_getTurboTimer()); + if(func_8028ADB4()) + bs_setState(badrone_enter()); + else + bs_setState(bs_getIdleState()); + +} + +void func_80295B04(void){ + f32 sp24; + enum bs_e sp20 = bs_getState(); + bool is_in_talon_trot; + + sp24 = (bslongleg_inSet(sp20)) ? stateTimer_get(STATE_TIMER_2_LONGLEG) : 0.0f; + bsStoredState_setLongLegTimer(sp24); + sp24 = 0.0f; + is_in_talon_trot = false; + if(bsbtrot_inSet(sp20)){ + sp24 = stateTimer_get(STATE_TIMER_3_TURBO_TALON); + is_in_talon_trot = true; + } + + bsStoredState_setTrot(is_in_talon_trot); + bsStoredState_setTurboTimer(sp24); + bs_setState(BS_5A_LOADZONE); + baMarker_free(); + func_8029065C(); + stateTimer_free(); + eggShatter_free(); + baModel_free(); + baAnim_free(); + func_80293E88(); + bacarry_end(); + basfx_free(); + func_8029A54C(); + func_8029ADA8(); + freeHazardSfxId(); + D_80363820 = 0; +} + +void func_80295C08(void (* arg0)(void)){ + D_8037C3B0 = arg0; +} + +void func_80295C14(void){ + func_802964B8(); + balookat_update(); + stateTimer_update(); + func_8029E100(); + pfsManager_update();//controller_update + disableInput_set(); + bakey_update(); + bastick_update(); + bainput_update(); //dive_cooldown_update + bs_updateState(); + baphysics_update(); + playerPosition_applyOffset(); + bafalldamage_update(); + func_80293F0C(); + pitch_update(); + roll_update(); + func_802993C8();//yaw update + func_802906D8(); + baAnim_update(); + func_8029A554(); + func_80298344(); //climb_cooldown_update + func_80290108(); + eggShatter_update(); + baeyes_update(); + baModel_update(); + playerPosition_func_8029842C(); + baMarker_update(); + bacarry_update(); + snackerctl_update(); + func_8028B71C(); + hazards_update(); + baiFrame_update(); + func_80294E60(); + cameraMode_update(); + func_802919A0(); + if(D_8037C3B0){ + D_8037C3B0(); + D_8037C3B0 = NULL; + } + basfx_update(); + babounds_update();//voidOut_update +} + +void func_80295D74(void){ + if(D_80363820){ + baAnim_defrag(); + baModel_defrag(); + eggShatter_defrag(); + func_80294750(); + func_8029AF1C(); + } +} diff --git a/src/core2/ba/ba_statusflags.c b/src/core2/ba/ba_statusflags.c index 866f0e15d..c0707812e 100644 --- a/src/core2/ba/ba_statusflags.c +++ b/src/core2/ba/ba_statusflags.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9C170.c #include #include "functions.h" #include "variables.h" @@ -330,7 +329,7 @@ void func_8032417C(struct56s *arg0, f32 arg1, f32 arg2[3], f32 arg3[3]) { func_80341180(var_f0, sp64, 3, sp60, sp44); ml_vec3f_diff_copy(arg2, sp44, sp50); ml_vec3f_normalize(arg2); - ml_horizontal_and_vertical_angles(sp44[0], sp44[1], sp44[2], sp50[0], sp50[1], sp50[2], &arg3[0], &arg3[1]); + func_8025727C(sp44[0], sp44[1], sp44[2], sp50[0], sp50[1], sp50[2], &arg3[0], &arg3[1]); arg3[0] = mlNormalizeAngle(-arg3[0]); arg3[2] = 0.0f; } diff --git a/src/core2/ba/bastick.c b/src/core2/ba/ba_stick.c similarity index 98% rename from src/core2/ba/bastick.c rename to src/core2/ba/ba_stick.c index 4e56e29ff..63b2ce6e2 100644 --- a/src/core2/ba/bastick.c +++ b/src/core2/ba/ba_stick.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bastick.c #include #include "core1/core1.h" #include "functions.h" @@ -140,7 +139,7 @@ void bastick_setZoneMax(s32 zone_id, f32 value){ f32 bastick_getAngleRelativeToBanjo(void){ f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); return viewport_adjustAngleToRight(sp1C, bastick_getAngle()); } diff --git a/src/core2/ba/ba_stickinterp.c b/src/core2/ba/ba_stickinterp.c index 1090b41fa..f1c65a47f 100644 --- a/src/core2/ba/ba_stickinterp.c +++ b/src/core2/ba/ba_stickinterp.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_11040.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/batimer.c b/src/core2/ba/ba_timer.c similarity index 93% rename from src/core2/ba/batimer.c rename to src/core2/ba/ba_timer.c index 87cc37caa..eec243169 100644 --- a/src/core2/ba/batimer.c +++ b/src/core2/ba/ba_timer.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/batimer.c #include #include "functions.h" #include "variables.h" @@ -16,10 +15,10 @@ void batimer_incrementBy(s32 id, f32 inc_value_sec){ s_batimer.value[id] += inc_value_sec; } -bool batimer_decrement(s32 id){ +int batimer_decrement(s32 id){ s_batimer.last[id] = s_batimer.value[id]; if(0.0f == s_batimer.value[id]){ - return false; + return 0; } s_batimer.value[id] = ml_max_f(0.0f, s_batimer.value[id] - time_getDelta()); return s_batimer.value[id] == 0.0f; diff --git a/src/core2/ba/ba_underwater.c b/src/core2/ba/ba_underwater.c index b5f0b42b9..00febdde0 100644 --- a/src/core2/ba/ba_underwater.c +++ b/src/core2/ba/ba_underwater.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_15F20.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/ba_yaw.c b/src/core2/ba/ba_yaw.c index 1fd1402d2..dc08799af 100644 --- a/src/core2/ba/ba_yaw.c +++ b/src/core2/ba/ba_yaw.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_12360.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ba/bsmethods.c b/src/core2/ba/bsmethods.c deleted file mode 100644 index 25e520266..000000000 --- a/src/core2/ba/bsmethods.c +++ /dev/null @@ -1,335 +0,0 @@ -// BanjoDecomp: core2/bsmethods.c -#include -#include "functions.h" -#include "variables.h" -#include "bsint.h" -#include "bs_funcs.h" -#include "core2/statetimer.h" -#include "core2/ba/physics.h" -#include "core2/snackerctl.h" - -u8 D_80363820 = 0; - -bsMap bsMethodsTable[] = { - //Banjo States Initialize Funcitons Update Functions End Functions Interrupt Functions - {BS_1_IDLE, bsstand_init, bsstand_update, bsstand_end, func_802B5350}, - {BS_2_WALK_SLOW, bswalk_slow_init, bswalk_slow_upate, NULL, func_802B5350}, - {BS_3_WALK, bswalk_init, bswalk_update, NULL, func_802B5350}, - {BS_4_WALK_FAST, bswalk_fast_init, bswalk_fast_update, bswalk_fast_end, func_802B5350}, - {BS_5_JUMP, bsjump_init, bsjump_update, bsjump_end, func_80296608}, - {BS_6_CLAW, bsclaw_init, bsclaw_update, bsclaw_end, func_80296608}, - {BS_7_CROUCH, bscrouch_init, bscrouch_update, bscrouch_end, func_802B5350}, - {BS_8_BTROT_JUMP, bsbtrot_jump_init, bsbtrot_jump_update, bsbtrot_jump_end, func_802B5350}, - {BS_C_SKID, bsturn_init, bsturn_update, bsturn_end, func_802B5350}, - {BS_D_TIMEOUT_TRANSFORMATION, timeout_transformation_init, timeout_transformation_update, timeout_transformation_end, func_80296590}, - {BS_E_OW, bsow_init, bsow_update, bsow_end, func_80296590}, - {BS_F_BBUSTER, bsbbuster_init, bsbbuster_update, bsbbuster_end, func_80296608}, - {BS_10_BFLAP, bsbflap_init, bsbflap_update, bsbflap_end, func_80296608}, - {BS_11_BPECK, bsbpeck_init, bsbpeck_update, bsbpeck_end, func_80296608}, - {BS_12_BFLIP, bsbflip_init, bsbflip_update, bsbflip_end, func_80296608}, - {BS_13_BBARGE, bsbarge_init, bsbarge_update, bsbarge_end, func_80296608}, - {BS_14_BTROT_ENTER, bsbtrot_enter_init, bsbtrot_enter_update, bsbtrot_enter_end, func_802B5350}, - {BS_15_BTROT_IDLE, bsbtrot_stand_init, bsbtrot_stand_update, bsbtrot_stand_end, func_802B5350}, - {BS_16_BTROT_WALK, bsbtrot_walk_init, bsbtrot_walk_update, bsbtrot_walk_end, func_802B5350}, - {BS_17_BTROT_EXIT, bsbtrot_exit_init, bsbtrot_exit_update, bsbtrot_exit_end, func_802B5350}, - {BS_18_FLY_KNOCKBACK, bsbfly_knockback_init, bsbfly_knockback_update, bsbfly_knockback_end, func_80296608}, - {BS_1A_WONDERWING_ENTER, bsbwhirl_enter_init, bsbwhirl_enter_update, bsbwhirl_enter_end, func_80296608}, - {BS_1B_WONDERWING_IDLE, bsbwhirl_stand_init, bsbwhirl_stand_update, bsbwhirl_stand_end, func_80296608}, - {BS_1C_WONDERWING_WALK, bsbwhirl_walk_init, bsbwhirl_walk_update, bsbwhirl_walk_end, func_80296608}, - {BS_1D_WONDERWING_JUMP, bsbwhirl_jump_init, bsbwhirl_jump_update, bsbwhirl_jump_end, func_80296608}, - {BS_1E_WONDERWING_EXIT, bsbwhirl_exit_init, bsbwhirl_exit_update, bsbwhirl_exit_end, func_80296608}, - {BS_9_EGG_HEAD, bsegghead_init, bsegghead_update, bsegghead_end, func_802B5350}, - {BS_A_EGG_ASS, bseggass_init, bseggass_update, bseggass_end, func_802B5350}, - {BS_1F_WALK_CREEP, bswalk_creep_init, bswalk_creep_update, NULL, func_802B5350}, - {BS_20_LANDING, bsstand_landing_init, bsstand_landing_update, NULL, func_802B5350}, - {BS_21_BSHOCK_CHARGE, bsbshock_charge_init, bsbshock_charge_update, bsbshock_charge_end, func_80296608}, - {BS_22_BSHOCK_JUMP, bsbshock_init, bsbshock_update, bsbshock_end, func_80296608}, - {BS_23_FLY_ENTER, bsbfly_enter_init, bsbfly_enter_update, bsbfly_enter_end, func_802A505C}, - {BS_24_FLY, bsbfly_init, bsbfly_update, bsbfly_end, func_802A505C}, - {BS_25_LONGLEG_ENTER, bsblongleg_enter_init, bsblongleg_enter_update, bsblongleg_enter_end, func_802B5350}, - {BS_26_LONGLEG_IDLE, bsblongleg_stand_enter, bsblongleg_stand_update, bsblongleg_stand_end, func_802B5350}, - {BS_27_LONGLEG_WALK, bsblongleg_walk_init, bsblongleg_walk_update, bsblongleg_walk_end, func_802B5350}, - {BS_28_LONGLEG_JUMP, bsblongleg_jump_init, bsblongleg_jump_update, bsblongleg_jump_end, func_80296608}, - {BS_29_LONGLEG_EXIT, bsblongleg_exit_init, bsblongleg_exit_update, bsblongleg_exit_end, func_802B5350}, - {BS_2A_BOMB, bsbfly_bomb_init, bsbfly_bomb_update, bsbfly_bomb_end, func_802A505C}, - {BS_2B_DIVE_IDLE, bsbdive_idle_init, bsbdive_idle_update, bsbdive_idle_end, func_80296608}, - {BS_2C_DIVE_B, bsbdiveb_init, bsbdiveb_update, bsbdiveb_end, func_80296608}, - {BS_2D_SWIM_IDLE, bsswim_idle_init, bsswim_idle_update, bsswim_idle_end, func_80296608}, - {BS_2E_SWIM, bsswim_swim_init, bsswim_swim_update, bsswim_swim_end, func_80296608}, - {BS_2F_FALL, bsjump_fall_init, bsjump_fall_update, bsjump_fall_end, func_80296608}, - {BS_30_DIVE_ENTER, bsSwim_dive_init, bsSwim_dive_update, bsSwim_dive_end, func_80296608}, - {BS_31_ROLL, bstwirl_init, bstwirl_update, bstwirl_end, func_802B5350}, - {BS_32_SLIDE, bsslide_init, bsslide_update, bsslide_end, func_802B5350}, - {BS_33_WASHY_UNKNOWN, bswashy_init, bswashy_update, bswashy_end, func_802B9D00}, - {BS_34_JIG_NOTEDOOR, bsjig_notedoor_init, bsjig_notedoor_update, bsjig_notedoor_end, func_80296590}, - {BS_35_ANT_IDLE, bsant_idle_init, bsant_idle_update, bsant_idle_end, func_802B5350}, - {BS_36_ANT_WALK, bsant_walk_init, bsant_walk_update, bsant_walk_end, func_802B5350}, - {BS_37_ANT_WALK, bsant_jump_init, bsant_jump_update, bsant_jump_end, func_802B5350}, - {BS_39_DIVE_A, bsswim_divea_init, bsswim_divea_update, bsswim_divea_end, func_80296608}, - {BS_3A_CARRY_IDLE, bscarry_idle_init, bscarry_idle_update, bscarry_idle_end, bscarry_interrupt}, - {BS_3B_CARRY_WALK, bscarry_walk_init, bscarry_walk_update, bscarry_walk_end, bscarry_interrupt}, - {BS_3C_TALK, bstalk_init, bstalk_update, bstalk_end, bstalk_interrupt}, - {BS_3D_FALL_TUMBLING, bsjump_tumble_init, bsjump_tumble_update, bsjump_tumble_end, func_80296608}, - {BS_38_ANT_FALL, bsant_fall_init, bsant_fall_update, bsant_fall_end, func_80296590}, - {BS_3E_ANT_OW, bsant_ow_init, bsant_ow_update, bsant_ow_end, func_80296590}, - {BS_3F_UNKNOWN, func_802B1BF4, func_802B1CF8, func_802B1DA4, func_80296590}, - {BS_40_PUMPKIN_FLUSH, bspumpkin_flush_init, bspumpkin_flush_update, bspumpkin_flush_end, func_80296590}, - {BS_41_DIE, bsdie_init, bsdie_update, bsdie_end, func_80296590}, - {BS_42_DINGPOT, bsfly_dingpotLaunch_init, bsfly_dingpotLaunch_update, bsfly_dingpotLaunch_end, func_80296590}, - {BS_43_ANT_DIE, bsant_die_init, bsant_die_update, bsant_die_end, func_80296590}, - {BS_44_JIG_JIGGY, bsjig_jiggy_init, bsjig_jiggy_update, bsjig_jiggy_end, bsjig_jiggy_interrupt}, - {BS_45_BTROT_SLIDE, bsbtrot_slide_init, bsbtrot_slide_update, bsbtrot_slide_end, func_802B5350}, - {BS_46_UNKNOWN, func_802A2098, func_802A2130, func_802A2054, func_80296590}, - {BS_48_PUMPKIN_IDLE, bspumpkin_idle_init, bspumpkin_idle_update, bspumpkin_idle_end, func_802B5350}, - {BS_49_PUMPKIN_WALK, bspumpkin_walk_init, bspumpkin_walk_update, bspumpkin_walk_end, func_802B5350}, - {BS_4A_PUMPKIN_JUMP, bspumpkin_jump_init, bspumpkin_jump_update, bspumpkin_jump_end, func_802B5350}, - {BS_4B_PUMPKIN_FALL, bspumpkin_fall_init, bspumpkin_fall_update, bspumpkin_fall_end, func_802B5350}, - {BS_4C_LANDING_IN_WATER, bsbswim_landingInWater_init, bsbswim_landingInWater_update, bsbswim_landingInWater_end, func_80296608}, - {BS_4D_PUMPKIN_OW, __bspumpkin_ow_init, __bspumpkin_ow_update, __bspumpkin_ow_end, func_80296590}, - {BS_4E_PUMPKIN_DIE, bspumpkin_die_init, bspumpkin_die_update, bspumpkin_die_end, func_80296590}, - {BS_4F_CLIMB_IDLE, bsclimb_idle_init, bsclimb_idle_update, bsclimb_idle_end, func_802ABD60}, - {BS_50_CLIMB_MOVE, bsclimb_move_init, bsclimb_move_update, bsclimb_move_end, func_802ABD60}, - {BS_51_CLIMB_EXIT, bsjump_climbExit_init, bsjump_climbExit_update, bsjump_climbExit_end, func_80296608}, - {BS_52_SURF, bssurf_init, bssurf_update, bssurf_end, func_802B60D8}, - {BS_53_TIMEOUT_BANJO, timeout_banjo_init, timeout_banjo_update, timeout_banjo_end, func_80296590}, - {BS_55_LONGLEG_SLIDE, bsblongleg_slide_init, bsblongleg_slide_update, bsblongleg_slide_end, func_802B5350}, - {BS_56_RECOIL, rebound_init, rebound_update, rebound_end, func_80296590}, - {BS_57_BOMB_END, bsbfly_beakbombend_init, bsbfly_beakbombend_update, bsbfly_beakbombend_end, func_802A505C}, - {BS_58_BEAKBOMB_CRASH, bsbfly_beakbomb_crash_init, func_802A48B4, func_802A4A40, func_80296590}, - {BS_59_BFLY_UNK59, func_802A4CD0, func_802A4CF0, func_802A4D10, func_802A505C}, - {BS_54_SWIM_DIE, bsbswim_die_init, bsbswim_die_update, bsbswim_die_end, func_80296590}, - {BS_5B_CARRY_THROW, bsthrow_init, bsthrow_update, bsthrow_end, bsthrow_interrupt}, - {BS_5E_CROC_IDLE, bscroc_idle_init, bscroc_idle_update, bscroc_idle_end, func_802B5350}, - {BS_5F_CROC_WALK, bscroc_walk_init, bscroc_walk_update, bscroc_walk_end, func_802B5350}, - {BS_60_CROC_JUMP, bscroc_jump_init, bscroc_jump_update, bscroc_jump_end, func_802B5350}, - {BS_61_CROC_FALL, bscroc_fall_init, bscroc_fall_update, bscroc_fall_end, func_802B5350}, - {BS_62_LONGLEG_LOCKED, bsblongleg_locked_init, bsblongleg_locked_update, bsblongleg_locked_end, func_80296608}, - {BS_63_CROC_OW, bscroc_ow_init, bscroc_ow_update, bscroc_ow_end, func_80296590}, - {BS_64_CROC_DIE, bscroc_die_init, bscroc_die_update, bscroc_die_end, func_80296590}, - {BS_67_WALRUS_IDLE, bswalrus_idle_init, bswalrus_idle_update, bswalrus_idle_end, func_802B5350}, - {BS_68_WALRUS_WALK, bswalrus_walk_init, bswalrus_walk_update, bswalrus_walk_end, func_802B5350}, - {BS_69_WALRUS_JUMP, bswalrus_jump_init, bswalrus_jump_update, bswalrus_jump_end, func_802B5350}, - {BS_6A_WALRUS_FALL, bswalrus_fall_init, bswalrus_fall_update, bswalrus_fall_end, func_802B5350}, - {BS_6B_BEE_LOCKED, bsbee_locked_init, bsbee_locked_update, bsbee_locked_end, func_80296608}, - {BS_6C_WALRUS_OW, bswalrus_ow_init, bswalrus_ow_update, bswalrus_ow_end, func_80296590}, - {BS_6D_WALRUS_DIE, bswalrus_die_init, bswalrus_die_update, bswalrus_die_end, func_80296590}, - {BS_6E_CROC_BITE, bscroc_bite_init, bscroc_bite_update, bscroc_bite_end, func_802B5350}, - {BS_6F_CROC_EAT_BAD, bscroc_eat_bad_init, bscroc_eat_bad_update, bscroc_eat_bad_end, func_802B5350}, - {BS_70_CROC_EAT_GOOD, bscroc_eat_good_init, bscroc_eat_good_update, bscroc_eat_good_end, func_802B5350}, - {BS_71_BTROT_FALL, bsbtrot_fall_init, bsbtrot_fall_update, bsbtrot_fall_end, func_80296608}, - {BS_72_SPLAT, bssplat_init, bssplat_update, bssplat_end, func_80296590}, - {BS_73_UNKNOWN, bsrest_bs73unknown_init, bsrest_bs73unknown_update, bsrest_bs73unknown_end, func_80296608}, - {BS_74_UNKNOWN, bsrest_bs74unknown_init, bsrest_bs74unknown_update, bsrest_bs74unknown_end, func_80296608}, - {BS_75_UNKNOWN, bsrest_bs75unknown_init, bsrest_bs75unknown_update, bsrest_bs75unknown_end, func_80296608}, - {BS_76_BFLY_LOCKED, bsbfly_locked_init, bsbfly_locked_update, bsbfly_locked_end, func_80296608}, - {BS_77_SWIM_LOOKAT_DRONE, bsswim_lookat_init, bsswim_lookat_update, bsswim_lookat_end, func_80296608}, - {BS_78_DIVE_LOOKAT_DRONE, bsbswim_lookat_init, bsbswim_lookat_update, bsbswim_lookat_end, func_80296608}, - {BS_79_BTROT_LOCKED, bsbtrot_locked_init, bsbtrot_locked_update, bsbtrot_locked_end, func_80296608}, - {BS_7A_WALK_MUD, bswalk_mud_init, bswalk_mud_update, NULL, func_80296608}, - {BS_7B_BTROT_OW, bsbtrot_ow_init, bsbtrot_ow_update, bsbtrot_ow_end, func_80296590}, - {BS_7C_SLED, bssled_init, bssled_update, bssled_end, bssled_interrupt}, - {BS_7D_WALRUS_SLED, bswalrus_sled_init, bswalrus_sled_update, bswalrus_sled_end, func_802B98C0}, - {BS_7E_WALRUS_SLED, bswalrus_sled_jump_init, bswalrus_sled_jump_update, bswalrus_sled_jump_end, func_802B98C0}, - {BS_7F_DIVE_OW, bsbswim_ow_init, bsbswim_ow_update, bsbswim_ow_end, func_80296590}, - {BS_80_WALRUS_SLED_LOSE, bswalrus_timeout_init, bswalrus_timeout_update, bswalrus_timeout_end, func_80296590}, - {BS_81_WALRUS_SLED_LOCKED, bswalrus_sledlocked_init, bswalrus_sledlocked_update, bswalrus_sledlocked_end, func_802B98C0}, - {BS_82_WALRUS_SLED_LOSE_IN_AIR,bswalrus_sledloseinair_init, bswalrus_sledloseinair_update, bswalrus_sledloseinair_end, func_802B98C0}, - {BS_85_BEE_IDLE, bsbeemain_idle_init, bsbeemain_idle_update, bsbeemain_idle_end, func_802B5350}, - {BS_86_BEE_WALK, bsbeemain_walk_init, bsbeemain_walk_update, bsbeemain_walk_end, func_802B5350}, - {BS_87_BEE_JUMP, bsbeemain_jump_init, bsbeemain_jump_update, bsbeemain_jump_end, func_802B5350}, - {BS_88_BEE_FALL, bsbeemain_fall_init, bsbeemain_fall_update, bsbeemain_fall_end, func_802B5350}, - {BS_89_BEE_OW, bsbeemain_ow_init, bsbeemain_ow_update, bsbeemain_ow_end, func_802B5350}, - {BS_8A_BEE_DIE, bsbeemain_die_init, bsbeemain_die_update, bsbeemain_die_end, func_80296590}, - {BS_8B_UNKNOWN, bsbeefly_bs8Bunknown_init, bsbeefly_bs8Bunknown_update, bsbeefly_bs8Bunknown_end, func_802B5350}, - {BS_8C_BEE_FLY, bsbeefly_enter, bsbeefly_update, bsbeefly_end, func_802B5350}, - {BS_8D_CROC_LOCKED, bscroc_locked_enter, bscroc_locked_update, bscroc_locked_end, func_802B5350}, - {BS_8E_ANT_LOCKED, bsant_locked_init, bsant_locked_update, bsant_locked_end, func_802B5350}, - {BS_8F_PUMPKIN_LOCKED, bspumpkin_locked_init, bspumpkin_locked_update, bspumpkin_locked_end, func_802B5350}, - {BS_91_FLY_OW, bsbfly_ow_init, bsbfly_ow_update, bsbfly_ow_end, func_802A505C}, - {BS_92_ANT_DRONE, bsant_drone_init, bsant_drone_update, bsant_drone_end, bsdrone_interrupt}, - {BS_93_PUMPKIN_DRONE, bspumpkin_drone_init, bspumpkin_drone_update, bspumpkin_drone_end, bsdrone_interrupt}, - {BS_94_CROC_DRONE, bscroc_drone_init, bscroc_drone_update, bscroc_drone_end, bsdrone_interrupt}, - {BS_95_WALRUS_DRONE, bswalrus_drone_init, bswalrus_drone_update, bswalrus_drone_end, bsdrone_interrupt}, - {BS_96_SWIM_DRONE, bsswim_drone_init, bsswim_drone_update, bsswim_drone_end, bsdrone_interrupt}, - {BS_97_DIVE_DRONE, bsbswim_drone_init, bsbswim_drone_update, bsbswim_drone_end, bsdrone_interrupt}, - {BS_98_WALK_DRONE, bswalk_drone_init, bswalk_drone_update, bswalk_drone_end, bsdrone_interrupt}, - {BS_99_BFLY_DRONE, bsbfly_drone_init, bsbfly_drone_update, bsbfly_drone_end, bsdrone_interrupt}, - {BS_9A_BTROT_DRONE, bsbtrot_drone_init, bsbtrot_drone_update, bsbtrot_drone_end, bsdrone_interrupt}, - {BS_9B_LONGLEG_DRONE, bsblongleg_drone_init, bsblongleg_drone_update, bsblongleg_drone_end, bsdrone_interrupt}, - {BS_9C_WALRUS_SLED_DRONE, bswalrus_sled_drone_init, bswalrus_sled_drone_update, bswalrus_sled_drone_end, bsdrone_interrupt}, - {BS_9D_BEE_DRONE, bsbee_drone_init, bsbee_drone_update, bsbee_drone_end, bsdrone_interrupt}, - {BS_9E_CLIMB_LOCKED, bsclimb_locked_init, bsclimb_locked_update, bsclimb_locked_end, func_802ABD60}, - {BS_9F_ANT_BOUNCE, bsant_bounce_init, bsant_bounce_update, bsant_bounce_end, func_80296590}, - {BS_A0_ANT_BOUNCE, bspumpkin_rebound_init, bspumpkin_rebound_update, bspumpkin_rebound_end, func_80296590}, - {BS_A1_CROC_BOUNCE, bscroc_bounce_init, bscroc_bounce_update, bscroc_bounce_end, func_80296590}, - {BS_A2_WALRUS_BOUNCE, bswalrus_bounce_init, bswalrus_bounce_update, bswalrus_bounce_end, func_80296590}, - {BS_A3_BEE_BOUNCE, bsbeemain_bounce_init, bsbeemain_bounce_update, bsbeemain_bounce_end, func_80296590}, - {BS_A4_WONDERWING_DRONE, bsbwhirl_drone_init, bsbwhirl_drone_update, bsbwhirl_drone_end, func_80296608}, - {BS_A5_WONDERWING_UNKA5, bsbwhirl_bsA5unknown_init, bsbwhirl_bsA5unknown_update, bsbwhirl_bsA5unknown_end, func_80296608}, - {0} -}; - -/* .bss */ -void (*D_8037C3B0)(); - -/* .code */ -void bsmethods_setMethods(void){ - s32 index; - bsMap *iPtr; - - for(index = 0; bsMethodsTable[index].uid != 0; index++){ - bsList_setInitMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.init_func); - bsList_setUpdateMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.update_func); - bsList_setEndMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.end_func); - bsList_setInterruptMethod(bsMethodsTable[index].uid, bsMethodsTable[index].behavior.interrupt_func); - } -} - -void bsmethods_reset(void){ - D_80363820 = 1; - D_8037C3B0 = NULL; - update_void_return_Location(); - playerPosition_init(); - snackerctl_reset(); - func_80291910(); - badrone_init(); - bafalldamage_init(); - baflag_clearAll(); - func_8028B6FC(); - func_80291590(); - bakey_reset(); - bastick_reset(); - bainput_reset(); - bsList_clearAll(); - bs_clearState(); - babounds_init(); - func_80296C30(); - baphysics_init(); - baiFrame_reset(); - pitch_reset(); - climb_clear(); - balookat_init(); - roll_reset(); - func_802992F0(); - func_80294DD8(); - func_8029CF6C(); - modelAppendages_reset(); - func_80290B6C(); - baeyes_reset(); - func_80290070(); - func_80290664(); - stateTimer_init(); - eggShatter_init(); - bacarry_init(); - func_80293DA4(); - baAnim_init(); - baModel_reset(); - baMarker_init(); - basfx_reset(); - func_8029A4D0(); - func_8029ADCC(); - hazards_reset(); - bsmethods_setMethods(); -} - -void func_80295A8C(void) -{ - stateTimer_set(STATE_TIMER_2_LONGLEG, bsStoredState_getLongLegTimer()); - stateTimer_set(STATE_TIMER_3_TURBO_TALON, bsStoredState_getTurboTimer()); - if(func_8028ADB4()) - bs_setState(badrone_enter()); - else - bs_setState(bs_getIdleState()); - -} - -void func_80295B04(void){ - f32 longleg_timer; - enum bs_e current_state = bs_getState(); - bool is_in_talon_trot; - - longleg_timer = (bslongleg_inSet(current_state)) ? stateTimer_get(STATE_TIMER_2_LONGLEG) : 0.0f; - bsStoredState_setLongLegTimer(longleg_timer); - longleg_timer = 0.0f; - is_in_talon_trot = false; - - if (bsbtrot_inSet(current_state)) { - longleg_timer = stateTimer_get(STATE_TIMER_3_TURBO_TALON); - is_in_talon_trot = true; - } - - bsStoredState_setTrot(is_in_talon_trot); - bsStoredState_setTurboTimer(longleg_timer); - bs_setState(BS_5A_LOADZONE); - baMarker_free(); - func_8029065C(); - stateTimer_free(); - eggShatter_free(); - baModel_free(); - baAnim_free(); - func_80293E88(); - bacarry_end(); - basfx_free(); - func_8029A54C(); - func_8029ADA8(); - freeHazardSfxId(); - D_80363820 = 0; -} - -void func_80295C08(void (* arg0)(void)){ - D_8037C3B0 = arg0; -} - -void func_80295C14(void){ - func_802964B8(); - balookat_update(); - stateTimer_update(); - modelAppendages_kazooiesUpperHalfVisibilityTimer(); - pfsManager_update();//controller_update - disableInput_set(); - bakey_update(); - bastick_update(); - bainput_update(); //dive_cooldown_update - bs_updateState(); - baphysics_update(); - playerPosition_applyOffset(); - bafalldamage_update(); - func_80293F0C(); - pitch_update(); - roll_update(); - func_802993C8();//yaw update - func_802906D8(); - baAnim_update(); - func_8029A554(); - climb_regrab_update(); - func_80290108(); - eggShatter_update(); - baeyes_update(); - baModel_update(); - playerPosition_func_8029842C(); - baMarker_update(); - bacarry_update(); - snackerctl_update(); - func_8028B71C(); - hazards_update(); - baiFrame_update(); - func_80294E60(); - cameraMode_update(); - func_802919A0(); - if(D_8037C3B0){ - D_8037C3B0(); - D_8037C3B0 = NULL; - } - basfx_update(); - babounds_update();//voidOut_update -} - -void func_80295D74(void){ - if(D_80363820){ - baAnim_defrag(); - baModel_defrag(); - eggShatter_defrag(); - func_80294750(); - func_8029AF1C(); - } -} diff --git a/src/core2/ba/iFrame.h b/src/core2/ba/iFrame.h deleted file mode 100644 index 41798abb8..000000000 --- a/src/core2/ba/iFrame.h +++ /dev/null @@ -1,10 +0,0 @@ -// BanjoDecomp: core2/ba/iFrame.h -#ifndef BANJO_KAZOOIE_BA_IFRAME_H -#define BANJO_KAZOOIE_BA_IFRAME_H - -typedef enum { - IFRAME_NONE = 1, - IFRAME_INVICIBLE = 3 -} IFrameState; - -#endif // BANJO_KAZOOIE_BA_IFRAME_H diff --git a/src/core2/ba/modelappendages.c b/src/core2/ba/modelappendages.c deleted file mode 100644 index b02da560a..000000000 --- a/src/core2/ba/modelappendages.c +++ /dev/null @@ -1,209 +0,0 @@ -// BanjoDecomp: core2/modelappendages.c -#include -#include "functions.h" -#include "variables.h" - -void modelAppendages_setKazooiesUpperHalfVisibility(bool); -void modelAppendages_setKazooiesFeetAndShoesVisibility(bool); -void modelAppendages_setKazooiesAssVisibility(bool); -void modelAppendages_setBanjosLeftEyeVisibility(f32); -void modelAppendages_setBanjosRightEyeVisibility(f32); -void modelAppendages_setTurboTrainersVisibility(bool); -void modelAppendages_setWadingBootsVisibility(bool); -void modelAppendages_setSledVisibility(bool); - -/* .bss */ -f32 showKazooiesUpperHalfModelTimer; // Only used in bFlap -u8 showKazooiesUpperHalfModelNext; // Only used in bFlap -u8 showKazooieAssModel; -u8 showKazooieFeetAndShoesModel; -u8 hideTurboTrainersModel; -u8 showKazooiesUpperHalfModel; -u8 hideWadingBootsModel; -u8 showSledModel; -f32 showBanjosLeftEye; -f32 showBanjosRightEye; - -/* .code */ -// Kazooie & Bee do not blink -// Wishywashy's eyes blink together -void modelAppendages_loadBlinkingEyes(void){ - s32 is_model_visible; - switch(baModel_getModelId()){ - case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: //L8029DC24 - case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: //L8029DC24 - is_model_visible = (s32) ml_interpolate_f(showBanjosLeftEye, 1.0f, 8.0f); - modelRender_setAppendageVisibility(0x1B, is_model_visible); - modelRender_setAppendageVisibility(0x1D, is_model_visible); - modelRender_setAppendageVisibility(0x1F, is_model_visible); - modelRender_setAppendageVisibility(0x21, is_model_visible); - is_model_visible = (s32) ml_interpolate_f(showBanjosRightEye, 1.0f, 8.0f); - modelRender_setAppendageVisibility(0x1A, is_model_visible); - modelRender_setAppendageVisibility(0x1C, is_model_visible); - modelRender_setAppendageVisibility(0x1E, is_model_visible); - modelRender_setAppendageVisibility(0x20, is_model_visible); - break; - - case ASSET_34F_MODEL_BANJO_TERMITE: //L8029DCCC - case ASSET_359_MODEL_BANJO_WALRUS: //L8029DCCC - case ASSET_36F_MODEL_BANJO_PUMPKIN: //L8029DCCC - case ASSET_374_MODEL_BANJO_CROC: //L8029DCCC - modelRender_setAppendageVisibility(0x1B, (s32) ml_interpolate_f(showBanjosLeftEye, 1.0f, 6.0f)); - modelRender_setAppendageVisibility(0x1A, (s32) ml_interpolate_f(showBanjosRightEye, 1.0f, 6.0f)); - break; - - case ASSET_356_MODEL_BANJO_WISHYWASHY: //L8029DD2C - modelRender_setAppendageVisibility(1, (s32) ml_interpolate_f(showBanjosRightEye, 1.0f, 4.0f)); - break; - } -} - -// This includes Kazooie, the shoes, and the sled -void modelAppendages_loadAppendage(void) { - s32 is_model_visible; // [port] must hold values > 1 for geo selector branches - - modelRender_func_8033A1FC(); - switch (baModel_getModelId()) { - case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: - case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: - /* Kazooie's Upper Half */ - modelRender_setAppendageVisibility(0x1, showKazooiesUpperHalfModel); - modelRender_setAppendageVisibility(0x9, showKazooiesUpperHalfModel); - modelRender_setAppendageVisibility(0xC, showKazooiesUpperHalfModel); - modelRender_setAppendageVisibility(0xF, showKazooiesUpperHalfModel); - /* Kazooie's Legs & Shoes */ - modelRender_setAppendageVisibility(0x2, showKazooieFeetAndShoesModel); - modelRender_setAppendageVisibility(0xA, showKazooieFeetAndShoesModel); - modelRender_setAppendageVisibility(0xD, showKazooieFeetAndShoesModel); - modelRender_setAppendageVisibility(0x10, showKazooieFeetAndShoesModel); - /* Kazooie's Ass */ - modelRender_setAppendageVisibility(0x8, showKazooieAssModel); - modelRender_setAppendageVisibility(0xB, showKazooieAssModel); - modelRender_setAppendageVisibility(0xE, showKazooieAssModel); - modelRender_setAppendageVisibility(0x11, showKazooieAssModel); - /* Turbo Talon Trainer */ - is_model_visible = hideTurboTrainersModel + 1; - modelRender_setAppendageVisibility(0x12, is_model_visible); - modelRender_setAppendageVisibility(0x14, is_model_visible); - modelRender_setAppendageVisibility(0x16, is_model_visible); - modelRender_setAppendageVisibility(0x18, is_model_visible); - modelRender_setAppendageVisibility(0x13, is_model_visible); - modelRender_setAppendageVisibility(0x15, is_model_visible); - modelRender_setAppendageVisibility(0x17, is_model_visible); - modelRender_setAppendageVisibility(0x19, is_model_visible); - /* Wading Boots */ - is_model_visible = hideWadingBootsModel + 1; - modelRender_setAppendageVisibility(0x22, is_model_visible); - modelRender_setAppendageVisibility(0x24, is_model_visible); - modelRender_setAppendageVisibility(0x26, is_model_visible); - modelRender_setAppendageVisibility(0x28, is_model_visible); - modelRender_setAppendageVisibility(0x23, is_model_visible); - modelRender_setAppendageVisibility(0x25, is_model_visible); - modelRender_setAppendageVisibility(0x27, is_model_visible); - modelRender_setAppendageVisibility(0x29, is_model_visible); - break; - case ASSET_359_MODEL_BANJO_WALRUS: - /* Sled */ - modelRender_setAppendageVisibility(0x3, showSledModel); - break; - case ASSET_374_MODEL_BANJO_CROC: - /* Turbo Talon Trainer */ - is_model_visible = hideTurboTrainersModel + 1; - modelRender_setAppendageVisibility(0x4, is_model_visible); - modelRender_setAppendageVisibility(0x5, is_model_visible); - modelRender_setAppendageVisibility(0x6, is_model_visible); - modelRender_setAppendageVisibility(0x7, is_model_visible); - break; - } - modelAppendages_loadBlinkingEyes(); -} - -bool modelAppendages_showKazooiesAss(void){ - return showKazooieAssModel; -} - -bool modelAppendages_showKazooiesFeetAndShoes(void){ - return showKazooieFeetAndShoesModel; -} - -bool modelAppendages_showKazooiesUpperHalf(void){ - return showKazooiesUpperHalfModel; -} - -f32 modelAppendages_showBanjosLeftEye(void){ - return showBanjosLeftEye; -} - -f32 modelAppendages_showBanjosRightEye(void){ - return showBanjosRightEye; -} - -bool modelAppendages_hideTurboTrainers(void){ - return hideTurboTrainersModel; -} - -bool modelAppendages_hideWadingBoots(void){ - return hideWadingBootsModel; -} - -void modelAppendages_reset(void) { - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); - modelAppendages_setKazooiesAssVisibility(false); - modelAppendages_setBanjosLeftEyeVisibility(0.0f); - modelAppendages_setBanjosRightEyeVisibility(0.0f); - modelAppendages_setTurboTrainersVisibility(false); - modelAppendages_setWadingBootsVisibility(false); - modelAppendages_setSledVisibility(false); - CALL_EVENT(OnPlayerAnimReset); -} - -void modelAppendages_setKazooiesAssVisibility(bool show_model){ - showKazooieAssModel = show_model; -} - -void modelAppendages_setKazooiesFeetAndShoesVisibility(bool show_model){ - showKazooieFeetAndShoesModel = show_model; -} - -void modelAppendages_setKazooiesUpperHalfVisibility(bool show_model) { - modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(show_model, 0.0f); -} - -// Timer only set in bFlap -void modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(bool show_model, f32 timer) { - showKazooiesUpperHalfModelTimer = timer; - showKazooiesUpperHalfModelNext = show_model; - if (timer == 0.0f) { - showKazooiesUpperHalfModel = show_model; - } -} - -void modelAppendages_setBanjosLeftEyeVisibility(f32 show_model){ - showBanjosLeftEye = show_model; -} - -void modelAppendages_setBanjosRightEyeVisibility(f32 show_model){ - showBanjosRightEye = show_model; -} - -void modelAppendages_setTurboTrainersVisibility(bool hide_model){ - hideTurboTrainersModel = hide_model; -} - -void modelAppendages_setSledVisibility(bool show_model){ - showSledModel = show_model; -} - -void modelAppendages_setWadingBootsVisibility(bool hide_model){ - hideWadingBootsModel = hide_model; -} - -void modelAppendages_kazooiesUpperHalfVisibilityTimer(void) { - if (showKazooiesUpperHalfModelTimer != 0.0f) { - showKazooiesUpperHalfModelTimer -= time_getDelta(); - if (showKazooiesUpperHalfModelTimer <= 0.0f) { - showKazooiesUpperHalfModel = showKazooiesUpperHalfModelNext; - } - } -} diff --git a/src/core2/bs/ant.c b/src/core2/bs/ant.c index f00639615..7ccf6ec65 100644 --- a/src/core2/bs/ant.c +++ b/src/core2/bs/ant.c @@ -50,11 +50,11 @@ void func_8029E48C(void){ } } -void bsant_end(void){ +void func_8029E4EC(void){ if(!bsant_inSet(bs_getNextState())){ bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); + func_8029E070(0); + func_8029E064(0); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -69,8 +69,8 @@ void func_8029E554(void){ int bsant_inSet(s32 move_indx){ return (move_indx == BS_35_ANT_IDLE) - || (move_indx == BS_36_ANT_WALK) - || (move_indx == BS_37_ANT_WALK) + || (move_indx == BS_ANT_WALK) + || (move_indx == BS_ANT_JUMP) || (move_indx == BS_38_ANT_FALL) || (move_indx == BS_3E_ANT_OW) || (move_indx == BS_43_ANT_DIE) @@ -81,7 +81,7 @@ int bsant_inSet(s32 move_indx){ void bsant_idle_init(void){ func_8029E554(); baanim_playForDuration_loopSmooth(ASSET_5E_ANIM_BSANT_IDLE, 1.2f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,YAW_STATE_1_DEFAULT,1,BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -101,23 +101,23 @@ void bsant_idle_update(void){ new_state = badrone_look(); if(bastick_getZone() > 0) - new_state = BS_36_ANT_WALK; + new_state = BS_ANT_WALK; if(bakey_pressed(BUTTON_A)) - new_state = BS_37_ANT_WALK; + new_state = BS_ANT_JUMP; bs_setState(new_state); } void bsant_idle_end(void){ func_802900FC(); - bsant_end(); + func_8029E4EC(); } void bsant_walk_init(void){ func_8029E554(); baanim_playForDuration_loopSmooth(ASSET_5F_ANIM_BSANT_WALK, 0.8f); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2, YAW_STATE_1_DEFAULT,1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364960, D_80364964, D_80364968, D_8036496C); func_802900B4(); } @@ -142,13 +142,13 @@ void bsant_walk_update(void){ sp1C = BS_38_ANT_FALL; if(bakey_pressed(BUTTON_A)) - sp1C = BS_37_ANT_WALK; + sp1C = BS_ANT_JUMP; bs_setState(sp1C); } void bsant_walk_end(void){ - bsant_end(); + func_8029E4EC(); func_802900FC(); } @@ -163,7 +163,7 @@ void bsant_jump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.4423f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsant.c", 0x17c); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -217,10 +217,10 @@ void bsant_jump_update(void){ if(player_isStable()){ baphysics_set_target_horizontal_velocity(0.0f); if(bastick_getZone() > 0) - sp2C = BS_36_ANT_WALK; + sp2C = BS_ANT_WALK; if(bakey_pressed(BUTTON_A)) - sp2C = BS_37_ANT_WALK; + sp2C = BS_ANT_JUMP; } bs_setState(sp2C); @@ -228,7 +228,7 @@ void bsant_jump_update(void){ void bsant_jump_end(void){ baphysics_reset_gravity(); - bsant_end(); + func_8029E4EC(); } void bsant_fall_init(void){ @@ -241,7 +241,7 @@ void bsant_fall_init(void){ anctrl_setStart(aCtrl, 0.4423f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bsant.c", 0x208); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); bsant_substate = 0; } @@ -276,7 +276,7 @@ void bsant_fall_update(void){ } void bsant_fall_end(void){ - bsant_end(); + func_8029E4EC(); } static void __bsant_recoil_init(int take_damage){ @@ -297,7 +297,7 @@ static void __bsant_recoil_init(int take_damage){ else func_8030E58C(SFX_56_BANJO_HUI, 1.8f); - playerPosition_get(sp2C); + _player_getPosition(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -305,7 +305,7 @@ static void __bsant_recoil_init(int take_damage){ baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -341,7 +341,7 @@ static void __bsant_recoil_end(void){ baphysics_reset_gravity(); baMarker_collisionOn(); baeyes_open(); - bsant_end(); + func_8029E4EC(); } void bsant_ow_init(void){ @@ -383,7 +383,7 @@ void bsant_die_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsant.c", 0x2f6); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); - playerPosition_get(sp2C); + _player_getPosition(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); D_8037D290 = 250.0f; @@ -392,12 +392,12 @@ void bsant_die_init(void){ baphysics_set_target_horizontal_velocity(D_8037D290); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); pitch_setAngVel(1000.0f, 12.0f); func_802914CC(0xd); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8029C984(); bsant_substate = 0; baMarker_collisionOff(); @@ -449,16 +449,16 @@ void bsant_die_end(void){ baeyes_open(); } -void bsant_locked_init(void){ +void func_8029F398(void){ func_8029E554(); baanim_playForDuration_loopSmooth(ASSET_5E_ANIM_BSANT_IDLE, 2.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); } -void bsant_locked_update(void){ +void func_8029F3F4(void){ enum bs_e sp1C = 0; func_802B3A50(); func_80299628(0); @@ -469,9 +469,9 @@ void bsant_locked_update(void){ bs_setState(sp1C); } -void bsant_locked_end(void){ +void func_8029F440(void){ func_8029C748(); - bsant_end(); + func_8029E4EC(); } void bsant_drone_init(void){ @@ -485,5 +485,5 @@ void bsant_drone_update(void){ void bsant_drone_end(void){ bsdrone_end(); - bsant_end(); + func_8029E4EC(); } diff --git a/src/core2/bs/bFlip.c b/src/core2/bs/backflip.c similarity index 94% rename from src/core2/bs/bFlip.c rename to src/core2/bs/backflip.c index 5f16813ee..128363f25 100644 --- a/src/core2/bs/bFlip.c +++ b/src/core2/bs/backflip.c @@ -1,9 +1,7 @@ -// BanjoDecomp: core2/bs/bFlip.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .data */ const f32 D_80364A20 = 920.0f; @@ -53,10 +51,10 @@ void bsbflip_init(void){ anctrl_setStart(aCtrl, 0.0f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsbflip.c", 0x80); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); basfx_80299BD4(); D_8037D310 = 0; } @@ -139,7 +137,7 @@ void bsbflip_update(void){ if(player_isFallTumbling()) sp24 = BS_3D_FALL_TUMBLING; if(player_isStable()){ - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); _bsbflip_802A2DC0(); sp24 = func_8029C9C0(sp24); D_8037D310 = 4; @@ -165,6 +163,6 @@ void bsbflip_end(void){ ability_use(2); baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); bastick_resetZones(); } diff --git a/src/core2/bs/bBarge.c b/src/core2/bs/beak_barge.c similarity index 94% rename from src/core2/bs/bBarge.c rename to src/core2/bs/beak_barge.c index c3fc7ca5a..21107b516 100644 --- a/src/core2/bs/bBarge.c +++ b/src/core2/bs/beak_barge.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/bBarge.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" void func_80292864(f32, f32); @@ -49,7 +47,7 @@ void func_8029F4F0(void){ void func_8029F60C(void){ f32 player_position[3]; - playerPosition_get(player_position); + _player_getPosition(player_position); func_8032728C(player_position, 50.0f, 2, func_8029F4E0); } @@ -70,11 +68,11 @@ void bsbarge_init(void){ anctrl_setPlaybackType(plyrMvmnt, ANIMCTRL_ONCE); anctrl_start(plyrMvmnt, "bsbbarge.c", 0x98); D_8037D2A4 = 0; - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_target_horizontal_velocity(baphysics_get_target_horizontal_velocity()*0.3); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); D_8037D2A6 = 0; D_8037D2A5 = 0; baflag_clear(BA_FLAG_A); @@ -176,6 +174,6 @@ void bsbarge_update(void){ void bsbarge_end(void){ ability_use(5); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); D_8037D2A6 = 0; } diff --git a/src/core2/bs/bFly.c b/src/core2/bs/beak_bomb.c similarity index 85% rename from src/core2/bs/bFly.c rename to src/core2/bs/beak_bomb.c index 539528063..265776934 100644 --- a/src/core2/bs/bFly.c +++ b/src/core2/bs/beak_bomb.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/bFly.c #include #include "core1/core1.h" #include "functions.h" @@ -6,11 +5,10 @@ #include "core2/ba/physics.h" #include "core2/ba/flap.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" extern void baModel_setYDisplacement(f32); extern f32 bastick_getX(void); -extern void ncbafly_func_802BFE50(f32, f32, f32); +extern void ncDynamicCam4_func_802BFE50(f32, f32, f32); extern void func_80354030(f32[3], f32); @@ -38,7 +36,7 @@ int func_802A3350(void){ } void func_802A339C(f32 arg0[3], f32 arg1[3], f32 arg2){ - viewport_getLookVector(arg0); + viewport_getLookbk_vector(arg0); ml_vec3f_scale(arg0, arg2); viewport_getRotation_vec3f(arg1); } @@ -67,7 +65,7 @@ void func_802A34C8(void){ if(!bsbfly_inSet(bs_getNextState())){ baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); baModel_setYDisplacement(0.0f); func_8029CB84(); yaw_setUpdateState(1); @@ -112,7 +110,7 @@ void func_802A3648(void){ void func_802A36D0(void){ f32 plyr_pos[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); plyr_pos[0] += randf2(-30.0f, 30.0f); plyr_pos[1] += 50.0f + randf2(0.0f, 30.0f); plyr_pos[2] += randf2(-30.0f, 30.0f); @@ -123,11 +121,11 @@ void func_802A36D0(void){ } int bsbfly_inSet(enum bs_e arg0){ - return arg0 == BS_2A_BOMB + return arg0 == BS_BOMB || arg0 == BS_57_BOMB_END || arg0 == BS_18_FLY_KNOCKBACK || arg0 == BS_59_BFLY_UNK59 - || arg0 == BS_91_FLY_OW + || arg0 == BS_FLY_OW || arg0 == BS_76_BFLY_LOCKED || arg0 == BS_24_FLY || arg0 == BS_99_BFLY_DRONE; @@ -138,8 +136,8 @@ int func_802A37F8(void){ } void bsbfly_enter_init(void){ - baanim_playForDuration_once(ASSET_45_ANIM_BSBFLY_ENTER, 1.4f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + baanim_playForDuration_onceSmooth(ASSET_45_ANIM_BSBFLY_ENTER, 1.4f); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -147,7 +145,7 @@ void bsbfly_enter_init(void){ baphysics_set_velocity(0); baphysics_set_target_horizontal_velocity(0.0f); baphysics_set_gravity(-1200.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); basfx_80299BD4(); D_8037D344 = 0; D_8037D346 = 0; @@ -178,12 +176,12 @@ void bsbfly_enter_update(void){ void bsbfly_enter_end(void){ ability_use(8); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); } void bsbfly_init(void){ baanim_playForDuration_loopSmooth(ASSET_38_ANIM_BSBFLY, 0.62f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); if(baflag_isTrue(BA_FLAG_9)){ baphysics_set_target_horizontal_velocity(0.0f); }else{ @@ -192,7 +190,7 @@ void bsbfly_init(void){ baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); baphysics_set_target_yaw(yaw_getIdeal()); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); baphysics_set_gravity(-300.0f); baphysics_set_terminal_velocity(-99.9f); func_802914CC(4); @@ -300,7 +298,7 @@ void bsbfly_update(void){ sp2C = 0; func_80346C10(&sp2C, 0, 1, ITEM_F_RED_FEATHER, 1); if(sp2C) - sp54 = BS_2A_BOMB; + sp54 = BS_BOMB; } if(player_inWater()) @@ -313,7 +311,7 @@ void bsbfly_update(void){ bs_setState(sp54); } -void bsbfly_end(void){ +void func_802A3F70(void){ func_802A34C8(); } @@ -323,23 +321,23 @@ int bsbfly_bombHitboxActive(void){ } //bsbfly_bomb_init -void bsbfly_bomb_init(void){ +void func_802A3F9C(void){ f32 sp1C[3]; - baanim_playForDuration_onceSmooth(ASSET_43_ANIM_BSBFLY_BEAKBOMB_START, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + baanim_playForDuration_once(ASSET_43_ANIM_BSBFLY_BEAKBOMB_START, 1.0f); + func_8029C7F4(1,1,3,BA_PHYSICS_FREEZE); func_802A339C(D_8037D338, sp1C, 4200.0f); yaw_setIdeal(sp1C[1] + 180.0f); pitch_setIdeal(sp1C[0]); roll_setIdeal(0.0f); baphysics_set_velocity(D_8037D338); pitch_setIdeal(sp1C[0]); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_802914CC(4); - ncbafly_func_802BFE74(1); + ncDynamicCam4_func_802BFE74(1); func_802A3430(); FUNC_8030E624(SFX_52_BANJO_YAH_OH, 1.0f, 28000); D_8037D345 = 0; - playerPosition_get(D_8037D328); + _player_getPosition(D_8037D328); D_8037D344 = 0; func_802D8BE4(0); } @@ -347,7 +345,7 @@ void bsbfly_bomb_init(void){ void func_802A4078(void){ f32 plyr_pos[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); plyr_pos[0] += D_8037D338[0]; plyr_pos[1] += D_8037D338[1]; plyr_pos[2] += D_8037D338[2]; @@ -364,7 +362,7 @@ s32 func_802A40E0(void){ return BS_41_DIE; } -void bsbfly_bomb_update(void) { +void func_802A411C(void) { s32 next_state; AnimCtrl *sp58; BKCollisionTriangle *phi_v0; @@ -426,7 +424,7 @@ void bsbfly_bomb_update(void) { next_state = BS_58_BEAKBOMB_CRASH; } } - playerPosition_get(sp48); + _player_getPosition(sp48); ml_vec3f_diff(sp48, D_8037D328); if (sp48[0]*sp48[0] + sp48[1]*sp48[1] + sp48[2]*sp48[2] > 16000000.0f) { next_state = BS_57_BOMB_END; @@ -442,13 +440,13 @@ void bsbfly_bomb_update(void) { bs_setState(next_state); } -void bsbfly_bomb_end(void){ +void func_802A4404(void){ basfx_80299E6C(); D_8037D345 = 0; func_802A34C8(); } -void bsbfly_beakbombend_init(void){ +void func_802A4430(void){ AnimCtrl *plyr_anctrl; plyr_anctrl = baanim_getAnimCtrlPtr(); @@ -458,8 +456,8 @@ void bsbfly_beakbombend_init(void){ anctrl_setDuration(plyr_anctrl, 0.38f); anctrl_setPlaybackType(plyr_anctrl, ANIMCTRL_LOOP); anctrl_start(plyr_anctrl, "bsbfly.c", 0x38a); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029C7F4(1, 1, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029E070(1); func_802A3430(); func_80293D74(); func_80294378(1); @@ -474,14 +472,14 @@ void bsbfly_beakbombend_init(void){ D_8037D344 = 0; } -void bsbfly_beakbombend_update(void){ +void func_802A4548(void){ s32 next_state = 0; f32 sp20[3]; baphysics_get_velocity(sp20); switch(D_8037D344){ case 0://L802A457C if(func_8028B254(0x5A)){ - baanim_playForDuration_onceSmoothStartingAt(ASSET_8_ANIM_BSJUMP, 2.0f, 0.6667f); + baanim_playForDuration_onceStartingAt(ASSET_8_ANIM_BSJUMP, 2.0f, 0.6667f); D_8037D344 = 1; } break; @@ -510,7 +508,7 @@ void bsbfly_beakbombend_update(void){ bs_setState(next_state); } -void bsbfly_beakbombend_end(void){ +void func_802A4664(void){ s32 next_state; basfx_80299E6C(); basfx_80299E90(); @@ -519,7 +517,7 @@ void bsbfly_beakbombend_end(void){ sfxsource_playHighPriority(SFX_3EA_BANJO_GUH_HUH); } func_802A34C8(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); } void func_802A46C8(void) { @@ -532,9 +530,9 @@ void func_802A46C8(void) { void bsbfly_beakbomb_crash_init(void) { - baanim_playForDuration_onceSmooth(ASSET_3E_ANIM_BSBFLY_BEAKBOMB_CRASH, 1.4f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); - modelAppendages_setKazooiesUpperHalfVisibility(true); + baanim_playForDuration_once(ASSET_3E_ANIM_BSBFLY_BEAKBOMB_CRASH, 1.4f); + func_8029C7F4(1, 1, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029E070(1); FUNC_8030E624(SFX_1F_HITTING_AN_ENEMY_3, 0.8f, 32750); basfx_80299CF4(SFX_36_BANJO_DOH, 1.0f, 28000); baMotor_80250D94(1.0f, 0.5f, 0.5f); @@ -578,13 +576,13 @@ void func_802A48B4(void) { if (item_getCount(ITEM_14_HEALTH) == 0) { func_8029C984(); func_8029151C(0xD); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8029B930(); batimer_set(0, 2.5f); D_8037D344 = 2; } } else if (anctrl_isAt(sp18, 0.92f)) { - baanim_playForDuration_onceSmooth(ASSET_D2_ANIM_BSSPLAT, 2.25f); + baanim_playForDuration_once(ASSET_D2_ANIM_BSSPLAT, 2.25f); D_8037D344 = 1; } break; @@ -616,7 +614,7 @@ void func_802A48B4(void) { void func_802A4A40(void) { func_80291548(); func_8029CB84(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); baMarker_collisionOn(); } @@ -636,10 +634,10 @@ void func_802A4A78(s32 arg0) { sp20 = 400.0f; } func_802BB3DC(2, 100.0f, 0.85f); - baanim_playForDuration_once(ASSET_D3_ANIM_BSBFLY_BEAKBOMB_REBOUND, 1.2f); + baanim_playForDuration_onceSmooth(ASSET_D3_ANIM_BSBFLY_BEAKBOMB_REBOUND, 1.2f); basfx_playOwSfx(1.0f); baMotor_80250D94(1.0f, 0.5f, 0.5f); - playerPosition_get(sp3C); + _player_getPosition(sp3C); func_80294980(sp30); func_80257F18(sp30, sp3C, &sp28); yaw_setIdeal(mlNormalizeAngle(sp28 + 180.0f)); @@ -651,13 +649,13 @@ void func_802A4A78(s32 arg0) { yaw_setIdeal(mlNormalizeAngle(sp28)); yaw_applyIdeal(); } - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(800.0f); baphysics_set_gravity(sp2C); baphysics_set_terminal_velocity(-4000.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_802914CC(4); - ncbafly_func_802BFE50(12.0f, 10000.0f, 800.0f); + ncDynamicCam4_func_802BFE50(12.0f, 10000.0f, 800.0f); baMarker_collisionOff(); func_802A3430(); } @@ -679,7 +677,7 @@ void func_802A4C88(s32 arg0) { baphysics_reset(); baMarker_collisionOn(); baiFrame_start(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); func_80291548(); func_802A34C8(); } @@ -696,27 +694,27 @@ void func_802A4D10(void){ func_802A4C88(0); } -void bsbfly_ow_init(void){ +void func_802A4D30(void){ func_802A4A78(1); } -void bsbfly_ow_update(void){ +void func_802A4D50(void){ func_802A4C34(1); } -void bsbfly_ow_end(void){ +void func_802A4D70(void){ func_802A4C88(1); } -void bsbfly_knockback_init(void) { +void func_802A4D90(void) { f32 sp34; f32 player_position[3]; f32 sp1C[3]; func_802BB3DC(2, 100.0f, 0.85f); - baanim_playForDuration_once(0x10D, 1.0f); + baanim_playForDuration_onceSmooth(0x10D, 1.0f); func_8030E58C(SFX_56_BANJO_HUI, 1.0f); - playerPosition_get(player_position); + _player_getPosition(player_position); func_80294980(sp1C); func_80257F18(sp1C, player_position, &sp34); yaw_setIdeal(mlNormalizeAngle(sp34 + 180.0f)); @@ -728,15 +726,15 @@ void bsbfly_knockback_init(void) { yaw_setIdeal(mlNormalizeAngle(sp34)); yaw_applyIdeal(); } - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(400.0f); baphysics_set_gravity(-1800.0f); baMarker_collisionOff(); func_802914CC(4); - ncbafly_func_802BFE50(12.0f, 10000.0f, 800.0f); + ncDynamicCam4_func_802BFE50(12.0f, 10000.0f, 800.0f); } -void bsbfly_knockback_update(void) { +void func_802A4EC8(void) { s32 next_state; AnimCtrl *sp18; @@ -752,21 +750,21 @@ void bsbfly_knockback_update(void) { bs_setState(next_state); } -void bsbfly_knockback_end(void){ +void func_802A4F44(void){ baphysics_reset_gravity(); baMarker_collisionOn(); func_802A34C8(); } -void bsbfly_locked_init(void) { +void func_802A4F74(void) { baanim_playForDuration_loopSmooth(ASSET_38_ANIM_BSBFLY, 0.62f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); + func_8029E070(1); func_802914CC(4); func_802A3430(); } -void bsbfly_locked_update(void) { +void func_802A4FC8(void) { s32 next_state; next_state = 0; @@ -779,7 +777,7 @@ void bsbfly_locked_update(void) { bs_setState(next_state); } -void bsbfly_locked_end(void){ +void func_802A503C(void){ func_802A34C8(); } @@ -797,32 +795,32 @@ void func_802A505C(void){ extern void baanim_playForDuration_loop(s32, f32); /* .code */ -void bsbfly_drone_init(void){ +void func_802A50B0(void){ func_802A3430(); bsdrone_init(); } -void bsbfly_drone_update(void){ +void func_802A50D8(void){ bsdrone_update(); } -void bsbfly_drone_end(void){ +void func_802A50F8(void){ bsdrone_end(); func_802A34C8(); } -void bsfly_dingpotLaunch_init(void){ +void func_802A5120(void){ baanim_playForDuration_loop(ASSET_68_ANIM_BSJUMP_TUMBLE, 0.35f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); baphysics_set_target_horizontal_velocity(0.0f); baphysics_set_velocity(0); baphysics_set_vertical_velocity(2000.0f); basfx_80299CF4(SFX_63_BANJO_UWAAAAOOH, 1.0f, 32000); } -void bsfly_dingpotLaunch_update(void){ +void func_802A5190(void){ baphysics_set_vertical_velocity(2000.0f); bs_setState(0); } -void bsfly_dingpotLaunch_end(void){} +void func_802A51C0(void){} diff --git a/src/core2/bs/bbuster.c b/src/core2/bs/beak_buster.c similarity index 94% rename from src/core2/bs/bbuster.c rename to src/core2/bs/beak_buster.c index 049ffedc0..3190548f2 100644 --- a/src/core2/bs/bbuster.c +++ b/src/core2/bs/beak_buster.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/bbuster.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /*.data*/ const f32 D_80364990 = 400.0f; @@ -66,12 +64,12 @@ void bsbbuster_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.35f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsbbuster.c", 0x81); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); baphysics_set_gravity(0.0f); baphysics_set_target_horizontal_velocity(0.0f); ml_vec3f_clear(sp20); baphysics_set_velocity(sp20); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_802A02B4(0); D_8037D2B9 = 0; D_8037D2B7 = 0; @@ -148,10 +146,10 @@ void bsbbuster_update(void){ D_8037D2B8 = 1; D_8037D2B0 = 0.09f; D_8037D2BA = 3; - playerPosition_get(player_position); + _player_getPosition(player_position); func_8032728C(player_position, 150.0f, 2, func_8029FB20); if(bafalldamage_get_damage(&sp3C)){ - sp44 = BS_72_SPLAT; + sp44 = BS_SPLAT; } } break; @@ -202,7 +200,7 @@ void bsbbuster_update(void){ void bsbbuster_end(void){ baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); D_8037D2B7 = 0; D_8037D2B8 = 0; } diff --git a/src/core2/bs/bEggHead.c b/src/core2/bs/beak_egg_aim.c similarity index 63% rename from src/core2/bs/bEggHead.c rename to src/core2/bs/beak_egg_aim.c index 65dedeff8..5d6bd79f0 100644 --- a/src/core2/bs/bEggHead.c +++ b/src/core2/bs/beak_egg_aim.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/bEggHead.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" void yaw_setVelocityBounded(f32, f32); //void anctrl_start(AnimCtrl *, char*, s32); @@ -15,11 +13,11 @@ u8 D_8037D2F1; /* .code */ void bsegghead_init(void){ - baanim_playForDuration_once(ASSET_2A_ANIM_BSEGGHEAD, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_onceSmooth(ASSET_2A_ANIM_BSEGGHEAD, 1.0f); + func_8029C7F4(1,3,1, BA_PHYSICS_LOCKED_ROTATION); yaw_setVelocityBounded(350.0f, 14.0f); baphysics_set_target_horizontal_velocity(0.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); D_8037D2F0 = (D_8037D2F1 = 1); bainput_enable(2,0); } @@ -42,19 +40,11 @@ void bsegghead_update(void) { func_80346C10((enum bs_e *)&sp28, -1, 0, ITEM_D_EGGS, 0); } if (has_eggs) { - // [port] Romhack gate: listeners may retune the sample rate and hook the - // egg noise into a stealth meter. - if (anctrl_isAt(aCtrl, 0.1f)) { - s32 rate = 0x7fff; - EventSystem_Should(VB_EGG_FIRE_SFX, true, 0, &rate); - func_8030E760(SFX_46_KAZOOIE_CHOKING_UP, 1.0f, rate); - } + if (anctrl_isAt(aCtrl, 0.1f)) + func_8030E760(SFX_46_KAZOOIE_CHOKING_UP, 1.0f, 0x7fff); - if (anctrl_isAt(aCtrl, 0.4f)) { - s32 rate = 0x7fff; - EventSystem_Should(VB_EGG_FIRE_SFX, true, 1, &rate); - func_8030E760(SFX_57_KAZOOIE_HEGH, 1.0f, rate); - } + if (anctrl_isAt(aCtrl, 0.4f)) + func_8030E760(SFX_57_KAZOOIE_HEGH, 1.0f, 0x7fff); if (anctrl_isAt(aCtrl, 0.4704f)){ commonParticle_new(COMMON_PARTICLE_1_EGG_HEAD, 1); @@ -68,7 +58,7 @@ void bsegghead_update(void) { } } if (anctrl_isStopped(aCtrl)) { - next_state = (bakey_held(BUTTON_Z))? BS_7_CROUCH : BS_1_IDLE; + next_state = (bakey_held(BUTTON_Z))? BS_CROUCH : BS_1_IDLE; } else if (0.65 < (f64) anctrl_getAnimTimer(aCtrl)) { next_state = func_802ADCD4(0); @@ -81,5 +71,5 @@ void bsegghead_update(void) { void bsegghead_end(void){ bainput_enable(2, 1); baphysics_reset_gravity(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); } diff --git a/src/core2/bs/bEggAss.c b/src/core2/bs/beak_egg_fire.c similarity index 72% rename from src/core2/bs/bEggAss.c rename to src/core2/bs/beak_egg_fire.c index b4941a6b0..6dac9bf1e 100644 --- a/src/core2/bs/bEggAss.c +++ b/src/core2/bs/beak_egg_fire.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/bEggAss.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .bss */ u8 D_8037D2E0; @@ -12,11 +10,11 @@ u8 D_8037D2E1; /* .code */ void bseggass_init(void){ - baanim_playForDuration_once(ASSET_2B_ANIM_BSEGGASS, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_onceSmooth(ASSET_2B_ANIM_BSEGGASS, 1.0f); + func_8029C7F4(1,3,1, BA_PHYSICS_LOCKED_ROTATION); yaw_setVelocityBounded(350.0f, 14.0f); baphysics_set_target_horizontal_velocity(0.0f); - modelAppendages_setKazooiesAssVisibility(true); + func_8029E058(1); D_8037D2E0 = (D_8037D2E1 = 1); bainput_enable(5,0); } @@ -40,10 +38,7 @@ void bseggass_update(void) { } if (has_eggs) { if (anctrl_isAt(plyr_mvmt, 0.3837f)) { - // [port] Romhack gate - s32 rate = 28000; - EventSystem_Should(VB_EGG_FIRE_SFX, true, 2, &rate); - func_8030E760(SFX_3E_POOP_NOISE, 1.4f, rate); + func_8030E760(SFX_3E_POOP_NOISE, 1.4f, 28000); commonParticle_new(COMMON_PARTICLE_4_EGG_ASS, 1); item_dec(ITEM_D_EGGS); ability_use(7); @@ -55,7 +50,7 @@ void bseggass_update(void) { } } if (anctrl_isStopped(plyr_mvmt)) { - next_state = (bakey_held(BUTTON_Z))? BS_7_CROUCH : BS_1_IDLE; + next_state = (bakey_held(BUTTON_Z))? BS_CROUCH : BS_1_IDLE; } else if (0.6 < (f64) anctrl_getAnimTimer(plyr_mvmt)) { next_state = func_802ADCD4(0); } @@ -68,5 +63,5 @@ void bseggass_update(void) { void bseggass_end(void){ bainput_enable(5, 1); baphysics_reset_gravity(); - modelAppendages_setKazooiesAssVisibility(false); + func_8029E058(0); } diff --git a/src/core2/bs/bPeck.c b/src/core2/bs/beak_peck.c similarity index 92% rename from src/core2/bs/bPeck.c rename to src/core2/bs/beak_peck.c index 8f1bcc506..ea581151b 100644 --- a/src/core2/bs/bPeck.c +++ b/src/core2/bs/beak_peck.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/bPeck.c #include #include "functions.h" #include "variables.h" @@ -40,10 +39,10 @@ void bsbpeck_init(void){ if(bafalldamage_get_state() == 1) bafalldamage_set_state(2); - baanim_playForDuration_once(ASSET_1A_ANIM_BSBPECK, 0.2f); - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_AIRBORN); + baanim_playForDuration_onceSmooth(ASSET_1A_ANIM_BSBPECK, 0.2f); + func_8029C7F4(1,YAW_STATE_3_BOUNDED, 1, BA_PHYSICS_AIRBORN); yaw_setVelocityBounded(1200.0f, 10.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); baphysics_set_gravity(D_80364A60); baphysics_set_vertical_velocity(D_80364A64); baModel_80292048(1, -38.0f, 0.0f, 105.0f); @@ -136,6 +135,6 @@ void bsbpeck_end(void){ baModel_80292048(1, 0.0f, 0.0f, 0.0f); baModel_80292048(0, 0.0f, 0.0f, 0.0f); baMarker_8028D638(0, 0); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); baphysics_reset_gravity(); } diff --git a/src/core2/bs/bSwim.c b/src/core2/bs/beak_swim.c similarity index 89% rename from src/core2/bs/bSwim.c rename to src/core2/bs/beak_swim.c index 15abe2080..f88395db2 100644 --- a/src/core2/bs/bSwim.c +++ b/src/core2/bs/beak_swim.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/bSwim.c #include #include "functions.h" #include "variables.h" @@ -6,7 +5,6 @@ #include "core2/ba/model.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" extern f32 func_8029494C(void); @@ -20,7 +18,7 @@ u8 D_8037D396; f32 D_8037D398; void func_802A7140() { - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NO_GRAVITY); + func_8029C7F4(1, 3, 3, BA_PHYSICS_NO_GRAVITY); } f32 func_802A716C() { @@ -66,7 +64,7 @@ bool func_802A73BC(void) { f32 sp1C; sp1C = (gsworld_getMap() == MAP_46_CCW_WINTER) ? 90.0f : 130.0f; - return floor_isCurrentFloorunk59() && playerPosition_getY() > (floor_getCurrentFloorYPosition() - sp1C); + return floor_isCurrentFloorunk59() && player_getYPosition() > (floor_getCurrentFloorYPosition() - sp1C); } void func_802A744C(void) { @@ -78,7 +76,7 @@ void func_802A744C(void) { baphysics_set_terminal_velocity(-399.99f); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_80294378(3); baModel_setYDisplacement(60.0f); baphysics_set_acceleration(2.0f); @@ -108,13 +106,13 @@ void func_802A75B0(void) { baphysics_reset_terminal_velocity(); baphysics_reset_gravity(); bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); func_80294378(1); baModel_setYDisplacement(0.0f); } } -void bsbdive_idle_init() { +void func_802A762C() { baanim_playForDuration_loopSmooth(0x70, 2.0f); func_802A7140(); baphysics_set_target_velocity(0); @@ -122,7 +120,7 @@ void bsbdive_idle_init() { baphysics_set_acceleration(0.4f); } -void bsbdive_idle_update() { +void func_802A7674() { s32 state_id = 0; func_802A71D8(); @@ -147,11 +145,11 @@ void bsbdive_idle_update() { bs_setState(state_id); } -void bsbdive_idle_end() { +void func_802A7718() { func_802A75B0(); } -void bsbdiveb_init(void) { +void func_802A7738(void) { AnimCtrl* temp_s0; AnimCtrl* temp_v0; @@ -181,7 +179,7 @@ void func_802A77D8(void) { baphysics_set_velocity(sp24); } -void bsbdiveb_update(void) { +void func_802A7838(void) { s32 next_state; AnimCtrl *anim_ctrl; f64 temp_f2; @@ -231,12 +229,12 @@ void bsbdiveb_update(void) { bs_setState(next_state); } -void bsbdiveb_end() { +void func_802A7A2C() { func_802906A4(1); func_802A75B0(); } -void bsswim_divea_init() { +void func_802A7A54() { baanim_playForDuration_loopSmooth(0x71, 0.75f); func_802A7140(); func_802A744C(); @@ -245,7 +243,7 @@ void bsswim_divea_init() { func_802906A4(2); } -void bsswim_divea_update(void) { +void func_802A7AB0(void) { s32 next_state; AnimCtrl *anim_ctl; @@ -277,20 +275,20 @@ void bsswim_divea_update(void) { bs_setState(next_state); } -void bsswim_divea_end(void) { +void func_802A7BA8(void) { func_802906A4(1); func_802A75B0(); } -void bsbswim_ow_init(void) { +void func_802A7BD0(void) { f32 sp3C; f32 sp30[3]; f32 sp24[3]; barebound_set_active(func_80296560()); - baanim_playForDuration_once(0x1A0, 1.4f); + baanim_playForDuration_onceSmooth(0x1A0, 1.4f); basfx_playOwSfx(1.0f); - playerPosition_get(sp30); + _player_getPosition(sp30); func_80294980(sp24); func_80257F18(sp24, sp30, &sp3C); yaw_setIdeal(mlNormalizeAngle(sp3C)); @@ -298,19 +296,19 @@ void bsbswim_ow_init(void) { baphysics_set_target_horizontal_velocity(barebound_get_horizontal_velocity()); baphysics_set_target_yaw(sp3C); baphysics_set_horizontal_velocity(sp3C, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); baMarker_collisionOff(); baeyes_close(); func_802A744C(); } -void bsbswim_ow_update(void) { +void func_802A7CA8(void) { s32 next_state; f32 plyr_pos[3]; ParticleEmitter *p_ctrl; next_state = 0; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); plyr_pos[1] += 60.0f; p_ctrl = func_8029B950(plyr_pos, 25.0f); particleEmitter_setParticleVelocityRange(p_ctrl, -60.0f, -50.0f, -60.0f, 60.0f, 100.0f, 60.0f); @@ -325,7 +323,7 @@ void bsbswim_ow_update(void) { } -void bsbswim_ow_end(void) { +void func_802A7D74(void) { baiFrame_start(); baMarker_collisionOn(); baeyes_open(); @@ -334,7 +332,7 @@ void bsbswim_ow_end(void) { void bsSwim_dive_init(void) { ability_use(ABILITY_3_CAMERA_CONTROL); - baanim_playForDuration_onceSmooth(ASSET_3C_ANIM_BSSWIM_DIVE_ENTER, 1.0f); + baanim_playForDuration_once(ASSET_3C_ANIM_BSSWIM_DIVE_ENTER, 1.0f); func_802A7140(); yaw_setVelocityBounded(500.0f, 5.0f); baphysics_set_target_velocity(0); @@ -345,7 +343,7 @@ void bsSwim_dive_init(void) { } -void bsSwim_dive_update(void) { +void func_802A7E2C(void) { s32 next_state; AnimCtrl *sp38; f32 sp34; @@ -381,11 +379,11 @@ void bsSwim_dive_update(void) { bs_setState(next_state); } -void bsSwim_dive_end(void){ +void func_802A7F4C(void){ func_802A75B0(); } -void bsbswim_die_init(void) { +void func_802A7F6C(void) { D_8037D394 = BOOL(bs_getPrevState() == BS_41_DIE); if (D_8037D394 || level_get() == LEVEL_9_RUSTY_BUCKET_BAY || gsworld_getMap() == MAP_46_CCW_WINTER) { @@ -411,7 +409,7 @@ void bsbswim_die_init(void) { basfx_80299CF4(SFX_CA_BANJO_DROWNING_1, 1.0f, 24000); } -void bsbswim_die_update(void) { +void func_802A8098(void) { s32 next_state; f32 sp40[3]; ParticleEmitter *p_ctrl; @@ -431,7 +429,7 @@ void bsbswim_die_update(void) { switch (D_8037D396) { case 0: if (globalTimer_getTimeMasked(1) == 0) { - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); plyr_pos[1] += 60.0f; p_ctrl = func_8029B950(plyr_pos, 25.0f); particleEmitter_setParticleVelocityRange(p_ctrl, -60.0f, -50.0f, -60.0f, 60.0f, 100.0f, 60.0f); @@ -445,7 +443,7 @@ void bsbswim_die_update(void) { } if (batimer_isAt(1, 1.9f)) { func_802914CC(0xD); - ncbadie_func_802BF2C0(80.0f); + ncDynamicCamD_func_802BF2C0(80.0f); if (D_8037D394) { batimer_set(0, 0.5f); } else { @@ -463,7 +461,7 @@ void bsbswim_die_update(void) { bs_setState(next_state); } -void bsbswim_die_end(void) { +void func_802A82D4(void) { func_802906A4(1); func_80291548(); core1_ce60_incOrDecCounter(false); @@ -480,8 +478,8 @@ void __bsbswim_update_rotation(void) { f32 sp2C[3]; if (balookat_getState() && balookat_try_get_position(sp2C)) { - playerPosition_get(sp44); - ml_horizontal_and_vertical_angles(sp44[0], sp44[1], sp44[2], sp2C[0], sp2C[1], sp2C[2], &sp38[0], &sp38[1]); + _player_getPosition(sp44); + func_8025727C(sp44[0], sp44[1], sp44[2], sp2C[0], sp2C[1], sp2C[2], &sp38[0], &sp38[1]); pitch_setIdeal(sp38[0]); yaw_setIdeal(sp38[1]); roll_setIdeal(0.0f); @@ -513,7 +511,7 @@ void bsbswim_lookat_end(void){ func_802A75B0(); } -void bsbswim_landingInWater_init(void) { +void func_802A846C(void) { AnimCtrl *temp_s0; f32 sp28; @@ -540,18 +538,18 @@ void bsbswim_landingInWater_init(void) { } D_8037D398 = ml_map_f(sp28, 40.0f, 1000.0f, -300.0f, -1200.0f); baphysics_set_vertical_velocity(D_8037D398); - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NO_GRAVITY); + func_8029C7F4(1, 3, 3, BA_PHYSICS_NO_GRAVITY); func_802A744C(); baphysics_set_type(BA_PHYSICS_AIRBORN); } -void bsbswim_landingInWater_update(void) { +void func_802A85EC(void) { s32 next_state; f32 sp38[3]; ParticleEmitter *sp34; next_state = 0; - playerPosition_get(sp38); + _player_getPosition(sp38); sp38[1] += 60.0f; sp34 = func_8029B950(sp38, 20.0f); particleEmitter_setParticleVelocityRange(sp34, -30.0f, -30.0f, -30.0f, 30.0f, 30.0f, 30.0f); @@ -572,7 +570,7 @@ void bsbswim_landingInWater_update(void) { bs_setState(next_state); } -void bsbswim_landingInWater_end(void){ +void func_802A872C(void){ func_802A75B0(); } diff --git a/src/core2/bs/bee.c b/src/core2/bs/bee.c index ef32faa9c..bbc820bf8 100644 --- a/src/core2/bs/bee.c +++ b/src/core2/bs/bee.c @@ -17,8 +17,8 @@ void func_802A02C0(void){ pitch_setIdeal(0.0f); //pitch_setIdeal roll_setIdeal(0.0f); bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); + func_8029E070(0); + func_8029E064(0); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); diff --git a/src/core2/bs/beeFly.c b/src/core2/bs/bee_fly.c similarity index 91% rename from src/core2/bs/beeFly.c rename to src/core2/bs/bee_fly.c index b837172ea..1f03de7e5 100644 --- a/src/core2/bs/beeFly.c +++ b/src/core2/bs/bee_fly.c @@ -1,11 +1,9 @@ -// BanjoDecomp: core2/bs/beeFly.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/flap.h" -#include "core2/yaw.h" void func_80354030(f32*, f32); @@ -13,7 +11,7 @@ f32 bastick_distance(void); f32 bastick_getAngleRelativeToBanjo(void); void baModel_setYDisplacement(f32); -void ncbafly_func_802BFE50(f32, f32, f32); +void ncDynamicCam4_func_802BFE50(f32, f32, f32); void yaw_setVelocityBounded(f32, f32); f32 bastick_getX(void); f32 bastick_getY(void); @@ -32,7 +30,7 @@ int bsBeeFly_inSet(s32); void func_802A04F0(void){ f32 player_position[3]; - playerPosition_get(player_position); + _player_getPosition(player_position); player_position[0] += randf2(-30.0f, 30.0f); player_position[1] += 30.0f + randf2(0.0f, 30.0f); player_position[2] += randf2(-30.0f, 30.0f); @@ -42,10 +40,10 @@ void func_802A04F0(void){ } -void bsbeefly_bs8Bunknown_init(void){ +void func_802A0590(void){ func_802A0340(); - baanim_playForDuration_once(0x1df, 1.5f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + baanim_playForDuration_onceSmooth(0x1df, 1.5f); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -55,7 +53,7 @@ void bsbeefly_bs8Bunknown_init(void){ D_8037D2C0 = 0; } -void bsbeefly_bs8Bunknown_update(void){ +void func_802A0630(void){ s32 next_state = 0; AnimCtrl * mvmnt; //sp1C @@ -73,13 +71,13 @@ void bsbeefly_bs8Bunknown_update(void){ if(anctrl_isStopped(mvmnt)) baanim_playForDuration_loopSmooth(ASSET_1DC_ANIM_BEE_FLY, 0.38f); if(baphysics_get_vertical_velocity() < 0.0f) - next_state = BS_8C_BEE_FLY; + next_state = BS_BEE_FLY; break; } bs_setState(next_state); } -void bsbeefly_bs8Bunknown_end(void){ +void func_802A0704(void){ func_802A02C0(); } @@ -123,7 +121,7 @@ void _bsBeeFly_updateYaw(void){ f32 sp30; f32 stickX; stickX = bastick_getX(); - ncbafly_func_802BFE50(2.0f, 2000.0f, 350.0f); + ncDynamicCam4_func_802BFE50(2.0f, 2000.0f, 350.0f); if(bakey_held(BUTTON_R)){ yaw_setVelocityBounded(500.0f, 30.0f); sp34 = 6.0f; @@ -153,7 +151,7 @@ void bsbeefly_enter(void){ mvmnt = bs_getPrevState(); baanim_playForDuration_loopSmooth(ASSET_1DC_ANIM_BEE_FLY, 0.38); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 3, BA_PHYSICS_LOCKED_ROTATION); if(baflag_isTrue(BA_FLAG_9)) baphysics_set_target_horizontal_velocity(0.0f); else @@ -187,7 +185,7 @@ void bsbeefly_update(void){ _bsBeeFly_updateYaw(); _bsBeeFly_updatePitch(); pitch_get(); //return value never used - if(bakey_pressed(BUTTON_A) && (playerPosition_getY() < 7500.0)){ + if(bakey_pressed(BUTTON_A) && (player_getYPosition() < 7500.0)){ baflap_add(1.0f); } if((baflap_getCount() == 0) && player_inWater()){ diff --git a/src/core2/bs/beeMain.c b/src/core2/bs/bee_main.c similarity index 85% rename from src/core2/bs/beeMain.c rename to src/core2/bs/bee_main.c index ed51d441a..754a135d3 100644 --- a/src/core2/bs/beeMain.c +++ b/src/core2/bs/bee_main.c @@ -1,16 +1,14 @@ -// BanjoDecomp: core2/bs/beeMain.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" f32 func_8029B41C(void); void func_80299628(s32); void yaw_applyIdeal(void); -void ncbadie_func_802BF2C0(f32); +void ncDynamicCamD_func_802BF2C0(f32); f32 baanim_getTimer(void); void baanim_setEndAndDuration(f32, f32); @@ -58,15 +56,15 @@ void func_802A1020(void){ } } -void bsbeemain_idle_init(void){ +void func_802A1080(void){ func_802A0340(); baanim_playForDuration_loopSmooth(ASSET_1DE_ANIM_BEE_IDLE,3.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802900B4(); } -void bsbeemain_idle_update(void){ +void func_802A10D4(void){ s32 s0; s0 = 0; @@ -78,31 +76,31 @@ void bsbeemain_idle_update(void){ s0 = badrone_look(); if(bastick_getZone() > 0) - s0 = BS_86_BEE_WALK; + s0 = BS_BEE_WALK; if(bakey_pressed(BUTTON_A)) - s0 = BS_87_BEE_JUMP; + s0 = BS_BEE_JUMP; if(player_inWater()) - s0 = BS_8C_BEE_FLY; + s0 = BS_BEE_FLY; bs_setState(func_8029CA94(s0)); } -void bsbeemain_idle_end(void){ +void func_802A117C(void){ func_802900FC(); func_802A02C0(); } -void bsbeemain_walk_init(void){ +void func_802A11A4(void){ func_802A0340(); baanim_playForDuration_loopSmooth(ASSET_1DD_ANIM_BEE_WALK, 0.38f); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_803649E0, D_803649E4, D_803649E8, D_803649EC); func_802900B4(); } -void bsbeemain_walk_update(void){ +void func_802A1214(void){ s32 s0; s0 = 0; @@ -117,20 +115,20 @@ void bsbeemain_walk_update(void){ s0 = BS_88_BEE_FALL; if(bakey_pressed(BUTTON_A)) - s0 = BS_87_BEE_JUMP; + s0 = BS_BEE_JUMP; if(player_inWater()) - s0 = BS_8C_BEE_FLY; + s0 = BS_BEE_FLY; bs_setState(s0); } -void bsbeemain_walk_end(void){ +void func_802A12D4(void){ func_802900FC(); func_802A02C0(); } -void bsbeemain_jump_init(void){ +void func_802A12FC(void){ AnimCtrl * s0; s0 = baanim_getAnimCtrlPtr(); @@ -143,7 +141,7 @@ void bsbeemain_jump_init(void){ anctrl_setDuration(s0, 1.2f); anctrl_setPlaybackType(s0, ANIMCTRL_ONCE); anctrl_start(s0, "bsbeemain.c", 0x15b); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -156,7 +154,7 @@ void bsbeemain_jump_init(void){ D_8037D2D4 = 0; } -void bsbeemain_jump_update(void){ +void func_802A1438(void){ s32 sp2c; AnimCtrl * sp28; f32 sp1c[3]; @@ -205,27 +203,27 @@ void bsbeemain_jump_update(void){ } if(player_isStable()){ if(bastick_getZone() > 0) - sp2c = BS_86_BEE_WALK; + sp2c = BS_BEE_WALK; if(bakey_pressed(BUTTON_A)){ - sp2c = BS_87_BEE_JUMP; + sp2c = BS_BEE_JUMP; } } else{ if(bakey_pressed(BUTTON_A)){ - sp2c = BS_8C_BEE_FLY; + sp2c = BS_BEE_FLY; } } if(player_inWater()) - sp2c = BS_8C_BEE_FLY; + sp2c = BS_BEE_FLY; bs_setState(sp2c); } -void bsbeemain_jump_end(void){ +void func_802A163C(void){ func_802A02C0(); baphysics_reset_gravity(); } -void bsbeemain_fall_init(void){ +void func_802A1664(void){ AnimCtrl * s0; s0 = baanim_getAnimCtrlPtr(); @@ -237,11 +235,11 @@ void bsbeemain_fall_init(void){ anctrl_setSubRange(s0, 0, 0.51f); anctrl_setPlaybackType(s0, ANIMCTRL_ONCE); anctrl_start(s0, "bsbeemain.c", 0x1e2); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); D_8037D2D4 = 0; } -void bsbeemain_fall_update(void){ +void func_802A170C(void){ s32 sp2c; //next state AnimCtrl * sp28; f32 sp1c[3]; @@ -280,22 +278,22 @@ void bsbeemain_fall_update(void){ sp2c = badrone_transform(); }else{ if(bastick_getZone() > 0) - sp2c = BS_86_BEE_WALK; + sp2c = BS_BEE_WALK; if(bakey_pressed(BUTTON_A)) - sp2c = BS_87_BEE_JUMP; + sp2c = BS_BEE_JUMP; sp2c = func_8029CA94(sp2c); } } else{ if(baflag_isFalse(BA_FLAG_F) && bakey_pressed(BUTTON_A)) - sp2c = BS_8C_BEE_FLY; + sp2c = BS_BEE_FLY; }//L802A189C if(player_inWater()) - sp2c = BS_8C_BEE_FLY; + sp2c = BS_BEE_FLY; bs_setState(sp2c); } -void bsbeemain_fall_end(void){ +void func_802A18C8(void){ func_802A02C0(); } @@ -320,7 +318,7 @@ void func_802A18E8(s32 arg0){ }else{ func_8030E58C(SFX_56_BANJO_HUI, 1.8f); } - playerPosition_get(sp2C); + _player_getPosition(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -328,7 +326,7 @@ void func_802A18E8(s32 arg0){ baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -369,27 +367,27 @@ void func_802A1B28(void){ func_802A02C0(); } -void bsbeemain_ow_init(void){ +void func_802A1B68(void){ func_802A18E8(1); } -void bsbeemain_ow_update(void){ +void func_802A1B88(void){ func_802A1A50(); } -void bsbeemain_ow_end(void){ +void func_802A1BA8(void){ func_802A1B28(); } -void bsbeemain_bounce_init(void){ +void func_802A1BC8(void){ func_802A18E8(2); } -void bsbeemain_bounce_update(void){ +void func_802A1BE8(void){ func_802A1A50(); } -void bsbeemain_bounce_end(void){ +void func_802A1C08(void){ func_802A1B28(); } @@ -409,8 +407,8 @@ void bsbeemain_die_init(void){ anctrl_setDuration(sp3C, 1.7f); anctrl_setPlaybackType(sp3C, ANIMCTRL_ONCE); anctrl_start(sp3C, "bsbeemain.c", 0x2ef); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); - playerPosition_get(sp2C); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + _player_getPosition(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -425,14 +423,14 @@ void bsbeemain_die_init(void){ baMarker_collisionOff(); baeyes_close(); func_802914CC(0xd); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8029C984(); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); batimer_set(0, 2.9f); D_8037D2D4 = 0; } -void bsbeemain_die_update(void){ +void func_802A1DD8(void){ baphysics_set_target_horizontal_velocity(D_8037D2D0); func_80299628(0); switch(D_8037D2D4){ @@ -469,7 +467,7 @@ void bsbeemain_die_update(void){ } -void bsbeemain_die_end(void){ +void func_802A1F2C(void){ core1_ce60_incOrDecCounter(false); baphysics_reset_gravity(); func_80291548(); @@ -477,16 +475,16 @@ void bsbeemain_die_end(void){ func_802A02C0(); } -void bsbee_locked_init(void){ +void func_802A1F6C(void){ func_802A0340(); baanim_playForDuration_loopSmooth(ASSET_1DE_ANIM_BEE_IDLE, 3.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); } -void bsbee_locked_update(void){ +void func_802A1FC8(void){ s32 sp1C; sp1C = 0; @@ -499,7 +497,7 @@ void bsbee_locked_update(void){ bs_setState(sp1C); } -void bsbee_locked_end(void){ +void func_802A2014(void){ pitch_setIdeal(0.0f); roll_setIdeal(0.0f); func_8029C748(); @@ -518,7 +516,7 @@ void func_802A2098(void){ baflag_clear(BA_FLAG_1A_OPEN_NOTEDOOR); baanim_playForDuration_loopSmooth(ASSET_1DE_ANIM_BEE_IDLE, 3.0f); yaw_setIdeal(func_8029B41C()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); core1_ce60_incOrDecCounter(false); func_8025A2FC(0, 0xFA0); diff --git a/src/core2/bs/bsList.c b/src/core2/bs/bs_list.c similarity index 97% rename from src/core2/bs/bsList.c rename to src/core2/bs/bs_list.c index 4232c817e..94103f61e 100644 --- a/src/core2/bs/bsList.c +++ b/src/core2/bs/bs_list.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bsList.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/bs_statemachine.c b/src/core2/bs/bs_statemachine.c index 5b18f4d99..dd1588f8d 100644 --- a/src/core2/bs/bs_statemachine.c +++ b/src/core2/bs/bs_statemachine.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_13780.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/bsStoredState.c b/src/core2/bs/bs_storedstate.c similarity index 97% rename from src/core2/bs/bsStoredState.c rename to src/core2/bs/bs_storedstate.c index 45badf5db..4d7db9391 100644 --- a/src/core2/bs/bsStoredState.c +++ b/src/core2/bs/bs_storedstate.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bsStoredState.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/carry.c b/src/core2/bs/carry.c index a8b79b32e..3ecb6e2e6 100644 --- a/src/core2/bs/carry.c +++ b/src/core2/bs/carry.c @@ -6,7 +6,6 @@ #include "core2/ba/anim.h" #include "core2/ba/carry.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .data */ const f32 D_80364AF0 = 30.0f; @@ -37,7 +36,7 @@ void bscarry_idle_init(void){ anctrl_setIndex(aCtrl, ASSET_72_ANIM_BSCARRY_IDLE); anctrl_setDuration(aCtrl, 1.2f); anctrl_start(aCtrl, "bscarry.c", 0x6f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -49,7 +48,7 @@ void bscarry_idle_update(void){ if(bastick_getZone() > 0) sp1C = BS_3B_CARRY_WALK; - if(bacarry_getMarker() == NULL) + if(bacarry_get_marker() == NULL) sp1C = BS_1_IDLE; bs_setState(sp1C); @@ -66,7 +65,7 @@ void bscarry_walk_init(void){ anctrl_setDuration(aCtrl, 0.8f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_LOOP); anctrl_start(aCtrl, "bscarry.c", 0xac); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364AF0, D_80364AF4, D_80364AF8, D_80364AFC); } @@ -78,7 +77,7 @@ void bscarry_walk_update(void){ if(bastick_getZone() == 0 && baphysics_is_slower_than(1.0f)) sp1C = BS_3A_CARRY_IDLE; - if(bacarry_getMarker() == NULL) + if(bacarry_get_marker() == NULL) sp1C = BS_1_IDLE; bs_setState(sp1C); @@ -107,7 +106,7 @@ void bscarry_interrupt(void){ break; case BS_INTR_16_THROW_CARRIED_OBJ: if(stateTimer_isDone(STATE_TIMER_1_THROW)){ - bs_setState(BS_5B_CARRY_THROW); + bs_setState(BS_CARRY_THROW); bs_setInterruptResponse(2); } else{ diff --git a/src/core2/bs/claw.c b/src/core2/bs/claw.c index cd43bd2eb..0ee1324be 100644 --- a/src/core2/bs/claw.c +++ b/src/core2/bs/claw.c @@ -3,7 +3,6 @@ #include "variables.h" #include "core2/abilityprogress.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" void func_802915CC(f32); @@ -18,8 +17,8 @@ int bsclaw_hitboxActive(void){ } void bsclaw_init(void){ - baanim_playForDuration_onceSmooth(ASSET_5_ANIM_BSPUNCH, 1.3f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_once(ASSET_5_ANIM_BSPUNCH, 1.3f); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_target_horizontal_velocity(160.0f); func_802915CC(80.0f); diff --git a/src/core2/bs/climb.c b/src/core2/bs/climb.c index 38b9724af..8252ea420 100644 --- a/src/core2/bs/climb.c +++ b/src/core2/bs/climb.c @@ -72,7 +72,7 @@ void bsclimb_idle_init(void){ f32 pole_pos[3]; player_getPosition(plyr_pos); - climb_getBottom(pole_pos); + climbGetBottom(pole_pos); if(!bsclimb_inSet(bs_getPrevState())){ func_80257F18(plyr_pos, pole_pos, &angle_towards_pole); yaw_setIdeal(angle_towards_pole); @@ -96,7 +96,7 @@ void bsclimb_idle_update(void){ case 0: D_8037D3D4 -= time_getDelta(); if(D_8037D3D4 <= 0.0f){ - baanim_playForDuration_onceSmooth(ASSET_B1_ANIM_BSCLIMB_IDLE_1, 2.96f); + baanim_playForDuration_once(ASSET_B1_ANIM_BSCLIMB_IDLE_1, 2.96f); D_8037D3D0 = 1; } break; @@ -164,13 +164,13 @@ void bsclimb_move_update(void){ if(!func_802AB788() && baphysics_get_vertical_velocity() < 30.0f) next_state = BS_4F_CLIMB_IDLE; - playerPosition_get(plyr_pos); - if(baphysics_get_target_vertical_velocity() < 0.0f && climb_getBottomY() == plyr_pos[1]) + _player_getPosition(plyr_pos); + if(baphysics_get_target_vertical_velocity() < 0.0f && climbGetBottomY() == plyr_pos[1]) next_state = BS_1_IDLE; if( func_8029825C() == 2 && 0.0f < baphysics_get_target_vertical_velocity() - && climb_getTopY() == plyr_pos[1] + && climbGetTopY() == plyr_pos[1] ){ next_state = BS_51_CLIMB_EXIT; } @@ -191,7 +191,7 @@ void bsclimb_move_end(void){ } //bsclimb_unknown_9E_init -void bsclimb_locked_init(void){ +void func_802ABCCC(void){ baanim_playForDuration_loopSmooth(ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f); baanim_setUpdateType(BAANIM_UPDATE_1_NORMAL); func_802AB654(); @@ -199,7 +199,7 @@ void bsclimb_locked_init(void){ } //bsclimb_unknown_9E_update -void bsclimb_locked_update(void){ +void func_802ABD0C(void){ s32 next_state = 0; if(!balookat_getState()) next_state = BS_4F_CLIMB_IDLE; @@ -208,7 +208,7 @@ void bsclimb_locked_update(void){ } //bsclimb_unknown_9E_end -void bsclimb_locked_end(void){ +void func_802ABD40(void){ func_802AB6F0(); } diff --git a/src/core2/bs/croc.c b/src/core2/bs/croc.c index c9671d38f..383d34b64 100644 --- a/src/core2/bs/croc.c +++ b/src/core2/bs/croc.c @@ -5,7 +5,6 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" int bscroc_inSet(enum bs_e state); @@ -55,7 +54,7 @@ void __bscroc_update_turbo_talon_trainers(void){ baflag_clear(BA_FLAG_10_TOUCHING_TURBO_TRAINERS); stateTimer_set(STATE_TIMER_3_TURBO_TALON, get_turbo_duration()); coMusicPlayer_playMusic(COMUSIC_8A_GETTING_TURBO_TRAINERS, -1); - modelAppendages_setTurboTrainersVisibility(true); + func_8029E0DC(1); } if(sp1C != 0.0f ){ @@ -63,7 +62,7 @@ void __bscroc_update_turbo_talon_trainers(void){ } if(stateTimer_isAt(STATE_TIMER_3_TURBO_TALON, 0.01f)){ - modelAppendages_setTurboTrainersVisibility(false); + func_8029E0DC(0); func_8030E58C(SFX_3EB_UNKNOWN, 1.35f); } } @@ -81,8 +80,8 @@ void __bscroc_update_velocity(void){ void __bscroc_end(void){ if(!bscroc_inSet(bs_getNextState())){ bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); + func_8029E070(0); + func_8029E064(0); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -92,13 +91,13 @@ void __bscroc_end(void){ int bscroc_inSet(enum bs_e state){ return state == BS_5E_CROC_IDLE - || state == BS_5F_CROC_WALK - || state == BS_60_CROC_JUMP + || state == BS_CROC_WALK + || state == BS_CROC_JUMP || state == BS_61_CROC_FALL - || state == BS_63_CROC_OW - || state == BS_63_CROC_OW + || state == BS_CROC_OW + || state == BS_CROC_OW || state == BS_6E_CROC_BITE - || state == BS_6F_CROC_EAT_BAD + || state == BS_CROC_EAT_BAD || state == BS_70_CROC_EAT_GOOD || state == BS_8D_CROC_LOCKED || state == BS_94_CROC_DRONE; @@ -106,7 +105,7 @@ int bscroc_inSet(enum bs_e state){ void bscroc_idle_init(void){ baanim_playForDuration_loopSmooth(ASSET_E1_ANIM_BSCROC_IDLE, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -127,13 +126,13 @@ void bscroc_idle_update(void){ next_state = badrone_look(); if(bastick_getZone() > 0) - next_state = BS_5F_CROC_WALK; + next_state = BS_CROC_WALK; if(bakey_pressed(BUTTON_B)) next_state = BS_6E_CROC_BITE; if(bakey_pressed(BUTTON_A)) - next_state = BS_60_CROC_JUMP; + next_state = BS_CROC_JUMP; next_state = func_8029CA94(next_state); bs_setState(next_state); @@ -146,8 +145,8 @@ void bscroc_idle_end(void){ } void bscroc_walk_init(void){ - baanim_playForDuration_loopSmoothStartingAt(ASSET_E0_ANIM_BSCROC_WALK, 0.8f, 0.4f); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + baanim_playForDuration_loopStartingAt(ASSET_E0_ANIM_BSCROC_WALK, 0.8f, 0.4f); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ, 1, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(bsCrocMinWalkVelocity, bsCrocMaxWalkVelocity, bsCrocSlowestWalkDuration, bsCrocFastestWalkDuration); func_802900B4(); } @@ -171,7 +170,7 @@ void bscroc_walk_update(void){ next_state = BS_6E_CROC_BITE; if(bakey_pressed(BUTTON_A)) - next_state = BS_60_CROC_JUMP; + next_state = BS_CROC_JUMP; bs_setState(next_state); } @@ -192,7 +191,7 @@ void bscroc_jump_init(void){ anctrl_setStart(aCtrl, 0.1f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bscroc.c", 0x1ac); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -254,10 +253,10 @@ void bscroc_jump_update(void){ if(player_isStable()){ if(bastick_getZone() > 0) - sp2C = BS_5F_CROC_WALK; + sp2C = BS_CROC_WALK; if(bakey_pressed(BUTTON_A)) - sp2C = BS_60_CROC_JUMP; + sp2C = BS_CROC_JUMP; } if(bakey_pressed(BUTTON_B)) @@ -280,7 +279,7 @@ void bscroc_fall_init(void){ anctrl_setDuration(aCtrl, 0.7f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bscroc.c", 0x235); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); D_8037D3EC = 0; } @@ -346,7 +345,7 @@ static void __bscroc_recoil_init(s32 damage){ else func_8030E58C(SFX_56_BANJO_HUI, 1.8f); - playerPosition_get(player_position); + _player_getPosition(player_position); func_80294980(sp20); func_80257F18(sp20, player_position, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -354,7 +353,7 @@ static void __bscroc_recoil_init(s32 damage){ baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -430,8 +429,8 @@ void bscroc_die_init(void){ anctrl_setDuration(aCtrl, 1.7f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bscroc.c", 0x32b); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); - playerPosition_get(player_position); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); + _player_getPosition(player_position); func_80294980(sp20); func_80257F18(sp20, player_position, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -446,7 +445,7 @@ void bscroc_die_init(void){ baMarker_collisionOff(); baeyes_close(); func_802914CC(0xd); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8029C984(); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); batimer_set(0, 2.9f); @@ -514,8 +513,8 @@ static void func_802ACF58(void){ } void bscroc_bite_init(void){ - baanim_playForDuration_loopSmoothStartingAt(ASSET_122_ANIM_BSCROC_BITE, 0.25f, 0.2f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_loopStartingAt(ASSET_122_ANIM_BSCROC_BITE, 0.25f, 0.2f); + func_8029C7F4(1,1,1, BA_PHYSICS_LOCKED_ROTATION); func_802ACF58(); D_8037D3F4 = 0; _bscrocHitboxActive = true; @@ -548,11 +547,11 @@ void bscroc_bite_update(void){ if(player_shouldFall()) next_state = BS_61_CROC_FALL; else - next_state = BS_5F_CROC_WALK; + next_state = BS_CROC_WALK; } if(player_isStable() && bakey_pressed(BUTTON_A)) - next_state = BS_60_CROC_JUMP; + next_state = BS_CROC_JUMP; bs_setState(next_state); } @@ -563,8 +562,8 @@ void bscroc_bite_end(void){ } void bscroc_eat_bad_init(void){ - baanim_playForDuration_onceSmooth(ASSET_123_ANIM_BSCROC_EAT_BAD, 2.41f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_once(ASSET_123_ANIM_BSCROC_EAT_BAD, 2.41f); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_horizontal_velocity(0.0f); } @@ -615,7 +614,7 @@ void bscroc_set_ate_wrong_thing(void){ void bscroc_eat_good_init(void){ baanim_playForDuration_loopSmooth(ASSET_122_ANIM_BSCROC_BITE, 0.25f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baModel_setPostDraw((void (*)(Gfx **, Mtx **, Vtx **))func_802AD2A8); D_8037D3E8 = assetcache_get(func_80294974()); D_8037D3F0 = 1.0f; @@ -646,7 +645,7 @@ void bscroc_eat_good_update(void){ break; case 3: if(s_ate_wrong) - next_state = BS_6F_CROC_EAT_BAD; + next_state = BS_CROC_EAT_BAD; else next_state = BS_5E_CROC_IDLE; break; @@ -671,7 +670,7 @@ void bscroc_eat_good_end(void){ void bscroc_locked_enter(void){ baanim_playForDuration_loopSmooth(ASSET_E1_ANIM_BSCROC_IDLE, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); diff --git a/src/core2/bs/crouch.c b/src/core2/bs/crouch.c index 440744f60..c4e0d3a01 100644 --- a/src/core2/bs/crouch.c +++ b/src/core2/bs/crouch.c @@ -18,12 +18,12 @@ void func_802AD6D0(void){ } void func_802AD6FC(void){ - baanim_playForDuration_onceSmooth(ASSET_116_ANIM_BSCROUCH_NOINPUT, 2.0f); + baanim_playForDuration_once(ASSET_116_ANIM_BSCROUCH_NOINPUT, 2.0f); D_8037D404 = 2; } void func_802AD728(void){ - baanim_playForDuration_onceSmoothStartingAt(ASSET_10C_ANIM_BSCROUCH_IDLE, 0.5f, 0.9999f); + baanim_playForDuration_onceStartingAt(ASSET_10C_ANIM_BSCROUCH_IDLE, 0.5f, 0.9999f); batimer_set(2, 2.0f); D_8037D404 = 1; } @@ -159,7 +159,7 @@ void bscrouch_update(void){ }//L802ADC50 if(player_isSliding()) - sp34 = BS_32_SLIDE; + sp34 = BS_SLIDE; if(player_shouldFall()) sp34 = BS_2F_FALL; @@ -181,7 +181,7 @@ enum bs_e func_802ADCD4(enum bs_e arg0){ arg0 = BS_1_IDLE; if(bakey_pressed(BUTTON_B) && can_claw()) - arg0 = BS_6_CLAW; + arg0 = BS_CLAW; if(bakey_pressed(BUTTON_A)) arg0 = bs_getTypeOfJump(); @@ -203,7 +203,7 @@ enum bs_e func_802ADCD4(enum bs_e arg0){ arg0 = BS_12_BFLIP; if(bainput_should_beak_barge()) - arg0 = BS_13_BBARGE; + arg0 = BS_BBARGE; } diff --git a/src/core2/bs/die.c b/src/core2/bs/die.c index ae2b823f4..626983387 100644 --- a/src/core2/bs/die.c +++ b/src/core2/bs/die.c @@ -37,7 +37,7 @@ void bsdie_init(void){ anctrl_start(aCtrl, "bsdie.c", 0x7e); func_8029B930(); func_8030E58C(SFX_36_BANJO_DOH, 1.0f); - playerPosition_get(sp2C); + _player_getPosition(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); D_8037D410 = 250.0f; @@ -53,9 +53,9 @@ void bsdie_init(void){ baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1400.0f); pitch_setAngVel(1000.0f, 12.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_8029151C(0xd); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8029C984(); batimer_set(0,2.9f); D_8037D414 = 0; @@ -112,7 +112,7 @@ void bsdie_update(void){ && floor_isCurrentFloorunk59() && ( D_8037D414 || ( anctrl_isStopped(aCtrl) - && ( playerPosition_getY() < (floor_getCurrentFloorYPosition() - 150.0f)) + && ( player_getYPosition() < (floor_getCurrentFloorYPosition() - 150.0f)) ) ) && player_inWater() @@ -127,7 +127,7 @@ void bsdie_update(void){ void bsdie_end(void){ core1_ce60_incOrDecCounter(false); baphysics_reset_gravity(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); pitch_setIdeal(0.0f); roll_setIdeal(0.0f); func_80291548(); diff --git a/src/core2/bs/bFlap.c b/src/core2/bs/flap_flip.c similarity index 94% rename from src/core2/bs/bFlap.c rename to src/core2/bs/flap_flip.c index bf2615a71..898da2356 100644 --- a/src/core2/bs/bFlap.c +++ b/src/core2/bs/flap_flip.c @@ -1,11 +1,9 @@ -// BanjoDecomp: core2/bs/bFlap.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" f32 func_802A2858(void); @@ -22,8 +20,8 @@ f32 D_8037D308; u8 D_8037D30C; void bsbflap_init(void) { - baanim_playForDuration_once(ASSET_18_ANIM_BSBFLAP_ENTER, 0.3f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + baanim_playForDuration_onceSmooth(ASSET_18_ANIM_BSBFLAP_ENTER, 0.3f); + func_8029C7F4(1, 1, 1, BA_PHYSICS_NORMAL); if (bastick_distance() != 0.0f) { yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -32,7 +30,7 @@ void bsbflap_init(void) { baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); baphysics_set_vertical_velocity(0.0f); baphysics_set_gravity(D_80364A14); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); baflag_set(BA_FLAG_12_HAS_FLAPPED); batimer_set(0, 2.5f); D_8037D30C = sfxsource_createSfxsourceAndReturnIndex(); @@ -199,6 +197,6 @@ void bsbflap_end(void) { ability_use(1); baphysics_reset_gravity(); baphysics_reset_terminal_velocity(); - modelAppendages_setKazooiesUpperHalfVisibilityAndTimer(0, 0.2f); + func_8029E090(0, 0.2f); sfxsource_freeSfxsourceByIndex(D_8037D30C); } diff --git a/src/core2/bs/ow.c b/src/core2/bs/hurt.c similarity index 98% rename from src/core2/bs/ow.c rename to src/core2/bs/hurt.c index d627bd33a..333f8c836 100644 --- a/src/core2/bs/ow.c +++ b/src/core2/bs/hurt.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/ow.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/jig.c b/src/core2/bs/jiggy_dance.c similarity index 92% rename from src/core2/bs/jig.c rename to src/core2/bs/jiggy_dance.c index 136e613cd..6ad7325a9 100644 --- a/src/core2/bs/jig.c +++ b/src/core2/bs/jiggy_dance.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/jig.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .bss */ u8 D_8037D4B0; @@ -32,7 +30,7 @@ void bsjig_jiggy_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsjig.c", 0x7f); yaw_setIdeal(func_8029B41C()); //face camera - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); core1_ce60_incOrDecCounter(false); func_8025A2FC(0,0xfa0); @@ -42,7 +40,7 @@ void bsjig_jiggy_init(void){ D_8037D4B1 = tmp; coMusicPlayer_playMusic(COMUSIC_D_JINGLE_JIGGY_COLLECTED, -1); func_8029151C(0xC); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_8030E6D4(SFX_33_BANJO_AHOO); baflag_clear(BA_FLAG_7_TOUCHING_JIGGY); baflag_clear(BA_FLAG_F); @@ -103,7 +101,7 @@ void bsjig_jiggy_end(void){ item_inc(ITEM_E_JIGGY); func_802B0CD8(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); func_80291548(); if(bs_getNextState() != BS_34_JIG_NOTEDOOR){ @@ -151,7 +149,7 @@ void bsjig_notedoor_end(void){ baMarker_collisionOn(); func_8025A2FC(-1, 0xfa0); core1_ce60_incOrDecCounter(true); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); func_80291548(); if( D_8037D4B2 && jiggyscore_total() == 100 @@ -173,7 +171,7 @@ void bsjig_notedoor_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsjig.c", 0x14d); yaw_setIdeal(func_8029B41C()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); if(bs_getPrevState() != BS_44_JIG_JIGGY){ core1_ce60_incOrDecCounter(false); @@ -181,7 +179,7 @@ void bsjig_notedoor_init(void){ } coMusicPlayer_playMusic(COMUSIC_42_NOTEDOOR_OPENING_FANFARE,-1); func_8029151C(0xc); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_8030E6D4(SFX_33_BANJO_AHOO); baMarker_collisionOff(); } diff --git a/src/core2/bs/jump.c b/src/core2/bs/jump.c index ea331a73a..2506d8990 100644 --- a/src/core2/bs/jump.c +++ b/src/core2/bs/jump.c @@ -7,7 +7,6 @@ #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" f32 func_80294438(void); void basfx_playJumpSfx(f32, f32); @@ -40,7 +39,7 @@ void bsjump_init(void){ D_8037D4C2 = baflag_isTrue(BA_FLAG_2_ON_SPRING_PAD); sp30 = bs_getPrevState(); if(bsclimb_inSet(sp30)){ - climb_release(); + climbRelease(); } if(sp30 == BS_11_BPECK){ @@ -60,7 +59,7 @@ void bsjump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.5042f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsjump.c", 0x95); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f){ yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -118,12 +117,12 @@ void bsjump_update(void){ } break; case 1://L802B14B4 - if( 500.0f < (playerPosition_getY() - func_80294438())){ + if( 500.0f < (player_getYPosition() - func_80294438())){ sp34 = BS_2F_FALL; } if(D_8037D4C2){ D_8037D4C2 = 0; - sp34 = BS_21_BSHOCK_CHARGE; + sp34 = BS_BSHOCK_CHARGE; } if(func_8028B254(0x5A)){ anctrl_setSubRange(aCtrl, 0.0, 1.0f); @@ -143,7 +142,7 @@ void bsjump_update(void){ D_8037D4C2 = 0; if(bainput_should_feathery_flap()) - sp34 = BS_10_BFLAP; + sp34 = BS_BFLAP; if(bainput_should_peck()) sp34 = BS_11_BPECK; @@ -184,7 +183,7 @@ void bsjump_fall_init(void){ anctrl_setTransitionDuration(aCtrl, 0.3f); anctrl_setDuration(aCtrl, 0.38f); anctrl_start(aCtrl, "bsjump.c", 0x188); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); D_8037D4C0 = 0; } @@ -220,7 +219,7 @@ void bsjump_fall_update(void){ sp2C = BS_3D_FALL_TUMBLING; if(bainput_should_feathery_flap() && baflag_isFalse(BA_FLAG_5_HAS_PECKED)) - sp2C = BS_10_BFLAP; + sp2C = BS_BFLAP; if(bainput_should_peck()) sp2C = BS_11_BPECK; @@ -234,7 +233,7 @@ void bsjump_fall_update(void){ else if(player_inWater()){ func_8029CCC4(); if(baflag_isTrue(BA_FLAG_6) || baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)){ - sp2C = BS_D_TIMEOUT_TRANSFORMATION; + sp2C = BS_D_TIMEOUT; } }//L802B18E8 @@ -249,11 +248,11 @@ void bsjump_fall_update(void){ void bsjump_fall_end(void){} -void bsjump_climbExit_init(void) { +void func_802B1928(void) { AnimCtrl *anim_ctrl; anim_ctrl = baanim_getAnimCtrlPtr(); - climb_release(); + climbRelease(); anctrl_reset(anim_ctrl); anctrl_setIndex(anim_ctrl, ASSET_8_ANIM_BSJUMP); anctrl_setDuration(anim_ctrl, 1.9f); @@ -276,7 +275,7 @@ void bsjump_climbExit_init(void) { func_802B1100(); } -void bsjump_climbExit_update(void) { +void func_802B1A54(void) { s32 next_state; AnimCtrl *anim_ctrl; f32 velocity[3]; @@ -320,7 +319,7 @@ void bsjump_climbExit_update(void) { bs_setState(next_state); } -void bsjump_climbExit_end(void){ +void func_802B1BCC(void){ func_80294378(1); baphysics_reset_gravity(); } @@ -389,7 +388,7 @@ bool bsjump_jumpingFromWater(void){ void bsjump_tumble_init(void){ baanim_playForDuration_loop(ASSET_68_ANIM_BSJUMP_TUMBLE, 0.35f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); baModel_setYDisplacement(60.0f); if(bafalldamage_get_state() == 1){ batimer_set(0, 0.5f); @@ -414,7 +413,7 @@ void bsjump_tumble_update(void){ } if(batimer_isNonzero(0)){ if(bainput_should_feathery_flap()) - sp1C = BS_10_BFLAP; + sp1C = BS_BFLAP; if(bainput_should_peck()) sp1C = BS_11_BPECK; @@ -427,7 +426,7 @@ void bsjump_tumble_update(void){ sp1C = BS_4C_LANDING_IN_WATER; if(player_isStable()) - sp1C = BS_72_SPLAT; + sp1C = BS_SPLAT; bs_setState(sp1C); } @@ -435,7 +434,7 @@ void bsjump_tumble_update(void){ void bsjump_tumble_end(void){ enum bs_e next_state = bs_getNextState(); if( next_state == BS_F_BBUSTER - || next_state == BS_10_BFLAP + || next_state == BS_BFLAP || next_state == BS_11_BPECK ){ bafalldamage_set_state(3); diff --git a/src/core2/bs/player_spawn.c b/src/core2/bs/player_spawn.c index 50c667bcc..d69f06c9c 100644 --- a/src/core2/bs/player_spawn.c +++ b/src/core2/bs/player_spawn.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_14420.c #include #include "core1/core1.h" #include "functions.h" @@ -60,138 +59,123 @@ s16 D_80364624[14] = { BS_1B_WONDERWING_IDLE }; -u8 D_80364640[14] = { - true, - true, - true, - true, - false, - false, - true, - false, - true, - true, - true, - true, - false, - true -}; +u8 D_80364640[14] = {1, 1, 1, 1, 0, 0, 1, 0 , 1, 1, 1, 1, 0, 1}; Struct_core2_13FC0 D_80364650[14] = { - {BS_92_ANT_DRONE, ASSET_5F_ANIM_BSANT_WALK, 0.4f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.4f}, - {BS_94_CROC_DRONE, ASSET_E0_ANIM_BSCROC_WALK, 0.6f}, - {BS_95_WALRUS_DRONE, ASSET_120_ANIM_BSWALRUS_WALK, 0.7f}, - {BS_96_SWIM_DRONE, ASSET_39_ANIM_BSSWIM_MOVE, 0.8f}, - {BS_97_DIVE_DRONE, ASSET_71_ANIM_BSSWIM_DIVE_SLOW, 0.75f}, - {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_15_ANIM_BSBTROT_WALK, 0.53f}, - {BS_9B_LONGLEG_DRONE, ASSET_42_ANIM_BSLONGLEG_WALK, 0.8f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DC_ANIM_BEE_FLY, 0.38f}, - {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, - {BS_A4_WONDERWING_DRONE, ASSET_11_ANIM_BSWHIRL_WALK, 0.53f} + {BS_92_ANT_DRONE, ASSET_5F_ANIM_BSANT_WALK, 0.4f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.4f}, + {BS_94_CROC_DRONE, ASSET_E0_ANIM_BSCROC_WALK, 0.6f}, + {BS_95_WALRUS_DRONE, ASSET_120_ANIM_BSWALRUS_WALK, 0.7f}, + {BS_96_SWIM_DRONE, ASSET_39_ANIM_BSSWIM_MOVE, 0.8f}, + {BS_97_DIVE_DRONE, ASSET_71_ANIM_BSSWIM_DIVE_SLOW, 0.75f}, + {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_15_ANIM_BSBTROT_WALK, 0.53f}, + {BS_9B_LONGLEG_DRONE, ASSET_42_ANIM_BSLONGLEG_WALK, 0.8f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DC_ANIM_BEE_FLY, 0.38f}, + {BS_98_WALK_DRONE, ASSET_3_ANIM_BSWALK, 0.43f}, + {BS_A4_WONDERWING_DRONE, ASSET_11_ANIM_BSWHIRL_WALK, 0.53f} }; Struct_core2_13FC0 D_803646C0[14] = { - {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, - {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, - {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, - {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, - {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, - {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, - {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, - {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} + {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, + {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, + {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, + {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, + {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, + {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, + {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, + {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f}, }; Struct_core2_13FC0 D_80364730[14] = { - {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, - {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, - {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, - {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, - {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, - {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, - {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, - {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} + {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, + {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, + {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, + {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, + {BS_98_WALK_DRONE, ASSET_19B_ANIM_UNKNOWN, 4.5f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, + {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, + {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, + {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f}, }; Struct_core2_13FC0 D_803647A0[14] = { - {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, - {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, - {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, - {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, - {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, - {BS_98_WALK_DRONE, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, - {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, - {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, - {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, - {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, - {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, - {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, - {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} + {BS_92_ANT_DRONE, ASSET_5E_ANIM_BSANT_IDLE, 1.2f}, + {BS_93_PUMPKIN_DRONE, ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f}, + {BS_94_CROC_DRONE, ASSET_E1_ANIM_BSCROC_IDLE, 1.0f}, + {BS_95_WALRUS_DRONE, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_96_SWIM_DRONE, ASSET_57_ANIM_BSSWIM_IDLE, 1.2f}, + {BS_97_DIVE_DRONE, ASSET_70_ANIM_BSSWIM_DIVE_IDLE, 2.0f}, + {BS_98_WALK_DRONE, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, + {BS_99_BFLY_DRONE, ASSET_38_ANIM_BSBFLY, 0.62f}, + {BS_9A_BTROT_DRONE, ASSET_26_ANIM_BSBTROT_IDLE, 1.2f}, + {BS_9B_LONGLEG_DRONE, ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f}, + {BS_9C_WALRUS_SLED_DRONE, ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f}, + {BS_9D_BEE_DRONE, ASSET_1DE_ANIM_BEE_IDLE, 3.0f}, + {BS_98_WALK_DRONE, ASSET_B2_ANIM_BSCLIMB_IDLE_2, 2.64f}, + {BS_A4_WONDERWING_DRONE, ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f} }; Struct_core2_13FC0 D_80364810[14] = { - {BS_8E_ANT_LOCKED, 0, 0.0f}, - {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, - {BS_8D_CROC_LOCKED, 0, 0.0f}, - {BS_73_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, - {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, - {BS_73_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, - {BS_76_BFLY_LOCKED, 0, 0.0f}, - {BS_79_BTROT_LOCKED, 0, 0.0f}, - {BS_62_LONGLEG_LOCKED, 0, 0.0f}, - {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, - {BS_6B_BEE_LOCKED, 0, 0.0f}, - {BS_9E_CLIMB_LOCKED, 0, 0.0f}, - {BS_A5_WONDERWING_UNKA5, 0, 0.0f} + {BS_8E_ANT_LOCKED, 0, 0.0f}, + {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, + {BS_8D_CROC_LOCKED, 0, 0.0f}, + {BS_73_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, + {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, + {BS_73_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, + {BS_76_BFLY_LOCKED, 0, 0.0f}, + {BS_79_BTROT_LOCKED, 0, 0.0f}, + {BS_62_LONGLEG_LOCKED, 0, 0.0f}, + {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, + {BS_6B_BEE_LOCKED, 0, 0.0f}, + {BS_9E_CLIMB_LOCKED, 0, 0.0f}, + {BS_A5_WONDERWING_UNKA5, 0, 0.0f}, }; Struct_core2_13FC0 D_80364880[14] = { - {BS_8E_ANT_LOCKED, 0, 0.0f}, - {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, - {BS_8D_CROC_LOCKED, 0, 0.0f}, - {BS_74_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, - {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, - {BS_74_UNKNOWN, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, - {BS_76_BFLY_LOCKED, 0, 0.0f}, - {BS_79_BTROT_LOCKED, 0, 0.0f}, - {BS_62_LONGLEG_LOCKED, 0, 0.0f}, - {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, - {BS_6B_BEE_LOCKED, 0, 0.0f}, - {BS_9E_CLIMB_LOCKED, 0, 0.0f}, - {BS_A5_WONDERWING_UNKA5, 0, 0.0f} + {BS_8E_ANT_LOCKED, 0, 0.0f}, + {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, + {BS_8D_CROC_LOCKED, 0, 0.0f}, + {BS_74_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, + {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, + {BS_74_UNKNOWN, ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f}, + {BS_76_BFLY_LOCKED, 0, 0.0f}, + {BS_79_BTROT_LOCKED, 0, 0.0f}, + {BS_62_LONGLEG_LOCKED, 0, 0.0f}, + {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, + {BS_6B_BEE_LOCKED, 0, 0.0f}, + {BS_9E_CLIMB_LOCKED, 0, 0.0f}, + {BS_A5_WONDERWING_UNKA5, 0, 0.0f} }; Struct_core2_13FC0 D_803648F0[14] = { - {BS_8E_ANT_LOCKED, 0, 0.0f}, - {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, - {BS_8D_CROC_LOCKED, 0, 0.0f}, - {BS_75_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, - {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, - {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, - {BS_75_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, - {BS_76_BFLY_LOCKED, 0, 0.0f}, - {BS_79_BTROT_LOCKED, 0, 0.0f}, - {BS_62_LONGLEG_LOCKED, 0, 0.0f}, - {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, - {BS_6B_BEE_LOCKED, 0, 0.0f}, - {BS_9E_CLIMB_LOCKED, 0, 0.0f}, - {BS_A5_WONDERWING_UNKA5, 0, 0.0f} + {BS_8E_ANT_LOCKED, 0, 0.0f}, + {BS_8F_PUMPKIN_LOCKED, 0, 0.0f}, + {BS_8D_CROC_LOCKED, 0, 0.0f}, + {BS_75_UNKNOWN, ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f}, + {BS_77_SWIM_LOOKAT_DRONE, 0, 0.0f}, + {BS_78_DIVE_LOOKAT_DRONE, 0, 0.0f}, + {BS_75_UNKNOWN, ASSET_14A_ANIM_BSREST_LISTEN, 11.4f}, + {BS_76_BFLY_LOCKED, 0, 0.0f}, + {BS_79_BTROT_LOCKED, 0, 0.0f}, + {BS_62_LONGLEG_LOCKED, 0, 0.0f}, + {BS_81_WALRUS_SLED_LOCKED, 0, 0.0f}, + {BS_6B_BEE_LOCKED, 0, 0.0f}, + {BS_9E_CLIMB_LOCKED, 0, 0.0f}, + {BS_A5_WONDERWING_UNKA5, 0, 0.0f} }; /* .bss */ @@ -297,8 +281,6 @@ void func_8029B62C(void){ func_802E4048(gVoidOutReturnLocation[0], gVoidOutReturnLocation[1], 1); return; } - // [port] Permadeath difficulty empties the reserve and erases the save here. - CALL_EVENT(OnPlayerDeath); if(item_empty(ITEM_16_LIFE)){ if(!fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE) || fileProgressFlag_get(FILEPROG_A6_FURNACE_FUN_COMPLETE)){ func_8025A430(-1, 0x7D0, 3); @@ -314,12 +296,7 @@ void func_8029B62C(void){ } } else{ - // [port] Romhack gate: listeners can replace the void-out respawn with a - // full map transition. - if (EventSystem_Should(VB_VOID_OUT_RESPAWN_TRANSITION, true, gVoidOutReturnLocation[0], - gVoidOutReturnLocation[1])) { - func_802E4048(gVoidOutReturnLocation[0], gVoidOutReturnLocation[1], 1); - } + func_802E4048(gVoidOutReturnLocation[0], gVoidOutReturnLocation[1], 1); } } @@ -399,7 +376,7 @@ void func_8029B984(f32 dst[3]){ f32 plyr_pos[3]; f32 sp18[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); viewport_getPosition_vec3f(sp18); ml_vec3f_diff_copy(dst, sp18, plyr_pos); } @@ -619,7 +596,7 @@ enum bs_e bs_getIdleState(void){ return BS_26_LONGLEG_IDLE; } if (player_inWater()) { - if (playerPosition_getY() > (floor_getCurrentFloorYPosition() - 80.0f)) { + if (player_getYPosition() > (floor_getCurrentFloorYPosition() - 80.0f)) { return BS_2D_SWIM_IDLE; } return BS_2B_DIVE_IDLE; @@ -638,7 +615,7 @@ void func_8029C0D0(void) { f32 sp34; if (floor_isCurrentFloorunk59()) { - playerPosition_get(sp3C); + _player_getPosition(sp3C); sp3C[1] = sp34 = floor_getCurrentFloorYPosition(); p_ctrl = func_802F4094(sp3C, 35.0f); fxRipple_802F3554(3, sp3C); @@ -658,7 +635,7 @@ void func_8029C0D0(void) { void func_8029C22C(void) { - if(floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > playerPosition_getY()) + if(floor_isCurrentFloorunk59() && floor_getCurrentFloorYPosition() > player_getYPosition()) return; D_80364620 = D_80364620 ? false : true; @@ -675,7 +652,7 @@ void func_8029C22C(void) { void func_8029C304(s32 arg0) { f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); sp1C[1] = floor_getCurrentFloorYPosition(); fxRipple_802F3584(arg0, sp1C, (uintptr_t)func_802946CC()); } @@ -683,7 +660,7 @@ void func_8029C304(s32 arg0) { void func_8029C348(void) { f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); sp1C[0] += randf2(-30.0f, 30.0f); sp1C[1] += randf2(60.0f, 70.0f); sp1C[2] += randf2(-30.0f, 30.0f); @@ -698,7 +675,7 @@ void func_8029C3E8(f32 arg0, f32 arg1) { f32 sp2C; f32 sp28; - playerPosition_get(sp30); + _player_getPosition(sp30); sp28 = ml_map_f(baphysics_get_horizontal_velocity(), 0.0f, 1000.0f, arg0, arg1); sp2C = player_getYaw(); func_802589E4(sp3C, sp2C, sp28); @@ -763,7 +740,7 @@ void func_8029C674(void) { baflag_set(BA_FLAG_17_FIRST_PERSON_VIEW); ncDynamicCamera_enterFirstPerson(); func_8028E9C4(5, sp1C); - ncba1p_setZoomedOutPosition(sp1C); + ncFirstPersonCamera_setZoomedOutPosition(sp1C); } } @@ -775,11 +752,11 @@ void func_8029C6D0(void) { if (balookat_getState() == 4 && D_8037D1E8) { func_8028E9C4(5, sp18); - ncba1p_setZoomedOutPosition(sp18); + ncFirstPersonCamera_setZoomedOutPosition(sp18); func_8028E9C4(5, sp30); balookat_try_get_position(sp24); func_802BC434(sp3C, sp24, sp30); - ncba1p_setZoomedOutRotation(sp3C); + ncFirstPersonCamera_setZoomedOutRotation(sp3C); } } @@ -803,7 +780,7 @@ enum bs_e bs_getTypeOfJump(void){ return BS_5_JUMP; } -void code_14420_setUpdateTypes(enum baanim_update_type_e arg0, enum yaw_state_e yaw_state, s32 arg2, BaPhysicsType arg3){ +void func_8029C7F4(s32 arg0, s32 yaw_state, s32 arg2, s32 arg3){ baanim_setUpdateType(arg0); yaw_setUpdateState(yaw_state); func_8029957C(arg2); @@ -873,16 +850,16 @@ s32 func_8029C9C0(s32 arg0){ // [port] v1.1 fix: check sliding first so claw swipe can't trigger during a slide if(bakey_pressed(BUTTON_B) && can_claw() && (EventSystem_Should(VB_CLAW_SWIPE_SLIDE, true) || !player_isSliding())) - arg0 = BS_6_CLAW; + arg0 = BS_CLAW; if(bakey_held(BUTTON_Z) && bainput_should_beak_barge()) - arg0 = BS_13_BBARGE; + arg0 = BS_BBARGE; if(bainput_should_look_first_person_camera()) arg0 = badrone_look(); if(player_isSliding()) - arg0 = BS_32_SLIDE; + arg0 = BS_SLIDE; return arg0; } @@ -901,14 +878,14 @@ s32 func_8029CA94(s32 arg0){ arg0 = BS_14_BTROT_ENTER; if(baflag_isTrue(BA_FLAG_6)) - arg0 = BS_53_TIMEOUT_BANJO; + arg0 = BS_53_TIMEOUT; if(baflag_isTrue(BA_FLAG_7_TOUCHING_JIGGY)) { arg0 = BS_44_JIG_JIGGY; } if(baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)) - arg0 = (player_getTransformation() == TRANSFORM_4_WALRUS) ? BS_80_WALRUS_SLED_LOSE : BS_53_TIMEOUT_BANJO; + arg0 = (player_getTransformation() == TRANSFORM_4_WALRUS) ? BS_80_WALRUS_SLED_LOSE : BS_53_TIMEOUT; baflag_clear(BA_FLAG_F); @@ -986,7 +963,7 @@ void func_8029CDC0(void) { f32 sp2C[3]; f32 sp20[3]; - playerPosition_get(sp20); + _player_getPosition(sp20); sp20[0] += (randf() * 90.0f) - 45.0f; sp20[2] += (randf() * 90.0f) - 45.0f; sp2C[0] = (randf() * 20.0f) - 10.0f; diff --git a/src/core2/bs/pumpkin.c b/src/core2/bs/pumpkin.c index c5f3d8b2e..1f1b41ff9 100644 --- a/src/core2/bs/pumpkin.c +++ b/src/core2/bs/pumpkin.c @@ -5,7 +5,6 @@ #include "core2/ba/model.h" #include "core2/ba/anim.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" extern void baanim_playForDuration_loop(s32, f32); extern void func_8029AD68(f32, s32); @@ -54,8 +53,8 @@ void func_802B223C(void) { void func_802B229C(void) { if (!bspumpkin_inSet(bs_getNextState())) { bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); + func_8029E070(0); + func_8029E064(0); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -76,7 +75,7 @@ int bspumpkin_inSet(s32 move_indx){ void bspumpkin_idle_init(void) { baanim_playForDuration_loop(ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 1, 1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -120,7 +119,7 @@ void bspumpkin_walk_init(void) { anctrl_setDuration(anim_ctrl, 0.8f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bspumpkin.c", 0x11D); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2, 1, 1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364CF0, D_80364CF4, D_80364CF8, D_80364CFC); func_802900B4(); } @@ -159,7 +158,7 @@ void bspumpkin_jump_init(void) { anctrl_setDuration(anim_ctrl, 1.2f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); anctrl_start(anim_ctrl, "bspumpkin.c", 0x16C); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1, 1, 3, BA_PHYSICS_AIRBORN); if (bastick_distance() != 0.0f) { yaw_setIdeal(bastick_getAngleRelativeToBanjo()); } @@ -253,7 +252,7 @@ void bspumpkin_fall_init(void) { anctrl_setDuration(anim_ctrl, 0.7f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_STOPPED); anctrl_start(anim_ctrl, "bspumpkin.c", 0x1F1); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1, 1, 3, BA_PHYSICS_AIRBORN); D_8037D4E0 = 0; } @@ -304,16 +303,16 @@ void bspumpkin_fall_end(void){ func_802B229C(); } -void bspumpkin_flush_init(void) { +void func_802B2BF0(void) { func_8029656C(D_8037D4E8); func_8028FAB0(D_8037D4E8); baanim_playForDuration_loop(ASSET_A0_ANIM_BSPUMPKIN_WALK, 0.8f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_FREEZE); + func_8029C7F4(1, 1, 2, BA_PHYSICS_FREEZE); func_80294378(6); batimer_set(0, 0.0f); } -void bspumpkin_flush_update(void) { +void func_802B2C58(void) { f32 sp3C; f32 sp38; f32 sp34; @@ -331,7 +330,7 @@ void bspumpkin_flush_update(void) { func_8028FAB0(sp28); } -void bspumpkin_flush_end(void) { +void func_802B2D50(void) { func_80294378(1); baModel_setScale(1.0f); } @@ -354,7 +353,7 @@ void __bspumpkin_bounce_init(s32 arg0) { } else { func_8030E58C(SFX_56_BANJO_HUI, 1.8f); } - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); func_80294980(sp20); func_80257F18(sp20, plyr_pos, &sp38); yaw_setIdeal(mlNormalizeAngle(sp38 + 180.0f)); @@ -362,7 +361,7 @@ void __bspumpkin_bounce_init(s32 arg0) { baphysics_set_target_horizontal_velocity(200.0f); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); baMarker_collisionOff(); @@ -442,7 +441,7 @@ void bspumpkin_die_init(void) { anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); anctrl_start(anim_ctrl, "bspumpkin.c", 0x32E); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); func_80294980(sp20); func_80257F18(sp20, plyr_pos, &sp38); D_8037D4F4 = 250.0f; @@ -451,12 +450,12 @@ void bspumpkin_die_init(void) { baphysics_set_target_horizontal_velocity(D_8037D4F4); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(510.0f); baphysics_set_gravity(-1200.0f); pitch_setAngVel(1000.0f, 12.0f); func_802914CC(0xD); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8029C984(); baMarker_collisionOff(); baeyes_close(); @@ -533,15 +532,15 @@ void bspumpkin_die_end(void) { func_80291548(); } -void bspumpkin_locked_init(void) { +void func_802B34A0(void) { baanim_playForDuration_loopSmooth(0xA0, 0.8f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B3A50(); } -void bspumpkin_locked_update(void) { +void func_802B34F8(void) { s32 next_state; next_state = 0; @@ -553,7 +552,7 @@ void bspumpkin_locked_update(void) { bs_setState(next_state); } -void bspumpkin_locked_end(void) { +void func_802B353C(void) { func_8029C748(); func_802B229C(); } diff --git a/src/core2/bs/rebound.c b/src/core2/bs/rebound.c index a8f4b9f7a..8c28825fe 100644 --- a/src/core2/bs/rebound.c +++ b/src/core2/bs/rebound.c @@ -4,7 +4,6 @@ #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" extern f32 func_80296548(void); extern f32 func_8029653C(void); @@ -28,7 +27,7 @@ void func_802B35DC(void) { void func_802B360C(void) { f32 sp44[3]; f32 sp38[3]; - f32 player_position[3]; + f32 sp2C[3]; f32 sp28; f32 sp24; f32 sp20; @@ -36,16 +35,16 @@ void func_802B360C(void) { sp1C = func_80296560(); func_80294980(sp38); - playerPosition_get(player_position); - func_80257F18(sp38, player_position, &sp28); + _player_getPosition(sp2C); + func_80257F18(sp38, sp2C, &sp28); if ((sp1C == 0xE) || (sp1C == 0x10)) { func_802B35D0(1); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_UNK1); + func_8029C7F4(1, 1, 2, BA_PHYSICS_UNK1); yaw_setIdeal(mlNormalizeAngle(sp28)); baphysics_set_gravity(func_80296548()); sp20 = func_8029653C(); - sp24 = func_8029B56C(player_position[1], sp38[1], sp20, baphysics_get_gravity()); - ml_vec3f_diff_copy(sp44, sp38, player_position); + sp24 = func_8029B56C(sp2C[1], sp38[1], sp20, baphysics_get_gravity()); + ml_vec3f_diff_copy(sp44, sp38, sp2C); D_8037D504 = sp24; sp44[0] /= sp24; sp44[1] /= sp24; @@ -62,7 +61,7 @@ void func_802B360C(void) { baphysics_set_horizontal_velocity(sp28, baphysics_get_target_horizontal_velocity()); baphysics_set_vertical_velocity(barebound_get_vertical_velocity()); baphysics_set_gravity(barebound_get_gravity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1, 1, 2, BA_PHYSICS_LOCKED_ROTATION); if (barebound_802987B4() == 2) { baphysics_set_type(BA_PHYSICS_AIRBORN); } @@ -86,7 +85,7 @@ void func_802B37DC(void) { } } -void rebound_init(void) { +void func_802B3868(void) { AnimCtrl *anim_ctrl; f32 sp20; @@ -110,7 +109,7 @@ void rebound_init(void) { } -void rebound_update(void) { +void func_802B3954(void) { s32 next_state; AnimCtrl *anim_ctrl; @@ -133,7 +132,7 @@ void rebound_update(void) { } -void rebound_end(void) { +void func_802B3A20(void) { func_802B35DC(); baphysics_reset_gravity(); baMarker_collisionOn(); diff --git a/src/core2/bs/rest.c b/src/core2/bs/rest.c index b811abb7d..7d625bf87 100644 --- a/src/core2/bs/rest.c +++ b/src/core2/bs/rest.c @@ -3,7 +3,6 @@ #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" void func_802B3A50(void) { f32 sp34; @@ -11,7 +10,7 @@ void func_802B3A50(void) { f32 sp1C[3]; if (balookat_getState()) { - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); if (balookat_try_get_position(sp1C) && func_80257F18(plyr_pos, sp1C, &sp34)) { yaw_setIdeal(sp34); } @@ -23,7 +22,7 @@ void func_802B3AAC(enum asset_e anim_id, f32 anim_duration) { anim_ctrl = baanim_getAnimCtrlPtr(); if (anim_id == ASSET_14A_ANIM_BSREST_LISTEN) { - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); switch (anctrl_getIndex(baanim_getAnimCtrlPtr())) { case ASSET_14A_ANIM_BSREST_LISTEN: baanim_playForDuration_loopSmooth(anim_id, anim_duration); @@ -35,14 +34,14 @@ void func_802B3AAC(enum asset_e anim_id, f32 anim_duration) { anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); break; default: - baanim_playForDuration_onceSmooth(ASSET_167_ANIM_BSREST_MOVE, 0.5f); + baanim_playForDuration_once(ASSET_167_ANIM_BSREST_MOVE, 0.5f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_ONCE); break; } } else { baanim_playForDuration_loopSmooth(anim_id, anim_duration); } - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802B3A50(); } @@ -86,10 +85,10 @@ bool func_802B3BB0(void) { } void func_802B3CCC(void){ - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); } -void bsrest_bs73unknown_init(void){ +void func_802B3CEC(void){ enum asset_e anim_id; f32 anim_duration; @@ -97,7 +96,7 @@ void bsrest_bs73unknown_init(void){ func_802B3AAC(anim_id, anim_duration); } -void bsrest_bs73unknown_update(void) { +void func_802B3D1C(void) { enum bs_e next_state; next_state = 0; @@ -110,11 +109,11 @@ void bsrest_bs73unknown_update(void) { bs_setState(next_state); } -void bsrest_bs73unknown_end(void){ +void func_802B3D6C(void){ func_802B3CCC(); } -void bsrest_bs75unknown_init(void){ +void func_802B3D8C(void){ enum asset_e anim_id; f32 anim_duration; @@ -123,7 +122,7 @@ void bsrest_bs75unknown_init(void){ } -void bsrest_bs75unknown_update(void) { +void func_802B3DBC(void) { enum bs_e next_state; next_state = 0; @@ -137,11 +136,11 @@ void bsrest_bs75unknown_update(void) { } -void bsrest_bs75unknown_end(void){ +void func_802B3E0C(void){ func_802B3CCC(); } -void bsrest_bs74unknown_init(void){ +void func_802B3E2C(void){ enum asset_e anim_id; f32 anim_duration; @@ -150,7 +149,7 @@ void bsrest_bs74unknown_init(void){ func_8029C674(); } -void bsrest_bs74unknown_update(void) { +void func_802B3E64(void) { s32 next_state; next_state = 0; @@ -168,7 +167,7 @@ void bsrest_bs74unknown_update(void) { } -void bsrest_bs74unknown_end(void){ +void func_802B3EF4(void){ func_802B3CCC(); func_8029C748(); } diff --git a/src/core2/bs/drone.c b/src/core2/bs/scripted.c similarity index 97% rename from src/core2/bs/drone.c rename to src/core2/bs/scripted.c index 9e774c2cb..6a683962a 100644 --- a/src/core2/bs/drone.c +++ b/src/core2/bs/scripted.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/drone.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/bs/droneenter.c b/src/core2/bs/scripted_enter.c similarity index 97% rename from src/core2/bs/droneenter.c rename to src/core2/bs/scripted_enter.c index f95220d91..e25767d92 100644 --- a/src/core2/bs/droneenter.c +++ b/src/core2/bs/scripted_enter.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/droneenter.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" enum bsdroneenter_state_e{ @@ -113,7 +111,7 @@ void bsDroneEnter_init(void) { func_8029BCF8(&anim_id, &anim_duration); baanim_playForDuration_loopSmooth(anim_id, anim_duration); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); func_80294378(6); __bsDroneEnter_init(); bsDroneEnterSubstate = BSDRONEENTER_SUBSTATE_0_UNINITIALIZED; diff --git a/src/core2/bs/dronegoto.c b/src/core2/bs/scripted_goto.c similarity index 94% rename from src/core2/bs/dronegoto.c rename to src/core2/bs/scripted_goto.c index 2b2befb88..7d69723e7 100644 --- a/src/core2/bs/dronegoto.c +++ b/src/core2/bs/scripted_goto.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/dronegoto.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .bss */ @@ -57,7 +55,7 @@ void func_802AEC78(void){ badrone_get_position_and_duration(target_position, &duration_s); baphysics_set_goto_position(target_position); baphysics_set_goto_duration(duration_s); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_GOTO); + func_8029C7F4(1,1,3,BA_PHYSICS_GOTO); func_8029436C(1); D_8037D441 = 0; } diff --git a/src/core2/bs/dronelook.c b/src/core2/bs/scripted_look.c similarity index 84% rename from src/core2/bs/dronelook.c rename to src/core2/bs/scripted_look.c index 61ca4e3d5..799fb2671 100644 --- a/src/core2/bs/dronelook.c +++ b/src/core2/bs/scripted_look.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/dronelook.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "port/Controller/ModernCamera.h" -#include "core2/yaw.h" extern f32 bastick_getX(void); @@ -22,17 +20,17 @@ void bsDroneLook_init(void) { basfx_80299D2C(SFX_12D_CAMERA_ZOOM_CLOSEST, 1.2f, 12000); func_8029BCF8(&anim_id, &anim_duration); baanim_playForDuration_loopSmooth(anim_id, anim_duration); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); baphysics_set_velocity(0); ncDynamicCamera_enterFirstPerson(); __bsDroneLook_getEyePos(eye_position); - ncba1p_setZoomedOutPosition(eye_position); + ncFirstPersonCamera_setZoomedOutPosition(eye_position); player_getRotation(eye_rotation); eye_rotation[0] = 0.0f; eye_rotation[1] += 180.0f; eye_rotation[2] = 0.0f; - ncba1p_setZoomedOutRotation(eye_rotation); + ncFirstPersonCamera_setZoomedOutRotation(eye_rotation); baflag_set(BA_FLAG_17_FIRST_PERSON_VIEW); } @@ -45,14 +43,14 @@ void bsDroneLook_update(void) { next_state = 0; dt = time_getDelta(); - if (ncba1p_getState() == FIRSTPERSON_STATE_2_IDLE) { + if (ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_2_IDLE) { //camera is in "idle" state - ncba1p_getZoomedInRotation(eye_rotation); + ncFirstPersonCamera_getZoomedInRotation(eye_rotation); eye_rotation[0] -= bastick_getY() * 90.0f * dt * port_cameraInvertYSign(); eye_rotation[1] -= bastick_getX() * 90.0f * dt * port_cameraInvertXSign(); eye_rotation[2] = 0.0f; eye_rotation[0] = (eye_rotation[0] > 180.0f) ? ml_max_f(305.0f, eye_rotation[0]) : ml_min_f(70.0f, eye_rotation[0]); - ncba1p_setZoomedOutRotation(eye_rotation); + ncFirstPersonCamera_setZoomedOutRotation(eye_rotation); yaw_setIdeal(eye_rotation[1] + 180.0f); exit_first_person = false; @@ -73,7 +71,7 @@ void bsDroneLook_update(void) { } } __bsDroneLook_getEyePos(eye_position); - ncba1p_setZoomedOutPosition(eye_position); + ncFirstPersonCamera_setZoomedOutPosition(eye_position); bs_setState(next_state); } diff --git a/src/core2/bs/dronexform.c b/src/core2/bs/scripted_transform.c similarity index 91% rename from src/core2/bs/dronexform.c rename to src/core2/bs/scripted_transform.c index 915cc28da..adc06db19 100644 --- a/src/core2/bs/dronexform.c +++ b/src/core2/bs/scripted_transform.c @@ -1,14 +1,12 @@ -// BanjoDecomp: core2/bs/dronexform.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" -extern void playerPosition_setY(f32); +extern void player_setYPosition(f32); extern void yaw_applyIdeal(void); extern f32 cosf(f32); @@ -58,28 +56,28 @@ void func_802AF900(void){ f32 sp44; f32 sp40; f32 sp3C; - f32 player_position[3]; + f32 sp30[3]; - player_getPosition(player_position); + player_getPosition(sp30); sp3C = D_8037D470.unk8; sp48 = func_80257A44(sp3C, 0.38f); sp4C = sp48 * 6.283185308; sp40 = sinf(sp4C); sp44 = cosf(sp4C); - player_position[0] += sp40 * D_8037D470.unk18; - player_position[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 0.0f, 130.0f); - player_position[2] += sp44 * D_8037D470.unk18; + sp30[0] += sp40 * D_8037D470.unk18; + sp30[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 0.0f, 130.0f); + sp30[2] += sp44 * D_8037D470.unk18; func_802AF88C(D_8037D470.unk4, sp40, sp44); - particleEmitter_setPosition(D_8037D470.unk4, player_position); + particleEmitter_setPosition(D_8037D470.unk4, sp30); particleEmitter_emitN(D_8037D470.unk4, 1); - player_getPosition(player_position); + player_getPosition(sp30); sp4C = (1.0 - ml_remainder_f(sp48 + 0.5, 1.0f))* 6.283185308; - player_position[0] -= sinf(sp4C) * D_8037D470.unk18; - player_position[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 130.0f, 0.0f); - player_position[2] -= cosf(sp4C) * D_8037D470.unk18; + sp30[0] -= sinf(sp4C) * D_8037D470.unk18; + sp30[1] += ml_interpolate_f(func_80257A44(sp3C, 1.14f), 130.0f, 0.0f); + sp30[2] -= cosf(sp4C) * D_8037D470.unk18; func_802AF88C(D_8037D470.unk0, sp40, sp44); - particleEmitter_setPosition(D_8037D470.unk0, player_position); + particleEmitter_setPosition(D_8037D470.unk0, sp30); particleEmitter_emitN(D_8037D470.unk0, 1); } @@ -251,13 +249,13 @@ void func_802B01C8(void){ static void __bsdronexform_setState(int next_state){ enum asset_e sp34; f32 sp30; - f32 player_position[3]; + f32 sp24[3]; D_8037D470.state = next_state; switch(next_state){ case 1:// 802B0230 D_8037D470.unk1C = 1; - D_8037D470.unk2C = playerPosition_getY(); + D_8037D470.unk2C = player_getYPosition(); func_802AFB94(0.28f); func_802AFBA0(180.0f); func_802AFBAC(0.04f); @@ -281,10 +279,10 @@ static void __bsdronexform_setState(int next_state){ break; case 5:// 802B02F4 - playerPosition_get(player_position); - player_position[1] += 30.0f; - viewport_adjustPointDistance(player_position, 80.0f); - func_802AFBB8(player_position); + _player_getPosition(sp24); + sp24[1] += 30.0f; + viewport_adjustPointDistance(sp24, 80.0f); + func_802AFBB8(sp24); batimer_set(0, 0.1f); break; @@ -326,7 +324,7 @@ void bsdronexform_init(void){ enum asset_e sp18; func_8029BCAC(&sp18, &sp1C); baanim_playForDuration_loopSmooth(sp18, sp1C); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + func_8029C7F4(1,1,3, BA_PHYSICS_FREEZE); baphysics_set_velocity(0); baphysics_set_target_velocity(0); pitch_setIdeal(0.0f); @@ -354,7 +352,7 @@ void bsdronexform_update(void){ switch(D_8037D470.state){ case 1: sp24 = batimer_decrement(0); - playerPosition_setY(func_802B051C(0, 2.8f, 0.0f, 90.0f) + D_8037D470.unk2C); + player_setYPosition(func_802B051C(0, 2.8f, 0.0f, 90.0f) + D_8037D470.unk2C); func_802AFB94(func_802B051C(0, 2.8f, 0.28f, 1.0f)); func_802AFBA0(func_802B051C(0, 2.8f, 180.0f, 55.0f)); func_802AFBAC(func_802B051C(0, 2.8f, 0.04f, 0.35f)); @@ -430,7 +428,7 @@ void bsdronexform_update(void){ case 9: sp24 = batimer_decrement(0); - playerPosition_setY(func_802B051C(0, 0.7f, 90.0f, 0.0f) + D_8037D470.unk2C); + player_setYPosition(func_802B051C(0, 0.7f, 90.0f, 0.0f) + D_8037D470.unk2C); if(sp24) bs_setState(bs_getIdleState()); break; diff --git a/src/core2/bs/dronevanish.c b/src/core2/bs/scripted_vanish.c similarity index 96% rename from src/core2/bs/dronevanish.c rename to src/core2/bs/scripted_vanish.c index 5647470e6..db3ba567d 100644 --- a/src/core2/bs/dronevanish.c +++ b/src/core2/bs/scripted_vanish.c @@ -1,11 +1,9 @@ -// BanjoDecomp: core2/bs/dronevanish.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" /* .bss */ struct { @@ -99,7 +97,7 @@ void bsDroneVanish_init(void){ func_8029BCF8(&anim_id, &anim_duration); baanim_playForDuration_loopSmooth(anim_id, anim_duration); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + func_8029C7F4(1,1,3, BA_PHYSICS_FREEZE); func_80294378(6); __bsDroneVanish_init(); D_8037D468 = 0; diff --git a/src/core2/bs/bShock.c b/src/core2/bs/shock_spring.c similarity index 86% rename from src/core2/bs/bShock.c rename to src/core2/bs/shock_spring.c index ce8347a83..77046f033 100644 --- a/src/core2/bs/bShock.c +++ b/src/core2/bs/shock_spring.c @@ -1,10 +1,8 @@ -// BanjoDecomp: core2/bs/bShock.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .data */ const f32 D_80364A70 = 1250.0f; @@ -25,7 +23,7 @@ void bsbshock_charge_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.1061f); anctrl_setPlaybackType(aCtrl,1); anctrl_start(aCtrl, "bsbshock.c", 0x61); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -33,8 +31,8 @@ void bsbshock_charge_init(void){ baphysics_set_target_yaw(yaw_getIdeal()); func_802B6FA8(); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - modelAppendages_setKazooiesFeetAndShoesVisibility(true); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E064(1); + func_8029E070(1); basfx_80299BD4(); D_8037D382 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(D_8037D382, SFX_2C_PULLING_NOISE); @@ -98,13 +96,13 @@ void bsbshock_charge_update(void){ } else{//L802A6D18 if(bainput_should_feathery_flap()) - sp2C = BS_10_BFLAP; + sp2C = BS_BFLAP; if(bainput_should_beak_bust()) sp2C = BS_F_BBUSTER; }//L802A6D44 if(anctrl_isAt( aCtrl, 0.3637f) && D_8037D380) - sp2C = BS_22_BSHOCK_JUMP; + sp2C = BS_BSHOCK_JUMP; if(anctrl_isAt(aCtrl, 0.5551f)){ baphysics_set_vertical_velocity(180.0f); @@ -119,8 +117,8 @@ void bsbshock_charge_update(void){ void bsbshock_charge_end(void){ sfxsource_freeSfxsourceByIndex(D_8037D382); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E064(0); + func_8029E070(0); if(baModel_80292230() != 0.0f){ baModel_80292158(0.0f); playerPosition_addY(50.0f); @@ -137,7 +135,7 @@ void bsbshock_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 1.0f); anctrl_setPlaybackType(aCtrl,1); anctrl_start(aCtrl, "bsbshock.c", 0x13a); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -148,8 +146,8 @@ void bsbshock_init(void){ baphysics_set_vertical_velocity(D_80364A70); baphysics_set_gravity(D_80364A74); sfxsource_playHighPriority(SFX_E_SHOCKSPRING_BOING); - modelAppendages_setKazooiesFeetAndShoesVisibility(true); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E064(1); + func_8029E070(1); ability_use(9); baModel_80292158(-50.0f); playerPosition_addY(-50.0f); @@ -180,7 +178,7 @@ void bsbshock_update(void){ sp2C = BS_3D_FALL_TUMBLING; if(bainput_should_feathery_flap()) - sp2C = BS_10_BFLAP; + sp2C = BS_BFLAP; if(bainput_should_beak_bust()) sp2C =BS_F_BBUSTER; @@ -193,8 +191,8 @@ void bsbshock_end(void){ if(bs_getNextState() != BS_11_BPECK) baphysics_reset_gravity(); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E064(0); + func_8029E070(0); baModel_80292158(0.0f); playerPosition_addY(50.0f); } diff --git a/src/core2/bs/sled.c b/src/core2/bs/sled.c index eaa653542..9d8a8ac92 100644 --- a/src/core2/bs/sled.c +++ b/src/core2/bs/sled.c @@ -2,7 +2,6 @@ #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" extern ActorMarker *func_80296554(void); @@ -30,7 +29,7 @@ void __bssled_unlinkSledMarker(void){ void bssled_init(void){ __bssled_linkSledMarker(); baanim_playForDuration_loopSmooth(ASSET_228_ANIM_BANJO_SLED, 1.8f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); baphysics_set_target_horizontal_velocity(0.0f); func_80294A8C(0); func_80294378(6); diff --git a/src/core2/bs/slide.c b/src/core2/bs/slide.c index 1cd561ef8..3c2a75be5 100644 --- a/src/core2/bs/slide.c +++ b/src/core2/bs/slide.c @@ -3,7 +3,6 @@ #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .bss */ s32 D_8037D520; @@ -16,7 +15,7 @@ void func_802B40D0(void){ f32 sp2C[3]; f32 sp28; - playerPosition_get(sp38); + _player_getPosition(sp38); sp38[1] += 20.0f; D_8037D524++; if(!(D_8037D524 < 3)) @@ -69,7 +68,7 @@ void bsslide_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_setDuration(aCtrl, 1.0f); anctrl_start(aCtrl, "bsslide.c", 0x7f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_horizontal_velocity(yaw_getIdeal() ,baphysics_get_target_horizontal_velocity()); pitch_setAngVel(800.0f, 8.0f); diff --git a/src/core2/bs/splat.c b/src/core2/bs/splat.c index 0ec89715c..eb3ec99ed 100644 --- a/src/core2/bs/splat.c +++ b/src/core2/bs/splat.c @@ -4,7 +4,6 @@ #include "bsint.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" void func_80292900(f32, f32); void baMotor_80250D94(f32, f32, f32); @@ -23,8 +22,8 @@ void func_802B4570(void) { void bssplat_init(void){ s32 sp1C; - baanim_playForDuration_once(ASSET_149_ANIM_BSSPLAT, 1.1f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + baanim_playForDuration_onceSmooth(ASSET_149_ANIM_BSSPLAT, 1.1f); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); bafalldamage_get_damage(&sp1C); item_adjustByDiffWithHud(ITEM_14_HEALTH, -sp1C); if(func_8029CEB0() == 4){ @@ -60,7 +59,7 @@ void bssplat_update(void){ sp1C = BS_2F_FALL; if(anctrl_isStopped(aCtrl)){ - baanim_playForDuration_onceSmooth(ASSET_D2_ANIM_BSSPLAT, 2.25f); + baanim_playForDuration_once(ASSET_D2_ANIM_BSSPLAT, 2.25f); D_8037D530 = 1; } break; diff --git a/src/core2/bs/stand.c b/src/core2/bs/stand.c index d049e10fa..1626eb750 100644 --- a/src/core2/bs/stand.c +++ b/src/core2/bs/stand.c @@ -4,7 +4,6 @@ #include "bsint.h" #include "core2/statetimer.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" extern f32 bastick_distance(void); void yaw_setVelocityBounded(f32, f32); @@ -53,23 +52,23 @@ s32 func_802B488C(s32 arg0){ s32 retVal = arg0; switch(bastick_getZone()){ case 1: //L802B48CC - retVal = BS_1F_WALK_CREEP; + retVal = BS_WALK_CREEP; break; case 2: //L802B48D4 retVal = BS_2_WALK_SLOW; break; case 3: //L802B48D4 - retVal = BS_3_WALK; + retVal = BS_WALK; break; case 4: //L802B48D4 retVal = BS_4_WALK_FAST; break; } if(bakey_held(BUTTON_Z)) - retVal = BS_7_CROUCH; + retVal = BS_CROUCH; if(bakey_pressed(BUTTON_B) && can_claw()) - retVal = BS_6_CLAW; + retVal = BS_CLAW; if(bakey_pressed(BUTTON_A)) retVal = bs_getTypeOfJump(); @@ -78,7 +77,7 @@ s32 func_802B488C(s32 arg0){ retVal = badrone_look(); if(player_isSliding()) - retVal = BS_32_SLIDE; + retVal = BS_SLIDE; retVal = func_8029CA94(retVal); @@ -90,10 +89,10 @@ s32 func_802B488C(s32 arg0){ void bsstand_init(void){ if(bsclimb_inSet(bs_getPrevState())) - climb_release(); + climbRelease(); - baanim_playForDuration_onceSmooth(ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + baanim_playForDuration_once(ASSET_6F_ANIM_BSSTAND_IDLE, 5.5f); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802900B4(); D_8037D540 = 0; @@ -206,12 +205,12 @@ void bsstand_update(void) { if (sp18 & 8) { if (sp18 & 4) { if (anctrl_isAt(anim_ctrl, 0.0909f)) basfx_80299BD4(); - if (anctrl_isAt(anim_ctrl, 0.0909f)) modelAppendages_setKazooiesUpperHalfVisibility(true); - if (anctrl_isAt(anim_ctrl, 0.6818f)) modelAppendages_setKazooiesUpperHalfVisibility(false); + if (anctrl_isAt(anim_ctrl, 0.0909f)) func_8029E070(1); + if (anctrl_isAt(anim_ctrl, 0.6818f)) func_8029E070(0); }//L802B4E70 if (sp18 & 2) { - if (anctrl_isAt(anim_ctrl, 0.7727f)) modelAppendages_setKazooiesUpperHalfVisibility(true); - if (anctrl_isAt(anim_ctrl, 0.9999f)) modelAppendages_setKazooiesUpperHalfVisibility(false); + if (anctrl_isAt(anim_ctrl, 0.7727f)) func_8029E070(1); + if (anctrl_isAt(anim_ctrl, 0.9999f)) func_8029E070(0); }//L802B50E4 } else if (sp18 & 0x20) { if (anctrl_getIndex(anim_ctrl) == ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK) { @@ -243,13 +242,13 @@ void bsstand_update(void) { D_8037D540 = func_802B4870(D_8037D540); sp18 = D_80364D20[D_8037D540]; if (sp18 & 0x10) { - baanim_playForDuration_onceSmooth(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); + baanim_playForDuration_once(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); anctrl_start(anim_ctrl, "bsstand.c", 0x1AB); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); func_802900FC(); } else if (sp18 & 0x20) { - baanim_playForDuration_onceSmooth(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + baanim_playForDuration_once(ASSET_95_ANIM_BSSTAND_KAZOOIE_PECK, 5.5f); + func_8029E070(1); func_802900FC(); } else if (sp18 & 8) { if (anctrl_getIndex(anim_ctrl) == ASSET_6F_ANIM_BSSTAND_IDLE) { @@ -264,7 +263,7 @@ void bsstand_update(void) { anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_setStart(anim_ctrl, sp1C); anctrl_start(anim_ctrl, "bsstand.c", 0x1C3); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); } } if (player_shouldFall() != 0) { @@ -274,14 +273,14 @@ void bsstand_update(void) { } void bsstand_end(void){ - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); func_802900FC(); baeyes_open(); } //bsStand_Land_init void bsstand_landing_init(void){ - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); } @@ -310,11 +309,11 @@ void bsstand_landing_update(void){ ///BREAK??? void func_802B5350(void){ - s32 interrupt_type = bs_getInterruptType(); - if(interrupt_type == BS_INTR_D_SURF){ + s32 sp1C = bs_getInterruptType(); + if(sp1C == BS_INTR_D_SURF){ bs_setState(0x52); } - if(interrupt_type == BS_INTR_7){ + if(sp1C == 0x7){ if(bsStoredState_getTransformation() != TRANSFORM_1_BANJO) bs_setInterruptResponse(1); else{ @@ -322,14 +321,14 @@ void func_802B5350(void){ bs_setState(BS_3A_CARRY_IDLE); } } - else if(interrupt_type == BS_INTR_12){//L802B53D0 + else if(sp1C == 0x12){//L802B53D0 bs_setInterruptResponse(1); if( bsStoredState_getTransformation() == TRANSFORM_1_BANJO && !baflag_isTrue(BA_FLAG_F) && stateTimer_isDone(STATE_TIMER_0_UNKNOWN)){ bacarriedobj_spawn(baMarker_getCarriedObjectActorId()); bs_setInterruptResponse(2); } } - else if(interrupt_type == BS_INTR_8){//L802B5438 + else if(sp1C == 0x8){//L802B5438 bs_setInterruptResponse(2); bs_setState(BS_3C_TALK); }else{ diff --git a/src/core2/bs/bLongLeg.c b/src/core2/bs/stilt_stride.c similarity index 88% rename from src/core2/bs/bLongLeg.c rename to src/core2/bs/stilt_stride.c index 343d1d763..7972e2774 100644 --- a/src/core2/bs/bLongLeg.c +++ b/src/core2/bs/stilt_stride.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/bLongLeg.c #include #include "functions.h" #include "variables.h" @@ -7,7 +6,6 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" /* .data */ @@ -50,10 +48,10 @@ void func_802A524C(void){ int bslongleg_inSet(s32 move_indx){ return (move_indx == BS_26_LONGLEG_IDLE) - || (move_indx == BS_27_LONGLEG_WALK) - || (move_indx == BS_28_LONGLEG_JUMP) - || (move_indx == BS_29_LONGLEG_EXIT) - || (move_indx == BS_55_LONGLEG_SLIDE) + || (move_indx == BS_LONGLEG_WALK) + || (move_indx == BS_LONGLEG_JUMP) + || (move_indx == BS_LONGLEG_EXIT) + || (move_indx == BS_LONGLEG_SLIDE) || (move_indx == BS_9B_LONGLEG_DRONE) || (move_indx == BS_62_LONGLEG_LOCKED); } @@ -68,9 +66,9 @@ void func_802A5374(void){ baModel_80292078(1, -50.0f); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); - modelAppendages_setKazooiesFeetAndShoesVisibility(true); - modelAppendages_setWadingBootsVisibility(true); + func_8029E070(1); + func_8029E064(1); + func_8029E0F4(1); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baflag_set(BA_FLAG_3); @@ -82,9 +80,9 @@ void func_802A5404(void){ baModel_80292078(1,0); bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); - modelAppendages_setWadingBootsVisibility(false); + func_8029E070(0); + func_8029E064(0); + func_8029E0F4(0); baModel_setDirection(PLAYER_MODEL_DIR_BANJO); pitch_setIdeal(0.0f); roll_setIdeal(0.0f); @@ -129,7 +127,7 @@ void bsblongleg_enter_init(void){ __bsblongleg_enterFromTrot(); else __bsblongleg_enter(); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A5374(); basfx_80299BD4(); @@ -160,7 +158,7 @@ void bsblongleg_enter_end(void){ void bsblongleg_stand_enter(void){ baanim_playForDuration_loopSmooth(ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); baModel_setDirection(PLAYER_MODEL_DIR_KAZOOIE); func_802A5374(); @@ -177,16 +175,16 @@ void bsblongleg_stand_update(void){ stateTimer_clear(STATE_TIMER_2_LONGLEG); if(bastick_getZone() > 0) - next_state = BS_27_LONGLEG_WALK; + next_state = BS_LONGLEG_WALK; if(player_shouldSlideTrot()) - next_state = BS_55_LONGLEG_SLIDE; + next_state = BS_LONGLEG_SLIDE; if(bakey_pressed(BUTTON_A) && player_isStable()) - next_state = BS_28_LONGLEG_JUMP; + next_state = BS_LONGLEG_JUMP; if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - next_state = BS_29_LONGLEG_EXIT; + next_state = BS_LONGLEG_EXIT; if(func_802A51D0()) next_state = BS_4C_LANDING_IN_WATER; @@ -206,7 +204,7 @@ void bsblongleg_walk_init(void){ anctrl_setIndex(aCtrl, ASSET_42_ANIM_BSLONGLEG_WALK); anctrl_setPlaybackType(aCtrl, ANIMCTRL_LOOP); anctrl_start(aCtrl, "bsblongleg.c", 0x1a1); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364A40, D_80364A44, D_80364A48, D_80364A4C); } @@ -231,13 +229,13 @@ void bsblongleg_walk_update(void){ next_state = BS_26_LONGLEG_IDLE; if(player_shouldSlideTrot()) - next_state = BS_55_LONGLEG_SLIDE; + next_state = BS_LONGLEG_SLIDE; if(bakey_pressed(BUTTON_A) && player_isStable()) - next_state = BS_28_LONGLEG_JUMP; + next_state = BS_LONGLEG_JUMP; if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - next_state = BS_29_LONGLEG_EXIT; + next_state = BS_LONGLEG_EXIT; if(func_802A51D0()) next_state = BS_4C_LANDING_IN_WATER; @@ -326,7 +324,7 @@ void bsblongleg_jump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.42f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsblongleg.c", 0x27F); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -350,7 +348,7 @@ void bsblongleg_jump_update(void){ if(bakey_released(BUTTON_A) && 0.0f < sp34[1]) baphysics_reset_gravity(); - sp30 = playerPosition_getY() - func_80294438(); + sp30 = player_getYPosition() - func_80294438(); switch(D_8037D360){ case 0://L802A5F24 if((sp34[1] < 100.0f) || sp30 < 10.0f) @@ -388,10 +386,10 @@ void bsblongleg_jump_update(void){ sp44 = BS_26_LONGLEG_IDLE; if(bakey_pressed(BUTTON_A)) - sp44 = BS_28_LONGLEG_JUMP; + sp44 = BS_LONGLEG_JUMP; if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - sp44 = BS_29_LONGLEG_EXIT; + sp44 = BS_LONGLEG_EXIT; break; }//L802A60F0 @@ -416,11 +414,11 @@ void bsblongleg_slide_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_setStart(aCtrl, 0.0865f); anctrl_start(aCtrl, "bsblongleg.c", 0x339); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - modelAppendages_setKazooiesUpperHalfVisibility(true); - modelAppendages_setKazooiesFeetAndShoesVisibility(true); + func_8029E070(1); + func_8029E064(1); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baphysics_set_target_horizontal_velocity(0.0f); @@ -449,7 +447,7 @@ void bsblongleg_slide_update(void){ } if(D_8037D358 == 0.0f && bakey_pressed(BUTTON_A)) - sp3C = BS_28_LONGLEG_JUMP; + sp3C = BS_LONGLEG_JUMP; if(func_802A51D0()) sp3C = BS_4C_LANDING_IN_WATER; @@ -465,16 +463,16 @@ void func_802A6388(f32 arg0){ D_8037D35C = arg0; } -void bsblongleg_locked_init(void){ +void func_802A6394(void){ baanim_playForDuration_loopSmooth(ASSET_41_ANIM_BSLONGLEG_IDLE, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A5374(); baModel_setDirection(PLAYER_MODEL_DIR_KAZOOIE); func_8029C674(); } -void bsblongleg_locked_update(void){ +void func_802A63F0(void){ enum bs_e next_state = 0; func_802A531C(); func_8029C6D0(); @@ -489,7 +487,7 @@ void bsblongleg_locked_update(void){ bs_setState(next_state); } -void bsblongleg_locked_end(void){ +void func_802A6450(void){ func_8029C748(); func_802A5404(); } @@ -503,7 +501,7 @@ void bsblongleg_drone_update(void){ func_802A531C(); bsdrone_update(); if(stateTimer_isDone(STATE_TIMER_2_LONGLEG)) - bs_setState(BS_29_LONGLEG_EXIT); + bs_setState(BS_LONGLEG_EXIT); } void bsblongleg_drone_end(void){ diff --git a/src/core2/bs/surf.c b/src/core2/bs/surf.c index 89d803f76..6ad84a30b 100644 --- a/src/core2/bs/surf.c +++ b/src/core2/bs/surf.c @@ -3,13 +3,12 @@ #include "variables.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" /* .bss */ s32 D_8037D560; /* .code */ -void bssurf_init(void) { +void func_802B5FD0(void) { AnimCtrl *anim_ctrl; anim_ctrl = baanim_getAnimCtrlPtr(); @@ -18,12 +17,12 @@ void bssurf_init(void) { anctrl_setDuration(anim_ctrl, 1.8f); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bssurf.c", 0x33); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); D_8037D560 = 1; } -void bssurf_update(void) { +void func_802B6064(void) { enum bs_e next_state; next_state = 0; @@ -35,12 +34,12 @@ void bssurf_update(void) { } D_8037D560 = 0; if (baflag_isTrue(BA_FLAG_6)) { - next_state = BS_53_TIMEOUT_BANJO; + next_state = BS_53_TIMEOUT; } bs_setState(next_state); } -void bssurf_end(void){} +void func_802B60D0(void){} void func_802B60D8(void) { if (bs_getInterruptType() == BS_INTR_D_SURF) { diff --git a/src/core2/bs/swim.c b/src/core2/bs/swim.c index e6e4d77a7..a96668f62 100644 --- a/src/core2/bs/swim.c +++ b/src/core2/bs/swim.c @@ -4,7 +4,6 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" extern void bainput_setDiveCooldown(s32, f32); @@ -74,7 +73,7 @@ void __bsswim_updateVelocity(void) { baphysics_set_target_horizontal_velocity(ml_interpolate_f(sp1C, bsSwimHorzVelocityMin, bsSwimHorzVelocityMax)); } -void __bsswim_enteredWater(void) { +void swim_enteredWater(void) { if (level_get() == LEVEL_9_RUSTY_BUCKET_BAY) { progressDialog_showDialogMaskZero(FILEPROG_AB_SWIM_OILY_WATER); } else if (gsworld_getMap() == MAP_46_CCW_WINTER) { @@ -140,10 +139,10 @@ void bsswim_idle_init(void) { anctrl_setDuration(anim_ctrl, 1.2f); anctrl_start(anim_ctrl, "bsswim.c", 0xFD); } - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 3, 3, BA_PHYSICS_NORMAL); yaw_setVelocityBounded(500.0f, 5.0f); baphysics_set_target_horizontal_velocity(0.0f); - __bsswim_enteredWater(); + swim_enteredWater(); bsSwimCurrentAnimation = 0; } @@ -181,7 +180,7 @@ void bsswim_idle_update(void) { next_state = BS_5_JUMP; } if (baflag_isTrue(BA_FLAG_6) || baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)) { - next_state = BS_D_TIMEOUT_TRANSFORMATION; + next_state = BS_D_TIMEOUT; } bs_setState(next_state); } @@ -246,7 +245,7 @@ void bsswim_swim_update(void) { if ((func_80294530() != 0) && (can_dive() != 0)) { func_802944D0(sp1C); if (sp1C[1] < -0.7) { - if ((floor_getCurrentFloorYPosition() - playerPosition_getY()) > 90.0f) { + if ((floor_getCurrentFloorYPosition() - player_getYPosition()) > 90.0f) { next_state = BS_30_DIVE_ENTER; } } @@ -258,7 +257,7 @@ void bsswim_swim_update(void) { next_state = BS_5_JUMP; } if (baflag_isTrue(BA_FLAG_6) || baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE)) { - next_state = BS_D_TIMEOUT_TRANSFORMATION; + next_state = BS_D_TIMEOUT; } bs_setState(next_state); } @@ -267,13 +266,13 @@ void bsswim_swim_end(void){ __bsswim_end(); } -void __bsswim_update_rotation(void) { +void __bsswim_enteredWater(void) { f32 sp34; f32 plyr_pos[3]; f32 sp1C[3]; if (balookat_getState() != 0) { - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); if (balookat_try_get_position(sp1C) && func_80257F18(plyr_pos, sp1C, &sp34)) { yaw_setIdeal(sp34); } @@ -282,11 +281,11 @@ void __bsswim_update_rotation(void) { void bsswim_lookat_init(void) { baanim_playForDuration_loopSmooth(0x57, 1.2f); - code_14420_setUpdateTypes(1, YAW_STATE_3_BOUNDED, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1, 3, 3, BA_PHYSICS_NORMAL); yaw_setVelocityBounded(500.0f, 5.0f); baphysics_set_target_horizontal_velocity(0.0f); + swim_enteredWater(); __bsswim_enteredWater(); - __bsswim_update_rotation(); } void bsswim_lookat_update(void) { @@ -296,7 +295,7 @@ void bsswim_lookat_update(void) { if (balookat_getState() == 0) { next_state = BS_2D_SWIM_IDLE; } - __bsswim_update_rotation(); + __bsswim_enteredWater(); bs_setState(next_state); } @@ -305,7 +304,7 @@ void bsswim_lookat_end(void){ } void bsswim_drone_init(void){ - __bsswim_enteredWater(); + swim_enteredWater(); bsdrone_init(); } diff --git a/src/core2/bs/talk.c b/src/core2/bs/talk.c index e2c8fb195..da8ad965a 100644 --- a/src/core2/bs/talk.c +++ b/src/core2/bs/talk.c @@ -20,7 +20,7 @@ void bstalk_init(void){ func_8029C848(player_anim_ctrl); anctrl_setPlaybackType(player_anim_ctrl, ANIMCTRL_LOOP); anctrl_start(player_anim_ctrl, "bstalk.c", 0x38); - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); get_talk_target_position(target_pos); func_80257F18(plyr_pos, target_pos, &yaw); yaw_setIdeal(yaw); diff --git a/src/core2/bs/bTrot.c b/src/core2/bs/talon_trot.c similarity index 92% rename from src/core2/bs/bTrot.c rename to src/core2/bs/talon_trot.c index 59af518e6..abfc22b86 100644 --- a/src/core2/bs/bTrot.c +++ b/src/core2/bs/talon_trot.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/bs/bTrot.c #include #include "functions.h" #include "variables.h" @@ -7,7 +6,6 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/statetimer.h" -#include "core2/yaw.h" /* .data */ f32 D_80364A90 = 30.0f; @@ -104,8 +102,8 @@ void bsbtrot_walkUpdateTargetVelocity(void){ void func_802A8A40(void){ bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); - modelAppendages_setKazooiesFeetAndShoesVisibility(true); + func_8029E070(1); + func_8029E064(1); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baflag_set(BA_FLAG_3); @@ -122,14 +120,14 @@ void func_802A8AD8(void){ } if(stateTimer_isDone(STATE_TIMER_3_TURBO_TALON)){ - if(modelAppendages_hideTurboTrainers()){ - modelAppendages_setTurboTrainersVisibility(false); + if(func_8029DFE0()){ + func_8029E0DC(0); if(baflag_isFalse(BA_FLAG_14_LOSE_BOGGY_RACE)) - sfxsource_playHighPriority(SFX_3EB_UNKNOWN); + sfxsource_playHighPriority(0x3eb); func_803219F4(1); } }else{ - modelAppendages_setTurboTrainersVisibility(true); + func_8029E0DC(1); } } @@ -141,8 +139,8 @@ void func_802A8BB0(void){ baModel_setDirection(PLAYER_MODEL_DIR_BANJO); bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); + func_8029E070(0); + func_8029E064(0); pitch_setIdeal(0.0f); roll_setIdeal(0.0f); baflag_clear(BA_FLAG_3); @@ -215,8 +213,8 @@ enum bs_e func_802A8D84(enum bs_e arg0){ void bsbtrot_enter_init(void){ func_802A8AD8(); - baanim_playForDuration_once(ASSET_16_ANIM_BSBTROT_ENTER, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_NORMAL); + baanim_playForDuration_onceSmooth(ASSET_16_ANIM_BSBTROT_ENTER, 1.0f); + func_8029C7F4(1,1,2, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A8A40(); basfx_80299BD4(); @@ -245,7 +243,7 @@ void bsbtrot_enter_end(void){ void bsbtrot_stand_init(void){ baanim_playForDuration_loopSmooth(ASSET_26_ANIM_BSBTROT_IDLE, 1.2f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A8A40(); } @@ -285,7 +283,7 @@ void func_802A9054(void){ void bsbtrot_walk_init(void){ baanim_playForDuration_loopSmooth(func_802A9030(), 0.53f); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); func_802A8A40(); func_802A9054(); } @@ -482,7 +480,7 @@ void bsbtrot_jump_end(void){ } void bsbtrot_exit_init(void){ - baanim_playForDuration_once(ASSET_7_ANIM_BSBTROT_EXIT, 0.6f); + baanim_playForDuration_onceSmooth(ASSET_7_ANIM_BSBTROT_EXIT, 0.6f); baanim_setUpdateType(BAANIM_UPDATE_1_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); } @@ -507,11 +505,11 @@ void bsbtrot_slide_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bsbtrot.c", 0x382); func_802A8A40(); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,3, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_target_yaw(yaw_getIdeal()); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); - modelAppendages_setKazooiesUpperHalfVisibility(true); - modelAppendages_setKazooiesFeetAndShoesVisibility(true); + func_8029E070(1); + func_8029E064(1); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); baphysics_set_target_horizontal_velocity(0.0f); @@ -561,7 +559,7 @@ int bsbtrot_inSet(s32 move_indx){ || (move_indx == BS_45_BTROT_SLIDE) || (move_indx == BS_14_BTROT_ENTER) || (move_indx == 0x79) - || (move_indx == BS_7B_BTROT_OW) + || (move_indx == BS_BTROT_OW) || (move_indx == BS_71_BTROT_FALL) || (move_indx == 0x9a); } @@ -575,7 +573,7 @@ void bsbtrot_fall_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bsbtrot.c", 0x400); func_802A8A40(); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); baphysics_set_target_yaw(yaw_getIdeal()); bsbtrot_walkUpdateTargetVelocity(); baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); @@ -680,16 +678,16 @@ void bsbtrot_fall_end(void){ func_802A8BB0(); } -void bsbtrot_locked_init(void){ +void bsbtrot_unk79_init(void){ baanim_playForDuration_loopSmooth(ASSET_26_ANIM_BSBTROT_IDLE, 1.2f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_802A8A40(); baModel_setDirection(PLAYER_MODEL_DIR_KAZOOIE); func_8029C674(); } -void bsbtrot_locked_update(void){ +void bsbtrot_unk79_update(void){ enum bs_e sp1C = 0; func_8029C6D0(); func_802A8AD8(); @@ -699,7 +697,7 @@ void bsbtrot_locked_update(void){ bs_setState(sp1C); } -void bsbtrot_locked_end(void){ +void bsbtrot_unk79_end(void){ func_8029C748(); func_802A8BB0(); } @@ -711,9 +709,9 @@ void bsbtrot_ow_init(void){ func_802A8A40(); barebound_set_active(func_80296560()); - baanim_playForDuration_once(ASSET_66_ANIM_BSBTROT_OW, 1.1f); + baanim_playForDuration_onceSmooth(ASSET_66_ANIM_BSBTROT_OW, 1.1f); basfx_playOwSfx(1.0f); - playerPosition_get(sp30); + _player_getPosition(sp30); func_80294980(sp24); func_80257F18(sp24, sp30, &sp3C); yaw_setIdeal(mlNormalizeAngle(sp3C + 180.0f));\ @@ -721,7 +719,7 @@ void bsbtrot_ow_init(void){ baphysics_set_target_horizontal_velocity(barebound_get_horizontal_velocity()); baphysics_set_target_yaw(sp3C); baphysics_set_horizontal_velocity(sp3C, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); if(barebound_802987B4() == 2) baphysics_set_type(BA_PHYSICS_AIRBORN); baphysics_set_vertical_velocity(barebound_get_vertical_velocity()); diff --git a/src/core2/bs/throw.c b/src/core2/bs/throw.c index ee4a64da0..2e5e95de3 100644 --- a/src/core2/bs/throw.c +++ b/src/core2/bs/throw.c @@ -5,7 +5,7 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" -extern ActorMarker *bacarry_getMarker(void); +extern ActorMarker *bacarry_get_marker(void); /* .bss */ u8 D_8037D580; @@ -35,12 +35,12 @@ void bsthrow_update(void){ f32 sp34[3]; f32 player_position[3]; f32 sp24; - ActorMarker *sp20 = bacarry_getMarker(); + ActorMarker *sp20 = bacarry_get_marker(); if(D_8037D580 == 0 && sp20 != NULL) bacarry_set_marker(sp20); - playerPosition_get(player_position); + _player_getPosition(player_position); get_throw_target_position(sp34); func_80257F18(player_position, sp34, &sp24); yaw_setIdeal(sp24); diff --git a/src/core2/bs/timeout.c b/src/core2/bs/timeout.c index 03b3fef09..0d01ed5cc 100644 --- a/src/core2/bs/timeout.c +++ b/src/core2/bs/timeout.c @@ -3,28 +3,27 @@ #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" void baeyes_openSingleEye(s32, f32); f32 func_8029B41C(void); -void ncbadie_func_802BF2C0(f32); +void ncDynamicCamD_func_802BF2C0(f32); -void timeout_banjo_init(void){ - baanim_playForDuration_onceSmooth(ASSET_77_ANIM_BSTIMEOUT, 3.2f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); +void func_802B6270(void){ + baanim_playForDuration_once(ASSET_77_ANIM_BSTIMEOUT, 3.2f); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); - func_802914CC(0xD); + func_802914CC(0xd); yaw_setIdeal(func_8029B41C() + 35.0f); - ncbadie_func_802BF2C0(80.0f); - func_8025A58C(0, 4000); + ncDynamicCamD_func_802BF2C0(80.0f); + func_8025A58C(0,0xfa0); comusic_playTrack(COMUSIC_3C_MINIGAME_LOSS); core1_ce60_incOrDecCounter(false); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); baMarker_collisionOff(); } -void timeout_banjo_update(void){ +void func_802B6314(void){ AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); if(anctrl_isAt(aCtrl, 0.0625f)) baeyes_close(); @@ -41,37 +40,37 @@ void timeout_banjo_update(void){ func_8029B6F0(); } -void timeout_banjo_end(void){ +void func_802B63C8(void){ baeyes_open(); func_80291548(); core1_ce60_incOrDecCounter(true); } -void timeout_transformation_init(void){ +void func_802B63F8(void){ AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); anctrl_reset(aCtrl); func_8029C848(aCtrl); anctrl_setPlaybackType(aCtrl, ANIMCTRL_LOOP); - anctrl_start(aCtrl, "bstimeout.c", 0x7E); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + anctrl_start(aCtrl, "bstimeout.c", 0x7e); + func_8029C7F4(1,1,3,BA_PHYSICS_FREEZE); baphysics_set_target_horizontal_velocity(0.0f); - func_802914CC(0xD); + func_802914CC(0xd); yaw_setIdeal(func_8029B41C() + 35.0f); - ncbadie_func_802BF2C0(80.0f); - func_8025A58C(0, 4000); + ncDynamicCamD_func_802BF2C0(80.0f); + func_8025A58C(0,0xfa0); comusic_playTrack(COMUSIC_3C_MINIGAME_LOSS); core1_ce60_incOrDecCounter(false); baMarker_collisionOff(); batimer_set(0, 2.9f); } -void timeout_transformation_update(void){ +void func_802B64D0(void){ if(batimer_decrement(0)) func_8029B6F0(); } -void timeout_transformation_end(void){ - modelAppendages_setKazooiesUpperHalfVisibility(false); +void func_802B6500(void){ + func_8029E070(0); func_80291548(); core1_ce60_incOrDecCounter(true); func_8025A904(); diff --git a/src/core2/bs/turn.c b/src/core2/bs/turn.c index 58758d251..2a0dfc397 100644 --- a/src/core2/bs/turn.c +++ b/src/core2/bs/turn.c @@ -54,10 +54,10 @@ void bsturn_update(void){ sp2C = BS_4_WALK_FAST; if(bakey_held(BUTTON_Z)) - sp2C = BS_7_CROUCH; + sp2C = BS_CROUCH; if(bakey_pressed(BUTTON_B)) - sp2C = BS_6_CLAW; + sp2C = BS_CLAW; if(bakey_pressed(BUTTON_A)) sp2C = bs_getTypeOfJump(); diff --git a/src/core2/bs/walk.c b/src/core2/bs/walk.c index e2540c5ee..c55574ad3 100644 --- a/src/core2/bs/walk.c +++ b/src/core2/bs/walk.c @@ -4,7 +4,6 @@ #include "animation.h" #include "core2/ba/anim.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" void baanim_setDurationRange(f32, f32); void func_802927E0(f32, f32); @@ -97,10 +96,10 @@ s32 func_802B6F20(s32 arg0){ if(bakey_pressed(BUTTON_B)){ if( bsWalkWalkFastWalkVelocityThreshold < baphysics_get_target_horizontal_velocity()){ if(can_roll()) - arg0 = BS_31_ROLL; + arg0 = BS_ROLL; }else{//L802B6F74 if(can_claw()) - arg0 = BS_6_CLAW; + arg0 = BS_CLAW; } } return arg0; @@ -129,7 +128,7 @@ void bswalk_creep_init(void){ anctrl_setStart(anim_ctrl, start_position); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0xe4); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkMinCreepVelocity, bsWalkCreepSlowWalkVelocityThreshold, bsWalkSlowestCreepDuration, bsWalkFastestCreepDuration); } @@ -153,14 +152,14 @@ void bswalk_creep_update(void){ next_state = BS_2_WALK_SLOW; break; case 3://L802B7188 - next_state = BS_3_WALK; + next_state = BS_WALK; break; case 4: next_state = BS_4_WALK_FAST; break; }//L802B7194 if(player_isOnDangerousGround()) - next_state = BS_7A_WALK_MUD; + next_state = BS_WALK_MUD; if(bainput_should_look_first_person_camera()) next_state = badrone_look(); @@ -169,7 +168,7 @@ void bswalk_creep_update(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_7_CROUCH; + next_state = BS_CROUCH; next_state = func_802B6F20(next_state); @@ -177,7 +176,7 @@ void bswalk_creep_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_32_SLIDE; + next_state = BS_SLIDE; next_state = func_8029CA94(next_state); @@ -202,7 +201,7 @@ void bswalk_slow_init(void){ anctrl_setStart(anim_ctrl, start_position); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0x168); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkCreepSlowWalkVelocityThreshold, bsWalkSlowWalkWalkVelocityThreshold, bsWalkSlowestSlowWalkDuration, bsWalkFastestSlowWalkDuration); } @@ -223,17 +222,17 @@ void bswalk_slow_upate(void){ next_state = BS_1_IDLE; break; case 1://L802B7180 - next_state = BS_1F_WALK_CREEP; + next_state = BS_WALK_CREEP; break; case 3://L802B7188 - next_state = BS_3_WALK; + next_state = BS_WALK; break; case 4: next_state = BS_4_WALK_FAST; break; }//L802B7194 if(player_isOnDangerousGround()) - next_state = BS_7A_WALK_MUD; + next_state = BS_WALK_MUD; if(bainput_should_look_first_person_camera()) next_state = badrone_look(); @@ -242,7 +241,7 @@ void bswalk_slow_upate(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_7_CROUCH; + next_state = BS_CROUCH; next_state = func_802B6F20(next_state); @@ -250,7 +249,7 @@ void bswalk_slow_upate(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_32_SLIDE; + next_state = BS_SLIDE; next_state = func_8029CA94(next_state); @@ -280,7 +279,7 @@ void bswalk_init(void){ anctrl_setStart(anim_ctrl, start_position); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0x1ed); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkSlowWalkWalkVelocityThreshold, bsWalkWalkFastWalkVelocityThreshold, bsWalkSlowestWalkDuration, bsWalkFastestWalkDuration); func_802B6EB0(0.3f); @@ -305,10 +304,10 @@ void bswalk_update(void){ break; }//L802B76B8 if(player_isOnDangerousGround()) - next_state = BS_7A_WALK_MUD; + next_state = BS_WALK_MUD; if(func_8028B4C4() && bsWalkSkidVelocity < baphysics_get_horizontal_velocity()){ - next_state = BS_C_SKID; + next_state = BS_SKID; } if(bainput_should_look_first_person_camera()) @@ -318,7 +317,7 @@ void bswalk_update(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_7_CROUCH; + next_state = BS_CROUCH; next_state = func_802B6F20(next_state); @@ -326,7 +325,7 @@ void bswalk_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_32_SLIDE; + next_state = BS_SLIDE; next_state = func_8029CA94(next_state); @@ -364,7 +363,7 @@ void bswalk_fast_init(void){ anctrl_setStart(anim_ctrl, sp28); anctrl_setPlaybackType(anim_ctrl, ANIMCTRL_LOOP); anctrl_start(anim_ctrl, "bswalk.c", 0x27d); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkWalkFastWalkVelocityThreshold, bsWalkMaxFastWalkVelocity, bsWalkSlowestFastWalkDuration, bsWalkFastestFastWalkDuration); pitch_setAngVel(1000.0f, 12.0f); @@ -401,24 +400,24 @@ void bswalk_fast_update(void){ break; case 3://L802B7A60 if(baphysics_is_slower_than(bsWalkWalkFastWalkVelocityThreshold) && func_802B6EF4()) - next_state = BS_3_WALK; + next_state = BS_WALK; if(bainput_should_look_first_person_camera()) next_state = badrone_look(); break; }//L802B7AA4 if(player_isOnDangerousGround()) - next_state = BS_7A_WALK_MUD; + next_state = BS_WALK_MUD; if(func_8028B4C4() && bsWalkSkidVelocity < baphysics_get_horizontal_velocity()){ - next_state = BS_C_SKID; + next_state = BS_SKID; } if(player_shouldFall()) next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_7_CROUCH; + next_state = BS_CROUCH; next_state = func_802B6F20(next_state); @@ -426,7 +425,7 @@ void bswalk_fast_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_32_SLIDE; + next_state = BS_SLIDE; next_state = func_8029CA94(next_state); @@ -443,7 +442,7 @@ void bswalk_fast_end(void){ void bswalk_mud_init(void){ baanim_playForDuration_loopSmooth(ASSET_B_ANIM_BSWALK_MUD, 0.43f); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setDurationRange(0.3f, 1.5f); baanim_setVelocityMapRanges(bsWalkMinMudVelocity, bsWalkMaxMudVelocity, bsWalkSlowestMudDuration, bsWalkFastestMudDuration); } @@ -467,7 +466,7 @@ void bswalk_mud_update(void){ next_state = BS_2F_FALL; if(bakey_held(BUTTON_Z)) - next_state = BS_7_CROUCH; + next_state = BS_CROUCH; next_state = func_802B6F20(next_state); @@ -475,7 +474,7 @@ void bswalk_mud_update(void){ next_state = bs_getTypeOfJump(); if(player_isSliding()) - next_state = BS_32_SLIDE; + next_state = BS_SLIDE; next_state = func_8029CA94(next_state); diff --git a/src/core2/bs/walrus.c b/src/core2/bs/walrus.c index 9b45a6a76..952203c40 100644 --- a/src/core2/bs/walrus.c +++ b/src/core2/bs/walrus.c @@ -4,7 +4,6 @@ #include "core2/ba/anim.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" extern void func_8029AD68(f32, s32); @@ -94,8 +93,8 @@ void func_802B8048(void){ pitch_setIdeal(0.0f); roll_setIdeal(0.0f); bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); - modelAppendages_setKazooiesFeetAndShoesVisibility(false); + func_8029E070(0); + func_8029E064(0); baflag_clear(BA_FLAG_3); baflag_clear(BA_FLAG_4); func_80293D74(); @@ -106,7 +105,7 @@ void func_802B8048(void){ void func_802B80D0(void) { if (bswalrus_inSledSet(bs_getNextState()) == 0) { func_802B8048(); - modelAppendages_setSledVisibility(false); + func_8029E0E8(0); } } @@ -117,7 +116,7 @@ void func_802B8110(void){ void func_802B813C(void) { if (!bswalrus_inSledSet(bs_getPrevState())) { D_8037D5C0 = 0.0f; - modelAppendages_setSledVisibility(true); + func_8029E0E8(1); func_8029CF48(4, 1, 0.15f); } } @@ -133,18 +132,18 @@ int bswalrus_inSledSet(enum bs_e state){ int bswalrus_inSet(enum bs_e state){ return state == BS_67_WALRUS_IDLE - || state == BS_68_WALRUS_WALK - || state == BS_69_WALRUS_JUMP + || state == BS_WALRUS_WALK + || state == BS_WALRUS_JUMP || state == BS_6A_WALRUS_FALL - || state == BS_6C_WALRUS_OW - || state == BS_6D_WALRUS_DIE + || state == BS_WALRUS_OW + || state == BS_WALRUS_DIE || state == BS_95_WALRUS_DRONE || bswalrus_inSledSet(state); } void bswalrus_idle_init(void){ baanim_playForDuration_loopSmooth(ASSET_11F_ANIM_BSWALRUS_IDLE, 4.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); pitch_setAngVel(1000.0f, 12.0f); roll_setAngularVelocity(1000.0f, 12.0f); @@ -167,10 +166,10 @@ void bswalrus_idle_update(void){ next_state = badrone_look(); if(bastick_getZone() > 0) - next_state = BS_68_WALRUS_WALK; + next_state = BS_WALRUS_WALK; if(bakey_pressed(BUTTON_A)) - next_state = BS_69_WALRUS_JUMP; + next_state = BS_WALRUS_JUMP; bs_setState(next_state); } @@ -182,7 +181,7 @@ void bswalrus_idle_end(void){ void bswalrus_walk_init(void){ baanim_playForDuration_loopSmooth(ASSET_120_ANIM_BSWALRUS_WALK, 0.8f); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364DC0, D_80364DC4, D_80364DC8, D_80364DCC); func_802900B4(); func_802B8110(); @@ -202,7 +201,7 @@ void bswalrus_walk_update(void){ next_state = BS_6A_WALRUS_FALL; if(bakey_pressed(BUTTON_A)) - next_state = BS_69_WALRUS_JUMP; + next_state = BS_WALRUS_JUMP; bs_setState(next_state); } @@ -223,7 +222,7 @@ void bswalrus_jump_init(void){ anctrl_setStart(aCtrl, 0.1); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bswalrus.c", 0x1f8); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -290,10 +289,10 @@ void bswalrus_jump_update(void){ if(player_isStable()){ if(bastick_getZone() > 0) - next_state = BS_68_WALRUS_WALK; + next_state = BS_WALRUS_WALK; if(bakey_pressed(BUTTON_A)) - next_state = BS_69_WALRUS_JUMP; + next_state = BS_WALRUS_JUMP; } bs_setState(next_state); @@ -312,7 +311,7 @@ void bswalrus_fall_init(void){ anctrl_setDuration(aCtrl, 0.7f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bswalrus.c", 0x284); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); func_802B8110(); D_8037D5C8 = 0; } @@ -373,13 +372,13 @@ static void __bswalrus_recoil_init(s32 damage){ f32 sp24[3]; barebound_set_active(func_80296560()); - baanim_playForDuration_once(ASSET_19C_ANIM_BSWALRUS_BOUNCE, 1.0f); + baanim_playForDuration_onceSmooth(0x19c, 1.0f); if(damage == 1) func_8030E58C(SFX_38_BANJO_AYE_1, 1.8f); else func_8030E58C(SFX_56_BANJO_HUI, 1.8f); - playerPosition_get(sp30); + _player_getPosition(sp30); func_80294980(sp24); func_80257F18(sp24, sp30, &sp3C); yaw_setIdeal(mlNormalizeAngle(sp3C + 180.0f)); @@ -387,7 +386,7 @@ static void __bswalrus_recoil_init(s32 damage){ baphysics_set_target_horizontal_velocity(barebound_get_horizontal_velocity()); baphysics_set_target_yaw(sp3C); baphysics_set_horizontal_velocity(sp3C, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(barebound_get_vertical_velocity()); baphysics_set_gravity(barebound_get_gravity()); baMarker_collisionOff(); @@ -452,7 +451,7 @@ void bswalrus_die_init(void){ anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bswalrus.c", 0x366); func_8030E58C(SFX_36_BANJO_DOH, 1.8f); - playerPosition_get(sp2C); + _player_getPosition(sp2C); func_80294980(sp20); func_80257F18(sp20, sp2C, &sp38); D_8037D5C4 = 250.0f; @@ -461,12 +460,12 @@ void bswalrus_die_init(void){ baphysics_set_target_horizontal_velocity(D_8037D5C4); baphysics_set_target_yaw(sp38); baphysics_set_horizontal_velocity(sp38, baphysics_get_target_horizontal_velocity()); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 2, BA_PHYSICS_LOCKED_ROTATION); + func_8029C7F4(1,1,2, BA_PHYSICS_LOCKED_ROTATION); baphysics_set_vertical_velocity(420.0f); //B) baphysics_set_gravity(-1200.0f); pitch_setAngVel(1000.0f, 12.0f); func_802914CC(0xd); - ncbadie_func_802BF2C0(30.0f); + ncDynamicCamD_func_802BF2C0(30.0f); func_8025AB00(); func_8025A2FC(0, 0xfa0); comusic_playTrack(0x1A); @@ -531,16 +530,16 @@ void bswalrus_drone_end(void){ func_802B8048(); } -void bswalrus_sledlocked_init(void){ +void func_802B90D0(void){ baanim_playForDuration_loopSmooth(ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); func_802B813C(); func_802B3A50(); } -void bswalrus_sledlocked_update(void){ +void func_802B9130(void){ enum bs_e next_state = 0; func_802B3A50(); func_80299628(0); @@ -551,14 +550,14 @@ void bswalrus_sledlocked_update(void){ bs_setState(next_state); } -void bswalrus_sledlocked_end(void){ +void func_802B917C(void){ func_8029C748(); func_802B80D0(); } void bswalrus_sled_init(void){ baanim_playForDuration_loopSmooth(ASSET_19E_ANIM_BSWALRUS_SLED, 0.8f); - code_14420_setUpdateTypes(BAANIM_UPDATE_2_SCALE_HORZ, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(BAANIM_UPDATE_2_SCALE_HORZ,1,1, BA_PHYSICS_NORMAL); baanim_setVelocityMapRanges(D_80364DC0, D_80364DC4, D_80364DE0, D_80364DE4); func_802900B4(); func_802B813C(); @@ -604,7 +603,7 @@ void bswalrus_sled_jump_init(void){ anctrl_setStart(aCtrl, 0.14f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bswalrus.c", 0x477); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); baphysics_set_target_yaw(yaw_getIdeal()); @@ -664,7 +663,7 @@ void bswalrus_sled_jump_end(void){ func_802B80D0(); } -void bswalrus_sledloseinair_init(void){ +void func_802B95A0(void){ AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); anctrl_reset(aCtrl); anctrl_setIndex(aCtrl, ASSET_19F_ANIM_BSWALRUS_SLED_JUMP); @@ -672,12 +671,12 @@ void bswalrus_sledloseinair_init(void){ anctrl_setDuration(aCtrl, 1.0f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_STOPPED); anctrl_start(aCtrl, "bswalrus.c", 0x4e2); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3, BA_PHYSICS_AIRBORN); func_802B813C(); D_8037D5C8 = 0; } -void bswalrus_sledloseinair_update(void){ +void func_802B963C(void){ enum bs_e next_state = 0; AnimCtrl *aCtrl = baanim_getAnimCtrlPtr(); f32 sp1C[3]; @@ -721,16 +720,16 @@ void bswalrus_sledloseinair_update(void){ bs_setState(next_state); } -void bswalrus_sledloseinair_end(void){ +void func_802B976C(void){ func_802B8048(); } void bswalrus_timeout_init(void) { - baanim_playForDuration_onceSmooth(ASSET_1A9_ANIM_BSWALRUS_LOSS, 3.2f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_FREEZE); + baanim_playForDuration_once(ASSET_1A9_ANIM_BSWALRUS_LOSS, 3.2f); + func_8029C7F4(1, 1, 3, BA_PHYSICS_FREEZE); baphysics_set_target_horizontal_velocity(0.0f); func_802914CC(0xD); - ncbadie_func_802BF2C0(60.0f); + ncDynamicCamD_func_802BF2C0(60.0f); func_8025A58C(0, 4000); comusic_playTrack(COMUSIC_3C_MINIGAME_LOSS); core1_ce60_incOrDecCounter(false); @@ -740,7 +739,7 @@ void bswalrus_timeout_init(void) { baeyes_close(); } -void bswalrus_timeout_update(void) { +void func_802B9830(void) { yaw_setIdeal(func_8029B41C() + 35.0f); func_80299628(0); if (batimer_decrement(0) != 0) { @@ -748,7 +747,7 @@ void bswalrus_timeout_update(void) { } } -void bswalrus_timeout_end(void) { +void func_802B9880(void) { func_80291548(); core1_ce60_incOrDecCounter(true); func_8025A904(); diff --git a/src/core2/bs/washy.c b/src/core2/bs/washing_machine.c similarity index 90% rename from src/core2/bs/washy.c rename to src/core2/bs/washing_machine.c index 6494ece1b..aa08904df 100644 --- a/src/core2/bs/washy.c +++ b/src/core2/bs/washing_machine.c @@ -1,11 +1,9 @@ -// BanjoDecomp: core2/bs/washy.c #include #include "functions.h" #include "variables.h" #include "core2/ba/physics.h" #include "core2/ba/timer.h" -#include "core2/yaw.h" /* .bss */ u8 D_8037D5D0; @@ -44,18 +42,18 @@ void func_802B9980(s32 arg0){ D_8037D5D0 = arg0; } -void bswashy_end(void){ +void func_802B9AAC(void){ func_802900FC(); } -void bswashy_init(void){ - baanim_playForDuration_onceSmooth(ASSET_281_ANIM_WISHYWASHY_DOOOH, 40.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); +void func_802B9ACC(void){ + baanim_playForDuration_once(ASSET_281_ANIM_WISHYWASHY_DOOOH, 40.0f); + func_8029C7F4(1, 1, 3, BA_PHYSICS_NORMAL); func_802900B4(); func_802B9980(0); } -void bswashy_update(void){ +void func_802B9B14(void){ s32 next_state = 0; s32 sp18; diff --git a/src/core2/bs/bWhirl.c b/src/core2/bs/wonderwing.c similarity index 90% rename from src/core2/bs/bWhirl.c rename to src/core2/bs/wonderwing.c index 4db5bd97a..48be4a02c 100644 --- a/src/core2/bs/bWhirl.c +++ b/src/core2/bs/wonderwing.c @@ -1,11 +1,9 @@ -// BanjoDecomp: core2/bs/bWhirl.c #include #include "functions.h" #include "variables.h" #include "core2/ba/anim.h" #include "core2/ba/physics.h" -#include "core2/yaw.h" const f32 D_80364AD0 = 80.0f; const f32 D_80364AD4 = 425.0f; @@ -39,7 +37,7 @@ static void __bsbwhirl_end(void){ ) ){ bastick_resetZones(); - modelAppendages_setKazooiesUpperHalfVisibility(false); + func_8029E070(0); func_8025A55C(-1, 0xfa0, 0xd); core1_ce60_incOrDecCounter(true); func_8025A7DC(COMUSIC_25_USING_GOLD_FEATHERS); @@ -81,12 +79,12 @@ void func_802AA58C(enum bs_e *arg0){ } void bsbwhirl_enter_init(void){ - baanim_playForDuration_once(ASSET_22_ANIM_BSWHIRL_EXIT, 0.5f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + baanim_playForDuration_onceSmooth(ASSET_22_ANIM_BSWHIRL_EXIT, 0.5f); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); bastick_setZoneMax(0, 0.03f); bastick_setZoneMax(1, 1.0f); - modelAppendages_setKazooiesUpperHalfVisibility(true); + func_8029E070(1); D_8037D3B0 = 0.0f; core1_ce60_incOrDecCounter(false); func_8025A55C(0, 0xfa0, 0xd); @@ -110,7 +108,7 @@ void bsbwhirl_enter_end(void){ void bsbwhirl_stand_init(void){ baanim_playForDuration_loopSmooth(ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,1, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); } @@ -121,7 +119,7 @@ void bsbwhirl_stand_update(void){ func_802AA58C(&sp1C); if(player_isSliding()) - sp1C = BS_32_SLIDE; + sp1C = BS_SLIDE; if(player_inWater()) sp1C = BS_4C_LANDING_IN_WATER; @@ -137,7 +135,7 @@ void bsbwhirl_stand_end(void){ void bsbwhirl_walk_init(void){ baanim_playForDuration_loopSmooth(ASSET_11_ANIM_BSWHIRL_WALK, 0.53f); baanim_setVelocityMapRanges(D_80364AD0, D_80364AD4, D_80364AD8, D_80364ADC); - code_14420_setUpdateTypes(2, YAW_STATE_1_DEFAULT, 1, BA_PHYSICS_NORMAL); + func_8029C7F4(2,1,1, BA_PHYSICS_NORMAL); } void bsbwhirl_walk_update(void){ @@ -162,7 +160,7 @@ void bsbwhirl_walk_update(void){ func_802AA58C(&sp1C); if(player_isSliding()) - sp1C = BS_32_SLIDE; + sp1C = BS_SLIDE; bs_setState(sp1C); } @@ -182,7 +180,7 @@ void bsbwhirl_jump_init(void){ anctrl_setSubRange(aCtrl, 0.0f, 0.4495f); anctrl_setPlaybackType(aCtrl, ANIMCTRL_ONCE); anctrl_start(aCtrl, "bsbwhirl.c", 0x181); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_AIRBORN); + func_8029C7F4(1,1,3,BA_PHYSICS_AIRBORN); if(bastick_distance() != 0.0f) yaw_setIdeal(bastick_getAngleRelativeToBanjo()); @@ -285,14 +283,14 @@ void bsbwhirl_drone_end(void){ __bsbwhirl_end(); } -void bsbwhirl_bsA5unknown_init(void){ +void func_802AADBC(void){ baanim_playForDuration_loopSmooth(ASSET_23_ANIM_BSWONDERWING_IDLE, 1.0f); - code_14420_setUpdateTypes(1, YAW_STATE_1_DEFAULT, 3, BA_PHYSICS_NORMAL); + func_8029C7F4(1,1,3, BA_PHYSICS_NORMAL); baphysics_set_target_horizontal_velocity(0.0f); func_8029C674(); } -void bsbwhirl_bsA5unknown_update(void){ +void func_802AAE08(void){ enum bs_e sp1C =0; __bsbwhirl_spawnSparkle(); func_8029C6D0(); @@ -302,7 +300,7 @@ void bsbwhirl_bsA5unknown_update(void){ bs_setState(sp1C); } -void bsbwhirl_bsA5unknown_end(void){ +void func_802AAE4C(void){ func_8029C748(); __bsbwhirl_end(); } diff --git a/src/core2/bundle.c b/src/core2/bundle.c index ce710eb32..c162b7d1a 100644 --- a/src/core2/bundle.c +++ b/src/core2/bundle.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_41FB0.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/nc/camera_debug_freecam.c b/src/core2/camera/camera_debug_freecam.c similarity index 98% rename from src/core2/nc/camera_debug_freecam.c rename to src/core2/camera/camera_debug_freecam.c index cc4a1fa1b..bf8b1e8a1 100644 --- a/src/core2/nc/camera_debug_freecam.c +++ b/src/core2/camera/camera_debug_freecam.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core1/stub_2FA0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/nc/camera_ease.c b/src/core2/camera/camera_ease.c similarity index 96% rename from src/core2/nc/camera_ease.c rename to src/core2/camera/camera_ease.c index b343b3edd..c76d52edd 100644 --- a/src/core2/nc/camera_ease.c +++ b/src/core2/camera/camera_ease.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_3B2C0.c #include #include "functions.h" #include "variables.h" @@ -30,7 +29,7 @@ void func_802C22B4(void){ s_state = 0; } -// something for dynamic camera + void func_802C22C0(f32 target_position[3], f32 target_rotation[3]){ f32 tmpf_1[3]; f32 tmpf_2[3]; diff --git a/src/core2/nc/camera_focus.c b/src/core2/camera/camera_focus.c similarity index 96% rename from src/core2/nc/camera_focus.c rename to src/core2/camera/camera_focus.c index 70624ae3f..519e2266f 100644 --- a/src/core2/nc/camera_focus.c +++ b/src/core2/camera/camera_focus.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_33C30.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/nc/camera_focustarget.c b/src/core2/camera/camera_focustarget.c similarity index 97% rename from src/core2/nc/camera_focustarget.c rename to src/core2/camera/camera_focustarget.c index c708c734e..45911191c 100644 --- a/src/core2/nc/camera_focustarget.c +++ b/src/core2/camera/camera_focustarget.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_F8EAF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/camera_fog.c b/src/core2/camera/camera_fog.c similarity index 98% rename from src/core2/nc/camera_fog.c rename to src/core2/camera/camera_fog.c index b20ee5d5f..fa2bc7f4e 100644 --- a/src/core2/nc/camera_fog.c +++ b/src/core2/camera/camera_fog.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_37E50.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/nc/camera_motor1.c b/src/core2/camera/camera_motor1.c similarity index 94% rename from src/core2/nc/camera_motor1.c rename to src/core2/camera/camera_motor1.c index ea43f777a..cb37c274d 100644 --- a/src/core2/nc/camera_motor1.c +++ b/src/core2/camera/camera_motor1.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_33F90.c #include #include "functions.h" #include "variables.h" @@ -74,7 +73,6 @@ s16 D_8036502C[] = { 0, -1, 0, 4, 0x12, 5, s16 D_8036503C[] = { 0, -1, 0, 0, -4, 0x1E}; s16 D_80365048[] = { 0, -1, 0, 2, 0x23, 1, 0x46, -6, -1, 0x46}; s16 D_8036505C[] = { 0, -1, 0, 1, 0x1A, -6, -1, 0x1A}; -#if VERSION == VERSION_USA_1_0 s16 D_8036506C[] = { 0, -1, 0, 0xC, 0xD, 0xD, 0x20, 0x3, 0x34, -6, -1, 0x39}; s16 D_80365084[] = { 0, -1, 0, 0, 0x13, 1, 0x30, 0xD, -4, 0x53}; s16 D_80365098[] = { 0, -1, 0, 6, 0xD, 7, 0x20, 0x14, -4, 0x39}; @@ -84,17 +82,6 @@ s16 D_803650D4[] = { 0, -1, 0, 3, 0xD, 4, 0x20, 0x13, s16 D_803650E8[] = { 0, -1, 0, 0, 0xD, 1, 0x20, 0x4, -4, 0x39}; s16 D_803650FC[] = { 0, -1, 0, 0, 0xD, 1, 0x20, 0xD, -4, 0x41}; s16 D_80365110[] = { 0, -1, 0, 3, 0xD, 4, 0x20, 0x20, -4, 0x39}; -#elif VERSION == VERSION_PAL -s16 D_8036506C[] = { 0, -1, 0, 0xC, 0xD, 0xD, 0x28, 0x3, 0x46, -6, -1, 0x4B}; -s16 D_80365084[] = { 0, -1, 0, 0, 0x13, 1, 0x38, 0xD, -4, 0x65}; -s16 D_80365098[] = { 0, -1, 0, 6, 0xD, 7, 0x28, 0x14, -4, 0x49}; -s16 D_803650AC[] = { 0, -1, 0, 2, 0xD, 3, 0x28, 0xB, -4, 0x49}; -s16 D_803650C0[] = { 0, -1, 0, 0, 0xD, 1, 0x26, 0xC, -4, 0x48}; -s16 D_803650D4[] = { 0, -1, 0, 3, 0xD, 4, 0x26, 0x13, -4, 0x48}; -s16 D_803650E8[] = { 0, -1, 0, 0, 0xD, 1, 0x26, 0x4, -4, 0x48}; -s16 D_803650FC[] = { 0, -1, 0, 0, 0xD, 1, 0x26, 0xD, -4, 0x50}; -s16 D_80365110[] = { 0, -1, 0, 3, 0xD, 4, 0x26, 0x20, -4, 0x48}; -#endif s16 D_80365124[] = { 0, -1, 0, 2, 0xF, 3, -4, 0x28}; s16 D_80365134[] = { 0, -1, 0, 5, 0xC, 6, -4, 0x21}; s16 D_80365144[] = { 0, -1, 0, 0, 0xC, 1, -4, 0x21}; diff --git a/src/core2/nc/camera_motor2.c b/src/core2/camera/camera_motor2.c similarity index 99% rename from src/core2/nc/camera_motor2.c rename to src/core2/camera/camera_motor2.c index 0be2a6be9..0675f3b4d 100644 --- a/src/core2/nc/camera_motor2.c +++ b/src/core2/camera/camera_motor2.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_34310.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/camera_nodemanager.c b/src/core2/camera/camera_nodemanager.c similarity index 94% rename from src/core2/nc/camera_nodemanager.c rename to src/core2/camera/camera_nodemanager.c index de7e2b158..20063fcc1 100644 --- a/src/core2/nc/camera_nodemanager.c +++ b/src/core2/camera/camera_nodemanager.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_34790.c #include #include "core1/core1.h" #include "functions.h" @@ -65,7 +64,7 @@ bool func_802BB720(s32 arg0, f32 arg1[3], f32 arg2[3], s32 *arg3) { if (temp_v0 != NULL) { nodeprop_getPosition(temp_v0, arg1); *arg3 = nodeprop_getScale(temp_v0); - temp_f6 = (f32) nodeProp_getYaw(temp_v0) - 180.0f; + temp_f6 = (f32) nodeprop_getYaw(temp_v0) - 180.0f; arg2[0] = 0.0f;\ arg2[1] = mlNormalizeAngle(temp_f6);\ arg2[2] = 0.0f; @@ -125,7 +124,7 @@ void func_802BBA84(void) { mapModel_getBounds((s32 *)min, (s32 *)max); viewport_getPosition_vec3f(vp_position); viewport_getRotation_vec3f(vp_rotation); - viewport_getLookVector(sp48); + viewport_getLookbk_vector(sp48); D_8037D8CC = (f32) coords_func_8033EAF8((s32*)min, (s32*)max, vp_position, sp48); D_8037D8CC += 100.0f; if (D_8037D8CC < 1000.0f) { @@ -187,9 +186,9 @@ void func_802BBD0C(Gfx **gdl, Mtx **mptr, Vtx **vptr){ func_802BEE2C(gdl, mptr, vptr); } -void core2_34790_getClipDistances(f32 *near, f32 *far) { - *near = D_8037D8C8; - *far = D_8037D8CC; +void func_802BBD2C(f32 *arg0, f32 *arg1){ + *arg0 = D_8037D8C8; + *arg1 = D_8037D8CC; } f32 func_802BBD48(void) { @@ -307,9 +306,6 @@ void ncCamera_update(void){ viewport_getPosition_vec3f(sp2C); viewport_getRotation_vec3f(sp20); func_802BB4D8(sp2C, sp20); - if (EventSystem_Should(VB_CAMERA_APPLY_SHAKE, true)) { - viewport_setPosition_vec3f(sp2C); - } viewport_update(); func_802BEFB0(); func_802BBA84(); @@ -365,7 +361,7 @@ void func_802BC2CC(s32 arg0) { viewport_setPosition_vec3f(D_8037D908); viewport_setRotation_vec3f(D_8037D918); viewport_update(); - __spawnQueue_add_2((GenFunction_2)func_802BC2A0, (uintptr_t)sp24, (uintptr_t)sp20); + __spawnQueue_add_2((void (*)(void))func_802BC2A0, (uintptr_t)sp24, (uintptr_t)sp20); if (ncCameraType == CAMERA_TYPE_2_DYNAMIC) { func_802BE720(); if (sp1C != 0x63) { @@ -380,7 +376,7 @@ bool func_802BC428(void){ } void func_802BC434(f32 arg0[3], f32 arg1[3], f32 arg2[3]) { - ml_horizontal_and_vertical_angles(arg1[0], arg1[1], arg1[2], arg2[0], arg2[1], arg2[2], &arg0[0], &arg0[1]); + func_8025727C(arg1[0], arg1[1], arg1[2], arg2[0], arg2[1], arg2[2], &arg0[0], &arg0[1]); arg0[0] = mlNormalizeAngle(-arg0[0]); arg0[2] = 0.0f; } diff --git a/src/core2/nc/camera_position.c b/src/core2/camera/camera_position.c similarity index 98% rename from src/core2/nc/camera_position.c rename to src/core2/camera/camera_position.c index e35048052..1c51a3142 100644 --- a/src/core2/nc/camera_position.c +++ b/src/core2/camera/camera_position.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_379B0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/camera_set.c b/src/core2/camera/camera_set.c similarity index 98% rename from src/core2/nc/camera_set.c rename to src/core2/camera/camera_set.c index 123270faf..93253ea10 100644 --- a/src/core2/nc/camera_set.c +++ b/src/core2/camera/camera_set.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CB610.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/cameranode_type1.c b/src/core2/camera/cameranode_type1.c similarity index 99% rename from src/core2/nc/cameranode_type1.c rename to src/core2/camera/cameranode_type1.c index 5b70fcaa1..b80596118 100644 --- a/src/core2/nc/cameranode_type1.c +++ b/src/core2/camera/cameranode_type1.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_336F0.c #include #include diff --git a/src/core2/nc/cameranode_type2.c b/src/core2/camera/cameranode_type2.c similarity index 98% rename from src/core2/nc/cameranode_type2.c rename to src/core2/camera/cameranode_type2.c index 43df38fbf..06905a8ba 100644 --- a/src/core2/nc/cameranode_type2.c +++ b/src/core2/camera/cameranode_type2.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_33AB0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/cameranode_type3.c b/src/core2/camera/cameranode_type3.c similarity index 99% rename from src/core2/nc/cameranode_type3.c rename to src/core2/camera/cameranode_type3.c index 9c2cf231b..fcdd6a99f 100644 --- a/src/core2/nc/cameranode_type3.c +++ b/src/core2/camera/cameranode_type3.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_33310.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/cameranode_type4.c b/src/core2/camera/cameranode_type4.c similarity index 96% rename from src/core2/nc/cameranode_type4.c rename to src/core2/camera/cameranode_type4.c index 36763a654..0fb4df6c7 100644 --- a/src/core2/nc/cameranode_type4.c +++ b/src/core2/camera/cameranode_type4.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_33250.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/cameranodelist.c b/src/core2/camera/cameranodelist.c similarity index 99% rename from src/core2/nc/cameranodelist.c rename to src/core2/camera/cameranodelist.c index 0e7d7d472..ce809a9e8 100644 --- a/src/core2/nc/cameranodelist.c +++ b/src/core2/camera/cameranodelist.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/cameranodelist.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/camera/dynamicCam1.c b/src/core2/camera/dynamicCam1.c new file mode 100644 index 000000000..fd28a665b --- /dev/null +++ b/src/core2/camera/dynamicCam1.c @@ -0,0 +1,46 @@ +#include +#include "functions.h" +#include "variables.h" + +extern f32 func_802BD51C(void); +extern f32 player_getYaw(void); +extern void func_802BD870(f32, f32, f32, f32); + +void ncDynamicCam1_init(void){ + func_802BD870(12.0f, 10.0f, 120.0f, 120.0f); +} + +void ncDynamicCam1_end(void){} + +void ncDynamicCam1_update(void) { + f32 sp8C[3]; + f32 sp80[3]; + f32 sp74[3]; + f32 sp68[3]; + f32 sp5C[3]; + f32 sp50[3]; + f32 sp4C; + f32 sp48; + f32 temp_f20; + f32 sp40; + f32 sp3C; + + ncDynamicCamera_getPosition(sp74); + func_802BD4C0(sp8C); + sp3C = func_802BD8D4(); + temp_f20 = time_getDelta(); + ml_vec3f_diff_copy(sp50, sp74, sp8C); + sp4C = gu_sqrtf((sp50[0] * sp50[0]) + (sp50[2] * sp50[2])); + sp4C += func_80259198((sp3C - sp4C) * temp_f20 * 2, temp_f20 * 120.0f); + func_8025801C(sp50, &sp48); + sp40 = func_80259198(mlDiffDegF(mlNormalizeAngle(180.0f + player_getYaw()), sp48) * (temp_f20 * 1), temp_f20 * 50.0f); + sp48 = mlNormalizeAngle(sp48 + sp40); + func_80256E24(sp68, 0.0f, sp48, 0.0f, 0.0f, sp4C); + ml_vec3f_add(sp80, sp8C, sp68); + sp80[1] = sp74[1] + ((func_802BD51C() - sp74[1]) * temp_f20 * 2); + ncDynamicCamera_setPosition(sp80); + func_8025727C(sp8C[0], sp8C[1], sp8C[2], sp80[0], sp80[1], sp80[2], &sp5C[0], &sp5C[1]); + sp5C[0] = -sp5C[0]; + sp5C[2] = 0.0f; + func_802BD720(sp5C); +} diff --git a/src/core2/nc/dynamicCam10.c b/src/core2/camera/dynamicCam10.c similarity index 96% rename from src/core2/nc/dynamicCam10.c rename to src/core2/camera/dynamicCam10.c index 745b7bb67..8382589b0 100644 --- a/src/core2/nc/dynamicCam10.c +++ b/src/core2/camera/dynamicCam10.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCam11.c b/src/core2/camera/dynamicCam11.c similarity index 98% rename from src/core2/nc/dynamicCam11.c rename to src/core2/camera/dynamicCam11.c index 755caf4cb..1861a0905 100644 --- a/src/core2/nc/dynamicCam11.c +++ b/src/core2/camera/dynamicCam11.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam11.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCam12.c b/src/core2/camera/dynamicCam12.c similarity index 99% rename from src/core2/nc/dynamicCam12.c rename to src/core2/camera/dynamicCam12.c index fddad612a..4d788f602 100644 --- a/src/core2/nc/dynamicCam12.c +++ b/src/core2/camera/dynamicCam12.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam12.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCam13.c b/src/core2/camera/dynamicCam13.c similarity index 98% rename from src/core2/nc/dynamicCam13.c rename to src/core2/camera/dynamicCam13.c index 854c54545..0798d448b 100644 --- a/src/core2/nc/dynamicCam13.c +++ b/src/core2/camera/dynamicCam13.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam13.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCam3.c b/src/core2/camera/dynamicCam3.c similarity index 81% rename from src/core2/nc/dynamicCam3.c rename to src/core2/camera/dynamicCam3.c index 6c81bdf20..6d0cbc1a4 100644 --- a/src/core2/nc/dynamicCam3.c +++ b/src/core2/camera/dynamicCam3.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam3.c #include #include "functions.h" #include "variables.h" @@ -39,11 +38,11 @@ void ncDynamicCam3_update(void) { sp30 = time_getDelta(); if (sp30); ml_vec3f_diff_copy(sp40, sp64, sp7C); - sp3C = sqrtf(sp40[0]*sp40[0] + sp40[2]*sp40[2]); - sp3C += ml_clamp_abs_f(sp30*(sp34 - sp3C)*2 , sp30 * 800.0f); - ml_horizontal_and_vertical_angles(sp7C[0], sp7C[1], sp7C[2], sp64[0], sp64[1], sp64[2], &sp4C[0], &sp4C[1]); + sp3C = gu_sqrtf(sp40[0]*sp40[0] + sp40[2]*sp40[2]); + sp3C += func_80259198(sp30*(sp34 - sp3C)*2 , sp30 * 800.0f); + func_8025727C(sp7C[0], sp7C[1], sp7C[2], sp64[0], sp64[1], sp64[2], &sp4C[0], &sp4C[1]); sp40[1] = sp30 * 0.77 * mlDiffDegF(mlNormalizeAngle(player_getYaw() + 180.0f), sp4C[1]); - sp40[1] = ml_clamp_abs_f(sp40[1], sp30 * 300.0f); + sp40[1] = func_80259198(sp40[1], sp30 * 300.0f); sp4C[1] = mlNormalizeAngle(sp4C[1] + sp40[1]); func_80256E24(sp58, 0.0f, sp4C[1], 0.0f, 0.0f, sp3C); sp70[0] = sp7C[0] + sp58[0]; diff --git a/src/core2/nc/fly.c b/src/core2/camera/dynamicCam4.c similarity index 70% rename from src/core2/nc/fly.c rename to src/core2/camera/dynamicCam4.c index 8ea98dafd..8fca9dc40 100644 --- a/src/core2/nc/fly.c +++ b/src/core2/camera/dynamicCam4.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/ba/fly.c #include #include "functions.h" #include "variables.h" @@ -7,8 +6,8 @@ extern f32 player_getYaw(void); extern f32 player_getPitch(void); extern void func_802BD870(f32, f32, f32, f32); -void ncbafly_func_802BFE50(f32 arg0, f32 arg1, f32 arg2); -void ncbafly_func_802BFE74(bool); +void ncDynamicCam4_func_802BFE50(f32 arg0, f32 arg1, f32 arg2); +void ncDynamicCam4_func_802BFE74(bool); /* .bss */ f32 D_8037DB10; @@ -18,19 +17,19 @@ f32 D_8037DB1C; f32 D_8037DB20; /* .code */ -void ncbafly_init(void) { +void ncDynamicCam4_init(void) { func_802BD870(10.0f, 20.0f, 120.0f, 200.0f); if (gsworld_getMap() == MAP_90_GL_BATTLEMENTS) { - ncbafly_func_802BFE50(10.0f, 800.0f, 1350.0f); + ncDynamicCam4_func_802BFE50(10.0f, 800.0f, 1350.0f); } else { - ncbafly_func_802BFE50(2.0f, 800.0f, 350.0f); + ncDynamicCam4_func_802BFE50(2.0f, 800.0f, 350.0f); } - ncbafly_func_802BFE74(0); + ncDynamicCam4_func_802BFE74(0); } -void ncbafly_end(void){} +void ncDynamicCam4_end(void){} -void ncbafly_update(void) { +void ncDynamicCam4_update(void) { f32 sp84[3]; f32 sp78[3]; f32 sp6C[3]; @@ -58,8 +57,8 @@ void ncbafly_update(void) { ml_vec3f_diff_copy(sp48, sp6C, sp84); sp44 = gu_sqrtf(sp48[0]*sp48[0] + sp48[1]*sp48[1] + sp48[2]*sp48[2]); temp_f10 = (sp3C - sp44) * sp38; - sp44 += ml_clamp_abs_f(temp_f10 * D_8037DB10, sp38 * D_8037DB14); - ml_horizontal_and_vertical_angles(sp84[0], sp84[1], sp84[2], sp6C[0], sp6C[1], sp6C[2], &sp54[0], &sp54[1]); + sp44 += func_80259198(temp_f10 * D_8037DB10, sp38 * D_8037DB14); + func_8025727C(sp84[0], sp84[1], sp84[2], sp6C[0], sp6C[1], sp6C[2], &sp54[0], &sp54[1]); if ((sp34 > 180.0f) && (sp34 < 360.0f)) { sp34 = ml_min_f(100.0f, (f32) ((f64) (360.0f - sp34) * 1.4)); } @@ -68,27 +67,27 @@ void ncbafly_update(void) { sp48[2] = 0.0f; sp48[0] = (f32) ((f64) sp48[0] * ((f64) sp38 * 0.8)); sp48[1] = sp48[1] * (sp38 * D_8037DB1C); - sp48[0] = ml_clamp_abs_f(sp48[0], sp38 * 40.0f); - sp48[1] = ml_clamp_abs_f(sp48[1], sp38 * D_8037DB20); + sp48[0] = func_80259198(sp48[0], sp38 * 40.0f); + sp48[1] = func_80259198(sp48[1], sp38 * D_8037DB20); sp54[0] = mlNormalizeAngle(sp54[0] + sp48[0]); sp54[1] = mlNormalizeAngle(sp54[1] + sp48[1]); func_80256E24(sp60, -sp54[0], sp54[1], 0.0f, 0.0f, sp44); ml_vec3f_add(sp78, sp84, sp60); ncDynamicCamera_setPosition(sp78); - ml_horizontal_and_vertical_angles(sp84[0], sp84[1], sp84[2], sp78[0], sp78[1], sp78[2], &sp54[0], &sp54[1]); + func_8025727C(sp84[0], sp84[1], sp84[2], sp78[0], sp78[1], sp78[2], &sp54[0], &sp54[1]); sp54[0] = -sp54[0]; sp54[2] = 0.0f; func_802BD720(sp54); } -void ncbafly_func_802BFE50(f32 arg0, f32 arg1, f32 arg2){ +void ncDynamicCam4_func_802BFE50(f32 arg0, f32 arg1, f32 arg2){ D_8037DB10 = arg0; D_8037DB14 = arg1; D_8037DB18 = arg2; } -void ncbafly_func_802BFE74(bool arg0) { +void ncDynamicCam4_func_802BFE74(bool arg0) { if (arg0) { D_8037DB1C = 6.0f; D_8037DB20 = 270.0f; diff --git a/src/core2/nc/dynamicCam5.c b/src/core2/camera/dynamicCam5.c similarity index 87% rename from src/core2/nc/dynamicCam5.c rename to src/core2/camera/dynamicCam5.c index 668b3f58d..8e9875cc9 100644 --- a/src/core2/nc/dynamicCam5.c +++ b/src/core2/camera/dynamicCam5.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam5.c #include #include "functions.h" #include "variables.h" @@ -37,7 +36,7 @@ void ncDynamicCam5_update(void) { ml_vec3f_diff_copy(sp68, sp74, sp50); func_802BE190(sp68); ncDynamicCamera_getPosition(sp68); - ml_horizontal_and_vertical_angles(sp74[0], sp74[1], sp74[2], sp68[0], sp68[1], sp68[2], &sp38[0], &sp38[1]); + func_8025727C(sp74[0], sp74[1], sp74[2], sp68[0], sp68[1], sp68[2], &sp38[0], &sp38[1]); sp38[0] = -sp38[0]; sp38[2] = 0.0f; func_802BD904(sp38); diff --git a/src/core2/nc/dynamicCam8.c b/src/core2/camera/dynamicCam8.c similarity index 97% rename from src/core2/nc/dynamicCam8.c rename to src/core2/camera/dynamicCam8.c index 81df36cbc..b39d0d3ec 100644 --- a/src/core2/nc/dynamicCam8.c +++ b/src/core2/camera/dynamicCam8.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam8.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCam9.c b/src/core2/camera/dynamicCam9.c similarity index 86% rename from src/core2/nc/dynamicCam9.c rename to src/core2/camera/dynamicCam9.c index 947415fa3..99de86932 100644 --- a/src/core2/nc/dynamicCam9.c +++ b/src/core2/camera/dynamicCam9.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCam9.c #include #include "functions.h" #include "variables.h" @@ -37,7 +36,7 @@ void ncDynamicCam9_func_802C0A60(f32 arg0[3]) { f32 sp30[3]; func_802BD4C0(sp54); - ml_horizontal_and_vertical_angles(sp54[0], sp54[1], sp54[2], D_8037DBB0[0], D_8037DBB0[1], D_8037DBB0[2], &sp30[0], &sp30[1]); + func_8025727C(sp54[0], sp54[1], sp54[2], D_8037DBB0[0], D_8037DBB0[1], D_8037DBB0[2], &sp30[0], &sp30[1]); sp30[1] = mlNormalizeAngle(sp30[1] - 60.0f); func_80256E24(sp48, 0.0f, sp30[1], 0.0f, 0.0f, D_8037DBC0); ml_vec3f_add(arg0, D_8037DBB0, sp48); @@ -59,9 +58,9 @@ void ncDynamicCam9_func_802C0B70(f32 arg0[3], f32 arg1[3]) { sp3C[0] *= dt * 1.5; sp3C[1] *= dt * 1.0; sp3C[2] *= dt * 1.5; - sp3C[0] = ml_clamp_abs_f(sp3C[0], dt * 1000.0); - sp3C[1] = ml_clamp_abs_f(sp3C[1], dt * 1000.0); - sp3C[2] = ml_clamp_abs_f(sp3C[2], dt * 1000.0); + sp3C[0] = func_80259198(sp3C[0], dt * 1000.0); + sp3C[1] = func_80259198(sp3C[1], dt * 1000.0); + sp3C[2] = func_80259198(sp3C[2], dt * 1000.0); ml_vec3f_add(arg0, sp30, sp3C); ncDynamicCamera_setPosition(arg0); } @@ -79,7 +78,7 @@ void ncDynamicCam9_func_802C0C5C(f32 arg0[3], f32 arg1[3]) { ml_vec3f_scale(sp3C, ml_map_f(sp38, 0.4f, 0.75f, 0.5f, 1.0f)); ml_vec3f_add(sp54, D_8037DBB0, sp3C); sp54[1] = sp48[1] + (sp54[1] - sp48[1]) * 0.4; - ml_horizontal_and_vertical_angles(sp54[0], sp54[1], sp54[2], arg1[0], arg1[1], arg1[2], &arg0[0], &arg0[1]); + func_8025727C(sp54[0], sp54[1], sp54[2], arg1[0], arg1[1], arg1[2], &arg0[0], &arg0[1]); arg0[0] = mlNormalizeAngle(-arg0[0]); arg0[2] = 0.0f; } diff --git a/src/core2/nc/dynamicCamA.c b/src/core2/camera/dynamicCamA.c similarity index 98% rename from src/core2/nc/dynamicCamA.c rename to src/core2/camera/dynamicCamA.c index c4cc76801..08006c4c9 100644 --- a/src/core2/nc/dynamicCamA.c +++ b/src/core2/camera/dynamicCamA.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCamA.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCamB.c b/src/core2/camera/dynamicCamB.c similarity index 98% rename from src/core2/nc/dynamicCamB.c rename to src/core2/camera/dynamicCamB.c index e7a70b6a6..83bc5f4bc 100644 --- a/src/core2/nc/dynamicCamB.c +++ b/src/core2/camera/dynamicCamB.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCamB.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/nc/dynamicCamC.c b/src/core2/camera/dynamicCamC.c similarity index 91% rename from src/core2/nc/dynamicCamC.c rename to src/core2/camera/dynamicCamC.c index 338dae9ac..f31d482b1 100644 --- a/src/core2/nc/dynamicCamC.c +++ b/src/core2/camera/dynamicCamC.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCamC.c #include #include "functions.h" #include "variables.h" @@ -70,7 +69,7 @@ void ncDynamicCamC_update(void) { ncDynamicCamera_getPosition(sp54); player_getPosition(sp3C); sp3C[1] += 100.0f; - ml_horizontal_and_vertical_angles(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); + func_8025727C(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); sp48[0] = mlNormalizeAngle(-sp48[0]); func_802BD904(sp48); } diff --git a/src/core2/nc/die.c b/src/core2/camera/dynamicCamD.c similarity index 73% rename from src/core2/nc/die.c rename to src/core2/camera/dynamicCamD.c index c0d636a87..61f3413c3 100644 --- a/src/core2/nc/die.c +++ b/src/core2/camera/dynamicCamD.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/ba/die.c #include #include "functions.h" #include "variables.h" @@ -7,18 +6,18 @@ f32 D_80365D90 = 30.0f; /* .code */ -void ncbadie_init(void){ +void ncDynamicCamD_init(void){ func_802BE244(4.0f, 16.0f); func_802BE230(1.4f, 14.0f); } -void ncbadie_end(void){} +void ncDynamicCamD_end(void){} -void ncbadie_func_802BF2C0(f32 arg0){ +void ncDynamicCamD_func_802BF2C0(f32 arg0){ D_80365D90 = arg0; } -void ncbadie_update(void) { +void ncDynamicCamD_update(void) { f32 sp54[3]; f32 sp48[3]; f32 sp3C[3]; @@ -37,7 +36,7 @@ void ncbadie_update(void) { ncDynamicCamera_getPosition(sp54); player_getPosition(sp3C); sp3C[1] += D_80365D90; - ml_horizontal_and_vertical_angles(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); + func_8025727C(sp3C[0], sp3C[1], sp3C[2], sp54[0], sp54[1], sp54[2], &sp48[0], &sp48[1]); sp48[0] = mlNormalizeAngle(-sp48[0]); func_802BD904(sp48); } diff --git a/src/core2/nc/dynamicCamF.c b/src/core2/camera/dynamicCamF.c similarity index 95% rename from src/core2/nc/dynamicCamF.c rename to src/core2/camera/dynamicCamF.c index 0ec2ec401..4656ce03c 100644 --- a/src/core2/nc/dynamicCamF.c +++ b/src/core2/camera/dynamicCamF.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCamF.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/nc/dynamicCamera.c b/src/core2/camera/dynamicCamera.c similarity index 85% rename from src/core2/nc/dynamicCamera.c rename to src/core2/camera/dynamicCamera.c index e35337ede..76e27e4f5 100644 --- a/src/core2/nc/dynamicCamera.c +++ b/src/core2/camera/dynamicCamera.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/dynamicCamera.c #include #include "core1/core1.h" #include "functions.h" @@ -32,33 +31,10 @@ void func_802BD8EC(f32 arg0); f32 D_80365CD0[] = {0.0f}; f32 D_80365CD4[] = {0.0f, -25.0f, 25.0f, -50.0f, 50.0f, -80.0f, 80.0f, -120.0f, 120.0f, -140.0f, 140.0f}; f32 D_80365D00[] = {0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 120.0f, 140.0f, 160.0f, 180.0f, 200.0f, 220.0f, 240.0f, 260.0f, 280.0f, 300.0f, 320.0f, 340.0f}; - Struct_core2_356B0_0 D_80365D48 = {D_80365CD0, 1}; Struct_core2_356B0_0 D_80365D50 = {D_80365CD4, 11}; Struct_core2_356B0_0 D_80365D58 = {D_80365D00, 18}; -enum ncdynamiccamera_state_e { - NCDYNAMICCAMERA_STATE_0_NOT_INIT, - NCDYNAMICCAMERA_STATE_1_UNK, - NCDYNAMICCAMERA_STATE_2_UNK, - NCDYNAMICCAMERA_STATE_3_UNK, - NCDYNAMICCAMERA_STATE_4_UNK, - NCDYNAMICCAMERA_STATE_5_UNK, - NCDYNAMICCAMERA_STATE_6_UNK, - NCDYNAMICCAMERA_STATE_7_UNK, - NCDYNAMICCAMERA_STATE_8_UNK, - NCDYNAMICCAMERA_STATE_9_UNK, - NCDYNAMICCAMERA_STATE_A_UNK, - NCDYNAMICCAMERA_STATE_B_UNK, - NCDYNAMICCAMERA_STATE_C_UNK, - NCDYNAMICCAMERA_STATE_D_UNK, - NCDYNAMICCAMERA_STATE_E_UNK, - NCDYNAMICCAMERA_STATE_F_UNK, - NCDYNAMICCAMERA_STATE_10_UNK, - NCDYNAMICCAMERA_STATE_11_UNK, - NCDYNAMICCAMERA_STATE_12_UNK, - NCDYNAMICCAMERA_STATE_13_UNK -}; /* .bss */ s32 D_8037D940; @@ -231,7 +207,7 @@ void func_802BCBD4(void) { func_802BD870(10.0f, 10.0f, 120.0f, 120.0f); func_802BE230(1.4f, 14.0f); func_802BD840(); - ncba1p_reset(); + ncFirstPersonCamera_reset(); func_802C0120(); func_802C2258(); func_802C0F4C(); @@ -299,9 +275,8 @@ void func_802BCE94(void){ } void ncDynamicCamera_update(void){ - f32 position[3]; - f32 rotation[3]; - + f32 sp24[3]; + f32 sp18[3]; if(!cameraUpdateEnabled) return; @@ -312,73 +287,73 @@ void ncDynamicCamera_update(void){ func_802BCA58(); switch(dynamicCameraState){ - case NCDYNAMICCAMERA_STATE_1_UNK:// L802BCF3C + case 1:// L802BCF3C ncDynamicCam1_update(); func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_3_UNK:// L802BCF54 + case 3:// L802BCF54 ncDynamicCam3_update(); break; - case NCDYNAMICCAMERA_STATE_4_UNK:// L802BCF64 - ncbafly_update(); + case 4:// L802BCF64 + ncDynamicCam4_update(); func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_5_UNK:// L802BCF7C + case 5:// L802BCF7C ncDynamicCam5_update(); func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_6_UNK:// L802BCF94 + case 6:// L802BCF94 func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_8_UNK:// L802BCFA4 + case 8:// L802BCFA4 ncDynamicCam8_update(); break; - case NCDYNAMICCAMERA_STATE_9_UNK:// L802BCFB4 + case 9:// L802BCFB4 ncDynamicCam9_update(); func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_A_UNK:// L802BCFCC + case 0xA:// L802BCFCC ncDynamicCamA_update(); break; - case NCDYNAMICCAMERA_STATE_B_UNK:// L802BCFDC + case 0xB:// L802BCFDC ncDynamicCamB_update(); break; - case NCDYNAMICCAMERA_STATE_C_UNK:// L802BCFEC + case 0xC:// L802BCFEC ncDynamicCamC_update(); func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_D_UNK:// L802BD004 - ncbadie_update(); + case 0xD:// L802BD004 + ncDynamicCamD_update(); func_802BCE94(); break; - case NCDYNAMICCAMERA_STATE_F_UNK:// L802BD01C + case 0xF:// L802BD01C ncDynamicCamF_update(); break; - case NCDYNAMICCAMERA_STATE_10_UNK:// L802BD02C + case 0x10:// L802BD02C ncDynamicCam10_update(); break; - case NCDYNAMICCAMERA_STATE_11_UNK:// L802BD03C + case 0x11:// L802BD03C ncDynamicCam11_update(); break; - case NCDYNAMICCAMERA_STATE_12_UNK:// L802BD04C + case 0x12:// L802BD04C ncDynamicCam12_update(); break; - case NCDYNAMICCAMERA_STATE_13_UNK:// L802BD05C + case 0x13:// L802BD05C ncDynamicCam13_update(); break; @@ -390,14 +365,14 @@ void ncDynamicCamera_update(void){ port_modernCamera_update(); break; }//// L802BD064 - ml_vec3f_copy(position, cameraPosition); - ml_vec3f_copy(rotation, cameraRotation); - func_802C22C0(position, rotation); + ml_vec3f_copy(sp24, cameraPosition); + ml_vec3f_copy(sp18, cameraRotation); + func_802C22C0(sp24, sp18); if(dynamicCameraInFirstPerson){ - ncba1p_getPositionAndRotation(position, rotation); + ncFirstPersonCamera_getPositionAndRotation(sp24, sp18); } - viewport_setPosition_vec3f(position); - viewport_setRotation_vec3f(rotation); + viewport_setPosition_vec3f(sp24); + viewport_setRotation_vec3f(sp18); } int ncDynamicCamera_getState(void){ @@ -409,126 +384,126 @@ void ncDynamicCamera_setState(s32 state){ return; switch(dynamicCameraState){ - case NCDYNAMICCAMERA_STATE_1_UNK://L802BD114 + case 0x1://L802BD114 ncDynamicCam1_end(); break; - case NCDYNAMICCAMERA_STATE_3_UNK://L802BD124 + case 0x3://L802BD124 ncDynamicCam3_end(); break; - case NCDYNAMICCAMERA_STATE_4_UNK://L802BD134 - ncbafly_end(); + case 0x4://L802BD134 + ncDynamicCam4_end(); break; - case NCDYNAMICCAMERA_STATE_5_UNK://L802BD144 + case 0x5://L802BD144 ncDynamicCam5_end(); break; - case NCDYNAMICCAMERA_STATE_8_UNK://L802BD154 + case 0x8://L802BD154 ncDynamicCam8_end(); break; - case NCDYNAMICCAMERA_STATE_9_UNK://L802BD164 + case 0x9://L802BD164 ncDynamicCam9_end(); break; - case NCDYNAMICCAMERA_STATE_A_UNK://L802BD174 + case 0xa://L802BD174 ncDynamicCamA_end(); break; - case NCDYNAMICCAMERA_STATE_B_UNK://L802BD184 + case 0xb://L802BD184 ncDynamicCamB_end(); break; - case NCDYNAMICCAMERA_STATE_C_UNK://L802BD194 + case 0xc://L802BD194 ncDynamicCamC_end(); break; - case NCDYNAMICCAMERA_STATE_D_UNK://L802BD1A4 - ncbadie_end(); + case 0xd://L802BD1A4 + ncDynamicCamD_end(); break; - case NCDYNAMICCAMERA_STATE_F_UNK://L802BD1B4 + case 0xf://L802BD1B4 ncDynamicCamF_end(); break; - case NCDYNAMICCAMERA_STATE_10_UNK://L802BD1C4 + case 0x10://L802BD1C4 ncDynamicCam10_end(); break; - case NCDYNAMICCAMERA_STATE_11_UNK://L802BD1D4 + case 0x11://L802BD1D4 ncDynamicCam11_end(); break; - case NCDYNAMICCAMERA_STATE_12_UNK://L802BD1E4 + case 0x12://L802BD1E4 ncDynamicCam12_end(); break; - case NCDYNAMICCAMERA_STATE_13_UNK://L802BD1F4 + case 0x13://L802BD1F4 ncDynamicCam13_end(); break; }//L802BD1FC switch (state) { - case NCDYNAMICCAMERA_STATE_1_UNK: //L802BD224 + case 0x1: //L802BD224 ncDynamicCam1_init(); break; - case NCDYNAMICCAMERA_STATE_3_UNK: //L802BD234 + case 0x3: //L802BD234 ncDynamicCam3_init(); break; - case NCDYNAMICCAMERA_STATE_4_UNK: //L802BD244 - ncbafly_init(); + case 0x4: //L802BD244 + ncDynamicCam4_init(); break; - case NCDYNAMICCAMERA_STATE_5_UNK: //L802BD254 + case 0x5: //L802BD254 ncDynamicCam5_init(); break; - case NCDYNAMICCAMERA_STATE_8_UNK: //L802BD264 + case 0x8: //L802BD264 ncDynamicCam8_init(); break; - case NCDYNAMICCAMERA_STATE_9_UNK: //L802BD274 + case 0x9: //L802BD274 ncDynamicCam9_init(); break; - case NCDYNAMICCAMERA_STATE_A_UNK: //L802BD284 + case 0xa: //L802BD284 ncDynamicCamA_init(); break; - case NCDYNAMICCAMERA_STATE_B_UNK: //L802BD294 + case 0xb: //L802BD294 ncDynamicCamB_init(); break; - case NCDYNAMICCAMERA_STATE_C_UNK: //L802BD2A4 + case 0xc: //L802BD2A4 ncDynamicCamC_init(); break; - case NCDYNAMICCAMERA_STATE_D_UNK: //L802BD2B4 - ncbadie_init(); + case 0xd: //L802BD2B4 + ncDynamicCamD_init(); break; - case NCDYNAMICCAMERA_STATE_F_UNK: //L802BD2C4 + case 0xf: //L802BD2C4 ncDynamicCamF_init(); break; - case NCDYNAMICCAMERA_STATE_10_UNK: //L802BD2D4 + case 0x10: //L802BD2D4 ncDynamicCam10_init(); break; - case NCDYNAMICCAMERA_STATE_11_UNK: //L802BD2E4 + case 0x11: //L802BD2E4 ncDynamicCam11_init(); break; - case NCDYNAMICCAMERA_STATE_12_UNK: //L802BD2F4 + case 0x12: //L802BD2F4 dynamicCam12_init(); break; - case NCDYNAMICCAMERA_STATE_13_UNK: //L802BD304 + case 0x13: //L802BD304 ncDynamicCam13_init(); break; } @@ -611,8 +586,8 @@ void func_802BD610(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3, f32 arg4, f32 a sp24[1] = mlDiffDegF(arg0[1], arg1[1]); sp24[0] *= 0.003333 * D_8037D984; sp24[1] *= 0.003333 * D_8037D988; - sp24[0] = ml_clamp_abs_f(sp24[0], D_8037D98C * 0.003333); - sp24[1] = ml_clamp_abs_f(sp24[1], D_8037D990 * 0.003333); + sp24[0] = func_80259198(sp24[0], D_8037D98C * 0.003333); + sp24[1] = func_80259198(sp24[1], D_8037D990 * 0.003333); sp24[2] = 0.0f; arg1[0] = mlNormalizeAngle(arg1[0] + sp24[0]); arg1[1] = mlNormalizeAngle(arg1[1] + sp24[1]); @@ -980,7 +955,7 @@ void func_802BE720(void){ ncDynamicCamera_setState(sp34); ml_vec3f_clear(D_8037D9C8); ml_vec3f_clear(D_8037D9E0); - ncba1p_reset(); + ncFirstPersonCamera_reset(); } void func_802BE794(void){ @@ -1022,11 +997,11 @@ void func_802BE894(f32 position[3], f32 rotation[3]){ void ncDynamicCamera_enterFirstPerson(void){ dynamicCameraInFirstPerson = true; - ncba1p_setState(FIRSTPERSON_STATE_1_ENTER); - ncba1p_setZoomedOutPosition(cameraPosition); - ncba1p_setZoomedOutRotation(cameraRotation); + ncFirstPersonCamera_setState(FIRSTPERSON_STATE_1_ENTER); + ncFirstPersonCamera_setZoomedOutPosition(cameraPosition); + ncFirstPersonCamera_setZoomedOutRotation(cameraRotation); } void ncDynamicCamera_exitFirstPerson(void){ - ncba1p_setState(FIRSTPERSON_STATE_3_EXIT); + ncFirstPersonCamera_setState(FIRSTPERSON_STATE_3_EXIT); } diff --git a/src/core2/nc/1p.c b/src/core2/camera/firstpersoncamera.c similarity index 74% rename from src/core2/nc/1p.c rename to src/core2/camera/firstpersoncamera.c index 89539d0cc..1c1af0010 100644 --- a/src/core2/nc/1p.c +++ b/src/core2/camera/firstpersoncamera.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/ba/1p.c #include #include "functions.h" #include "variables.h" @@ -6,7 +5,7 @@ extern void func_802BD780(f32[3], f32[3], f32, f32, f32, f32); -void ncba1p_setState(enum nc_first_person_state state); +void ncFirstPersonCamera_setState(enum nc_first_person_state state); /* .bss */ struct{ @@ -21,11 +20,11 @@ struct{ } D_8037DC60; /* .code */ -bool __ncba1p_fullyZoomedIn(void) { +bool __ncFirstPersonCamera_fullyZoomedIn(void) { return (ml_vec3f_distance(D_8037DC60.position, D_8037DC60.zoomed_in_position) < 40.0f); } -void __ncba1p_getPositionAndRotation_entering(f32 arg0[3], f32 arg1[3]) { +void __ncFirstPersonCamera_getPositionAndRotation_entering(f32 arg0[3], f32 arg1[3]) { s32 i; ml_sub_delta_time(&D_8037DC60.transistion_timer); @@ -34,9 +33,9 @@ void __ncba1p_getPositionAndRotation_entering(f32 arg0[3], f32 arg1[3]) { D_8037DC60.rotation[i] = mlNormalizeAngle(D_8037DC60.zoomed_out_rotation[i] + func_80257CF8(D_8037DC60.transistion_timer, 0.5f, 0.0f, 0.0f, mlDiffDegF(D_8037DC60.zoomed_in_rotation[i], D_8037DC60.zoomed_out_rotation[i]))); } if (D_8037DC60.transistion_timer == 0.0f) { - ncba1p_setState(FIRSTPERSON_STATE_2_IDLE); + ncFirstPersonCamera_setState(FIRSTPERSON_STATE_2_IDLE); } - if (__ncba1p_fullyZoomedIn() && func_8028F150()) { + if (__ncFirstPersonCamera_fullyZoomedIn() && func_8028F150()) { player_setModelVisible(0); } ml_vec3f_copy(arg0, D_8037DC60.position); @@ -44,7 +43,7 @@ void __ncba1p_getPositionAndRotation_entering(f32 arg0[3], f32 arg1[3]) { } -void __ncba1p_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[3]) { +void __ncFirstPersonCamera_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[3]) { s32 i; ml_sub_delta_time(&D_8037DC60.transistion_timer); @@ -53,9 +52,9 @@ void __ncba1p_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[3]) { D_8037DC60.rotation[i] = mlNormalizeAngle(D_8037DC60.zoomed_in_rotation[i] + func_80257CF8(D_8037DC60.transistion_timer, 1.0f, 0.5f, 0.0f, mlDiffDegF(arg1[i], D_8037DC60.zoomed_in_rotation[i]))); } if (D_8037DC60.transistion_timer == 0.0f) { - ncba1p_setState(FIRSTPERSON_STATE_4_DONE); + ncFirstPersonCamera_setState(FIRSTPERSON_STATE_4_DONE); } - if (!__ncba1p_fullyZoomedIn() && !func_8028F150()) { + if (!__ncFirstPersonCamera_fullyZoomedIn() && !func_8028F150()) { player_setModelVisible(1); } ml_vec3f_copy(arg0, D_8037DC60.position); @@ -63,7 +62,7 @@ void __ncba1p_getPositionAndRotation_exiting(f32 arg0[3], f32 arg1[3]) { } -void __ncba1p_getPositionAndRotation_idle(f32 arg0[3], f32 arg1[3]) { +void __ncFirstPersonCamera_getPositionAndRotation_idle(f32 arg0[3], f32 arg1[3]) { ml_vec3f_copy(D_8037DC60.position, D_8037DC60.zoomed_in_position); func_802BD780(D_8037DC60.zoomed_in_rotation, D_8037DC60.rotation, 10.0f, 20.0f, 120.0f, 200.0f); D_8037DC60.rotation[2] = 0.0f; @@ -71,7 +70,7 @@ void __ncba1p_getPositionAndRotation_idle(f32 arg0[3], f32 arg1[3]) { ml_vec3f_copy(arg1, D_8037DC60.rotation); } -void ncba1p_reset(void){ +void ncFirstPersonCamera_reset(void){ ml_vec3f_clear(D_8037DC60.position); ml_vec3f_clear(D_8037DC60.rotation); ml_vec3f_clear(D_8037DC60.zoomed_in_position); @@ -81,23 +80,23 @@ void ncba1p_reset(void){ D_8037DC60.state = 0; } -void ncba1p_getPositionAndRotation(f32 position[3], f32 rotation[3]) { +void ncFirstPersonCamera_getPositionAndRotation(f32 position[3], f32 rotation[3]) { switch (D_8037DC60.state) { case FIRSTPERSON_STATE_1_ENTER: - __ncba1p_getPositionAndRotation_entering(position, rotation); + __ncFirstPersonCamera_getPositionAndRotation_entering(position, rotation); break; case FIRSTPERSON_STATE_2_IDLE: - __ncba1p_getPositionAndRotation_idle(position, rotation); + __ncFirstPersonCamera_getPositionAndRotation_idle(position, rotation); break; case FIRSTPERSON_STATE_3_EXIT: - __ncba1p_getPositionAndRotation_exiting(position, rotation); + __ncFirstPersonCamera_getPositionAndRotation_exiting(position, rotation); /* fallthrough */ case FIRSTPERSON_STATE_4_DONE: break; } } -void ncba1p_setState(enum nc_first_person_state next_state) { +void ncFirstPersonCamera_setState(enum nc_first_person_state next_state) { if (next_state == FIRSTPERSON_STATE_1_ENTER) { if (D_8037DC60.state == FIRSTPERSON_STATE_3_EXIT) { ml_vec3f_copy(D_8037DC60.zoomed_out_position, D_8037DC60.position); @@ -116,20 +115,20 @@ void ncba1p_setState(enum nc_first_person_state next_state) { D_8037DC60.state = next_state; } -void ncba1p_setZoomedOutPosition(f32 src[3]){ +void ncFirstPersonCamera_setZoomedOutPosition(f32 src[3]){ ml_vec3f_copy(D_8037DC60.zoomed_in_position, src); } -void ncba1p_setZoomedOutRotation(f32 src[3]){ +void ncFirstPersonCamera_setZoomedOutRotation(f32 src[3]){ D_8037DC60.zoomed_in_rotation[0] = mlNormalizeAngle(src[0]); D_8037DC60.zoomed_in_rotation[1] = mlNormalizeAngle(src[1]); D_8037DC60.zoomed_in_rotation[2] = mlNormalizeAngle(src[2]); } -void ncba1p_getZoomedInRotation(f32 dst[3]){ +void ncFirstPersonCamera_getZoomedInRotation(f32 dst[3]){ ml_vec3f_copy(dst, D_8037DC60.zoomed_in_rotation); } -s32 ncba1p_getState(void){ +s32 ncFirstPersonCamera_getState(void){ return D_8037DC60.state; } diff --git a/src/core2/nc/randomCamera.c b/src/core2/camera/randomCamera.c similarity index 97% rename from src/core2/nc/randomCamera.c rename to src/core2/camera/randomCamera.c index 7916a5c10..36ddf5871 100644 --- a/src/core2/nc/randomCamera.c +++ b/src/core2/camera/randomCamera.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/randomCamera.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/nc/staticCamera.c b/src/core2/camera/staticCamera.c similarity index 96% rename from src/core2/nc/staticCamera.c rename to src/core2/camera/staticCamera.c index 58e88e284..f62fb0147 100644 --- a/src/core2/nc/staticCamera.c +++ b/src/core2/camera/staticCamera.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/nc/staticCamera.c #include #include "core1/core1.h" #include "functions.h" @@ -20,7 +19,7 @@ void ncStaticCamera_init(void){ void ncStaticCamera_end(void){} void ncStaticCamera_rotateToTarget(f32 target[3]){ - ml_horizontal_and_vertical_angles( + func_8025727C( target[0], target[1], target[2], ncStaticCameraPosition[0], ncStaticCameraPosition[1], ncStaticCameraPosition[2], &ncStaticCameraRotation[0], &ncStaticCameraRotation[1] diff --git a/src/core2/ch/beehive.c b/src/core2/ch/beehive.c index 4f4037470..c54111705 100644 --- a/src/core2/ch/beehive.c +++ b/src/core2/ch/beehive.c @@ -34,8 +34,8 @@ void chBeehive_die(ActorMarker *this, ActorMarker *other){ __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_4C_STEAM, reinterpret_cast(s32, actor->position[0]), reinterpret_cast(s32, actor->position[1]), reinterpret_cast(s32, actor->position[2])); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_4A_WOOD_EXPLOSION, reinterpret_cast(s32, actor->position[0]), reinterpret_cast(s32, actor->position[1]), reinterpret_cast(s32, actor->position[2])); actor->marker->propPtr->unk8_3 = 0; - func_803115C4(VER_SELECT(ASSET_D96_DIALOG_BEEHIVE_MEET, 0x0A14, 0, 0)); - func_803115C4(VER_SELECT(ASSET_DA6_DIALOG_BEEHIVE_WITH_BEES, 0x0A24, 0, 0)); + func_803115C4(ASSET_D96_DIALOG_BEEHIVE_MEET); + func_803115C4(ASSET_DA6_DIALOG_BEEHIVE_WITH_BEES); } void chBeehive_update(Actor *this){ @@ -62,7 +62,7 @@ void chBeehive_update(Actor *this){ ){ if(player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT){ if( player_getTransformation() == TRANSFORM_1_BANJO - && gcdialog_showDialog(VER_SELECT(ASSET_D96_DIALOG_BEEHIVE_MEET, 0xA14, 0, 0), 0, NULL, NULL, NULL, 0) + && gcdialog_showDialog(ASSET_D96_DIALOG_BEEHIVE_MEET, 0, NULL, NULL, NULL, 0) ){ fileProgressFlag_set(FILEPROG_D_BEEHIVE_TEXT, 1); } diff --git a/src/core2/ch/beeswarm.c b/src/core2/ch/beeswarm.c index a45d072ca..40ccdb12b 100644 --- a/src/core2/ch/beeswarm.c +++ b/src/core2/ch/beeswarm.c @@ -1,6 +1,8 @@ #include #include "functions.h" #include "variables.h" + +#include "core2/quiz_storage.h" #include "port/Interpolation/FrameInterpolation.h" extern void func_8030DBFC(u32, f32, f32, f32); @@ -37,7 +39,7 @@ Actor *chBeeSwarm_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); /* .data */ -ActorInfo chBeeSwarm = { +ActorInfo D_80367310 = { MARKER_217_BEE_SWARM, ACTOR_34D_BEE_SWARM, ASSET_49E_SPRITE_BEE_SWARM, 1, NULL, chBeeSwarm_update, NULL, chBeeSwarm_draw, @@ -223,7 +225,7 @@ void chBeeSwarm_802CF1C8(f32 arg0[3], f32 arg1[3], f32 arg2[3], f32 arg3, f32 ar } if (arg5 != 0) { sp3C[0] = sp3C[1] = sp3C[2] = 0.0f; - ml_horizontal_and_vertical_angles(arg2[0], arg2[1], arg2[2], sp3C[0], sp3C[1], sp3C[2], arg5, arg5 + 1); + func_8025727C(arg2[0], arg2[1], arg2[2], sp3C[0], sp3C[1], sp3C[2], arg5, arg5 + 1); } } @@ -449,7 +451,7 @@ void chBeeSwarm_update(Actor *this) { if (!fileProgressFlag_get(FILEPROG_8F_MET_BEE_INFESTED_BEEHIVE) && subaddie_playerIsWithinCylinder(this, 250, 300) && ((player_movementGroup() == BSGROUP_0_NONE) || (player_movementGroup() == BSGROUP_8_TROT)) && (player_getTransformation() == TRANSFORM_1_BANJO) - && (gcdialog_showDialog(VER_SELECT(0xDA6, 0xA24, 0, 0), 0, NULL, NULL, NULL, NULL) != 0) + && (gcdialog_showDialog(0xDA6, 0, NULL, NULL, NULL, NULL) != 0) ) { fileProgressFlag_set(FILEPROG_8F_MET_BEE_INFESTED_BEEHIVE, true); } diff --git a/src/core2/ch/bottlesbonus.c b/src/core2/ch/bottlesbonus.c index f24b279ee..be20b6560 100644 --- a/src/core2/ch/bottlesbonus.c +++ b/src/core2/ch/bottlesbonus.c @@ -51,21 +51,20 @@ typedef struct{ extern void actor_postdrawMethod(ActorMarker *); extern void viewport_setNearAndFar(f32, f32); -extern s16 *picturebox_getColorBuffer(void); - +extern s16 *func_8030C704(void); Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chBottlesBonus_update(Actor *this); /* .data */ Struct_core2_560F0_0 D_803681A0[] = { { 0, 0x000, 0, 0x211}, - {99, VER_SELECT(0xE27, 0xA69, 0, 0), 0, 0x2C1}, - {99, VER_SELECT(0xE29, 0xA6B, 0, 0), 0, 0x2C2}, - {99, VER_SELECT(0xE2B, 0xA6D, 0, 0), 0, 0x2C9}, - {99, VER_SELECT(0xE2D, 0xA6F, 0, 0), 0, 0x2C3}, - {99, VER_SELECT(0xE2F, 0xA71, 0, 0), 0, 0x2C4}, - {99, VER_SELECT(0xE31, 0xA73, 0, 0), 0, 0x2C5}, - {75, VER_SELECT(0xE34, 0xA76, 0, 0), 0, 0x007} + {99, 0xE27, 0, 0x2C1}, + {99, 0xE29, 0, 0x2C2}, + {99, 0xE2B, 0, 0x2C9}, + {99, 0xE2D, 0, 0x2C3}, + {99, 0xE2F, 0, 0x2C4}, + {99, 0xE31, 0, 0x2C5}, + {75, 0xE34, 0, 0x007} }; ActorAnimationInfo chBottlesBonusAnimations[] ={ @@ -158,7 +157,7 @@ Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) void *sp50; sp6C = marker_getActor(marker); - sp50 = picturebox_getColorBuffer(); //grabs frame as texture? + sp50 = func_8030C704(); //grabs frame as texture? if ((sp50 == NULL) || (getGameMode() != GAME_MODE_8_BOTTLES_BONUS)) return sp6C; @@ -172,9 +171,9 @@ Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) gDPSetTextureFilter((*gfx)++, G_TF_BILERP); gDPSetColorDither((*gfx)++, G_CD_DISABLE); func_802DF160(gfx, mtx, vtx); - depthbuffer_clear(gfx); - - gDPSetTextureFilter((*gfx)++, G_TF_POINT); + func_80253190(gfx); + + gDPSetTextureFilter((*gfx)++, G_TF_BILERP); gSPSegment((*gfx)++, 0x04, osVirtualToPhysical(sp50)); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)sp6C); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); diff --git a/src/core2/ch/bottlesbonuscursor.c b/src/core2/ch/bottlesbonuscursor.c index 4b37d33a9..5e328b2c0 100644 --- a/src/core2/ch/bottlesbonuscursor.c +++ b/src/core2/ch/bottlesbonuscursor.c @@ -37,25 +37,25 @@ void chBottlesBonusCursor_func_802DF99C(void); void chBottlesBonusCursor_update(Actor *this); /* .data */ -ActorAnimationInfo chBottlesBonusCursorAnimations[] = { +ActorAnimationInfo D_803683B0[] = { {0x000, 0.0f}, - {ASSET_2A2_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 1.0f}, - {ASSET_2A5_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 1.0f}, - {ASSET_2A4_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.4f}, - {ASSET_2A3_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.4f}, - {ASSET_2A1_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.3f}, - {ASSET_2A7_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.4f}, - {ASSET_2A1_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 0.3f}, - {ASSET_2A6_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 2.6f}, - {ASSET_2A8_ANIM_BOTTLES_BONUS_CURSOR_UNKNOWN, 2.6f} + {0x2A2, 1.0f}, + {0x2A5, 1.0f}, + {0x2A4, 0.4f}, + {0x2A3, 0.4f}, + {0x2A1, 0.3f}, + {0x2A7, 0.4f}, + {0x2A1, 0.3f}, + {0x2A6, 2.6f}, + {0x2A8, 2.6f} }; f32 D_80368400[3] = {570.0f, 328.9f, -186.4f}; f32 D_8036840C[3] = {-11.28f, 3.92f, -52.96f}; -ActorInfo chBottlesBonusCursor = { - MARKER_17A_BOTTLES_BONUS_BANJO_HAND, ACTOR_2B4_BOTTLES_BONUS_BANJO_HAND, ASSET_565_MODEL_BOTTLES_BONUS_BANJO_HAND, - 0x1, chBottlesBonusCursorAnimations, +ActorInfo D_80368418 = { + 0x17A, 0x2B4, 0x565, + 0x1, D_803683B0, chBottlesBonusCursor_update, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 }; @@ -65,7 +65,6 @@ ActorMarker *chBottlesBonusCursorMarker; f32 D_8037E068[60][2]; Struct_core2_584D0_0 D_8037E248[20]; //puzzle pieces s32 D_8037E5B8; - struct { s32 unk0; u8 pad4[0xC]; @@ -77,7 +76,6 @@ struct { f32 unk28; f32 unk2C; } D_8037E5C0; - f32 D_8037E5F0; f32 D_8037E5F4; f32 D_8037E5F8[3]; @@ -154,7 +152,7 @@ void chBottlesBonusCursor_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { actor_setOpacity(this, 0xB9); viewport_func_8024E030(this->position, D_8037E5C0.unk18); sp3C = (this->scale * 650.0f); - depthbuffer_clearRegion(gfx, + func_80253208(gfx, (s32)(D_8037E5C0.unk18[0] - sp3C/2), (s32)(D_8037E5C0.unk18[1] - sp3C/2), (s32)sp3C, (s32)sp3C, gFramebuffers[getActiveFramebuffer()] diff --git a/src/core2/ch/climbBase.c b/src/core2/ch/climb_base.c similarity index 95% rename from src/core2/ch/climbBase.c rename to src/core2/ch/climb_base.c index a3e561bac..5b3f87c66 100644 --- a/src/core2/ch/climbBase.c +++ b/src/core2/ch/climb_base.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/climbBase.c #include #include "functions.h" #include "variables.h" @@ -13,8 +12,8 @@ typedef struct { }ActorLocal_climbBase; /* .data */ -ActorInfo D_80367B20 = { - MARKER_35_CLIMB_BASE, ACTOR_26_CLIMB_BASE, 0x0, +ActorInfo D_80367B20 = { + 0x35, 0x26, 0x0, 0x1, NULL, func_802D77D4, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 diff --git a/src/core2/ch/clucker.c b/src/core2/ch/clucker.c index 3c3953bb7..d3b77877a 100644 --- a/src/core2/ch/clucker.c +++ b/src/core2/ch/clucker.c @@ -2,7 +2,7 @@ #include "functions.h" #include "variables.h" -extern void modelRender_setAppendageVisibility(s32, s32); +extern void func_8033A45C(s32, s32); typedef struct{ u8 unk0; @@ -118,8 +118,8 @@ void chClucker_die(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *chClucker_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this = marker_getActor(marker); - modelRender_setAppendageVisibility(3, (this->state == 5)? 1 : 0); - modelRender_setAppendageVisibility(4, (this->state == 0 || this->state == 1 || this->state == 6)? 0 : 1); + func_8033A45C(3, (this->state == 5)? 1 : 0); + func_8033A45C(4, (this->state == 0 || this->state == 1 || this->state == 6)? 0 : 1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/core2/ch/collectible.c b/src/core2/ch/collectible.c index f31cf7f09..9d6aafa1f 100644 --- a/src/core2/ch/collectible.c +++ b/src/core2/ch/collectible.c @@ -10,21 +10,21 @@ Actor *chCollectible_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); void chCollectible_update(Actor *this); /* .data */ -extern ActorInfo chBlueEgg = { +extern ActorInfo D_80367D00 = { MARKER_60_BLUE_EGG_COLLECTIBLE, ACTOR_52_BLUE_EGG, ASSET_36D_SPRITE_BLUE_EGG, 0, NULL, chCollectible_update, actor_update_func_80326224, chCollectible_draw, 0, 0, 0.7f, 0 }; -extern ActorInfo chRedFeather = { +extern ActorInfo D_80367D24 = { MARKER_B5_RED_FEATHER_COLLECTIBLE, ACTOR_129_RED_FEATHER, ASSET_580_SPRITE_RED_FEATHER, 0, NULL, chCollectible_update, actor_update_func_80326224, chCollectible_draw, 0, 0, 0.5f, 0 }; -extern ActorInfo chGoldFeather = { +extern ActorInfo D_80367D48 = { MARKER_1E5_GOLD_FEATHER_COLLECTIBLE, ACTOR_370_GOLD_FEATHER, ASSET_6D1_SPRITE_GOLDFEATHER, 0, NULL, chCollectible_update, actor_update_func_80326224, chCollectible_draw, @@ -99,7 +99,7 @@ s32 chCollectible_collectEgg(ActorProp *arg0){ if(arg0->isActorProp) actPtr = marker_getActor(arg0->marker); } - chCollectible_collectItem(actPtr, FILEPROG_5_BLUE_EGG_TEXT, VER_SELECT(0xD9E, 0xA1C, 0, 0), COMUSIC_C_EGG_COLLECTED, 0xD, 2.0f); + return chCollectible_collectItem(actPtr, FILEPROG_5_BLUE_EGG_TEXT, 0xD9E, COMUSIC_C_EGG_COLLECTED, 0xD, 2.0f); } bool chCollectible_collectRedFeather(ActorProp *arg0){ @@ -107,7 +107,7 @@ bool chCollectible_collectRedFeather(ActorProp *arg0){ fxSparkle_redFeather(&arg0->x); if(arg0->isActorProp) actPtr = marker_getActor(arg0->marker); - chCollectible_collectItem(actPtr, FILEPROG_6_RED_FEATHER_TEXT, VER_SELECT(0xD9F, 0xA1D, 0, 0), COMUSIC_B_RED_FEATHER_COLLECTED, 0xF, 4.0f); + return chCollectible_collectItem(actPtr, FILEPROG_6_RED_FEATHER_TEXT, 0xD9F, COMUSIC_B_RED_FEATHER_COLLECTED, 0xF, 4.0f); } bool chCollectible_collectGoldFeather(ActorProp *arg0){ @@ -115,7 +115,7 @@ bool chCollectible_collectGoldFeather(ActorProp *arg0){ fxSparkle_goldFeather(&arg0->x); if(arg0->isActorProp) actPtr = marker_getActor(arg0->marker); - chCollectible_collectItem(actPtr, FILEPROG_7_GOLD_FEATHER_TEXT, VER_SELECT(0xDA0, 0xA1E, 0, 0), COMUSIC_14_GOLD_FEATHER_COLLECTED, ITEM_10_GOLD_FEATHER, 6.0f); + return chCollectible_collectItem(actPtr, FILEPROG_7_GOLD_FEATHER_TEXT, 0xDA0, COMUSIC_14_GOLD_FEATHER_COLLECTED, ITEM_10_GOLD_FEATHER, 6.0f); } Actor *chCollectible_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3){ diff --git a/src/core2/ch/crab.c b/src/core2/ch/crab.c index 6e253cb25..a2193fdfe 100644 --- a/src/core2/ch/crab.c +++ b/src/core2/ch/crab.c @@ -1,47 +1,32 @@ -// BanjoDecomp: core2/ch/crab.c #include #include "functions.h" #include "variables.h" /* .data */ - -enum crab_states -{ - CRAB_STATE_1_IDLE_UNK = 1, - CRAB_STATE_2_IDLE_UNK, - CRAB_STATE_3_TURN_TO_PLAYER, - CRAB_STATE_4_CHASE_PLAYER, - CRAB_STATE_5_UPSIDE_DOWN, - CRAB_STATE_6_FLIP_UPSIDE_DOWN, - CRAB_STATE_7_FLIP_UPRIGHT, - CRAB_STATE_8_MUTIES_FIRST_DIALOG, - CRAB_STATE_9_MUTIES_REVISIT -}; - ActorAnimationInfo chCrabAnimations[] ={ { 0, 0.0f}, - { ASSET_1DA_ANIM_CRAB_IDLE, 0.8f}, - { ASSET_2C_ANIM_CRAB_WALK, 2.0f}, - { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, - { ASSET_2C_ANIM_CRAB_WALK, 0.7f}, - { ASSET_96_ANIM_CRAB_UPSIDEDOWN, 0.5f}, + { ASSET_1DA_ANIM_CRAB_IDLE, 0.8f}, + { ASSET_2C_ANIM_CRAB_WALK, 2.0f}, + { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, + { ASSET_2C_ANIM_CRAB_WALK, 0.7f}, + { ASSET_96_ANIM_CRAB_UPSIDEDOWN, 0.5f}, { ASSET_97_ANIM_CRAB_FLIP_UPSIDEDOWN, 0.8f}, - { ASSET_155_ANIM_CRAB_FLIP_UPRIGHT, 0.55f}, - { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, - { ASSET_2C_ANIM_CRAB_WALK, 4.0f} + { ASSET_155_ANIM_CRAB_FLIP_UPRIGHT, 0.55f}, + { ASSET_2C_ANIM_CRAB_WALK, 1.4f}, + { ASSET_2C_ANIM_CRAB_WALK, 4.0f} }; ActorAnimationInfo chCrabMutantAnimations[] = { {0x000, 0.0f}, - {ASSET_1DB_ANIM_MUTANT_CRAB_IDLE, 0.8f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 0.7f}, - {ASSET_158_ANIM_MUTANT_CRAB_UPSIDEDOWN, 0.5f}, + {ASSET_1DB_ANIM_MUTANT_CRAB_IDLE, 0.8f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 0.7f}, + {ASSET_158_ANIM_MUTANT_CRAB_UPSIDEDOWN, 0.5f}, {ASSET_157_ANIM_MUTANT_CRAB_FLIP_UPSIDEDOWN, 0.8f}, - {ASSET_159_ANIM_MUTANT_CRAB_UPRIGHT, 0.55f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, - {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f} + {ASSET_159_ANIM_MUTANT_CRAB_UPRIGHT, 0.55f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 1.4f}, + {ASSET_156_ANIM_MUTANT_CRAB_WALK, 2.0f} }; /* .code */ @@ -59,18 +44,18 @@ void __chCrab_802CB078(Actor *this) { return; } else{ - if( subaddie_playerIsWithinSphereAndActive(this, 1500) + if( subaddie_playerIsWithinSphereAndActive(this, 1500) && ( (this->modelCacheIndex == ACTOR_F2_BLACK_SNIPPET) || func_803292E0(this)) ) { this->actor_specific_1_f = 0.0f; - subaddie_set_state(this, CRAB_STATE_3_TURN_TO_PLAYER); + subaddie_set_state(this, 3U); } } } } void __chCrab_802CB140(Actor *this) { - subaddie_set_state(this, CRAB_STATE_2_IDLE_UNK); + subaddie_set_state(this, 2U); __chCrab_802CB040(this); func_80328CEC(this, (s32) this->yaw_ideal, 135, 175); this->unk38_31 = 150; @@ -80,10 +65,10 @@ void __chCrab_touch(ActorMarker *marker, ActorMarker *other){ Actor *this; this = marker_getActor(marker); - if ((this->state == CRAB_STATE_4_CHASE_PLAYER) && func_803294F0(this, 80, subaddie_getYawToPlayer(this))) { + if ((this->state == 4) && func_803294F0(this, 80, subaddie_getYawToPlayer(this))) { sfx_playFadeShorthandDefault(SFX_1E_HITTING_AN_ENEMY_2, 1.0f, 28000, this->position, 950, 1900); __chCrab_802CB140(this); - subaddie_set_state(this, CRAB_STATE_1_IDLE_UNK); + subaddie_set_state(this, 1); } } @@ -92,7 +77,7 @@ void __chCrab_ow(ActorMarker *marker, ActorMarker *other) { this = marker_getActor(marker); this->lifetime_value = 3.0f; - subaddie_set_state(this, CRAB_STATE_6_FLIP_UPSIDE_DOWN); + subaddie_set_state(this, 6); actor_playAnimationOnce(this); if (marker->id == MARKER_13_SNIPPET) { sfx_playFadeShorthandDefault(SFX_6E_VILE_EGH, 2.0f, 26000, this->position, 950, 1900); @@ -157,7 +142,7 @@ void __chCrab_spawn_mutant_crab_jiggy(void) { } void __chCrab_mutantTextCallback(ActorMarker *caller, enum asset_e text_id, s32 model_id){ - if (text_id == VER_SELECT(ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT, 0xA06, 0, 0)) { + if (text_id == ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT) { func_80324E38(0.0f, 3); timed_setStaticCameraToNode(0.0f, 4); timedFunc_set_0(0.1f, __chCrab_spawn_mutant_crab_jiggy); @@ -165,17 +150,17 @@ void __chCrab_mutantTextCallback(ActorMarker *caller, enum asset_e text_id, s32 func_80324E38(3.0f, 0); return; } - levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, FALSE); + levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, false); } -bool __chCrab_802CB76C(ActorMarker *marker, ActorMarker *other) { +s32 __chCrab_802CB76C(ActorMarker *marker, ActorMarker *other) { Actor *this; this = marker_getActor(marker); if ((this->modelCacheIndex == ACTOR_F2_BLACK_SNIPPET) && !maCastle_hasBanjoKazooieCodeBeenEntered()) { - return FALSE; + return false; } - return TRUE; + return true; } void __chCrab_die(ActorMarker *marker, ActorMarker *other){ @@ -194,7 +179,7 @@ void __chCrab_die(ActorMarker *marker, ActorMarker *other){ sfx_playFadeShorthandDefault(SFX_79_TICKER_DEATH, 1.0f, 28000, this->position, 950, 1900); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_f32, ACTOR_4C_STEAM, reinterpret_cast(s32, this->position[0]), reinterpret_cast(s32, this->position[1]), reinterpret_cast(s32, this->position[2])); this->lifetime_value = 5.0f; - marker->collidable = FALSE; + marker->collidable = false; this->unk138_27 = 1; marker_despawn(marker); if( gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN @@ -207,7 +192,7 @@ void __chCrab_die(ActorMarker *marker, ActorMarker *other){ jiggy_spawn_position[1] = 3812.0f; jiggy_spawn_position[2] = 0.0f; coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - func_80324DBC(2.25f, VER_SELECT(ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT, 0xA06, 0, 0), 0xF, jiggy_spawn_position, NULL, __chCrab_mutantTextCallback, NULL); + func_80324DBC(2.25f, ASSET_D33_DIALOG_MUTANT_CRAB_DEFEAT, 0xF, jiggy_spawn_position, NULL, __chCrab_mutantTextCallback, NULL); } } p_ctrl = partEmitMgr_newEmitter(2); @@ -250,10 +235,10 @@ void chCrab_update(Actor *this) { is_mutant_snippet = this->modelCacheIndex == ACTOR_F5_MUTIE_SNIPPET; if (!this->volatile_initialized) { marker_setCollisionScripts(this->marker, __chCrab_touch, __chCrab_ow, __chCrab_die); - func_803300C0(this->marker, (s32 (*)(ActorMarker *, ActorMarker *)) &__chCrab_802CB76C); // [port] bool/s32 fn-ptr cast - this->unk124_0 = this->unk138_31 = FALSE; - this->has_met_before = FALSE; - this->volatile_initialized = TRUE; + func_803300C0(this->marker, &__chCrab_802CB76C); + this->unk124_0 = this->unk138_31 = false; + this->has_met_before = false; + this->volatile_initialized = true; anctrl_setTransitionDuration(this->anctrl, 0.25f); if (gsworld_getMap() == MAP_A_TTC_SANDCASTLE) { if (!jiggyscore_isCollected(JIGGY_10_TTC_SANDCASTLE)) { @@ -282,11 +267,11 @@ void chCrab_update(Actor *this) { && subaddie_playerIsWithinSphereAndActive(this, 500) && !subaddie_playerIsWithinSphereAndActive(this, 200) && !player_movementGroup() ) { - if ((this->state != CRAB_STATE_6_FLIP_UPSIDE_DOWN) && (this->state != CRAB_STATE_5_UPSIDE_DOWN)) { - gcdialog_showDialog(VER_SELECT(ASSET_D32_DIALOG_MUTANT_CRAB_MEET, 0xA05, 0, 0), 0xF, this->position, NULL, __chCrab_mutantTextCallback, NULL); - mapSpecificFlags_set(0, TRUE); - levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, TRUE); - this->has_met_before = TRUE; + if ((this->state != 6) && (this->state != 5)) { + gcdialog_showDialog(ASSET_D32_DIALOG_MUTANT_CRAB_MEET, 0xF, this->position, NULL, __chCrab_mutantTextCallback, NULL); + mapSpecificFlags_set(0, true); + levelSpecificFlags_set(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS, true); + this->has_met_before = true; } } if (gsworld_getMap() == MAP_A_TTC_SANDCASTLE) { @@ -296,66 +281,66 @@ void chCrab_update(Actor *this) { && !jiggyscore_isCollected(JIGGY_10_TTC_SANDCASTLE) && subaddie_playerIsWithinSphereAndActive(this, 1600) ) { - gcdialog_showDialog(VER_SELECT(ASSET_A12_DIALOG_BLACK_SNIPPET_SPAWNED, 0x912, 0, 0), 4, this->position, NULL, NULL, NULL); - mapSpecificFlags_set(0, TRUE); + gcdialog_showDialog(ASSET_A12_DIALOG_BLACK_SNIPPET_SPAWNED, 4, this->position, NULL, NULL, NULL); + mapSpecificFlags_set(0, true); } else if (mapSpecificFlags_get(1)) { - gcdialog_showDialog(VER_SELECT(ASSET_A13_DIALOG_BLACK_SNIPPET_DEFEATED, 0x913, 0, 0), 4, this->position, NULL, NULL, NULL); - mapSpecificFlags_set(1, FALSE); + gcdialog_showDialog(ASSET_A13_DIALOG_BLACK_SNIPPET_DEFEATED, 4, this->position, NULL, NULL, NULL); + mapSpecificFlags_set(1, false); } } if (levelSpecificFlags_get(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS)) { - if ((this->state != CRAB_STATE_8_MUTIES_FIRST_DIALOG) && (this->state != CRAB_STATE_9_MUTIES_REVISIT)) { - subaddie_set_state_with_direction(this, (this->has_met_before) ? CRAB_STATE_8_MUTIES_FIRST_DIALOG : CRAB_STATE_9_MUTIES_REVISIT, 0.0f, 1); - this->has_met_before = FALSE; + if ((this->state != 8) && (this->state != 9)) { + subaddie_set_state_with_direction(this, (this->has_met_before) ? 8 : 9, 0.0f, 1); + this->has_met_before = false; } } switch(this->state){ - case CRAB_STATE_1_IDLE_UNK: //L802CBE30 - if (subaddie_maybe_set_state(this, CRAB_STATE_2_IDLE_UNK, 0.03f)) { + case 1: //L802CBE30 + if (subaddie_maybe_set_state(this, 2, 0.03f)) { __chCrab_802CB040(this); } __chCrab_802CB078(this); break; - case CRAB_STATE_9_MUTIES_REVISIT: //L802CBE6C + case 9: //L802CBE6C if (!levelSpecificFlags_get(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS)) { - subaddie_set_state_with_direction(this, CRAB_STATE_3_TURN_TO_PLAYER, 0.0f, 1); + subaddie_set_state_with_direction(this, 3, 0.0f, 1); } break; - case CRAB_STATE_2_IDLE_UNK: //L802CBE9C + case 2: //L802CBE9C subaddie_turnToYaw(this, 1.0f); if( func_8032CA80(this, (this->modelCacheIndex == ACTOR_F2_BLACK_SNIPPET)? 0xD: 0) && func_80329480(this) ) { func_80328CEC(this, (s32) this->yaw, 90, 150); } - subaddie_maybe_set_state_position_direction(this, CRAB_STATE_1_IDLE_UNK, 0.0f, 1, 0.0075f); + subaddie_maybe_set_state_position_direction(this, 1, 0.0f, 1, 0.0075f); __chCrab_802CB078(this); break; - case CRAB_STATE_3_TURN_TO_PLAYER: //L802CBF44 + case 3: //L802CBF44 this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); if (func_80329480(this)) { - subaddie_set_state(this, CRAB_STATE_4_CHASE_PLAYER); + subaddie_set_state(this, 4); this->actor_specific_1_f = 12.0f; } break; - case CRAB_STATE_8_MUTIES_FIRST_DIALOG: //L802CBF9C + case 8: //L802CBF9C this->yaw_ideal = subaddie_getYawToPlayer(this) + 90.0; subaddie_turnToYaw(this, 4.0f); if (func_80329480(this)) { - subaddie_set_state(this, CRAB_STATE_9_MUTIES_REVISIT); + subaddie_set_state(this, 9); this->actor_specific_1_f = 12.0f; } else if (!levelSpecificFlags_get(LEVEL_FLAG_E_CC_MUTIE_SNIPPETS)) { - subaddie_set_state_with_direction(this, CRAB_STATE_3_TURN_TO_PLAYER, 0.0f, 1); + subaddie_set_state_with_direction(this, 3, 0.0f, 1); } break; - case CRAB_STATE_4_CHASE_PLAYER: //L802CC024 + case 4: //L802CC024 if ((globalTimer_getTime() & 0xF) == 9) { this->yaw_ideal = (f32) subaddie_getYawToPlayer(this); } @@ -365,12 +350,12 @@ void chCrab_update(Actor *this) { } break; - case CRAB_STATE_5_UPSIDE_DOWN: //L802CC0AC + case 5: //L802CC0AC this->lifetime_value = MAX(0.0, this->lifetime_value - sp30); if (this->lifetime_value == 0.0f) { - subaddie_set_state(this, CRAB_STATE_7_FLIP_UPRIGHT); + subaddie_set_state(this, 7); actor_playAnimationOnce(this); - if (this->marker->id == MARKER_16B_SNIPPET_UPSIDEDOWN) { + if (this->marker->id == 0x16B) { this->marker->id = MARKER_13_SNIPPET; } if (this->marker->id == MARKER_DE_BLACK_SNIPPET_UPSIDEDOWN) { @@ -379,26 +364,26 @@ void chCrab_update(Actor *this) { } break; - case CRAB_STATE_6_FLIP_UPSIDE_DOWN: //L802CC18C + case 6: //L802CC18C if (anctrl_isStopped(this->anctrl)) { if (this->lifetime_value == 0.0f) { func_80326310(this); } else { - subaddie_set_state(this, CRAB_STATE_5_UPSIDE_DOWN); + subaddie_set_state(this, 5); actor_loopAnimation(this); } } break; - case CRAB_STATE_7_FLIP_UPRIGHT: //L802CC1E8 + case 7: //L802CC1E8 if (anctrl_isStopped(this->anctrl)) { - subaddie_set_state(this, CRAB_STATE_1_IDLE_UNK); + subaddie_set_state(this, 1); actor_loopAnimation(this); } break; } - if ((this->state == CRAB_STATE_2_IDLE_UNK) || (this->state == CRAB_STATE_3_TURN_TO_PLAYER) || (this->state == CRAB_STATE_4_CHASE_PLAYER)) { + if ((this->state == 2) || (this->state == 3) || (this->state == 4)) { if (sp34 != D_803670B0) { D_803670B0 = sp34; D_803670B4 = 1; @@ -412,24 +397,6 @@ void chCrab_update(Actor *this) { } /* .data */ - -ActorInfo chSnippet = { - MARKER_13_SNIPPET, ACTOR_67_SNIPPET, ASSET_358_SNIPPET, - 0x1, chCrabAnimations, - chCrab_update, actor_update_func_80326224, actor_draw, - 1900, 0, 0.8f, 0 -}; - -ActorInfo chBlackSnippet = { - MARKER_DD_BLACK_SNIPPET, ACTOR_F2_BLACK_SNIPPET, ASSET_566_MODEL_BLACK_SNIPPET, - 0x1, chCrabAnimations, - chCrab_update, actor_update_func_80326224, actor_draw, - 1900, 0, 0.8f, 0 -}; - -ActorInfo chMutieSnippet = { - MARKER_13_SNIPPET, ACTOR_F5_MUTIE_SNIPPET, ASSET_38F_MODEL_MUTIE_SNIPPET, - 0x1, chCrabMutantAnimations, - chCrab_update, actor_update_func_80326224, actor_draw, - 1900, 0, 0.8f, 0 -}; \ No newline at end of file +ActorInfo chSnippet = { MARKER_13_SNIPPET, ACTOR_67_SNIPPET, ASSET_358_SNIPPET, 0x1, chCrabAnimations, chCrab_update, actor_update_func_80326224, actor_draw, 1900, 0, 0.8f, 0}; +ActorInfo chBlackSnippet = { MARKER_DD_BLACK_SNIPPET, ACTOR_F2_BLACK_SNIPPET, ASSET_566_MODEL_BLACK_SNIPPET, 0x1, chCrabAnimations, chCrab_update, actor_update_func_80326224, actor_draw, 1900, 0, 0.8f, 0}; +ActorInfo chMutieSnippet = { MARKER_13_SNIPPET, ACTOR_F5_MUTIE_SNIPPET, ASSET_38F_MODEL_MUTIE_SNIPPET, 0x1, chCrabMutantAnimations, chCrab_update, actor_update_func_80326224, actor_draw, 1900, 0, 0.8f, 0}; diff --git a/src/core2/ch/extralife.c b/src/core2/ch/extralife.c index 484842ec8..d0f8a2936 100644 --- a/src/core2/ch/extralife.c +++ b/src/core2/ch/extralife.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_41F30.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ch/feather.c b/src/core2/ch/feather.c index f4cd8ff77..363b00296 100644 --- a/src/core2/ch/feather.c +++ b/src/core2/ch/feather.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_43800.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/ch/gameSelect.h b/src/core2/ch/gameSelect.h deleted file mode 100644 index a7a3ec955..000000000 --- a/src/core2/ch/gameSelect.h +++ /dev/null @@ -1,14 +0,0 @@ -// BanjoDecomp: core2/ch/gameSelect.h -#ifndef BANJO_KAZOOIE_CH_GAMESELECT_H -#define BANJO_KAZOOIE_CH_GAMESELECT_H - -typedef enum { - GAME_SELECT_INITIALIZE = 1, - GAME_SELECT_IDLE = 2, - GAME_SELECT_STARTING = 3, - GAME_SELECT_STARTING_SILLY = 4, - GAME_SELECT_ERASE_CONFIRMATION = 5, - GAME_SELECT_DONE = 6 -} GameSelectState; - -#endif // BANJO_KAZOOIE_CH_GAMESELECT_H diff --git a/src/core2/ch/ghost.c b/src/core2/ch/ghost.c index 16dd4500f..98c80714e 100644 --- a/src/core2/ch/ghost.c +++ b/src/core2/ch/ghost.c @@ -9,11 +9,11 @@ typedef struct { f32 unk4; } ActorLocal_Core2_D4050; -void chTeehee_update(Actor *this); -void chPurpleTeehee_update(Actor *this); +void func_8035B900(Actor *this); +void func_8035BD48(Actor *this); /* .data */ -ActorAnimationInfo chTeeheeAnimations[] ={ +ActorAnimationInfo D_80372BE0[] ={ {0x00, 0.0f}, {ASSET_9E_ANIM_TEEHEE_IDLE, 2.0f}, {ASSET_9F_ANIM_TEEHEE_ALERTED, 1.5f}, @@ -23,17 +23,17 @@ ActorAnimationInfo chTeeheeAnimations[] ={ {ASSET_2AB_ANIM_TEEHEE_DIE, 1.0f} }; -ActorInfo chTeeHee = { //TEEHEE +ActorInfo D_80372C18 = { //TEEHEE MARKER_99_TEEHEE, ACTOR_CA_TEEHEE, ASSET_3CB_MODEL_TEEHEE, - 0x1, chTeeheeAnimations, - chTeehee_update, actor_update_func_80326224, actor_draw, + 0x1, D_80372BE0, + func_8035B900, actor_update_func_80326224, actor_draw, 6500, 0, 0.9f, 0 }; -ActorInfo chPurpleTeeHee = { //PURPLE_TEEHEE (inside tumblar) +ActorInfo D_80372C3C = { //PURPLE_TEEHEE (inside tumblar) MARKER_296_TEEHEE_PURPLE, ACTOR_3C1_PURPLE_TEEHEE, ASSET_564_MODEL_PURPLE_TEEHEE, - 0x1, chTeeheeAnimations, - chTeehee_update, chPurpleTeehee_update, actor_draw, + 0x1, D_80372BE0, + func_8035B900, func_8035BD48, actor_draw, 6500, 0, 0.9f, 0 }; @@ -41,48 +41,27 @@ s32 D_80372C60[3] = {0x46, 0xFE, 0x46}; s32 D_80372C6C[3] = {0xFE, 0x46, 0xFE}; -enum chteehee_state_e { - CH_TEEHEE_STATE_0_NOT_INIT, - CH_TEEHEE_STATE_1_IDLE, - CH_TEEHEE_STATE_2_ALERT, - CH_TEEHEE_STATE_3_CHASE, - CH_TEEHEE_STATE_4_UNK, - CH_TEEHEE_STATE_5_UNK, - CH_TEEHEE_STATE_6_DIE -}; - -enum chpurpleteehee_state_e { - CH_PURPLE_TEEHEE_STATE_0_NOT_INIT, - CH_PURPLE_TEEHEE_STATE_1_UNK, - CH_PURPLE_TEEHEE_STATE_2_UNUSED, - CH_PURPLE_TEEHEE_STATE_3_ROAMING, - CH_PURPLE_TEEHEE_STATE_4_UNUSED, - CH_PURPLE_TEEHEE_STATE_5_UNUSED, - CH_PURPLE_TEEHEE_STATE_6_DIE -}; - /* .code */ -void chTeehee_emitDust(f32 scale, f32 pos[3], s32 cnt, enum asset_e sprite_id, s32 arg4[3]) -{ +void func_8035AFE0(f32 scale, f32 pos[3], s32 cnt, enum asset_e sprite_id, s32 arg4[3]){ ParticleEmitter *pCtrl = partEmitMgr_newEmitter(cnt); particleEmitter_setSprite(pCtrl, sprite_id); particleEmitter_setRGB(pCtrl, arg4); particleEmitter_setPosition(pCtrl, pos); particleEmitter_setSpawnPositionRange(pCtrl, - -100.0f * scale, 20.0f * scale, -100.0f * scale, - 100.0f * scale, 200.0f * scale, 100.0f * scale + -100.0f*scale, 20.0f*scale, -100.0f*scale, + 100.0f*scale, 200.0f*scale, 100.0f*scale ); particleEmitter_setAccelerationRange(pCtrl, - 0.0f, -10.0f * scale, 0.0f, - 0.0f, -10.0f * scale, 0.0f + 0.0f, -10.0f*scale, 0.0f, + 0.0f, -10.0f*scale, 0.0f ); particleEmitter_setParticleVelocityRange(pCtrl, - -100.0f * scale, -20.0f * scale, -100.0f * scale, - 100.0f * scale, 100.0f * scale, 100.0f * scale + -100.0f*scale, -20.0f*scale, -100.0f*scale, + 100.0f*scale, 100.0f*scale, 100.0f*scale ); - particleEmitter_setStartingScaleRange(pCtrl, scale * 0.4, scale * 0.6); - particleEmitter_setFinalScaleRange(pCtrl, scale * 1.0, scale * 1.4); + particleEmitter_setStartingScaleRange(pCtrl, scale*0.4, scale*0.6); + particleEmitter_setFinalScaleRange(pCtrl, scale*1.0, scale*1.4); particleEmitter_setSpawnIntervalRange(pCtrl, 0.0f, 0.01f); particleEmitter_setParticleLifeTimeRange(pCtrl, 1.0f, 1.4f); particleEmitter_setFade(pCtrl, 0.0f, 0.01f); @@ -90,54 +69,49 @@ void chTeehee_emitDust(f32 scale, f32 pos[3], s32 cnt, enum asset_e sprite_id, s particleEmitter_emitN(pCtrl, cnt); } -void chTeehee_die(ActorMarker *this_marker, ActorMarker *other_marker) -{ +void func_8035B1CC(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *this = marker_getActor(this_marker); - f32 scale; + f32 sp30; - scale = this->scale; - func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); - func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); - subaddie_set_state_with_direction(this, CH_TEEHEE_STATE_6_DIE, 0.01f, 1); + sp30 = this->scale; + func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + subaddie_set_state_with_direction(this, 6, 0.01f, 1); actor_playAnimationOnce(this); actor_collisionOff(this); func_80326310(this); - chTeehee_emitDust(scale, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C60); + func_8035AFE0(sp30, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C60); } -void chTeeheePurple_die(ActorMarker *this_marker, ActorMarker *other_marker) -{ +void func_8035B2C4(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *this = marker_getActor(this_marker); - f32 scale = this->scale; - func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); - func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); - subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_6_DIE, 0.01f, 1); + f32 sp30 = this->scale; + func_8030E878(SFX_121_AWAWAU, 1.3f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + func_8030E878(SFX_30_MAGIC_POOF, 1.0f, 32000, this->position, this->scale*400.0f, this->scale*1800.0f); + subaddie_set_state_with_direction(this, 6, 0.01f, 1); actor_playAnimationOnce(this); actor_collisionOff(this); - chTeehee_emitDust(scale, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C6C); + func_8035AFE0(sp30, this->position, 8, ASSET_700_SPRITE_DUST, D_80372C6C); } -void chTeehee_hitPlayer(ActorMarker *this_marker, ActorMarker *other_marker) -{ +void func_8035B3B4(ActorMarker *this_marker, ActorMarker *other_marker){ Actor *this = marker_getActor(this_marker); this->lifetime_value = 1.0f; } -bool func_8035B3E4(Actor *this) -{ - if(subaddie_playerIsWithinSphereAndActive(this, (s32)(this->scale * 600.0f)) && func_803292E0(this)) - return true; - return false; +int func_8035B3E4(Actor *this){ + if(subaddie_playerIsWithinSphereAndActive(this, (s32)(this->scale*600.0f)) && func_803292E0(this)) + return 1; + return 0; } -bool func_8035B444(Actor *this, f32 arg1) -{ +int func_8035B444(Actor *this, f32 arg1){ int out; - subaddie_turnToYaw(this, arg1); + if(!func_80329054(this, 2) && func_80329480(this)) - return false; - return true; + return 0; + return 1; } void func_8035B49C(Actor *this){ @@ -153,16 +127,16 @@ void func_8035B49C(Actor *this){ } void func_8035B56C(Actor *this){ - f32 scale_doubled; + f32 sp2C; f32 plyr_pos[3]; - scale_doubled = 2 * (f64)this->scale; + sp2C = 2*(f64)this->scale; player_getPosition(plyr_pos); if(this->position_y < plyr_pos[1]){ - if(this->position_y + scale_doubled < plyr_pos[1]){ - this->position_y = this->position_y + scale_doubled; - this->velocity_x += scale_doubled; + if(this->position_y + sp2C < plyr_pos[1]){ + this->position_y = this->position_y + sp2C; + this->velocity_x += sp2C; } else{ this->velocity_x += plyr_pos[1] - this->position_y; @@ -170,9 +144,9 @@ void func_8035B56C(Actor *this){ } } else if(plyr_pos[1] < this->position_y){ - if(plyr_pos[1] < this->position_y - scale_doubled){ - this->position_y = this->position_y - scale_doubled; - this->velocity_x -= scale_doubled; + if(plyr_pos[1] < this->position_y - sp2C){ + this->position_y = this->position_y - sp2C; + this->velocity_x -= sp2C; } else{ this->velocity_x -= (this->position_y - plyr_pos[1]); @@ -196,14 +170,14 @@ void func_8035B6CC(Actor *this){ subaddie_set_state_with_direction(this, 2, 0.01f, 1); actor_playAnimationOnce(this); this->actor_specific_1_f = 1.0f; - func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); } void func_8035B75C(Actor *this){ subaddie_set_state_with_direction(this, 3, 0.01f, 1); actor_loopAnimation(this); this->actor_specific_1_f = volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE) ? 0.0 : 12.0; - func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); } void func_8035B824(Actor *this){ @@ -222,78 +196,78 @@ void func_8035B8A8(Actor *this){ func_80328CEC(this, (s32)this->yaw_ideal, 0xE1, 0x87); } -void chTeehee_update(Actor *this){ +void func_8035B900(Actor *this){ ActorLocal_Core2_D4050 *local = (ActorLocal_Core2_D4050 *)&this->local; - s32 global_time = globalTimer_getTime(); - f32 time_delta = time_getDelta(); + s32 sp30 = globalTimer_getTime(); + f32 sp2C = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = true; - marker_setCollisionScripts(this->marker, NULL, chTeehee_hitPlayer, chTeehee_die); + marker_setCollisionScripts(this->marker, NULL, func_8035B3B4, func_8035B1CC); this->marker->propPtr->unk8_3 = false; actor_collisionOn(this); this->velocity_z = 0.0f; this->lifetime_value = 0.0f; - this->unk1C[0] = this->position_y + this->scale * 100.0f; - this->velocity_y = this->scale * 2.0; + this->unk1C[0] = this->position_y + this->scale*100.0f; + this->velocity_y = this->scale*2.0; this->velocity_x = this->unk1C[0]; local->unk0 = randf2(1.0f, 4.5f); anctrl_setTransitionDuration(this->anctrl, 0.8f); }//L8035B9D4 - if(0.0 < this->lifetime_value - time_delta){ - this->lifetime_value -= time_delta; + if(0.0 < this->lifetime_value - sp2C){ + this->lifetime_value -= sp2C; } else{//L8035BA08 switch(this->state){ - case CH_TEEHEE_STATE_1_IDLE: //L8035BA30 + case 1: //L8035BA30 func_8035B49C(this); if(func_8035B3E4(this)){ func_8035B6CC(this); } - else if(0.0 < local->unk0 - time_delta){ - local->unk0 = local->unk0 - time_delta; + else if(0.0 < local->unk0 - sp2C){ + local->unk0 = local->unk0 - sp2C; } else{ func_8035B824(this); } break; - case CH_TEEHEE_STATE_2_ALERT: //L8035BA98 + case 2: //L8035BA98 this->yaw_ideal = subaddie_getYawToPlayer(this); func_8035B444(this, 4.0f); if(actor_animationIsAt(this, 0.99f)){ func_8035B75C(this); } break; - case CH_TEEHEE_STATE_3_CHASE: //L8035BAE0 + case 3: //L8035BAE0 func_8035B56C(this); - if((global_time & 0x3F) == 7 && randf() < 0.7){ - func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + if((sp30 & 0x3F) == 7 && randf() < 0.7){ + func_8030E878(0x3F4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); }//L8035BB6C this->yaw_ideal = subaddie_getYawToPlayer(this); if(!func_8035B3E4(this) || !func_8035B444(this, 5.0f)){ func_8035B674(this); } break; - case CH_TEEHEE_STATE_4_UNK: //L8035BBB0 + case 4: //L8035BBB0 func_8035B49C(this); if(!func_8035B444(this, 2.0f)){ func_8035B8A8(this); } - else if(local->unk4 - time_delta <= 0.0){ + else if(local->unk4 - sp2C <= 0.0){ func_8035B674(this); } else{ - local->unk4 = local->unk4 - time_delta; + local->unk4 = local->unk4 - sp2C; } break; - case CH_TEEHEE_STATE_5_UNK: //L8035BC1C + case 5: //L8035BC1C func_8035B49C(this); subaddie_turnToYaw(this, 3.0f); if(func_80329480(this)){ func_8035B674(this); } break; - case CH_TEEHEE_STATE_6_DIE: //L8035BC48 + case 6: //L8035BC48 break; } }//L8035BC48 @@ -323,12 +297,12 @@ int func_8035BC5C(Actor *this, s32 target, s32 delta){ return done; } -void chPurpleTeehee_update(Actor *this){ +void func_8035BD48(Actor *this){ if(!this->volatile_initialized){ this->volatile_initialized = true; this->marker->propPtr->unk8_3 = false; actor_collisionOn(this); - marker_setCollisionScripts(this->marker, NULL, chTeehee_hitPlayer, chTeeheePurple_die); + marker_setCollisionScripts(this->marker, NULL, func_8035B3B4, func_8035B2C4); mapSpecificFlags_set(3, false); mapSpecificFlags_set(4, false); if(gsworld_getMap() == MAP_24_MMM_TUMBLARS_SHED){ @@ -338,32 +312,32 @@ void chPurpleTeehee_update(Actor *this){ marker_despawn(this->marker); } else{//L8035BE04 - subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_1_UNK, 0.01f, 1); + subaddie_set_state_with_direction(this, 1, 0.01f, 1); actor_setOpacity(this, 0); } } else{//L8035BE2C - subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_3_ROAMING, 0.01f, 1); + subaddie_set_state_with_direction(this, 3, 0.01f, 1); actor_setOpacity(this, 0xff); } }//L8035BE50 switch(this->state){ - case CH_PURPLE_TEEHEE_STATE_1_UNK: //L8035BE78 + case 1: //L8035BE78 actor_collisionOff(this); if(mapSpecificFlags_getClear(4)){ marker_despawn(this->marker); } else if(mapSpecificFlags_getClear(3)){ - subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_3_ROAMING, 0.01f, 1); + subaddie_set_state_with_direction(this, 3, 0.01f, 1); } break; - case CH_PURPLE_TEEHEE_STATE_3_ROAMING: //L8035BECC + case 3: //L8035BECC this->unk58_0 = true; actor_collisionOn(this); if(mapSpecificFlags_getClear(4)){ this->unk38_0 = true; - chTeeheePurple_die(this->marker, NULL); + func_8035B2C4(this->marker, NULL); } else{//L8035BF14 if(this->alpha_124_19 == 0xFF || func_8035BC5C(this, 0xff, 0xA)){ @@ -371,11 +345,11 @@ void chPurpleTeehee_update(Actor *this){ } if((globalTimer_getTime() &0x3F) == 7 && randf() < 0.7){ - func_8030E878(0x3f4, randf2(1.0f, 1.2f), 32000, this->position, this->scale * 400.0f, this->scale * 1800.0f); + func_8030E878(0x3f4, randf2(1.0f, 1.2f), 32000, this->position, this->scale*400.0f, this->scale*1800.0f); } } break; - case CH_PURPLE_TEEHEE_STATE_6_DIE: //L8035BFD4 + case 6: //L8035BFD4 if(func_8035BC5C(this, 0, -7)){ this->unk58_0 = false; this->unk48 = 0.0f; @@ -384,7 +358,7 @@ void chPurpleTeehee_update(Actor *this){ marker_despawn(this->marker); } else{ - subaddie_set_state_with_direction(this, CH_PURPLE_TEEHEE_STATE_1_UNK, 0.01f, 1); + subaddie_set_state_with_direction(this, 1, 0.01f, 1); timedFunc_set_2(randf2(5.0f, 10.0f), (GenFunction_2)mapSpecificFlags_set, 3, true); } } diff --git a/src/core2/ch/gloop.c b/src/core2/ch/gloop.c index 2fee4d88e..6a71d5c7d 100644 --- a/src/core2/ch/gloop.c +++ b/src/core2/ch/gloop.c @@ -60,7 +60,7 @@ void chgloop_update(Actor *this){ if( !mapSpecificFlags_get(2) && subaddie_playerIsWithinSphereAndActive(this, 350) - && gcdialog_showDialog(VER_SELECT(ASSET_D34_DIALOG_GLOOP_MEET, 0xA07, 0, 0), 0, NULL, NULL, NULL, NULL) + && gcdialog_showDialog(ASSET_D34_DIALOG_GLOOP_MEET, 0, NULL, NULL, NULL, NULL) ){ mapSpecificFlags_set(2, true); } diff --git a/src/core2/ch/goldfeather.c b/src/core2/ch/goldfeather.c index bc45e3e15..ff39d1ff0 100644 --- a/src/core2/ch/goldfeather.c +++ b/src/core2/ch/goldfeather.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_51950.c #include #include "functions.h" #include "variables.h" @@ -8,14 +7,14 @@ extern f32 player_getYaw(void); void func_802D88E0(Actor *this); /* .data */ -ActorInfo fxSpentRedFeather = { +ActorInfo D_80367C90 = { 0x100, 0x1FF, 0x580, 0x0, NULL, func_802D88E0, actor_update_func_80326224, fxTouchSparkle_draw, 0, 0, 0.0f, 0 }; -ActorInfo fxSpentGoldFeather = { +ActorInfo D_80367CB4 = { 0x101, 0x200, 0x6D1, 0x0, NULL, func_802D88E0, actor_update_func_80326224, fxTouchSparkle_draw, diff --git a/src/core2/ch/gravestone.c b/src/core2/ch/gravestone.c index 4a17efff6..97cf86660 100644 --- a/src/core2/ch/gravestone.c +++ b/src/core2/ch/gravestone.c @@ -47,8 +47,8 @@ Actor *chgravestone_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { this = marker_getActorAndRotation(marker, rotation); local = (ActorLocal_core2_D7D10 *)&this->local; - modelRender_setAppendageVisibility(3, (s32) this->velocity[1]); - modelRender_setAppendageVisibility(4, local->unk0); + func_8033A45C(3, (s32) this->velocity[1]); + func_8033A45C(4, local->unk0); modelRender_setPreDrawCallback( (model_render_pre_draw_callback_f)actor_predrawMethod, (void *)this); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); modelRender_draw(gfx, mtx, this->position, rotation, this->scale, D_80373008, func_803257B4(marker)); diff --git a/src/core2/ch/grillechompa.c b/src/core2/ch/grill_chompa.c similarity index 97% rename from src/core2/ch/grillechompa.c rename to src/core2/ch/grill_chompa.c index a6a74f62c..cbb060d68 100644 --- a/src/core2/ch/grillechompa.c +++ b/src/core2/ch/grill_chompa.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/grillechompa.c #include #include "functions.h" #include "variables.h" @@ -73,7 +72,7 @@ Actor *chGrilleChompa_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) return actor; } else{ - modelRender_setAppendageVisibility(3, (actor->state == 1 || actor->state == 6)? 0:1); + func_8033A45C(3, (actor->state == 1 || actor->state == 6)? 0:1); return actor_draw(marker, gfx, mtx, vtx); } diff --git a/src/core2/ch/honeycomb.c b/src/core2/ch/honeycomb.c index dcf803337..fbdf64f24 100644 --- a/src/core2/ch/honeycomb.c +++ b/src/core2/ch/honeycomb.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_42CB0.c #include #include "functions.h" #include "variables.h" @@ -12,15 +11,13 @@ typedef struct{ void chHoneycomb_update(Actor *this); /* .data */ -ActorInfo chEmptyHoneycomb = { - MARKER_53_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, ASSET_361_MODEL_EMPTY_HONEYCOMB, +ActorInfo D_80366C80 = { MARKER_53_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, ASSET_361_MODEL_EMPTY_HONEYCOMB, 0, NULL, chHoneycomb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.8f, 0 }; -ActorInfo chHoneycomb = { - MARKER_55_HONEYCOMB, ACTOR_50_HONEYCOMB, ASSET_363_MODEL_HONEYCOMB, +ActorInfo D_80366CA4 = { MARKER_55_HONEYCOMB, ACTOR_50_HONEYCOMB, ASSET_363_MODEL_HONEYCOMB, 0, NULL, chHoneycomb_update, actor_update_func_80326224, actor_draw, 0, 0, 0.8f, 0 @@ -168,19 +165,3 @@ enum honeycomb_e func_802CA1C4(Actor *this){ void func_802CA1CC(enum honeycomb_e id){ D_8037DDC0 = id; } - -// [port] Anchor: spawn a teammate's dropped empty honeycomb locally. Spawned through the -// same per-map bundle as the local drop so it gets the pickup drop physics. -static void __chHoneycomb_netSpawnDrop(uintptr_t uid, uintptr_t bundle, uintptr_t x, uintptr_t y, uintptr_t z){ - f32 pos[3]; - pos[0] = reinterpret_cast(f32, x); - pos[1] = reinterpret_cast(f32, y); - pos[2] = reinterpret_cast(f32, z); - func_802CA1CC((enum honeycomb_e)uid); - bundle_spawn_f32((enum bundle_e)bundle, pos); -} - -void chHoneycomb_netSpawnDropAt(s32 uid, s32 bundleId, f32 x, f32 y, f32 z){ - __spawnQueue_add_5((GenFunction_5)__chHoneycomb_netSpawnDrop, (uintptr_t)uid, (uintptr_t)bundleId, - reinterpret_cast(s32, x), reinterpret_cast(s32, y), reinterpret_cast(s32, z)); -} diff --git a/src/core2/ch/icecube.c b/src/core2/ch/icecube.c index 231756902..2582264c4 100644 --- a/src/core2/ch/icecube.c +++ b/src/core2/ch/icecube.c @@ -39,7 +39,7 @@ s32 D_80372BD4[3] = {200, 200, 255}; /*.code */ Actor *chicecube_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *actor = marker_getActor(marker); - modelRender_setAppendageVisibility(3, actor->unk38_31); + func_8033A45C(3, actor->unk38_31); actor = actor_draw(marker, gfx, mtx, vtx); return actor; } diff --git a/src/core2/ch/jiggy.c b/src/core2/ch/jiggy.c index 02cb2178a..fed32dbd7 100644 --- a/src/core2/ch/jiggy.c +++ b/src/core2/ch/jiggy.c @@ -1,21 +1,31 @@ -// BanjoDecomp: core2/ch/jiggy.c #include #include "functions.h" #include "variables.h" #include "enums.h" -#include "jiggy.h" -#include "core2/commonParticle.h" -#include "port/Enhancements/Events/Hooks/Events.h" extern void func_802BE720(void); - +extern f32 modelRender_func_8033A244(f32); extern void modelRender_func_8033A280(f32); +typedef struct chjiggy_s{ + u32 unk0; + u32 index; +} ActorLocal_Jiggy; + +Actor *spawnQueue_actor_s32(f32, f32, f32); +void spawnJiggyDestroyedEffects(u32 x, u32 y, u32 z, u32 arg3); +Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void chjiggy_update_2(Actor * arg0); +void chjiggy_update(Actor *this); +enum jiggy_e chjiggy_getJiggyId(Actor *this); + + + /* .data */ ActorAnimationInfo JIGGY_ANIMATIONS[] = { - { 0, 0.0f }, - { 0, 0.0f }, - { 0, 0.0f } + {0, 0.0f}, + {0, 0.0f}, + {0, 0.0f} }; ActorInfo chJiggy = { @@ -26,137 +36,119 @@ ActorInfo chJiggy = { }; /* .code */ -enum jiggy_e getJiggyId(Actor *this) { +enum jiggy_e getJiggyId(Actor *this){ s32 id; - s32 position[3]; + s32 sp18[3]; id = gsworld_getMap(); - position[0] = (s32)this->position[0]; - position[1] = (s32)this->position[1]; - position[2] = (s32)this->position[2]; - - id = func_80307164(position); - - if (id < 0) { + sp18[0] = (s32)this->position[0]; + sp18[1] = (s32)this->position[1]; + sp18[2] = (s32)this->position[2]; + id = func_80307164(sp18); + if( id < 0){ return 0; } - - return func_80306DBC(id) + 1; + else{ + return func_80306DBC(id) + 1; + } } -void playJiggyDestroyedSoundsAndReset(ActorMarker *marker, u32 resetSwitchFlag) { +void playJiggyDestroyedSoundsAndReset(ActorMarker * arg0, u32 arg1){ func_8030E6D4(SFX_30_MAGIC_POOF); coMusicPlayer_playMusic(COMUSIC_3C_MINIGAME_LOSS, 0x7FF8); - mapSpecificFlags_set(resetSwitchFlag, TRUE); - marker_despawn(marker); + mapSpecificFlags_set(arg1, 1); + marker_despawn(arg0); } -void spawnJiggyDestroyedEffects(u32 x, u32 y, u32 z, u32 resetSwitchFlag) { +void spawnJiggyDestroyedEffects(u32 x, u32 y, u32 z, u32 arg3){ __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_s32, ACTOR_4C_STEAM, x, y, z); __spawnQueue_add_4((GenFunction_4)spawnQueue_actor_s32, ACTOR_14F_DESTROYED_JIGGY, x, y, z); - mapSpecificFlags_set(resetSwitchFlag, TRUE); + mapSpecificFlags_set(arg3, 1); } -void resetFlag(enum bgs_specific_flags flag) { - mapSpecificFlags_set(flag, FALSE); +void resetFlag(u32 arg0){ + mapSpecificFlags_set(arg0, 0); } -void destroyJiggy(Actor *this, s32 jiggyFlag, s32 timerRunningFlag, s32 cameraId, s32 switchPressedFlag, s32 resetSwitchFlag, enum volatile_flags_e dialogFlag) { - - // Jiggy is still active - if (mapSpecificFlags_get(jiggyFlag) - || !mapSpecificFlags_get(timerRunningFlag) - || item_getCount(ITEM_0_HOURGLASS_TIMER) != 0) { - - return; +void destroyJiggy(Actor *this, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, enum volatile_flags_e arg6){ + if( !mapSpecificFlags_get(arg1) + && mapSpecificFlags_get(arg2) + && item_getCount(ITEM_0_HOURGLASS_TIMER) == 0 + ){ + player_setModelVisible(1); + actor_collisionOff(this); + gcStaticCamera_activate(arg3); + volatileFlag_setAndTriggerDialog_0(arg6); + timedFunc_set_4(0.6f, (GenFunction_4)spawnJiggyDestroyedEffects, (s32)this->position[0], (s32)this->position[1], (s32)this->position[2], arg4); + timedFunc_set_2(0.6f, (GenFunction_2)playJiggyDestroyedSoundsAndReset, (uintptr_t)this->marker, arg5); + timedFunc_set_0(1.0f, (GenFunction_0)func_802BE720); + timedFunc_set_1(3.9f, (GenFunction_1)resetFlag, arg4); + mapSpecificFlags_set(arg1, 1); } - - CALL_EVENT(OnTimedJiggyExpired, (s32)chjiggy_getJiggyId(this)); - player_setModelVisible(1); - actor_collisionOff(this); - - // Switch camera to a static one showing the newly destroyed jiggy - gcStaticCamera_activate(cameraId); - - progressDialog_setAndTriggerDialog_0(dialogFlag); - timedFunc_set_4(0.6f, (GenFunction_4)spawnJiggyDestroyedEffects, (s32)this->position[0], (s32)this->position[1], (s32)this->position[2], switchPressedFlag); - timedFunc_set_2(0.6f, (GenFunction_2)playJiggyDestroyedSoundsAndReset, reinterpret_cast(uintptr_t, this->marker), resetSwitchFlag); - timedFunc_set_0(1.0f, (GenFunction_0)func_802BE720); - timedFunc_set_1(3.9f, (GenFunction_1)resetFlag, switchPressedFlag); - mapSpecificFlags_set(jiggyFlag, TRUE); } -void chjiggy_updateRotation(Actor *this) { +void chjiggy_updateRotation(Actor *this){ f32 delta = time_getDelta(); - - // Controls the rotation speed this->yaw += delta * 230.0f; - - if (360.0f <= this->yaw) { + if(360.0f <= this->yaw){ this->yaw -= 360.0f; } - this->yaw_ideal = this->yaw; } -Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **vtx) { - Actor *jiggy_actor = marker_getActor(this); - ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&jiggy_actor->local; +//chjiggy_draw +Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3){ + Actor * thisActor = marker_getActor(this); + ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&thisActor->local; u32 jiggyId; - if (!local->isHidden) { - jiggyId = chjiggy_getJiggyId(jiggy_actor); - - if ((jiggyId == JIGGY_1C_CC_RINGS) || (jiggyId == JIGGY_1D_CC_SLOW_SAWBLADES)) { + if(!local->unk0){ + jiggyId = chjiggy_getJiggyId(thisActor); + if((jiggyId == JIGGY_1C_CC_RINGS) || (jiggyId == JIGGY_1D_CC_SLOW_SAWBLADES)){ modelRender_func_8033A280(10.0f); modelRender_func_8033A244(30000.0f); } - - jiggy_actor = actor_draw(this, gdl, mptr, vtx); + thisActor = actor_draw(this, gdl, mptr, arg3); } - - return jiggy_actor; + return thisActor; } -void chjiggy_update_2(Actor *this) { - func_80343DEC(this); - chjiggy_updateRotation(this); +void chjiggy_update_2(Actor * arg0){ + func_80343DEC(arg0); + chjiggy_updateRotation(arg0); } -void chjiggy_update(Actor *this) { +//chjiggy_update +void chjiggy_update(Actor *this){ ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; int i; - // A small chance to show a jiggy shine effect. Up to four can be shown at once. - if (this->marker->unk14_21) { - for (i = 0; i < 4; i++) { - if (randf() < 0.015) { + if(this->marker->unk14_21){ + for(i = 0; i < 4; i++){ + if(randf() < 0.015){ commonParticle_add(this->marker, i + 5, func_80329904); - commonParticle_new(COMMON_PARTICLE_8_JIGGY_SHINE, 1); + commonParticle_new(8, 1); } } - } - - switch (this->state) { - case JIGGY_STATE_1_INIT: - local->isHidden = FALSE; - - if (local->id == 0) { - local->id = getJiggyId(this); - } + }//L802C7E44 + switch(this->state){ + case 1: //L802C7E68 + local->unk0 = 0; + if(local->index == 0) + local->index = getJiggyId(this); - if (jiggyscore_isCollected(local->id)) { + if(jiggyscore_isCollected(local->index)){ marker_despawn(this->marker); - } else { - subaddie_set_state(this, JIGGY_STATE_2_IDLE); - switch (chjiggy_getJiggyId(this)) { - case JIGGY_17_CC_CLANKER_RAISED: - case JIGGY_49_CCW_EYRIE: + } + else{ + subaddie_set_state(this, 2); + switch(chjiggy_getJiggyId(this)){ + case JIGGY_17_CC_CLANKER_RAISED: //L802C7EF8 + case JIGGY_49_CCW_EYRIE:// L802C7EF8 this->marker->unk40_21 = 1; break; - - case JIGGY_36_LAIR_TTC_WITCH_SWITCH: + case JIGGY_36_LAIR_TTC_WITCH_SWITCH:// L802C7F0C this->unk44_14 = func_80341F2C(0x20A); this->unk48 = 0.0f; this->unk4C = 300.0f; @@ -165,63 +157,53 @@ void chjiggy_update(Actor *this) { func_80343DEC(this); chjiggy_updateRotation(this); break; - - case JIGGY_3E_GV_GRABBA: - case JIGGY_4D_CCW_FLOWER: + case JIGGY_3E_GV_GRABBA:// L802C7F6C + case JIGGY_4D_CCW_FLOWER:// L802C7F6C this->unk124_6 = 0; break; - - case JIGGY_41_GV_MAZE: + case JIGGY_41_GV_MAZE:// L802C7F7C this->marker->unk14_10 = 30; break; - - case JIGGY_13_TTC_LOCKUP: + case JIGGY_13_TTC_LOCKUP: //L802C7F94 this->marker->unk14_10 = 40; break; } } - break; - - case JIGGY_STATE_2_IDLE: + case 2: //L802C7FAC chjiggy_updateRotation(this); - - switch (chjiggy_getJiggyId(this)) { - case JIGGY_20_BGS_ELEVATED_WALKWAY: - destroyJiggy(this, BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY, BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING, STATIC_CAMERA_D_WALKWAY_JIGGY_DESTROY, - BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED, BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET, VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED); + switch(chjiggy_getJiggyId(this)){ + case JIGGY_20_BGS_ELEVATED_WALKWAY: //L802C7FE8 + destroyJiggy(this, 4, 3, 0xD, 5, 2, VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED); break; - - case JIGGY_25_BGS_MAZE: - destroyJiggy(this, BGS_SPECIFIC_FLAG_D_MAZE_JIGGY, BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING, STATIC_CAMERA_1E_MAZE_JIGGY_DESTROY, - BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED, BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET, VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED); + case JIGGY_25_BGS_MAZE://L802C8018 + destroyJiggy(this, 0xd, 0xc, 0x1e, 9, 0xb, VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED); break; - - case JIGGY_2F_FP_XMAS_TREE: + case JIGGY_2F_FP_XMAS_TREE://L802C8048 if (levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { actor_collisionOn(this); - } else { + } + else { actor_collisionOff(this); } break; } - break; - } + }//L802C8074 } -enum jiggy_e chjiggy_getJiggyId(Actor *this) { +enum jiggy_e chjiggy_getJiggyId(Actor *this){ ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; - return local->id; + return local->index; } -void chjiggy_hide(Actor *this) { +void chjiggy_hide(Actor * this){ ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; - local->isHidden = TRUE; + local->unk0 = 1; actor_collisionOff(this); } -void chjiggy_setJiggyId(Actor *this, u32 id) { +void chjiggy_setJiggyId(Actor *this, u32 id){ ActorLocal_Jiggy *local = (ActorLocal_Jiggy *)&this->local; - local->id = id; + local->index = id; } diff --git a/src/core2/ch/jiggy.h b/src/core2/ch/jiggy.h deleted file mode 100644 index b66c45a28..000000000 --- a/src/core2/ch/jiggy.h +++ /dev/null @@ -1,20 +0,0 @@ -// BanjoDecomp: core2/ch/jiggy.h -#ifndef BANJO_KAZOOIE_CH_JIGGY_H -#define BANJO_KAZOOIE_CH_JIGGY_H - -typedef struct chjiggy_s { - bool isHidden; - u32 id; -} ActorLocal_Jiggy; - -Actor *chjiggy_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chjiggy_update_2(Actor * arg0); -void chjiggy_update(Actor *this); -enum jiggy_e chjiggy_getJiggyId(Actor *this); - -enum jiggy_state_e { - JIGGY_STATE_1_INIT = 1, - JIGGY_STATE_2_IDLE = 2 -}; - -#endif // BANJO_KAZOOIE_CH_JIGGY_H diff --git a/src/core2/ch/jinjo.c b/src/core2/ch/jinjo.c index 09d57b993..45533fbff 100644 --- a/src/core2/ch/jinjo.c +++ b/src/core2/ch/jinjo.c @@ -1,7 +1,6 @@ #include #include "functions.h" #include "variables.h" -#include "port/Enhancements/Retention/Retention.h" extern void subaddie_set_state_with_direction(Actor *, s32, f32 , s32); extern f32 func_80309B24(f32*); @@ -29,49 +28,30 @@ ActorInfo chJinjoYellow = { MARKER_5E_JINJO_YELLOW, ACTOR_5E_JINJO_YELLOW, ASSET ActorInfo chJinjoPink = { MARKER_5D_JINJO_PINK, ACTOR_61_JINJO_PINK, ASSET_3C1_MODEL_JINJO_PINK, 0x1, chJinjoAnimations, chJinjo_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; ActorInfo chJinjoOrange = { MARKER_5C_JINJO_ORANGE, ACTOR_5F_JINJO_ORANGE, ASSET_3BC_MODEL_JINJO_ORANGE, 0x1, chJinjoAnimations, chJinjo_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -enum chjinjo_state_e { - CH_JINJO_STATE_0_NOT_INIT, - CH_JINJO_STATE_1_IDLE, - CH_JINJO_STATE_2_ONE_HAND_WAVE, - CH_JINJO_STATE_3_TWO_HAND_WAVE, - CH_JINJO_STATE_4_JUMPING_WAVE, - CH_JINJO_STATE_5_UNK, - CH_JINJO_STATE_6_COLLECTED, - CH_JINJO_STATE_7_FLY_START, - CH_JINJO_STATE_8_FLY_END, - CH_JINJO_STATE_9_UNK -}; - -/*.code */ enum asset_e __chJinjo_getMeetDialogId(enum marker_e marker_id){ switch(marker_id){ - case MARKER_5A_JINJO_BLUE: return VER_SELECT(ASSET_D98_DIALOG_JINJO_MEET_BLUE, 0x0A16, 0, 0); - case MARKER_5B_JINJO_GREEN: return VER_SELECT(ASSET_D99_DIALOG_JINJO_MEET_GREEN, 0x0A17, 0, 0); - case MARKER_5C_JINJO_ORANGE: return VER_SELECT(ASSET_D9B_DIALOG_JINJO_MEET_ORANGE, 0x0A19, 0, 0); - case MARKER_5D_JINJO_PINK: return VER_SELECT(ASSET_D9A_DIALOG_JINJO_MEET_PINK, 0x0A18, 0, 0); - case MARKER_5E_JINJO_YELLOW: return VER_SELECT(ASSET_D97_DIALOG_JINJO_MEET_YELLOW, 0x0A15, 0, 0); + case MARKER_5A_JINJO_BLUE: return ASSET_D98_DIALOG_JINJO_MEET_BLUE; + case MARKER_5B_JINJO_GREEN: return ASSET_D99_DIALOG_JINJO_MEET_GREEN; + case MARKER_5C_JINJO_ORANGE: return ASSET_D9B_DIALOG_JINJO_MEET_ORANGE; + case MARKER_5D_JINJO_PINK: return ASSET_D9A_DIALOG_JINJO_MEET_PINK; + case MARKER_5E_JINJO_YELLOW: return ASSET_D97_DIALOG_JINJO_MEET_YELLOW; } return 0; } -void __chJinjo_collected(ActorMarker *this, ActorMarker *other){ +void __chJinjo_802CDBA8(ActorMarker *this, ActorMarker *other){ Actor *actorPtr = marker_getActor(this); ActorLocal_Jinjo *localPtr = &actorPtr->jinjo; - if(actorPtr->state < CH_JINJO_STATE_5_UNK){ + if(actorPtr->state < 5){ if(!fileProgressFlag_get(FILEPROG_E_JINJO_TEXT)){ gcdialog_showDialog(__chJinjo_getMeetDialogId(actorPtr->marker->id), 4, 0, 0, 0, 0); fileProgressFlag_set(FILEPROG_E_JINJO_TEXT, 1); } - subaddie_set_state_with_direction(actorPtr, CH_JINJO_STATE_6_COLLECTED, 0.0f , -1); - /* - If multiple Jinjos of a color are collected, it overflows into the next Jinjo. - Example, two Green Jinjos -> Orange Jinjo collected & no Green Jinjo collected - */ + subaddie_set_state_with_direction(actorPtr, 6, 0.0f , -1); if (!EventSystem_Should(VB_UPDATE_JINJO_HUD, false, actorPtr->position)) { if (item_adjustByDiffWithHud(ITEM_12_JINJOS, 1 << ((this->id + 6) & 0x1F)) == 0x1f) // [port] MIPS SLL uses low 5 bits; mask to avoid UB localPtr->unk4 = 1; - port_jinjoRetention_onLocalJinjoCollected(this->id); } actor_loopAnimation(actorPtr); this->collidable = false; @@ -82,7 +62,7 @@ void __chJinjo_802CDC9C(Actor *this, s16 arg1){ f32 tmpf; tmpf = this->yaw; - tmpf -= time_getDelta() * arg1 / 45.0; + tmpf -= time_getDelta()*arg1/45.0; if(tmpf >= 360.0f) tmpf -= 360.0f; @@ -92,7 +72,7 @@ void __chJinjo_802CDC9C(Actor *this, s16 arg1){ this->yaw = tmpf; } -void __chJinjo_free(Actor * this){ +void __chJinjo_802CDD3C(Actor * this){ ActorLocal_Jinjo *localPtr = &this->jinjo; if(localPtr->unkC != 0){ func_802F9D38(localPtr->unkC); @@ -102,21 +82,21 @@ void __chJinjo_free(Actor * this){ void chJinjo_update(Actor * this){ f32 sp7C[3]; - f32 player_velocity[3]; + f32 sp70[3]; f32 sp6C; f32 sp68; //unused?? s16 sp66; s16 sp64; - s32 is_within_jinjos_vision; + s32 sp60; // f32 sp5C; ActorLocal_Jinjo *local; //= &this->jinjo; //sp34 - f32 time_delta = time_getDelta(); + f32 sp58 = time_getDelta(); s32 i; - int is_flying_start; - f32 *this_position; + int sp50; + f32 *sp30; //f32 sp4C; //unused - f32 jiggy_position[3]; + f32 sp40[3]; //s32 sp3C; //s32 sp38; @@ -129,50 +109,50 @@ void chJinjo_update(Actor * this){ local->unk0 = 1; local->unk4 = 0; local->unk8 = (this->position_y < func_80309B24(this->position)); - this->marker->collisionFunc = __chJinjo_collected; - marker_setFreeMethod(this->marker, __chJinjo_free); + this->marker->collisionFunc = __chJinjo_802CDBA8; + marker_setFreeMethod(this->marker, __chJinjo_802CDD3C); if(volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)){ marker_despawn(this->marker); } }//L802CDE24 - this_position = this->position; + sp30 = this->position; func_8028E964(sp7C); - func_80257F18(this_position, sp7C, &sp6C); + func_80257F18(sp30, sp7C, &sp6C); sp64 = (this->yaw * 182.04444); // sp66 = sp64 - (s32)(sp6C*182.04444); sp66 = (s32) (sp6C * 182.04444); sp66 = sp64 - sp66; - is_within_jinjos_vision = func_8028AED4(this_position, 55.0f); + sp60 = func_8028AED4(sp30, 55.0f); switch(this->state){ - case CH_JINJO_STATE_1_IDLE: + case 1: if(randf() < 0.015){ - if(is_within_jinjos_vision){ - subaddie_set_state_with_direction(this, CH_JINJO_STATE_3_TWO_HAND_WAVE, 0.0f, -1); + if(sp60){ + subaddie_set_state_with_direction(this, 3, 0.0f, -1); }else{ - subaddie_set_state_with_direction(this, CH_JINJO_STATE_2_ONE_HAND_WAVE, 0.0f, -1); + subaddie_set_state_with_direction(this, 2, 0.0f, -1); } actor_playAnimationOnce(this); }//L802CDF24 break; - case CH_JINJO_STATE_2_ONE_HAND_WAVE: /* 46FA0 802CDF30 3C053F7D */ - case CH_JINJO_STATE_3_TWO_HAND_WAVE: + case 2: /* 46FA0 802CDF30 3C053F7D */ + case 3: if(actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, CH_JINJO_STATE_1_IDLE, 0.0f, -1); + subaddie_set_state_with_direction(this, 1, 0.0f, -1); } break; - case CH_JINJO_STATE_4_JUMPING_WAVE: /* 46FD8 802CDF68 3C053F7D */ + case 4: /* 46FD8 802CDF68 3C053F7D */ if(actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, CH_JINJO_STATE_1_IDLE, 0.0f, -1); + subaddie_set_state_with_direction(this, 1, 0.0f, -1); }else{//L802CDF9C tmp_f0 = this->yaw; if(sp66 >= 0){ - tmp_f0 -= 80.0f * time_delta; + tmp_f0 -= 80.0f * sp58; } else{//L802CDFBC - tmp_f0 += 80.0f * time_delta; + tmp_f0 += 80.0f * sp58; }//L802CDFD0 if(tmp_f0 >= 360.0f) tmp_f0 -= 360.0f; @@ -182,17 +162,17 @@ void chJinjo_update(Actor * this){ this->yaw = tmp_f0; }//L802CE018 break; - case CH_JINJO_STATE_6_COLLECTED:/* 47094 802CE024 02002025 */ + case 6:/* 47094 802CE024 02002025 */ __chJinjo_802CDC9C(this, sp66); if(actor_animationIsAt(this, 0.0f) && --(local->unk0) == 0){ - subaddie_set_state_with_direction(this, CH_JINJO_STATE_7_FLY_START, 0.0f, -1); + subaddie_set_state_with_direction(this, 7, 0.0f, -1); actor_playAnimationOnce(this); if(local->unk4){ - jiggy_position[0] = this->position_x; - jiggy_position[1] = this->position_y; - jiggy_position[2] = this->position_z; - jiggy_position[1] += 50.0f; - jiggy_spawn(10 * level_get() - 9, jiggy_position); + sp40[0] = this->position_x; + sp40[1] = this->position_y; + sp40[2] = this->position_z; + sp40[1] += 50.0f; + jiggy_spawn(10*level_get()-9, sp40); }//L802CE0CC core1_ce60_incOrDecCounter(false); func_8032BB88(this, 0, 4000); @@ -204,27 +184,27 @@ void chJinjo_update(Actor * this){ }//L802CE114 break; - case CH_JINJO_STATE_7_FLY_START: - case CH_JINJO_STATE_8_FLY_END: - is_flying_start = this->state == CH_JINJO_STATE_7_FLY_START; - if(!is_flying_start || 0.1 < anctrl_getAnimTimer(this->anctrl)){//L802CE158 - player_getVelocity(player_velocity); - player_velocity[0] *= time_delta * 6.0f;\ - player_velocity[1] *= time_delta * 6.0f;\ - player_velocity[2] *= time_delta * 6.0f; - player_velocity[0] = player_velocity[0] + sp7C[0];\ - player_velocity[1] = player_velocity[1] + sp7C[1];\ - player_velocity[2] = player_velocity[2] + sp7C[2]; - player_velocity[0] -= this->position_x;\ - player_velocity[1] -= this->position_y;\ - player_velocity[2] -= this->position_z; - player_velocity[0] *= time_delta * 3.0f; - player_velocity[1] *= time_delta * 3.0f; - player_velocity[2] *= time_delta * 3.0f; - this->position_x = this->position_x + player_velocity[0]; - this->position_y = this->position_y + player_velocity[1]; - this->position_z = this->position_z + player_velocity[2]; - if(is_flying_start || anctrl_getAnimTimer(this->anctrl) < 0.8){ + case 7: + case 8: + sp50 = this->state == 7; + if(!sp50 || 0.1 < anctrl_getAnimTimer(this->anctrl)){//L802CE158 + player_getVelocity(sp70); + sp70[0] *= sp58*6.0f;\ + sp70[1] *= sp58*6.0f;\ + sp70[2] *= sp58*6.0f; + sp70[0] = sp70[0] + sp7C[0];\ + sp70[1] = sp70[1] + sp7C[1];\ + sp70[2] = sp70[2] + sp7C[2]; + sp70[0] -= this->position_x;\ + sp70[1] -= this->position_y;\ + sp70[2] -= this->position_z; + sp70[0] *= sp58*3.0f; + sp70[1] *= sp58*3.0f; + sp70[2] *= sp58*3.0f; + this->position_x = this->position_x + sp70[0]; + this->position_y = this->position_y + sp70[1]; + this->position_z = this->position_z + sp70[2]; + if(sp50 || anctrl_getAnimTimer(this->anctrl) < 0.8){ for(i = 0; i < 4; i++){ if(randf() < 0.3){ commonParticle_add(this->marker, i + 5, func_80329904); @@ -234,38 +214,38 @@ void chJinjo_update(Actor * this){ }//L802CE2D0 } - if(is_flying_start){ + if(sp50){ if(anctrl_getAnimTimer(this->anctrl) < 0.2) __chJinjo_802CDC9C(this, sp66); if(actor_animationIsAt(this, 0.1f)){ local->unkC = func_802F9AA8(SFX_18_BIGBUTT_SLIDE); - func_802F9EC4(local->unkC, this_position, 500, 2000); + func_802F9EC4(local->unkC, sp30, 500, 2000); func_802F9F80(local->unkC, 0.0f, 9e+09, 0.0f); func_802FA0B0(local->unkC, 0); coMusicPlayer_playMusic(COMUSIC_43_ENTER_LEVEL_GLITTER, 0x7FFF); func_8025AABC(COMUSIC_43_ENTER_LEVEL_GLITTER); - func_8030E9C4(SFX_C7_SHWOOP, 0.8f, 0x7FFF, this_position, 300.0f, 2000.0f); + func_8030E9C4(SFX_C7_SHWOOP, 0.8f, 0x7FFF, sp30, 300.0f, 2000.0f); }//L802CE3C4 if(actor_animationIsAt(this, 0.434f)){ - func_8030E9C4(SFX_C7_SHWOOP, 0.9f, 0x7fff, this_position, 300.0f, 2000.0f); + func_8030E9C4(SFX_C7_SHWOOP, 0.9f, 0x7fff, sp30, 300.0f, 2000.0f); }//L802CE408 if(actor_animationIsAt(this, 0.811f)){ - func_8030E9C4(SFX_C7_SHWOOP, 1.0f, 0x7fff, this_position, 300.0f, 2000.0f); + func_8030E9C4(SFX_C7_SHWOOP, 1.0f, 0x7fff, sp30, 300.0f, 2000.0f); } }else{//L802CE450 - if(actor_animationIsAt(this, 0.214f)){ - func_8030E9C4(SFX_C7_SHWOOP, 1.1f, 0x7fff, this_position, 300.0f, 2000.0f); + if(actor_animationIsAt(this,0.214f)){ + func_8030E9C4(SFX_C7_SHWOOP, 1.1f, 0x7fff, sp30, 300.0f, 2000.0f); }//L802CE490 - if(actor_animationIsAt(this, 0.55f)){ - func_8030E9C4(SFX_53_BANJO_HUIII, 1.5f, 0x7fff, this_position, 300.0f, 2000.0f); + if(actor_animationIsAt(this,0.55f)){ + func_8030E9C4(SFX_53_BANJO_HUIII, 1.5f, 0x7fff, sp30, 300.0f, 2000.0f); }//L802CE4D0 - if(actor_animationIsAt(this, 0.75f)){ + if(actor_animationIsAt(this,0.75f)){ func_80326310(this); if(local->unk4 == 0){ func_8032BB88(this, -1, 4000); @@ -275,7 +255,7 @@ void chJinjo_update(Actor * this){ } }//L802CE518 - if(actor_animationIsAt(this, 0.85f)){ + if(actor_animationIsAt(this,0.85f)){ if(local->unkC){ func_802F9D38(local->unkC); local->unkC = 0; @@ -284,7 +264,7 @@ void chJinjo_update(Actor * this){ func_8025A7DC(COMUSIC_43_ENTER_LEVEL_GLITTER); }//L802CE558 - if(local->unk4 && actor_animationIsAt(this, 0.95f)){ + if(local->unk4 && actor_animationIsAt(this,0.95f)){ func_8032BB88(this, -1, 4000); if (EventSystem_Should(VB_SET_JINJO_COUNT, true)) { core1_ce60_incOrDecCounter(true); @@ -292,47 +272,44 @@ void chJinjo_update(Actor * this){ } }//L802CE598 - if(is_flying_start){ + if(sp50){ if(actor_animationIsAt(this, 0.96f) || actor_animationIsAt(this, 0.99f)){ - subaddie_set_state_with_direction(this, CH_JINJO_STATE_8_FLY_END, 0.0f, -1); + subaddie_set_state_with_direction(this, 8, 0.0f, -1); actor_playAnimationOnce(this); } } break; }//L802CE5F0 - if(this->state < CH_JINJO_STATE_4_JUMPING_WAVE - && !(((sp66 >= 0)? sp66: -sp66) <= 0x1000)) - { - subaddie_set_state_with_direction(this, CH_JINJO_STATE_4_JUMPING_WAVE, 0.0f, -1); + if(this->state < 4 && !(((sp66 >= 0)? sp66: -sp66) <= 0x1000)){ + subaddie_set_state_with_direction(this, 4, 0.0f, -1); actor_playAnimationOnce(this); }//L802CE630 - if(!gcdialog_hasCurrentTextId()){ switch(chJinjoAnimations[this->state].index){ case ASSET_31_ANIM_JINJO_JUMP: if(actor_animationIsAt(this, 0.6f)){ if(local->unk8){ - func_8030E988(SFX_8_BANJO_LANDING_04, 1.8f, 18000, this_position, 120.0f, 1200.0f); + func_8030E988(SFX_8_BANJO_LANDING_04, 1.8f, 18000, sp30, 120.0f, 1200.0f); }else{ - sfx_playFadeShorthandDefault(SFX_8_BANJO_LANDING_04, 1.8f, 18000, this_position, 120, 1200); + sfx_playFadeShorthandDefault(SFX_8_BANJO_LANDING_04, 1.8f, 18000, sp30, 120, 1200); } } break; case ASSET_2D_ANIM_JINJO_IDLE: //L802CE6F4 if(actor_animationIsAt(this, 0.2f)){ if(local->unk8){ - func_8030E988(SFX_17_JINJO_WHISTLE, 1.0f, 22000, this_position, 120.0f, 1200.0f); + func_8030E988(SFX_17_JINJO_WHISTLE, 1.0f, 22000, sp30, 120.0f, 1200.0f); }else{ - sfx_playFadeShorthandDefault(SFX_17_JINJO_WHISTLE, 1.0f, 22000, this_position, 120, 1200); + sfx_playFadeShorthandDefault(SFX_17_JINJO_WHISTLE, 1.0f, 22000, sp30, 120, 1200); } } break; case ASSET_2F_ANIM_JINJO_HELP: //L802CE760 if(actor_animationIsAt(this, 0.2f)){ if(local->unk8){ - func_8030E988(SFX_27_JINJO_HI, 1.0f, 22000, this_position, 120.0f, 1200.0f); + func_8030E988(SFX_27_JINJO_HI, 1.0f, 22000, sp30, 120.0f, 1200.0f); }else{ - sfx_playFadeShorthandDefault(SFX_27_JINJO_HI, 1.0f, 22000, this_position, 120, 1200); + sfx_playFadeShorthandDefault(SFX_27_JINJO_HI, 1.0f, 22000, sp30, 120, 1200); } } break; diff --git a/src/core2/ch/level_collectible.c b/src/core2/ch/level_collectible.c new file mode 100644 index 000000000..1d1fb4dcf --- /dev/null +++ b/src/core2/ch/level_collectible.c @@ -0,0 +1,378 @@ +#include +#include "functions.h" +#include "variables.h" + +extern void func_8028F7D4(f32, f32); +void chLevelCollectible_update(Actor *this); +extern ActorMarker *func_8028E86C(void); +extern void timed_mapSpecificFlags_setTrue(f32, s32); +extern void progressDialog_showDialogMaskFour(s32); + +ActorAnimationInfo D_80367B50[] = { + {0, 0.0f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, + {ASSET_18A_ANIM_XMAS_GIFT, 1.5f} +}; + +ActorInfo D_80367B80 = { + MARKER_36_ORANGE_COLLECTIBLE, ACTOR_29_ORANGE_COLLECTIBLE, ASSET_2D2_MODEL_ORANGE, + 0x5, NULL, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.6f,0 +}; + +ActorInfo D_80367BA4 = { + MARKER_37_GOLD_BULLION, ACTOR_2A_GOLD_BULLION, ASSET_3C7_MODEL_GOLD_BULLION, + 0x5, NULL, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 0.6f, 0 +}; + +ActorInfo D_80367BC8 = { + MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE, ASSET_47F_MODEL_XMAS_GIFT_BLUE, + 0x5, D_80367B50, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 1.8f, 0 +}; + +ActorInfo D_80367BEC = { + MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE, ASSET_480_MODEL_XMAS_GIFT_GREEN, + 0x5, D_80367B50, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 1.4f, 0 +}; + +ActorInfo D_80367C10 = { + MARKER_1FF_RED_PRESENT_COLLECTIBLE, ACTOR_1F1_RED_PRESENT_COLLECTIBLE, ASSET_481_MODEL_XMAS_GIFT_RED, + 0x5, D_80367B50, + chLevelCollectible_update, actor_update_func_80326224, actor_draw, + 0, 0, 1.4f, 0 +}; + +/* .code */ +void __chLevelCollectible_presentReturnEmitSparkles(f32 position[3], enum asset_e sprite_id) { + static ParticleScaleAndLifetimeRanges D_80367C34 = {{0.2f, 0.4f}, {0.1f, 0.1f}, {0.0f, 0.01f}, {3.0f, 3.5f}, 0.1f, 0.1f}; + ParticleEmitter *p_emitter; + + p_emitter = partEmitMgr_newEmitter(1); + particleEmitter_setSprite(p_emitter, sprite_id); + particleEmitter_setStartingFrameRange(p_emitter, 0, 7); + particleEmitter_setPosition(p_emitter, position); + particleEmitter_setSpawnPositionRange(p_emitter, -40.0f, 0.0f, -40.0f, 40.0f, 60.0f, 40.0f); + particleEmitter_setAccelerationRange(p_emitter, 0.0f, -1000.0f, 0.0f, 0.0f, -1000.0f, 0.0f); + particleEmitter_setScaleAndLifetimeRanges(p_emitter, &D_80367C34); + particleEmitter_emitN(p_emitter, 1); +} + +void __chLevelCollectible_presentCollectEmitSparkles(f32 position[3], enum asset_e sprite_id) { + ParticleEmitter *p_emitter; + + p_emitter = partEmitMgr_newEmitter(8); + particleEmitter_setSprite(p_emitter, sprite_id); + particleEmitter_setPosition(p_emitter, position); + particleEmitter_setAccelerationRange(p_emitter, 0.0f, -250.0f, 0.0f, 0.0f, -250.0f, 0.0f); + particleEmitter_setParticleVelocityRange(p_emitter, -100.0f, 200.0f, -100.0f, 100.0f, 350.0f, 100.0f); + particleEmitter_setAngularVelocityRange(p_emitter, 0.0f, 0.0f, 200.0f, 0.0f, 0.0f, 240.0f); + particleEmitter_setStartingScaleRange(p_emitter, 0.47f, 0.47f); + particleEmitter_setFinalScaleRange(p_emitter, 0.03f, 0.03f); + particleEmitter_setFade(p_emitter, 0.4f, 0.8f); + particleEmitter_setParticleLifeTimeRange(p_emitter, 0.9f, 0.9f); + particleEmitter_emitN(p_emitter, 8); +} + +s32 __chLevelCollectible_dialogCallback(ActorMarker *marker, enum asset_e text_id, s32 arg2) { + return -(levelSpecificFlags_get(LEVEL_FLAG_2A_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2B_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2C_FP_UNKNOWN)); +} + + +void __chLevelCollectible_callDialog(enum asset_e text_id){ + gcdialog_showDialogConditional(text_id, 0, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker*,s32,s32))__chLevelCollectible_dialogCallback); +} + +void __chLevelCollectible_collide(ActorMarker *marker, ActorMarker *other_marker) { + Actor *this; + f32 pad28; + s32 dialog_id; + f32 sp18[3]; + + this = marker_getActor(marker); + dialog_id = 0; + if ((this->state == 1) || (this->state == 2)) { + sp18[0] = this->position[0]; + sp18[1] = this->position[1]; + sp18[2] = this->position[2]; + switch (marker->id) { + case MARKER_36_ORANGE_COLLECTIBLE: + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_1_ORANGE_HAS_BEEN_COLLECTED)) { + return; + } + + progressDialog_showDialogMaskFour(FILEPROG_8_ORANGE_TEXT); + func_8030E6D4(SFX_B3_ORANGE_TALKING); + dialog_id = 0; + break; + + case MARKER_37_GOLD_BULLION: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + timedFunc_set_1(0.5f, (GenFunction_1)progressDialog_showDialogMaskFour, FILEPROG_9_GOLD_BULLION_TEXT); + dialog_id = 0; + break; + + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + levelSpecificFlags_set(LEVEL_FLAG_2A_FP_UNKNOWN, true); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); + dialog_id = ASSET_C20_DIALOG_PRESENT_COLLECTIBLE_MEET_BLUE; + break; + + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + levelSpecificFlags_set(LEVEL_FLAG_2B_FP_UNKNOWN, true); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_712_SPRITE_SPARKLE_GREEN); + dialog_id = ASSET_C21_DIALOG_PRESENT_COLLECTIBLE_MEET_GREEN; + break; + + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + levelSpecificFlags_set(LEVEL_FLAG_2C_FP_UNKNOWN, true); + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); + __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); + dialog_id = ASSET_C22_DIALOG_PRESENT_COLLECTIBLE_MEET_RED; + break; + + default: + break; + } + if (dialog_id != 0) { + timedFunc_set_1(0.5f, (GenFunction_1)__chLevelCollectible_callDialog, dialog_id); + } + func_8028F030(this->modelCacheIndex); + marker_despawn(marker); + } +} + +void func_802D7DE8(ActorMarker *marker, f32 arg1[3]) { + Actor *this; + s32 sp50[3]; + s32 sp4C; + f32 var_f12; + f32 var_f14; + f32 var_f18; + + sp4C = marker->id; + this = marker_getActor(marker); + ml_vec3f_to_vec3w(sp50, arg1); + if (sp4C == MARKER_37_GOLD_BULLION) { + if (mapSpecificFlags_get(0)) { + mapSpecificFlags_set(1, true); + } else { + mapSpecificFlags_set(0, true); + } + } + func_8028F010(this->modelCacheIndex); + subaddie_set_state(this, 4); + var_f12 = this->position[1]; + var_f14 = 28.0f; + var_f18 = 0.0f; + this->unk1C[0] = arg1[0]; + this->unk1C[1] = arg1[1]; + this->unk1C[2] = arg1[2]; + this->velocity[0] = (f32) sp50[0] - this->position[0]; + this->velocity[1] = 28.0f; + this->velocity[2] = (f32) sp50[2] - this->position[2]; + while (!(var_f12 < sp50[1]) || !(var_f14 < 0.0f)) { + var_f18 += 1.0f; + var_f12 += (var_f14 -= 5.0); + } + this->velocity[0] /= var_f18; + this->velocity[2] /= var_f18; + this->unk38_31 = (u32)var_f18; +} + +void func_802D8030(Actor *this){ + s32 *local; + + local = (s32*)&this->local; + *local = 1; + this->marker->collisionFunc = __chLevelCollectible_collide; + subaddie_set_state(this, 2); +} + +void __chLevelCollectible_returnObj(Actor *this) { + s32 *local; + f32 sp20; + + local = (s32*)&this->local; + if( (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) + || (this->secondaryId == 0) + ) { + this->position[0] += this->velocity[0]; + this->position[1] += (this->velocity[1] -= 5.0); + this->position[2] += this->velocity[2]; + } + if (--this->unk38_31 < 4) { + sp20 = this->unk1C[1]; + } else { + sp20 = this->position[1]; + } + if (this->position[1] < sp20) { + if (this->modelCacheIndex == ACTOR_2A_GOLD_BULLION) { + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + if (mapSpecificFlags_get(1)) { + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 32000); + } + } + this->position[1] = sp20; + if (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) { + sfx_playFadeShorthandDefault(SFX_21_EGG_BOUNCE_1, 0.76f, 25000, this->position, 1000, 2000); + } else { + sfx_playFadeShorthandDefault(SFX_B3_ORANGE_TALKING, 1.0f, 25000, this->position, 1000, 2000); + } + if (this->state == 4) { + switch (this->marker->id) { + case MARKER_37_GOLD_BULLION: + break; + case MARKER_36_ORANGE_COLLECTIBLE: + timed_mapSpecificFlags_setTrue(1.7f, MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED); + coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); + break; + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + levelSpecificFlags_set(LEVEL_FLAG_11_FP_UNKNOWN, true); + break; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + levelSpecificFlags_set(LEVEL_FLAG_12_FP_UNKNOWN, true); + break; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); + levelSpecificFlags_set(LEVEL_FLAG_13_FP_UNKNOWN, true); + break; + } + } + this->unk138_22 = this->unk138_21 = 0; + subaddie_set_state(this, 2); + } + switch (this->marker->id) { + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); + break; + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, 0x712); + break; + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); + break; + } + + if (*local != 0) { + *local = 0; + } +} + +void func_802D8374(Actor *this){ + s32 pad2C; + f32 sp20[3]; + + if(func_8028E86C() != this->marker){ + func_8028F050(this->modelCacheIndex); + marker_despawn(this->marker); + } + else{ + if(this->unk138_21){ + func_8028EF28(sp20); + func_802D7DE8(this->marker, sp20); + } + } +} + +void func_802D83EC(Actor *this) { + s32 var_s0; + + // temp_f20 = D_80376D70; + for(var_s0 = 0; var_s0 < 10; var_s0++){ + if (randf() < 0.03) { + commonParticle_add(this->marker, var_s0 + 5, func_80329904); + commonParticle_new(8, this->marker->unk14_21); + } + } + this->yaw = this->yaw + time_getDelta() * 25.0f; + if (360.0 < this->yaw) { + this->yaw -= 360.0; + } + if (mapSpecificFlags_get(0x1F)) { + marker_despawn(this->marker); + } +} + +void func_802D84F4(Actor *this){ + this->marker->propPtr->unk8_3 = ( this->state == 2 ); +} + +void chLevelCollectible_update(Actor *this){ + s32 marker_id; + if(this->despawn_flag) return; + + if(!this->volatile_initialized){ + this->volatile_initialized = true; + if( this->marker->id == MARKER_1FD_BLUE_PRESENT_COLLECTIBLE + || this->marker->id == MARKER_1FE_GREEN_PRESENT_COLLECTIBLE + || this->marker->id == MARKER_1FF_RED_PRESENT_COLLECTIBLE + ){ + if(jiggyscore_isCollected(JIGGY_2E_FP_PRESENTS)){ + marker_despawn(this->marker); + return; + } + } + if(this->unk138_22){ + func_8028F7D4(0.0f, 0.0f); + subaddie_set_state(this, 3); + } + }//L802D85DC + + switch(this->state){ + case 5:// 802D8604 + func_802D8030(this); + break; + + case 1:// 802D8620 + __chLevelCollectible_returnObj(this); + break; + + case 2:// 802D863C + break; + + case 3:// 802D8650 + func_802D8374(this); + break; + + case 4:// 802D866C + __chLevelCollectible_returnObj(this); + break; + + default: + break; + } + + marker_id = this->marker->id; + + switch(this->marker->id){ + + case MARKER_37_GOLD_BULLION: //L802D86CC + func_802D83EC(this); + break; + case MARKER_36_ORANGE_COLLECTIBLE: //L802D86DC + if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_3_CHIMPY_HAS_LEFT) && gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN) { + marker_despawn(this->marker); + } + break; + + case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: + case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: + case MARKER_1FF_RED_PRESENT_COLLECTIBLE: + func_802D84F4(this); + break; + } +} diff --git a/src/core2/ch/levelcollectible.c b/src/core2/ch/levelcollectible.c deleted file mode 100644 index 2591e199d..000000000 --- a/src/core2/ch/levelcollectible.c +++ /dev/null @@ -1,692 +0,0 @@ -// BanjoDecomp: core2/levelcollectible.c -#include -#include "functions.h" -#include "variables.h" -#include "port/Enhancements/Retention/Retention.h" - -extern void func_8028F7D4(f32, f32); -void chLevelCollectible_update(Actor *this); -extern ActorMarker *bacarry_getMarkerWithExtraSteps(void); - -static s32 levelCollectible_syncKind(s32 markerId) { - switch (markerId) { - case MARKER_36_ORANGE_COLLECTIBLE: return ANCHOR_COLLECTIBLE_ORANGE; - case MARKER_37_GOLD_BULLION: return ANCHOR_COLLECTIBLE_GOLD; - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: return ANCHOR_COLLECTIBLE_PRESENT_BLUE; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: return ANCHOR_COLLECTIBLE_PRESENT_GREEN; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: return ANCHOR_COLLECTIBLE_PRESENT_RED; - default: return -1; - } -} - -extern s32 port_anchor_getDummyTransform(u32 clientId, f32 pos[3], f32* yaw); -extern void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]); - -void __chLevelCollectible_presentReturnEmitSparkles(f32 position[3], enum asset_e sprite_id); - -#define REMOTE_CARRY_MAX 16 -static struct { - u32 clientId; // 0 = free slot - ActorMarker *marker; // NULL while the spawn is still queued - s32 markerId; - u8 throwPending; - f32 throwStart[3]; - f32 throwTarget[3]; - f32 carryOff[3]; // held pose: object position relative to the owner - f32 carryYawOff; // held pose: object yaw relative to the owner's yaw -} sRemoteCarry[REMOTE_CARRY_MAX]; - -static s32 __remoteCarry_actorIdForMarker(s32 markerId) { - switch (markerId) { - case MARKER_36_ORANGE_COLLECTIBLE: return ACTOR_29_ORANGE_COLLECTIBLE; - case MARKER_37_GOLD_BULLION: return ACTOR_2A_GOLD_BULLION; - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: return ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: return ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: return ACTOR_1F1_RED_PRESENT_COLLECTIBLE; - case MARKER_1B5_CATERPILLAR: return ACTOR_2A2_CATERPILLAR; - case 0x1BC /* acorn marker (unnamed) */: return ACTOR_2A9_ACORN; - default: return 0; - } -} - -static s32 __remoteCarry_findByClient(u32 clientId) { - s32 i; - for (i = 0; i < REMOTE_CARRY_MAX; i++) { - if (sRemoteCarry[i].clientId == clientId) { - return i; - } - } - return -1; -} - -static s32 __remoteCarry_findByMarker(ActorMarker *marker) { - s32 i; - for (i = 0; i < REMOTE_CARRY_MAX; i++) { - if (sRemoteCarry[i].clientId != 0 && sRemoteCarry[i].marker == marker) { - return i; - } - } - return -1; -} - -static void __remoteCarry_clearSlot(s32 slot) { - sRemoteCarry[slot].clientId = 0; - sRemoteCarry[slot].marker = NULL; - sRemoteCarry[slot].markerId = 0; - sRemoteCarry[slot].throwPending = 0; - sRemoteCarry[slot].carryOff[0] = sRemoteCarry[slot].carryOff[1] = sRemoteCarry[slot].carryOff[2] = 0.0f; - sRemoteCarry[slot].carryYawOff = 0.0f; -} - -static void __remoteCarry_setPose(s32 slot, f32 offset[3], f32 yawOffset) { - sRemoteCarry[slot].carryOff[0] = offset[0]; - sRemoteCarry[slot].carryOff[1] = offset[1]; - sRemoteCarry[slot].carryOff[2] = offset[2]; - sRemoteCarry[slot].carryYawOff = yawOffset; -} - -// Mirror of func_802D7DE8's arc math without its side effects. State 7 = remote flight. -static void __remoteCarry_launch(Actor *actor, f32 start[3], f32 target[3]) { - s32 tgt[3]; - f32 var_f12; - f32 var_f14; - f32 var_f18; - - actor->position[0] = start[0]; - actor->position[1] = start[1]; - actor->position[2] = start[2]; - ml_vec3f_to_vec3w(tgt, target); - actor->unk1C[0] = target[0]; - actor->unk1C[1] = target[1]; - actor->unk1C[2] = target[2]; - actor->velocity[0] = (f32)tgt[0] - actor->position[0]; - actor->velocity[1] = 28.0f; - actor->velocity[2] = (f32)tgt[2] - actor->position[2]; - var_f12 = actor->position[1]; - var_f14 = 28.0f; - var_f18 = 0.0f; - while (!(var_f12 < tgt[1]) || !(var_f14 < 0.0f)) { - var_f18 += 1.0f; - var_f12 += (var_f14 -= 5.0); - } - actor->velocity[0] /= var_f18; - actor->velocity[2] /= var_f18; - actor->unk38_31 = (u32)var_f18; - subaddie_set_state(actor, 7); -} - -static void __remoteCarry_spawnMethod(s32 markerId, s32 clientId) { - f32 pos[3]; - f32 yaw = 0.0f; - Actor *actor; - s32 slot = __remoteCarry_findByClient((u32)clientId); - s32 actorId = __remoteCarry_actorIdForMarker(markerId); - - if (slot < 0 || sRemoteCarry[slot].markerId != markerId || actorId == 0) { - return; // stale queue entry - } - if (!port_anchor_getDummyTransform((u32)clientId, pos, &yaw)) { - __remoteCarry_clearSlot(slot); - return; - } - actor = actor_spawnWithYaw_f32(actorId, pos, (s32)yaw); - // Display copy: skip init, no collision with the local player. - actor->volatile_initialized = true; - actor->marker->propPtr->unk8_3 = false; - if (sRemoteCarry[slot].throwPending) { - __remoteCarry_launch(actor, sRemoteCarry[slot].throwStart, sRemoteCarry[slot].throwTarget); - __remoteCarry_clearSlot(slot); - } else { - sRemoteCarry[slot].marker = actor->marker; - subaddie_set_state(actor, 6); - } -} - -void port_remoteCarry_setCarried(u32 clientId, s32 markerId, f32 offset[3], f32 yawOffset) { - s32 slot; - if (clientId == 0) { - return; - } - if (markerId != 0 && __remoteCarry_actorIdForMarker(markerId) == 0) { - markerId = 0; // not a synced carryable - } - slot = __remoteCarry_findByClient(clientId); - if (markerId == 0) { - if (slot >= 0 && !sRemoteCarry[slot].throwPending) { - if (sRemoteCarry[slot].marker != NULL) { - marker_despawn(sRemoteCarry[slot].marker); - } - __remoteCarry_clearSlot(slot); - } - return; - } - if (slot >= 0) { - if (sRemoteCarry[slot].markerId == markerId) { - __remoteCarry_setPose(slot, offset, yawOffset); - return; - } - if (sRemoteCarry[slot].marker != NULL) { - marker_despawn(sRemoteCarry[slot].marker); - } - __remoteCarry_clearSlot(slot); - } - slot = __remoteCarry_findByClient(0); - if (slot < 0) { - return; // registry full - } - sRemoteCarry[slot].clientId = clientId; - sRemoteCarry[slot].markerId = markerId; - sRemoteCarry[slot].marker = NULL; - sRemoteCarry[slot].throwPending = 0; - __remoteCarry_setPose(slot, offset, yawOffset); - __spawnQueue_add_2((GenFunction_2)__remoteCarry_spawnMethod, markerId, clientId); -} - -void port_remoteCarry_throw(u32 clientId, s32 markerId, f32 start[3], f32 target[3]) { - s32 slot; - if (clientId == 0 || __remoteCarry_actorIdForMarker(markerId) == 0) { - return; - } - slot = __remoteCarry_findByClient(clientId); - if (slot >= 0 && sRemoteCarry[slot].marker != NULL) { - Actor *actor = marker_getActor(sRemoteCarry[slot].marker); - __remoteCarry_launch(actor, start, target); - __remoteCarry_clearSlot(slot); - return; - } - if (slot < 0) { - slot = __remoteCarry_findByClient(0); - if (slot < 0) { - return; - } - sRemoteCarry[slot].clientId = clientId; - __spawnQueue_add_2((GenFunction_2)__remoteCarry_spawnMethod, markerId, clientId); - } - sRemoteCarry[slot].markerId = markerId; - sRemoteCarry[slot].throwPending = 1; - sRemoteCarry[slot].throwStart[0] = start[0]; - sRemoteCarry[slot].throwStart[1] = start[1]; - sRemoteCarry[slot].throwStart[2] = start[2]; - sRemoteCarry[slot].throwTarget[0] = target[0]; - sRemoteCarry[slot].throwTarget[1] = target[1]; - sRemoteCarry[slot].throwTarget[2] = target[2]; -} - -void port_remoteCarry_reset(void) { - s32 i; - for (i = 0; i < REMOTE_CARRY_MAX; i++) { - __remoteCarry_clearSlot(i); - } -} - -s32 port_remoteCarry_displayUpdate(Actor *this) { - s32 slot = __remoteCarry_findByMarker(this->marker); - - if (this->state == 6 || slot >= 0) { // carried: glued to the owner's dummy - f32 pos[3]; - f32 yaw = 0.0f; - if (slot < 0 || !port_anchor_getDummyTransform(sRemoteCarry[slot].clientId, pos, &yaw)) { - if (slot >= 0) { - __remoteCarry_clearSlot(slot); - } - marker_despawn(this->marker); - return 1; - } - this->position[0] = pos[0] + sRemoteCarry[slot].carryOff[0]; - this->position[1] = pos[1] + sRemoteCarry[slot].carryOff[1]; - this->position[2] = pos[2] + sRemoteCarry[slot].carryOff[2]; - this->yaw = mlNormalizeAngle(yaw + sRemoteCarry[slot].carryYawOff); - return 1; - } - - if (this->state == 7) { // thrown: replay the arc, land with feedback only - f32 landY; - this->position[0] += this->velocity[0]; - this->position[1] += (this->velocity[1] -= 5.0); - this->position[2] += this->velocity[2]; - landY = (--this->unk38_31 < 4) ? this->unk1C[1] : this->position[1]; - if (this->position[1] < landY) { - if (this->modelCacheIndex == ACTOR_2A2_CATERPILLAR || this->modelCacheIndex == ACTOR_2A9_ACORN) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); - marker_despawn(this->marker); - return 1; - } - if (this->modelCacheIndex == ACTOR_2A_GOLD_BULLION) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - } - if (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) { - sfx_playFadeShorthandDefault(SFX_21_EGG_BOUNCE_1, 0.76f, 25000, this->position, 1000, 2000); - } else { - sfx_playFadeShorthandDefault(SFX_B3_ORANGE_TALKING, 1.0f, 25000, this->position, 1000, 2000); - } - // State 8: landed display copy. - this->position[1] = landY; - subaddie_set_state(this, 8); - return 1; - } - switch (this->marker->id) { - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); - break; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, 0x712); - break; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); - break; - } - return 1; - } - - // State 8 (landed display copy) falls through to the vanilla lifecycle below. - - return 0; -} -extern void timed_mapSpecificFlags_setTrue(f32, s32); -extern void progressDialog_showDialogMaskFour(s32); - -ActorAnimationInfo chPresentCollectibleAnimations[] = { - {0, 0.0f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f}, - {ASSET_18A_ANIM_XMAS_GIFT, 1.5f} -}; - -ActorInfo chOrangeCollectible = { - MARKER_36_ORANGE_COLLECTIBLE, ACTOR_29_ORANGE_COLLECTIBLE, ASSET_2D2_MODEL_ORANGE, - 0x5, NULL, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.6f,0 -}; - -ActorInfo chGoldBullion = { - MARKER_37_GOLD_BULLION, ACTOR_2A_GOLD_BULLION, ASSET_3C7_MODEL_GOLD_BULLION, - 0x5, NULL, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 0.6f, 0 -}; - -ActorInfo chBluePresentCollectible = { - MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE, ASSET_47F_MODEL_XMAS_GIFT_BLUE, - 0x5, chPresentCollectibleAnimations, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 1.8f, 0 -}; - -ActorInfo chGreenPresentCollectible = { - MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE, ASSET_480_MODEL_XMAS_GIFT_GREEN, - 0x5, chPresentCollectibleAnimations, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 1.4f, 0 -}; - -ActorInfo chRedPresentCollectible = { - MARKER_1FF_RED_PRESENT_COLLECTIBLE, ACTOR_1F1_RED_PRESENT_COLLECTIBLE, ASSET_481_MODEL_XMAS_GIFT_RED, - 0x5, chPresentCollectibleAnimations, - chLevelCollectible_update, actor_update_func_80326224, actor_draw, - 0, 0, 1.4f, 0 -}; - -/* .code */ -void __chLevelCollectible_presentReturnEmitSparkles(f32 position[3], enum asset_e sprite_id) { - static ParticleScaleAndLifetimeRanges D_80367C34 = {{0.2f, 0.4f}, {0.1f, 0.1f}, {0.0f, 0.01f}, {3.0f, 3.5f}, 0.1f, 0.1f}; - ParticleEmitter *p_emitter; - - p_emitter = partEmitMgr_newEmitter(1); - particleEmitter_setSprite(p_emitter, sprite_id); - particleEmitter_setStartingFrameRange(p_emitter, 0, 7); - particleEmitter_setPosition(p_emitter, position); - particleEmitter_setSpawnPositionRange(p_emitter, -40.0f, 0.0f, -40.0f, 40.0f, 60.0f, 40.0f); - particleEmitter_setAccelerationRange(p_emitter, 0.0f, -1000.0f, 0.0f, 0.0f, -1000.0f, 0.0f); - particleEmitter_setScaleAndLifetimeRanges(p_emitter, &D_80367C34); - particleEmitter_emitN(p_emitter, 1); -} - -void __chLevelCollectible_presentCollectEmitSparkles(f32 position[3], enum asset_e sprite_id) { - ParticleEmitter *p_emitter; - - p_emitter = partEmitMgr_newEmitter(8); - particleEmitter_setSprite(p_emitter, sprite_id); - particleEmitter_setPosition(p_emitter, position); - particleEmitter_setAccelerationRange(p_emitter, 0.0f, -250.0f, 0.0f, 0.0f, -250.0f, 0.0f); - particleEmitter_setParticleVelocityRange(p_emitter, -100.0f, 200.0f, -100.0f, 100.0f, 350.0f, 100.0f); - particleEmitter_setAngularVelocityRange(p_emitter, 0.0f, 0.0f, 200.0f, 0.0f, 0.0f, 240.0f); - particleEmitter_setStartingScaleRange(p_emitter, 0.47f, 0.47f); - particleEmitter_setFinalScaleRange(p_emitter, 0.03f, 0.03f); - particleEmitter_setFade(p_emitter, 0.4f, 0.8f); - particleEmitter_setParticleLifeTimeRange(p_emitter, 0.9f, 0.9f); - particleEmitter_emitN(p_emitter, 8); -} - -s32 __chLevelCollectible_dialogCallback(ActorMarker *marker, enum asset_e text_id, s32 arg2) { - return -(levelSpecificFlags_get(LEVEL_FLAG_2A_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2B_FP_UNKNOWN) + levelSpecificFlags_get(LEVEL_FLAG_2C_FP_UNKNOWN)); -} - - -void __chLevelCollectible_callDialog(enum asset_e text_id){ - gcdialog_showDialogConditional(text_id, 0, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker*,s32,s32))__chLevelCollectible_dialogCallback); -} - -void __chLevelCollectible_collide(ActorMarker *marker, ActorMarker *other_marker) { - Actor *this; - f32 pad28; - s32 dialog_id; - f32 sp18[3]; - - this = marker_getActor(marker); - dialog_id = 0; - if ((this->state == 1) || (this->state == 2)) { - sp18[0] = this->position[0]; - sp18[1] = this->position[1]; - sp18[2] = this->position[2]; - switch (marker->id) { - case MARKER_36_ORANGE_COLLECTIBLE: - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_1_ORANGE_HAS_BEEN_COLLECTED)) { - return; - } - - progressDialog_showDialogMaskFour(FILEPROG_8_ORANGE_TEXT); - func_8030E6D4(SFX_B3_ORANGE_TALKING); - dialog_id = 0; - break; - - case MARKER_37_GOLD_BULLION: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - timedFunc_set_1(0.5f, (GenFunction_1)progressDialog_showDialogMaskFour, FILEPROG_9_GOLD_BULLION_TEXT); - dialog_id = 0; - break; - - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - levelSpecificFlags_set(LEVEL_FLAG_2A_FP_UNKNOWN, true); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); - dialog_id = VER_SELECT(ASSET_C20_DIALOG_PRESENT_COLLECTIBLE_MEET_BLUE, 0x99A, 0, 0); - break; - - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - levelSpecificFlags_set(LEVEL_FLAG_2B_FP_UNKNOWN, true); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_712_SPRITE_SPARKLE_GREEN); - dialog_id = VER_SELECT(ASSET_C21_DIALOG_PRESENT_COLLECTIBLE_MEET_GREEN, 0x99B, 0, 0); - break; - - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - levelSpecificFlags_set(LEVEL_FLAG_2C_FP_UNKNOWN, true); - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 0x7FFF); - __chLevelCollectible_presentCollectEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); - dialog_id = VER_SELECT(ASSET_C22_DIALOG_PRESENT_COLLECTIBLE_MEET_RED, 0x99C, 0, 0); - break; - - default: - break; - } - if (dialog_id != 0) { - timedFunc_set_1(0.5f, (GenFunction_1)__chLevelCollectible_callDialog, dialog_id); - } - bacarriedobj_incWithExtraSteps(this->modelCacheIndex); - { - s32 kind = levelCollectible_syncKind(marker->id); - if (kind >= 0) { - port_carriedSync_onLocalCollect(kind, marker); - } - } - marker_despawn(marker); - } -} - -void func_802D7DE8(ActorMarker *marker, f32 arg1[3]) { - Actor *this; - s32 sp50[3]; - s32 sp4C; - f32 var_f12; - f32 var_f14; - f32 var_f18; - - sp4C = marker->id; - this = marker_getActor(marker); - ml_vec3f_to_vec3w(sp50, arg1); - if (sp4C == MARKER_37_GOLD_BULLION) { - if (mapSpecificFlags_get(0)) { - mapSpecificFlags_set(1, true); - } else { - mapSpecificFlags_set(0, true); - } - } - bacarriedobj_decWithExtraSteps(this->modelCacheIndex); - { - s32 kind = levelCollectible_syncKind(marker->id); - if (kind >= 0) { - port_carriedSync_onLocalSpend(kind); - } - } - subaddie_set_state(this, 4); - var_f12 = this->position[1]; - var_f14 = 28.0f; - var_f18 = 0.0f; - this->unk1C[0] = arg1[0]; - this->unk1C[1] = arg1[1]; - this->unk1C[2] = arg1[2]; - this->velocity[0] = (f32) sp50[0] - this->position[0]; - this->velocity[1] = 28.0f; - this->velocity[2] = (f32) sp50[2] - this->position[2]; - while (!(var_f12 < sp50[1]) || !(var_f14 < 0.0f)) { - var_f18 += 1.0f; - var_f12 += (var_f14 -= 5.0); - } - this->velocity[0] /= var_f18; - this->velocity[2] /= var_f18; - this->unk38_31 = (u32)var_f18; -} - -void func_802D8030(Actor *this){ - s32 *local; - - local = (s32*)&this->local; - *local = 1; - this->marker->collisionFunc = __chLevelCollectible_collide; - subaddie_set_state(this, 2); -} - -void __chLevelCollectible_returnObj(Actor *this) { - s32 *local; - f32 sp20; - - local = (s32*)&this->local; - if( (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) - || (this->secondaryId == 0) - ) { - this->position[0] += this->velocity[0]; - this->position[1] += (this->velocity[1] -= 5.0); - this->position[2] += this->velocity[2]; - } - if (--this->unk38_31 < 4) { - sp20 = this->unk1C[1]; - } else { - sp20 = this->position[1]; - } - if (this->position[1] < sp20) { - if (this->modelCacheIndex == ACTOR_2A_GOLD_BULLION) { - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - if (mapSpecificFlags_get(1)) { - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 32000); - } - } - this->position[1] = sp20; - if (this->marker->id != MARKER_36_ORANGE_COLLECTIBLE) { - sfx_playFadeShorthandDefault(SFX_21_EGG_BOUNCE_1, 0.76f, 25000, this->position, 1000, 2000); - } else { - sfx_playFadeShorthandDefault(SFX_B3_ORANGE_TALKING, 1.0f, 25000, this->position, 1000, 2000); - } - if (this->state == 4) { - switch (this->marker->id) { - case MARKER_37_GOLD_BULLION: - break; - case MARKER_36_ORANGE_COLLECTIBLE: - timed_mapSpecificFlags_setTrue(1.7f, MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED); - coMusicPlayer_playMusic(COMUSIC_2D_PUZZLE_SOLVED_FANFARE, 0x7FFF); - break; - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - levelSpecificFlags_set(LEVEL_FLAG_11_FP_UNKNOWN, true); - break; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - levelSpecificFlags_set(LEVEL_FLAG_12_FP_UNKNOWN, true); - break; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 32000); - levelSpecificFlags_set(LEVEL_FLAG_13_FP_UNKNOWN, true); - break; - } - } - this->unk138_22 = this->unk138_21 = 0; - subaddie_set_state(this, 2); - } - switch (this->marker->id) { - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_711_SPRITE_SPARKLE_DARK_BLUE); - break; - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, 0x712); - break; - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - __chLevelCollectible_presentReturnEmitSparkles(this->position, ASSET_715_SPRITE_SPARKLE_RED); - break; - } - - if (*local != 0) { - *local = 0; - } -} - -void func_802D8374(Actor *this){ - s32 pad2C; - f32 sp20[3]; - - if(bacarry_getMarkerWithExtraSteps() != this->marker){ - bacarriedobj_displayOnHudWithExtraSteps(this->modelCacheIndex); - marker_despawn(this->marker); - } - else{ - if(this->unk138_21){ - func_8028EF28(sp20); - // [port] Anchor: replay this throw on teammates; sent before func_802D7DE8 moves the actor. - port_anchor_onCarryThrow(this->marker->id, this->position, sp20); - func_802D7DE8(this->marker, sp20); - } - } -} - -void func_802D83EC(Actor *this) { - s32 var_s0; - - // temp_f20 = D_80376D70; - for(var_s0 = 0; var_s0 < 10; var_s0++){ - if (randf() < 0.03) { - commonParticle_add(this->marker, var_s0 + 5, func_80329904); - commonParticle_new(8, this->marker->unk14_21); - } - } - this->yaw = this->yaw + time_getDelta() * 25.0f; - if (360.0 < this->yaw) { - this->yaw -= 360.0; - } - if (mapSpecificFlags_get(0x1F)) { - marker_despawn(this->marker); - } -} - -void func_802D84F4(Actor *this){ - this->marker->propPtr->unk8_3 = ( this->state == 2 ); -} - -void chLevelCollectible_update(Actor *this){ - s32 marker_id; - if(this->despawn_flag) return; - - if (port_remoteCarry_displayUpdate(this)) { - return; - } - - if(!this->volatile_initialized){ - this->volatile_initialized = true; - if( this->marker->id == MARKER_1FD_BLUE_PRESENT_COLLECTIBLE - || this->marker->id == MARKER_1FE_GREEN_PRESENT_COLLECTIBLE - || this->marker->id == MARKER_1FF_RED_PRESENT_COLLECTIBLE - ){ - if(jiggyscore_isCollected(JIGGY_2E_FP_PRESENTS)){ - marker_despawn(this->marker); - return; - } - } - if(this->unk138_22){ - func_8028F7D4(0.0f, 0.0f); - subaddie_set_state(this, 3); - } else { - s32 kind = levelCollectible_syncKind(this->marker->id); - if (kind >= 0) { - s32 suppress; - port_carriedSync_register(kind, this->marker, (s32)this->position[0], - (s32)this->position[1], (s32)this->position[2], &suppress); - if (suppress) { - marker_despawn(this->marker); - return; - } - } - } - }//L802D85DC - - if (!this->unk138_22) { - s32 kind = levelCollectible_syncKind(this->marker->id); - if (kind >= 0 && port_carriedSync_consumeRemoteDespawn(kind, this->marker)) { - marker_despawn(this->marker); - return; - } - } - - switch(this->state){ - case 5:// 802D8604 - func_802D8030(this); - break; - - case 1:// 802D8620 - __chLevelCollectible_returnObj(this); - break; - - case 2:// 802D863C - break; - - case 3:// 802D8650 - func_802D8374(this); - break; - - case 4:// 802D866C - __chLevelCollectible_returnObj(this); - break; - - default: - break; - } - - marker_id = this->marker->id; - - switch(this->marker->id){ - - case MARKER_37_GOLD_BULLION: //L802D86CC - func_802D83EC(this); - break; - case MARKER_36_ORANGE_COLLECTIBLE: //L802D86DC - if (mapSpecificFlags_get(MM_SPECIFIC_FLAG_3_CHIMPY_HAS_LEFT) && gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN) { - marker_despawn(this->marker); - } - break; - - case MARKER_1FD_BLUE_PRESENT_COLLECTIBLE: - case MARKER_1FE_GREEN_PRESENT_COLLECTIBLE: - case MARKER_1FF_RED_PRESENT_COLLECTIBLE: - func_802D84F4(this); - break; - } -} diff --git a/src/core2/ch/mole.c b/src/core2/ch/mole.c index ca9a701a5..fc2813357 100644 --- a/src/core2/ch/mole.c +++ b/src/core2/ch/mole.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/mole.c #include #include "functions.h" #include "variables.h" @@ -15,29 +14,6 @@ typedef struct{ } ChMoleDescription; /* .data */ - -enum mole_states -{ - MOLE_STATE_1_AWAITING_PLAYER = 1, - MOLE_STATE_2_POP_OUT_OF_MOLEHILL, - MOLE_STATE_3_EXPLAINING_ABILITY, - MOLE_STATE_4_REENTER_MOLEHILL, - MOLE_STATE_5_REFRESHER -}; - -enum mole_ability_learn_actions -{ - MOLE_ABILITY_LEARN_ACTION_1_STILT_STRIDE = 1, - MOLE_ABILITY_LEARN_ACTION_2_UNK, - MOLE_ABILITY_LEARN_ACTION_3_TURBO_TALON_TRAINER, - MOLE_ABILITY_LEARN_ACTION_4_UNK, - MOLE_ABILITY_LEARN_ACTION_5_EGG_FIRING, - MOLE_ABILITY_LEARN_ACTION_6_FLIGHT, - MOLE_ABILITY_LEARN_ACTION_7_WONDERWING, - MOLE_ABILITY_LEARN_ACTION_8_REFILL_HEALTH, - MOLE_ABILITY_LEARN_ACTION_FF_UNK = 0xFF -}; - ActorAnimationInfo moleAnimations[]= { {0, 0.0f}, {ASSET_13A_ANIM_BOTTLES_ENTER, 2000000000.0f}, @@ -54,22 +30,22 @@ ActorInfo gChMole = { 0, 0, 0.0f, 0 }; +// D_80367DC4 ChMoleDescription moleTable[] = { - {VER_SELECT(ASSET_C23_DIALOG_BEAKBOMB_LEARN, 0x99D, 0, 0), VER_SELECT(ASSET_C24_DIALOG_BEAKBOMB_REFRESHER, 0x99E, 0, 0), 0x0F, ABILITY_1_BEAK_BOMB}, - {VER_SELECT(ASSET_B47_DIALOG_EGGS_LEARN, 0x965, 0, 0), VER_SELECT(ASSET_B4B_DIALOG_EGGS_REFRESHER, 0x969, 0, 0), 0x16, ABILITY_6_EGGS}, - {VER_SELECT(ASSET_B48_DIALOG_BEAKBUSTER_LEARN, 0x966, 0, 0), VER_SELECT(ASSET_B4C_DIALOG_BEAKBUSTER_REFRESHER, 0x96A, 0, 0), 0x17, ABILITY_2_BEAK_BUSTER}, - {VER_SELECT(ASSET_B49_DIALOG_TALON_TROT_LEARN, 0x967, 0, 0), VER_SELECT(ASSET_B4A_DIALOG_TALON_TROT_REFRESHER, 0x968, 0, 0), 0x18, ABILITY_10_TALON_TROT}, - {VER_SELECT(ASSET_A1F_DIALOG_SHOCKJUMP_LEARN, 0x91F, 0, 0), VER_SELECT(ASSET_A23_DIALOG_SHOCKJUMP_REFRESHER, 0x923, 0, 0), 0x0C, ABILITY_D_SHOCK_JUMP}, - {VER_SELECT(ASSET_A20_DIALOG_FLY_LEARN, 0x920, 0, 0), VER_SELECT(ASSET_A22_DIALOG_FLY_REFRESHER, 0x922, 0, 0), 0x0D, ABILITY_9_FLIGHT}, - {VER_SELECT(ASSET_D35_DIALOG_WONDERWING_LEARN, 0xA08, 0, 0), VER_SELECT(ASSET_D36_DIALOG_WONDERWING_REFRESHER, 0xA09, 0, 0), 0x01, ABILITY_12_WONDERWING}, - {VER_SELECT(ASSET_C88_DIALOG_WADING_BOOTS_LEARN, 0x9CB, 0, 0), VER_SELECT(ASSET_C89_DIALOG_WADING_BOOTS_REFRESHER, 0x9CC, 0, 0), 0x10, ABILITY_E_WADING_BOOTS}, - {VER_SELECT(ASSET_A84_DIALOG_TURBOTRAINERS_LEARN, 0x940, 0, 0), VER_SELECT(ASSET_A85_DIALOG_TURBOTRAINERS_REFRESHER, 0x941, 0, 0), 0x19, ABILITY_11_TURBO_TALON}, - {VER_SELECT(ASSET_F64_DIALOG_NOTEDOORS_LEARN, 0xACA, 0, 0), VER_SELECT(ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, 0xACB, 0, 0), 0x0E, ABILITY_13_1ST_NOTEDOOR} + {ASSET_C23_DIALOG_BEAKBOMB_LEARN, ASSET_C24_DIALOG_BEAKBOMB_REFRESHER, 0x0F, ABILITY_1_BEAK_BOMB}, + {ASSET_B47_DIALOG_EGGS_LEARN, ASSET_B4B_DIALOG_EGGS_REFRESHER, 0x16, ABILITY_6_EGGS}, + {ASSET_B48_DIALOG_BEAKBUSTER_LEARN, ASSET_B4C_DIALOG_BEAKBUSTER_REFRESHER, 0x17, ABILITY_2_BEAK_BUSTER}, + {ASSET_B49_DIALOG_TALON_TROT_LEARN, ASSET_B4A_DIALOG_TALON_TROT_REFRESHER, 0x18, ABILITY_10_TALON_TROT}, + {ASSET_A1F_DIALOG_SHOCKJUMP_LEARN, ASSET_A23_DIALOG_SHOCKJUMP_REFRESHER, 0x0C, ABILITY_D_SHOCK_JUMP}, + {ASSET_A20_DIALOG_FLY_LEARN, ASSET_A22_DIALOG_FLY_REFRESHER, 0x0D, ABILITY_9_FLIGHT}, + {ASSET_D35_DIALOG_WONDERWING_LEARN, ASSET_D36_DIALOG_WONDERWING_REFRESHER, 0x01, ABILITY_12_WONDERWING}, + {ASSET_C88_DIALOG_WADING_BOOTS_LEARN, ASSET_C89_DIALOG_WADING_BOOTS_REFRESHER, 0x10, ABILITY_E_WADING_BOOTS}, + {ASSET_A84_DIALOG_TURBOTRAINERS_LEARN, ASSET_A85_DIALOG_TURBOTRAINERS_REFRESHER, 0x19, ABILITY_11_TURBO_TALON}, + {ASSET_F64_DIALOG_NOTEDOORS_LEARN, ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, 0x0E, ABILITY_13_1ST_NOTEDOOR} }; -#define MOLE_ID_TO_TABLE_SHIFT 9 - /* .code */ +// chmole_learnedAllLevelAbilities int chmole_learnedAllLevelAbilities(enum level_e level){ // Checks if all of the level's abilities are learned. switch (level){ @@ -89,7 +65,7 @@ int chmole_learnedAllLevelAbilities(enum level_e level){ case LEVEL_7_GOBIS_VALLEY: return ability_isUnlocked(ABILITY_11_TURBO_TALON); default: - return FALSE; + return false; } } @@ -100,19 +76,19 @@ enum asset_e chmole_learnedAllLevelAbilitiesDialog(void){ int learned_all_moves = chmole_learnedAllLevelAbilities(level_id); switch(level_id){ case LEVEL_1_MUMBOS_MOUNTAIN: - return learned_all_moves ? ASSET_B4E_DIALOG_BOTTLES_ALL_MM_MOVES_LEARNED : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return learned_all_moves ? ASSET_B4E_DIALOG_BOTTLES_ALL_MM_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; case LEVEL_2_TREASURE_TROVE_COVE: - return learned_all_moves ? ASSET_A27_DIALOG_BOTTLES_ALL_TTC_MOVES_LEARNED : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return learned_all_moves ? ASSET_A27_DIALOG_BOTTLES_ALL_TTC_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; case LEVEL_3_CLANKERS_CAVERN: - return learned_all_moves ? VER_SELECT(ASSET_D37_DIALOG_BOTTLES_ALL_CC_MOVES_LEARNED, 0xA0A, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return learned_all_moves ? ASSET_D37_DIALOG_BOTTLES_ALL_CC_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; case LEVEL_4_BUBBLEGLOOP_SWAMP: - return learned_all_moves ? VER_SELECT(ASSET_C8A_DIALOG_BOTTLES_ALL_BGS_MOVES_LEARNED, 0x9CD, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return learned_all_moves ? ASSET_C8A_DIALOG_BOTTLES_ALL_BGS_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; case LEVEL_5_FREEZEEZY_PEAK: - return learned_all_moves ? VER_SELECT(ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED, 0x9A4, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return learned_all_moves ? ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; case LEVEL_7_GOBIS_VALLEY: - return learned_all_moves ? VER_SELECT(ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED, 0x9A4, 0, 0) : VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return learned_all_moves ? ASSET_C2A_DIALOG_BOTTLES_ALL_FP_GV_MOVES_LEARNED : ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; default: - return VER_SELECT(ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0xA0B, 0, 0); + return ASSET_D38_DIALOG_BOTTLES_ALL_MOVES_LEARNED; } } @@ -133,9 +109,9 @@ int chmole_learnedAllGameAbilities(void){ Actor *func_802D94B4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *actor = marker_getActor(marker); - if(actor->state != MOLE_STATE_1_AWAITING_PLAYER && actor->state != MOLE_STATE_5_REFRESHER){ - modelRender_setAppendageVisibility(3, 0); - modelRender_setAppendageVisibility(4, 0); + if(actor->state != 1 && actor->state != 5){ + func_8033A45C(3, 0); + func_8033A45C(4, 0); actor = actor_draw(marker, gfx, mtx, vtx); } @@ -146,9 +122,9 @@ void func_802D9530(Actor *this){ Actor *other = subaddie_getLinkedActor(this); if(this->partnerActor && other){ if(this->partnerActor->id == 0xB8) - subaddie_set_state_with_direction(other, MOLE_STATE_3_EXPLAINING_ABILITY, 0.0001f, 1); + subaddie_set_state_with_direction(other, 3, 0.0001f, 1); } - subaddie_set_state_with_direction(this, MOLE_STATE_4_REENTER_MOLEHILL, 0.0001f, 1); + subaddie_set_state_with_direction(this, 4, 0.0001f, 1); actor_playAnimationOnce(this); this->unk44_31 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(this->unk44_31, SFX_3F9_UNKNOWN); @@ -160,35 +136,37 @@ void func_802D9530(Actor *this){ void func_802D9600(Actor * this){ anctrl_setSmoothTransition(this->anctrl, 0); - subaddie_set_state_with_direction(this, MOLE_STATE_1_AWAITING_PLAYER, 0.0001f, 1); + subaddie_set_state_with_direction(this, 1, 0.0001f, 1); this->marker->propPtr->unk8_3 = 0; } +// chmole_setStaticCamera void chmole_setStaticCamera(Actor *this){ // Sets the camera to a static camera - timed_setStaticCameraToNode(0.0f, moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].camera_node); + timed_setStaticCameraToNode(0.0f, moleTable[this->actorTypeSpecificField-9].camera_node); } +// chmole_healthRefill void chmole_healthRefill(ActorMarker *marker, enum asset_e arg1, s32 arg2){ // Refills the player's health upon learning a new ability, if needed // Also releases the camera Actor *actor = marker_getActor(marker); - if( arg1 == moleTable[actor->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].teach_text_id + if( arg1 == moleTable[actor->actorTypeSpecificField-9].teach_text_id && item_getCount(ITEM_14_HEALTH) < item_getCount(ITEM_15_HEALTH_TOTAL) ){ - gcdialog_showDialog(VER_SELECT(ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH, 0xA0C, 0, 0), 7, 0, actor->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); + gcdialog_showDialog(ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH, 7, 0, actor->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); }//L802D9738 - else if(arg1 == moleTable[actor->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].teach_text_id || arg1 == VER_SELECT(ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH, 0xA0C, 0, 0)){ - gcdialog_showDialog(chmole_learnedAllGameAbilities()? VER_SELECT(ASSET_A87_DIALOG_BOTTLES_ALL_MOVES_LEARNED, 0x943, 0, 0) : chmole_learnedAllLevelAbilitiesDialog(), 7, 0, actor->marker, chmole_healthRefill, NULL); + else if(arg1 == moleTable[actor->actorTypeSpecificField-9].teach_text_id || arg1 == ASSET_D39_DIALOG_BOTTLES_REFILL_HEALTH){ + gcdialog_showDialog(chmole_learnedAllGameAbilities()? 0xa87 : chmole_learnedAllLevelAbilitiesDialog(), 7, 0, actor->marker, chmole_healthRefill, NULL); } else{//L802D97BC if(actor->has_met_before){ func_80347A14(1); - actor->has_met_before = FALSE; + actor->has_met_before = false; } timed_exitStaticCamera(0.0f); - if(actor->state == MOLE_STATE_5_REFRESHER){ + if(actor->state == 5){ func_8028F918(0); func_802D9600(actor); }//L802D9814 @@ -198,83 +176,84 @@ void chmole_healthRefill(ActorMarker *marker, enum asset_e arg1, s32 arg2){ }//L802D9820 } +// chmole_additionalAbilityLearnActions void chmole_additionalAbilityLearnActions(ActorMarker *marker, enum asset_e arg1, s32 arg2){ // Performs actions depending on what move is being learned Actor *actor = marker_getActor(marker); switch(arg2){ - case MOLE_ABILITY_LEARN_ACTION_1_STILT_STRIDE: + case 1: // Stilt Stride timed_setStaticCameraToNode(0.0f, 0x11); - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, TRUE); + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, true); break; - case MOLE_ABILITY_LEARN_ACTION_2_UNK: - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, FALSE); + case 2: + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, false); chmole_setStaticCamera(actor); break; - case MOLE_ABILITY_LEARN_ACTION_3_TURBO_TALON_TRAINER: + case 3: // Turbo Talon Trainer timed_setStaticCameraToNode(0.0f, 0x29); - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, TRUE); + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, true); break; - case MOLE_ABILITY_LEARN_ACTION_4_UNK: - levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, FALSE); + case 4: + levelSpecificFlags_set(LEVEL_FLAG_1A_UNKNOWN, false); chmole_setStaticCamera(actor); break; - case MOLE_ABILITY_LEARN_ACTION_5_EGG_FIRING: + case 5: // Egg Firing item_adjustByDiffWithHud(ITEM_D_EGGS, 50); break; - case MOLE_ABILITY_LEARN_ACTION_6_FLIGHT: + case 6: // Flight item_adjustByDiffWithHud(ITEM_F_RED_FEATHER, 25); break; - case MOLE_ABILITY_LEARN_ACTION_7_WONDERWING: + case 7: // Wonderwing item_adjustByDiffWithHud(ITEM_10_GOLD_FEATHER, 5); break; - case MOLE_ABILITY_LEARN_ACTION_8_REFILL_HEALTH: + case 8: // Refill Health item_set(ITEM_14_HEALTH, item_getCount(ITEM_15_HEALTH_TOTAL)); break; - case MOLE_ABILITY_LEARN_ACTION_FF_UNK: + case 0xff: chmole_setStaticCamera(actor); break; } } +// chmole_learnAbility int chmole_learnAbility(Actor *this){ - s32 teach_text_id; + s32 sp2C; s32 sp28 = 0xe; - // [port] Rando hands out its own item here, whether or not the vanilla move is known. - if (!EventSystem_Should(VB_OVERRIDE_MOLEHILL_ABILITY, false, this, &teach_text_id, &sp28)) { + if (!EventSystem_Should(VB_OVERRIDE_MOLEHILL_ABILITY, false, this, &sp2C, &sp28)) { // Known Ability: Refresher Dialog - if(ability_isUnlocked(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability)){ + if (ability_isUnlocked(moleTable[this->actorTypeSpecificField - 9].ability)) { sp28 = 0xf; - teach_text_id = moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].refresher_text_id; + sp2C = moleTable[this->actorTypeSpecificField - 9].refresher_text_id; }//L802D99EC // New Ability: Learn Dialog & Misc Actions - else{ + else { func_80347A14(0); - this->has_met_before = TRUE; - teach_text_id = moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].teach_text_id; - ability_unlock(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability); - switch(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability){ - case ABILITY_9_FLIGHT: - case ABILITY_D_SHOCK_JUMP: - gcsfx_playWithPitch(SFX_113_PAD_APPEARS, 0.9f, 32000); - break; - case ABILITY_13_1ST_NOTEDOOR: - func_802FAD64(ITEM_C_NOTE); - break; + this->has_met_before = true; + sp2C = moleTable[this->actorTypeSpecificField - 9].teach_text_id; + ability_unlock(moleTable[this->actorTypeSpecificField - 9].ability); + switch (moleTable[this->actorTypeSpecificField - 9].ability) { + case ABILITY_9_FLIGHT: + case ABILITY_D_SHOCK_JUMP: + gcsfx_playWithPitch(SFX_113_PAD_APPEARS, 0.9f, 32000); + break; + case ABILITY_13_1ST_NOTEDOOR: + func_802FAD64(ITEM_C_NOTE); + break; } }//L802D9A9C } - gcdialog_showDialog(teach_text_id, sp28, this->position, this->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); - return TRUE; + gcdialog_showDialog(sp2C, sp28, this->position, this->marker, chmole_healthRefill, chmole_additionalAbilityLearnActions); + return true; } void func_802D9ADC(Actor *this){ Actor *other = subaddie_getLinkedActor(this); if(this->partnerActor && other && this->partnerActor->id == 0xB8){ - subaddie_set_state_with_direction(other, MOLE_STATE_2_POP_OUT_OF_MOLEHILL, 0.0001f, 1); + subaddie_set_state_with_direction(other, 2, 0.0001f, 1); } this->marker->propPtr->unk8_3 = 1; - anctrl_setSmoothTransition(this->anctrl, TRUE); - subaddie_set_state_with_direction(this, MOLE_STATE_2_POP_OUT_OF_MOLEHILL, 0.0001f, 1); + anctrl_setSmoothTransition(this->anctrl, true); + subaddie_set_state_with_direction(this, 2, 0.0001f, 1); actor_playAnimationOnce(this); this->unk44_31 = sfxsource_createSfxsourceAndReturnIndex(); sfxsource_setSfxId(this->unk44_31, SFX_3F9_UNKNOWN); @@ -287,15 +266,16 @@ void func_802D9ADC(Actor *this){ void chmole_Refresher(Actor *this){ // Plays the scene where Bottles gives the player a refresher on the ability. - subaddie_set_state(this, MOLE_STATE_5_REFRESHER); + subaddie_set_state(this, 5); chmole_setStaticCamera(this); func_8028F94C(2, this->position); chmole_learnAbility(this); } +// chmole_setFacingDirection void chmole_setFacingDirection(Actor *this){ // Sets the actor to always be facing the player - subaddie_set_state_with_direction(this, MOLE_STATE_3_EXPLAINING_ABILITY, 0.0001f, 1); + subaddie_set_state_with_direction(this, 3, 0.0001f, 1); actor_loopAnimation(this); } @@ -316,10 +296,11 @@ void func_802D9C90(Actor *this){ } } +// chmole_startingDialog void chmole_startingDialog(Actor *this){ // If the player knows the ability, use refresher function // Otherwise, set player's position and spawn mole - if(ability_isUnlocked(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability)){ + if(ability_isUnlocked(moleTable[this->actorTypeSpecificField - 9].ability)){ chmole_Refresher(this); } else{ @@ -333,6 +314,7 @@ void chmole_startingDialog(Actor *this){ } } +// chmole_update void chmole_update(Actor *this){ // Sets up the initial functions and state for the actor s32 sp50[6]; @@ -344,11 +326,11 @@ void chmole_update(Actor *this){ // Checks the actor's selector value is between 0x8 and 0x13 // Anything lower is a Spiral Mountain ability, and should use a different actor id - if(this->actorTypeSpecificField < CH_SM_MOLE_ID_8_BRIDGE || this->actorTypeSpecificField >= CH_MOLE_ID_13_EMPTY) + if(this->actorTypeSpecificField < 8 || this->actorTypeSpecificField >= 0x13) return; if(!this->volatile_initialized){ - this->volatile_initialized = TRUE; + this->volatile_initialized = true; marker_setFreeMethod(this->marker, func_802D9C90); if(this->initialized){ other = actorArray_findClosestActorFromActorId(this->position, ACTOR_12C_MOLEHILL, -1, &sp4C); @@ -356,7 +338,7 @@ void chmole_update(Actor *this){ if(this->partnerActor){ other = subaddie_getLinkedActor(this); if(other && this->partnerActor->id == MARKER_B8_MOLEHILL){ - subaddie_set_state(other, MOLE_STATE_1_AWAITING_PLAYER); + subaddie_set_state(other, 1); } } } @@ -367,17 +349,17 @@ void chmole_update(Actor *this){ // If actor exists and player is within radius, force trigger conversation node_prop = nodeprop_findByActorIdAndActorPosition(0x372, this); if(node_prop == NULL){ - this->unk38_0 = FALSE; + this->unk38_0 = false; } else{ - this->unk38_0 = TRUE; + this->unk38_0 = true; nodeprop_getPosition(node_prop, this->unk1C); } // Spawns molehill - __spawnQueue_add_1((GenFunction_1)chmole_spawnMolehill, reinterpret_cast(uintptr_t, this->marker)); - this->marker->propPtr->unk8_3 = FALSE; - this->marker->collidable = FALSE; - this->initialized = TRUE; + __spawnQueue_add_1((GenFunction_1)chmole_spawnMolehill, (uintptr_t)this->marker); + this->marker->propPtr->unk8_3 = false; + this->marker->collidable = false; + this->initialized = true; if(this->actorTypeSpecificField == CH_MOLE_ID_12_OPEN_NOTEDOORS){ node_prop = nodeprop_findByActorIdAndActorPosition(0x349, this); if(node_prop == NULL){ @@ -394,12 +376,12 @@ void chmole_update(Actor *this){ }//L802D9F34 controller_copyFaceButtons(0, sp50); // get face buttons press counters switch(this->state){ - case MOLE_STATE_1_AWAITING_PLAYER://L802D9F70 + case 1://L802D9F70 this->yaw_ideal = subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); - if(player_isStableWithExtraSteps() && player_isBanjoOrWishywashy() && !func_8028EC04()){ + if(func_8028F20C() && func_8028F0D4() && !func_8028EC04()){ if( this->actorTypeSpecificField == CH_MOLE_ID_12_OPEN_NOTEDOORS - && !ability_isUnlocked(moleTable[this->actorTypeSpecificField - MOLE_ID_TO_TABLE_SHIFT].ability) + && !ability_isUnlocked(moleTable[this->actorTypeSpecificField-9].ability) && (player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT) ){ player_getPosition(sp34); @@ -418,8 +400,8 @@ void chmole_update(Actor *this){ } } break; - case MOLE_STATE_2_POP_OUT_OF_MOLEHILL://L802DA0A0 - this->marker->propPtr->unk8_3 = TRUE; + case 2://L802DA0A0 + this->marker->propPtr->unk8_3 = true; this->yaw_ideal = subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); if( 0.0 < anctrl_getAnimTimer(this->anctrl) @@ -445,7 +427,7 @@ void chmole_update(Actor *this){ chmole_learnAbility(this); } break; - case MOLE_STATE_3_EXPLAINING_ABILITY://L802DA210 + case 3://L802DA210 this->yaw_ideal = subaddie_getYawToPlayer(this); subaddie_turnToYaw(this, 4.0f); if( ( actor_animationIsAt(this, 0.37f) @@ -474,7 +456,7 @@ void chmole_update(Actor *this){ func_8030E878(SFX_6F_BANJO_HEADSCRATCH, randf2(1.35f, 1.5f), 6000, this->position, 1250.0f, 2500.0f); } break; - case MOLE_STATE_4_REENTER_MOLEHILL://L802DA400 + case 4://L802DA400 if( 0.35 < anctrl_getAnimTimer(this->anctrl) && anctrl_getAnimTimer(this->anctrl) < 0.9 ){ diff --git a/src/core2/ch/molehill.c b/src/core2/ch/molehill.c index 83f010c1e..8a484c54c 100644 --- a/src/core2/ch/molehill.c +++ b/src/core2/ch/molehill.c @@ -14,16 +14,16 @@ Actor *func_802DA560(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802DA740(Actor *this); /*.data */ -ActorAnimationInfo chMolehillAnimations[] = { +ActorAnimationInfo D_80367E00[] = { {0x000, 0.0f}, - {ASSET_13D_ANIM_MOLEHILL_UNKNOWN, 2000000000.0f}, - {ASSET_13D_ANIM_MOLEHILL_UNKNOWN, 4.5f}, - {ASSET_13C_ANIM_MOLEHILL_UNKNOWN, 1.7f} + {0x13D, 2000000000.0f}, + {0x13D, 4.5f}, + {0x13C, 1.7f} }; -ActorInfo chMolehill = { +ActorInfo D_80367E20= { MARKER_B8_MOLEHILL, ACTOR_12C_MOLEHILL, ASSET_388_MODEL_MOLEHILL, - 0, chMolehillAnimations, + 0, D_80367E00, func_802DA740, actor_update_func_80326224, func_802DA560, 0, 0, 0.0f, 0 }; diff --git a/src/core2/ch/mumbo_sign.c b/src/core2/ch/mumbo_sign.c new file mode 100644 index 000000000..1944b538d --- /dev/null +++ b/src/core2/ch/mumbo_sign.c @@ -0,0 +1,26 @@ +#include +#include "functions.h" +#include "variables.h" + +void chMumboSign_update(Actor *this); + +/* .data */ +ActorInfo D_80367530 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_368_5_MUMBO_TOKEN_SIGN, ASSET_301_MODEL_5_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367554 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36B_10_MUMBO_TOKEN_SIGN, ASSET_302_MODEL_10_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367578 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36A_15_MUMBO_TOKEN_SIGN, ASSET_303_MODEL_15_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8036759C = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_369_20_MUMBO_TOKEN_SIGN, ASSET_304_MODEL_20_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_803675C0 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36C_25_MUMBO_TOKEN_SIGN, ASSET_305_MODEL_25_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; + +void chMumboSign_update(Actor *this) { + if (!this->volatile_initialized) { + if( fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST) + || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) + ) { + marker_despawn(this->marker); + } + this->volatile_initialized = true; + } + if (fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST)) { + func_80326310(this); + } +} diff --git a/src/core2/ch/mumbosign.c b/src/core2/ch/mumbosign.c deleted file mode 100644 index 46ff261ba..000000000 --- a/src/core2/ch/mumbosign.c +++ /dev/null @@ -1,27 +0,0 @@ -// BanjoDecomp: core2/mumbosign.c -#include -#include "functions.h" -#include "variables.h" - -void chMumboSign_update(Actor *this); - -/* .data */ -ActorInfo chMumboSign5 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_368_5_MUMBO_TOKEN_SIGN, ASSET_301_MODEL_5_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chMumboSign10 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36B_10_MUMBO_TOKEN_SIGN, ASSET_302_MODEL_10_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chMumboSign15 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36A_15_MUMBO_TOKEN_SIGN, ASSET_303_MODEL_15_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chMumboSign20 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_369_20_MUMBO_TOKEN_SIGN, ASSET_304_MODEL_20_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chMumboSign25 = { MARKER_1E9_MUMBO_COST_SIGN, ACTOR_36C_25_MUMBO_TOKEN_SIGN, ASSET_305_MODEL_25_MUMBO_TOKEN_SIGN, 0x0, 0x0, chMumboSign_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; - -void chMumboSign_update(Actor *this) { - if (!this->volatile_initialized) { - if( fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST) - || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - ) { - marker_despawn(this->marker); - } - this->volatile_initialized = true; - } - if (fileProgressFlag_get(this->modelCacheIndex - ACTOR_368_5_MUMBO_TOKEN_SIGN + FILEPROG_90_PAID_TERMITE_COST)) { - func_80326310(this); - } -} diff --git a/src/core2/ch/mumbotoken.c b/src/core2/ch/mumbotoken.c index ddcb1ba29..c3623b286 100644 --- a/src/core2/ch/mumbotoken.c +++ b/src/core2/ch/mumbotoken.c @@ -7,14 +7,14 @@ typedef struct { enum mumbotoken_e uid; }ActorLocal_MumboToken; -void chMumboToken_update(Actor *this); +void func_802E0B10(Actor *this); enum mumbotoken_e func_802E0CB0(Actor *this); /* .data */ - ActorInfo chMumboToken = { + ActorInfo D_803685A0 = { MARKER_39_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, ASSET_41A_SPRITE_MUMBO_TOKEN, - 0, NULL, - chMumboToken_update, actor_update_func_80326224, fxTouchSparkle_draw, + 0, NULL, + func_802E0B10, actor_update_func_80326224, fxTouchSparkle_draw, 2000, 0, 0.0f, 0 }; @@ -27,7 +27,6 @@ void chMumboToken_collect(ActorMarker *marker, ActorMarker *other_marker){ this = marker_getActor(marker); mumboscore_set(func_802E0CB0(this), true); - CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_MUMBO, func_802E0CB0(this)); func_8030E760(0x401, 1.0f, 0x7fff); timedFunc_set_1(0.75f, (GenFunction_1)progressDialog_showDialogMaskZero, FILEPROG_4_MUMBO_TOKEN_TEXT); fxSparkle_mumboToken(&marker->propPtr->x); @@ -57,7 +56,7 @@ enum mumbotoken_e func_802E0A90(Actor *this){ } } -void chMumboToken_update(Actor *this){ +void func_802E0B10(Actor *this){ ActorLocal_MumboToken *local; f32 sp28[3]; diff --git a/src/core2/ch/shock_jumppad.c b/src/core2/ch/shock_jumppad.c index cd127c9ae..2b53f347a 100644 --- a/src/core2/ch/shock_jumppad.c +++ b/src/core2/ch/shock_jumppad.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_43A40.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/ch/snacker.c b/src/core2/ch/snacker.c index 63d518b95..1191d59f6 100644 --- a/src/core2/ch/snacker.c +++ b/src/core2/ch/snacker.c @@ -80,7 +80,7 @@ static void __chsnacker_start_dialog(Actor *this) { text_index = mapSpecificFlags_getN(8, 3); if( !this->has_met_before ) { if(text_index < 4) { - if(gcdialog_showDialog(VER_SELECT(ASSET_A1B_DIALOG_SNACKER_SPAWNED_1, 0x91B, 0, 0) + text_index, 0, NULL, NULL, NULL, NULL)){ + if(gcdialog_showDialog(ASSET_A1B_DIALOG_SNACKER_SPAWNED_1 + text_index, 0, NULL, NULL, NULL, NULL)){ text_index++; mapSpecificFlags_setN(8, text_index, 3); this->has_met_before = true; @@ -195,7 +195,7 @@ void chsnacker_update(Actor *this) { this->unk154 = 0x085E0000; marker_setCollisionScripts(this->marker, __chsnacker_ow, func_802E1010, __chsnacker_die); } - playerPosition_get(player_position); + _player_getPosition(player_position); controller_state = snackerctl_get_state(); if(func_802E0DC0(this->position) || ((controller_state != SNACKER_CTL_STATE_1_RBB) && (controller_state != SNACKER_CTL_STATE_2_TTC))) { @@ -330,7 +330,7 @@ void chSnacker_spawn(void) { f32 sp20[3]; - playerPosition_get(spawn_position); + _player_getPosition(spawn_position); if (volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE) != 0) { nodeprop_getPosition(nodeprop_findByActorIdAndPosition_f32(ACTOR_3CB_UNKNOWN, spawn_position), spawn_position); } diff --git a/src/core2/ch/snowball.c b/src/core2/ch/snowball.c index 3d82557ef..fefe9928d 100644 --- a/src/core2/ch/snowball.c +++ b/src/core2/ch/snowball.c @@ -160,7 +160,7 @@ void chSnowball_update(Actor *this) { } break; case 2: - this->marker->unk40_22 = NOT(player_isInFirstPersonView()); + this->marker->unk40_22 = NOT(func_8028F170()); this->velocity[0] *= 0.7; this->velocity[1] *= 0.7; this->velocity[2] *= 0.7; diff --git a/src/core2/ch/snowman.c b/src/core2/ch/snowman.c index 9b152afc8..dba509c54 100644 --- a/src/core2/ch/snowman.c +++ b/src/core2/ch/snowman.c @@ -2,8 +2,6 @@ #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - extern void particleEmitter_func_802EFA20(ParticleEmitter *, f32, f32); extern void subaddie_set_state_with_direction(Actor *, s32, f32, s32); extern void subaddie_turnToYaw(Actor *, f32); @@ -49,8 +47,8 @@ Actor *chSnowman_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ actor = marker_getActor(marker); local = (ActorLocal_chSirSlush *)&actor->local; - modelRender_setAppendageVisibility(1, local->unk9); - modelRender_setAppendageVisibility(2, local->unkA); + func_8033A45C(1, local->unk9); + func_8033A45C(2, local->unkA); return actor_draw(marker, gfx, mtx, vtx); } @@ -187,11 +185,8 @@ void __chSnowman_deathCallback(ActorMarker *marker, ActorMarker *other_marker){ sfx_playFadeShorthandDefault(SFX_2F_ORANGE_SPLAT, 1.0f, 30000, actor->position, 1500, 4500); __spawnQueue_add_1((GenFunction_1)__chSnowman_spawnHat, (uintptr_t)actor->marker); - if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ + if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK) maSnowy_decRemaining(); - port_puzzlePos_mark(ANCHOR_PUZZLE_FP_SLUSHES, (s32)actor->position[0], (s32)actor->position[1], - (s32)actor->position[2]); - } __chSnowman_spawnSnowballParticles(actor->position, 0xC); marker_despawn(actor->marker); } @@ -229,20 +224,8 @@ void chSnowman_update(Actor *this){ if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ local->unk0 = actorArray_findActorFromActorId(0x336)->marker; maSnowy_incTotal(); - if(port_puzzlePos_isMarked(ANCHOR_PUZZLE_FP_SLUSHES, (s32)this->position[0], - (s32)this->position[1], (s32)this->position[2])){ - maSnowy_decRemaining(); - marker_despawn(this->marker); - return; - } } }//L802E21D8 - if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK && !this->despawn_flag - && port_puzzlePos_isMarked(ANCHOR_PUZZLE_FP_SLUSHES, (s32)this->position[0], - (s32)this->position[1], (s32)this->position[2])){ - __chSnowman_deathCallback(this->marker, NULL); - return; - } if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ if(maSlalom_isActive() || func_8038DD14()){ actor_collisionOff(this); diff --git a/src/core2/ch/trainers.c b/src/core2/ch/trainers.c index da9df47f8..29635e1bc 100644 --- a/src/core2/ch/trainers.c +++ b/src/core2/ch/trainers.c @@ -82,8 +82,8 @@ void chtrainers_update(Actor *this){ && !volatileFlag_get(VOLATILE_FLAG_F_HAS_MEET_TURBO_SHOES) && player_getTransformation() == TRANSFORM_1_BANJO ){ - if(gcdialog_showDialog(VER_SELECT(0xda4, 0xA22, 0, 0), 0, NULL, NULL, NULL, NULL)){ - volatileFlag_set(VOLATILE_FLAG_F_HAS_MEET_TURBO_SHOES, TRUE); + if(gcdialog_showDialog(0xda4, 0, NULL, NULL, NULL, NULL)){ + volatileFlag_set(VOLATILE_FLAG_F_HAS_MEET_TURBO_SHOES, true); } }//L802CA620 _chtrainers_802CA378(this, sp2C); diff --git a/src/core2/ch/wadingboots.c b/src/core2/ch/wadingboots.c index 319620ba9..0499263ce 100644 --- a/src/core2/ch/wadingboots.c +++ b/src/core2/ch/wadingboots.c @@ -9,16 +9,16 @@ Actor *chwadingboots_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void chwadingboots_update(Actor *this); /* .data */ -ActorAnimationInfo chWadingBootsAnimations[] = { +ActorAnimationInfo D_80367A00[] = { {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, {ASSET_67_ANIM_WADINGBOOTS_WALK, 0.7f}, }; -ActorInfo chWadingBoots = { +ActorInfo D_80367A20 = { MARKER_11_WADING_BOOTS, ACTOR_65_WADING_BOOTS, ASSET_366_MODEL_WADING_BOOTS, - 0x0, chWadingBootsAnimations, + 0x0, D_80367A00, chwadingboots_update, actor_update_func_80326224, chwadingboots_draw, 0, 0, 0.0f, 0 }; @@ -70,8 +70,8 @@ void chwadingboots_update(Actor *this){ if(!subaddie_playerIsWithinSphereAndActive(this, 250)) break; if(player_getTransformation() != TRANSFORM_1_BANJO) break; - if(gcdialog_showDialog(VER_SELECT(ASSET_DA5_DIALOG_WADINGBOOTS_MEET, 0xA23, 0, 0), 0, NULL, NULL, NULL, NULL)){ - volatileFlag_set(VOLATILE_FLAG_10_HAS_MEET_WADING_BOOTS, TRUE); + if(gcdialog_showDialog(ASSET_DA5_DIALOG_WADINGBOOTS_MEET, 0, NULL, NULL, NULL, NULL)){ + volatileFlag_set(VOLATILE_FLAG_10_HAS_MEET_WADING_BOOTS, true); } break; diff --git a/src/core2/checksums.c b/src/core2/checksums.c deleted file mode 100644 index 15652a8f4..000000000 --- a/src/core2/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: core2/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsCore2; diff --git a/src/core2/climb.c b/src/core2/climb.c index d1a6e3015..deda2e7c5 100644 --- a/src/core2/climb.c +++ b/src/core2/climb.c @@ -7,29 +7,30 @@ /* .bss */ f32 climbPoleBottom[3]; f32 climbPoleTop[3]; -f32 climbRadius; +f32 climbRadius;//climbRadius f32 D_8037C580[3]; -f32 climbRegrabWaitTime; -u8 isClimbingBool; +f32 D_8037C58C; +u8 D_8037C590; //bool climbing u8 D_8037C591; /* .code */ -void climb_clear(void){ +void climbClear(void){ //climbClear ml_vec3f_clear(climbPoleBottom); ml_vec3f_clear(climbPoleTop); - isClimbingBool = 0; - climbRegrabWaitTime = 0.0f; + D_8037C590 = 0; + D_8037C58C = 0.0f; + } -void climb_getBottom(f32 dst[3]){ +void climbGetBottom(f32 dst[3]){ //climbGetBottom ml_vec3f_copy(dst, climbPoleBottom); } -f32 climb_getBottomY(void){ +f32 climbGetBottomY(void){ //climbGetBottomY return climbPoleBottom[1]; } -f32 climb_getRadius(void){ +f32 climbGetRadius(void){ //climbGetRadius return climbRadius; } @@ -37,32 +38,32 @@ u8 func_8029825C(void){ //climb_2098250 return D_8037C591; } -f32 climb_getTopY(void){ +f32 climbGetTopY(void){ //climbGetTopY return climbPoleTop[1]; } -void climb_set(f32 bottom[3], f32 top[3], f32 radius, u32 arg3){ - if( !(climbRegrabWaitTime > 0.0f) || D_8037C580[0] != bottom[0] +void climbSet(f32 bottom[3], f32 top[3], f32 radius, u32 arg3){ + if( !(D_8037C58C > 0.0f) || D_8037C580[0] != bottom[0] || D_8037C580[1] != bottom[1] || D_8037C580[2] != bottom[2]) { ml_vec3f_copy(climbPoleBottom, bottom); ml_vec3f_copy(climbPoleTop, top); climbRadius = radius; D_8037C591 = arg3; - isClimbingBool = 1; + D_8037C590 = 1; } } -void climb_regrab_update(void){ - climbRegrabWaitTime = ml_max_f(climbRegrabWaitTime - time_getDelta(), 0.0f); - if(isClimbingBool && ability_hasLearned(ABILITY_5_CLIMB)){ +void func_80298344(void){ //climbUpdateRegrab + D_8037C58C = ml_max_f(D_8037C58C - time_getDelta(), 0.0f); + if(D_8037C590 && ability_hasLearned(ABILITY_5_CLIMB)){ bs_checkInterrupt(BS_INTR_C_CLIMB); } - isClimbingBool = 0; + D_8037C590 = 0; } -void climb_release(void){ - isClimbingBool = 0; +void climbRelease(void){ //climbRelease + D_8037C590 = 0; ml_vec3f_copy(D_8037C580, climbPoleBottom); - climbRegrabWaitTime = 0.6f; + D_8037C58C = 0.6f; } diff --git a/src/core2/collision/climbsurface.c b/src/core2/collision/climbsurface.c index f820a626f..1175fa005 100644 --- a/src/core2/collision/climbsurface.c +++ b/src/core2/collision/climbsurface.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C4B0.c #include #include "core1/core1.h" #include "functions.h" @@ -62,8 +61,8 @@ s32 D_8037C284; /* .code */ void func_80293440(void){ f32 sp34[3]; - f32 bottomY = climb_getBottomY(); - f32 topY = climb_getTopY(); + f32 bottomY = climbGetBottomY(); + f32 topY = climbGetTopY(); f32 sp28; f32 diff; @@ -73,7 +72,7 @@ void func_80293440(void){ if(D_8037C218[1] < bottomY) D_8037C218[1] = bottomY; - climb_getBottom(sp34); + climbGetBottom(sp34); func_80257F18(D_8037C218, sp34, &sp28); diff = mlDiffDegF(sp28, yaw_get()); diff = mlAbsF(diff); @@ -298,7 +297,7 @@ void func_80293F0C(void){ f32 sp38[3]; f32 sp2C[3]; - playerPosition_get(sp44); + _player_getPosition(sp44); if(gsworld_getMap() == MAP_34_RBB_ENGINE_ROOM && ml_vec3f_inside_box_f(sp44, -900.0f, -940.0f, 200.0f, 900.0f, 940.0f, 800.0f)){ func_8031C5FC(D_8037C200, 150.0f); } else{ @@ -317,7 +316,7 @@ void func_80293F0C(void){ case 1: case 3: case 4: - playerPosition_get(D_8037C218); + _player_getPosition(D_8037C218); playerPosition_func_80298504(D_8037C228); ml_vec3f_diff_copy(D_8037C238, D_8037C218, D_8037C228); if ((D_8037C274 == 3) && func_8031C594(D_8037C200) && (D_8037C218[1] > (floor_getYPosition(D_8037C200) - 70.0f))) { @@ -326,15 +325,15 @@ void func_80293F0C(void){ baphysics_set_vertical_velocity(1.0f); } func_80293668(); - playerPosition_set(D_8037C218); + player_setPosition(D_8037C218); break; case 5: - playerPosition_get(D_8037C218); + _player_getPosition(D_8037C218); playerPosition_func_80298504(D_8037C228); func_80293668(); func_80293440(); - playerPosition_set(D_8037C218); + player_setPosition(D_8037C218); break; case 2: @@ -365,7 +364,7 @@ void func_80293F0C(void){ } if (D_8037C27F) { - playerPosition_set(sp44); + player_setPosition(sp44); } D_8037C27A = 0; @@ -376,7 +375,7 @@ void func_80293F0C(void){ D_8037C280 = 0; } playerPosition_func_80298504(sp2C); - playerPosition_get(sp38); + _player_getPosition(sp38); ml_vec3f_diff_copy(D_8037C268, sp38, sp2C); if (D_8037C204) { collisionTri_copy(&D_8037C208, D_8037C204); @@ -413,7 +412,7 @@ void func_80294390(void) { } f32 func_80294404(void){ - return playerPosition_getY() - floor_getXPosition(D_8037C200); + return player_getYPosition() - floor_getXPosition(D_8037C200); } f32 func_80294438(void){ diff --git a/src/core2/collision/dispatch.c b/src/core2/collision/dispatch.c index a2a5470ca..bf7c6ddc4 100644 --- a/src/core2/collision/dispatch.c +++ b/src/core2/collision/dispatch.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_999A0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/collision/enemy.c b/src/core2/collision/enemy.c index 7c022dcc1..1d275daca 100644 --- a/src/core2/collision/enemy.c +++ b/src/core2/collision/enemy.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_45310.c #include #include "core1/core1.h" #include "functions.h" @@ -29,7 +28,7 @@ Actor *func_802CCA7C(ActorMarker *, Gfx **, Mtx **, Vtx **); void func_802CCC5C(Actor *this); /* .data */ -ActorInfo chBuzzbomb = { +ActorInfo D_80367130 = { MARKER_C2_BUZZBOMB, ACTOR_134_BUZZBOMB, ASSET_3ED_MODEL_BUZZBOMB, 0, NULL, func_802CCC5C, NULL, func_802CCA7C, @@ -435,7 +434,7 @@ void func_802CCC5C(Actor *this) { if (this->state == 1) { player_getPosition(sp8C); viewport_getPosition_vec3f(sp80); - viewport_getLookVector(sp74); + viewport_getLookbk_vector(sp74); sp5C[0] = this->position[0] - sp80[0]; sp5C[1] = this->position[1] - sp80[1]; sp5C[2] = this->position[2] - sp80[2]; diff --git a/src/core2/collision/filter.c b/src/core2/collision/filter.c index b74354afa..ffa350843 100644 --- a/src/core2/collision/filter.c +++ b/src/core2/collision/filter.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C9F00.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/collision/geometrybounds.c b/src/core2/collision/geometrybounds.c index 31e68f968..979a927bb 100644 --- a/src/core2/collision/geometrybounds.c +++ b/src/core2/collision/geometrybounds.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B6640.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/collision/hitboxdata.c b/src/core2/collision/hitboxdata.c index 8f2993899..c28adc8b6 100644 --- a/src/core2/collision/hitboxdata.c +++ b/src/core2/collision/hitboxdata.c @@ -1,31 +1,14 @@ -// BanjoDecomp: core2/code_B62B0.c #include #include "functions.h" #include "variables.h" -#include "version.h" -//CollisionParams = u16 packed bitwise as (aaaa bbcc cdde eeff) +//Struct5Cs = u16 packed bitwise as (aaaa bbcc cdde eeff) typedef struct{ - u16 markerId; - u16 collisionUnion; - union{ - u16 collisionTypes[11]; - struct{ - u16 activeClawSwipe; - u16 activeRoll; - u16 jumpOnTop; - u16 activeRatATat; - u16 activeBeakBarge; - u16 activeBeakBuster; - u16 activeBeakBomb; - u16 activeEggFiring; - u16 activeWonderwing; - u16 activeCrocBite; - u16 otherContact; - }; - }; -} CollisionTable; + u16 unk0; + u16 unk2; //Struct5Cs + u16 unk4[11]; //Struct5Cs +} Struct_core2_B62B0_0; typedef struct{ s32 (*unk0)(ActorMarker *, ActorMarker *); @@ -33,202 +16,194 @@ typedef struct{ } Struct_core2_B62B0_1; /* .data */ - -#define COLLISION_TABLE_SIZE 187 - -CollisionTable collision_table[COLLISION_TABLE_SIZE] = { - {MARKER_12A_TOPPER_THE_CARROT_A, 0x0000, {0x0904, 0x8504, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, - {MARKER_129_BAWL_THE_ONION_A, 0x0000, {0x0504, 0x0984, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, - {MARKER_128_COLLYWOBBLE_THE_CAULIFLOWER_A, 0x0000, {0x0000, 0x0000, 0x8404, 0x0984, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404}}, - {MARKER_135_QUARRIE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_1E6_TOPPER_THE_CARROT_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_1E7_BAWL_THE_ONION_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_1EA_GRUNTLING_RED, 0x0001, {0x0A08, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0984, 0x2020}}, - {MARKER_295_GRUNTLING_BLUE, 0x0001, {0x0A0C, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_1F1_GRUNTLING_BLACK, 0x0001, {0x0A10, 0x898C, 0x8100, 0x8988, 0x8A08, 0x8A08, 0x0A84, 0x098C, 0x0A04, 0x0000, 0x2020}}, - {MARKER_1E0_BRENTILDA, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0004, 0x8000, 0x0000, 0x7000}}, - {MARKER_5_GRUBLIN, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x1020}}, - {MARKER_4_TERMITE, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1020}}, - {MARKER_3_BIGBUTT, 0x0000, {0x0914, 0x990C, 0x2020, 0x8908, 0x8908, 0x8908, 0x0A04, 0x0914, 0x0904, 0x0000, 0x4020}}, - {MARKER_29E_BIGBUTT_KNOCKED_DOWN, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xA000, 0x0004, 0x8000, 0x0000, 0x8000}}, - {MARKER_7_CONGA, 0x0000, {0x0000, 0x0000, 0x3020, 0x9000, 0x0000, 0x0000, 0x0000, 0x0804, 0x9000, 0x0000, 0x3020}}, - {MARKER_13_SNIPPET, 0x0002, {0x0504, 0x7584, 0x8100, 0x7584, 0x7604, 0x0A04, 0x0A84, 0x0504, 0x0A04, 0x0000, 0x1020}}, - {MARKER_16B_SNIPPET_UPSIDEDOWN, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0904, 0x0A04, 0x0000, 0x1020}}, - {MARKER_DD_BLACK_SNIPPET, 0x0002, {0x060C, 0x7588, 0x8100, 0x7588, 0x7608, 0x8604, 0x0A84, 0x050C, 0x0A04, 0x0000, 0x1020}}, - {MARKER_DE_BLACK_SNIPPET_UPSIDEDOWN, 0x0001, {0x0908, 0x0988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x090C, 0x0A04, 0x0000, 0x1020}}, - {MARKER_15_CLAM, 0x0001, {0x0A88, 0x7988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1424}}, - {MARKER_65_SHRAPNEL, 0x0804, {0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x090E, 0x0804, 0x0000, 0x5844}}, - {MARKER_14_SNACKER, 0x0003, {0x3020, 0x3020, 0x3020, 0x9080, 0x9080, 0x9080, 0x0A84, 0x0914, 0x0904, 0x0000, 0x3020}}, - {MARKER_A5_NIPPER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x5020}}, - {MARKER_16C_NIPPER, 0x0000, {0x0000, 0x0000, 0x0000, 0xB804, 0x0000, 0x0000, 0x0000, 0x0404, 0xB804, 0x0000, 0x5020}}, - {MARKER_A4_LOCKUP_SLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {MARKER_F6_LOCKUP_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {MARKER_F7_LOCKUP_FAST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {MARKER_29_GRILLE_CHOMPA, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x3444}}, - {MARKER_1CF_GRILLE_CHOMPA_ATTACKING, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x1424}}, - {MARKER_1A6_BETA_VENT, 0x0000, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x0000, 0x0000, 0x3020, 0x3020}}, - {MARKER_1A7_CLANKER_WHIPCRACK, 0x0804, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, - {MARKER_69_CHUMP_FISH, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_173_CHUMP_FISH_2, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x4020}}, - {MARKER_C1_FLIBBIT_RED, 0x0000, {0x0A09, 0x0985, 0x8100, 0x0985, 0x0A05, 0x0A05, 0x0000, 0x0989, 0x0A05, 0x0986, 0x2020}}, - {MARKER_C5_FLIBBIT_YELLOW, 0x0000, {0x0A0D, 0x8989, 0x8100, 0x8989, 0x7A09, 0x7A09, 0x0000, 0x098D, 0x0A05, 0x0986, 0x2020}}, - {MARKER_C2_BUZZBOMB, 0x0000, {0x0805, 0x0805, 0x8000, 0x0805, 0x0805, 0x0805, 0x0000, 0x0805, 0x0805, 0x0806, 0x3020}}, - {MARKER_B1_SIR_SLUSH, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x9000, 0x0004, 0x8000, 0x0000, 0x7000}}, - {0x0287, 0x0001, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x8804, 0x0004, 0x8000, 0x0000, 0x7000}}, // snowman.c - {MARKER_205_TWINKLY_MUNCHER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0404, 0x0404, 0x0404, 0x0000, 0x0408, 0x0404, 0x0000, 0x0000}}, - {MARKER_245_XMAS_TREE_EGG_TOLL, 0x0000, {0x3004, 0x3004, 0x3004, 0x3004, 0x3004, 0x2004, 0x3004, 0x0000, 0x0000, 0x3004, 0x3004}}, - {MARKER_250_ICECUBE_A, 0x0000, {0x0A90, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0910, 0x0A04, 0x0984, 0x3104}}, - {MARKER_25F_ICECUBE_B, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0908, 0x0A04, 0x0984, 0x3104}}, - {0x00AD, 0x0001, {0x0A10, 0x998C, 0x0020, 0x9988, 0x8A08, 0x0A04, 0x0A84, 0x0914, 0x0A04, 0x0000, 0x5124}}, - {MARKER_253_SCARAB_BEETLE, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x3020}}, - {MARKER_219_MUMMUM, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x0588, 0x0A04, 0x0000, 0x2020}}, - {MARKER_298_MUMMUM_BALL, 0x0000, {0x7000, 0x8000, 0x7000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0004, 0x0A04, 0x0000, 0x2020}}, - {MARKER_218_LIMBO, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x050C, 0x0A04, 0x0000, 0x2020}}, - {MARKER_99_TEEHEE, 0x0001, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, - {MARKER_296_TEEHEE_PURPLE, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, - {MARKER_96_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, - {MARKER_297_GIANT_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, - {MARKER_127_BAT, 0x0001, {0x0804, 0x0804, 0x8100, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x1424}}, - {MARKER_254_PORTRAIT_CHOMPA_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3444}}, - {MARKER_1D1_PORTRAIT_CHOMPA_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x1424}}, - {MARKER_21A_SEAMAN_GRUBLIN, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_C9_FLOTSAM, 0x0001, {0x0808, 0x8808, 0x8000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0808, 0x0804, 0x0000, 0x3424}}, - {MARKER_1B7_BOOM_BOX, 0x0000, {0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x098C, 0x0404, 0x0804, 0x5000}}, - {MARKER_2E_GRIMLET, 0x0004, {0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x8000, 0x3000, 0x3004}}, - {MARKER_1A1_BOSS_BOOM_BOX_LARGEST, 0x0000, {0x8020, 0x8884, 0x8020, 0x8884, 0x9884, 0x9884, 0x0804, 0x0904, 0x0884, 0x0000, 0x4020}}, - {MARKER_1A2_BOSS_BOOM_BOX_LARGE, 0x0000, {0x8020, 0x8904, 0x8020, 0x8904, 0x9904, 0x9904, 0x0804, 0x0984, 0x0904, 0x0000, 0x4020}}, - {MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, 0x0000, {0x9020, 0x9984, 0x9020, 0x9984, 0x9984, 0x9984, 0x0804, 0x0A04, 0x0984, 0x0000, 0x3020}}, - {MARKER_1A4_BOSS_BOOM_BOX_SMALL, 0x0000, {0x9020, 0x9A04, 0x9020, 0x9A04, 0x9A04, 0x9A04, 0x0804, 0x0A84, 0x0A04, 0x0000, 0x3020}}, - {MARKER_185_RBB_REAR_PROPELLER, 0x5060, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5060}}, - {MARKER_191_ENGINE_ROOM_PROPELLOR_1, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, - {MARKER_192_ENGINE_ROOM_PROPELLOR_2, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, - {MARKER_193_ENGINE_ROOM_PROPELLOR_3, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, - {MARKER_1E2_GRUBLIN_HOOD, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, - {MARKER_1C5_WHIPCRACK, 0x0001, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x080C, 0x0804, 0x0000, 0x3020}}, - {MARKER_1F9_SNARE_BEAR, 0x0000, {0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x0000, 0x0000, 0x0000, 0x2040}}, - {MARKER_1B2_CLUCKER_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x3444}}, - {MARKER_1D0_CLUCKER_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x1424}}, - {MARKER_1B4_EEYRIE_BABY, 0x8000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000}}, - {0x000E, 0x0001, {0x3000, 0x7504, 0x7080, 0x7504, 0x7584, 0x0804, 0x0804, 0x0488, 0x0804, 0x0000, 0x1020}}, - {MARKER_1AC_ZUBBA_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_256_FIRE_FX, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x2020, 0x2020}}, - {MARKER_C_ORANGE_PROJECTILE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2424}}, - {MARKER_DB_BURIED_TREASURE, 0x0000, {0x7000, 0x7000, 0x7000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x7000}}, - {MARKER_28_CLANKER_SAWBLADE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x2020}}, - {MARKER_4A_CC_KEY, 0x0404, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, - {MARKER_6E_PINK_EGG_LARGEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D7_PINK_EGG_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D9_PINK_EGG_SMALLEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D6_PINK_EGG_LARGE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_D8_PINK_EGG_SMALL, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_6D_TANKTUP_LEG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_19B_CHOIR_TURTLE_YELLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_19C_CHOIR_TURTLE_CYAN, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_19D_CHOIR_TURTLE_BLUE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_19E_CHOIR_TURTLE_RED, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_19F_CHOIR_TURTLE_PINK, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_1A0_CHOIR_TURTLE_PURPLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_B9_FP_SNOWMAN_BUTTON, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_124_BOGGY_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_97_BOGGY_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, - {MARKER_125_BOGGY_RACE_FLAG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, - {MARKER_126_BOGGY_RACE_FLAG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, - {MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_1FF_RED_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_20B_WOZZA, 0x7000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x7000}}, - {MARKER_20F_WOZZA_IN_CAVE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, - {MARKER_204_TWINKLY_BOX, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_207_XMAS_TREE_STAR, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0404}}, - {MARKER_206_XMAS_TREE_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, - {MARKER_BC_GOBI_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_BE_GOBI_ROCK, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x0000}}, - {MARKER_BF_GOBI_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_C3_GOBI_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, - {MARKER_252_LOGGO, 0x0000, {0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0000, 0x0004, 0x0004, 0x0004}}, - {MARKER_48_NAPPER, 0x0004, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0000, 0x8000, 0x0000, 0x8004}}, - {MARKER_132_CCW_SPRING_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_130_CCW_SUMMER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_12E_CCW_AUTUMN_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_12C_CCW_WINTER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_1BF_GNAWTY_BOULDER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x7404, 0x0000, 0x0414, 0x7404, 0x0000, 0x0000}}, - {MARKER_1B3_EAGLE_EGG, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_1B0_CCW_BEANSTALK, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0814, 0x0000, 0x0000, 0x0000}}, - {MARKER_1AE_ZUBBA, 0x0000, {0x3004, 0x3004, 0x3004, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3004}}, - {MARKER_50_BEEHIVE, 0x0003, {0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000}}, - {MARKER_9A_1881_BARREL_TOP, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_9E_CELLAR_HATCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_9D_MANSION_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_E7_DINING_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_9C_SHACK_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_EA_LIGHTHOUSE_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_22D_SHIP_SHADOW_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_22E_SHIP_SUNNY_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_235_CRACKED_SKYLIGHT, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_163_CRYPT_COFFIN_LID, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_239_CCW_UNKNOWN_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_236_CCW_UNKNOWN_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_237_CCW_AUTUMN_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_238_CCW_WINTER_NABNUT_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_263_CCW_WHIPCRACK_ROOM_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_17D_IRON_GATE_NO_LOCK, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_9F_CHURCH_GATE_LEFT_LOCK, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_107_ENGINE_ROOM_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_108_CABIN_CLOSET_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_109_BREAKABLE_BRICK_WALL, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x080C, 0x0804, 0x0000, 0x0000}}, - {MARKER_118_GRATE_TO_LEVEL_3_WATER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_119_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_11A_GRATE_TO_RBB_PUZZLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_11E_ICE_BALL_TO_CHEATO, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x8804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_11F_RAREWARE_BOX, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x7804, 0x7804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, - {MARKER_121_GLASS_EYE, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x8804, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_123_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_1F2_WIDE_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_1F3_TALL_WINDOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, - {MARKER_224_BREAKABLE_FLOOR_COBWEB, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xA000, 0x080C, 0x0000, 0x0000, 0x0000}}, - {MARKER_225_BREAKABLE_WALL_COBWEB, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0xA000, 0x080C, 0x8000, 0x0000, 0x0000}}, - {MARKER_A2_CHURCH_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x8804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_1A9_CC_BREAKABLE_GRATES, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x080C, 0x0000, 0x0000, 0x0000}}, - {MARKER_195_WHISTLE_SWITCH_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_196_WHISTLE_SWITCH_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_197_WHISTLE_SWITCH_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_2F_ANCHOR_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_194_RBB_GREY_PROPELLER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_186_RBB_GREEN_PROPELLER_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_183_RBB_CAGE_UP_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_184_RBB_TNT_DOWN_SWITCH, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_164_GL_GRUNTY_FLOOR_PICTURE_EYE_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_165_GL_GRUNTY_FLOOR_PICTURE_EYE_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - {MARKER_E4_CS_BK_SLEEPING, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, - {MARKER_E5_CS_BK_GAMEBOY, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, - {MARKER_E6_CS_BK_COOKING, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, - {MARKER_B2_SNOWBALL, 0x0001, {0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, - {MARKER_1A5_SANDYBUTT_EGG_TOLL, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001}}, - {MARKER_1A6_BETA_VENT, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, - {MARKER_16D_CHEATO_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, - {MARKER_16E_CHEATO_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, - {MARKER_16F_CHEATO_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, - {MARKER_170_BLUE_EGG_REFILL_PILLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, - {MARKER_171_RED_FEATHER_REFILL_PILLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, - {MARKER_172_GOLD_FEATHER_REFILL_PILLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, - {MARKER_25C_GRUNTY_SPELL_FIREBALL, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, - {MARKER_25D_GREEN_BLAST, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, - {MARKER_27A_JINJO_STATUE_BASE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, - {MARKER_27F_JINJONATOR_STATUE_BASE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, - {MARKER_25E_GRUNTILDA_FINAL_BOSS_VULNERABLE, 0x0000, {0x4000, 0x4000, 0x4000, 0xA604, 0x4000, 0x4000, 0x4000, 0x0584, 0xA000, 0x0000, 0x4000}}, - {MARKER_260_GRUNTY_PHASE_1_2_MOVING, 0x0000, {0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x0000, 0xA000, 0x0000, 0x5000}}, - {MARKER_281_GRUNTY_PHASE_2_VULNERABLE, 0x0000, {0x4080, 0x4080, 0x4080, 0xA604, 0x4080, 0x4080, 0x4080, 0x0584, 0xA200, 0x0000, 0x4080}}, - {MARKER_282_GRUNTY_PHASE_3_FLIGHT, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0xA604, 0xA604, 0x0000, 0xA200, 0x0000, 0x4080}}, -#if VERSION == VERSION_USA_1_0 - {MARKER_283_GRUNTY_PHASE_4_5_INVULNERABLE, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x0000, 0xA200, 0x0000, 0x4080}}, - {MARKER_284_GRUNTY_SPELL_BARRIER, 0x0000, {0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x0000, 0xB404, 0x5404, 0x5404}}, -#elif VERSION == VERSION_PAL - {MARKER_283_GRUNTY_PHASE_4_5_INVULNERABLE, 0x0000, {0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x0004, 0xA000, 0x0000, 0x4000}}, - {MARKER_284_GRUNTY_SPELL_BARRIER, 0x0000, {0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x0004, 0xB404, 0x5404, 0x5404}}, -#endif +Struct_core2_B62B0_0 D_80370AC0[0xBB] = { + {MARKER_12A_TOPPER_THE_CARROT_A, 0x0000, {0x0904, 0x8504, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, + {MARKER_129_BAWL_THE_ONION_A, 0x0000, {0x0504, 0x0984, 0x8504, 0x0000, 0x8504, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7484}}, + {MARKER_128_COLLYWOBBLE_THE_CAULIFLOWER_A, 0x0000, {0x0000, 0x0000, 0x8404, 0x0984, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404}}, + {MARKER_135_QUARRIE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_1E6_TOPPER_THE_CARROT_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_1E7_BAWL_THE_ONION_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_1E8_COLLYWOBBLE_THE_CAULIFLOWER_B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {MARKER_1EA_GRUNTLING_RED, 0x0001, {0x0A08, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0984, 0x2020}}, + {MARKER_295_GRUNTLING_BLUE, 0x0001, {0x0A0C, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_1F1_GRUNTLING_BLACK, 0x0001, {0x0A10, 0x898C, 0x8100, 0x8988, 0x8A08, 0x8A08, 0x0A84, 0x098C, 0x0A04, 0x0000, 0x2020}}, + {0x1E0, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0004, 0x8000, 0x0000, 0x7000}}, + {0x005, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x1020}}, + {0x004, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1020}}, + {0x003, 0x0000, {0x0914, 0x990C, 0x2020, 0x8908, 0x8908, 0x8908, 0x0A04, 0x0914, 0x0904, 0x0000, 0x4020}}, + {0x29E, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xA000, 0x0004, 0x8000, 0x0000, 0x8000}}, + {MARKER_7_CONGA, 0x0000, {0x0000, 0x0000, 0x3020, 0x9000, 0x0000, 0x0000, 0x0000, 0x0804, 0x9000, 0x0000, 0x3020}}, + {MARKER_13_SNIPPET, 0x0002, {0x0504, 0x7584, 0x8100, 0x7584, 0x7604, 0x0A04, 0x0A84, 0x0504, 0x0A04, 0x0000, 0x1020}}, + {0x16B, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0904, 0x0A04, 0x0000, 0x1020}}, + {MARKER_DD_BLACK_SNIPPET, 0x0002, {0x060C, 0x7588, 0x8100, 0x7588, 0x7608, 0x8604, 0x0A84, 0x050C, 0x0A04, 0x0000, 0x1020}}, + {0x0DE, 0x0001, {0x0908, 0x0988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x090C, 0x0A04, 0x0000, 0x1020}}, + {0x015, 0x0001, {0x0A88, 0x7988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x1424}}, + {0x065, 0x0804, {0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x5040, 0x090E, 0x0804, 0x0000, 0x5844}}, + {0x014, 0x0003, {0x3020, 0x3020, 0x3020, 0x9080, 0x9080, 0x9080, 0x0A84, 0x0914, 0x0904, 0x0000, 0x3020}}, + {MARKER_A5_NIPPER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x5020}}, + {0x16C, 0x0000, {0x0000, 0x0000, 0x0000, 0xB804, 0x0000, 0x0000, 0x0000, 0x0404, 0xB804, 0x0000, 0x5020}}, + {MARKER_A4_LOCKUP_SLOW, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {MARKER_F6_LOCKUP_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {MARKER_F7_LOCKUP_FAST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {0x0029, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x3444}}, + {0x01CF, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0808, 0x0804, 0x0000, 0x1424}}, + {0x01A6, 0x0000, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x0000, 0x0000, 0x3020, 0x3020}}, + {MARKER_1A7_CLANKER_WHIPCRACK, 0x0804, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, + {MARKER_69_CHUMP_FISH, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_173_CHUMP_FISH_2, 0x0001, {0x2020, 0x2020, 0x2020, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x4020}}, + {MARKER_C1_FLIBBIT_RED, 0x0000, {0x0A09, 0x0985, 0x8100, 0x0985, 0x0A05, 0x0A05, 0x0000, 0x0989, 0x0A05, 0x0986, 0x2020}}, + {MARKER_C5_FLIBBIT_YELLOW, 0x0000, {0x0A0D, 0x8989, 0x8100, 0x8989, 0x7A09, 0x7A09, 0x0000, 0x098D, 0x0A05, 0x0986, 0x2020}}, + {MARKER_C2_BUZZBOMB, 0x0000, {0x0805, 0x0805, 0x8000, 0x0805, 0x0805, 0x0805, 0x0000, 0x0805, 0x0805, 0x0806, 0x3020}}, + {MARKER_B1_SIR_SLUSH, 0x0000, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x9000, 0x0004, 0x8000, 0x0000, 0x7000}}, + {0x0287, 0x0001, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0x8804, 0x0004, 0x8000, 0x0000, 0x7000}}, + {MARKER_205_TWINKLY_MUNCHER, 0x0000, {0x0000, 0x0000, 0x0000, 0x0404, 0x0404, 0x0404, 0x0000, 0x0408, 0x0404, 0x0000, 0x0000}}, + {MARKER_245_XMAS_TREE_EGG_TOLL, 0x0000, {0x3004, 0x3004, 0x3004, 0x3004, 0x3004, 0x2004, 0x3004, 0x0000, 0x0000, 0x3004, 0x3004}}, + {MARKER_250_ICECUBE_A, 0x0000, {0x0A90, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0910, 0x0A04, 0x0984, 0x3104}}, + {MARKER_25F_ICECUBE_B, 0x0001, {0x0A88, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0908, 0x0A04, 0x0984, 0x3104}}, + {0x00AD, 0x0001, {0x0A10, 0x998C, 0x0020, 0x9988, 0x8A08, 0x0A04, 0x0A84, 0x0914, 0x0A04, 0x0000, 0x5124}}, + {MARKER_253_SCARAB_BEETLE, 0x0001, {0x0904, 0x0984, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0984, 0x0A04, 0x0000, 0x3020}}, + {MARKER_219_MUMMUM, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x0588, 0x0A04, 0x0000, 0x2020}}, + {MARKER_298_MUMMUM_BALL, 0x0000, {0x7000, 0x8000, 0x7000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0004, 0x0A04, 0x0000, 0x2020}}, + {MARKER_218_LIMBO, 0x0001, {0x0588, 0x7584, 0x8100, 0x7584, 0x7604, 0x7604, 0x0684, 0x050C, 0x0A04, 0x0000, 0x2020}}, + {MARKER_99_TEEHEE, 0x0001, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, + {MARKER_296_TEEHEE_PURPLE, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x0804, 0x0000, 0x2424}}, + {MARKER_96_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, + {MARKER_297_GIANT_GRAVESTONE, 0x0001, {0x0A10, 0x890C, 0x8100, 0x8908, 0x8988, 0x8988, 0x0A84, 0x0914, 0x0984, 0x0000, 0x3024}}, + {MARKER_127_BAT, 0x0001, {0x0804, 0x0804, 0x8100, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x1424}}, + {MARKER_254_PORTRAIT_CHOMPA_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3444}}, + {MARKER_1D1_PORTRAIT_CHOMPA_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x1424}}, + {MARKER_21A_SEAMAN_GRUBLIN, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0000, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_C9_FLOTSAM, 0x0001, {0x0808, 0x8808, 0x8000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0808, 0x0804, 0x0000, 0x3424}}, + {MARKER_1B7_BOOM_BOX, 0x0000, {0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x098C, 0x0404, 0x0804, 0x5000}}, + {MARKER_2E_GRIMLET, 0x0004, {0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x8000, 0x3000, 0x3004}}, + {MARKER_1A1_BOSS_BOOM_BOX_LARGEST, 0x0000, {0x8020, 0x8884, 0x8020, 0x8884, 0x9884, 0x9884, 0x0804, 0x0904, 0x0884, 0x0000, 0x4020}}, + {MARKER_1A2_BOSS_BOOM_BOX_LARGE, 0x0000, {0x8020, 0x8904, 0x8020, 0x8904, 0x9904, 0x9904, 0x0804, 0x0984, 0x0904, 0x0000, 0x4020}}, + {MARKER_1A3_BOSS_BOOM_BOX_MEDIUM, 0x0000, {0x9020, 0x9984, 0x9020, 0x9984, 0x9984, 0x9984, 0x0804, 0x0A04, 0x0984, 0x0000, 0x3020}}, + {MARKER_1A4_BOSS_BOOM_BOX_SMALL, 0x0000, {0x9020, 0x9A04, 0x9020, 0x9A04, 0x9A04, 0x9A04, 0x0804, 0x0A84, 0x0A04, 0x0000, 0x3020}}, + {MARKER_185_RBB_REAR_PROPELLER, 0x5060, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5060}}, + {MARKER_191_ENGINE_ROOM_PROPELLOR_1, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, + {MARKER_192_ENGINE_ROOM_PROPELLOR_2, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, + {MARKER_193_ENGINE_ROOM_PROPELLOR_3, 0x0000, {0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x8000, 0x0000, 0x2000}}, + {MARKER_1E2_GRUBLIN_HOOD, 0x0001, {0x0A08, 0x8988, 0x8100, 0x0984, 0x0A04, 0x0A04, 0x0A84, 0x0988, 0x0A04, 0x0000, 0x2020}}, + {MARKER_1C5_WHIPCRACK, 0x0001, {0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x3020, 0x080C, 0x0804, 0x0000, 0x3020}}, + {MARKER_1F9_SNARE_BEAR, 0x0000, {0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x2040, 0x0000, 0x0000, 0x0000, 0x2040}}, + {MARKER_1B2_CLUCKER_A, 0x0001, {0x0804, 0x0804, 0x2020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x3444}}, + {MARKER_1D0_CLUCKER_B, 0x0001, {0x0804, 0x0804, 0x1020, 0x0804, 0x0804, 0x0804, 0x0804, 0x0810, 0x0804, 0x0000, 0x1424}}, + {MARKER_1B4_EEYRIE_BABY, 0x8000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000}}, + {0x000E, 0x0001, {0x3000, 0x7504, 0x7080, 0x7504, 0x7584, 0x0804, 0x0804, 0x0488, 0x0804, 0x0000, 0x1020}}, + {0x01AC, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_256_FIRE_FX, 0x0000, {0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x0000, 0x0000, 0x2020, 0x2020}}, + {MARKER_C_ORANGE_PROJECTILE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2424}}, + {MARKER_DB_BURIED_TREASURE, 0x0000, {0x7000, 0x7000, 0x7000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000, 0x7000}}, + {MARKER_28_CLANKER_SAWBLADE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x2020}}, + {MARKER_4A_CC_KEY, 0x0404, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, + {MARKER_6E_PINK_EGG_LARGEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D7_PINK_EGG_MEDIUM, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D9_PINK_EGG_SMALLEST, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D6_PINK_EGG_LARGE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_D8_PINK_EGG_SMALL, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x006D, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x019B, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x019C, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x019D, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x019E, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x019F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x01A0, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_B9_FP_SNOWMAN_BUTTON,0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000}}, + {MARKER_124_BOGGY_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0097, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, + {0x0125, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, + {0x0126, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404}}, + {MARKER_1FD_BLUE_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_1FE_GREEN_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_1FF_RED_PRESENT_COLLECTIBLE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_20B_WOZZA, 0x7000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x7000}}, + {MARKER_20F_WOZZA_IN_CAVE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000}}, + {0x0204, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0207, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0404}}, + {0x0206, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, + {MARKER_BC_GOBI_1, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {0x00BE, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x0000}}, + {MARKER_BF_GOBI_2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_C3_GOBI_3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004}}, + {MARKER_252_LOGGO, 0x0000, {0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0000, 0x0004, 0x0004, 0x0004}}, + {MARKER_48_NAPPER, 0x0004, {0x7000, 0x8000, 0x8000, 0x8000, 0x9000, 0x9000, 0xB000, 0x0000, 0x8000, 0x0000, 0x8004}}, + {0x0132, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0130, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x012E, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x012C, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x01BF, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x7404, 0x7404, 0x0000, 0x0414, 0x7404, 0x0000, 0x0000}}, + {0x01B3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x01B0, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0814, 0x0000, 0x0000, 0x0000}}, + {MARKER_1AE_ZUBBA, 0x0000, {0x3004, 0x3004, 0x3004, 0x0804, 0x0804, 0x0804, 0x0804, 0x080C, 0x0804, 0x0000, 0x3004}}, + {0x0050, 0x0003, {0x0804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0804, 0x0000}}, + {0x009A, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x009E, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x009D, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x00E7, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x009C, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {MARKER_EA_LIGHTHOUSE_DOOR, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x022D, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x022E, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0235, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0163, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0239, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0236, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0237, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0238, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0263, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x017D, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x009F, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x00A0, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x00FF, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x0107, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x0108, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0109, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x080C, 0x0804, 0x0000, 0x0000}}, + {0x0118, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x0119, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x011A, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x0000, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x011E, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x8804, 0x8804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x011F, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x7804, 0x7804, 0x0000, 0x0808, 0x0804, 0x0000, 0x0000}}, + {0x0121, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x8804, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0123, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x01F2, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x01F3, 0x0000, {0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0804, 0x0804, 0x0000, 0x0000}}, + {0x0224, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xA000, 0x080C, 0x0000, 0x0000, 0x0000}}, + {0x0225, 0x0000, {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0xA000, 0x080C, 0x8000, 0x0000, 0x0000}}, + {0x00A2, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x8804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x01A9, 0x0000, {0x0000, 0x0000, 0x0000, 0x7804, 0x0000, 0x0804, 0x0000, 0x080C, 0x0000, 0x0000, 0x0000}}, + {0x0195, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0196, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0197, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x002F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0194, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0186, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0183, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0184, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0164, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x0165, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x00E4, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, + {0x00E5, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, + {0x00E6, 0x0000, {0x8004, 0x8004, 0x8004, 0x8404, 0x8404, 0x8004, 0x8004, 0x0000, 0x8004, 0x8004, 0x8004}}, + {0x00B2, 0x0001, {0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0804, 0x0000, 0x0000, 0x0000, 0x0000, 0x2020}}, + {0x01A5, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001}}, + {0x01A6, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3020}}, + {0x016D, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, + {0x016E, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, + {0x016F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8004}}, + {0x0170, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, + {0x0171, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, + {0x0172, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7004}}, + {0x025C, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, + {0x025D, 0x0000, {0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x3804, 0x0000, 0x0804, 0x3804, 0x3804}}, + {0x027A, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, + {0x027F, 0x0000, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, 0x0000, 0x0000}}, + {0x025E, 0x0000, {0x4000, 0x4000, 0x4000, 0xA604, 0x4000, 0x4000, 0x4000, 0x0584, 0xA000, 0x0000, 0x4000}}, + {0x0260, 0x0000, {0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x0000, 0xA000, 0x0000, 0x5000}}, + {0x0281, 0x0000, {0x4080, 0x4080, 0x4080, 0xA604, 0x4080, 0x4080, 0x4080, 0x0584, 0xA200, 0x0000, 0x4080}}, + {0x0282, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0xA604, 0xA604, 0x0000, 0xA200, 0x0000, 0x4080}}, + {0x0283, 0x0000, {0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x4080, 0x0000, 0xA200, 0x0000, 0x4080}}, + {0x0284, 0x0000, {0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x0000, 0xB404, 0x5404, 0x5404}}, }; s32 func_8033D240(ActorMarker *arg0, ActorMarker *arg1); @@ -242,10 +217,10 @@ Struct_core2_B62B0_1 D_80371DC0[11] = { {func_8033D2A8, HITBOX_2_BEAK_BARGE}, {func_8033D2A8, HITBOX_1_BEAK_BUSTER}, {func_8033D2A8, HITBOX_3_BEAK_BOMB}, - {func_8033D240, 1}, // Egg Firing + {func_8033D240, 1}, {func_8033D2A8, HITBOX_6_WONDERWING}, {func_8033D2A8, HITBOX_9_CROC_BITE}, - {func_8033D240, 0} // Other Contact + {func_8033D240, 0} }; /* .bss */ @@ -274,53 +249,49 @@ void func_8033D2F4(void) { s32 var_a0; bool var_a1; s32 var_v1; - s32 var_v0 = COLLISION_TABLE_SIZE; + s32 var_v0 = 0xBB; for(var_v1 = 0; var_v1 < 0x2A9; var_v1++) { - for(((var_a0 = 0), (var_a1 = FALSE), (D_80383F10[var_v1] = -1)); (var_a0 < var_v0) && !var_a1; var_a0++){ - if (var_v1 == collision_table[var_a0].markerId) { + for(((var_a0 = 0), (var_a1 = false), (D_80383F10[var_v1] = -1)); (var_a0 < var_v0) && !var_a1; var_a0++){ + if (var_v1 == D_80370AC0[var_a0].unk0) { D_80383F10[var_v1] = var_a0; - var_a1 = TRUE; + var_a1 = true; } } } for(var_a0 = 0; var_a0 < var_v0; var_a0++) { for(var_v1 = 0; var_v1 < 10; var_v1++){ - collision_table[var_a0].collisionTypes[var_v1] |= collision_table[var_a0].collisionUnion; + D_80370AC0[var_a0].unk4[var_v1] |= D_80370AC0[var_a0].unk2; } } } bool func_8033D410(ActorMarker *arg0, ActorMarker *arg1) { s32 var_s2; - s32 collision_index; + s32 sp38; s16 temp_t0; s32 temp_s0; - collision_index = D_80383F10[arg1->id]; - if (collision_index == -1) { - return FALSE; + sp38 = D_80383F10[arg1->id]; + if (sp38 == -1) { + return false; } for(var_s2 = 0; var_s2 < 11; var_s2++){ - if ((collision_table[collision_index].collisionTypes[var_s2] != 0) && (D_80371DC0[var_s2].unk0(arg0, arg1) == D_80371DC0[var_s2].unk4)) { - func_80330078(arg1, arg0, collision_table[collision_index].collisionTypes + var_s2); - func_80330078(arg0, arg1, collision_table[collision_index].collisionTypes + var_s2); + if ((D_80370AC0[sp38].unk4[var_s2] != 0) && (D_80371DC0[var_s2].unk0(arg0, arg1) == D_80371DC0[var_s2].unk4)) { + func_80330078(arg1, arg0, D_80370AC0[sp38].unk4 + var_s2); + func_80330078(arg0, arg1, D_80370AC0[sp38].unk4 + var_s2); break; } } - return TRUE; + return true; } s32 collision_getPlayerInteraction(CollisionParams *arg0){ - // Player Bounce vs Player Knockback - // Includes the distance the player is sent return arg0->playerInteraction; } enum marker_collision_func_type_e collision_getNextState(CollisionParams *arg0){ - // 01 -> Alternate State - // 10 -> Death return arg0->nextState; } @@ -333,16 +304,9 @@ s32 collision_getDamageToPlayer(CollisionParams *arg0){ } s32 collision_getHitsToTrigger(CollisionParams *arg0){ - // Enemies have health - // 1 divided by hits to trigger = % of health the enemy loses return arg0->hitsToTrigger; } s32 collision_getDropBundleNum(CollisionParams *arg0){ - // By default, - // 0 is nothing - // 1 is one honeycomb - // 2 is two honeycombs - // 3 is three honeycombs return arg0->dropBundleNum; } diff --git a/src/core2/collision/polydetect.c b/src/core2/collision/polydetect.c index 1903fd150..9d3869777 100644 --- a/src/core2/collision/polydetect.c +++ b/src/core2/collision/polydetect.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B9090.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/collision/raycast.c b/src/core2/collision/raycast.c index c4422b518..3192cbe9a 100644 --- a/src/core2/collision/raycast.c +++ b/src/core2/collision/raycast.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_94A20.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/collision/scarabbeetle.c b/src/core2/collision/raycastmap.c similarity index 97% rename from src/core2/collision/scarabbeetle.c rename to src/core2/collision/raycastmap.c index d0bfcebd6..d98f84bef 100644 --- a/src/core2/collision/scarabbeetle.c +++ b/src/core2/collision/raycastmap.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/scarabbeetle.c #include #include "functions.h" #include "variables.h" @@ -6,8 +5,8 @@ extern BKCollisionTriangle *func_80320DB0(f32[3], f32, f32[3], u32); /* .h */ -Actor *chScarabBeetle_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chScarabBeetle_update(Actor *this); +Actor *func_80358344(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_80358684(Actor *this); typedef struct { u8 sfxsourceIdx; @@ -25,14 +24,14 @@ typedef struct { }ActorLocal_core2_D0CA0; /* .data */ -// Scabby -ActorInfo chScarabBeetle = { +ActorInfo D_803728A0 = { MARKER_253_SCARAB_BEETLE, ACTOR_380_SCARAB_BEETLE, ASSET_51B_MODEL_SCARAB_BEETLE, 0, NULL, - chScarabBeetle_update, NULL, chScarabBeetle_draw, + func_80358684, NULL, func_80358344, 0, 0, 1.0f, 0 }; + /* .code */ bool func_80357C30(Actor *this) { ActorLocal_core2_D0CA0 *local; @@ -196,7 +195,7 @@ void func_80358304(ActorMarker *marker, ActorMarker *other_marker){ } } -Actor *chScarabBeetle_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { +Actor *func_80358344(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { Actor *this; ActorLocal_core2_D0CA0 *local; @@ -267,7 +266,7 @@ void func_80358610(Actor *this) { func_80358524(this->position, 4, 0x520); } -void chScarabBeetle_update(Actor *this) { +void func_80358684(Actor *this) { f32 sp94[3]; ActorLocal_core2_D0CA0 *local; //sp90 s32 next_state; //sp8C diff --git a/src/core2/collision/spherecast.c b/src/core2/collision/spherecast.c index 6c9ce5982..0522afcc4 100644 --- a/src/core2/collision/spherecast.c +++ b/src/core2/collision/spherecast.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_A4D00.c #include "functions.h" #include "structs.h" #include "variables.h" diff --git a/src/core2/collision/tricheck.c b/src/core2/collision/tricheck.c index 51a539d4a..37f171478 100644 --- a/src/core2/collision/tricheck.c +++ b/src/core2/collision/tricheck.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_BDCC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gc/bound.c b/src/core2/context/bound.c similarity index 98% rename from src/core2/gc/bound.c rename to src/core2/context/bound.c index 54bd56587..e179bf95a 100644 --- a/src/core2/gc/bound.c +++ b/src/core2/context/bound.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/bound.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gc/dialog.c b/src/core2/context/dialog.c similarity index 97% rename from src/core2/gc/dialog.c rename to src/core2/context/dialog.c index ad2493486..548508dfd 100644 --- a/src/core2/gc/dialog.c +++ b/src/core2/context/dialog.c @@ -1,9 +1,7 @@ -// BanjoDecomp: core2/gc/dialog.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "dialog.h" #include "core2/gc/zoombox.h" @@ -138,7 +136,7 @@ void gcdialog_init(void) { g_Dialog.unk128_3 = true; } -static void freeZoomboxes(void){ +static void _gcdialog_freeZoomboxes(void){ s32 i; for(i =0; i < 2; i++){ gczoombox_free(g_Dialog.zoombox[i]); @@ -169,7 +167,7 @@ void clearDialog(void){ func_80347A14(1); } if(!g_Dialog.unk11A[0].unk0_7 && !g_Dialog.unk11A[1].unk0_7){ - freeZoomboxes(); + _gcdialog_freeZoomboxes(); } g_Dialog.unk130 = -1; g_Dialog.unk128_15 = 0; @@ -246,7 +244,7 @@ void gcdialog_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ } } -void dialog_setState(s32 next_state){ +void gcdialog_setState(s32 next_state){ s32 i; s32 j; s32 v0 = 6; @@ -324,7 +322,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ break; case 3: //L8030F7BC - dialog_setState(2); + gcdialog_setState(2); break; case 4: //L8030F7CC @@ -333,7 +331,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ if(g_Dialog.unk12C_25 == 0){ temp_a0 = ((g_Dialog.unk11A[0].unk0_7) ? 1 : 0); temp_v0 = ((g_Dialog.unk11A[1].unk0_7) ? 1 : 0); - dialog_setState((temp_v0 + temp_a0) ? 8 : 5); + gcdialog_setState((temp_v0 + temp_a0) ? 8 : 5); }//L8030F980 break; } @@ -342,7 +340,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ if(temp_v0 > (s32)g_Dialog.unk12C_29){ g_Dialog.unk12C_29++; if(g_Dialog.unk128_15 == g_Dialog.unk12C_29 + g_Dialog.unk12C_27){ - dialog_setState(8); + gcdialog_setState(8); } } break; @@ -350,11 +348,11 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ case 6: //L8030F8FC g_Dialog.unk12C_27++; if(g_Dialog.unk12C_27 == g_Dialog.unk128_15){ - dialog_setState(7); + gcdialog_setState(7); }//L8030F964 if(g_Dialog.unk128_15 == g_Dialog.unk12C_29 + g_Dialog.unk12C_27){ - dialog_setState(8); + gcdialog_setState(8); } break; }//L8030F984 @@ -363,7 +361,7 @@ void newZoomboxCallback(GcZoomboxSprite portrait_id, s32 arg1){ #define CMD(i) (g_Dialog.string_list[g_Dialog.u8_s.active_zoombox] + i) #define CMD2(i) (&g_Dialog.string_list[g_Dialog.u8_s.active_zoombox][i]) -void dialog_update(void) { +void gcdialog_update(void) { s32 i; s32 spA8; s32 controller_face_buttons[6]; @@ -391,10 +389,10 @@ void dialog_update(void) { } } if (spA8 == 2) { - dialog_setState(7); + gcdialog_setState(7); } else if (g_Dialog.u8_s.unk12C_31 == g_Dialog.u8_s.unk128_15) { g_Dialog.u8_s.unk12C_31 = 0; - dialog_setState(2); + gcdialog_setState(2); } break; @@ -419,7 +417,7 @@ void dialog_update(void) { case -1: // Choice g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 = 2; - dialog_setState(4); + gcdialog_setState(4); break; case -4: // Close @@ -478,7 +476,7 @@ void dialog_update(void) { case -3: g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 = 0; - dialog_setState(4); + gcdialog_setState(4); break; default: @@ -566,7 +564,7 @@ void dialog_update(void) { g_Dialog.string_index[g_Dialog.u8_s.active_zoombox]++; } - dialog_setState(3); + gcdialog_setState(3); } break; } @@ -575,7 +573,7 @@ void dialog_update(void) { case 3: if ((g_Dialog.u8_s.unk128_31 & 1) && controller_face_buttons[FACE_BUTTON(BUTTON_B)] == 1u) { - dialog_setState(6); + gcdialog_setState(6); break; } @@ -587,7 +585,7 @@ void dialog_update(void) { break; } - dialog_setState(6); + gcdialog_setState(6); break; case 4: // Waiting for player to make choice @@ -598,13 +596,13 @@ void dialog_update(void) { } if (g_Dialog.u8_s.unk12C_23 != -1) { - dialog_setState(g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 ? 8 : 5); + gcdialog_setState(g_Dialog.unk11A[g_Dialog.u8_s.active_zoombox].unk0_7 ? 8 : 5); } break; case 7: case 8: - dialog_setState(0); + gcdialog_setState(0); break; } @@ -719,7 +717,7 @@ void loadAndCreateDialogs(s32 text_id, s32 arg1, ActorMarker *marker, void(*call g_Dialog.unk140 = arg4; g_Dialog.unk144 = arg5; g_Dialog.unk138 = (marker != NULL )? ((marker->unk5C)? marker->unk5C : -1) : 0; - dialog_setState(((func_802E4A08() || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE)) && g_Dialog.unk128_3) ? 6 : 1); + gcdialog_setState(((func_802E4A08() || volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE)) && g_Dialog.unk128_3) ? 6 : 1); //L803109EC } @@ -818,7 +816,7 @@ void func_80310D2C(void){ g_Dialog.unk12C_15--; }else{//L80310F88 - dialog_update(); + gcdialog_update(); }//L80310F98 if( ( g_Dialog.state != 0 && g_Dialog.state != 5 && g_Dialog.state != 7) || ((!g_Dialog.state && (g_Dialog.unk11A[0].unk0_7 || g_Dialog.unk11A[1].unk0_7))) @@ -863,7 +861,7 @@ void func_80310D2C(void){ } } -int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, s32 (*arg4)(ActorMarker *, enum asset_e, s32)){ +int func_803110F8(s32 next_state, s32 arg1, s32 arg2, s32 arg3, void (*arg4)(ActorMarker *, enum asset_e, s32)){ func_8025A55C(15000, 300, 2); gcdialog_showDialogConditional(next_state + 0xe57, 0x84, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker *, s32, s32))arg4); func_80310A5C(arg2, arg3, arg1, 0, 0); @@ -964,7 +962,7 @@ void func_803114D0(void){ s32 i; if(gcdialog_hasCurrentTextId()){ - dialog_setState(6); + gcdialog_setState(6); }else{ if(g_Dialog.state != 6){ g_Dialog.unk12C_25 = 0; @@ -988,7 +986,7 @@ int func_803115C4(s32 next_state){ if(gcdialog_getCurrentTextId() != next_state){ return 0; }else{ - dialog_setState(6); + gcdialog_setState(6); return 1; } } diff --git a/src/core2/gc/enter_text_trigger.c b/src/core2/context/enter_text_trigger.c similarity index 78% rename from src/core2/gc/enter_text_trigger.c rename to src/core2/context/enter_text_trigger.c index c089e8337..3c83c50c9 100644 --- a/src/core2/gc/enter_text_trigger.c +++ b/src/core2/context/enter_text_trigger.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_53A10.c #include #include "functions.h" #include "variables.h" @@ -6,9 +5,8 @@ void func_802DAA14(Actor *this); /* .data */ //000E0EE0 -// lair dialog object? -ActorInfo D_80367E70 = { - MARKER_21B_UNKNOWN, ACTOR_351_UNKNOWN, 0, +ActorInfo D_80367E70= { + 0x21B, 0x351, 0, 0, NULL, func_802DAA14, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 @@ -18,17 +16,16 @@ ActorInfo D_80367E70 = { /* .code */ void func_802DA9A0(ActorMarker *caller, enum asset_e text_id, s32 arg2){ enum file_progress_e flag; - enum file_progress_e flag_tmp; - + enum file_progress_e tmp; if(level_get() == LEVEL_A_MAD_MONSTER_MANSION){ flag = FILEPROG_15_ENTER_MMM_TEXT; } else{ if(gsworld_getMap() == MAP_69_GL_MM_LOBBY) - flag_tmp = FILEPROG_97_ENTERED_LAIR_TEXT; + tmp = FILEPROG_97_ENTERED_LAIR_TEXT; else - flag_tmp = FILEPROG_98_EXITED_LEVEL_TEXT; - flag = flag_tmp; + tmp = FILEPROG_98_EXITED_LEVEL_TEXT; + flag = tmp; } fileProgressFlag_set(flag, 1); FUNC_8030E624(SFX_EA_GRUNTY_LAUGH_1, 1.0f, 30000); @@ -72,13 +69,13 @@ void func_802DAA14(Actor *this){ if(!this->has_met_before){ if(level_get() == LEVEL_A_MAD_MONSTER_MANSION){ - text_id = VER_SELECT(ASSET_ADC_DIALOG_GRUNTY_ENTER_SHED, 0x94E, 0, 0); + text_id = ASSET_ADC_DIALOG_GRUNTY_ENTER_SHED; } else{ if(gsworld_getMap() == MAP_69_GL_MM_LOBBY) - tmp = VER_SELECT(ASSET_F66_DIALOG_UNKNOWN, 0xACC, 0, 0); + tmp = ASSET_F66_DIALOG_UNKNOWN; else - tmp = VER_SELECT(ASSET_F67_DIALOG_UNKNOWN, 0xACD, 0, 0); + tmp = ASSET_F67_DIALOG_UNKNOWN; text_id = tmp; } gcdialog_showDialog(text_id, 4, NULL, this->marker, func_802DA9A0, NULL); diff --git a/src/core2/gc/gameoversign.c b/src/core2/context/gameover.c similarity index 85% rename from src/core2/gc/gameoversign.c rename to src/core2/context/gameover.c index 9e63caa9e..3ace29792 100644 --- a/src/core2/gc/gameoversign.c +++ b/src/core2/context/gameover.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/gameoversign.c #include #include "core1/core1.h" #include "functions.h" @@ -8,15 +7,14 @@ extern void actor_postdrawMethod(ActorMarker *); Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void gcGameOverSign_update(Actor *this); +void func_802DC45C(Actor *this); /* .data */ f32 D_80368040[3] = {0.0f, 0.0f, 0.0f}; - -ActorInfo gcGameOverSign = { +ActorInfo D_8036804C = { MARKER_174_GAME_OVER, ACTOR_1DB_GAME_OVER, ASSET_54C_MODEL_GAME_OVER, 0x1, NULL, - gcGameOverSign_update, actor_update_func_80326224, func_802DC320, + func_802DC45C, actor_update_func_80326224, func_802DC320, 0, 0, 0.0f, 0 }; @@ -58,23 +56,23 @@ Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ } -void gcGameOverSign_free(Actor * this){ +void func_802DC430(Actor * this){ D_8037DE40 = NULL; func_8025A7DC(COMUSIC_31_GAME_OVER); } -void gcGameOverSign_update(Actor *this){ +void func_802DC45C(Actor *this){ if(!this->initialized){ this->initialized = true; this->depth_mode = MODEL_RENDER_DEPTH_NONE; func_803262E4(this); actor_collisionOff(this); - marker_setFreeMethod(this->marker, gcGameOverSign_free); + marker_setFreeMethod(this->marker, func_802DC430); } } -void gcGameOverSign_spawn(void) { +void func_802DC4C4(void) { Actor *actor; if (D_8037DE40 == 0) { actor = actor_spawnWithYaw_f32(ACTOR_1DB_GAME_OVER, D_80368040, 0); @@ -87,7 +85,7 @@ void gcGameOverSign_spawn(void) { void func_802DC528(NodeProp *arg0, ActorMarker *arg1){ if(D_8037DE40 == NULL){ - __spawnQueue_add_0(gcGameOverSign_spawn); + __spawnQueue_add_0(func_802DC4C4); } } @@ -101,7 +99,7 @@ void func_802DC560(NodeProp *arg0, ActorMarker *arg1){ void func_802DC5B8(void){ if(D_8037DE40 != NULL){ - gcGameOverSign_update(marker_getActor(D_8037DE40)); + func_802DC45C(marker_getActor(D_8037DE40)); func_80326894(marker_getActor(D_8037DE40)); } } diff --git a/src/core2/gc/section.c b/src/core2/context/map_info.c similarity index 99% rename from src/core2/gc/section.c rename to src/core2/context/map_info.c index cc38fb812..fb2d95f52 100644 --- a/src/core2/gc/section.c +++ b/src/core2/context/map_info.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/section.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gc/overlaycopyright.c b/src/core2/context/overlay_copyright.c similarity index 97% rename from src/core2/gc/overlaycopyright.c rename to src/core2/context/overlay_copyright.c index 132d5f048..d0b34563c 100644 --- a/src/core2/gc/overlaycopyright.c +++ b/src/core2/context/overlay_copyright.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/overlaycopyright.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gc/overlaynocontroller.c b/src/core2/context/overlay_nocontroller.c similarity index 97% rename from src/core2/gc/overlaynocontroller.c rename to src/core2/context/overlay_nocontroller.c index b0f1e3d26..95a51d662 100644 --- a/src/core2/gc/overlaynocontroller.c +++ b/src/core2/context/overlay_nocontroller.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/overlaynocontroller.c #include #include "core1/core1.h" #include "functions.h" @@ -18,10 +17,8 @@ ActorAnimationInfo D_80368150[] ={ {0x286, 1.1f}, {0x287, 1.6f} }; - f32 D_80368168[3] = {0.0f, 0.0f, 0.0f}; - -ActorInfo chOverlayNoController = { +ActorInfo D_80368174 = { MARKER_178_NO_CONTROLLER_OVERLAY, ACTOR_1DF_NO_CONTROLLER_OVERLAY, ASSET_55D_MODEL_NO_CONTROLLER_OVERLAY, 0x0, D_80368150, chOverlayNoController_update, actor_update_func_80326224, chOverlayNoController_draw, diff --git a/src/core2/gc/overlaypressstart.c b/src/core2/context/overlay_pressstart.c similarity index 94% rename from src/core2/gc/overlaypressstart.c rename to src/core2/context/overlay_pressstart.c index 8ac99b3ab..ebba0e6cc 100644 --- a/src/core2/gc/overlaypressstart.c +++ b/src/core2/context/overlay_pressstart.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/overlaypressstart.c #include #include "core1/core1.h" #include "functions.h" @@ -17,7 +16,7 @@ void chOverlayPressStart_update(Actor *this); /* .data */ -ActorAnimationInfo chOverlayPressStartAnimations[] = { +ActorAnimationInfo D_80368100[] = { {0, 0.0f}, {0x284, 1.6f}, {0x285, 1.6f} @@ -25,9 +24,9 @@ ActorAnimationInfo chOverlayPressStartAnimations[] = { f32 D_80368118[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo chOverlayPressStart = { +ActorInfo D_80368124 = { MARKER_177_PRESS_START_OVERLAY, ACTOR_1DE_PRESS_START_OVERLAY, ASSET_55C_MODEL_PRESS_START_OVERLAY, - 0x0, chOverlayPressStartAnimations, + 0x0, D_80368100, chOverlayPressStart_update, actor_update_func_80326224, chOverlayPressStart_draw, 0, 0, 0.0f, 0 }; diff --git a/src/core2/gc/parade.c b/src/core2/context/parade.c similarity index 99% rename from src/core2/gc/parade.c rename to src/core2/context/parade.c index 87d83a3ac..c2dc549cb 100644 --- a/src/core2/gc/parade.c +++ b/src/core2/context/parade.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/parade.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gc/pauseMenu.c b/src/core2/context/pause_menu.c similarity index 95% rename from src/core2/gc/pauseMenu.c rename to src/core2/context/pause_menu.c index 53aec1773..3180bf448 100644 --- a/src/core2/gc/pauseMenu.c +++ b/src/core2/context/pause_menu.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/pauseMenu.c #include #include "core1/core1.h" #include "functions.h" @@ -428,11 +427,6 @@ void gcpausemenu_printTotals(void) { } s32 gcpausemenu_levelToMenuPage(enum level_e level) { - // [port] Romhack gate: listeners can pin every level to one menu page. - s32 override_page = 0; - if (!EventSystem_Should(VB_PAUSEMENU_LEVEL_TO_PAGE, true, level, &override_page)) { - return override_page; - } switch (level) { case LEVEL_1_MUMBOS_MOUNTAIN: case LEVEL_2_TREASURE_TROVE_COVE: @@ -536,10 +530,7 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { gcpausemenu_zoomboxes_initTotalsMenu(); if (D_80383010.selection == gcpausemenu_levelToMenuPage(level_get())) { - // [port] Romhack gate: listeners can swap the highlight bold-font texture. - s32 boldFontId = 0x6e7; - EventSystem_Should(VB_PAUSEMENU_BOLD_FONT_TEXTURE, true, &boldFontId); - print_setBoldFontTexture(boldFontId); + print_setBoldFontTexture(0x6e7); } if (D_80383010.selection) { @@ -555,17 +546,13 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { if (hideCollLvl < 0) { hideCollLvl = LEVEL_6_LAIR; } if (hideJigLvl < 0) { hideJigLvl = LEVEL_B_SPIRAL_MOUNTAIN; } for (i = 0; i < 4; i++) { - s32 rowVisible; if (selLvl == hideCollLvl) { - rowVisible = (!(i == 0) && !(i == 2)); + gczoombox_highlight(D_80383010.zoombox[i], (!(i == 0) && !(i == 2))); } else if (selLvl == hideJigLvl) { - rowVisible = (!(i == 0) && !(i == 1)); + gczoombox_highlight(D_80383010.zoombox[i], (!(i == 0) && !(i == 1))); } else { - rowVisible = 1; + gczoombox_highlight(D_80383010.zoombox[i], 1); } - // [port] Romhack gate: level-merging hacks can hide extra rows per page. - rowVisible = EventSystem_Should(VB_PAUSEMENU_ROW_VISIBLE, rowVisible, selLvl, i); - gczoombox_highlight(D_80383010.zoombox[i], rowVisible); } break; @@ -622,10 +609,7 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { D_80383010.selection = D_80383010.page; if (D_80383010.selection && D_80383010.selection == gcpausemenu_levelToMenuPage(level_get())) { - // [port] Romhack gate: listeners can swap the highlight bold-font texture. - s32 boldFontId = 0x6e7; - EventSystem_Should(VB_PAUSEMENU_BOLD_FONT_TEXTURE, true, &boldFontId); - print_setBoldFontTexture(boldFontId); + print_setBoldFontTexture(0x6e7); } if (D_80383010.selection) { @@ -641,17 +625,13 @@ void gcPauseMenu_setState(enum gcpausemenu_state_e next_state) { if (hideCollLvl < 0) { hideCollLvl = LEVEL_6_LAIR; } if (hideJigLvl < 0) { hideJigLvl = LEVEL_B_SPIRAL_MOUNTAIN; } for (i = 0; i < 4; i++) { - s32 rowVisible; if (selLvl == hideCollLvl) { - rowVisible = !((i == 0) || (i == 2)); + gczoombox_highlight(D_80383010.zoombox[i], !((i == 0) || (i == 2))); } else if (selLvl == hideJigLvl) { - rowVisible = (!(i == 0) && !(i == 1)); + gczoombox_highlight(D_80383010.zoombox[i], (!(i == 0) && !(i == 1))); } else { - rowVisible = 1; + gczoombox_highlight(D_80383010.zoombox[i], 1); } - // [port] Romhack gate: level-merging hacks can hide extra rows per page. - rowVisible = EventSystem_Should(VB_PAUSEMENU_ROW_VISIBLE, rowVisible, selLvl, i); - gczoombox_highlight(D_80383010.zoombox[i], rowVisible); if (gczoombox_is_highlighted(D_80383010.zoombox[i])) { gczoombox_maximize(D_80383010.zoombox[i]); @@ -887,11 +867,7 @@ void gcpausemenu_printTotalsHeader(s32 page_id) { if (port_pauseBannerUpdate(page_id)) { return; } - // [port] A custom romhack name inherits the vanilla name's hand-tuned x; let a - // listener recenter it for its own width. - s32 nameX = v0->x; - EventSystem_Should(VB_PAUSEMENU_LEVEL_NAME_X, true, &nameX, page_id, (const char*)v0->string, name); - print_bold_overlapping(nameX, D_80383010.unk8, -1.05f, name ? (u8*)name : v0->string); + print_bold_overlapping(v0->x, D_80383010.unk8, -1.05f, name ? (u8*)name : v0->string); } void gcpausemenu_80312FD0(s32 arg0) { @@ -921,10 +897,6 @@ s32 gcpausemenu_getMaxPage(void) { } void gcpausemenu_setNextPage(s32 increment) { - // [port] Romhack gate: listeners can pin the page and skip paging entirely. - if (!EventSystem_Should(VB_PAUSEMENU_SET_NEXT_PAGE, true, &D_80383010.page)) { - return; - } D_80383010.page = D_80383010.selection; do { D_80383010.page += increment; @@ -1496,10 +1468,8 @@ void gcpausemenu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { } } - if (EventSystem_Should(VB_PAUSEMENU_DRAW_JOYSTICKS, true, NULL)) { - gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, 30.0f, 196.0f, 1, (s32) D_80383010.left_joystick_alpha); - gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, (f32)(gFramebufferWidth - 0x1E), 196.0f, 0, (s32) D_80383010.right_joystick_alpha); - } + gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, 30.0f, 196.0f, 1, (s32) D_80383010.left_joystick_alpha); + gcpausemenu_drawSprite(gfx, mtx, vtx, D_80383010.joystick_sprite, D_80383010.joystick_frame, (f32)(gFramebufferWidth - 0x1E), 196.0f, 0, (s32) D_80383010.right_joystick_alpha); // [port] Original decomp used raw u32 bit extraction: ((*((u32*)&D_80383010.state) << N) >> 0x1f) // This depends on big-endian byte order (byte 3 of the u32 is the bitfield byte on MIPS). // On little-endian, byte 0 of the u32 is 'state', so the shifts extract wrong bits. @@ -1578,9 +1548,9 @@ void gcpausemenu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { sp80[2] = 0.0f; for (var_s0_2 = 0; var_s0_2 < 7; var_s0_2++) { - modelRender_setAppendageVisibility(var_s0_2 + 1, 0); + func_8033A45C(var_s0_2 + 1, 0); } - modelRender_setAppendageVisibility(i, 1); + func_8033A45C(i, 1); modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE); modelRender_setAlpha(D_80383010.sns_alpha); modelRender_draw(gfx, mtx, sp98, sp8C, 0.8f, sp80, D_80383010.sns_egg_model); diff --git a/src/core2/gc/pictureframe.c b/src/core2/context/pictureframe.c similarity index 89% rename from src/core2/gc/pictureframe.c rename to src/core2/context/pictureframe.c index 4697b14a5..483d22a7b 100644 --- a/src/core2/gc/pictureframe.c +++ b/src/core2/context/pictureframe.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_581D0.c #include #include "functions.h" #include "variables.h" @@ -12,11 +11,8 @@ void func_802DF2C4(Actor *this); f32 D_80368360[3] = {0.0f, 0.0f, 0.0f}; s32 D_8036836C[4] = {0x60, 0x60, 0x60, 0xFF}; s32 D_8036837C[4] = {0xFF, 0xFF, 0xFF, 0xFF}; - -// Asset is blank white rectangle -// Appears during Bottles Bonus ActorInfo D_8036838C = { - MARKER_17B_UNKNOWN, ACTOR_2B5_UNKNOWN, ASSET_472_UNKNOWN, + 0x17B, 0x2B5, 0x472, 0, NULL, func_802DF2C4, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 @@ -32,9 +28,10 @@ Actor *func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx) { void *sp38; this = marker_getActor(D_8037E000); - sp38 = picturebox_getColorBuffer(); + sp38 = func_8030C704(); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); gDPSetTextureFilter((*gfx)++, G_TF_BILERP); + port_readAuxFbToCpu(gfx); gSPSegment((*gfx)++, 0x04, osVirtualToPhysical(sp38)); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)this); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)D_8037E000); @@ -48,17 +45,15 @@ Actor *func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx) { void func_802DF270(void){ Actor *this; if(D_8037E000 == NULL){ - this = actor_spawnWithYaw_f32(ACTOR_2B5_UNKNOWN, D_80368360, 0); + this = actor_spawnWithYaw_f32(0x2B5, D_80368360, 0); D_8037E000 = this->marker; } } -// free void func_802DF2B4(Actor *this){ D_8037E000 = NULL; } -// update void func_802DF2C4(Actor *this) { s32 temp_fp; s32 i; @@ -66,6 +61,7 @@ void func_802DF2C4(Actor *this) { Struct70s *temp_v0; s32 val; + temp_fp = chBottlesBonusCursor_func_802E06B4() - 0x15; if (!this->initialized) { this->initialized = true; diff --git a/src/core2/gc/sky.c b/src/core2/context/sky.c similarity index 88% rename from src/core2/gc/sky.c rename to src/core2/context/sky.c index fe157f99e..021c6205e 100644 --- a/src/core2/gc/sky.c +++ b/src/core2/context/sky.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/sky.c #include #include "core1/core1.h" #include "functions.h" @@ -65,7 +64,7 @@ static MapSkyInfo sSkyOverride; MapSkyInfo * sky_getMapSkyInfo(enum map_e map_id){ int models[3]; float scales[3], rotations[3]; - if (port_getRomhackSkyboxFull(map_id, models, scales, rotations)) { + if (port_getRomhackSkyboxFull(map_getLevel(map_id), models, scales, rotations)) { sSkyOverride.map = map_id; for (int i = 0; i < 3; i++) { sSkyOverride.sky_list[i].model_id = (s16)models[i]; @@ -85,32 +84,30 @@ MapSkyInfo * sky_getMapSkyInfo(enum map_e map_id){ return v1; } -void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){ int i; f32 position[3]; f32 rotation[3]; - BKModelBin *sky_model_bin; + BKModelBin *iAsset; viewport_setNearAndFar(5.0f, 15000.0f); - - if (gcSky.model_bins[0]) { - if (EventSystem_Should(VB_SKY_DRAW_BACKDROP_RECT, true)) { - drawRectangle2D(gfx, 0, 0, (f32) gFramebufferWidth, (f32) gFramebufferHeight, 0, 0, 0); - } + if(gcSky.model_bins[0]){ + drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight, 0, 0, 0); viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); viewport_getPosition_vec3f(position); - for (i = 0; i < 3; i++) { - sky_model_bin = gcSky.model_bins[i]; - if (sky_model_bin) { + for(i = 0; i < 3; i++){ + iAsset = gcSky.model_bins[i]; + if(iAsset){ rotation[0] = 0.0f; rotation[1] = gcSky.sky_info->sky_list[i].rotation_speed * gcSky.timer; rotation[2] = 0.0f; - modelRender_draw(gfx, mtx, position, rotation, gcSky.sky_info->sky_list[i].scale, NULL, sky_model_bin); + modelRender_draw(gfx, mtx, position, rotation, gcSky.sky_info->sky_list[i].scale, NULL, iAsset); } } - } else { - drawRectangle2D(gfx, 0, 0, (f32) gFramebufferWidth, (f32) gFramebufferHeight, 0, 0, 0); } + else{//L8030B200 + drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight, 0, 0, 0); + }//L8030B254 } void sky_free(void){ diff --git a/src/core2/gc/transition.c b/src/core2/context/transition.c similarity index 94% rename from src/core2/gc/transition.c rename to src/core2/context/transition.c index 01408d48a..ea1ea1248 100644 --- a/src/core2/gc/transition.c +++ b/src/core2/context/transition.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/transition.c #include #include "core1/core1.h" #include "functions.h" @@ -6,7 +5,6 @@ #include "gc/gctransition.h" #include "port/Patches/Patches.h" #include "port/Engine.h" -#include "port/Interpolation/FrameInterpolation.h" void anctrl_setAnimTimer(AnimCtrl*, f32); void func_8025AC20(s32, s32, s32, f32, char*, s32); @@ -243,7 +241,7 @@ void gctransition_defrag(void){ s_current_transition.model_ptr = defrag_asset(s_current_transition.model_ptr); } -void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){ f32 vp_position[3]; f32 vp_rotation[3]; f32 percentage; @@ -254,7 +252,6 @@ void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { if(s_current_transition.state == 0) return; - FrameInterpolation_RecordOpenChild("transition", 0); viewport_backupState(); if(s_current_transition.anctrl != NULL){ vp_position[0] = 0.0f; @@ -273,31 +270,31 @@ void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { viewport_setPosition_vec3f(vp_position); //viewport_getPosition_vec3f viewport_setRotation_vec3f(vp_rotation); //viewport_getRotation_vec3f viewport_update(); //camera_updateNormal - viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); + viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); sp58[0] = 0.0f; sp58[1] = 0.0f; sp58[2] = 0.0f; if(s_current_transition.anctrl != NULL){ - gDPSetTextureFilter((*gfx)++, G_TF_POINT); - gDPSetColorDither((*gfx)++, G_CD_DISABLE); + gDPSetTextureFilter((*gdl)++, G_TF_POINT); + gDPSetColorDither((*gdl)++, G_CD_DISABLE); anctrl_drawSetup(s_current_transition.anctrl, sp58, 1); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); } // [port] Widescreen transition scaling is applied by the port listener f32 transitionScale = 1.0f; - CALL_EVENT(OnTransitionModelScale, gfx, mtx, + CALL_EVENT(OnTransitionModelScale, gdl, mptr, s_current_transition.transistion_info != NULL ? s_current_transition.transistion_info->uid : 0, &transitionScale); //complex animation (from animation bin file) if(s_current_transition.state == 1 || s_current_transition.state == 6){ - modelRender_draw(gfx, mtx, sp58, vp_rotation, 1.0f, 0, s_current_transition.model_ptr); + modelRender_draw(gdl, mptr, sp58, vp_rotation, transitionScale, 0, s_current_transition.model_ptr); if(s_current_transition.anctrl != NULL){ - gDPSetTextureFilter((*gfx)++, G_TF_BILERP); - gDPSetColorDither((*gfx)++, G_CD_MAGICSQ); + gDPSetTextureFilter((*gdl)++, G_TF_BILERP); + gDPSetColorDither((*gdl)++, G_CD_MAGICSQ); } return; } @@ -314,7 +311,7 @@ void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { vp_rotation[2] = s_current_transition.rotation - 90.0f*percentage; scale = percentage*s_current_transition.transistion_info->scale + 0.1; } - modelRender_draw(gfx, mtx, sp58, vp_rotation, scale, 0, s_current_transition.model_ptr); + modelRender_draw(gdl, mptr, sp58, vp_rotation, scale * transitionScale, 0, s_current_transition.model_ptr); } else if(s_current_transition.state == TRANSITION_STATE_5_FADE_OUT){//L8030B9EC switch (s_current_transition.transistion_info->uid) @@ -335,7 +332,7 @@ void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { break; } if(!(s_current_transition.substate < 3) || s_current_transition.transistion_info->uid != 0x11){ - modelRender_draw(gfx, mtx, sp58, vp_rotation, scale, 0, s_current_transition.model_ptr); + modelRender_draw(gdl, mptr, sp58, vp_rotation, scale * transitionScale, 0, s_current_transition.model_ptr); } else{ modelRender_reset(); @@ -347,14 +344,14 @@ void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { gcbound_reset(); gcbound_alpha((1.0f - percentage)*255.0f + 0.5); gcbound_color(0,0,0); - gcbound_draw(gfx); + gcbound_draw(gdl); } else if(s_current_transition.state == TRANSITION_STATE_3_BLACK_OUT){//L8030BB6C //fade out black (i.e. get more black) gcbound_reset(); gcbound_alpha(percentage*255.0f + 0.5); gcbound_color(0,0,0); - gcbound_draw(gfx); + gcbound_draw(gdl); } else if(s_current_transition.state == TRANSITION_STATE_7_WHITE_IN){//L8030BBD8 //fade in white (i.e. get less white) @@ -362,35 +359,31 @@ void gctransition_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { gcbound_reset(); gcbound_alpha(percentage*255.0f + 0.5); gcbound_color(0xff,0xff,0xff); - gcbound_draw(gfx); + gcbound_draw(gdl); } else if(s_current_transition.state == TRANSITION_STATE_8_WHITE_OUT){//L8030BC8C //fade out white (i.e. get more white) gcbound_reset(); gcbound_alpha(percentage*255.0f + 0.5); gcbound_color(0xff,0xff,0xff); - gcbound_draw(gfx); + gcbound_draw(gdl); }//L8030BD00 else{ } if(s_current_transition.anctrl != NULL){ - gDPSetTextureFilter((*gfx)++, G_TF_BILERP); + gDPSetTextureFilter((*gdl)++, G_TF_BILERP); } viewport_restoreState(); - viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); - FrameInterpolation_RecordCloseChild(); + viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); + } void gctransition_8030BD4C(void){ MapTransitionInfo *tmp_10s; TransitionInfo *tmp_a1; - s32 in_index; tmp_10s = _gctranstion_get_map_transition_info(gsworld_getMap()); - in_index = tmp_10s->in_index; - // [port] Romhack gate: listeners may override the incoming transition style. - EventSystem_Should(VB_MAP_TRANSITION_IN_INDEX, true, gsworld_getMap(), &in_index); - tmp_a1 = _gctranstion_8030B400(in_index); + tmp_a1 = _gctranstion_8030B400(tmp_10s->in_index); _gctranstion_changeState(tmp_a1->state, tmp_a1); } @@ -421,7 +414,7 @@ void gctransition_8030BE3C(void){ void gctransition_8030BE60(void){ TransitionInfo *tmp_a1; tmp_a1 = _gctranstion_8030B400(_gctranstion_get_map_transition_info(gsworld_getMap())->out_index); - picturebox_func_8030C180(); + func_8030C180(); _gctranstion_changeState(tmp_a1->state, tmp_a1); } @@ -510,7 +503,7 @@ void gctransition_update(void){ }//L8030C104 _gctranstion_changeState(s_current_transition.transistion_info->next_state, 0); if(s_current_transition.state == TRANSITION_STATE_4_FADE_IN) - picturebox_func_8030C180(); + func_8030C180(); if(s_current_transition.anctrl != NULL) gsworld_update(); diff --git a/src/core2/gc/zoombox.c b/src/core2/context/zoombox.c similarity index 98% rename from src/core2/gc/zoombox.c rename to src/core2/context/zoombox.c index 6a59d9769..40b629804 100644 --- a/src/core2/gc/zoombox.c +++ b/src/core2/context/zoombox.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/zoombox.c #include #include "core1/core1.h" #include "core1/core1.h" @@ -419,9 +418,9 @@ gczoomboxPortraitInfo D_8036C6C0[] = { {SFX_FA_GRUNTLING_NOISE_2, 20000, 1.3f}, {SFX_FB_GRUNTLING_NOISE_3, 20000, 1.3f} }}, - {0x084A, VER_SELECT(0xF2, 0xF0, 0, 0), VER_SELECT(0x0A, 0x05, 0, 0), {{VER_SELECT(SFX_6E_VILE_EGH, SFX_C3_HEGH, 0, 0), 20000, 1.0f}}}, - {0x084B, VER_SELECT(0xF2, 0xF0, 0, 0), VER_SELECT(0x0A, 0x05, 0, 0), {{VER_SELECT(SFX_6E_VILE_EGH, SFX_C3_HEGH, 0, 0), 20000, VER_SELECT(1.0f, 1.1f, 0.0f, 0.0f)}}}, - {0x084C, VER_SELECT(0xF2, 0xF0, 0, 0), VER_SELECT(0x0A, 0x05, 0, 0), {{VER_SELECT(SFX_6E_VILE_EGH, SFX_C3_HEGH, 0, 0), 20000, VER_SELECT(1.0f, 0.9f, 0.0f, 0.0f)}}}, + {0x084A, 0xF2, 0x0A, {{SFX_6E_VILE_EGH, 20000, 1.0f}}}, + {0x084B, 0xF2, 0x0A, {{SFX_6E_VILE_EGH, 20000, 1.0f}}}, + {0x084C, 0xF2, 0x0A, {{SFX_6E_VILE_EGH, 20000, 1.0f}}}, }; s32 D_8036D924[] = { 70, 35, 18, 9, 4, 2, 1}; @@ -614,9 +613,7 @@ void func_8031594C(GcZoombox * this, u8 *str, s32 arg2, s32 arg3){ s1 = 0; f22 = (this->portrait_id == ZOOMBOX_SPRITE_5F_TOOTY_4) ? 0.4 : 0.8; - // [port] The zoombox draws from the shared gameplay RNG, and these two calls are a - // save/restore of the whole state around that. - if(func_802E4A08()){ + if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ sfx_rand_sync_to_rand(); } for(s2 = arg2; s2 <= arg3; s2++){ @@ -669,7 +666,7 @@ void func_8031594C(GcZoombox * this, u8 *str, s32 arg2, s32 arg3){ }//L80315B6C this->unk189 = s1; this->unk187 = 0; - if(func_802E4A08()){ + if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ rand_sync_to_sfx_rand(); } } @@ -997,7 +994,7 @@ void gczoombox_draw(GcZoombox *this, Gfx **gdl, Mtx ** mptr, void *vptr){ if(!this) return; - if(func_802E4A08()) + if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE) sfx_rand_sync_to_rand(); //L80316BCC // [port] Stable scope. The crossfade branch below toggles 1↔2 sprite @@ -1048,7 +1045,7 @@ void gczoombox_draw(GcZoombox *this, Gfx **gdl, Mtx ** mptr, void *vptr){ } }//L80316DD8 FrameInterpolation_RecordCloseChild(); - if(func_802E4A08()){ + if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ rand_sync_to_sfx_rand(); } @@ -1403,14 +1400,9 @@ void __gczoombox_load_sfx(GcZoombox *this, GcZoomboxSprite portrait_id){ } //L80317E48 } - // [port] Balanced bracket. Vanilla restores below without a matching save, - // which rewinds the shared stream to whenever the last snapshot was taken; - // taking one here means the restore only undoes this randi2. - if(func_802E4A08()){ - sfx_rand_sync_to_rand(); - } this->prev_sfx = randi2(0,this->sfx_count); - if(func_802E4A08()){ + // [port] This mode needs a rand sync like many other places + if(getGameMode() == GAME_MODE_9_BANJO_AND_KAZOOIE){ rand_sync_to_sfx_rand(); } } diff --git a/src/core2/crc_bootvalidation.c b/src/core2/crc_bootvalidation.c index 079c30546..73c64a4ee 100644 --- a/src/core2/crc_bootvalidation.c +++ b/src/core2/crc_bootvalidation.c @@ -1,90 +1,92 @@ -// BanjoDecomp: core2/code_CF5F0.c #include -#include "bool.h" -#include "checksums.h" -#include "enums.h" +#include "functions.h" +#include "variables.h" -extern u8 boot_bk_boot_ROM_START[]; // bk_boot segment start (skipping entry function) -extern u8 boot_bk_boot_ROM_END[]; // bk_boot segment end +//THIS VALUE +#ifndef CORE2_CODE_CRC2 + #define CORE2_CODE_CRC2 0x9E44C2DC +#endif + +// bk_boot segment start (skipping entry function) +extern u8 boot_bk_boot_ROM_START[]; +// bk_boot segment end +extern u8 boot_bk_boot_ROM_END[]; +extern u8 crc_ROM_START[]; +// bk_boot segment crc next word s32 D_803727F0 = 0; -s32 D_803727F4 = VER_SELECT(0x9E44C2DC, 0xC1A6FD58, 0, 0); // CORE2_TEXT_CRC2 +s32 D_803727F4 = CORE2_CODE_CRC2; s32 D_803727F8 = 0; +s32 D_803727FC = 0; -s32 sBootROMOffset = 0; -u32 sCalculatedChecksum1 = 0; -u32 sCalculatedChecksum2 = 0; -s32 sBootROMRemainingBytes = 0; +// bk_boot segment crc values +s32 D_80372800 = 0; +s32 D_80372804 = 0; -void codeCF5F0_reset(void) { +// bk_boot segment crc remaining words +s32 D_80372808 = 0; + +// init bk_boot crc +void codeCF5F0_initChecksumsVars(void) { #if ANTI_TAMPER - sBootROMOffset = (s32) boot_bk_boot_ROM_START; - sCalculatedChecksum1 = 0; - sCalculatedChecksum2 = -1; - sBootROMRemainingBytes = (s32) (boot_bk_boot_ROM_END - boot_bk_boot_ROM_START); + D_803727FC = (s32) boot_bk_boot_ROM_START; + D_80372800 = 0; + D_80372804 = -1; + D_80372808 = (s32) (boot_bk_boot_ROM_END - boot_bk_boot_ROM_START); #endif } -bool codeCF5F0_validate(void) { +// advance bk_boot crc by one word +s32 codeCF5F0_areChecksumsValid(void) { + // Lighthouse TODO what should this actually return? #if ANTI_TAMPER - u32 checksum1, checksum2; - u8 rom_bytes[4]; - u8 cur_byte; - - if (sBootROMOffset != 0) { - if (sBootROMRemainingBytes != 0) { - checksum1 = sCalculatedChecksum1; - checksum2 = sCalculatedChecksum2; - - osPiReadIo(sBootROMOffset, (u32 *) rom_bytes); - - cur_byte = rom_bytes[0]; - checksum1 += cur_byte; - checksum2 ^= cur_byte << (checksum1 & 0x17); - - cur_byte = rom_bytes[1]; - checksum1 += cur_byte; - checksum2 ^= cur_byte << (checksum1 & 0x17); - - cur_byte = rom_bytes[2]; - checksum1 += cur_byte; - checksum2 ^= cur_byte << (checksum1 & 0x17); - - cur_byte = rom_bytes[3]; - checksum1 += cur_byte; - checksum2 ^= cur_byte << (checksum1 & 0x17); - - sCalculatedChecksum1 = checksum1; - sCalculatedChecksum2 = checksum2; - - sBootROMOffset += 4; - sBootROMRemainingBytes -= 4; + u32 crc1; + u32 crc2; + u8 romBytes[4]; + u8 curByte; + + if (D_803727FC != 0) { + if (D_80372808 != 0) { + crc1 = D_80372800; + crc2 = D_80372804; + osPiReadIo(D_803727FC, (u32*)romBytes); + curByte = romBytes[0]; + crc1 += curByte; + crc2 ^= curByte << (crc1 & 0x17); + curByte = romBytes[1]; + crc1 += curByte; + crc2 ^= curByte << (crc1 & 0x17); + curByte = romBytes[2]; + crc1 += curByte; + crc2 ^= curByte << (crc1 & 0x17); + curByte = romBytes[3]; + crc1 += curByte; + crc2 ^= curByte << (crc1 & 0x17); + D_80372800 = crc1; + D_80372804 = crc2; + D_803727FC = D_803727FC + 4; + D_80372808 = D_80372808 - 4; } else { - sBootROMOffset = 0; - - osPiReadIo((u32) crc_ROM_START + CRC_BOOT_TEXT_CHECKSUM1, &checksum1); - if (checksum1 != sCalculatedChecksum1) - return FALSE; - - osPiReadIo((u32) crc_ROM_START + CRC_BOOT_TEXT_CHECKSUM2, &checksum2); - if (checksum2 != sCalculatedChecksum2) - return FALSE; + D_803727FC = 0; + osPiReadIo((u32)crc_ROM_START + 0, &crc1); + if (crc1 != D_80372800) + return 0; + osPiReadIo((u32)crc_ROM_START + 4, &crc2); + if (crc2 != D_80372804) + return 0; } } #endif - - return TRUE; + return 1; } -void codeCF5F0_init(void) { - codeCF5F0_reset(); +void func_80356714(void) { + codeCF5F0_initChecksumsVars(); } -void codeCF5F0_triggerAntiTamperMeasurement(void) { -#if ANTI_TAMPER - codeCF5F0_validate(); - if (!codeCF5F0_validate()) { - ability_setAllLearned(1 << ABILITY_4_CLAW_SWIPE); +void codeCF5F0_forgetAllAbilitiesExceptClawSwipeIfChecksumsFail(void) { + codeCF5F0_areChecksumsValid(); + if (codeCF5F0_areChecksumsValid() == 0) { + ability_setAllLearned(0x10); } -#endif } diff --git a/src/core2/mumboshandwithpicture.c b/src/core2/demo_ctrl.c similarity index 68% rename from src/core2/mumboshandwithpicture.c rename to src/core2/demo_ctrl.c index 5c4b044fe..d7f4f15cb 100644 --- a/src/core2/mumboshandwithpicture.c +++ b/src/core2/demo_ctrl.c @@ -1,31 +1,31 @@ -// BanjoDecomp: core2/ch/mumboshandwithpicture.c #include #include "functions.h" #include "variables.h" extern void actor_postdrawMethod(ActorMarker *); extern void chBottlesBonus_func_802DD080(Gfx **, Mtx **); +extern void func_80311714(s32); #include "port/Patches/Patches.h" -Actor *chMumbosHandWithPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void chMumbosHandWithPicture_update(Actor *this); +Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); +void func_802DEE1C(Actor *this); /* .data */ -ActorAnimationInfo chMumbosHandWithPictureAnimations[] ={ +ActorAnimationInfo D_80368300[] ={ {0x000, 0.0f}, - {ASSET_2C7_ANIM_MUMBOS_HAND_WITH_PICTURE, 0.6f}, - {ASSET_2C6_ANIM_MUMBOS_HAND_WITH_PICTURE, 3.0f}, - {ASSET_2C8_ANIM_MUMBOS_HAND_WITH_PICTURE, 0.6f}, - {ASSET_2C8_ANIM_MUMBOS_HAND_WITH_PICTURE, 0.6f}, - {ASSET_2C6_ANIM_MUMBOS_HAND_WITH_PICTURE, 9e+09}, + {0x2C7, 0.6f}, + {0x2C6, 3.0f}, + {0x2C8, 0.6f}, + {0x2C8, 0.6f}, + {0x2C6, 9e+09}, }; f32 D_80368330[3] = {0.0f, 0.0f, 0.0f}; -ActorInfo chMumbosHandWithPicture = { - MARKER_294_MUMBOS_HAND_WITH_PICTURE, ACTOR_19B_MUMBOS_HAND_WITH_PICTURE, ASSET_56D_MUMBOS_HAND_WITH_PICTURE, - 0x1, chMumbosHandWithPictureAnimations, - chMumbosHandWithPicture_update, actor_update_func_80326224, chMumbosHandWithPicture_draw, +ActorInfo D_8036833C = { + 0x294, 0x19B, ASSET_56D_MUMBOS_HAND_WITH_PICTURE, + 0x1, D_80368300, + func_802DEE1C, actor_update_func_80326224, func_802DEC00, 0, 0, 0.0f, 0 }; @@ -36,7 +36,7 @@ BKModelBin *D_8037DFE8; f32 D_8037DFF0[3]; /* .code */ -Actor *chMumbosHandWithPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ Actor *this; f32 sp58[3]; f32 sp4C[3]; @@ -44,7 +44,7 @@ Actor *chMumbosHandWithPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, V this = marker_getActor(marker); - sp48 = picturebox_getColorBuffer(); + sp48 = func_8030C704(); if ((sp48 == 0) || (getGameMode() != GAME_MODE_A_SNS_PICTURE)) return this; @@ -62,13 +62,14 @@ Actor *chMumbosHandWithPicture_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, V D_8037DFF0[1] = 270.0f; D_8037DFF0[2] = 0.0f; // [port] Draw the background picture and Mumbo's hand without depth testing. - // On N64, depthbuffer_clear cleared the hardware depth buffer between the two draws + // On N64, func_80253190 cleared the hardware depth buffer between the two draws // via CPU-accessible memory. On PC, the GBI depth fill may not translate to a // GPU depth clear, causing the hand to fail depth tests against the 3D scene. modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE); modelRender_draw(gfx, mtx, sp58, NULL, 1.0f, sp4C, D_8037DFE8); gDPSetColorDither((*gfx)++, G_CD_DISABLE); - depthbuffer_clear(gfx); + func_80253190(gfx); + port_readAuxFbToCpu(gfx); gDPSetTextureFilter((*gfx)++, G_TF_BILERP); gSPSegment((*gfx)++, 0x04, osVirtualToPhysical(sp48)); modelRender_setPreDrawCallback((model_render_pre_draw_callback_f)actor_predrawMethod, (void *)this); @@ -94,11 +95,11 @@ void func_802DEDDC(Actor *this){ } -void chMumbosHandWithPicture_update(Actor *this) { - enum level_e level_id_1; - enum asset_e text_id; - enum level_e level_id_2; - f32 time; +void func_802DEE1C(Actor *this) { + s32 sp4C; + s32 sp48; + s32 sp44; + f32 sp38; if (!this->initialized) { this->initialized = true; @@ -106,33 +107,33 @@ void chMumbosHandWithPicture_update(Actor *this) { marker_setFreeMethod(this->marker, func_802DEDDC); actor_playAnimationOnce(this); if (D_8037DFE8 == NULL) { - D_8037DFE8 = assetcache_get(ASSET_56E_HAMMERHEAD_BEACH_SCENERY); + D_8037DFE8 = assetcache_get(0x56E); } - level_id_1 = map_getLevel(gsworld_getMap()); - level_id_2 = level_id_1 == D_8037DFE4; - if (level_id_2) { + sp4C = map_getLevel(gsworld_getMap()); + sp44 = sp4C == D_8037DFE4; + if (sp44) { subaddie_set_state_with_direction(this, 2, 0.0f, 1); actor_loopAnimation(this); } - switch(level_id_1){ + switch(sp4C){ case LEVEL_2_TREASURE_TROVE_COVE: - text_id = level_id_2 + 0xE39; // 0xE3B + sp48 = sp44 + 0xE39; break; case LEVEL_5_FREEZEEZY_PEAK: - text_id = level_id_2 + 0xE3B; // 0xE40 + sp48 = sp44 + 0xE3B; break; case LEVEL_7_GOBIS_VALLEY: default: - text_id = level_id_2 + 0xE3D; // 0xE44 + sp48 = sp44 + 0xE3D; break; } - time = (f32) ((f64) (level_id_2 + 1) * 0.75); - timedFunc_set_1(time, (GenFunction_1)func_80311714, 0); - func_80324DBC(time, text_id, 0x80, NULL, NULL, NULL, NULL); - timedFunc_set_1(time, (GenFunction_1)func_80311714, 1); - D_8037DFE4 = level_id_1; + sp38 = (f32) ((f64) (sp44 + 1) * 0.75); + timedFunc_set_1(sp38, (GenFunction_1)func_80311714, 0); + func_80324DBC(sp38, sp48, 0x80, NULL, NULL, NULL, NULL); + timedFunc_set_1(sp38, (GenFunction_1)func_80311714, 1); + D_8037DFE4 = sp4C; } switch(this->state){ case 1: diff --git a/src/core2/demo.c b/src/core2/demo_input.c similarity index 91% rename from src/core2/demo.c rename to src/core2/demo_input.c index c03c7dbd7..9b089624d 100644 --- a/src/core2/demo.c +++ b/src/core2/demo_input.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/demo.c #include #include "functions.h" #include "variables.h" @@ -42,11 +41,8 @@ s32 func_80349EC0(s32 arg0){ } int demo_readInput(OSContPad* arg0, s32* arg1){ - s32 idx = D_803860D8; - int not_eof = (idx + 1) < D_803860DC; - DemoInput *input_ptr = not_eof ? &D_803860D0[idx] : &D_80371EF0; - if (idx < D_803860DC) - D_803860D8 = idx + 1; + int not_eof = D_803860D8 < D_803860DC; + DemoInput *input_ptr = not_eof ? &D_803860D0[D_803860D8++] : &D_80371EF0; #if 0 DemoInput *input_ptr = &D_803860D0[D_803860D8++]; int not_eof = D_803860D8 < D_803860DC; diff --git a/src/core2/dialog/binload.c b/src/core2/dialog/binload.c index 192ee134b..b5919ff20 100644 --- a/src/core2/dialog/binload.c +++ b/src/core2/dialog/binload.c @@ -1,10 +1,10 @@ -// BanjoDecomp: core2/code_94620.c #include #include "functions.h" #include "variables.h" #include "structs.h" #include "port/Patches/Patches.h" -#include "port/ResourceHelpers.h" + +extern int ResourceMgr_GetDialogLanguageCount(void); /* .bss */ s32 D_80383150; @@ -19,7 +19,6 @@ s32 code94620_func_8031B5B0(void) { return s_dialogBin.unk0; } -// s32 func_8031B5BC(void){ return VER_SELECT(1, 3, 0, 0); } s32 func_8031B5BC(void){ return ResourceMgr_GetDialogLanguageCount(); } void func_8031B5C4(s32 arg0) { diff --git a/src/core2/dialog/progressDialog.c b/src/core2/dialog/progressDialog.c deleted file mode 100644 index e81c5cd4c..000000000 --- a/src/core2/dialog/progressDialog.c +++ /dev/null @@ -1,135 +0,0 @@ -// BanjoDecomp: core2/progressDialog.c -#include -#include "functions.h" -#include "variables.h" - -typedef KEY_VALUE_PAIR(s16, s16) MapProgressFlagToDialogID; - -/* Mapping for file progess flags to Dialog IDs */ -MapProgressFlagToDialogID fileProgressDialogMap[] = { - { FILEPROG_AB_SWIM_OILY_WATER, VER_SELECT(ASSET_BA1_DIALOG_GRUNTY_TOUCH_OILY_WATER, 0x976, 0, 0)}, - { FILEPROG_AC_DIVE_OILY_WATER, VER_SELECT(ASSET_BA2_DIALOG_GRUNTY_DIVE_OILY_WATER, 0x977, 0, 0)}, - { FILEPROG_AA_HAS_TOUCHED_CCW_BRAMBLE_FIELD, VER_SELECT(ASSET_CE6_DIALOG_GRUNTY_TOUCH_BRAMBLE, 0x9FB, 0, 0)}, - { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, VER_SELECT(ASSET_C85_DIALOG_PIRANHA_TOUCH_SWAMP_WATER, 0x9C8, 0, 0)}, - { FILEPROG_A9_HAS_TOUCHED_RBB_OVEN, VER_SELECT(ASSET_BA0_DIALOG_GRUNTY_TOUCH_OVEN, 0x975, 0, 0)}, - { FILEPROG_10_HAS_TOUCHED_SAND_EEL_SAND, VER_SELECT(ASSET_A7E_DIALOG_SAND_EELS_MEET, 0x93A, 0, 0)}, - { FILEPROG_14_HAS_TOUCHED_FP_ICY_WATER, VER_SELECT(ASSET_C11_DIALOG_TOUCH_ICY_WATER, 0x98B, 0, 0)}, - { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, VER_SELECT(ASSET_C85_DIALOG_PIRANHA_TOUCH_SWAMP_WATER, 0x9C8, 0, 0)}, - { FILEPROG_86_HAS_TOUCHED_MMM_THORN_HEDGE, VER_SELECT(ASSET_AE1_DIALOG_GRUNTY_HEDGE_THORNS, 0x953, 0, 0)}, - { FILEPROG_DD_HAS_TOUCHED_CCW_ICY_WATER, VER_SELECT(ASSET_CE7_DIALOG_GRUNTY_TOUCH_ICY_WATER, 0x9FC, 0, 0)}, - { FILEPROG_3_MUSIC_NOTE_TEXT, VER_SELECT(ASSET_D9C_DIALOG_MUSIC_NOTE_MEET, 0xA1A, 0, 0)}, - { FILEPROG_4_MUMBO_TOKEN_TEXT, VER_SELECT(ASSET_D9D_DIALOG_MUMBO_TOKEN_MEET, 0xA1B, 0, 0)}, - { FILEPROG_5_BLUE_EGG_TEXT, VER_SELECT(ASSET_D9E_DIALOG_BLUE_EGG_MEET, 0xA1C, 0, 0)}, - { FILEPROG_6_RED_FEATHER_TEXT, VER_SELECT(ASSET_D9F_DIALOG_RED_FEATHER_MEET, 0xA1D, 0, 0)}, - { FILEPROG_7_GOLD_FEATHER_TEXT, VER_SELECT(ASSET_DA0_DIALOG_GOLD_FEATHER_MEET, 0xA1E, 0, 0)}, - { FILEPROG_8_ORANGE_TEXT, VER_SELECT(ASSET_B46_DIALOG_CONGA_COLLECT_ORANGE, 0x964, 0, 0)}, - { FILEPROG_9_GOLD_BULLION_TEXT, VER_SELECT(ASSET_A21_DIALOG_BLUBBER_MEET, 0x921, 0, 0)}, - { FILEPROG_A_HONEYCOMB_TEXT, VER_SELECT(ASSET_DA1_DIALOG_HONEYCOMB_MEET, 0xA1F, 0, 0)}, - { FILEPROG_B_EMPTY_HONEYCOMB_TEXT, VER_SELECT(ASSET_DA2_DIALOG_EMPTY_HONEYCOMB_MEET, 0xA20, 0, 0)}, - { FILEPROG_C_EXTRA_LIFE_TEXT, VER_SELECT(ASSET_DA3_DIALOG_EXTRA_LIFE_MEET, 0xA21, 0, 0)}, - { FILEPROG_BE_CHEATO_BLUEEGGS, VER_SELECT(ASSET_FA8_EGG_CHEAT_ACTIVATION, 0xB0E, 0, 0)}, - { FILEPROG_BF_CHEATO_REDFEATHERS, VER_SELECT(ASSET_FA9_RED_FEATHER_CHEAT_ACTIVATION, 0xB0F, 0, 0)}, - { FILEPROG_C0_CHEATO_GOLDFEATHERS, VER_SELECT(ASSET_FAA_GOLD_FEATHER_CHEAT_ACTIVATION, 0xB10, 0, 0)}, - { FILEPROG_95_UNUSED_UNKNOWN_ITEM_COLLECT, VER_SELECT(ASSET_B50_DIALOG_BOTTLES_BACKPACK_STORE, 0x96E, 0, 0)}, - { FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT, VER_SELECT(ASSET_F7B_DIALOG_BOTTLES_JIGSAW_PICTURE_MEET, 0xAE1, 0, 0)}, - { -1, -1 } -}; - -/* This progress IDs are not saved in the save file, like when Banjo goes near a Note door which requires more notes than the Banjo has. */ -/* Triggers a dialog every time after the game restarts. */ -MapProgressFlagToDialogID gVolatileFlagDialogMap[] = { - { VOLATILE_FLAG_9E_BETA_OILY_SCUM, VER_SELECT(ASSET_BA3_DIALOG_GRUNTY_TOUCH_OILY_WATER_2, 0x978, 0, 0)}, // (unused) - { VOLATILE_FLAG_9F_BETA_DIVE_IN_ICY_WATER, VER_SELECT(ASSET_CE8_DIALOG_GRUNTY_TOUCH_ICY_WATER_2, 0x9FD, 0, 0)}, // (unused) - { VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT, VER_SELECT(ASSET_1032_DIALOG_FF_FIRST_ANSWER_CORRECT, 0xB3A, 0, 0)}, - { VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT, VER_SELECT(ASSET_1033_DIALOG_FF_NEXT_ANSWER_CORRECT, 0xB3B, 0, 0)}, - { VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT, VER_SELECT(ASSET_1034_DIALOG_FF_GRUNTY_ANSWER_CORRECT, 0xB3C, 0, 0)}, - { VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG, VER_SELECT(ASSET_1035_DIALOG_FF_FIRST_ANSWER_WRONG, 0xB3D, 0, 0)}, - { VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG, VER_SELECT(ASSET_1036_DIALOG_FF_NEXT_ANSWER_WRONG, 0xB3E, 0, 0)}, - { VOLATILE_FLAG_A5_FF_UNUSED, VER_SELECT(ASSET_1037_DIALOG_FF_CHOICE_IS_YOURS_UNUSED, 0xB3F, 0, 0)}, - { VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB, VER_SELECT(ASSET_1038_DIALOG_FF_GET_HONEYCOMB, 0xB40, 0, 0)}, - { VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE, VER_SELECT(ASSET_1039_DIALOG_FF_GET_EXTRA_LIFE, 0xB41, 0, 0)}, - { VOLATILE_FLAG_A8_FF_GOT_JOKER, VER_SELECT(ASSET_103A_DIALOG_FF_GET_JOKER, 0xB42, 0, 0)}, - { VOLATILE_FLAG_A9_FF_USED_JOKER, VER_SELECT(ASSET_103B_DIALOG_FF_USE_JOKER, 0xB43, 0, 0)}, - { VOLATILE_FLAG_AA_FF_LOW_HEALTH, VER_SELECT(ASSET_103C_DIALOG_FF_LOW_HEALTH, 0xB44, 0, 0)}, - { VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL, VER_SELECT(ASSET_103D_DIALOG_FF_LOW_HEALTH_ON_SKULL, 0xB45, 0, 0)}, - { VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED, VER_SELECT(ASSET_A88_DIALOG_GRUNTY_WATER_PYRAMID_DOOR_MISS, 0x944, 0, 0)}, - { VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED, VER_SELECT(ASSET_AE2_DIALOG_GRUNTY_CHURCH_DOOR_MISS, 0x954, 0, 0)}, - { VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED, VER_SELECT(ASSET_C8B_DIALOG_GRUNTY_LONG_SWITCH_MISS, 0x9CE, 0, 0)}, - { VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED, VER_SELECT(ASSET_C8C_DIALOG_GRUNTY_SHORT_SWITCH_MISS, 0x9CF, 0, 0)}, - { VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES, VER_SELECT(ASSET_FBD_DIALOG_GRUNTY_NOT_ENOUGH_NOTES, 0xB23, 0, 0)}, - { VOLATILE_FLAG_C2_NOBONUS_TEXT, VER_SELECT(ASSET_E36_DIALOG_BOTTLES_NO_BONUS, 0xA78, 0, 0)}, - { VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT, VER_SELECT(ASSET_DB6_DIALOG_MUMBO_WISHYWASHY, 0xA34, 0, 0)}, - { -1, -1 } -}; - -static s32 __findIndex(MapProgressFlagToDialogID *map, s32 key) { - s32 i = 0; - - while (map[i].key >= 0) { - if (key == map[i].key) { - return i; - } - i++; - } - - return -1; -} - -/* Checks for a specific file progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ -s32 showProgressFlagDialog(enum file_progress_e progress_flag, s32 arg1) { - s32 index; - - if (fileProgressFlag_get(progress_flag) != 0) { - return 0; - } else { - index = __findIndex(fileProgressDialogMap, progress_flag); - if (index != -1) { - if (gcdialog_showDialog(fileProgressDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { - fileProgressFlag_set(progress_flag, 1); - } - return fileProgressFlag_get(progress_flag); - } - return 0; - } -} - -void progressDialog_showDialogMaskZero(enum file_progress_e progress_flag){ - showProgressFlagDialog(progress_flag, 0); -} - -void progressDialog_showDialogMaskFour(enum file_progress_e progress_flag) { - showProgressFlagDialog(progress_flag, 4); -} - -/* Checks for a specific "volatile" progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ -s32 progressDialog_setAndTriggerDialog(enum volatile_flags_e id, s32 arg1) { - s32 index; - - if (volatileFlag_get(id) != 0) { - return 0; - } else { - index = __findIndex(gVolatileFlagDialogMap, id); - if (index != -1) { - if (gcdialog_showDialog(gVolatileFlagDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { - volatileFlag_set(id, 1); - } - return volatileFlag_get(id); - } - return 0; - } -} - -// called for dialogs when banjo is not fast enough to reach a door or jiggy and for NOBONUS text -void progressDialog_setAndTriggerDialog_0(enum volatile_flags_e arg0) { - progressDialog_setAndTriggerDialog(arg0, 0); -} - -// called for FFQ dialogs -void progressDialog_setAndTriggerDialog_4(enum volatile_flags_e arg0) { - progressDialog_setAndTriggerDialog(arg0, 4); -} - -// called for WISHYWASHYBANJO dialog, mumbo jumbo speaking? -void progressDialog_setAndTriggerDialog_E(enum volatile_flags_e arg0) { - progressDialog_setAndTriggerDialog(arg0, 0xE); -} diff --git a/src/core2/dialog/progress_dialogs.c b/src/core2/dialog/progress_dialogs.c new file mode 100644 index 000000000..07089daf3 --- /dev/null +++ b/src/core2/dialog/progress_dialogs.c @@ -0,0 +1,134 @@ +#include +#include "functions.h" +#include "variables.h" + +typedef KEY_VALUE_PAIR(s16, s16) MapProgressFlagToDialogID; + +/* Mapping for file progess flags to Dialog IDs */ +MapProgressFlagToDialogID fileProgressDialogMap[] = { + { FILEPROG_AB_SWIM_OILY_WATER, 0xBA1}, + { FILEPROG_AC_DIVE_OILY_WATER, 0xBA2}, + { FILEPROG_AA_HAS_TOUCHED_CCW_BRAMBLE_FIELD, 0xCE6}, + { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, 0xC85}, + { FILEPROG_A9_HAS_TOUCHED_RBB_OVEN, 0xBA0}, + { FILEPROG_10_HAS_TOUCHED_SAND_EEL_SAND, 0xA7E}, + { FILEPROG_14_HAS_TOUCHED_FP_ICY_WATER, 0xC11}, + { FILEPROG_F_HAS_TOUCHED_PIRANHA_WATER, 0xC85}, + { FILEPROG_86_HAS_TOUCHED_MMM_THORN_HEDGE, 0xAE1}, + { FILEPROG_DD_HAS_TOUCHED_CCW_ICY_WATER, 0xCE7}, + { FILEPROG_3_MUSIC_NOTE_TEXT, 0xD9C}, + { FILEPROG_4_MUMBO_TOKEN_TEXT, 0xD9D}, + { FILEPROG_5_BLUE_EGG_TEXT, 0xD9E}, + { FILEPROG_6_RED_FEATHER_TEXT, 0xD9F}, + { FILEPROG_7_GOLD_FEATHER_TEXT, 0xDA0}, + { FILEPROG_8_ORANGE_TEXT, 0xB46}, + { FILEPROG_9_GOLD_BULLION_TEXT, 0xA21}, + { FILEPROG_A_HONEYCOMB_TEXT, 0xDA1}, + { FILEPROG_B_EMPTY_HONEYCOMB_TEXT, 0xDA2}, + { FILEPROG_C_EXTRA_LIFE_TEXT, 0xDA3}, + { FILEPROG_BE_CHEATO_BLUEEGGS, 0xFA8}, + { FILEPROG_BF_CHEATO_REDFEATHERS, 0xFA9}, + { FILEPROG_C0_CHEATO_GOLDFEATHERS, 0xFAA}, + { FILEPROG_95_UNUSED_UNKNOWN_ITEM_COLLECT, 0xB50}, + { FILEPROG_A7_NEAR_PUZZLE_PODIUM_TEXT, 0xF7B}, + { -1, -1} +}; + +/* This progress IDs are not saved in the save file, like when Banjo goes near a Note door which requires more notes than the Banjo has. */ +/* Triggers a dialog every time after the game restarts. */ +MapProgressFlagToDialogID gVolatileFlagDialogMap[] = { + {VOLATILE_FLAG_9E_BETA_OILY_SCUM, 0xBA3}, // Oily scum (unused) + {VOLATILE_FLAG_9F_BETA_DIVE_IN_ICY_WATER, 0xCE8}, // Dive in icy water (unused) + {VOLATILE_FLAG_A0_FF_FIRST_ANSWER_RIGHT, 0x1032}, + {VOLATILE_FLAG_A1_FF_NEXT_ANSWER_RIGHT, 0x1033}, + {VOLATILE_FLAG_A2_FF_GRUNTY_ANSWER_RIGHT, 0x1034}, + {VOLATILE_FLAG_A3_FF_FIRST_ANSWER_WRONG, 0x1035}, + {VOLATILE_FLAG_A4_FF_NEXT_ANSWER_WRONG, 0x1036}, + {VOLATILE_FLAG_A5_FF_UNUSED, 0x1037}, // FF "the choice is yours" + {VOLATILE_FLAG_A6_FF_FOUND_HONEYCOMB, 0x1038}, + {VOLATILE_FLAG_A7_FF_FOUND_EXTRALIFE, 0x1039}, + {VOLATILE_FLAG_A8_FF_GOT_JOKER, 0x103A}, + {VOLATILE_FLAG_A9_FF_USED_JOKER, 0x103B}, + {VOLATILE_FLAG_AA_FF_LOW_HEALTH, 0x103C}, + {VOLATILE_FLAG_AB_LAST_LIFE_ON_SKULL, 0x103D}, + {VOLATILE_FLAG_AC_GV_TRAPDOOR_MISSED, 0xA88}, + {VOLATILE_FLAG_AD_MMM_CHURCH_DOOR_MISSED, 0xAE2}, + {VOLATILE_FLAG_AE_BGS_WALKWAY_JIGGY_MISSED, 0xC8B}, + {VOLATILE_FLAG_AF_BGS_MAZE_JIGGY_MISSED, 0xC8C}, + {VOLATILE_FLAG_B0_NOT_ENOUGH_NOTES, 0xFBD}, + {VOLATILE_FLAG_C2_NOBONUS_TEXT, 0xE36}, + {VOLATILE_FLAG_C5_WISHYWASHYBANJO_TEXT, 0xDB6}, + { -1, -1} +}; + +static s32 __findIndex(MapProgressFlagToDialogID *map, s32 key) { + s32 i = 0; + + while (map[i].key >= 0) { + if (key == map[i].key) { + return i; + } + i++; + } + + return -1; +} + +/* Checks for a specific file progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ +s32 showProgressFlagDialog(enum file_progress_e progress_flag, s32 arg1) { + s32 index; + + if (fileProgressFlag_get(progress_flag) != 0) { + return 0; + } else { + index = __findIndex(fileProgressDialogMap, progress_flag); + if (index != -1) { + if (gcdialog_showDialog(fileProgressDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { + fileProgressFlag_set(progress_flag, 1); + } + return fileProgressFlag_get(progress_flag); + } + return 0; + } +} + +void progressDialog_showDialogMaskZero(enum file_progress_e progress_flag){ + showProgressFlagDialog(progress_flag, 0); +} + +void progressDialog_showDialogMaskFour(enum file_progress_e progress_flag) { + showProgressFlagDialog(progress_flag, 4); +} + +/* Checks for a specific "volatile" progress flag and triggers a dialog only if the progress flag was not set and sets the progress flag */ +s32 volatileFlag_setAndTriggerDialog(enum volatile_flags_e id, s32 arg1) { + s32 index; + + if (volatileFlag_get(id) != 0) { + return 0; + } else { + index = __findIndex(gVolatileFlagDialogMap, id); + if (index != -1) { + if (gcdialog_showDialog(gVolatileFlagDialogMap[index].value, arg1, 0, 0, 0, 0) != 0) { + volatileFlag_set(id, 1); + } + return volatileFlag_get(id); + } + return 0; + } +} + +// called for dialogs when banjo is not fast enough to reach a door or jiggy and for NOBONUS text +void volatileFlag_setAndTriggerDialog_0(enum volatile_flags_e arg0) { + volatileFlag_setAndTriggerDialog(arg0, 0); +} + +// called for FFQ dialogs +void volatileFlag_setAndTriggerDialog_4(enum volatile_flags_e arg0) { + volatileFlag_setAndTriggerDialog(arg0, 4); +} + +// called for WISHYWASHYBANJO dialog, mumbo jumbo speaking? +void volatileFlag_setAndTriggerDialog_E(enum volatile_flags_e arg0) { + volatileFlag_setAndTriggerDialog(arg0, 0xE); +} diff --git a/src/core2/displaylist_init.c b/src/core2/displaylist_init.c index 8ada226cd..7ecdb6c46 100644 --- a/src/core2/displaylist_init.c +++ b/src/core2/displaylist_init.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_8DC20.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -42,7 +41,7 @@ s32 D_803830A0; void func_80314BB0(Gfx **gfx, Mtx **mtx, Vtx **vtx, void * frame_buffer_1, void *frame_buffer_2) { // [port] GPU-side pause snapshot s32 pauseFb = port_getPauseFramebufferId(); - bool isCapture = (frame_buffer_1 == depthbuffer_getDataPtr()); + bool isCapture = (frame_buffer_1 == zBuffer_get()); gSPDisplayList((*gfx)++, D_8036C630); @@ -80,7 +79,7 @@ void func_80314BB0(Gfx **gfx, Mtx **mtx, Vtx **vtx, void * frame_buffer_1, void void func_80315084(Gfx **gfx, Mtx **mtx, Vtx **vtx){ gsworld_setEnableDraw(0); D_803830A0 = 2; - func_80314BB0(gfx, mtx, vtx, depthbuffer_getDataPtr(), gFramebuffers[getActiveFramebuffer()]); + func_80314BB0(gfx, mtx, vtx, zBuffer_get(), gFramebuffers[getActiveFramebuffer()]); port_mirror_markCapture(); } @@ -94,7 +93,7 @@ void func_80315110(Gfx **gfx, Mtx **mtx, Vtx **vtx){ else{ D_803830A0--; } - func_80314BB0(gfx, mtx, vtx, gFramebuffers[getActiveFramebuffer()], depthbuffer_getDataPtr()); + func_80314BB0(gfx, mtx, vtx, gFramebuffers[getActiveFramebuffer()], zBuffer_get()); } void func_803151D0(Gfx **gfx, Mtx **mtx, Vtx **vtx){ diff --git a/src/core2/fileselect.c b/src/core2/fileselect.c index bd5b6f451..5f7b9e42a 100644 --- a/src/core2/fileselect.c +++ b/src/core2/fileselect.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B5E00.c #include #include "functions.h" #include "variables.h" @@ -117,7 +116,6 @@ return 0; void gameFile_clear(s32 gamenum){ s32 filenum = gameFile_GameIdToFileIdMap[gamenum]; savedata_clear(&gameFile_saveData[filenum]); - CALL_EVENT(OnGameErase, gamenum); } void gameFile_load(s32 gamenum){ diff --git a/src/core2/flags_bitfield.c b/src/core2/flags_bitfield.c index 055ddee55..7e215e899 100644 --- a/src/core2/flags_bitfield.c +++ b/src/core2/flags_bitfield.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_98CB0.c #include #include "functions.h" #include "variables.h" @@ -6,10 +5,10 @@ void func_8031FFAC(void); void fileProgressFlag_set(enum file_progress_e index, s32 set); -s32 bitfieldarray_getBit(u8 *array, s32 index); -s32 bitfieldarray_getNBits(u8 *array, s32 offset, s32 numBits); -void bitfieldarray_setBit(u8 *array, s32 index, s32 set); -void bitfieldarray_setNBits(u8 *array, s32 startIndex, s32 set, s32 length); +s32 bitfield_get_bit(u8 *array, s32 index); +s32 bitfield_get_n_bits(u8 *array, s32 offset, s32 numBits); +void bitfield_set_bit(u8 *array, s32 index, s32 set); +void bitfield_set_n_bits(u8 *array, s32 startIndex, s32 set, s32 length); void volatileFlag_clear(void); void volatileFlag_set(enum volatile_flags_e index, s32 set); s32 fileProgressFlag_getN(enum file_progress_e offset, s32 numBits); @@ -118,11 +117,11 @@ void func_8031FEC0(void) { } bool fileProgressFlag_get(enum file_progress_e index) { - return bitfieldarray_getBit(gFileProgressFlags.unk8, index); + return bitfield_get_bit(gFileProgressFlags.unk8, index); } s32 fileProgressFlag_getN(enum file_progress_e offset, s32 numBits) { - return bitfieldarray_getNBits(gFileProgressFlags.unk8, offset, numBits); + return bitfield_get_n_bits(gFileProgressFlags.unk8, offset, numBits); } s32 fileProgressFlag_getAndSet(enum file_progress_e index, s32 set) { @@ -143,25 +142,16 @@ void func_8031FFAC(void) { func_8031FEC0(); } -void fileProgressFlag_setEx(enum file_progress_e index, s32 set, s32 triggerEvent) { - s32 changed = bitfieldarray_getBit(gFileProgressFlags.unk8, index) != (set ? 1 : 0); - bitfieldarray_setBit(gFileProgressFlags.unk8, index, set); +void fileProgressFlag_set(enum file_progress_e index, s32 set) { + bitfield_set_bit(gFileProgressFlags.unk8, index, set); func_8031FC40(); func_8031FEC0(); - if (triggerEvent && changed) { - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_FILE_PROGRESS, index, set ? 1 : 0, 1); - } -} - -void fileProgressFlag_set(enum file_progress_e index, s32 set) { - fileProgressFlag_setEx(index, set, 1); } void fileProgressFlag_setN(enum file_progress_e startIndex, s32 set, s32 length) { - bitfieldarray_setNBits(gFileProgressFlags.unk8, startIndex, set, length); + bitfield_set_n_bits(gFileProgressFlags.unk8, startIndex, set, length); func_8031FC40(); func_8031FEC0(); - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_FILE_PROGRESS, startIndex, set, length); } void fileProgressFlag_getSizeAndPtr(s32 *size, u8 **addr) { @@ -170,7 +160,7 @@ void fileProgressFlag_getSizeAndPtr(s32 *size, u8 **addr) { } // Returns a single bit from a byte array -s32 bitfieldarray_getBit(u8 *array, s32 index) { +s32 bitfield_get_bit(u8 *array, s32 index) { s32 ret; if (array[index / 8] & (1 << (index & 7))) { ret = 1; @@ -181,18 +171,18 @@ s32 bitfieldarray_getBit(u8 *array, s32 index) { } // Extracts an integer of the given number of bits from a byte array at the starting bit offset -s32 bitfieldarray_getNBits(u8 *array, s32 offset, s32 numBits) { +s32 bitfield_get_n_bits(u8 *array, s32 offset, s32 numBits) { s32 ret = 0; s32 i; for (i = 0; i < numBits; i++) { - ret |= (bitfieldarray_getBit(array, offset + i) << i); + ret |= (bitfield_get_bit(array, offset + i) << i); } return ret; } // Sets or clears a single bit in a byte array -void bitfieldarray_setBit(u8 *array, s32 index, s32 set) { +void bitfield_set_bit(u8 *array, s32 index, s32 set) { if (set) { array[index / 8] |= (1 << (index & 7)); } else { @@ -201,11 +191,11 @@ void bitfieldarray_setBit(u8 *array, s32 index, s32 set) { } // Sets or clears a range of bits in a byte array -void bitfieldarray_setNBits(u8 *array, s32 startIndex, s32 set, s32 length) { +void bitfield_set_n_bits(u8 *array, s32 startIndex, s32 set, s32 length) { s32 i; for (i = 0; i < length; i++) { - bitfieldarray_setBit(array, startIndex + i, (1 << i) & set); + bitfield_set_bit(array, startIndex + i, (1 << i) & set); } } @@ -283,11 +273,11 @@ void func_803203A0(void) { } s32 volatileFlag_get(enum volatile_flags_e index) { - return bitfieldarray_getBit(gVolatileFlags.unk8, index); + return bitfield_get_bit(gVolatileFlags.unk8, index); } s32 volatileFlag_getN(enum volatile_flags_e index, s32 numBits) { - return bitfieldarray_getNBits(gVolatileFlags.unk8, index, numBits); + return bitfield_get_n_bits(gVolatileFlags.unk8, index, numBits); } s32 volatileFlag_getAndSet(enum volatile_flags_e index, s32 arg1) { @@ -307,30 +297,16 @@ void volatileFlag_clear(void) { func_803203A0(); } -void volatileFlag_setEx(enum volatile_flags_e index, s32 set, s32 triggerEvent) { - s32 changed = bitfieldarray_getBit(gVolatileFlags.unk8, index) != (set ? 1 : 0); - bitfieldarray_setBit(gVolatileFlags.unk8, index, set); +void volatileFlag_set(enum volatile_flags_e index, s32 set) { + bitfield_set_bit(gVolatileFlags.unk8, index, set); func_803202D0(); func_803203A0(); - if (triggerEvent && changed) { - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_VOLATILE, index, set ? 1 : 0, 1); - } -} - -void volatileFlag_set(enum volatile_flags_e index, s32 set) { - volatileFlag_setEx(index, set, 1); } void volatileFlag_setN(enum volatile_flags_e startIndex, s32 set, s32 length) { - bitfieldarray_setNBits(gVolatileFlags.unk8, startIndex, set, length); + bitfield_set_n_bits(gVolatileFlags.unk8, startIndex, set, length); func_803202D0(); func_803203A0(); - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_VOLATILE, startIndex, set, length); -} - -void volatileFlag_getSizeAndPtr(s32 *size, u8 **addr) { - *size = 0x19; - *addr = gVolatileFlags.unk8; } s32 func_8032056C(void) { diff --git a/src/core2/font/print.c b/src/core2/font/print.c index 61bf3ce4f..f551887a9 100644 --- a/src/core2/font/print.c +++ b/src/core2/font/print.c @@ -1,15 +1,19 @@ -// BanjoDecomp: core2/print.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" -#include "port/ResourceHelpers.h" -#include "port/Interpolation/FrameInterpolation.h" - +extern int ResourceMgr_GetDialogLanguageCount(void); +extern int ResourceMgr_IsJapanese(void); +// [port] PAL font has 75 glyphs (0x21-0x6B), overlapping NTSC control codes b,d,e,f,h,j. +// When PAL, fmtStrings use shifted codes above the glyph range. +#define PRINT_PAL (ResourceMgr_GetDialogLanguageCount() > 1) +// [port] JP uses font index 2 (sprite 1770, 256 I4 glyphs) for dialog text. +// Dialog strings begin with "\xFD\x6A" (escape + 'j') which switches to font index 2. #define PRINT_JP (ResourceMgr_IsJapanese()) + + typedef struct{ s8 pad0[0x20]; } struct23s; @@ -33,17 +37,17 @@ typedef struct font_letter{ typedef struct map_font_texture_map{ s16 mapID; s16 assetId; -} MapToBoldFontTextureMap; +} MapFontTextureMap; typedef struct{ u8 firstLetter; u8 secondLetter; s8 xOffset; s8 yOffset; -}BoldFontKerningData; +}Struct_6DA30_0_s; /* .data */ -extern BoldFontKerningData boldFontKernings[] = { +extern Struct_6DA30_0_s boldFontKernings[] = { {'A', 'V', -3, 0}, {'W', 'A', -3, 0}, {'V', 'A', -3, 0}, @@ -72,16 +76,16 @@ extern BoldFontKerningData boldFontKernings[] = { 0 }; -s32 maxFontLetterWidths[] = {8, 16, 16, 0}; //max letter width +s32 D_80369068[] = {8, 16, 16, 0}; //max letter width struct { - u8 r; - u8 g; - u8 b; - u8 a; + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; } normalTextColor = {0xFF, 0xFF, 0xFF, 0XFF}; -MapToBoldFontTextureMap mapToBoldFontTextureMap[] ={ +MapFontTextureMap mapToBoldFontTextureMap[] ={ {MAP_1_SM_SPIRAL_MOUNTAIN, SPRITE_BOLD_FONT_BLUE_SPHERE_TEXTURE}, {MAP_2_MM_MUMBOS_MOUNTAIN, 0x6EF}, {0x3, 0x6EE}, @@ -202,28 +206,28 @@ Gfx D_80369238[] = { }; /* .bss */ -char print_sPreviousBoldLetter; -BKSprite *print_sFontSpriteAssets[0x5]; +char D_80380AB0; +BKSprite *D_80380AB8[0x5]; FontLetter *print_sFonts[4]; PrintBuffer *print_sPrintBuffer; PrintBuffer *print_sCurrentPtr; -s32 print_sCurrentFont; -s32 print_sPreviousFont; -s32 print_sMonospacedModeEnabled; //print_sMonospaced -s32 print_sGradientModeEnabled; -s32 print_sGradient2ModeEnabled; -s32 print_sBrokenFontModeEnabled; -s32 print_sBackgroundModeEnabled; -s32 print_sUnknownMode; +s32 D_80380AE8; +s32 D_80380AEC; +s32 D_80380AF0; //print_sMonospaced +s32 D_80380AF4; +s32 D_80380AF8; +s32 D_80380AFC; +s32 D_80380B00; +s32 D_80380B04; bool print_sInFontFormatMode; s32 D_80380B0C; -s32 print_sShakyModeEnabled; -s32 print_sBilinearFilterModeEnabled; -s32 print_sBoldLetterFontFreeTimer; -s32 print_sCurrentBoldFontTexture; +s32 D_80380B10; +s32 D_80380B14; +s32 D_80380B18; +s32 D_80380B1C; s8 D_80380B20[0x400]; -s8 print_sBoldFontLetterToSpriteMap[0x80]; +s8 D_80380F20[0x80]; s32 print_sDialogFontGlyphCount; // [port] actual glyph count from loaded font sprite @@ -304,7 +308,7 @@ void print_applyTextureToBoldFontLetter(BKSpriteTextureBlock *alphaMask, BKSprit FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprite){ BKSpriteFrame * font = sprite_getFramePtr(alphaMask, 0); BKSpriteTextureBlock *chunkPtr; - FontLetter * letters = bk_malloc((font->chunkCnt + 1)*sizeof(FontLetter)); + FontLetter * sp2C = bk_malloc((font->chunkCnt + 1)*sizeof(FontLetter)); u8* palDataPtr; u8* chunkDataPtr; s32 chunkSize; @@ -328,8 +332,8 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit while((uintptr_t)chunkDataPtr % 8) chunkDataPtr++; - letters[i].sprite = chunkPtr; - letters[i].palette = palDataPtr; + sp2C[i].sprite = chunkPtr; + sp2C[i].palette = palDataPtr; chunkSize = chunkPtr->w*chunkPtr->h; chunkPtr = (BKSpriteTextureBlock *)(chunkDataPtr + chunkSize); } @@ -349,7 +353,7 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit BKSpriteTextureBlock *copy = bk_malloc(copySize); memcpy(copy, chunkPtr, copySize); print_applyTextureToBoldFontLetter(copy, (BKSpriteTextureBlock *)(sprite_getFramePtr(textureSprite, 0) + 1)); - letters[i].sprite = copy; + sp2C[i].sprite = copy; CALL_EVENT(OnBoldFontLetterBuilt, copy, chunkPtr, (BKSpriteTextureBlock *)(sprite_getFramePtr(textureSprite, 0) + 1)); } @@ -364,7 +368,7 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit { chunkPtr = (BKSpriteTextureBlock *) (font + 1); for( i = 0; i < font->chunkCnt; i++){ - letters[i].sprite = chunkPtr; + sp2C[i].sprite = chunkPtr; chunkDataPtr = (u8*)(chunkPtr + 1); chunkSize = chunkPtr->w*chunkPtr->h; while((uintptr_t)chunkDataPtr % 8) @@ -378,7 +382,7 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit chunkPtr = (BKSpriteTextureBlock *)(font + 1); for( i = 0; i < font->chunkCnt; i++){ chunkDataPtr = (u8*)(chunkPtr + 1); - letters[i].sprite = chunkPtr; + sp2C[i].sprite = chunkPtr; chunkSize = chunkPtr->w*chunkPtr->h; while((uintptr_t)chunkDataPtr % 8) chunkDataPtr++; @@ -387,14 +391,14 @@ FontLetter *print_getLettersFromFont(BKSprite *alphaMask, BKSprite *textureSprit } break; }; - return letters; + return sp2C; } void print_free(void){ s32 i; for(i = 0; i< 5; i++){ - assetcache_release(print_sFontSpriteAssets[i]); - print_sFontSpriteAssets[i] = NULL; + assetcache_release(D_80380AB8[i]); + D_80380AB8[i] = NULL; if(i < 4){ bk_free(print_sFonts[i]); print_sFonts[i] = NULL; @@ -416,33 +420,33 @@ void print_setBoldFontTexture(s32 textureId){ CALL_EVENT(OnBoldFontReset); // [port] func_802546E4 reads bk_malloc HeapHeader, but assets now come from resource manager. // code_B3A80_func_8033BDAC is stubbed (returns 0), so always falls through to assetcache_get. - // tmp_a2 = func_802546E4(print_sFontSpriteAssets[1]); + // tmp_a2 = func_802546E4(D_80380AB8[1]); // if(tmp_a2 & 0xF) // tmp_a2 += 0x10 - (tmp_a2 & 0xF); - // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK, print_sFontSpriteAssets[1],tmp_a2)){ - assetcache_release(print_sFontSpriteAssets[1]); - print_sFontSpriteAssets[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); + // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK, D_80380AB8[1],tmp_a2)){ + assetcache_release(D_80380AB8[1]); + D_80380AB8[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); // } - if(print_sFontSpriteAssets[3]){ + if(D_80380AB8[3]){ // [port] Same as above — func_802546E4 unsafe on resource-manager pointers - // tmp_a2 = func_802546E4(print_sFontSpriteAssets[3]); + // tmp_a2 = func_802546E4(D_80380AB8[3]); // if(tmp_a2 & 0xF) // tmp_a2 += 0x10 - (tmp_a2 & 0xF); - // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK, print_sFontSpriteAssets[3],tmp_a2)){ - assetcache_release(print_sFontSpriteAssets[3]); - print_sFontSpriteAssets[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); + // if(!code_B3A80_func_8033BDAC(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK, D_80380AB8[3],tmp_a2)){ + assetcache_release(D_80380AB8[3]); + D_80380AB8[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); // } }//L802F510C - print_sFontSpriteAssets[4] = assetcache_get(textureId); + D_80380AB8[4] = assetcache_get(textureId); bk_free(print_sFonts[1]); - print_sFonts[1] = print_getLettersFromFont(print_sFontSpriteAssets[1], print_sFontSpriteAssets[4]); - if(print_sFontSpriteAssets[3]){ + print_sFonts[1] = print_getLettersFromFont(D_80380AB8[1], D_80380AB8[4]); + if(D_80380AB8[3]){ bk_free(print_sFonts[3]); - print_sFonts[3] = print_getLettersFromFont(print_sFontSpriteAssets[3], print_sFontSpriteAssets[4]); + print_sFonts[3] = print_getLettersFromFont(D_80380AB8[3], D_80380AB8[4]); } - assetcache_release(print_sFontSpriteAssets[4]); - print_sFontSpriteAssets[4] = NULL; - print_sCurrentBoldFontTexture = textureId; + assetcache_release(D_80380AB8[4]); + D_80380AB8[4] = NULL; + D_80380B1C = textureId; } void print_resetBoldFontTexture(void){ @@ -456,30 +460,29 @@ void print_init(void){ int found; length = strlen(boldFontLetters); - print_sCurrentFont = \ - print_sPreviousFont = \ - print_sMonospacedModeEnabled = \ - print_sGradientModeEnabled = \ - print_sGradient2ModeEnabled = \ - print_sBrokenFontModeEnabled = \ + D_80380AE8 = \ + D_80380AEC = \ + D_80380AF0 = \ + D_80380AF4 = \ + D_80380AF8 = \ + D_80380AFC = \ print_sInFontFormatMode = \ - print_sUnknownMode = \ - print_sBackgroundModeEnabled = \ - print_sShakyModeEnabled = \ - print_sBilinearFilterModeEnabled = 0; - print_sPreviousBoldLetter = 0; + D_80380B04 = \ + D_80380B00 = \ + D_80380B10 = \ + D_80380B14 = 0; + D_80380AB0 = 0; func_802F7A2C(3); - print_sFontSpriteAssets[0] = assetcache_get(SPRITE_DIALOG_FONT_ALPHAMASK); - print_sFontSpriteAssets[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); - print_sFontSpriteAssets[4] = assetcache_get(print_getCurrentMapBoldFontTexture()); - print_sFonts[0] = print_getLettersFromFont(print_sFontSpriteAssets[0], print_sFontSpriteAssets[4]); - print_sDialogFontGlyphCount = sprite_getFramePtr(print_sFontSpriteAssets[0], 0)->chunkCnt; - port_dialogFontHd_rebuild(); - print_sFonts[1] = print_getLettersFromFont(print_sFontSpriteAssets[1], print_sFontSpriteAssets[4]); + D_80380AB8[0] = assetcache_get(SPRITE_DIALOG_FONT_ALPHAMASK); + D_80380AB8[1] = assetcache_get(SPRITE_BOLD_FONT_NUMBERS_ALPHAMASK); + D_80380AB8[4] = assetcache_get(print_getCurrentMapBoldFontTexture()); + print_sFonts[0] = print_getLettersFromFont(D_80380AB8[0], D_80380AB8[4]); + print_sDialogFontGlyphCount = sprite_getFramePtr(D_80380AB8[0], 0)->chunkCnt; + print_sFonts[1] = print_getLettersFromFont(D_80380AB8[1], D_80380AB8[4]); if (PRINT_JP) { // [port] JP font index 2 = the Japanese dialog font (sprite 1770, 256 I4 glyphs). - print_sFontSpriteAssets[2] = assetcache_get(SPRITE_JP_DIALOG_FONT_ALPHAMASK); - print_sFonts[2] = print_getLettersFromFont(print_sFontSpriteAssets[2], print_sFontSpriteAssets[4]); + D_80380AB8[2] = assetcache_get(SPRITE_JP_DIALOG_FONT_ALPHAMASK); + print_sFonts[2] = print_getLettersFromFont(D_80380AB8[2], D_80380AB8[4]); } print_sPrintBuffer = bk_malloc(0x20*sizeof(PrintBuffer)); print_clearPrintBufferStrings(); @@ -488,37 +491,37 @@ void print_init(void){ found = 0; for(j = 0; j < length && !found; j++){//L802F5304 if(boldFontLetters[j] == i){ - print_sBoldFontLetterToSpriteMap[i] = j; + D_80380F20[i] = j; found = 1; }//L802F531C }//L802F5330 if(!found) - print_sBoldFontLetterToSpriteMap[i] = -1; + D_80380F20[i] = -1; } - assetcache_release(print_sFontSpriteAssets[4]); - print_sFontSpriteAssets[4] = NULL; - print_sCurrentBoldFontTexture = print_getCurrentMapBoldFontTexture(); + assetcache_release(D_80380AB8[4]); + D_80380AB8[4] = NULL; + D_80380B1C = print_getCurrentMapBoldFontTexture(); } void print_updateBoldLetterFontDelayedFreeing(void){ - if(print_sBoldLetterFontFreeTimer > 0 && --print_sBoldLetterFontFreeTimer == 0){ - assetcache_release(print_sFontSpriteAssets[3]); - print_sFontSpriteAssets[3] = 0; + if(D_80380B18 > 0 && --D_80380B18 == 0){ + assetcache_release(D_80380AB8[3]); + D_80380AB8[3] = 0; bk_free(print_sFonts[3]); print_sFonts[3] = NULL; } } void print_freeBoldLetterFont(void){ - if(print_sFontSpriteAssets[3]){ - assetcache_release(print_sFontSpriteAssets[3]); - print_sFontSpriteAssets[3] = NULL; + if(D_80380AB8[3]){ + assetcache_release(D_80380AB8[3]); + D_80380AB8[3] = NULL; } if(print_sFonts[3]){ bk_free(print_sFonts[3]); print_sFonts[3] = NULL; } - print_sBoldLetterFontFreeTimer = 0; + D_80380B18 = 0; } void printbuffer_defrag(void){ @@ -532,103 +535,103 @@ void printbuffer_defrag(void){ //returns the pixel data and type for a given letter BKSpriteTextureBlock *print_getBoldFontLetterSprite(s32 letterId, s32 *fontType){ - if(print_sCurrentFont != 1 || (print_sCurrentFont == 1 && letterId < 0xA)){ - s32 slot = print_sCurrentFont; + if(D_80380AE8 != 1 || (D_80380AE8 == 1 && letterId < 0xA)){ + s32 slot = D_80380AE8; // [port] Let the language system remap the slot/letter (e.g. fall back to // the base font if the JP font slot is momentarily unloaded mid-swap). CALL_EVENT(ResolveBoldFontSlot, &slot, &letterId); - *fontType = print_sFontSpriteAssets[slot]->type; + *fontType = D_80380AB8[slot]->type; return print_sFonts[slot][letterId].sprite; } else{//L802F5510 - if(!print_sFontSpriteAssets[3]){ - print_sFontSpriteAssets[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); - print_sFontSpriteAssets[4] = assetcache_get(print_sCurrentBoldFontTexture); - print_sFonts[3] = print_getLettersFromFont(print_sFontSpriteAssets[3], print_sFontSpriteAssets[4]); - assetcache_release(print_sFontSpriteAssets[4]); - print_sFontSpriteAssets[4] = NULL; + if(!D_80380AB8[3]){ + D_80380AB8[3] = assetcache_get(SPRITE_BOLD_FONT_LETTERS_ALPHAMASK); + D_80380AB8[4] = assetcache_get(D_80380B1C); + print_sFonts[3] = print_getLettersFromFont(D_80380AB8[3], D_80380AB8[4]); + assetcache_release(D_80380AB8[4]); + D_80380AB8[4] = NULL; }//L802F5568 - print_sBoldLetterFontFreeTimer = 5; - *fontType = print_sFontSpriteAssets[3]->type; + D_80380B18 = 5; + *fontType = D_80380AB8[3]->type; return print_sFonts[3][letterId-10].sprite; } } //returns the letter's palette void *print_getCurrentFontPalette(u8 arg0){ - return print_sFonts[print_sCurrentFont][arg0].palette; + return print_sFonts[D_80380AE8][arg0].palette; } void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx **gfx, Mtx **mtx, Vtx **vtx){ static f32 left_margin; // u8 letter = arg0; - BKSpriteTextureBlock *letter_sprite; + BKSpriteTextureBlock *sp214; uintptr_t sp210; - s32 letter_id; - s32 valid_letter; - s8 y_offset; - f32 x; - f32 y; - f32 letter_width; - s32 font_type; //font_type; + s32 sp20C; + s32 t0; + s8 t1; + f32 sp200; + f32 f28; + f32 sp1F8; + s32 sp1F4; //font_type; int i; - valid_letter = 0; - x = *xPtr; - y = *yPtr; - y_offset = 0; + t0 = 0; + sp200 = *xPtr; + f28 = *yPtr; + t1 = 0; - if(!print_sUnknownMode && !letter){ + if(!D_80380B04 && !letter){ left_margin = 0.0f; }//L802F563C - switch(print_sCurrentFont){ + switch(D_80380AE8){ case 0: //L802F5678 if(letter >= '\x21' && letter < ('\x21' + print_sDialogFontGlyphCount)){ - letter_id = letter - '\x21'; - valid_letter = 1; + sp20C = letter - '\x21'; + t0 = 1; } break; case 1: //L802F56A0 - if((u8)letter < 0x80 && print_sBoldFontLetterToSpriteMap[(u8)letter] >= 0){ // [port] char is signed on MSVC; MIPS char is unsigned + if((u8)letter < 0x80 && D_80380F20[(u8)letter] >= 0){ // [port] char is signed on MSVC; MIPS char is unsigned for(i = 0; boldFontKernings[i].firstLetter != 0; i++){ - if(letter == boldFontKernings[i].secondLetter && print_sPreviousBoldLetter == boldFontKernings[i].firstLetter){ - y_offset = boldFontKernings[i].yOffset; + if(letter == boldFontKernings[i].secondLetter && D_80380AB0 == boldFontKernings[i].firstLetter){ + t1 = boldFontKernings[i].yOffset; break; } }//L802F5710 - letter_id = print_sBoldFontLetterToSpriteMap[(u8)letter]; - valid_letter = 1; - print_sPreviousBoldLetter = (u8)letter; - y += (f32)y_offset*arg3; + sp20C = D_80380F20[(u8)letter]; + t0 = 1; + D_80380AB0 = (u8)letter; + f28 += (f32)t1*arg3; }//L802F5738 break; case 2: //L802F5740 - letter_id = (u8)letter; - if(print_sUnknownMode){ - valid_letter = 1; - letter_id += (print_sUnknownMode << 8) - 0x100; - print_sUnknownMode = 0; + sp20C = (u8)letter; + if(D_80380B04){ + t0 = 1; + sp20C += (D_80380B04 << 8) - 0x100; + D_80380B04 = 0; } else if(PRINT_JP){ - if(letter_id > 0 && letter_id != 0xFD && letter_id != 0x0F){ - valid_letter = 1; - if(letter_id == 0x36) - letter_id = 0xFD; + if(sp20C > 0 && sp20C != 0xFD && sp20C != 0x0F){ + t0 = 1; + if(sp20C == 0x36) + sp20C = 0xFD; } } else{//L802F5764 - if(letter_id > 0 && letter_id < 0xfD) - valid_letter = 1; + if(sp20C > 0 && sp20C < 0xfD) + t0 = 1; } break; }//L802F5778 - if(!valid_letter || print_sInFontFormatMode){ + if(!t0 || print_sInFontFormatMode){ print_sInFontFormatMode = false; switch((u8)letter){ case '\x0F': // [port] JP font-2 word space; no-op for US/PAL @@ -636,54 +639,54 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * break; // fallthrough case ' '://802F5818 - *xPtr += ((print_sMonospacedModeEnabled) ? maxFontLetterWidths[print_sCurrentFont]: maxFontLetterWidths[print_sCurrentFont]*0.8) * arg3; + *xPtr += ((D_80380AF0) ? D_80369068[D_80380AE8]: D_80369068[D_80380AE8]*0.8) * arg3; break; case 'b': //L802F5890 case '\x6D': // [port] PAL shifted b //toggle background - print_sBackgroundModeEnabled = print_sBackgroundModeEnabled ^ 1; + D_80380B00 = D_80380B00 ^ 1; break; case 'f': //L802F58A8 case '\x72': // [port] PAL shifted f - print_sPreviousFont = print_sCurrentFont = print_sCurrentFont ^ 1; + D_80380AEC = D_80380AE8 = D_80380AE8 ^ 1; break; case 'l': //L802F58BC - print_sShakyModeEnabled = 0; + D_80380B10 = 0; break; case 'h': //L802F58C8 case '\x73': // [port] PAL shifted h - print_sShakyModeEnabled = 1; + D_80380B10 = 1; break; case 'j': //L802F58D4 case '\x74': // [port] PAL shifted j - if(print_sBrokenFontModeEnabled == 0){ - print_sBrokenFontModeEnabled = 1; - print_sPreviousFont = print_sCurrentFont; - print_sCurrentFont = 2; - // print_sCurrentFont = 2; + if(D_80380AFC == 0){ + D_80380AFC = 1; + D_80380AEC = D_80380AE8; + D_80380AE8 = 2; + // D_80380AE8 = 2; } break; case 'e': //L802F58FC case '\x6F': // [port] PAL shifted e - if(print_sBrokenFontModeEnabled){ - print_sBrokenFontModeEnabled = 0; - print_sCurrentFont = print_sPreviousFont; + if(D_80380AFC){ + D_80380AFC = 0; + D_80380AE8 = D_80380AEC; } break; case 'p': //L802F5924 - print_sMonospacedModeEnabled = print_sMonospacedModeEnabled ^1; + D_80380AF0 = D_80380AF0 ^1; break; case 'q': //L802F593C - print_sBilinearFilterModeEnabled = print_sBilinearFilterModeEnabled^1; - if(print_sBilinearFilterModeEnabled){ + D_80380B14 = D_80380B14^1; + if(D_80380B14){ gDPSetTextureFilter((*gfx)++, G_TF_POINT); } else{//L802F5978 @@ -693,8 +696,8 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * case 'v': //L802F59A0 //toggle letter gradient - print_sGradientModeEnabled ^= 1; - if(print_sGradientModeEnabled){ + D_80380AF4 ^= 1; + if(D_80380AF4){ viewport_setRenderViewportAndOrthoMatrix(gfx, mtx); gDPPipeSync((*gfx)++); gDPSetTexturePersp((*gfx)++, G_TP_PERSP); @@ -709,8 +712,8 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * case 'd': //L802F5A8C case '\x6E': // [port] PAL shifted d - print_sGradient2ModeEnabled ^= 1; - if(print_sGradient2ModeEnabled){ + D_80380AF8 ^= 1; + if(D_80380AF8){ gDPPipeSync((*gfx)++); gDPSetCycleType((*gfx)++, G_CYC_2CYCLE); gDPSetRenderMode((*gfx)++, G_RM_PASS, G_RM_XLU_SURF2); @@ -731,81 +734,81 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * break; case 0xfe://L802F5BF4 - print_sUnknownMode = 1; + D_80380B04 = 1; break; case 0xff://L802F5BFC - print_sUnknownMode = 2; + D_80380B04 = 2; break; default: break; } } else{//L802F5C08 - letter_sprite = print_getBoldFontLetterSprite(letter_id, &font_type); - if (print_sShakyModeEnabled != 0) { - x += randf2(-2.0f, 2.0f); - y += randf2(-2.0f, 2.0f); + sp214 = print_getBoldFontLetterSprite(sp20C, &sp1F4); + if (D_80380B10 != 0) { + sp200 += randf2(-2.0f, 2.0f); + f28 += randf2(-2.0f, 2.0f); } - letter_width = (print_sMonospacedModeEnabled != 0) ? maxFontLetterWidths[print_sCurrentFont] : letter_sprite->x; + sp1F8 = (D_80380AF0 != 0) ? D_80369068[D_80380AE8] : sp214->x; // temp_f2 = left_margin; // phi_f2 = temp_f2; if (left_margin == 0.0f) { - left_margin = -letter_width * 0.5; + left_margin = -sp1F8 * 0.5; } - x += (left_margin + (letter_width - letter_sprite->x) * 0.5); - y -= letter_sprite->h*0.5; - sp210 = (uintptr_t)(letter_sprite + 1); + sp200 += (left_margin + (sp1F8 - sp214->x) * 0.5); + f28 -= sp214->h*0.5; + sp210 = (uintptr_t)(sp214 + 1); while(sp210 % 8){ sp210++; } // [port] Resolve alt bold fonts const char* hdPath = NULL; - CALL_EVENT(ResolveSpriteHdPath, letter_sprite, &hdPath); + CALL_EVENT(ResolveSpriteHdPath, sp214, &hdPath); if (hdPath != NULL) { sp210 = (uintptr_t)hdPath; } const char* boldHdPath = NULL; - CALL_EVENT(ResolveBoldFontHd, letter_sprite, &boldHdPath); + CALL_EVENT(ResolveBoldFontHd, sp214, &boldHdPath); if (boldHdPath != NULL) { sp210 = (uintptr_t)boldHdPath; } - if (font_type == SPRITE_TYPE_RGBA32) { - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (font_type == SPRITE_TYPE_IA8) { - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_IA, G_IM_SIZ_8b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (font_type == SPRITE_TYPE_I8) { - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_I, G_IM_SIZ_8b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (font_type == SPRITE_TYPE_I4) { - gDPLoadTextureTile_4b((*gfx)++, sp210, G_IM_FMT_I, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - } else if (font_type == SPRITE_TYPE_CI8) { - void * pal = print_getCurrentFontPalette(letter_id); + if (sp1F4 == SPRITE_TYPE_RGBA32) { + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (sp1F4 == SPRITE_TYPE_IA8) { + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_IA, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (sp1F4 == SPRITE_TYPE_I8) { + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_I, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (sp1F4 == SPRITE_TYPE_I4) { + gDPLoadTextureTile_4b((*gfx)++, sp210, G_IM_FMT_I, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (sp1F4 == SPRITE_TYPE_CI8) { + void * pal = print_getCurrentFontPalette(sp20C); gDPLoadTLUT_pal256((*gfx)++, pal); - gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_CI, G_IM_SIZ_8b, letter_sprite->w, letter_sprite->h, 0, 0, letter_sprite->x-1, letter_sprite->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_CI, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y-1, 0, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gDPSetTextureLUT((*gfx)++, G_TT_RGBA16); }//L802F6570 - if (print_sGradient2ModeEnabled != 0) { + if (D_80380AF8 != 0) { s32 temp_t1; s32 phi_a0; temp_t1 = ((print_sCurrentPtr->topVertexAlpha - print_sCurrentPtr->y) - D_80380B0C) + 1; phi_a0 = - MAX(1 - D_80380B0C, MIN(0, temp_t1)); gDPSetTextureImage((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, 32, &D_80380B20); - gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, (letter_sprite->x + 8) >> 3, 0x0100, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); + gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, (sp214->x + 8) >> 3, 0x0100, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); gDPLoadSync((*gfx)++); - gDPLoadTile((*gfx)++, G_TX_LOADTILE, 0 << G_TEXTURE_IMAGE_FRAC, (phi_a0) << G_TEXTURE_IMAGE_FRAC, (letter_sprite->x) << G_TEXTURE_IMAGE_FRAC, (D_80380B0C - 1) << G_TEXTURE_IMAGE_FRAC); + gDPLoadTile((*gfx)++, G_TX_LOADTILE, 0 << G_TEXTURE_IMAGE_FRAC, (phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (D_80380B0C - 1) << G_TEXTURE_IMAGE_FRAC); gDPPipeSync((*gfx)++); - gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, ((letter_sprite->x - 0 + 1)*G_IM_SIZ_8b_LINE_BYTES + 7) >> 3, 0x0100, 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); - gDPSetTileSize((*gfx)++, 1, 0 << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) + phi_a0) << G_TEXTURE_IMAGE_FRAC, (letter_sprite->x) << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) - (1 - D_80380B0C))<x - 0 + 1)*G_IM_SIZ_8b_LINE_BYTES + 7) >> 3, 0x0100, 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD); + gDPSetTileSize((*gfx)++, 1, 0 << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) + phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) - (1 - D_80380B0C))<x - 1.0); - spD0 = letter_sprite->y - 1.0; - temp_f26 = (f64) x - (f32) gFramebufferWidth * 0.5; - spC0 = (f64)y - (f32)gFramebufferHeight*0.5 -0.5f; + temp_f24 = (sp214->x - 1.0); + spD0 = sp214->y - 1.0; + temp_f26 = (f64) sp200 - (f32) gFramebufferWidth * 0.5; + spC0 = (f64)f28 - (f32)gFramebufferHeight*0.5 -0.5f; gSPVertex((*gfx)++, (uintptr_t)*vtx, 4, 0); for(iy = 0.0f; iy < 2.0; iy+= 1.0){ for(ix = 0.0f; ix < 2.0; ix += 1.0){ @@ -840,9 +843,9 @@ void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx * else{ // [port] Wide variant: widescreen-anchored HUD text can start left of x=0; the Scis // macro would CPU-clamp it to the 4:3 edge and crop the glyph. - gSPWideTextureRectangle((*gfx)++, (s32)(x*4.0f), (s32)(y*4.0f), (s32)((x + letter_sprite->x*arg3)*4.0f), (s32)((y + letter_sprite->y*arg3)*4.0f), 0, 0, 0, (s32)(1024.0f / arg3), (s32)(1024.0f / arg3)); + gSPWideTextureRectangle((*gfx)++, (s32)(sp200*4.0f), (s32)(f28*4.0f), (s32)((sp200 + sp214->x*arg3)*4.0f), (s32)((f28 + sp214->y*arg3)*4.0f), 0, 0, 0, (s32)(1024.0f / arg3), (s32)(1024.0f / arg3)); } - *xPtr += letter_width * arg3; + *xPtr += sp1F8 * arg3; } } @@ -858,17 +861,17 @@ f32 print_calculateLetterXPos(u8 letter, f32* xPtr, f32 *yPtr, f32 arg3){ sp38 = *xPtr; var_v0 = false; sp34 = 0; - if (print_sCurrentFont == 1) { + if (D_80380AE8 == 1) { if (letter < 0x80) { - if (print_sBoldFontLetterToSpriteMap[letter] >= 0) { + if (D_80380F20[letter] >= 0) { for(i = 0; boldFontKernings[i].firstLetter != 0; i++) { - if ((boldFontKernings[i].secondLetter == letter) && (boldFontKernings[i].firstLetter == print_sPreviousBoldLetter)) { + if ((boldFontKernings[i].secondLetter == letter) && (boldFontKernings[i].firstLetter == D_80380AB0)) { sp34 = boldFontKernings[i].xOffset; break; } } - print_sPreviousBoldLetter = letter; - sp44 = print_sBoldFontLetterToSpriteMap[letter]; + D_80380AB0 = letter; + sp44 = D_80380F20[letter]; var_v0 = true; sp38 += sp34 * arg3; } @@ -879,15 +882,15 @@ f32 print_calculateLetterXPos(u8 letter, f32* xPtr, f32 *yPtr, f32 arg3){ } if (!var_v0 || print_sInFontFormatMode) { if (letter == ' ') { - var_f2 = (print_sMonospacedModeEnabled) ? maxFontLetterWidths[print_sCurrentFont] : 0.8*maxFontLetterWidths[print_sCurrentFont]; + var_f2 = (D_80380AF0) ? D_80369068[D_80380AE8] : 0.8*D_80369068[D_80380AE8]; } else{ return *xPtr; } } else { - if(print_sMonospacedModeEnabled){ - var_f2 = maxFontLetterWidths[print_sCurrentFont]; + if(D_80380AF0){ + var_f2 = D_80369068[D_80380AE8]; } else{ var_f2 = print_getBoldFontLetterSprite(sp44, &sp2C)->x; @@ -907,7 +910,6 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { f32 _y; f32 width; - FrameInterpolation_RecordOpenChild("printbuffer", 0); gSPDisplayList((*gfx)++, D_80369238); for(print_sCurrentPtr = print_sPrintBuffer; print_sCurrentPtr < print_sPrintBuffer + 0x20; print_sCurrentPtr++){ if (print_sCurrentPtr->string != 0) { @@ -918,17 +920,17 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { _printbuffer_draw_letter(0xFD, &_x, &_y, 1.0f, gfx, mtx, vtx); _printbuffer_draw_letter(print_sCurrentPtr->fmtString[j], &_x, &_y, 1.0f, gfx, mtx, vtx); } - if (print_sBackgroundModeEnabled != 0) { - width = (strlen(print_sCurrentPtr->string) -1)*maxFontLetterWidths[print_sCurrentFont]; + if (D_80380B00 != 0) { + width = (strlen(print_sCurrentPtr->string) -1)*D_80369068[D_80380AE8]; gDPPipeSync((*gfx)++); gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0x64); gDPSetCombineMode((*gfx)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); - gDPScisFillRectangle((*gfx)++, _x - maxFontLetterWidths[print_sCurrentFont]/2 - 1.0f, _y - maxFontLetterWidths[print_sCurrentFont]/2 - 1.0f, _x + width + maxFontLetterWidths[print_sCurrentFont]/2, _y + maxFontLetterWidths[print_sCurrentFont]/2 + 1.0f); + gDPScisFillRectangle((*gfx)++, _x - D_80369068[D_80380AE8]/2 - 1.0f, _y - D_80369068[D_80380AE8]/2 - 1.0f, _x + width + D_80369068[D_80380AE8]/2, _y + D_80369068[D_80380AE8]/2 + 1.0f); gDPPipeSync((*gfx)++); }//L802F73E8 - if ((print_sGradient2ModeEnabled == 0) && (print_sGradientModeEnabled == 0)) { - if (print_sCurrentFont != 0) { + if ((D_80380AF8 == 0) && (D_80380AF4 == 0)) { + if (D_80380AE8 != 0) { gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA); gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF); } else { @@ -936,7 +938,7 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { gDPSetPrimColor((*gfx)++, 0, 0, print_sCurrentPtr->rgba[0], print_sCurrentPtr->rgba[1], print_sCurrentPtr->rgba[2], print_sCurrentPtr->rgba[3]); } } - if ((print_sCurrentFont == 1) && ((f64) print_sCurrentPtr->scale < 0.0)) { + if ((D_80380AE8 == 1) && ((f64) print_sCurrentPtr->scale < 0.0)) { for(j = 0; print_sCurrentPtr->string[j]; j++){ letter_x_coords[j] = print_calculateLetterXPos(print_sCurrentPtr->string[j], &_x, &_y, -print_sCurrentPtr->scale); } @@ -946,7 +948,7 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { j--; } } else { - for(j = 0; (print_sCurrentPtr->string[j] != 0) || (print_sUnknownMode != 0); j++){ + for(j = 0; (print_sCurrentPtr->string[j] != 0) || (D_80380B04 != 0); j++){ _printbuffer_draw_letter(print_sCurrentPtr->string[j], &_x, &_y, print_sCurrentPtr->scale, gfx, mtx, vtx); } } @@ -963,7 +965,6 @@ void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { gDPSetTexturePersp((*gfx)++, G_TP_PERSP); gDPSetTextureFilter((*gfx)++, G_TF_BILERP); viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); - FrameInterpolation_RecordCloseChild(); }//*/ //adds a new string to the print buffer and updates string buffer end ptr @@ -979,16 +980,16 @@ void _printbuffer_push_new(s32 x, s32 y, u8 * string) { print_sCurrentPtr->fmtString[0] = (u8)0; print_sCurrentPtr->string = string; print_sCurrentPtr->scale = 1.0f; - print_sCurrentPtr->rgba[0] = (u8) normalTextColor.r; - print_sCurrentPtr->rgba[1] = (u8) normalTextColor.g; - print_sCurrentPtr->rgba[2] = (u8) normalTextColor.b; - print_sCurrentPtr->rgba[3] = (u8) normalTextColor.a; + print_sCurrentPtr->rgba[0] = (u8) normalTextColor.unk0; + print_sCurrentPtr->rgba[1] = (u8) normalTextColor.unk1; + print_sCurrentPtr->rgba[2] = (u8) normalTextColor.unk2; + print_sCurrentPtr->rgba[3] = (u8) normalTextColor.unk3; } void print_bold_overlapping(s32 x, s32 y, f32 arg2, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x72l" : "fl"); + strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x72l" : "fl"); print_sCurrentPtr->scale = arg2; } } @@ -996,21 +997,21 @@ void print_bold_overlapping(s32 x, s32 y, f32 arg2, u8* string){ void print_bold_spaced(s32 x, s32 y, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x72" : "f"); + strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x72" : "f"); } } void print_dialog(s32 x, s32 y, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x6Flq" : "elq"); + strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x6Flq" : "elq"); } } void print_dialog_w_bg(s32 x, s32 y, u8* string){ _printbuffer_push_new(x, y, string); if(print_sCurrentPtr){ - strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "p\x6D" : "pb"); + strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "p\x6D" : "pb"); } } @@ -1028,7 +1029,7 @@ void print_dialog_gradient2(s32 x, s32 y, u8* string, s32 arg3, s32 arg4){ if(print_sCurrentPtr){ print_sCurrentPtr->topVertexAlpha = arg3; print_sCurrentPtr->bottomVertexAlpha = arg4; - strcpy(print_sCurrentPtr->fmtString, ResourceMgr_IsPal() ? "\x6E\x6Flq" : "delq"); + strcpy(print_sCurrentPtr->fmtString, PRINT_PAL ? "\x6E\x6Flq" : "delq"); } } @@ -1055,11 +1056,11 @@ void func_802F7A2C(s32 arg0) { } void text_setNormalTextColor(s32 arg0, s32 arg1, s32 arg2){ - normalTextColor.r = arg0; - normalTextColor.g = arg1; - normalTextColor.b = arg2; + normalTextColor.unk0 = arg0; + normalTextColor.unk1 = arg1; + normalTextColor.unk2 = arg2; } void text_setNormalTextAlpha(s32 arg0){ - normalTextColor.a = arg0; + normalTextColor.unk3 = arg0; } diff --git a/src/core2/font/render.c b/src/core2/font/render.c index 763994506..300f58e76 100644 --- a/src/core2/font/render.c +++ b/src/core2/font/render.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_5DBC0.c #include #include "functions.h" #include "variables.h" @@ -314,33 +313,33 @@ void func_802E57E0(struct5DBC0_1s *arg0, Gfx **gfx) { } } -void func_802E5C98(Gfx **gfx) { +void func_802E5C98(Gfx **gdl){ int i; - gDPPipeSync((*gfx)++); - gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); - gSPTexture((*gfx)++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); - gSPSetGeometryMode((*gfx)++, G_TEXTURE_GEN_LINEAR); - gDPSetCycleType((*gfx)++, G_CYC_1CYCLE); - gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE); - gDPSetTextureLOD((*gfx)++, G_TL_TILE); - gDPSetTextureLUT((*gfx)++, G_TT_NONE); - gDPSetTextureDetail((*gfx)++, G_TD_CLAMP); - gDPSetTexturePersp((*gfx)++, G_TP_NONE); - gDPSetTextureFilter((*gfx)++, G_TF_BILERP); - gDPSetTextureConvert((*gfx)++, G_TC_FILT); - gDPSetAlphaCompare((*gfx)++, G_AC_NONE); - gDPSetRenderMode((*gfx)++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPPipeSync((*gdl)++); + gSPClearGeometryMode((*gdl)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); + gSPTexture((*gdl)++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); + gSPSetGeometryMode((*gdl)++, G_TEXTURE_GEN_LINEAR); + gDPSetCycleType((*gdl)++, G_CYC_1CYCLE); + gDPPipelineMode((*gdl)++, G_PM_NPRIMITIVE); + gDPSetTextureLOD((*gdl)++, G_TL_TILE); + gDPSetTextureLUT((*gdl)++, G_TT_NONE); + gDPSetTextureDetail((*gdl)++, G_TD_CLAMP); + gDPSetTexturePersp((*gdl)++, G_TP_NONE); + gDPSetTextureFilter((*gdl)++, G_TF_BILERP); + gDPSetTextureConvert((*gdl)++, G_TC_FILT); + gDPSetAlphaCompare((*gdl)++, G_AC_NONE); + gDPSetRenderMode((*gdl)++, G_RM_XLU_SURF, G_RM_XLU_SURF2); for(i = 0; i < D_8037E900->unkC; i++){ D_8037E900->unk0[i].unk4 -= 0x10; - func_802E57E0(D_8037E900->unk0 + i, gfx); + func_802E57E0(D_8037E900->unk0 + i, gdl); D_8037E900->unk0[i].unk4 += 0x10; } - gDPSetTexturePersp((*gfx)++, G_TP_PERSP); + gDPSetTexturePersp((*gdl)++, G_TP_PERSP); } -void func_802E5F10(Gfx **gfx) { - func_802E5C98(gfx); +void func_802E5F10(Gfx **gdl){ + func_802E5C98(gdl); func_802E5188(); } diff --git a/src/core2/frame/auxbuffer.c b/src/core2/frame/auxbuffer.c index 2578da188..28b1ca355 100644 --- a/src/core2/frame/auxbuffer.c +++ b/src/core2/frame/auxbuffer.c @@ -1,9 +1,13 @@ -// BanjoDecomp: core2/code_851D0.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" +int gfx_create_framebuffer(unsigned int width, unsigned int height, unsigned int native_width, + unsigned int native_height, unsigned char resize, unsigned char force_fixed_aspect); + +s32 sAuxGpuFbId = -1; + #define TILE_SIZE 32 #define TILE_COUNT_X 5 #define TILE_COUNT_Y 4 @@ -14,7 +18,8 @@ #define HORIZONTAL_MARGIN (((SCREEN_WIDTH) - IMAGE_WIDTH) / 2) #define VERTICAL_MARGIN (((SCREEN_HEIGHT) - IMAGE_HEIGHT) / 2) -Gfx sPictureBoxInitDL[] = { +/* .data */ +Gfx D_8036C450[] = { gsDPPipeSync(), gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH), gsSPSetGeometryMode(G_SHADE | G_TEXTURE_GEN_LINEAR | G_SHADING_SMOOTH), @@ -24,86 +29,87 @@ Gfx sPictureBoxInitDL[] = { gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE_ALPHA, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE_ALPHA, 0, 0, 0, 0, TEXEL0), gsDPSetTextureFilter(G_TF_POINT), gsDPSetTexturePersp(G_TP_NONE), - gsDPSetPrimColor(0, 0, 0, 0, 0, 120), + gsDPSetPrimColor(0, 0, 0x00, 0x00, 0x00, 0x78), gsSPEndDisplayList() }; -Gfx sPictureBoxFinishDL[] = { +Gfx D_8036C4A8[] = { gsDPPipeSync(), gsDPSetTextureFilter(G_TF_BILERP), gsDPSetTexturePersp(G_TP_PERSP), gsSPEndDisplayList() }; -s16 *sPictureBoxColorBuffer; -void *sPictureBoxColorBufferBase; +/* .bss */ +s16 *D_80382450; +void *D_80382454; -void picturebox_func_8030C160(void) { +/* .code */ +void func_8030C160(void){ func_8024F150(); } -void picturebox_func_8030C180(void) { +void func_8030C180(void){ func_8024F180(); } -void picturebox_init(void) { - if (sPictureBoxColorBufferBase == NULL) { - sPictureBoxColorBuffer = malloc(IMAGE_WIDTH * IMAGE_HEIGHT * sizeof(u16) + 64); - sPictureBoxColorBufferBase = sPictureBoxColorBuffer; - - // Make sure that the color buffer is aligned on a 64-byte boundary - while ((uintptr_t)sPictureBoxColorBuffer & 0x3F) { // [port] pointer-width - sPictureBoxColorBuffer++; +void func_8030C1A0(void){ + if(D_80382454 == NULL){ + D_80382454 = D_80382450 = bk_malloc(IMAGE_WIDTH * IMAGE_HEIGHT * sizeof(u16) + 64); + while((uintptr_t)D_80382450 & 0x3F){ + D_80382450++; } } + if (sAuxGpuFbId < 0) { + sAuxGpuFbId = gfx_create_framebuffer(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0); + } } -void picturebox_free(void) { - if (sPictureBoxColorBufferBase) { - free(sPictureBoxColorBufferBase); - sPictureBoxColorBufferBase = NULL; +void func_8030C204(void){ + if(D_80382454){ + bk_free(D_80382454); + D_80382454 = NULL; } - switch (getGameMode()) { + switch(getGameMode()){ case GAME_MODE_8_BOTTLES_BONUS: chBottlesBonus_func_802DEA8C(0, 0); break; - case GAME_MODE_A_SNS_PICTURE: func_802DF11C(0, 0); break; } } -void picturebox_spawn(void) { - switch (getGameMode()) { +void func_8030C27C(void){ + switch(getGameMode()){ case GAME_MODE_8_BOTTLES_BONUS: chBottlesBonus_spawn(0, 0); break; - case GAME_MODE_A_SNS_PICTURE: func_802DF090(0, 0); break; + } } -void picturebox_resetScissorBoxAndFramebuffer(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void func_8030C2D4(Gfx **gdl, Mtx **mptr, Vtx **vptr){ scissorBox_setDefault(); - setupFramebuffer(gfx, gFramebuffers[getActiveFramebuffer()]); + func_80253640(gdl, gFramebuffers[getActiveFramebuffer()]); } // [port] This function is not called anywhere // Draws a 160x128 image pointed to by D_80382450 into the center of the screen -void picturebox_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void func_8030C33C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 x, y; // Set up the rendering state to draw the image - gSPDisplayList((*gfx)++, sPictureBoxInitDL); + gSPDisplayList((*gfx)++, D_8036C450); // Iterate over every tile in the image for (y = 0; y < TILE_COUNT_Y; y++) { for(x = 0; x < TILE_COUNT_X; x++){ // Load the current tile from the image - gDPLoadTextureTile((*gfx)++, osVirtualToPhysical(sPictureBoxColorBuffer), G_IM_FMT_IA, G_IM_SIZ_16b, IMAGE_WIDTH, IMAGE_HEIGHT, + gDPLoadTextureTile((*gfx)++, osVirtualToPhysical(D_80382450), G_IM_FMT_IA, G_IM_SIZ_16b, IMAGE_WIDTH, IMAGE_HEIGHT, TILE_SIZE * x, TILE_SIZE * y, TILE_SIZE * (x + 1) - 1, TILE_SIZE * (y + 1) - 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, @@ -119,14 +125,13 @@ void picturebox_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { } } // Reset the rendering state - gSPDisplayList((*gfx)++, sPictureBoxFinishDL); + gSPDisplayList((*gfx)++, D_8036C4A8); } - -s16 *picturebox_getColorBuffer(void) { - return sPictureBoxColorBuffer; +s16 *func_8030C704(void){ + return D_80382450; } -void picturebox_setScissorBox(void) { - scissorBox_set(0, IMAGE_WIDTH, 0, IMAGE_HEIGHT); +void scissorBox_setSmall(void){ + scissorBox_set(0, 160, 0, 128); } diff --git a/src/core2/frame/rendermem.c b/src/core2/frame/rendermem.c index 865009e91..b69c54ce6 100644 --- a/src/core2/frame/rendermem.c +++ b/src/core2/frame/rendermem.c @@ -1,14 +1,12 @@ -// BanjoDecomp: core2/code_5C240.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" #include "bk_time.h" -#include "port/Interpolation/FrameInterpolation.h" extern void func_8023DFF0(s32); -extern void coMusicPlayer_update(void); +extern void comusicPlayer_update(void); extern void func_802F1A10(void *, f32); extern void func_8033DC10(void); extern void func_8033DC18(void); @@ -46,26 +44,22 @@ void func_802E329C(s32 arg0, Gfx **gfx_begin, Gfx **gfx_end) { Vtx *vtx; Vtx *vtx_start; - graphicscache_swapAndGetStacks(&gfx, &mtx, &vtx); + getGraphicsStacks(&gfx, &mtx, &vtx); gfx_start = gfx; mtx_start = mtx; vtx_start = vtx; - setupFramebufferForGamemode(&gfx, arg0); + scissorBox_SetForGameMode(&gfx, arg0); if (D_8037E8C0.unk14 == 2) { drawRectangle2D(&gfx, 0, 0, (s32) (f32) gFramebufferWidth, (s32) (f32) gFramebufferHeight, 0, 0, 0); } if ((D_8037E8C0.unk14 == 0) || (D_8037E8C0.unk14 == 3)) { - FrameInterpolation_RecordOpenChild("rendermem_bound", 0); viewport_setRenderViewportAndPerspectiveMatrix(&gfx, &mtx); gcbound_draw(&gfx); - FrameInterpolation_RecordCloseChild(); } if (D_8037E8C0.unk14 == 1) { - FrameInterpolation_RecordOpenChild("rendermem_pause", 0); drawRectangle2D(&gfx, 0, 0, (s32) (f32) gFramebufferWidth, (s32) (f32) gFramebufferHeight, 0, 0, 0); viewport_setRenderViewportAndPerspectiveMatrix(&gfx, &mtx); func_802F1858(D_8037E8C0.unk10, &gfx, &mtx, &vtx); - FrameInterpolation_RecordCloseChild(); } core1_15B30_finishDList(&gfx); graphicsCache_checkFrame(gfx_start, gfx, mtx_start, mtx, vtx_start, vtx); @@ -118,8 +112,8 @@ void func_802E3580(void) { assetcache_release((void *)(intptr_t)D_8037E8C0.unkC); func_802F1884(D_8037E8C0.unk10); func_802E5F68(); - coMusicPlayer_free(); - depthbuffer_stub(); + comusicPlayer_free(); + depthBuffer_stub(); viMgr_func_8024BF94(2); } @@ -173,7 +167,7 @@ void func_802E35D8(void ) { return; } } - coMusicPlayer_update(); + comusicPlayer_update(); if (D_8037E8C0.unk14 == 0) { gcbound_alpha(D_8037E8C0.unk8); } diff --git a/src/core2/frame/texture_capture.c b/src/core2/frame/texture_capture.c index 51b7c1070..d3798e782 100644 --- a/src/core2/frame/texture_capture.c +++ b/src/core2/frame/texture_capture.c @@ -1,19 +1,10 @@ -// BanjoDecomp: core2/code_77E50.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "port/Patches/Patches.h" - extern void gfx_texture_cache_clear(void); -// [port] The texture cache belongs to the renderer; marshal the clear. -static void __textureCacheClearFn(void* arg) { - (void)arg; - gfx_texture_cache_clear(); -} - u8 *textureList_getDataPtr(BKTextureList *texture_list); void model_copyFramebufferBlockToTexture(BKTextureList *texture_list, s32 indx, s32 x_offset, s32 y_offset){ @@ -43,10 +34,6 @@ void model_copyFramebufferToTextures(BKModelBin *model_bin){ s32 x, y; texture_list = modelbin_getTextureList(model_bin); - // [port] The blocks below read the rendered frame from the CPU-side - // buffer, so the frame this tick submitted has to be drawn first. One - // sync covers the whole capture. - port_pipelineSyncPoint(); osInvalDCache((void *)gFramebuffers[getActiveFramebuffer()], gFramebufferWidth * gFramebufferHeight*2); for(y = 0; y < 8; y++){ @@ -59,5 +46,5 @@ void model_copyFramebufferToTextures(BKModelBin *model_bin){ // [port] The CPU just modified texture data that LUS may have cached on the GPU. // Clear the texture cache so the next draw re-uploads from CPU memory. - port_runOnRenderThread(__textureCacheClearFn, NULL); + gfx_texture_cache_clear(); } diff --git a/src/core2/fla.c b/src/core2/freelist.c similarity index 99% rename from src/core2/fla.c rename to src/core2/freelist.c index 05c22d3fd..2d50f492f 100644 --- a/src/core2/fla.c +++ b/src/core2/freelist.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fla.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/cutscene_actors.c b/src/core2/fx/background_decor.c similarity index 69% rename from src/core2/fx/cutscene_actors.c rename to src/core2/fx/background_decor.c index 850a98751..2d3a70e33 100644 --- a/src/core2/fx/cutscene_actors.c +++ b/src/core2/fx/background_decor.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_59780.c #include #include "core1/core1.h" #include "functions.h" @@ -9,44 +8,44 @@ extern void actor_postdrawMethod(ActorMarker *); Actor *func_802E0738(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); void func_802E07E0(Actor *this); -void chFireSparkle_update(Actor *this); +void func_802E08F0(Actor *this); /* .data */ -ActorAnimationInfo chFireSparkleAnimations[] = { +ActorAnimationInfo D_80368440[] = { {0, 0.0f}, {ASSET_98_ANIM_FIRE_SPARKLE, 1.2f} }; -ActorInfo chFireSparkle = { +ActorInfo D_80368450 = { MARKER_72_FIRE_SPARKLE, ACTOR_A2_FIRE_SPARKLE, ASSET_3AD_FIRE_SPARKLE, - 0x1, chFireSparkleAnimations, - chFireSparkle_update, actor_update_func_80326224, actor_draw, + 0x1, D_80368440, + func_802E08F0, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0 }; -ActorInfo chBanjoCurtains = { - MARKER_8C_BANJOS_CURTAINS, ACTOR_BC_BANJOS_CURTAINS, ASSET_45C_MODEL_BANJOS_CURTAINS, +ActorInfo D_80368474 = { + 0x8C, 0xBC, 0x45C, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 }; -ActorInfo chBanjoHouseDoor = { - MARKER_8D_BANJOS_HOUSE_DOOR, ACTOR_BD_BANJOS_HOUSE_DOOR, ASSET_45E_MODEL_BANJOS_HOUSE_DOOR, +ActorInfo D_80368498 = { + 0x8D, 0xBD, 0x45E, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 }; -ActorInfo chFishbowl = { - MARKER_13D_FISHBOWL, ACTOR_2F4_FISHBOWL, ASSET_46E_MODEL_FISHBOWL, +ActorInfo D_803684BC = { + 0x13D, 0x2F4, 0x46E, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 }; -ActorInfo chCuckooClock = { - MARKER_13E_CUCKOO_CLOCK, ACTOR_2F5_CUCKOO_CLOCK, ASSET_46F_MODEL_CUCKOO_CLOCK, +ActorInfo D_803684E0 = { + 0x13E, 0x2F5, 0x46F, 0, NULL, NULL, func_802E07E0, func_802E0738, 0, 0, 0.0f, 0 @@ -87,13 +86,13 @@ void func_802E0710(Actor *this){ } Actor *func_802E0738(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - f32 rotation[3]; + f32 sp34[3]; Actor *this; - this = marker_getActorAndRotation(marker, rotation); + this = marker_getActorAndRotation(marker, sp34); modelRender_setPreDrawCallback( (model_render_pre_draw_callback_f)func_802E0710, (void *)this); modelRender_setPostDrawCallback((model_render_post_draw_callback_f)actor_postdrawMethod, (void *)marker); - modelRender_draw(gfx, mtx, this->position, rotation, this->scale, NULL, marker_loadModelBin(marker)); + modelRender_draw(gfx, mtx, this->position, sp34, this->scale, NULL, marker_loadModelBin(marker)); return this; } @@ -110,9 +109,9 @@ void func_802E07E0(Actor *this) { sp24 = 0; break; - case ASSET_451_MODEL_GRUNTILDA: - case ASSET_458_MODEL_BANJO_TOP_SLEEPING: - case ASSET_532_MODEL_BANJO_KAZOOIE_CUTSCENES: + case 0x451: + case 0x458: + case 0x532: sp24 = 1; break; } @@ -138,8 +137,8 @@ void func_802E07E0(Actor *this) { func_80361EE0(this); } -void chFireSparkle_update(Actor *this) { - f32 rotation[3]; +void func_802E08F0(Actor *this) { + f32 sp24[3]; this->marker->collidable = false; anctrl_setDuration(this->anctrl, this->unk5C); @@ -147,6 +146,6 @@ void chFireSparkle_update(Actor *this) { if (actor_animationIsAt(this, 0.99f) != 0) { marker_despawn(this->marker); } - viewport_getRotation_vec3f(rotation); - this->yaw = rotation[1]; + viewport_getRotation_vec3f(sp24); + this->yaw = sp24[1]; } diff --git a/src/core2/fx/drips.c b/src/core2/fx/drips.c index fa6ec221d..580e85501 100644 --- a/src/core2/fx/drips.c +++ b/src/core2/fx/drips.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/drips.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/piranhaWaterParticles.c b/src/core2/fx/droplet.c similarity index 94% rename from src/core2/fx/piranhaWaterParticles.c rename to src/core2/fx/droplet.c index d26d8c98f..67a61fb79 100644 --- a/src/core2/fx/piranhaWaterParticles.c +++ b/src/core2/fx/droplet.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/piranhaWaterParticles.c #include #include "core1/core1.h" #include "functions.h" @@ -9,7 +8,7 @@ extern ParticleEmitter *func_802F4094(f32 pos[3], f32 arg1); void chPiranhaWaterParticles_update(Actor *this); /* .data */ -ActorInfo chPiranhaWaterParticles = { +ActorInfo D_80367C60 = { 0x15E, 0x188, 0x0, 0, NULL, chPiranhaWaterParticles_update, actor_update_func_80326224, func_80325340, diff --git a/src/core2/fx/effect_colordata.c b/src/core2/fx/effect_colordata.c index 05ec9e930..b0b7b64f2 100644 --- a/src/core2/fx/effect_colordata.c +++ b/src/core2/fx/effect_colordata.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_BE2C0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/fx/effect_debris.c b/src/core2/fx/effect_debris.c index bf9f8c40e..13f7acf9c 100644 --- a/src/core2/fx/effect_debris.c +++ b/src/core2/fx/effect_debris.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_41460.c #include "functions.h" #include "variables.h" #include @@ -35,49 +34,12 @@ f32 D_80366330 = 0.5f; f32 D_80366334 = 30.0f; f32 D_80366338 = 150.0f; f32 D_8036633C = 25.0f; - -ActorInfo D_80366340 = { - MARKER_56_UNKNOWN, 0x4A, 0x0, - 0x2, NULL, - func_802C8C5C, actor_update_func_80326224, func_802C8484, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80366364 = { - MARKER_56_UNKNOWN, 0x4B, 0x0, - 0x2, NULL, - func_802C8C5C, actor_update_func_80326224, func_802C8484, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80366388 = { - MARKER_56_UNKNOWN, 0xD, 0x0, - 0x2, NULL, - func_802C8C5C, actor_update_func_80326224, func_802C8484, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803663AC = { - MARKER_56_UNKNOWN, 0x11F, 0x0, - 0x2, NULL, - func_802C8C5C, actor_update_func_80326224, func_802C8484, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803663D0 = { - MARKER_56_UNKNOWN, 0x14F, 0x0, - 0x2, NULL, - func_802C8C5C, actor_update_func_80326224, func_802C8484, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_803663F4 = { - MARKER_56_UNKNOWN, 0x3AD, 0x0, - 0x2, NULL, - func_802C8C5C, actor_update_func_80326224, func_802C8484, - 0, 0, 0.0f, 0 -}; - +ActorInfo D_80366340 = { 0x56, 0x4A, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; +ActorInfo D_80366364 = { 0x56, 0x4B, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; +ActorInfo D_80366388 = { 0x56, 0xD, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; +ActorInfo D_803663AC = { 0x56, 0x11F, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; +ActorInfo D_803663D0 = { 0x56, 0x14F, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; +ActorInfo D_803663F4 = { 0x56, 0x3AD, 0x0, 0x2, 0x0, func_802C8C5C, actor_update_func_80326224, func_802C8484, 0, 0, 0.0f, 0}; s32 D_80366418[3] = {0,0,0}; /* .bss */ @@ -109,14 +71,14 @@ void func_802C83F0(Actor *actor) { Actor *func_802C8484(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { Struct25s *temp_s1; Struct24s *phi_s0; - f32 rotation[3]; - Actor *this; + f32 sp5C[3]; + Actor *sp58; u32 phi_v1; s32 phi_s4; - this = marker_getActorAndRotation(marker, rotation); - temp_s1 = (Struct25s*)this->unk40; - phi_s4 = FALSE; + sp58 = marker_getActorAndRotation(marker, sp5C); + temp_s1 = sp58->unk40; + phi_s4 = false; for(phi_s0 = temp_s1->begin; phi_s0 < temp_s1->current; phi_s0++){ if ((phi_s0->unk0 != 0) && (phi_s0->model_bin != NULL)) { // [port] Stable scope per piece. Expiry shrinks the range @@ -131,7 +93,7 @@ Actor *func_802C8484(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { if (phi_s4 == false) { marker_despawn(marker); } - return this; + return sp58; } Actor *func_802C8580(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ @@ -165,44 +127,44 @@ Actor *func_802C8580(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){ s0->unk8[1] = 0.0f; s0->unk8[2] = 0.0f; switch(D_8037DD94){ - case 1: // 802C8740 - s0->unk30[0] = randf2(125.0f, 175.0f); - s0->unk30[1] = randf2(400.0f, 600.0f); - s0->unk30[2] = randf2(125.0f, 175.0f); - s0->model_bin = (BKModelBin *) assetcache_get(0x2e7); - s0->unk2C = 18.0f; - break; - case 2: // 802C87A8 - s0->model_bin = (BKModelBin *) assetcache_get(0x344); - s0->unk2C = 2.0f; - break; - case 4: // 802C87C4 - s0->model_bin = (BKModelBin *) assetcache_get(0x345); - s0->unk2C = 1.0f; - s0->unk30[0] = randf2(20.0f, 100.0f); - s0->unk30[1] = randf2(400.0f, 740.0f); - s0->unk30[2] = randf2(20.0f, 100.0f); - - s0->unk8[0] = randf2(0.0f, 30.0f); - s0->unk8[1] = 0.0f; - s0->unk8[2] = 0.0f; - break; - case 0: // 802C883C - if(0.5 < randf()) - s0->model_bin = (BKModelBin *) assetcache_get(MODEL_ASSET_OFFSET); - else - s0->model_bin = (BKModelBin *) assetcache_get(0x2e5); - - s0->unk2C = randf2(5.0f, 12.0f); - break; - case 3: // 802C88A0 - s0->model_bin = (BKModelBin *) assetcache_get(0x30e); - s0->unk2C = randf2(9.0f, 15.0f); - break; - case 5: // 802C88C8 - s0->model_bin = (BKModelBin *) assetcache_get(0x8a2); - s0->unk2C = 2.0f; - break; + case 1: // 802C8740 + s0->unk30[0] = randf2(125.0f, 175.0f); + s0->unk30[1] = randf2(400.0f, 600.0f); + s0->unk30[2] = randf2(125.0f, 175.0f); + s0->model_bin = (BKModelBin *) assetcache_get(0x2e7); + s0->unk2C = 18.0f; + break; + case 2: // 802C87A8 + s0->model_bin = (BKModelBin *) assetcache_get(0x344); + s0->unk2C = 2.0f; + break; + case 4: // 802C87C4 + s0->model_bin = (BKModelBin *) assetcache_get(0x345); + s0->unk2C = 1.0f; + s0->unk30[0] = randf2(20.0f, 100.0f); + s0->unk30[1] = randf2(400.0f, 740.0f); + s0->unk30[2] = randf2(20.0f, 100.0f); + + s0->unk8[0] = randf2(0.0f, 30.0f); + s0->unk8[1] = 0.0f; + s0->unk8[2] = 0.0f; + break; + case 0: // 802C883C + if(0.5 < randf()) + s0->model_bin = (BKModelBin *) assetcache_get(0x2d1); + else + s0->model_bin = (BKModelBin *) assetcache_get(0x2e5); + + s0->unk2C = randf2(5.0f, 12.0f); + break; + case 3: // 802C88A0 + s0->model_bin = (BKModelBin *) assetcache_get(0x30e); + s0->unk2C = randf2(9.0f, 15.0f); + break; + case 5: // 802C88C8 + s0->model_bin = (BKModelBin *) assetcache_get(0x8a2); + s0->unk2C = 2.0f; + break; }//L802C88E0 s0->unk3C = NULL; sp68[0] = (f32)position[0]; diff --git a/src/core2/fx/eggshatter.c b/src/core2/fx/effect_eggshatter.c similarity index 98% rename from src/core2/fx/eggshatter.c rename to src/core2/fx/effect_eggshatter.c index 88b7db8e4..19dfb5f76 100644 --- a/src/core2/fx/eggshatter.c +++ b/src/core2/fx/effect_eggshatter.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/eggshatter.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/explosionripple.c b/src/core2/fx/effect_generic.c similarity index 94% rename from src/core2/fx/explosionripple.c rename to src/core2/fx/effect_generic.c index 73edc1542..a52c26a49 100644 --- a/src/core2/fx/explosionripple.c +++ b/src/core2/fx/effect_generic.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/explosionripple.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_ice.c b/src/core2/fx/effect_ice.c index 1b4378276..ed50f683e 100644 --- a/src/core2/fx/effect_ice.c +++ b/src/core2/fx/effect_ice.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_54D50.c #include #include "functions.h" #include "variables.h" @@ -17,14 +16,13 @@ void func_802DC018(Actor *this); /* .data */ ActorInfo D_80367F30= { - MARKER_1F5_UNKNOWN, ACTOR_1E5_UNKNOWN, 0, + 0x1F5, 0x1E5, 0, 0, NULL, func_802DC018, actor_update_func_80326224, func_80325340, 0, 0, 0.0f, 0 }; s32 D_80367F54[3] = {0xff, 0xff, 0xff}; - ParticleSettingsScaleAndLifetimeDrawModeEmitCount D_80367F60 = { { {0.1f, 0.5f}, {1.0f, 1.5f}, {0.0f, 0.01f}, {0.5f, 1.4f}, 0.0f, 0.01f diff --git a/src/core2/fx/effect_jiggy.c b/src/core2/fx/effect_jiggy.c index 711b94de1..db3d1fd68 100644 --- a/src/core2/fx/effect_jiggy.c +++ b/src/core2/fx/effect_jiggy.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C0CF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_jiggy_list.c b/src/core2/fx/effect_jiggy_list.c index 6f0ef34d5..efc1edcd6 100644 --- a/src/core2/fx/effect_jiggy_list.c +++ b/src/core2/fx/effect_jiggy_list.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_ABC00.c #include #include "functions.h" #include "variables.h" @@ -254,7 +253,6 @@ void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]) { temp_v0->unk10.position[2] = pos[2]; temp_v0->init(&temp_v0->unk10); jiggyscore_setSpawned(jiggy_id, true); - CALL_EVENT(OnJiggySpawned, jiggy_id, pos[0], pos[1], pos[2]); if (!jiggyscore_isCollected(jiggy_id) && (jiggy_id != JIGGY_3E_GV_GRABBA) && (jiggy_id != JIGGY_0B_TTC_JINJO)) { core1_ce60_incOrDecCounter(false); func_8025A55C(0, 4000, 5); @@ -265,15 +263,7 @@ void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]) { } } -// [port] Anchor: true once the jiggylist slot's marker is linked (covers bundle-pop, unlike jiggyscore_isSpawned). -s32 jiggylist_hasSpawnedObject(enum jiggy_e jiggy_id) { - if ((jiggy_id <= 0) || (jiggy_id >= (s_jiggyList_level_jiggy_count * 10))) { - return 0; - } - return jiggylist_list[jiggy_id - 1].unk10.marker != NULL; -} - -void codeABC00_spawnJiggyAtLocationEx(enum jiggy_e jiggy_id, f32 location[3], s32 triggerEvent) { +void codeABC00_spawnJiggyAtLocation(enum jiggy_e jiggy_id, f32 location[3]) { jiggy_id = ((jiggy_id <= 0) || (jiggy_id >= (s_jiggyList_level_jiggy_count * 10))) ? JIGGY_A_MM_CONGA : jiggy_id; jiggylist_list[jiggy_id - 1].unk10.position[0] = location[0]; @@ -281,13 +271,6 @@ void codeABC00_spawnJiggyAtLocationEx(enum jiggy_e jiggy_id, f32 location[3], s3 jiggylist_list[jiggy_id - 1].unk10.position[2] = location[2]; jiggylist_list[jiggy_id - 1].init(&jiggylist_list[jiggy_id - 1].unk10); jiggyscore_setSpawned(jiggy_id, true); - if (triggerEvent) { - CALL_EVENT(OnJiggySpawned, jiggy_id, location[0], location[1], location[2]); - } -} - -void codeABC00_spawnJiggyAtLocation(enum jiggy_e jiggy_id, f32 location[3]) { - codeABC00_spawnJiggyAtLocationEx(jiggy_id, location, 1); } void func_80333270(enum jiggy_e jiggy_id, f32 position[3], void (*method)(Actor *, ActorMarker *), ActorMarker *other_marker) { diff --git a/src/core2/fx/effect_jiggy_spawn.c b/src/core2/fx/effect_jiggy_spawn.c index f50f5fa4f..d94f7f52d 100644 --- a/src/core2/fx/effect_jiggy_spawn.c +++ b/src/core2/fx/effect_jiggy_spawn.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C0B80.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_modelparticle.c b/src/core2/fx/effect_modelparticle.c index 31e9bbbdb..6247ae4d4 100644 --- a/src/core2/fx/effect_modelparticle.c +++ b/src/core2/fx/effect_modelparticle.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_53C10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_playerspray.c b/src/core2/fx/effect_playerspray.c index 44d5f3f04..2c71deae2 100644 --- a/src/core2/fx/effect_playerspray.c +++ b/src/core2/fx/effect_playerspray.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B850.c #include #include "functions.h" #include "variables.h" @@ -15,7 +14,7 @@ void func_802927E0(f32 arg0, f32 arg1){ f32 sp18[3]; arg1 *= 0.51; - playerPosition_get(sp18); + _player_getPosition(sp18); sp18[1] += 10.0f; func_802589E4(sp24, arg0, arg1); sp24[1] = 40.0f; @@ -28,7 +27,7 @@ void func_80292864(f32 arg0, f32 arg1){ f32 sp1C[3]; ml_vec3f_assign(sp1C, 0.0f, 40.0f, 0.0f); - playerPosition_get(sp28); + _player_getPosition(sp28); func_802589E4(sp34, arg0, arg1); sp34[1] = 10.0f; sp28[0] += sp34[0]; sp28[1] += sp34[1]; sp28[2] += sp34[2]; @@ -40,7 +39,7 @@ void func_80292900(f32 arg0, f32 arg1){ f32 sp18[3]; arg1 *= 0.51; - playerPosition_get(sp18); + _player_getPosition(sp18); func_802589E4(sp24, arg0, arg1); sp24[1] = 40.0f; func_80352CF4(sp18, sp24, 10.0f, 150.0f); @@ -50,7 +49,7 @@ void func_80292974(f32 arg0, f32 arg1, f32 arg2){ f32 sp24[3]; f32 sp18[3]; arg1 *= 0.51; - playerPosition_get(sp18); + _player_getPosition(sp18); sp18[1] += 10.0f; func_802589E4(sp24, arg0, arg1); sp24[1] = arg2; diff --git a/src/core2/fx/effect_ripple.c b/src/core2/fx/effect_ripple.c index 8348a55e4..34eb0566c 100644 --- a/src/core2/fx/effect_ripple.c +++ b/src/core2/fx/effect_ripple.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_DB010.c #include #include "core1/core1.h" #include "functions.h" @@ -588,7 +587,7 @@ void func_80363330(Actor *this){ void func_80363388(struct_core2_DB010 *arg0, s32 arg1){ f32 sp2C[3]; s32 sp20[3]; - s32 tmp_v0 = codeA5BC0_getPositionAndSelectorOrRadius(arg0, sp20); + s32 tmp_v0 = codeA5BC0_getPositionAndReturnRadius(arg0, sp20); sp2C[0] = (f32)sp20[0]; sp2C[1] = (f32)sp20[1]; sp2C[2] = (f32)sp20[2]; diff --git a/src/core2/fx/ripple.c b/src/core2/fx/effect_ripple_spawn.c similarity index 99% rename from src/core2/fx/ripple.c rename to src/core2/fx/effect_ripple_spawn.c index 32677ab4f..f30debf76 100644 --- a/src/core2/fx/ripple.c +++ b/src/core2/fx/effect_ripple_spawn.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/ripple.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_simplesprite.c b/src/core2/fx/effect_simplesprite.c index f1d14fdef..1f317d764 100644 --- a/src/core2/fx/effect_simplesprite.c +++ b/src/core2/fx/effect_simplesprite.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_55180.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/fx/effect_soundemit.c b/src/core2/fx/effect_soundemit.c new file mode 100644 index 000000000..7044b384a --- /dev/null +++ b/src/core2/fx/effect_soundemit.c @@ -0,0 +1,132 @@ +#include +#include "functions.h" +#include "variables.h" + +extern void func_802F82F4(struct3s *, f32, f32, f32, f32); + +typedef struct { + s16 unk0; + //u8 pad[0x2]; + int (*unk4)(Actor *); +} Struct_Core2_D2180_0; + +typedef struct { + Struct_Core2_D2180_0 *unk0; +} ActorLocal_core2_D2180; + +int func_80359110(Actor *); +int func_8035911C(Actor *); +int func_80359110(Actor *); +int func_80359160(Actor *); +int func_80359110(Actor *); +int func_803591A4(Actor *); +void func_8035933C(Actor *this); +void func_80359424(Actor *this); +void func_80359454(Actor *this); + +/* .data */ +Struct_Core2_D2180_0 D_80372940[] ={ + {2, func_80359110}, + {2, func_8035911C}, + {3, func_80359110}, + {3, func_80359160}, + {4, func_80359110}, + {4, func_803591A4} +}; + +ActorInfo D_80372970 = { 0x1C1, 0x2AE, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_80372994 = { 0x1C1, 0x2AF, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_803729B8 = { 0x1C1, 0x2B0, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_803729DC = { 0x1C1, 0x2B1, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_80372A00 = { 0x1C1, 0x2B2, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_80372A24 = { 0x1C1, 0x2B3, 0x0, 0, NULL, func_8035933C, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_80372A48 = { 0x1C1, 0x316, 0x0, 0, NULL, func_80359424, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_80372A6C = { 0x1C1, 0x317, 0x0, 0, NULL, func_80359454, NULL, func_80325340, 0, 0, 0.0f, 0}; + +/* .code */ +int func_80359110(Actor *this){ + return true; +} + +int func_8035911C(Actor *this){ + f32 plyr_pos[3]; + + player_getPosition(plyr_pos); + return (plyr_pos[2] < -1700.0f); +} + +int func_80359160(Actor *this){ + f32 plyr_pos[3]; + + player_getPosition(plyr_pos); + return (1700.0f < plyr_pos[2]); +} + +int func_803591A4(Actor *this){ + f32 plyr_pos[3]; + + player_getPosition(plyr_pos); + return (1700.0f < plyr_pos[0]); +} + +void func_803591E8(Actor *this, s32 next_state){ + ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; + + if(next_state == 2) + func_802F8C90(func_802F7C38()); + + if(this->state == 2) + func_802F8CB0(func_802F7C38()); + + if(next_state == 3){ + struct3s *rain = func_802F7C7C(); + func_802F8338(rain); + if(local->unk0->unk4 == func_80359110) { + func_802F82F4(rain, 5.0f, 30.0f, 5.0f, 30.0f); + } + } + + if(this->state == 3) + func_802F8358(func_802F7C7C()); + + if(next_state == 4){ + func_802F7CC0(); + func_802F90F4(); + } + if(this->state == 4){ + func_802F7CC0(); + func_802F9114(); + } + + + this->state = next_state; +} + +void func_8035933C(Actor *this){ + ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; + if(!this->volatile_initialized){ + this->volatile_initialized = true; + local->unk0 = D_80372940 + (this->modelCacheIndex - 0x2AE); + func_803591E8(this, 1); + } + if(this->state == 1){ + if(local->unk0->unk4(this)){ + func_803591E8(this, local->unk0->unk0); + } + } + if(this->state != 1){ + if(!local->unk0->unk4(this)){ + func_803591E8(this, 1); + } + } +} + +void func_80359424(Actor *this){ + if(func_803292E0(this)) + func_802F7D44(); +} + +void func_80359454(Actor *this){ + if(func_803292E0(this)) + func_802F7DE4(); +} diff --git a/src/core2/fx/shoesparkle.c b/src/core2/fx/effect_sparkle.c similarity index 50% rename from src/core2/fx/shoesparkle.c rename to src/core2/fx/effect_sparkle.c index b48ee8009..84150fdad 100644 --- a/src/core2/fx/shoesparkle.c +++ b/src/core2/fx/effect_sparkle.c @@ -1,57 +1,53 @@ -// BanjoDecomp: core2/fx/shoesparkle.c #include #include "functions.h" #include "variables.h" typedef struct{ - s32 frameCount; + s32 unk0; } ActorLocal_Core2_3EAD0; -void fxShoeSparkle_update(Actor *this); +void func_802C5A60(Actor *this); /* .data */ -s32 fxShoeSparkleFrames[] = { +s32 D_80365F30[] = { 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 8 }; - -#define MAX_FRAME_COUNT 12 - -ActorInfo fxWadingBootsTouchSparkle = { - MARKER_58_WADING_BOOTS_TOUCH_SPARKLE, ACTOR_4E_WADING_BOOTS_TOUCH_SPARKLE, ASSET_7DE_SPRITE_SHOE_SPARKLES, +ActorInfo D_80365F60 = { + 0x58, 0x4E, ASSET_7DE_SPRITE_SHOE_SPARKLES, 0, NULL, - fxShoeSparkle_update, actor_update_func_80326224, fxTouchSparkle_draw, + func_802C5A60, actor_update_func_80326224, fxTouchSparkle_draw, 0, 0, 0.0f, 0 }; -ActorInfo fxTurboTrainersTouchSparkle = { +ActorInfo D_80365F84 = { 0x59, 0x4F, ASSET_7DE_SPRITE_SHOE_SPARKLES, 0, NULL, - fxShoeSparkle_update, actor_update_func_80326224, fxTouchSparkle_draw, + func_802C5A60, actor_update_func_80326224, fxTouchSparkle_draw, 0, 0, 0.0f, 0 }; /* .code */ -void fxShoeSparkle_update(Actor *this){ +void func_802C5A60(Actor *this){ // Spawns a sparkle sprite when touching turbo trainers or wading boots ActorLocal_Core2_3EAD0 *local = (ActorLocal_Core2_3EAD0*)&this->local; if(!this->initialized){ switch(this->marker->id){ - case MARKER_58_WADING_BOOTS_TOUCH_SPARKLE: + case 0x58: suSetSpriteScale(this, 0.35f); break; - case MARKER_59_TURBO_TRAINERS_TOUCH_SPARKLE: + case 0x59: suSetSpriteScale(this, 0.4f); break; } this->marker->propPtr->isMirrored = 0.5 < randf(); - this->position_y += 100.0 * this->scale; + this->position_y += 100.0*this->scale; actor_collisionOff(this); this->initialized = true; }//L802C5B60 - this->marker->propPtr->frame = fxShoeSparkleFrames[local->frameCount]; - local->frameCount++; - if(local->frameCount >= MAX_FRAME_COUNT) + this->marker->propPtr->frame = D_80365F30[local->unk0]; + local->unk0++; + if(local->unk0 >= 0xC) marker_despawn(this->marker); } diff --git a/src/core2/fx/sparkle.c b/src/core2/fx/effect_sparkle_spawn.c similarity index 99% rename from src/core2/fx/sparkle.c rename to src/core2/fx/effect_sparkle_spawn.c index dfd8fe4da..5d0d0d4f3 100644 --- a/src/core2/fx/sparkle.c +++ b/src/core2/fx/effect_sparkle_spawn.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/sparkle.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/effect_sparkleemit.c b/src/core2/fx/effect_sparkleemit.c index e3127d1b4..3cdf83c99 100644 --- a/src/core2/fx/effect_sparkleemit.c +++ b/src/core2/fx/effect_sparkleemit.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_50490.c #include #include "functions.h" #include "variables.h" @@ -17,9 +16,7 @@ f32 D_80367A84 = 30.0f; f32 D_80367A88 = 150.0f; f32 D_80367A8C = 25.0f; s32 D_80367A90[4] = {250, 250, 250, 120}; - -enum dust_emitter_type_e D_80367AA0 = DUST_EMITTER_TYPE_DUST; - +s32 D_80367AA0 = 0; f32 D_80367AA4[3] = {0.0f, 0.0f, 0.0f}; ActorInfo D_80367AB0 = { diff --git a/src/core2/fx/banjokazooiesign.c b/src/core2/fx/effect_spriteanim.c similarity index 61% rename from src/core2/fx/banjokazooiesign.c rename to src/core2/fx/effect_spriteanim.c index 10398096e..f1075c066 100644 --- a/src/core2/fx/banjokazooiesign.c +++ b/src/core2/fx/effect_spriteanim.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gc/banjokazooiesign.c #include #include "core1/core1.h" #include "functions.h" @@ -7,20 +6,19 @@ extern void actor_postdrawMethod(ActorMarker *); Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void gcBanjoKazooieSign_update(Actor *this); +void func_802DC900(Actor *this); /* .data */ -f32 gcBanjoKazooieSignPosition[3] = {0.0f, 0.0f, 0.0f}; - -ActorInfo gcBanjoKazooieSign = { - MARKER_175_BANJO_KAZOOIE_SIGN, ACTOR_1DC_BANJO_KAZOOIE_SIGN, ASSET_54D_MODEL_BANJO_KAZOOIE_SIGN, +f32 D_803680A0[3] = {0.0f, 0.0f, 0.0f}; +ActorInfo D_803680AC = { + 0x175, 0x1DC, 0x54D, 0x1, NULL, - gcBanjoKazooieSign_update, actor_update_func_80326224, func_802DC7E0, + func_802DC900, actor_update_func_80326224, func_802DC7E0, 0, 0, 0.0f, 0 }; /* .bss */ -ActorMarker *gcBanjoKazooieSignMarker; +ActorMarker *D_8037DE60; /* .code */ Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ @@ -56,35 +54,35 @@ Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ return this; } -void gcBanjoKazooieSign_free(Actor *this){ - gcBanjoKazooieSignMarker = NULL; +void func_802DC8F0(Actor *this){ + D_8037DE60 = NULL; } -void gcBanjoKazooieSign_update(Actor *this){ +void func_802DC900(Actor *this){ if(!this->initialized){ this->initialized = true; this->depth_mode = MODEL_RENDER_DEPTH_NONE; actor_collisionOff(this); - marker_setFreeMethod(this->marker, gcBanjoKazooieSign_free); + marker_setFreeMethod(this->marker, func_802DC8F0); } } -void gcBanjoKazooieSign_spawn(void) { +void func_802DC960(void) { Actor *actor; - if (gcBanjoKazooieSignMarker == NULL) { - actor = actor_spawnWithYaw_f32(ACTOR_1DC_BANJO_KAZOOIE_SIGN, gcBanjoKazooieSignPosition, 0); - gcBanjoKazooieSignMarker = actor->marker; + if (D_8037DE60 == 0) { + actor = actor_spawnWithYaw_f32(0x1DC, D_803680A0, 0); + D_8037DE60 = actor->marker; } } void func_802DC9A4(s32 arg0, s32 arg1){ - if(gcBanjoKazooieSignMarker == NULL){ - __spawnQueue_add_0(gcBanjoKazooieSign_spawn); + if(D_8037DE60 == NULL){ + __spawnQueue_add_0(func_802DC960); } } void func_802DC9DC(s32 arg0, s32 arg1){ - if(gcBanjoKazooieSignMarker != NULL){ - func_80326310(marker_getActor(gcBanjoKazooieSignMarker)); + if(D_8037DE60 != NULL){ + func_80326310(marker_getActor(D_8037DE60)); } } diff --git a/src/core2/fx/badShad.c b/src/core2/fx/enemy_shadow.c similarity index 93% rename from src/core2/fx/badShad.c rename to src/core2/fx/enemy_shadow.c index 6804b9564..971b2e88c 100644 --- a/src/core2/fx/badShad.c +++ b/src/core2/fx/enemy_shadow.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/badShad.c #include #include "core1/core1.h" #include "functions.h" @@ -14,8 +13,8 @@ void func_802D729C(Actor *actor, f32 arg1); /* .data */ ActorInfo chBadShad = { - MARKER_9B_MODEL_PLAYER_SHADOW, ACTOR_108_MODEL_PLAYER_SHADOW, ASSET_3BF_MODEL_PLAYER_SHADOW, - 0x1, NULL, + 0x9B, 0x108, 0x3BF, + 0x1, NULL, chBadShad_update, actor_update_func_80326224, chBadShad_draw, 0, 0, 0.0f, 0 }; @@ -56,9 +55,9 @@ Actor *chBadShad_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ modelRender_setAlpha(other->alpha_124_19); sp40 = ml_map_f(this->actor_specific_1_f, 0.0f , 800.0f, 0.53f, 0.18f)*this->unk1C[1]; modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); - FrameInterpolation_CameraRelativePush(); + FrameInterpolation_NoInterpolatePush(); modelRender_draw(gfx, mtx, this->position, sp44, sp40, NULL, marker_loadModelBin(marker)); - FrameInterpolation_CameraRelativePop(); + FrameInterpolation_NoInterpolatePop(); return this; } @@ -144,7 +143,7 @@ void func_802D729C(Actor *actor, f32 arg1){ return; } if(!actor->unk104){ - __spawnQueue_add_2((GenFunction_2)func_802D71A0, (uintptr_t)actor->marker, reinterpret_cast(s32, arg1)); + __spawnQueue_add_2((void (*)(void))func_802D71A0, (uintptr_t)actor->marker, reinterpret_cast(s32, arg1)); return; } diff --git a/src/core2/fx/firefx.c b/src/core2/fx/firefx.c index 8942b86e1..3e60f8000 100644 --- a/src/core2/fx/firefx.c +++ b/src/core2/fx/firefx.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/firefx.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/fx/projectile_anim.c b/src/core2/fx/projectile_anim.c index 92137d625..3e74868fa 100644 --- a/src/core2/fx/projectile_anim.c +++ b/src/core2/fx/projectile_anim.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CBD10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_blueegg.c b/src/core2/fx/projectile_blueegg.c index 20abf395c..3c5323449 100644 --- a/src/core2/fx/projectile_blueegg.c +++ b/src/core2/fx/projectile_blueegg.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CC1E0.c #include #include "functions.h" #include "variables.h" @@ -107,7 +106,7 @@ s32 func_803531C8(u8 projectile_indx, s32 arg1){ func_8038685C(other_marker); break; - case MARKER_BB_JINXY_HEAD_SANDYBUTT: //L803533E4 + case MARKER_BB_UNKNOWN: //L803533E4 //"BIG_JINXYHEAD" other_actor = marker_getActor(other_marker); *(s32 *)&other_actor->local = 1; commonParticle_setCurrentInUseFalse(); @@ -120,9 +119,9 @@ s32 func_803531C8(u8 projectile_indx, s32 arg1){ break; case MARKER_AB_RUBEES_EGG_POT: //L80353434 - if (collisionTri_isHitFromAbove_marker(egg_position, other_marker, 0x1E) && (func_8038E178() < rubeeEggPot_getEggGoal())) { + if (collisionTri_isHitFromAbove_marker(egg_position, other_marker, 0x1E) && (func_8038E178() < func_8038E184())) { commonParticle_setCurrentInUseFalse(); - rubeeEggPot_addedEggToPot(); + func_8038E140(); } break; @@ -181,7 +180,7 @@ void fxegg_head_spawn(void){ func_8033EA40(0, 20.0f); func_8033EA40(1, 0.0f); func_8033EA40(2, 0.0f); - playerPosition_get(sp50); + _player_getPosition(sp50); sp50[1] += spawnHeight; ml_vec3f_copy(sp68, sp50); player_getRotation(sp44); @@ -291,7 +290,7 @@ void fxegg_ass_spawn(void) { func_8033EA40(1, 0); func_8033EA40(0, 20.0f); func_8033EA40(2, 0); - playerPosition_get(marker); + _player_getPosition(marker); player_getRotation(sp30); sp30[1] = mlNormalizeAngle(sp30[1] + 180.0f); func_80256E24(sp48, 0.0f, sp30[1], 0.0f, 0.0f, -18.0f); diff --git a/src/core2/fx/commonParticle.c b/src/core2/fx/projectile_manager.c similarity index 96% rename from src/core2/fx/commonParticle.c rename to src/core2/fx/projectile_manager.c index 9f93abca2..7cc4979b3 100644 --- a/src/core2/fx/commonParticle.c +++ b/src/core2/fx/projectile_manager.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/commonParticle.c #include "core2/commonParticle.h" #include #include "functions.h" @@ -183,18 +182,14 @@ s32 commonParticle_findFree(void){ int commonParticle_new(enum common_particle_e particle_id, int arg1){ f32 sp34[3]; uintptr_t a0; - s32 slot; if(arg1 == 0) return -1; ml_vec3f_clear(sp34); - // [port] Don't publish -1 to the global; every D_80384490[D_80384FD0] access - // downstream (accessors, commonParticle_update) would read out of bounds. - slot = commonParticle_findFree(); - if(slot < 0) + D_80384FD0 = commonParticle_findFree(); + if(D_80384FD0 < 0) return -1; - D_80384FD0 = slot; D_80384490[D_80384FD0].projectileIndex = func_8033FA84(); @@ -253,10 +248,6 @@ void freeParticleByIndex(s32 arg0){ void commonParticle_add(ActorMarker *arg0, s32 arg1, FuncUnk40 arg2){ s32 tmp_v0 = commonParticle_findFree(); - // [port] Pool full returns -1; writing D_80384490[-1] corrupts whatever precedes it. - if(tmp_v0 < 0){ - return; - } D_80384490[tmp_v0].isInUse--; D_80384490[tmp_v0].unk38 = arg0; D_80384490[tmp_v0].unk3C = arg1; diff --git a/src/core2/fx/projectile_render.c b/src/core2/fx/projectile_render.c index cb562833c..54d8ccfce 100644 --- a/src/core2/fx/projectile_render.c +++ b/src/core2/fx/projectile_render.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CD6E0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_smoke.c b/src/core2/fx/projectile_smoke.c index 2e2a78cb6..4dd750152 100644 --- a/src/core2/fx/projectile_smoke.c +++ b/src/core2/fx/projectile_smoke.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CF090.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_sparkle.c b/src/core2/fx/projectile_sparkle.c index 8157fcd69..4bc192573 100644 --- a/src/core2/fx/projectile_sparkle.c +++ b/src/core2/fx/projectile_sparkle.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CECD0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_spawnfx.c b/src/core2/fx/projectile_spawnfx.c index c7b154631..5f943c7b3 100644 --- a/src/core2/fx/projectile_spawnfx.c +++ b/src/core2/fx/projectile_spawnfx.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CD3F0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/projectile_system.c b/src/core2/fx/projectile_system.c index 509b6321f..ef858ca10 100644 --- a/src/core2/fx/projectile_system.c +++ b/src/core2/fx/projectile_system.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B8860.c #include "core1/core1.h" #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/shrapnel.c b/src/core2/fx/shrapnel.c index 225f2a28d..b112945c6 100644 --- a/src/core2/fx/shrapnel.c +++ b/src/core2/fx/shrapnel.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/shrapnel.c #include #include "functions.h" #include "variables.h" @@ -157,7 +156,7 @@ void chshrapnel_update(Actor *this) { this->unk1C[2] = this->position[2]; this->unk1C[1] = func_80309B24(this->position) - 15.0f; this->position[1] = this->unk1C[1] - (sinf(this->lifetime_value * 4.0f) * 10.0f); - playerPosition_get(player_position); + _player_getPosition(player_position); switch (this->state) { case 1: chShrapnel_func_802D0A38(this); diff --git a/src/core2/fx/weather_emitter.c b/src/core2/fx/weather_emitter.c deleted file mode 100644 index 118eb4db3..000000000 --- a/src/core2/fx/weather_emitter.c +++ /dev/null @@ -1,188 +0,0 @@ -// BanjoDecomp: core2/code_D2180.c -#include -#include "functions.h" -#include "variables.h" - -extern void func_802F82F4(struct3s *, f32, f32, f32, f32); - -typedef struct { - s16 startState; - //u8 pad[0x2]; - bool (*shouldStartFunc)(Actor *); -} Struct_Core2_D2180_0; - -typedef struct { - Struct_Core2_D2180_0 *unk0; -} ActorLocal_core2_D2180; - -bool weatherParticle_isAlwaysActive(Actor *); -bool weatherParticle_shouldStartCCWHubLeafFalling(Actor *); -bool weatherParticle_isAlwaysActive(Actor *); -bool weatherParticle_shouldStartCCWHubRainFalling(Actor *); -bool weatherParticle_isAlwaysActive(Actor *); -bool weatherParticle_shouldStartCCWHubSnowFalling(Actor *); -void weatherParticle_update(Actor *this); -void func_80359424(Actor *this); -void func_80359454(Actor *this); - -/* .data */ -enum weatherParticle_state_enum { - WEATHERPARTICLE_STATE_0_NOT_INIT, - WEATHERPARTICLE_STATE_1_IDLE, - WEATHERPARTICLE_STATE_2_LEAF_FALLING, - WEATHERPARTICLE_STATE_3_RAINING, - WEATHERPARTICLE_STATE_4_SNOWING -}; - -Struct_Core2_D2180_0 D_80372940[] = { - {WEATHERPARTICLE_STATE_2_LEAF_FALLING, weatherParticle_isAlwaysActive}, - {WEATHERPARTICLE_STATE_2_LEAF_FALLING, weatherParticle_shouldStartCCWHubLeafFalling}, - {WEATHERPARTICLE_STATE_3_RAINING, weatherParticle_isAlwaysActive}, - {WEATHERPARTICLE_STATE_3_RAINING, weatherParticle_shouldStartCCWHubRainFalling}, - {WEATHERPARTICLE_STATE_4_SNOWING, weatherParticle_isAlwaysActive}, - {WEATHERPARTICLE_STATE_4_SNOWING, weatherParticle_shouldStartCCWHubSnowFalling} -}; - -ActorInfo leafEmitterCCWAutumn = { - 0x1C1, ACTOR_2AE_LEAF_EMITTER_CCW_AUTUMN, 0x0, - 0, NULL, - weatherParticle_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo leafEmitterCCWHub = { - 0x1C1, ACTOR_2AF_LEAF_EMITTER_CCW_HUB, 0x0, - 0, NULL, - weatherParticle_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo rainEmitterCCWSpring = { - 0x1C1, ACTOR_2B0_RAIN_EMITTER_CCW_SPRING, 0x0, - 0, NULL, - weatherParticle_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo rainEmitterCCWHub = { - 0x1C1, ACTOR_2B1_RAIN_EMITTER_CCW_HUB, 0x0, - 0, NULL, - weatherParticle_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo snowEmitterCCWWinter = { - 0x1C1, ACTOR_2B2_SNOW_EMITTER_CCW_WINTER, 0x0, - 0, NULL, - weatherParticle_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo snowEmitterCCWHub = { - 0x1C1, ACTOR_2B3_SNOW_EMITTER_CCW_HUB, 0x0, - 0, NULL, - weatherParticle_update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80372A48 = { - 0x1C1, ACTOR_316_UNKNOWN, 0x0, - 0, NULL, - func_80359424, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80372A6C = { - 0x1C1, ACTOR_317_UNKNOWN, 0x0, - 0, NULL, - func_80359454, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -/* .code */ -bool weatherParticle_isAlwaysActive(Actor *this){ - return TRUE; -} - -// Player's Z Position -bool weatherParticle_shouldStartCCWHubLeafFalling(Actor *this){ - f32 plyr_pos[3]; - - player_getPosition(plyr_pos); - return (plyr_pos[2] < -1700.0f); -} - -bool weatherParticle_shouldStartCCWHubRainFalling(Actor *this){ - f32 plyr_pos[3]; - - player_getPosition(plyr_pos); - return (1700.0f < plyr_pos[2]); -} - -bool weatherParticle_shouldStartCCWHubSnowFalling(Actor *this){ - f32 plyr_pos[3]; - - player_getPosition(plyr_pos); - return (1700.0f < plyr_pos[0]); -} - -void weatherParticle_setState(Actor *this, s32 next_state){ - ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; - struct3s *sp20; // [port] pointer-width - - if(next_state == WEATHERPARTICLE_STATE_2_LEAF_FALLING) - func_802F8C90(func_802F7C38()); - - if(this->state == WEATHERPARTICLE_STATE_2_LEAF_FALLING) - func_802F8CB0(func_802F7C38()); - - if(next_state == WEATHERPARTICLE_STATE_3_RAINING){ - sp20 = func_802F7C7C(); - func_802F8338(sp20); - if(local->unk0->shouldStartFunc == weatherParticle_isAlwaysActive) - func_802F82F4(sp20, 5.0f, 30.0f, 5.0f, 30.0f); - } - - if(this->state == WEATHERPARTICLE_STATE_3_RAINING) - func_802F8358(func_802F7C7C()); - - if(next_state == WEATHERPARTICLE_STATE_4_SNOWING){ - func_802F7CC0(); - func_802F90F4(); - } - if(this->state == WEATHERPARTICLE_STATE_4_SNOWING){ - func_802F7CC0(); - func_802F9114(); - } - - this->state = next_state; -} - -void weatherParticle_update(Actor *this){ - ActorLocal_core2_D2180 * local = (ActorLocal_core2_D2180 *) &this->local; - if(!this->volatile_initialized){ - this->volatile_initialized = TRUE; - local->unk0 = D_80372940 + (this->modelCacheIndex - ACTOR_2AE_LEAF_EMITTER_CCW_AUTUMN); - weatherParticle_setState(this, WEATHERPARTICLE_STATE_1_IDLE); - } - if(this->state == WEATHERPARTICLE_STATE_1_IDLE){ - if(local->unk0->shouldStartFunc(this)){ - weatherParticle_setState(this, local->unk0->startState); - } - } - if(this->state != WEATHERPARTICLE_STATE_1_IDLE){ - if(!local->unk0->shouldStartFunc(this)){ - weatherParticle_setState(this, WEATHERPARTICLE_STATE_1_IDLE); - } - } -} - -void func_80359424(Actor *this){ - if(func_803292E0(this)) - func_802F7D44(); -} - -void func_80359454(Actor *this){ - if(func_803292E0(this)) - func_802F7DE4(); -} diff --git a/src/core2/fx/whipcrack.c b/src/core2/fx/whipcrack.c index 72cddba8b..92b8d56f0 100644 --- a/src/core2/fx/whipcrack.c +++ b/src/core2/fx/whipcrack.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/whipcrack.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/gameSelect.c b/src/core2/gameSelect.c index 8238aae99..22c1322a7 100644 --- a/src/core2/gameSelect.c +++ b/src/core2/gameSelect.c @@ -1,13 +1,11 @@ -// BanjoDecomp: core2/ch/gameSelect.c #include #include "functions.h" #include "variables.h" -#include "ch/gameSelect.h" #include "core2/modelRender.h" #include "core2/gc/zoombox.h" -#include "core2/quiz/storage.h" +#include "core2/quiz_storage.h" #include "port/Romhack/RomhackConfig.h" #include "port/Patches/Patches.h" @@ -73,7 +71,7 @@ ActorAnimationInfo banjoGameboyAnimations[] = { {0x24F, 0.6f}, {0x24D, 2.0f} }; -ActorInfo gameSelect_banjoSleeping = { 0xE4, 0x195, 0x532, 0x1, banjoGameboyAnimations, gameSelect_initAndUpdate, actor_update_func_80326224, gameSelect_zoomboxDraw, 0, 0, 0.0f, 0}; +ActorInfo D_80365E58 = { 0xE4, 0x195, 0x532, 0x1, banjoGameboyAnimations, gameSelect_initAndUpdate, actor_update_func_80326224, gameSelect_zoomboxDraw, 0, 0, 0.0f, 0}; ActorAnimationInfo D_80365E7C[] = { {0x000, 0.0f}, @@ -83,7 +81,7 @@ ActorAnimationInfo D_80365E7C[] = { {0x252, 0.67f}, {0x250, 4.5f}, }; -ActorInfo gameSelect_banjoGameboy = { 0xE5, 0x196, 0x532, 0x1, D_80365E7C, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80365EAC = { 0xE5, 0x196, 0x532, 0x1, D_80365E7C, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; ActorAnimationInfo D_80365ED0[] = { {0x000, 0.0f}, @@ -93,19 +91,12 @@ ActorAnimationInfo D_80365ED0[] = { {0x24C, 1.0f}, {0x24A, 1.0f} }; -ActorInfo gameSelect_banjoCooking = { 0xE6, 0x197, 0x532, 0x1, D_80365ED0, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80365F00 = { 0xE6, 0x197, 0x532, 0x1, D_80365ED0, gameSelect_update, actor_update_func_80326224, gameSelect_draw, 0, 0, 0.0f, 0}; -// Yes, Gaming Chair is before Kitchen -enum chgameselect_savefile_e { - CH_GAME_SELECT_SAVEFILE_0_BED, - CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR, - CH_GAME_SELECT_SAVEFILE_2_KITCHEN -}; - /* .bss */ s32 mm_hut_smash_count; -u32 chtreasureHunt_puzzleCurrentStep; +u32 CH_TREASUREHUNT_PUZZLE_CURRENT_STEP; struct FF_StorageStruct* ffStorage; s32 mmhut_smashCount; u8 gCompletedBottlesBonusGames[7]; // bottle bonus puzzle? @@ -140,16 +131,16 @@ f32 D_8037DD34; /* .code */ Actor *gameSelect_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ s32 sp1C = marker->id - 0xe4; - modelRender_setAppendageVisibility(3, sp1C); - modelRender_setAppendageVisibility(1, 1); - modelRender_setAppendageVisibility(4, 1); - modelRender_setAppendageVisibility(9, 1); - modelRender_setAppendageVisibility(5, 0); - modelRender_setAppendageVisibility(8, 0); - modelRender_setAppendageVisibility(6, 0); - modelRender_setAppendageVisibility(7, 0); - modelRender_setAppendageVisibility(0xC, 1); - modelRender_setAppendageVisibility(0xF, 1); + func_8033A45C(3, sp1C); + func_8033A45C(1, 1); + func_8033A45C(4, 1); + func_8033A45C(9, 1); + func_8033A45C(5, 0); + func_8033A45C(8, 0); + func_8033A45C(6, 0); + func_8033A45C(7, 0); + func_8033A45C(0xC, 1); + func_8033A45C(0xF, 1); if(sp1C == D_80365E00){ modelRender_setEnvColor(0xFF, 0xFF, 0xFF, 0xFF); } @@ -224,13 +215,13 @@ void setGameInformationZoombox(s32 gamenum){ strcpy(upperTextLine, ""); strcat(upperTextLine, sGamePrefix[lang]); switch(gamenum){ - case CH_GAME_SELECT_SAVEFILE_0_BED: //L802C4820 + case 0: //L802C4820 strIToA(upperTextLine, 1); break; - case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: //L802C4838 + case 1: //L802C4838 strIToA(upperTextLine, 3); break; - case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: //L802C484C + case 2: //L802C484C strIToA(upperTextLine, 2); break; }//L802C4858 @@ -259,13 +250,13 @@ void setGameInformationZoombox(s32 gamenum){ strcpy(upperTextLine, ""); strcat(upperTextLine, sGamePrefix[lang]); switch (gamenum){ - case CH_GAME_SELECT_SAVEFILE_0_BED: + case 0: strIToA(upperTextLine, 1); break; - case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: + case 1: strIToA(upperTextLine, 3); break; - case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: + case 2: strIToA(upperTextLine, 2); break; }//L802C4A40 @@ -285,8 +276,6 @@ void setGameInformationZoombox(s32 gamenum){ void eraseGame(s32 arg0){ gameFile_clear(arg0); - // [port] The clear only zeroes the slot in RAM; also delete the file. - CALL_EVENT(OnGameFileErase, arg0); setGameInformationZoombox(arg0); } @@ -360,7 +349,7 @@ void gameSelect_update(Actor *this){ __spawnQueue_add_1((GenFunction_1)spawnGameSelectProps, (uintptr_t)this->marker); func_802C7318(this); this->unk130 = func_802C71F0; - if(sp84 == CH_GAME_SELECT_SAVEFILE_0_BED){ + if(sp84 == 0){ func_802C75A0(this, 1); func_802C74F4(this, 0, 1.0f); func_802C74F4(this, 1, 1.0f); @@ -381,20 +370,20 @@ void gameSelect_update(Actor *this){ case 2: case 5: switch(sp84){ - case CH_GAME_SELECT_SAVEFILE_0_BED://L802C4D8C + case 0://L802C4D8C if(actor_animationIsAt(this, 0.1f)) sfxsource_play(SFX_5D_BANJO_RAAOWW, 8000); if(actor_animationIsAt(this, 0.7f)) sfxsource_play(SFX_5E_BANJO_PHEWWW, 8000); break; - case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR://L802C4DD0 + case 1://L802C4DD0 if(randf() < 0.1){ // if(randf() < D_80376118){ gcsfx_playWithPitch(MIN(2.0f, randf() *3.0f) + 311.0f, 1.0f, 12000); } break; - case CH_GAME_SELECT_SAVEFILE_2_KITCHEN://L802C4E74 + case 2://L802C4E74 if(randf() < 0.03){ gcsfx_playWithPitch(0x3ed, randf()*0.3 + 0.7, 15000); } @@ -405,7 +394,7 @@ void gameSelect_update(Actor *this){ if(!func_8038AAB0()){ switch(this->state){ case 1://L802C4F10 - if(sp84 == CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR){ + if(sp84 == 1){ sfxsource_play(SFX_136_GAMEBOY_STARTUP, 15000); timedFunc_set_3(0.25f, (GenFunction_3)comusic_8025AB44, COMUSIC_73_GAMEBOY, -1, 2000); func_8025A58C(0, 2000); @@ -415,7 +404,7 @@ void gameSelect_update(Actor *this){ func_8025A58C(-1, 2000); } - if(sp84 == CH_GAME_SELECT_SAVEFILE_2_KITCHEN){ + if(sp84 == 2){ D_8037DD28 = func_802F9AA8(SFX_12B_BOILING_AND_BUBBLING); func_802F9F80(D_8037DD28, 0.5f, 9000000000.0f, 0.5f); func_802F9DB8(D_8037DD28, 0.9f, 0.9f, 0.0f); @@ -452,15 +441,14 @@ void gameSelect_update(Actor *this){ chBottlesBonus_resetCompleted(); gameFile_load(gSelectedGameNum); port_syncBottlesBonusIndex(); - CALL_EVENT(OnGameStart); - if(EventSystem_Should(VB_GAMESELECT_START_NEW_GAME, !gameFile_isNotEmpty(sp84), sp84)){ + if(!gameFile_isNotEmpty(sp84)){ s32 skipIntro = 0; CALL_EVENT(OnNewGame, &skipIntro); if (skipIntro) { timedFunc_set_2(0.0f, (GenFunction_2)warp_lairEnterLairFromSMLevel, 0, 0); timedFunc_set_1(0.0f, (GenFunction_1)gsworld_setEnableUpdate, 1); } else { - // [port] Romhacks can override the new-game boot map + // [port] BB romhacks can override the new-game boot map s32 newGameMap = port_getRomhackNewGameMap(); if (newGameMap < 0) { newGameMap = MAP_85_CS_SPIRAL_MOUNTAIN_3; @@ -468,18 +456,15 @@ void gameSelect_update(Actor *this){ timedFunc_set_3(0.0f, (GenFunction_3)transitionToMap, newGameMap, 0, 1); if (port_getRomhackKnowAllMoves() >= 0) { ability_setAllLearned(-1); + ability_setAllUsed(-1); } } } else{//L802C511C sp44 = 0.0f; - if(this->state == 4 && (sp84 == CH_GAME_SELECT_SAVEFILE_0_BED || sp84 == CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR)) + if(this->state == 4 && (sp84 == 0 || sp84 == 1)) sp44 = 0.25f; - // [port] Romhacks can replace the resume transition outright - if(port_getRomhackResumeWarpFunc() != NULL){ - timedFunc_set_2(sp44, (GenFunction_2)port_getRomhackResumeWarpFunc(), 0, 0); - } - else if(chmole_learnedAllSpiralMountainAbilities() && fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE)){ + if(chmole_learnedAllSpiralMountainAbilities() && fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE)){ timedFunc_set_2(sp44, (GenFunction_2)warp_lairEnterLairFromSMLevel, 0, 0); } else{//L802C5188 @@ -508,22 +493,22 @@ void gameSelect_update(Actor *this){ if(gameFile_isNotEmpty(sp84)){ if(randf() < 0.1){ switch(sp84){ - case CH_GAME_SELECT_SAVEFILE_0_BED://L802C52B8 + case 0://L802C52B8 sfxsource_play(SFX_31_BANJO_OHHWAAOOO, 28000); - gcsfx_play(SFX_135_CARTOONY_SPRING); + gcsfx_playAtSampleRate(SFX_135_CARTOONY_SPRING); timedFunc_set_2(0.4f, (GenFunction_2)sfxsource_play, SFX_13A_GLASS_BREAKING_7, 0x7fff); timedFunc_set_2(0.9f, (GenFunction_2)sfxsource_play, SFX_150_PORCELAIN_CRASH, 0x7fff); timedFunc_set_2(1.0f, (GenFunction_2)sfxsource_play, SFX_151_CAT_MEOW, 0x7fff); break; - case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR://L802C5320 + case 1://L802C5320 timedFunc_set_2(0.4f, (GenFunction_2)sfxsource_play, SFX_31_BANJO_OHHWAAOOO, 28000); timedFunc_set_2(0.2f, (GenFunction_2)sfxsource_play, SFX_E_SHOCKSPRING_BOING, 28000); - gcsfx_play(SFX_2D_KABOING); + gcsfx_playAtSampleRate(SFX_2D_KABOING); break; - case CH_GAME_SELECT_SAVEFILE_2_KITCHEN://L802C5364 + case 2://L802C5364 timedFunc_set_2(0.15f, (GenFunction_2)sfxsource_play, SFX_32_BANJO_EGHEE, 28000); sfxsource_play(SFX_3F6_RUBBING, 28000); - gcsfx_play(SFX_8F_SNOWBALL_FLYING); + gcsfx_playAtSampleRate(SFX_8F_SNOWBALL_FLYING); break; }//L802C5394 subaddie_set_state(this, 4); @@ -537,10 +522,10 @@ void gameSelect_update(Actor *this){ sfxsource_play(SFX_4F_BANJO_WAHOO, 28000); subaddie_set_state(this, 3); }//L802C53E8 - if(sp84 == CH_GAME_SELECT_SAVEFILE_0_BED) + if(sp84 == 0) func_802C75A0(this, 2); - if(sp84 == CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR) + if(sp84 == 1) comusic_8025AB44(COMUSIC_73_GAMEBOY, 0, 4000); func_8025A58C(0, 0x1f4); @@ -553,28 +538,28 @@ void gameSelect_update(Actor *this){ if(sp54[0] < 0.0f){ D_8037DCEC = 1; switch(D_80365E00){ - case CH_GAME_SELECT_SAVEFILE_0_BED: + case 0: D_8037DCEC = 0; break; - case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: - D_80365E00 = CH_GAME_SELECT_SAVEFILE_2_KITCHEN; + case 1: + D_80365E00 = 2; break; - case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: - D_80365E00 = CH_GAME_SELECT_SAVEFILE_0_BED; + case 2: + D_80365E00 = 0; break; } } else{//L802C54D4 D_8037DCEC = 1; switch(D_80365E00){ - case CH_GAME_SELECT_SAVEFILE_0_BED: - D_80365E00 = CH_GAME_SELECT_SAVEFILE_2_KITCHEN; + case 0: + D_80365E00 = 2; break; - case CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR: + case 1: D_8037DCEC = 0; break; - case CH_GAME_SELECT_SAVEFILE_2_KITCHEN: - D_80365E00 = CH_GAME_SELECT_SAVEFILE_1_GAMING_CHAIR; + case 2: + D_80365E00 = 1; break; } }//L802C550C @@ -617,6 +602,7 @@ void gameSelect_update(Actor *this){ ); if(this->marker->unk14_21) { osViBlack(0); + port_setViBlack(0); } }//L802C5734 } @@ -647,8 +633,8 @@ void gameSelect_initAndUpdate(Actor * this){ D_8037DCEC = 0; debugScoreStates(); clearScoreStates(); - D_8037DCE8 = CH_GAME_SELECT_SAVEFILE_0_BED; - D_80365E00 = CH_GAME_SELECT_SAVEFILE_0_BED; + D_8037DCE8 = 0; + D_80365E00 = 0; cameraPositions[1][0] = D_80365DD0[0][0]; cameraPositions[1][1] = D_80365DD0[0][1]; cameraPositions[1][2] = D_80365DD0[0][2]; @@ -674,11 +660,6 @@ void gameSelect_saveAndExit(void){ s32 sp1C = level_get(); s32 t6 = gsworld_getMap() == MAP_83_CS_GAME_OVER_MACHINE_ROOM; s32 a1 = (0 < sp1C && sp1C < 0xd); - // [port] Permadeath erases the save on death; the game over path routes back through - // here, and saving would write the still-live game state over the erased slot. - if(!EventSystem_Should(VB_SAVE_AND_EXIT, true)){ - return; - } if( a1 || t6) { if(D_80365E00 != -1 && !func_802E4A08() && gsworld_getMap() != MAP_91_FILE_SELECT){ diff --git a/src/core2/gameloop.c b/src/core2/gameloop.c index c48c00169..8ce87f1ca 100644 --- a/src/core2/gameloop.c +++ b/src/core2/gameloop.c @@ -1,12 +1,8 @@ -// BanjoDecomp: core2/code_5C870.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -extern void Graphics_PushFrame(Gfx* data); -extern void Framebuffer_ReadbackGPU(int bufferIndex); - #include "gc/gctransition.h" #include "bk_time.h" #include "port/Patches/Patches.h" @@ -19,10 +15,10 @@ extern void func_8025A2B0(void); extern void func_8025A430(s32, s32, s32); extern void gsworld_setEnableUpdate(s32); extern void func_8034BB90(void); -extern void picturebox_spawn(void); +extern void func_8030C27C(void); extern void func_80321C34(void); extern void func_8030ED0C(void); -extern void coMusicPlayer_update(void); +extern void comusicPlayer_update(void); enum transition_e { TRANSITION_0_NONE @@ -115,46 +111,50 @@ void func_802E38E8(enum map_e map, s32 exit, s32 reset_on_load){ void func_802E398C(s32 arg0) { gsworld_free(); func_8030ED0C(); - coMusicPlayer_update(); + comusicPlayer_update(); if (arg0 != 0) { func_802E3854(); } } -void func_802E39D0(Gfx **gfx, Mtx **mtx, Vtx **vtx, s32 framebuffer_idx, bool arg4) { - Mtx* mtx_start = *mtx; - Vtx* vtx_start = *vtx; +void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4){ + Mtx* m_start = *mptr; + Vtx* v_start = *vptr; - setupFramebufferForGamemode(gfx, framebuffer_idx); + scissorBox_SetForGameMode(gdl, framebuffer_idx); D_8037E8E0.unkC = false; port_mirror_beginScene(); - gsworld_draw(gfx, mtx, vtx); - CALL_EVENT(OnWorldDraw, gfx, mtx, vtx); + gsworld_draw(gdl, mptr, vptr); + CALL_EVENT(OnWorldDraw, gdl, mptr, vptr); port_mirror_endScene(); - port_mirror_undoProjection(gfx, mtx); + port_mirror_undoProjection(gdl, mptr); + if (port_shouldCaptureTransition()) { + port_captureTransitionFb(gdl); + } if(!arg4){ func_802E67AC(); func_802E3BD0(getActiveFramebuffer()); func_802E67C4(); - func_802E5F10(gfx); + func_802E5F10(gdl); } - - if ((D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE) && (D_8037E8E0.unk19 != 6) && (D_8037E8E0.unk19 != 5)) { - if (port_shouldCaptureTransition()) { - port_captureTransitionFb(gfx); - } - gctransition_draw(gfx, mtx, vtx); + if( D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE + && D_8037E8E0.unk19 != 6 + && D_8037E8E0.unk19 != 5 + ){ + gctransition_draw(gdl, mptr, vptr); } // [port] Return rendering to main FB after scene draw + transitions for // SNS/Bottles modes. Must come AFTER gctransition_draw so the transition // fade renders into the aux FB (visible on the picture), not the main FB. if (D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS || D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE) { - gsSPResetFB((*gfx)++); + gsSPResetFB((*gdl)++); } - if ((D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS) || (D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE)) { - picturebox_resetScissorBoxAndFramebuffer(gfx, mtx, vtx); + if( D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS + || D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE + ){ + func_8030C2D4(gdl, mptr, vptr); } // [port] Skip all HUD/overlay draws while pause menu is capturing the @@ -163,44 +163,42 @@ void func_802E39D0(Gfx **gfx, Mtx **mtx, Vtx **vtx, s32 framebuffer_idx, bool ar bool capturing = gcpausemenu_isCapturing(); if(!game_is_frozen() && gsworld_getEnableDraw() && !capturing){ - core2_A5BC0_drawScreenOverlayMarkers(gfx, mtx, vtx); + func_8032D474(gdl, mptr, vptr); } - gcpausemenu_draw(gfx, mtx, vtx); + gcpausemenu_draw(gdl, mptr, vptr); if(!game_is_frozen() && !capturing){ - // dummy_func_8025AFC0(gfx, mtx, vtx); + dummy_func_8025AFC0(gdl, mptr, vptr); } if (!capturing) { - gcdialog_draw(gfx, mtx, vtx); + gcdialog_draw(gdl, mptr, vptr); } if(!game_is_frozen() && !capturing){ - itemPrint_draw(gfx, mtx, vtx); + itemPrint_draw(gdl, mptr, vptr); } if (!capturing) { - CALL_EVENT(OnHudDraw, gfx, mtx, vtx); - printbuffer_draw(gfx, mtx, vtx); + printbuffer_draw(gdl, mptr, vptr); } - if ((D_8037E8E0.game_mode != GAME_MODE_A_SNS_PICTURE) || (D_8037E8E0.unk19 == 6) || (D_8037E8E0.unk19 == 5)) { - // [port] Snapshot the composed frame for the falling-jiggy piece textures. - if (port_shouldCaptureTransition()) { - port_captureTransitionFb(gfx); - } - gctransition_draw(gfx, mtx, vtx); + if( D_8037E8E0.game_mode != GAME_MODE_A_SNS_PICTURE + || D_8037E8E0.unk19 == 6 + || D_8037E8E0.unk19 == 5 + ){ + gctransition_draw(gdl, mptr, vptr); } // [port] Populate gFramebuffers from the GPU via gDPReadFB at native resolution. // Transitions and particles read from gFramebuffers during game logic. // On N64, gFramebuffers was the render target directly; on PC the GPU renders // to its own buffer, so we read it back here when requested. if (port_consumeReadbackRequest()) { - gDPReadFB((*gfx)++, 0, (u16 *)gFramebuffers[getActiveFramebuffer()], + gDPReadFB((*gdl)++, 0, (u16 *)gFramebuffers[getActiveFramebuffer()], 0, 0, gFramebufferWidth, gFramebufferHeight, 1); } - core1_15B30_finishDList(gfx); - osWritebackDCache(mtx_start, sizeof(Mtx)*( *mtx - mtx_start)); - osWritebackDCache(vtx_start, sizeof(Vtx)*( *vtx - vtx_start)); + core1_15B30_finishDList(gdl); + osWritebackDCache(m_start, sizeof(Mtx)*( *mptr - m_start)); + osWritebackDCache(v_start, sizeof(Vtx)*( *vptr - v_start)); } void func_802E3BD0(s32 frame_buffer_indx){ @@ -231,10 +229,10 @@ void game_setMode(enum game_mode_e next_mode, s32 arg1){ //L802E3C84 if(next_mode == GAME_MODE_8_BOTTLES_BONUS || next_mode == GAME_MODE_A_SNS_PICTURE){ - picturebox_init(); + func_8030C1A0(); } else{ - picturebox_free(); + func_8030C204(); }//L802E3CB4 D_8037E8E0.game_mode = next_mode; @@ -293,7 +291,6 @@ void func_802E3E7C(enum game_mode_e mode){ s32 sp28; s32 prev_mode; s32 prev_map; - s32 outgoing_mode = D_8037E8E0.game_mode; // [port] game_setMode below overwrites it core1_15B30_sendMesg3ToRenderThread(); sp34 = D_8037E8E0.unk18; @@ -303,16 +300,13 @@ void func_802E3E7C(enum game_mode_e mode){ prev_mode = D_8037E8E0.unk0; game_setMode(GAME_MODE_2_UNKNOWN, 0); if(!volatileFlag_getAndSet(VOLATILE_FLAG_21, 0) || map_getLevel(gsworld_getMap()) == map_getLevel(D_8037E8E0.map)){ - if(!volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) - && EventSystem_Should(VB_MAP_SAVESTATE_USE, true, outgoing_mode)) + if(!volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE)) mapSavestate_save(gsworld_getMap()); } func_802E398C(1); prev_map = gsworld_getMap(); func_802E38E8(map, sp28, sp34); - if(EventSystem_Should(VB_MAP_SAVESTATE_USE, true, mode)){ - mapSavestate_apply(map); - } + mapSavestate_apply(map); D_8037E8E0.unk0 = prev_mode; game_setMode(mode, sp30); jiggylist_map_actors(); @@ -324,21 +318,26 @@ s32 func_802E3F80(void){ return D_8037E8E0.unk0; } -void game_draw(bool arg0) { - Gfx *gfx, *gfx_start, *gfx_end; +extern void Graphics_PushFrame(Gfx* data); +extern void Framebuffer_ReadbackGPU(int bufferIndex); + +void game_draw(s32 arg0){ + Gfx *gfx; + Gfx *gfx_start; + Gfx *sp2C; Mtx *mtx; Mtx *mtx_start; Vtx *vtx; Vtx *vtx_start; - if (arg0) { + if(arg0) { scissorBox_setDefault(); } - graphicscache_swapAndGetStacks(&gfx, &mtx, &vtx); + getGraphicsStacks(&gfx, &mtx, &vtx); - if (D_8037E8E0.unkC == TRUE) { // BUG: Compares explicit for integral value of TRUE, instead for true-ness - graphicscache_swapAndGetStacks(&gfx, &mtx, &vtx); + if(D_8037E8E0.unkC == 1){ + getGraphicsStacks(&gfx, &mtx, &vtx); } gfx_start = gfx; @@ -347,11 +346,6 @@ void game_draw(bool arg0) { func_802E39D0(&gfx, &mtx, &vtx, getActiveFramebuffer(), arg0); - // [port] Frame submission gate - if (!EventSystem_Should(VB_PICTUREBOX_SUBMIT_FRAME, true, (s32)(gfx - gfx_start))) { - return; - } - graphicsCache_checkFrame(gfx_start, gfx, mtx_start, mtx, vtx_start, vtx); // Lighthouse [Port] not sure if this should be here or after the following block @@ -361,11 +355,11 @@ void game_draw(bool arg0) { Framebuffer_ReadbackGPU(getActiveFramebuffer()); if(D_8037E8E0.unkC == 0){ - gfx_end = gfx; + sp2C = gfx; viMgr_func_8024C1DC(); - core1_15B30_addF3DEXTaskData_40000000(gfx_start, gfx_end); + core1_15B30_addF3DEXTaskData_40000000(gfx_start, sp2C); - if (arg0) { + if(arg0) { scissorBox_setDefault(); } } @@ -385,8 +379,6 @@ void transitionToMap(enum map_e map, s32 exit, s32 transition){ } void func_802E40A8(s32 map, s32 exit){ - // [port] Romhack gate: listeners may rewrite the requested destination. - EventSystem_Should(VB_MAP_CHANGE_REQUEST, true, &map, &exit); D_8037E8E0.unk18 = 1; D_8037E8E0.map = map; D_8037E8E0.exit = exit; @@ -397,8 +389,6 @@ void func_802E40C4( s32 arg0){ } void func_802E40D0(s32 map, s32 exit){ - // [port] Romhack gate: listeners may rewrite the requested destination. - EventSystem_Should(VB_MAP_CHANGE_REQUEST, true, &map, &exit); D_8037E8E0.unk18 = 0; D_8037E8E0.map = map; D_8037E8E0.exit = exit; @@ -430,13 +420,13 @@ void func_802E4170(void){ timedFuncQueue_free(); func_802F9C48(); modelRender_free(); - depthbuffer_stub(); + depthBuffer_stub(); func_802E398C(0); func_8030AFD8(0); func_80321854(); debugScoreStates(); animCache_free(); - coMusicPlayer_free(); + comusicPlayer_free(); func_8030D8DC(); } @@ -445,12 +435,12 @@ void func_802E4214(enum map_e map_id){ D_8037E8E0.unk19 = D_8037E8E0.unk18 = 0; D_8037E8E0.map = D_8037E8E0.exit = D_8037E8E0.unk17 = 0; D_8037E8E0.unk1B = D_8037E8E0.unk1A = 0; - D_8037E8E0.unkC = FALSE; + D_8037E8E0.unkC = 0; D_8037E8E0.unk1C = 0; savedata_init(); sns_save_and_update_global_data(); func_8030D86C(); - coMusicPlayer_init(); + comusicPlayer_init(); func_80322764(); timedFuncQueue_init(); func_802F9CD8(); @@ -462,7 +452,7 @@ void func_802E4214(enum map_e map_id){ func_802E5F38(); defragManager_init(); modelRender_init(); - depthbuffer_enable(TRUE); + func_80253428(1); animCache_init(); viewport_reset(); viewport_setNearAndFar(1.0f, 10000.0f); @@ -490,9 +480,6 @@ void func_802E4384(void){ } else{ func_8033DC18(); - // [port] Latch this cutscene frame's stutter before anything reads it, so the - // time delta below and the renderer's frame budget agree for the whole tick. - port_tickCutsceneStutter(); // [port] Use a fixed 2-VI timestep for normal gameplay. s32 viDivisor = viMgr_func_8024BFA0(); func_8033DC20(); // always consume wall-clock to keep last_ticks fresh @@ -574,7 +561,6 @@ bool func_802E4424(void) { return false; case 7: /* switch 1 */ - port_beginDemoAudioHold(); func_8034B8C0(D_8037E8E0.map, D_8037E8E0.exit); func_802E3E7C(GAME_MODE_8_BOTTLES_BONUS); return false; @@ -606,11 +592,11 @@ bool func_802E4424(void) { sp1C = gsworld_update(); func_80321C34(); func_8030ED0C(); - coMusicPlayer_update(); + comusicPlayer_update(); switch (D_8037E8E0.game_mode) { case GAME_MODE_8_BOTTLES_BONUS: case GAME_MODE_A_SNS_PICTURE: - picturebox_spawn(); + func_8030C27C(); /* fallthrough */ case GAME_MODE_7_ATTRACT_DEMO: /* fallthrough */ @@ -699,7 +685,7 @@ s32 game_defrag(void){ gcpausemenu_defrag(); switch(overlayManager_getLoadedID()){ case OVERLAY_2_WHALE: - maClanker_defrag(); + func_803894A0(); break; case OVERLAY_D_WITCH: code_C9E70_defrag(); diff --git a/src/core2/gamestate.c b/src/core2/gamestate.c index b8534231b..0ea5ed961 100644 --- a/src/core2/gamestate.c +++ b/src/core2/gamestate.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_BEF20.c #include #include "core1/core1.h" #include "functions.h" @@ -30,12 +29,7 @@ bool func_80347A4C(void); /* .code */ void func_80345EB0(enum item_e item){ if(func_802FAFE8(item)){ - // [port] Pin the Bottles Bonus hourglass for timer consistency - f32 dt = time_getDelta(); - if(item == ITEM_0_HOURGLASS_TIMER && getGameMode() == GAME_MODE_8_BOTTLES_BONUS){ - dt = 1.0f / 30.0f; - } - item_adjustByDiffWithHud(item, (s32)(-dt*(float)(FRAMERATE) * 1.1)); + item_adjustByDiffWithHud(item, (s32)(-time_getDelta()*60.0f * 1.1)); }else{ code_73640_printItemCount(item); } @@ -59,7 +53,7 @@ s32 item_getCount(enum item_e item){ } // func_80345FB4 -s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent){ +s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud){ // Modifies the count of an item by the diff // no_hud determines whether the HUD pops up during the adjustment s32 oldVal; @@ -99,7 +93,7 @@ s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent){ sp34 = ((fileProgressFlag_get(FILEPROG_B9_DOUBLE_HEALTH))? 2 : 1); D_80385F30[ITEM_15_HEALTH_TOTAL] = MIN(sp34*8, D_80385F30[ITEM_15_HEALTH_TOTAL]); D_80385F30[ITEM_14_HEALTH]= MIN(D_80385F30[ITEM_15_HEALTH_TOTAL], D_80385F30[ITEM_14_HEALTH]); - D_80385F30[ITEM_17_AIR] = MIN(VER_SELECT(3600, 3000, 0, 0), D_80385F30[ITEM_17_AIR]); + D_80385F30[ITEM_17_AIR] = MIN(3600, D_80385F30[ITEM_17_AIR]); D_80385F30[ITEM_25_MUMBO_TOKEN_TOTAL] = D_80385F30[ITEM_1C_MUMBO_TOKEN]; D_80385F30[ITEM_16_LIFE] = MIN(0xFF, D_80385F30[ITEM_16_LIFE]); @@ -181,9 +175,6 @@ s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent){ D_80385F30[ITEM_2B_UNKNOWN] += diff; break; } - if (triggerEvent) { - CALL_EVENT(OnItemCountChanged, item, D_80385F30[item]); - } return D_80385F30[item]; } @@ -191,22 +182,18 @@ s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent){ s32 item_adjustByDiffWithHud(enum item_e item, s32 diff){ // Modifies the count of an item by the diff // Displays the HUD during the adjustment - return item_adjustByDiff(item, diff, 0, 1); + return item_adjustByDiff(item, diff, 0); } // item_adjustByDiffWithoutHud void item_adjustByDiffWithoutHud(enum item_e item, s32 diff){ // Modifies the count of an item by the diff // Does not display the HUD during the adjustment - item_adjustByDiff(item, diff, 1, 1); -} - -void item_setEx(s32 item, s32 val, s32 triggerEvent){ - item_adjustByDiff(item, val - item_getCount(item), 0, triggerEvent); + item_adjustByDiff(item, diff, 1); } void item_set(s32 item, s32 val){ - item_setEx(item, val, 1); + item_adjustByDiffWithHud(item, val - item_getCount(item)); } // item_setMaxCount @@ -228,7 +215,7 @@ void item_setItemsStartCounts(void){ D_80385F30[ITEM_10_GOLD_FEATHER] = 0; D_80385F30[ITEM_14_HEALTH] = D_80385F30[ITEM_15_HEALTH_TOTAL] = 5; D_80385F30[ITEM_16_LIFE] = 3; - D_80385F30[ITEM_17_AIR] = VER_SELECT(3600, 3000, 0, 0); + D_80385F30[ITEM_17_AIR] = 3600; D_80385F30[ITEM_1C_MUMBO_TOKEN] = 0; D_80385F30[0x2B] = 0; D_80385F30[ITEM_26_JIGGY_TOTAL] = 0; @@ -248,7 +235,7 @@ void itemscore_levelReset(enum level_e level){ D_80385F30[ITEM_C_NOTE] = 0; D_80385F30[ITEM_E_JIGGY] = jiggyscore_leveltotal(level); D_80385F30[ITEM_12_JINJOS] = 0; - D_80385F30[ITEM_17_AIR] = VER_SELECT(3600, 3000, 0, 0); + D_80385F30[ITEM_17_AIR] = 3600; D_80385F30[ITEM_18_GOLD_BULLIONS] = 0; D_80385F30[ITEM_19_ORANGE] = 0; D_80385F30[ITEM_23_ACORNS] = 0; @@ -331,16 +318,16 @@ void func_803465E4(void){ D_80385FEC = MAX(0.0, D_80385FEC - time_getDelta()); }//L80346870 if( (!is_in_polluted_or_winter_water && is_underwater) || (is_in_polluted_or_winter_water && is_on_water_surface) ){//L80346894 - item_adjustByDiffWithHud(ITEM_17_AIR, (s32)((f64)((-time_getDelta())*(float)(FRAMERATE))*1.1)); + item_adjustByDiffWithHud(ITEM_17_AIR, (s32)((f64)((-time_getDelta())*60.0f)*1.1)); } else{ if(is_in_polluted_or_winter_water && is_underwater){//L803468D8 - item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(f64)((-time_getDelta()*(float)(FRAMERATE))*2.1)); + item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(f64)((-time_getDelta()*60.0f)*2.1)); }//L80346930 if(!is_in_polluted_or_winter_water || D_80385FEC == 0.0f){ - if(!D_80385FE4 && D_80385F30[ITEM_17_AIR] < VER_SELECT(3600, 3000, 0, 0)){ - item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(((time_getDelta()*(float)(FRAMERATE))*100.0)*1.1)); - D_80385F30[ITEM_17_AIR] = MIN(D_80385F30[ITEM_17_AIR], VER_SELECT(3600, 3000, 0, 0)); + if(!D_80385FE4 && D_80385F30[ITEM_17_AIR] < 3600){ + item_adjustByDiffWithHud(ITEM_17_AIR, (s32)(((time_getDelta()*60.0f)*100.0)*1.1)); + D_80385F30[ITEM_17_AIR] = MIN(D_80385F30[ITEM_17_AIR], 3600); } } } @@ -396,7 +383,7 @@ void func_80346CA8(void) { if (D_80385FE4) { D_80385FE0 = true; D_80385F30[ITEM_14_HEALTH] = D_80385F30[ITEM_15_HEALTH_TOTAL]; - D_80385F30[ITEM_17_AIR] = VER_SELECT(3600, 3000, 0, 0); + D_80385F30[ITEM_17_AIR] = 60*60; } } @@ -438,16 +425,16 @@ void func_80346DB4(s32 note_count) { if (D_80385FF0[level_id] < note_count) { D_80385FF0[level_id] = note_count; if ((level_get() == LEVEL_1_MUMBOS_MOUNTAIN) && (note_count == 50)) { - gcdialog_showDialog(VER_SELECT(0xF74, 0xADA, 0, 0), 4, NULL, NULL, NULL, NULL); + gcdialog_showDialog(0xF74, 4, NULL, NULL, NULL, NULL); } - if (note_count == 100) { - gcdialog_showDialog(VER_SELECT(0xF78, 0xADE, 0, 0), 4, NULL, NULL, NULL, NULL); + if (note_count == notesMax) { + gcdialog_showDialog(0xF78, 4, NULL, NULL, NULL, NULL); } if (note_count == 1) { levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, true); } - if (!levelSpecificFlags_get(LEVEL_FLAG_34_UNKNOWN) && (gcdialog_showDialog(VER_SELECT(0xF76, 0xADC, 0, 0), 0, NULL, NULL, NULL, NULL))) { - levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, TRUE); + if (!levelSpecificFlags_get(LEVEL_FLAG_34_UNKNOWN) && (gcdialog_showDialog(0xF76, 0, NULL, NULL, NULL, NULL))) { + levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, true); } if (volatileFlag_get(VOLATILE_FLAG_17) == 0) { volatileFlag_set(VOLATILE_FLAG_17, 1); @@ -485,19 +472,6 @@ void notescore_getSizeAndPtr(s32 *size, void **ptr) { } } -// Raw per-level note-score array (vs. the packed u64 above). -void itemscore_noteScores_getSizeAndPtr(s32 *size, u8 **addr) { - *size = 0xE; - *addr = D_80385FF0; -} - -// Max-merge a level's note high score. -void itemscore_noteScores_setLevel(enum level_e level, s32 score) { - if (level >= 0 && level < 0xE && score > D_80385FF0[level]) { - D_80385FF0[level] = score; - } -} - void itemscore_noteScoress_maxAll(void) { s32 i; diff --git a/src/core2/gc/dialog.h b/src/core2/gc/dialog.h deleted file mode 100644 index 191a0fea6..000000000 --- a/src/core2/gc/dialog.h +++ /dev/null @@ -1,22 +0,0 @@ -// BanjoDecomp: core2/gc/dialog.h -#ifndef BANJO_KAZOOIE_GC_DIALOG_H -#define BANJO_KAZOOIE_GC_DIALOG_H - -enum { - DIALOG_BOTTOM = 0, - DIALOG_TOP = 1 -}; - -typedef enum { - DIALOG_STATE_0 = 0, - DIALOG_STATE_1 = 1, - DIALOG_STATE_2 = 2, - DIALOG_STATE_3 = 3, - DIALOG_WAITING_FOR_PLAYER_CHOICE = 4, - DIALOG_STATE_5 = 5, - DIALOG_STATE_6 = 6, - DIALOG_STATE_7 = 7, - DIALOG_STATE_8 = 8 -} DialogState; - -#endif // BANJO_KAZOOIE_GC_DIALOG_H diff --git a/src/core2/inventory_slots.c b/src/core2/inventory_slots.c index f2cdc3383..7feea4b74 100644 --- a/src/core2/inventory_slots.c +++ b/src/core2/inventory_slots.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9D760.c #include #include "functions.h" #include "variables.h" @@ -12,7 +11,7 @@ void func_80324700(u8* self){ for(i_ptr = self; i_ptr < self + 0x10; i_ptr++){ if(*i_ptr != 0xFF){ - modelRender_setAppendageVisibility((i_ptr - self) + 1, *i_ptr); + func_8033A45C((i_ptr - self) + 1, *i_ptr); } } } diff --git a/src/core2/level/lightconfig.c b/src/core2/level/lightconfig.c index 3ccea6f57..84fbe73ec 100644 --- a/src/core2/level/lightconfig.c +++ b/src/core2/level/lightconfig.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/code_35520.c +// BanjoDecomp: code_35520.c -> lightconfig.c // This file defines the distances for type-4 camera nodes (the normal 3rd person view camera?) for each map #include #include "functions.h" diff --git a/src/core2/level/metadata.c b/src/core2/level/metadata.c index 553039d23..83b8e9b7d 100644 --- a/src/core2/level/metadata.c +++ b/src/core2/level/metadata.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_117D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/level/levelspecificflags.c b/src/core2/level/specificflags.c similarity index 82% rename from src/core2/level/levelspecificflags.c rename to src/core2/level/specificflags.c index 69a066baf..f055d5c97 100644 --- a/src/core2/level/levelspecificflags.c +++ b/src/core2/level/specificflags.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/levelspecificflags.c #include #include "functions.h" #include "variables.h" @@ -79,12 +78,12 @@ void _levelSpecificFlags_updateCRC2(void) { s32 levelSpecificFlags_get(s32 i){ CALL_CANCELLABLE_RETURN_EVENT(OnGetLevelSpecificFlag, i) { - return bitfieldarray_getBit(D_80383320.unk8, i); + return bitfield_get_bit(D_80383320.unk8, i); } } s32 levelSpecificFlags_getN(s32 i, s32 n){ - return bitfieldarray_getNBits(D_80383320.unk8, i, n); + return bitfield_get_n_bits(D_80383320.unk8, i, n); } s32 levelSpecificFlags_getSet(s32 arg0, s32 arg1){ @@ -102,30 +101,16 @@ void levelSpecificFlags_clear(void){ _levelSpecificFlags_updateCRC2(); } -void levelSpecificFlags_setEx(s32 index, s32 val, s32 triggerEvent){ - s32 changed = bitfieldarray_getBit(D_80383320.unk8, index) != (val ? 1 : 0); - bitfieldarray_setBit(D_80383320.unk8, index, val); +void levelSpecificFlags_set(s32 index, s32 val){ + bitfield_set_bit(D_80383320.unk8, index, val); _levelSpecificFlags_updateCRC1(); _levelSpecificFlags_updateCRC2(); - if (triggerEvent && changed) { - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_LEVEL_SPECIFIC, index, val ? 1 : 0, 1); - } -} - -void levelSpecificFlags_set(s32 index, s32 val){ - levelSpecificFlags_setEx(index, val, 1); } void levelSpecificFlags_setN(s32 index, s32 val, s32 n){ - bitfieldarray_setNBits(D_80383320.unk8, index, val, n); + bitfield_set_n_bits(D_80383320.unk8, index, val, n); _levelSpecificFlags_updateCRC1(); _levelSpecificFlags_updateCRC2(); - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_LEVEL_SPECIFIC, index, val, n); -} - -void levelSpecificFlags_getSizeAndPtr(s32 *size, u8 **addr){ - *size = 8; - *addr = D_80383320.unk8; } s32 levelSpecificFlags_validateCRC1(void) { diff --git a/src/core2/map/audioconfig.c b/src/core2/map/audioconfig.c index b32268d2d..ac373dd69 100644 --- a/src/core2/map/audioconfig.c +++ b/src/core2/map/audioconfig.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9D640.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/cutscene_skip.c b/src/core2/map/cutscene_skip.c index 32cf24111..79c3e1bdd 100644 --- a/src/core2/map/cutscene_skip.c +++ b/src/core2/map/cutscene_skip.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_956B0.c #include #include "functions.h" #include "variables.h" @@ -8,6 +7,7 @@ extern void player_walkToPosition(f32 *, f32, void(*)(ActorMarker *), ActorMark extern void func_8028F760(s32, f32, f32); extern void func_8031CE70(f32 *arg0, enum map_e arg1, s32 arg2); extern void func_8031FFAC(void); +extern void fileProgressFlag_set(enum file_progress_e index, s32 set); extern NodeProp *func_80304ED0(void*, f32 *); extern void func_8031CD44(enum map_e, s32, f32, f32, s32); extern void mapSpecificFlags_set(s32, s32); @@ -135,9 +135,6 @@ void func_8031CB50(enum map_e map_id, s32 exit_id, s32 arg2) { s32 sp1C; if ((D_80383190 == 0) && (getGameMode() != GAME_MODE_8_BOTTLES_BONUS) && (getGameMode() != GAME_MODE_7_ATTRACT_DEMO)) { - // [port] Romhack gate: a listener may call musicKeepsPlaying() here to - // carry a special-music state across this warp. - EventSystem_Should(VB_WARP_KEEPS_MUSIC, true, map_id); sp1C = func_803226E8(gsworld_getMap()); if ((func_803226E8(map_id) != sp1C) && (func_80322914() == 0)) { func_8025A388(0, 0x4E2); @@ -1377,8 +1374,18 @@ void warp_smExitBanjosHouse(NodeProp *arg0, ActorMarker *arg1) { } void warp_lairEnterMMLobbyFromSMLevel(NodeProp *arg0, ActorMarker *arg1) { + // [port] BB romhacks can override this warp destination via BKCF; port + // listeners can refine further by responding to OnWarpResolveDest. s32 dest = 0x6912; - CALL_EVENT(OnWarpResolveDest, WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL, 0x6912, -1, &dest); + s32 bkcf = port_getRomhackWarpEnterLair(); + if (bkcf >= 0) { + dest = bkcf; + } + s32 mapOverride = port_getRomhackStartLevel2(); + if (mapOverride >= 0) { + dest = (mapOverride << 8) | (dest & 0xFF); + } + CALL_EVENT(OnWarpResolveDest, WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL, 0x6912, bkcf, &dest); func_8031CC8C(arg0, dest); } @@ -1515,15 +1522,9 @@ void func_8031FAB4(NodeProp *arg0, ActorMarker *arg1) { void warp_lairEnterLairFromSMLevel(NodeProp *arg0, ActorMarker *arg1) { if (fileProgressFlag_get(FILEPROG_BD_ENTER_LAIR_CUTSCENE) != 0) { // MM Lobby - // [port] BB romhacks can override this warp destination via BKCF; port - // listeners can refine further by responding to OnWarpResolveDest. - s32 dest = 0x6912; - s32 bkcf = port_getRomhackWarpEnterLair(); - if (bkcf >= 0) { - dest = bkcf; - } - CALL_EVENT(OnWarpResolveDest, WARP_ID_LAIR_ENTER_LAIR_FROM_SM_LEVEL, 0x6912, bkcf, &dest); - func_8031CC8C(arg0, dest); + // [port] BB romhacks can override this warp destination + s32 override = port_getRomhackWarpEnterLair(); + func_8031CC8C(arg0, override >= 0 ? override : 0x6912); } else { fileProgressFlag_set(FILEPROG_BD_ENTER_LAIR_CUTSCENE, 1); // Enter Lair Cutscene diff --git a/src/core2/map/cutscene_triggers.c b/src/core2/map/cutscene_triggers.c index b734f1179..2520d1d60 100644 --- a/src/core2/map/cutscene_triggers.c +++ b/src/core2/map/cutscene_triggers.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9B180.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/envcolor.c b/src/core2/map/envcolor.c index b4f62ae65..595d620b8 100644 --- a/src/core2/map/envcolor.c +++ b/src/core2/map/envcolor.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_94780.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/exit.c b/src/core2/map/exit.c index ef01e5a22..d90dfa235 100644 --- a/src/core2/map/exit.c +++ b/src/core2/map/exit.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C4320.c #include #include "functions.h" #include "variables.h" @@ -45,9 +44,9 @@ extern Struct_core2_C4320_0 D_80371F44[] = { extern Struct_core2_C4320_0 D_80371F70 = {MAP_41_FP_BOGGYS_IGLOO, 6, 0x5D, 7, 8, 3}; extern Struct_core2_C4320_0 D_80371F78[] ={ - {MAP_7_TTC_TREASURE_TROVE_COVE, 0, VER_SELECT(0x5F, 0x5E, 0, 0), 6, 9, 9}, - {MAP_27_FP_FREEZEEZY_PEAK, 0, VER_SELECT(0x5F, 0x5E, 0, 0), 9, 9, 9}, - {MAP_12_GV_GOBIS_VALLEY, 0, VER_SELECT(0x5F, 0x5E, 0, 0), 9, 5, 9} + {MAP_7_TTC_TREASURE_TROVE_COVE, 0, 0x5F, 6, 9, 9}, + {MAP_27_FP_FREEZEEZY_PEAK, 0, 0x5F, 9, 9, 9}, + {MAP_12_GV_GOBIS_VALLEY, 0, 0x5F, 9, 5, 9} }; extern s32 D_80371F8C = 0xA; //attract demo count @@ -222,9 +221,7 @@ void func_8034B8C0(enum map_e map_id, s32 demo_id) { volatileFlag_set(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE, 1); func_802E4A70(); } - // [port] 0x5E: SNS picture demo slot on non-v1.0 bases (table retargeted in - // ResourceHelpers); unused leftover slot on v1.0, so always safe to accept. - if ((demo_id == 0x5B) || (demo_id == 0x5E) || (demo_id == 0x5F)) { + if ((demo_id == 0x5B) || (demo_id == 0x5F)) { sns_backup_items_and_unlock_all(); } } diff --git a/src/core2/map/gsworld.c b/src/core2/map/gsworld.c index 8426ecdcf..154af5ad4 100644 --- a/src/core2/map/gsworld.c +++ b/src/core2/map/gsworld.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gsworld.c #include #include "core1/core1.h" #include "functions.h" @@ -8,18 +7,17 @@ #include #include "core2/particle.h" #include "port/Interpolation/FrameInterpolation.h" -#include "port/Enhancements/Retention/Retention.h" +#include "port/Enhancements/NoteRetention/NoteRetention.h" /* .data */ extern u8 D_80370250 = 0; /* .bss */ -struct gsworld_data_s { - s32 unk0; // probably game_mode_e - enum map_e map; - s32 exit; -}; -struct gsworld_data_s sGsWorldData; +struct { + s32 unk0; + s32 map_4; + s32 unk8; +}sGsWorldData; s32 D_803835DC; u32 sEnableDraw; @@ -40,15 +38,15 @@ extern Struct64s *func_8032994C(void); extern void func_802F2ED0(Struct64s *, Gfx **, Mtx **, Vtx **); /* .code */ -void gsworld_draw(Gfx** gfx, Mtx **mtx, Vtx **vtx) { +void gsworld_draw(Gfx** gdl, Mtx **mptr, Vtx **vptr) { f32 sp44; f32 sp40; if (sEnableDraw == 0) { - drawRectangle2D(gfx, 0, 0, gFramebufferWidth, gFramebufferHeight, 0, 0, 0); - core2_34790_getClipDistances(&sp44, &sp40); + drawRectangle2D(gdl, 0, 0, gFramebufferWidth, gFramebufferHeight, 0, 0, 0); + func_802BBD2C(&sp44, &sp40); viewport_setNearAndFar(sp44, sp40); - viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); + viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); return; } // Lighthouse [port] Crashing here, not sure what this is. @@ -57,87 +55,87 @@ void gsworld_draw(Gfx** gfx, Mtx **mtx, Vtx **vtx) { // } spawnQueue_unlock(); FrameInterpolation_RecordOpenChild("sky", 0); - sky_draw(gfx, mtx, vtx); + sky_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); - core2_34790_getClipDistances(&sp44, &sp40); + func_802BBD2C(&sp44, &sp40); viewport_setNearAndFar(sp44, sp40); - viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx); + viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr); if (mapModel_has_xlu_bin() != 0) { FrameInterpolation_RecordOpenChild("map_opa", 0); - mapModel_opa_draw(gfx, mtx, vtx); + mapModel_opa_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); if (game_is_frozen() == 0) { - leveloverlay_drawCallback(gfx, mtx, vtx); + leveloverlay_drawCallback(gdl, mptr, vptr); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("player", 0); - player_draw(gfx, mtx, vtx); + player_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); - CALL_EVENT(OnPlayerDraw, gfx, mtx, vtx); + CALL_EVENT(OnPlayerDraw, gdl, mptr, vptr); } if (game_is_frozen() == 0) { - func_80302C94(gfx, mtx, vtx); + func_80302C94(gdl, mptr, vptr); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("jiggylist", 0); - jiggylist_draw(gfx, mtx, vtx); + jiggylist_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { - func_803500D8(gfx, mtx, vtx); + func_803500D8(gdl, mptr, vptr); } if (game_is_frozen() == 0) { - func_802F2ED0(func_8032994C(), gfx, mtx, vtx); + func_802F2ED0(func_8032994C(), gdl, mptr, vptr); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("part_pass0", 0); - partEmitMgr_drawPass0(gfx, mtx, vtx); + partEmitMgr_drawPass0(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("map_xlu", 0); - mapModel_xlu_draw(gfx, mtx, vtx); + mapModel_xlu_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); } - if (!game_is_frozen()) { - core2_A5BC0_drawUnknownMarkers(gfx, mtx, vtx); + if (game_is_frozen() == 0) { + func_8032D3D8(gdl, mptr, vptr); } if (game_is_frozen() == 0) { FrameInterpolation_RecordOpenChild("part_pass1", 0); - partEmitMgr_drawPass1(gfx, mtx, vtx); + partEmitMgr_drawPass1(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { - func_8034F6F0(gfx, mtx, (s32)(intptr_t)vtx); + func_8034F6F0(gdl, mptr, (s32)(intptr_t)vptr); } - func_802D520C(gfx, mtx, vtx); + func_802D520C(gdl, mptr, vptr); } else { FrameInterpolation_RecordOpenChild("map_opa", 0); - mapModel_opa_draw(gfx, mtx, vtx); + mapModel_opa_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); - leveloverlay_drawCallback(gfx, mtx, vtx); - func_8034F6F0(gfx, mtx, (s32)(intptr_t)vtx); + leveloverlay_drawCallback(gdl, mptr, vptr); + func_8034F6F0(gdl, mptr, (s32)(intptr_t)vptr); FrameInterpolation_RecordOpenChild("player", 0); - player_draw(gfx, mtx, vtx); + player_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); - CALL_EVENT(OnPlayerDraw, gfx, mtx, vtx); - func_80302C94(gfx, mtx, vtx); - core2_A5BC0_drawUnknownMarkers(gfx, mtx, vtx); + CALL_EVENT(OnPlayerDraw, gdl, mptr, vptr); + func_80302C94(gdl, mptr, vptr); + func_8032D3D8(gdl, mptr, vptr); FrameInterpolation_RecordOpenChild("jiggylist", 0); - jiggylist_draw(gfx, mtx, vtx); + jiggylist_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); - func_803500D8(gfx, mtx, vtx); - func_802F2ED0(func_8032994C(), gfx, mtx, vtx); - func_802D520C(gfx, mtx, vtx); + func_803500D8(gdl, mptr, vptr); + func_802F2ED0(func_8032994C(), gdl, mptr, vptr); + func_802D520C(gdl, mptr, vptr); FrameInterpolation_RecordOpenChild("part_draw", 0); - partEmitMgr_draw(gfx, mtx, vtx); + partEmitMgr_draw(gdl, mptr, vptr); FrameInterpolation_RecordCloseChild(); } if (game_is_frozen() == 0) { - func_80350818(gfx, mtx, vtx); + func_80350818(gdl, mptr, vptr); } if (game_is_frozen() == 0) { - func_802BBD0C(gfx, mtx, vtx); + func_802BBD0C(gdl, mptr, vptr); } spawnQueue_lock(); } @@ -146,15 +144,15 @@ void gsworld_stub1(s32 arg0, s32 arg1, s32 arg2){ } enum map_e gsworld_getMap(void){ - return sGsWorldData.map; + return sGsWorldData.map_4; } s32 gsworld_getExit(){ - return sGsWorldData.exit; + return sGsWorldData.unk8; } void gsworld_transitionToExit(s32 arg0) { - transitionToMap(sGsWorldData.map, arg0, 1); + transitionToMap(sGsWorldData.map_4, arg0, 1); } s32 gsworld_getUnk0(){ @@ -216,9 +214,9 @@ void gsworld_free(void) { itemPrint_free(); } dialogBin_terminate(); - playerModel_free(); - if (!func_80322914()) { - func_8024F7C4(func_803226E8(sGsWorldData.map)); + func_802986D0(); + if (func_80322914() == 0) { + func_8024F7C4(func_803226E8(sGsWorldData.map_4)); } core1_7090_release(); AnimTextureListCache_free(); @@ -230,12 +228,12 @@ void gsworld_free(void) { void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { sGsWorldData.unk0 = 3; - CALL_EVENT(OnMapLoad, sGsWorldData.map, arg0, arg1); - sGsWorldData.map = arg0; + CALL_EVENT(OnMapLoad, sGsWorldData.map_4, arg0, arg1); + sGsWorldData.map_4 = arg0; // [port] Drop the prev tree; the next sub-frame would otherwise lerp // the old map's geometry against the new one's. FrameInterpolation_DontInterpolateCamera(); - sGsWorldData.exit = arg1; + sGsWorldData.unk8 = arg1; leveloverlay_init(); gsworld_setEnableUpdate(1); gsworld_setEnableDraw(1); @@ -245,15 +243,15 @@ void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { func_8038E7C4(); } if (func_80322914() == 0) { - func_8024F764(func_803226E8(sGsWorldData.map)); + func_8024F764(func_803226E8(sGsWorldData.map_4)); } func_80320B84(); AnimTextureListCache_init(); func_8034C97C(); func_8030A078(); func_8031B718(); - playerModel_set(); - if (!func_802E4A08()) { + func_80298700(); + if (func_802E4A08() == 0) { itemPrint_init(); } dialogBin_initialize(); @@ -302,7 +300,7 @@ void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { func_80350174(); gcparade_init(); func_80351998(); - func_802BC2CC(sGsWorldData.exit); + func_802BC2CC(sGsWorldData.unk8); func_802D63D4(); func_80255A04(); func_802D6948(); @@ -316,11 +314,11 @@ void gsworld_set(enum map_e arg0, s32 arg1, s32 arg2) { void gsworld_reload(void) { gsworld_free(); - gsworld_set(sGsWorldData.map, sGsWorldData.exit, 1); + gsworld_set(sGsWorldData.map_4, sGsWorldData.unk8, 1); } void gsworld_stub2(void) { - gsworld_stub3(sGsWorldData.map); + gsworld_stub3(sGsWorldData.map_4); } void gsworld_setUnk0(s32 arg0) { @@ -342,7 +340,7 @@ s32 gsworld_update(void) { s32 phi_v1; s32 phi_v0; - codeCF5F0_triggerAntiTamperMeasurement(); + codeCF5F0_forgetAllAbilitiesExceptClawSwipeIfChecksumsFail(); func_802D5628(); itemPrint_update(); if (getGameMode() != GAME_MODE_4_PAUSED) { @@ -385,9 +383,7 @@ s32 gsworld_update(void) { func_8031B790(); func_8034C9D4(); propModelList_flush(1); - if (EventSystem_Should(VB_SKY_UPDATE, true)) { - sky_update(); - } + sky_update(); partEmitMgr_update(); func_8034F918(); func_80350250(); @@ -407,7 +403,7 @@ s32 gsworld_update(void) { func_803306C8(1); func_8032AD7C(1); func_80322490(); - if (map_getLevel(sGsWorldData.map) == LEVEL_D_CUTSCENE) { + if (map_getLevel(sGsWorldData.map_4) == LEVEL_D_CUTSCENE) { func_802C79C4(); } func_8032AABC(); @@ -436,7 +432,6 @@ void gsworld_load(enum map_e map_id) { File *fp; port_noteRetention_beginMapLoad((int32_t)map_id); - port_carriedSync_beginMapLoad((int32_t)map_id); core1_15B30_sendMesg3ToRenderThread(); fp = file_openMap(map_id); //LevelSetupFile_Open diff --git a/src/core2/map/list.c b/src/core2/map/list.c index c2e0b0487..7ee10a629 100644 --- a/src/core2/map/list.c +++ b/src/core2/map/list.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_12F30.c #include #include "functions.h" #include "variables.h" @@ -126,7 +125,7 @@ void func_80299EC0(f32 arg0[3]) { } else { sp78 = 250; } - playerPosition_get(spEC); + _player_getPosition(spEC); sp6C = func_8029463C(); spC8 = func_802946A8(); if (spC8 == NULL) { diff --git a/src/core2/map/loadzone.c b/src/core2/map/loadzone.c index c26f81e0e..1ab7baf3c 100644 --- a/src/core2/map/loadzone.c +++ b/src/core2/map/loadzone.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_A960.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/mapModel.c b/src/core2/map/model.c similarity index 93% rename from src/core2/map/mapModel.c rename to src/core2/map/model.c index 09517ffb5..8cb5f4c68 100644 --- a/src/core2/map/mapModel.c +++ b/src/core2/map/model.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/mapModel.c #include #include "functions.h" #include "variables.h" @@ -12,7 +11,7 @@ extern BKCollisionTriangle *func_802E92AC(BKCollisionList *, BKVertexList *, f32 extern s32 bkmodelunk14list_func_802EC394(BKModelUnk14List *arg0, f32 position[3], f32 rotation[3], f32 scale, f32 arg4[3], f32 arg5[3], s32 arg6); extern void vtxList_getBounds_s32(BKVertexList *, s32[3], s32[3]); extern void func_802F7BC0(Gfx **, Mtx **, Vtx **); -extern void modelRender_setAppendageVisibility(s32, s32); +extern void func_8033A45C(s32, s32); extern Vec3fArray *vec3fArray_defrag(Vec3fArray *this); extern Vec3fArray *vec3fArray_new(void); extern void func_8034C6DC(BKModel *arg0); @@ -261,101 +260,101 @@ f32 func_80308FDC(f32 arg0[3], u32 arg1) { void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 temp_a0; if (func_80320708() && levelSpecificFlags_validateCRC2() && dummy_func_80320248()) { - if (mapModel_getOpaModelId() == VER_SELECT(ASSET_14CF_MODEL_SM_SPIRAL_MOUNTAIN_OPA, 0xD2D, 0, 0)) { - modelRender_setAppendageVisibility(1, 0); - modelRender_setAppendageVisibility(2, 1); + if (mapModel_getOpaModelId() == ASSET_14CF_MODEL_SM_SPIRAL_MOUNTAIN_OPA) { + func_8033A45C(1, 0); + func_8033A45C(2, 1); } switch (gsworld_getMap()) { /* irregular */ case MAP_88_CS_SPIRAL_MOUNTAIN_6: if (mapSpecificFlags_get(0) != 0) { - modelRender_setAppendageVisibility(1, 1); - modelRender_setAppendageVisibility(2, 0); + func_8033A45C(1, 1); + func_8033A45C(2, 0); } break; case MAP_12_GV_GOBIS_VALLEY: - modelRender_setAppendageVisibility(1, levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN) ? 1 : 0); - modelRender_setAppendageVisibility(2, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 0 : 1); - modelRender_setAppendageVisibility(5, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 1 : 0); + func_8033A45C(1, levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN) ? 1 : 0); + func_8033A45C(2, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 0 : 1); + func_8033A45C(5, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 1 : 0); break; case MAP_14_GV_SANDYBUTTS_MAZE: - modelRender_setAppendageVisibility(5, (player_movementGroup() == BSGROUP_4_LOOK) ? 1 : 0); + func_8033A45C(5, (player_movementGroup() == BSGROUP_4_LOOK) ? 1 : 0); break; case MAP_E_MM_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 1); - modelRender_setAppendageVisibility(5, 1); + func_8033A45C(1, 1); + func_8033A45C(5, 1); break; case MAP_47_BGS_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 2); - modelRender_setAppendageVisibility(5, 2); + func_8033A45C(1, 2); + func_8033A45C(5, 2); break; case MAP_48_FP_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 3); - modelRender_setAppendageVisibility(5, 3); + func_8033A45C(1, 3); + func_8033A45C(5, 3); break; case MAP_30_MMM_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 4); - modelRender_setAppendageVisibility(5, 4); + func_8033A45C(1, 4); + func_8033A45C(5, 4); break; case MAP_4A_CCW_SPRING_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 5); - modelRender_setAppendageVisibility(5, 5); + func_8033A45C(1, 5); + func_8033A45C(5, 5); break; case MAP_4B_CCW_SUMMER_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 6); - modelRender_setAppendageVisibility(5, 6); + func_8033A45C(1, 6); + func_8033A45C(5, 6); break; case MAP_4C_CCW_AUTUMN_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 7); - modelRender_setAppendageVisibility(5, 7); + func_8033A45C(1, 7); + func_8033A45C(5, 7); break; case MAP_4D_CCW_WINTER_MUMBOS_SKULL: - modelRender_setAppendageVisibility(1, 8); - modelRender_setAppendageVisibility(5, 8); + func_8033A45C(1, 8); + func_8033A45C(5, 8); break; case MAP_5E_CCW_SPRING_NABNUTS_HOUSE: case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE: case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE: - modelRender_setAppendageVisibility(1, 1); - modelRender_setAppendageVisibility(2, 0); + func_8033A45C(1, 1); + func_8033A45C(2, 0); break; case MAP_61_CCW_WINTER_NABNUTS_HOUSE: - modelRender_setAppendageVisibility(1, 0); - modelRender_setAppendageVisibility(2, 1); + func_8033A45C(1, 0); + func_8033A45C(2, 1); break; case MAP_1D_MMM_CELLAR: - modelRender_setAppendageVisibility(1, actorArray_findActorFromActorId(0x191) ? 0 : 1); + func_8033A45C(1, actorArray_findActorFromActorId(0x191) ? 0 : 1); break; case MAP_7C_CS_INTRO_BANJOS_HOUSE_1: case MAP_89_CS_INTRO_BANJOS_HOUSE_2: case MAP_8A_CS_INTRO_BANJOS_HOUSE_3: case MAP_8C_SM_BANJOS_HOUSE: case MAP_91_FILE_SELECT: - modelRender_setAppendageVisibility(5, 1); + func_8033A45C(5, 1); break; case MAP_7B_CS_INTRO_GL_DINGPOT_1: case MAP_81_CS_INTRO_GL_DINGPOT_2: - modelRender_setAppendageVisibility(4, 0); - modelRender_setAppendageVisibility(5, 0); - modelRender_setAppendageVisibility(6, 0); + func_8033A45C(4, 0); + func_8033A45C(5, 0); + func_8033A45C(6, 0); break; case MAP_82_CS_ENTERING_GL_MACHINE_ROOM: case MAP_83_CS_GAME_OVER_MACHINE_ROOM: case MAP_84_CS_UNUSED_MACHINE_ROOM: - modelRender_setAppendageVisibility(4, 1); - modelRender_setAppendageVisibility(5, 1); - modelRender_setAppendageVisibility(6, 1); + func_8033A45C(4, 1); + func_8033A45C(5, 1); + func_8033A45C(6, 1); break; case MAP_93_GL_DINGPOT: - modelRender_setAppendageVisibility(4, 1); - modelRender_setAppendageVisibility(5, 1); - modelRender_setAppendageVisibility(6, (jigsawPicture_isJigsawPictureComplete(0xA) || fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE))); + func_8033A45C(4, 1); + func_8033A45C(5, 1); + func_8033A45C(6, (jigsawPicture_isJigsawPictureComplete(0xA) || fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE))); break; } modelRender_setRefPoints(mapModel.unk24); @@ -377,7 +376,7 @@ void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { if (mapModel.model_bin_xlu != NULL) { if (gsworld_getMap() == MAP_1D_MMM_CELLAR) { - modelRender_setAppendageVisibility(1, (actorArray_findActorFromActorId(0x191) != NULL) ? 0 : 1); + func_8033A45C(1, (actorArray_findActorFromActorId(0x191) != NULL) ? 0 : 1); } modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); temp_a0 = mapModel.unk4; diff --git a/src/core2/map/overlay.c b/src/core2/map/overlay.c index 9146ee351..c37d3e3bf 100644 --- a/src/core2/map/overlay.c +++ b/src/core2/map/overlay.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/code_9B990.c +// BanjoDecomp: code_9B990.c -> overlay.c (level overlay callbacks) #include #include "functions.h" #include "variables.h" @@ -164,22 +164,22 @@ static void leveloverlay_MMM_unk14(s32 arg0, s32 arg1) { } static void leveloverlay_CC_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { - maClanker_draw(gfx, mtx, vtx); + CC_func_80388760(gfx, mtx, vtx); } static void leveloverlay_CC_release(void) { - maClanker_release(); - maClankerRings_release(); + func_80388CB4(); + func_803880D4(); } static void leveloverlay_CC_init(void) { - maClanker_init(); - maClankerRings_init(); + func_80388D54(); + func_80388104(); } static void leveloverlay_CC_update(void) { - maClanker_update(); - maClankerRings_update(); + CC_func_80388F4C(); + func_8038817C(); } static void leveloverlay_CC_unk14(s32 arg0, s32 arg1) {} @@ -372,8 +372,7 @@ void leveloverlay_debug(void) {} void leveloverlay_init(void) { int i; enum overlay_e overlay_id; - - codeCF5F0_init(); + func_80356714(); overlay_id = overlayManager_getLoadedID(); sActiveCallbacks.init = NULL; sActiveCallbacks.update = NULL; diff --git a/src/core2/map/mapsavestate.c b/src/core2/map/savestate.c similarity index 99% rename from src/core2/map/mapsavestate.c rename to src/core2/map/savestate.c index a84578949..9e1aa4cce 100644 --- a/src/core2/map/mapsavestate.c +++ b/src/core2/map/savestate.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/mapsavestate.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/map/mapspecificflags.c b/src/core2/map/specificflags.c similarity index 85% rename from src/core2/map/mapspecificflags.c rename to src/core2/map/specificflags.c index e6df70f0d..dfaac4ad8 100644 --- a/src/core2/map/mapspecificflags.c +++ b/src/core2/map/specificflags.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/mapspecificflags.c #include #include "functions.h" #include "variables.h" @@ -44,24 +43,16 @@ u32 mapSpecificFlags_getN(s32 idx, s32 n){ u32 mapSpecificFlags_getClear(s32 i){ u32 ret_val = mapSpecificFlags_get(i); - mapSpecificFlags_setEx(i, 0, 0); + mapSpecificFlags_set(i, 0); return ret_val; } -void mapSpecificFlags_setEx(s32 i, s32 val, s32 triggerEvent){ - s32 changed = ((D_80367000 >> i) & 1) != (val ? 1 : 0); +void mapSpecificFlags_set(s32 i, s32 val){ if(val) D_80367000 |= 1 << i; else D_80367000 &= ~(1 << i); _mapSpecificFlags_updateCRCs(); - if (triggerEvent && changed) { - CALL_EVENT(OnGameFlagSet, ANCHOR_FLAGSPACE_MAP_SPECIFIC, i, val ? 1 : 0, 1); - } -} - -void mapSpecificFlags_set(s32 i, s32 val){ - mapSpecificFlags_setEx(i, val, 1); } void mapSpecificFlags_setN(s32 idx, s32 val, s32 n){ diff --git a/src/core2/map/warp_dispatch.c b/src/core2/map/warp_dispatch.c index 839b4a8b1..98c6c7e0b 100644 --- a/src/core2/map/warp_dispatch.c +++ b/src/core2/map/warp_dispatch.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_AD110.c #include #include "functions.h" #include "variables.h" @@ -555,28 +554,25 @@ void func_80334448(NodeProp *arg0, ActorMarker *arg1) { s32 warpIdx; s32 warpDest; - switch(codeA5BC0_getNodePropCategory(arg0)) { + switch(codeA5BC0_getNodePropBit6(arg0)) { case 3: // warp (L80334480) global_timer_time = globalTimer_getTime(); if ((codeA5BC0_getNodePropUnkC(arg0) + 1) != global_timer_time) { - // [port] Romhacks remap warp destinations via BKCF config - warpIdx = codeA5BC0_getNodePropActorId(arg0); + // [port] BB romhacks remap warp destinations via BKCF config + warpIdx = codeA5BC0_getNodePropUnk8(arg0); warpDest = port_getRomhackWarpDest(warpIdx); CALL_EVENT(OnWarpDispatch, warpIdx, warpDest); - // [port] Romhacks can hold a warp shut behind progress - if (EventSystem_Should(VB_WARP_DISPATCH, true, warpIdx)) { - if (warpDest >= 0) { - func_8031CC8C(arg0, warpDest); - } else { - sWarpFunctions[warpIdx](arg0, arg1); - } + if (warpDest >= 0) { + func_8031CC8C(arg0, warpDest); + } else { + sWarpFunctions[warpIdx](arg0, arg1); } } codeA5BC0_setNodePropUnkC(arg0, global_timer_time); break; case 4: // radius trigger like camera (L803344E0) - sRadiusTriggers[codeA5BC0_getNodePropActorId(arg0)](arg0, arg1); + sRadiusTriggers[codeA5BC0_getNodePropUnk8(arg0)](arg0, arg1); break; case 0: //L80334508 diff --git a/src/core2/map/world_reset.c b/src/core2/map/world_reset.c index 5859154cb..93cfd6f83 100644 --- a/src/core2/map/world_reset.c +++ b/src/core2/map/world_reset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9A740.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/matrix_interp.c b/src/core2/matrix_interp.c index 812af806c..fe09ea19b 100644 --- a/src/core2/matrix_interp.c +++ b/src/core2/matrix_interp.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C3A40.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/lighting.c b/src/core2/model/lighting.c index 0ed2de3c2..f5d86ff0f 100644 --- a/src/core2/model/lighting.c +++ b/src/core2/model/lighting.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_66490.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/mesh_dataaccess.c b/src/core2/model/mesh_dataaccess.c index 58253b248..27c9a16ca 100644 --- a/src/core2/model/mesh_dataaccess.c +++ b/src/core2/model/mesh_dataaccess.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_63410.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/meshbounds.c b/src/core2/model/meshbounds.c index cfe91eb90..2575ffe6d 100644 --- a/src/core2/model/meshbounds.c +++ b/src/core2/model/meshbounds.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B8080.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/modelRender.c b/src/core2/model/render.c similarity index 97% rename from src/core2/model/modelRender.c rename to src/core2/model/render.c index d701fb000..87cbd446a 100644 --- a/src/core2/model/modelRender.c +++ b/src/core2/model/render.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/modelRender.c #include #include "core1/core1.h" #include "functions.h" @@ -155,7 +154,7 @@ void modelRender_geoCmd_DRAWDIST(Gfx **, Mtx **, struct bk_geo_cmd_s *); void modelRender_geoCmd_UnkE(Gfx **, Mtx **, struct bk_geo_cmd_s *); void modelRender_geoCmd_CAMERA(Gfx **, Mtx **, struct bk_geo_cmd_s *); void modelRender_executeGeoCmds(Gfx **, Mtx **, BKGeoCmd *); -void modelRender_setAppendageVisibility(s32 arg0, s32 arg1); +void func_8033A45C(s32 arg0, s32 arg1); // Sets up 2 cycle mode Gfx setup2CycleDL[] = @@ -691,8 +690,8 @@ void modelRender_reset(void){ D_803837B0.unk0 = 0; sSecondaryModelData.model_id = 0; modelRenderDepthMode = MODEL_RENDER_DEPTH_NONE; - modelRender_setAppendageVisibility(1,1); - modelRender_setAppendageVisibility(2,0); + func_8033A45C(1,1); + func_8033A45C(2,0); if(D_80383758.unk18){ viewport_setPosition_vec3f(D_80383758.unk1C); viewport_setRotation_vec3f(D_80383758.unk28); @@ -711,7 +710,6 @@ void modelRender_geoCmd_Unk0(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2){ f32 sp30[3]; if(cmd->unk8){ - FrameInterpolation_RecordOpenChildHash3("billboard", (uintptr_t)cmd, 0, 0); mlMtx_apply_vec3f(sp30, cmd->unkC); mlMtx_push_translation(sp30[0], sp30[1], sp30[2]); mlMtxRotYaw(modelRenderCameraRotation[1]); @@ -725,7 +723,6 @@ void modelRender_geoCmd_Unk0(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2){ modelRender_executeGeoCmds(gfx, mtx, (BKGeoCmd*)((u8*)cmd + cmd->unk8)); mlMtxPop(); gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW); - FrameInterpolation_RecordCloseChild(); } } @@ -794,8 +791,11 @@ void modelRender_geoCmd_TEXWRAP(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2) void modelRender_geoCmd_BONE(Gfx **gfx, Mtx **mtx, struct bk_geo_cmd_s *arg2){ GeoCmd2 *cmd = (GeoCmd2 *)arg2; - // [port] Stable per-bone scope. - FrameInterpolation_RecordOpenChildHash3("bone", (uintptr_t)(u8)cmd->unk9, (uintptr_t)cmd, 0); + // [port] Stable per-bone scope. Without it, any op-count shift in the + // geo walk mis-pairs every subsequent bone — Banjo ends up half in + // one pose and half in another on the affected sub-frame. Nested + // bones nest their scopes via the recursive walk below. + FrameInterpolation_RecordOpenChild("bone", (uintptr_t)(u8)cmd->unk9); if(D_8038371C){ mlMtx_push_multiplied_2(&D_80383BF8, animMtxList_get(D_8038371C, cmd->unk9)); if(D_80370990){ @@ -958,10 +958,8 @@ void modelRender_geoCmd_DRAWDIST(Gfx ** gfx, Mtx ** mtx, struct bk_geo_cmd_s *ar sp20[2] = (f32)cmd->unkE[2] * modelRenderScale; // [port] The N64 bounding boxes in CmdD_DRAW_DISTANCE are too conservative // for the port's viewport (292x216 -> 320x240 at 4:3). Extend to all aspect - // ratios since the port always renders at a higher effective resolution. - if (EventSystem_Should(VB_DRAWDIST_BOX_CULL, true, sp2C, sp20)) { - modelRender_executeGeoCmds(gfx, mtx, (BKGeoCmd*)((u8*)cmd + cmd->unk14)); - } + //ratios since the port always renders at a higher effective resolution. + modelRender_executeGeoCmds(gfx, mtx, (BKGeoCmd*)((u8*)cmd + cmd->unk14)); } } @@ -1159,7 +1157,6 @@ BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation tmp_f0 = D_80383708 - 500.0f; if(tmp_f0 < camera_focus_distance){ alpha = (s32)((1.0f - (camera_focus_distance - tmp_f0)/500.0f)*255.0f); - EventSystem_Should(VB_MODEL_DRAWDIST_FADE_ALPHA, true, &alpha); if(modelRenderColorMode == COLOR_MODE_DYNAMIC_PRIM_AND_ENV){ modelRenderDynColors.prim[3] = (modelRenderDynColors.prim[3] * alpha) / 0xff; } @@ -1292,8 +1289,6 @@ BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation if(model_bin->anim_vertices_list_offset != 0 && D_8038371C != NULL){ animVerticesList_transform((BKAnimVerticesList *)((uintptr_t)modelRenderModelBin + (uintptr_t)(u32)modelRenderModelBin->anim_vertices_list_offset), modelRendervertexList, D_8038371C); - // [port] The transform just posed the model's shared vertex array. Hand this draw a private copy. - port_modelRender_snapshotAnimVertices(gfx, vtxList_getVertices(modelRendervertexList), vtxList_getVtxCount(modelRendervertexList)); } mlMtxIdent(); @@ -1332,9 +1327,6 @@ BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation // [port] Mirror mode: restore culling inversion if (_mirror_excluded) gSPSetExtraGeometryMode((*gfx)++, G_EX_INVERT_CULLING); gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW); - // [port] Romhack model DLs can leave a palette (TLUT) mode enabled and leak it - // into the next model's draw; reset it after every model for romhacks. - port_modelRenderResetTLUT(gfx); if(modelRenderCallback.post_draw != NULL){ modelRenderCallback.post_draw(modelRenderCallback.post_draw_arg); @@ -1546,8 +1538,8 @@ void modelRender_setRefPoints(Vec3fArray *arg0){ modelRenderRefPoints = arg0; } -void modelRender_setAppendageVisibility(s32 appendage_id, s32 appendage_visibility){ - D_80383658[appendage_id] = appendage_visibility; +void func_8033A45C(s32 arg0, s32 arg1){ + D_80383658[arg0] = arg1; } void modelRender_func_8033A470(s32 arg0, s32 arg1){ diff --git a/src/core2/model/rendernormal.c b/src/core2/model/rendernormal.c index f3502200e..5f3355085 100644 --- a/src/core2/model/rendernormal.c +++ b/src/core2/model/rendernormal.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_5FB00.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/skinning.c b/src/core2/model/skinning.c index e924e029f..2d08038a8 100644 --- a/src/core2/model/skinning.c +++ b/src/core2/model/skinning.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_637D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/model/vertex_brightness.c b/src/core2/model/vertex_brightness.c index 056e99524..908d1260e 100644 --- a/src/core2/model/vertex_brightness.c +++ b/src/core2/model/vertex_brightness.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C8360.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/mumbo.c b/src/core2/mumbo_transforms.c similarity index 74% rename from src/core2/mumbo.c rename to src/core2/mumbo_transforms.c index 4b3031d82..a495a1ef9 100644 --- a/src/core2/mumbo.c +++ b/src/core2/mumbo_transforms.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/mumbo.c #include #include "functions.h" #include "variables.h" @@ -26,7 +25,7 @@ ActorAnimationInfo D_80367490[] = { {ASSET_180_ANIM_MUMBO_ROTATE, 0.7f}, }; -ActorInfo chMumbo = { +ActorInfo D_803674E0 = { MARKER_6_MUMBO, ACTOR_7_MUMBO, ASSET_3C6_MODEL_MUMBO, 0x1, D_80367490, chMumbo_update, actor_update_func_80326224, chMumbo_draw, @@ -55,17 +54,17 @@ static bool __chMumbo_actorExists(enum actor_e actorId) { enum transformation_e func_802D16AC(void) { s32 ret = TRANSFORM_2_TERMITE; - __chMumbo_actorExists(ACTOR_1F_UNUSED); - if (__chMumbo_actorExists(ACTOR_20_TRANSFORM_PUMPKIN)) { + __chMumbo_actorExists(0x1F); + if (__chMumbo_actorExists(0x20)) { ret = TRANSFORM_3_PUMPKIN; } - if (__chMumbo_actorExists(ACTOR_21_TRANSFORM_CROC)) { + if (__chMumbo_actorExists(0x21)) { ret = TRANSFORM_5_CROC; } - if (__chMumbo_actorExists(ACTOR_22_TRANSFORM_WALRUS)) { + if (__chMumbo_actorExists(0x22)) { ret = TRANSFORM_4_WALRUS; } - if (__chMumbo_actorExists(ACTOR_23_TRANSFORM_BEE)) { + if (__chMumbo_actorExists(0x23)) { ret = TRANSFORM_6_BEE; } return ret; @@ -150,24 +149,24 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 this = marker_getActor(caller); switch(text_id){ - case VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0): //L802D1A04 - gcdialog_showDialog((this->unk38_0) ? VER_SELECT(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xA28, 0, 0) : VER_SELECT(ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS, 0xA29, 0, 0), 0xe, this->position, this->marker, __chMumbo_textCallback, NULL); + case ASSET_D8F_DIALOG_MUMBO_MEET: //L802D1A04 + gcdialog_showDialog((this->unk38_0) ? ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS : ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS, 0xe, this->position, this->marker, __chMumbo_textCallback, NULL); return; - case VER_SELECT(ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR, 0xA0E, 0, 0): //L802D1A40 - fileProgressFlag_set(FILEPROG_12_HAS_TRANSFORMED_BEFORE, TRUE); - gcdialog_showDialog(VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0) + D_8037DDF0, 4, NULL, NULL, NULL, NULL); + case ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR: //L802D1A40 + fileProgressFlag_set(FILEPROG_12_HAS_TRANSFORMED_BEFORE, true); + gcdialog_showDialog(ASSET_D8F_DIALOG_MUMBO_MEET + D_8037DDF0, 4, NULL, NULL, NULL, NULL); gcpausemenu_80314AC8(1); break; - case VER_SELECT(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xA28, 0, 0): //L802D1A7C /* fall-through */ - fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, TRUE); - case VER_SELECT(ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS, 0xA29, 0, 0): //L802D1A88 + case ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS: //L802D1A7C /* fall-through */ + fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, true); + case ASSET_DAB_DIALOG_MUMBO_NOT_ENOUGH_TOKENS: //L802D1A88 func_8028F918(0); break; - case VER_SELECT(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xA2D, 0, 0): //L802D1A98 - this->has_met_before = FALSE; + case ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE: //L802D1A98 + this->has_met_before = false; if(this->unk38_31 != 0){ coMusicPlayer_playMusic(COMUSIC_2B_DING_B, 28000); item_adjustByDiffWithHud(ITEM_1C_MUMBO_TOKEN, -this->unk38_31); @@ -176,9 +175,9 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 subaddie_set_state_with_direction(this, 5, 0.0f, 1); return; - case VER_SELECT(ASSET_DB0_DIALOG_MUMBO_MISTAKE_0, 0xA2E, 0, 0): //L802D1AF8 - case VER_SELECT(ASSET_DB1_DIALOG_MUMBO_MISTAKE_1, 0xA2F, 0, 0): //L802D1AF8 - case VER_SELECT(ASSET_DB2_DIALOG_MUMBO_MISTAKE_2, 0xA30, 0, 0): //L802D1AF8 + case ASSET_DB0_DIALOG_MUMBO_MISTAKE_0: //L802D1AF8 + case ASSET_DB1_DIALOG_MUMBO_MISTAKE_1: //L802D1AF8 + case ASSET_DB2_DIALOG_MUMBO_MISTAKE_2: //L802D1AF8 D_8037DDF0 = this->unk10_12; this->unk10_12 = 1; if(this->unk38_31){ @@ -186,7 +185,7 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 item_adjustByDiffWithHud(ITEM_1C_MUMBO_TOKEN, -this->unk38_31); } - case VER_SELECT(ASSET_DAE_DIALOG_MUMBO_TREX_START, 0xA2C, 0, 0): //L802D1B48 + case ASSET_DAE_DIALOG_MUMBO_TREX_START: //L802D1B48 subaddie_set_state_with_direction(this, 5, 0.0f, 1); return; @@ -199,24 +198,24 @@ static void __chMumbo_textCallback(ActorMarker *caller, enum asset_e text_id, s3 void chMumbo_func_802D1B8C(Actor *this, enum transformation_e transform_id) { if (this->unk10_12 != 0) { - gcdialog_showDialog(fileProgressFlag_getN(FILEPROG_BB_MUMBO_MISTAKE_INDEX, 2) + VER_SELECT(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xA2D, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(fileProgressFlag_getN(FILEPROG_BB_MUMBO_MISTAKE_INDEX, 2) + ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); return; } if (fileProgressFlag_get(FILEPROG_12_HAS_TRANSFORMED_BEFORE)) { if (this->velocity[0] == 0.0f) { - gcdialog_showDialog(transform_id + VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0), 6, this->position, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(transform_id + ASSET_D8F_DIALOG_MUMBO_MEET, 6, this->position, this->marker, __chMumbo_textCallback, NULL); return; } if (gsworld_getMap() == MAP_7A_GL_CRYPT && transform_id == TRANSFORM_3_PUMPKIN && !fileProgressFlag_get(FILEPROG_F7_HAS_TRANSFORMED_IN_CRYPT)) { - gcdialog_showDialog(VER_SELECT(ASSET_DAD_DIALOG_MUMBO_XFORM_IN_CRYPT, 0xA2B, 0, 0), 6, this->position, this->marker, __chMumbo_textCallback, NULL); - fileProgressFlag_set(FILEPROG_F7_HAS_TRANSFORMED_IN_CRYPT, TRUE); + gcdialog_showDialog(ASSET_DAD_DIALOG_MUMBO_XFORM_IN_CRYPT, 6, this->position, this->marker, __chMumbo_textCallback, NULL); + fileProgressFlag_set(FILEPROG_F7_HAS_TRANSFORMED_IN_CRYPT, true); return; } gcpausemenu_80314AC8(1); subaddie_set_state(this, 4U); return; } - gcdialog_showDialog(VER_SELECT(ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR, 0xA0E, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(ASSET_D90_DIALOG_MUMBO_MAGIC_PAID_FOR, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); } void chMumbo_update(Actor *this) { @@ -289,8 +288,8 @@ void chMumbo_update(Actor *this) { && !volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) ) { subaddie_set_state(this, 3); - gcdialog_showDialog(VER_SELECT(ASSET_D8F_DIALOG_MUMBO_MEET, 0xA0D, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); - fileProgressFlag_set(FILEPROG_11_HAS_MET_MUMBO, TRUE); + gcdialog_showDialog(ASSET_D8F_DIALOG_MUMBO_MEET, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + fileProgressFlag_set(FILEPROG_11_HAS_MET_MUMBO, true); break; } @@ -300,8 +299,8 @@ void chMumbo_update(Actor *this) { && this->unk38_0 ){ subaddie_set_state(this, 3); - gcdialog_showDialog(VER_SELECT(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xA28, 0, 0), 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); - fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, TRUE); + gcdialog_showDialog(ASSET_DAA_DIALOG_MUMBO_HAS_ENOUGH_TOKENS, 0xE, this->position, this->marker, __chMumbo_textCallback, NULL); + fileProgressFlag_set(FILEPROG_DC_HAS_HAD_ENOUGH_TOKENS_BEFORE, true); break; } @@ -318,7 +317,7 @@ void chMumbo_update(Actor *this) { sp48 = (gsworld_getMap() == MAP_7A_GL_CRYPT) ? chMumbo_withinHorzDistToPlayer(0x442, 0, 0x3C) : chMumbo_withinHorzDistToPlayer(0, -0x5A, 0x3C); if( sp48 && player_movementGroup() == BSGROUP_0_NONE - && player_isStableWithExtraSteps() + && func_8028F20C() && func_8028EFC8() ){ controller_copyFaceButtons(0, face_buttons); @@ -335,10 +334,10 @@ void chMumbo_update(Actor *this) { func_8028F94C(2, this->position); if ( sp44 && gsworld_getMap() != MAP_7A_GL_CRYPT && !fileProgressFlag_get(FILEPROG_BA_HAS_SEEN_TREX_TEXT) - && romhack_mumboRandomEventsAllowed() && randf() < 0.01 + && randf() < 0.01 && sp48 ) { - gcdialog_showDialog(VER_SELECT(ASSET_DAE_DIALOG_MUMBO_TREX_START, 0xA2C, 0, 0), 6, NULL, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(ASSET_DAE_DIALOG_MUMBO_TREX_START, 6, NULL, this->marker, __chMumbo_textCallback, NULL); fileProgressFlag_set(FILEPROG_BA_HAS_SEEN_TREX_TEXT, 1); this->has_met_before = true; subaddie_set_state(this, 3); @@ -347,7 +346,7 @@ void chMumbo_update(Actor *this) { && gsworld_getMap() != MAP_7A_GL_CRYPT && !this->unk138_23 && (sp40 = fileProgressFlag_getN(FILEPROG_BB_MUMBO_MISTAKE_INDEX, 2), sp40 < 3) - && romhack_mumboRandomEventsAllowed() && randf() < 0.05 + && randf() < 0.05 && sp48 ){ this->unk138_23 = true; @@ -367,7 +366,7 @@ void chMumbo_update(Actor *this) { break; } coMusicPlayer_playMusic(COMUSIC_2C_BUZZER, 22000); - if ((levelSpecificFlags_get(LEVEL_FLAG_3E_UNKNOWN) == FALSE) && (gcdialog_showDialog(VER_SELECT(ASSET_DAC_DIALOG_MUMBO_FAIL_TO_BUY, 0xA2A, 0, 0), 0, NULL, NULL, NULL, NULL) != 0)) { + if ((levelSpecificFlags_get(LEVEL_FLAG_3E_UNKNOWN) == false) && (gcdialog_showDialog(ASSET_DAC_DIALOG_MUMBO_FAIL_TO_BUY, 0, NULL, NULL, NULL, NULL) != 0)) { levelSpecificFlags_set(LEVEL_FLAG_3E_UNKNOWN, 1); } } @@ -375,10 +374,6 @@ void chMumbo_update(Actor *this) { break; case 5: //L802D2488 - // [port] Fast Transformation drives this state from Cheats.cpp instead. - if (!EventSystem_Should(VB_MUMBO_HUT_TRANSFORM_CUTSCENE, true, this)) { - break; - } actor_playAnimationOnce(this); if (actor_animationIsAt(this, 0.35f)){ sfxSource_func_8030E2C4(this->unk44_31); @@ -399,11 +394,11 @@ void chMumbo_update(Actor *this) { if ( this->has_met_before || (this->unk10_12 == 0 && (player_getTransformation() != TRANSFORM_1_BANJO) - && (player_getTransformation() != romhack_mumboWishwashyId())) + && (player_getTransformation() != TRANSFORM_7_WISHWASHY)) ) { - romhack_mumboTransform(TRANSFORM_1_BANJO); - } else if (romhack_mumboTransform(D_8037DDF0)) { - if (D_8037DDF0 != romhack_mumboWishwashyId()) { + func_8028FB88(TRANSFORM_1_BANJO); + } else if (func_8028FB88(D_8037DDF0)) { + if (D_8037DDF0 != TRANSFORM_7_WISHWASHY) { if (fileProgressFlag_getAndSet(__bkProgId_from_transformationId(D_8037DDF0), true)) { this->velocity[0] = 1.0f; } @@ -429,7 +424,7 @@ void chMumbo_update(Actor *this) { } if (this->has_met_before) { subaddie_set_state(this, 3); - gcdialog_showDialog(VER_SELECT(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 0xA2D, 0, 0), 6, NULL, this->marker, __chMumbo_textCallback, NULL); + gcdialog_showDialog(ASSET_DAF_DIALOG_MUMBO_TREX_MISTAKE, 6, NULL, this->marker, __chMumbo_textCallback, NULL); break; } gcpausemenu_80314AC8(1); @@ -446,8 +441,8 @@ void chMumbo_update(Actor *this) { sp48 = chMumbo_withinHorzDistToPlayer(0, -0x6B, 0xBC); } if (sp48 != 0) { - gcdialog_showDialog(VER_SELECT(ASSET_DA7_DIALOG_MUMBO_CCW_SUMMER, 0xA25, 0, 0), 7, NULL, NULL, NULL, NULL); - volatileFlag_set(VOLATILE_FLAG_11, TRUE); + gcdialog_showDialog(ASSET_DA7_DIALOG_MUMBO_CCW_SUMMER, 7, NULL, NULL, NULL, NULL); + volatileFlag_set(VOLATILE_FLAG_11, true); } } actor_loopAnimation(this); @@ -462,8 +457,8 @@ void chMumbo_update(Actor *this) { sp48 = chMumbo_withinHorzDistToPlayer(0, -0x6B, 0xBC); } if (sp48 != 0) { - gcdialog_showDialog(VER_SELECT(ASSET_DA8_DIALOG_MUMBO_CCW_AUTUMN, 0xA26, 0, 0), 7, NULL, NULL, NULL, NULL); - volatileFlag_set(VOLATILE_FLAG_12, TRUE); + gcdialog_showDialog(ASSET_DA8_DIALOG_MUMBO_CCW_AUTUMN, 7, NULL, NULL, NULL, NULL); + volatileFlag_set(VOLATILE_FLAG_12, true); } } actor_loopAnimation(this); @@ -494,12 +489,12 @@ Actor *chMumbo_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { f32 sp44[3]; f32* sp38 = D_80367510; - modelRender_setAppendageVisibility(4, (this->lifetime_value == 0.0f)); - modelRender_setAppendageVisibility(5, (this->lifetime_value == 1.0f)); - modelRender_setAppendageVisibility(6, (this->lifetime_value == 0.0f)); - modelRender_setAppendageVisibility(7, (this->lifetime_value == 1.0f)); - modelRender_setAppendageVisibility(8, (this->lifetime_value == 2.0f)); - modelRender_setAppendageVisibility(9, 0); + func_8033A45C(4, (this->lifetime_value == 0.0f)); + func_8033A45C(5, (this->lifetime_value == 1.0f)); + func_8033A45C(6, (this->lifetime_value == 0.0f)); + func_8033A45C(7, (this->lifetime_value == 1.0f)); + func_8033A45C(8, (this->lifetime_value == 2.0f)); + func_8033A45C(9, 0); out = actor_draw(marker, gfx, mtx, vtx); if( marker->unk14_21 && out->state == 8){ if( actor_animationIsAt(out, 0.2f) @@ -514,30 +509,26 @@ Actor *chMumbo_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { } void chMumbo_detransformWarn(NodeProp *arg0, ActorMarker *arg1){ - if (EventSystem_Should(VB_MUMBO_DETRANSFORM, true)) { - s32 xform; - xform = player_getTransformation(); - if (xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || sHasWarnedBanjoAboutDetransform) - return; - - sHasWarnedBanjoAboutDetransform++; - if (D_8037DDF3) - return; - - gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_83_MAGIC_GET_WEAK_TEXT, TRUE) ? VER_SELECT(ASSET_F5C_DIALOG_MUMBO_MAGIC_GET_WEAK_ABREV, 0xAC2, 0, 0) : VER_SELECT(ASSET_F5B_DIALOG_MUMBO_MAGIC_GET_WEAK_FULL, 0xAC1, 0, 0), 0xe, NULL, NULL, NULL, NULL); - } + s32 xform; + xform = player_getTransformation(); + if(xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || sHasWarnedBanjoAboutDetransform) + return; + + sHasWarnedBanjoAboutDetransform++; + if(D_8037DDF3) + return; + + gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_83_MAGIC_GET_WEAK_TEXT, true) ? ASSET_F5C_DIALOG_MUMBO_MAGIC_GET_WEAK_ABREV : ASSET_F5B_DIALOG_MUMBO_MAGIC_GET_WEAK_FULL, 0xe, NULL, NULL, NULL, NULL); } void chMumbo_detransformTrigger(NodeProp *arg0, ActorMarker *arg1){ - if (EventSystem_Should(VB_MUMBO_DETRANSFORM, true)) { - s32 xform; - xform = player_getTransformation(); - if (xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || D_8037DDF1) - return; - gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_84_MAGIC_ALL_GONE_TEXT, TRUE) ? VER_SELECT(ASSET_F5E_DIALOG_MUMBO_MAGIC_RUN_OUT_ABREV, 0xAC4, 0, 0) : VER_SELECT(ASSET_F5D_DIALOG_MUMBO_MAGIC_RUN_OUT_FULL, 0xAC3, 0, 0), 0xe, NULL, NULL, NULL, NULL); - D_8037DDF1++; - player_transform(TRANSFORM_1_BANJO); - } + s32 xform; + xform = player_getTransformation(); + if(xform == TRANSFORM_1_BANJO || xform == TRANSFORM_7_WISHWASHY || D_8037DDF1) + return; + gcdialog_showDialog(fileProgressFlag_getAndSet(FILEPROG_84_MAGIC_ALL_GONE_TEXT, true) ? ASSET_F5E_DIALOG_MUMBO_MAGIC_RUN_OUT_ABREV: ASSET_F5D_DIALOG_MUMBO_MAGIC_RUN_OUT_FULL, 0xe, NULL, NULL, NULL, NULL); + D_8037DDF1++; + func_8028FB88(TRANSFORM_1_BANJO); } void func_802D2CB8(void){ diff --git a/src/core2/nc/dynamicCam1.c b/src/core2/nc/dynamicCam1.c deleted file mode 100644 index eab3d2703..000000000 --- a/src/core2/nc/dynamicCam1.c +++ /dev/null @@ -1,50 +0,0 @@ -// BanjoDecomp: core2/nc/dynamicCam1.c -#include -#include "functions.h" -#include "variables.h" - -extern f32 func_802BD51C(void); -extern f32 player_getYaw(void); -extern void func_802BD870(f32, f32, f32, f32); - -void ncDynamicCam1_init(void){ - func_802BD870(12.0f, 10.0f, 120.0f, 120.0f); -} - -void ncDynamicCam1_end(void){} - -void ncDynamicCam1_update(void) { - f32 sp8C[3]; - f32 new_camera_position[3]; - f32 current_camera_position[3]; - f32 dst[3]; - f32 angles[3]; - f32 sp50[3]; - f32 position_z; - f32 phi; - f32 time_delta; - f32 sp40; - f32 sp3C; - - ncDynamicCamera_getPosition(current_camera_position); - func_802BD4C0(sp8C); - sp3C = func_802BD8D4(); - time_delta = time_getDelta(); - ml_vec3f_diff_copy(sp50, current_camera_position, sp8C); - position_z = sqrtf((sp50[0] * sp50[0]) + (sp50[2] * sp50[2])); - position_z += ml_clamp_abs_f((sp3C - position_z) * time_delta * 2, time_delta * 120.0f); - func_8025801C(sp50, &phi); - sp40 = ml_clamp_abs_f(mlDiffDegF(mlNormalizeAngle(180.0f + player_getYaw()), phi) * (time_delta * 1), time_delta * 50.0f); - phi = mlNormalizeAngle(phi + sp40); - func_80256E24(dst, 0.0f, phi, 0.0f, 0.0f, position_z); - ml_vec3f_add(new_camera_position, sp8C, dst); - new_camera_position[1] = current_camera_position[1] + ((func_802BD51C() - current_camera_position[1]) * time_delta * 2); - ncDynamicCamera_setPosition(new_camera_position); - ml_horizontal_and_vertical_angles( - sp8C[0], sp8C[1], sp8C[2], - new_camera_position[0], new_camera_position[1], new_camera_position[2], - &angles[0], &angles[1]); - angles[0] = -angles[0]; - angles[2] = 0.0f; - func_802BD720(angles); -} diff --git a/src/core2/particle/particleemittermanager.c b/src/core2/particle/accel.c similarity index 98% rename from src/core2/particle/particleemittermanager.c rename to src/core2/particle/accel.c index e501e9c7b..47aac78e1 100644 --- a/src/core2/particle/particleemittermanager.c +++ b/src/core2/particle/accel.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/particleemittermanager.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/dustemitter.c b/src/core2/particle/colordefault.c similarity index 98% rename from src/core2/particle/dustemitter.c rename to src/core2/particle/colordefault.c index 2dc63ae76..524dfd6aa 100644 --- a/src/core2/particle/dustemitter.c +++ b/src/core2/particle/colordefault.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/dustemitter.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/emitter1.c b/src/core2/particle/emitter1.c index ea01aca00..b3edf8f32 100644 --- a/src/core2/particle/emitter1.c +++ b/src/core2/particle/emitter1.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6CD20.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/emitter2.c b/src/core2/particle/emitter2.c index 6be9fcee8..28df752af 100644 --- a/src/core2/particle/emitter2.c +++ b/src/core2/particle/emitter2.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6CEC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/emitterstruct.c b/src/core2/particle/emitterstruct.c index 06c8cffb9..f0e136c48 100644 --- a/src/core2/particle/emitterstruct.c +++ b/src/core2/particle/emitterstruct.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CB050.c #include #include "functions.h" #include "variables.h" @@ -65,7 +64,7 @@ void func_80352114(Struct_core2_CB050_0 *arg0, Struct68s *arg1, f32 arg2) { arg0->unk64 = (f32) (arg0->unk64 + arg2); player_getPosition(player_position); if( (func_80294660() == 0x100) - && player_isStableWithExtraSteps() + && func_8028F20C() && (ml_vec3f_length_sq(player_position, arg0->unk4C) < 50000.0f) ) { sp58 = arg0->unk4C[0] - player_position[0]; diff --git a/src/core2/particle/commonParticleTypeMap.c b/src/core2/particle/factory.c similarity index 98% rename from src/core2/particle/commonParticleTypeMap.c rename to src/core2/particle/factory.c index d187c709b..592db456e 100644 --- a/src/core2/particle/commonParticleTypeMap.c +++ b/src/core2/particle/factory.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/commonParticleTypeMap.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/initcallback.c b/src/core2/particle/initcallback.c index e00fb760e..7afb94169 100644 --- a/src/core2/particle/initcallback.c +++ b/src/core2/particle/initcallback.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CBBF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/lifescale.c b/src/core2/particle/lifescale.c index d08fd8ee2..a2ca784cb 100644 --- a/src/core2/particle/lifescale.c +++ b/src/core2/particle/lifescale.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6A4B0.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/particle/particle.c b/src/core2/particle/particle.c index 27b0c0c04..025830472 100644 --- a/src/core2/particle/particle.c +++ b/src/core2/particle/particle.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/particle.c #include #include "core1/core1.h" #include "functions.h" @@ -52,17 +51,12 @@ typedef struct particle{ f32 velocity_50[3]; u8 unk5C; //u8 pad5D[3]; - // [port] Spawn serial; see the identity comment in __particleEmitter_drawOnPass. - u32 portSerial; } Particle; /* .bss */ f32 particleSfxTimer; u8 partEmitMgrEnable; -// [port] Monotonic source for Particle::portSerial. -static u32 sPortParticleSerial = 0; - /* .code */ void func_802EE930(ParticleEmitter *this){ func_8033B388(&this->sprite_1C, &this->unk34); @@ -126,7 +120,6 @@ void __particleEmitter_initParticle(ParticleEmitter *this, Particle *particle){ particle->angluar_velocity[1] = randf2(this->unkBC[1], this->unkC8[1]); particle->angluar_velocity[2] = randf2(this->unkBC[2], this->unkC8[2]); - particle->portSerial = ++sPortParticleSerial; // [port] interpolation identity particle->age_48 = 0.0f; particle->lifetime_4C = randf2(this->particleLifeTimeRange[0], this->particleLifeTimeRange[1]) + 0.001; if(!this->sphericalParticleVelocity_48){ @@ -171,10 +164,19 @@ void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, V return; if(this->model_20 != NULL){ - // [port] Stable scope per emitter + per particle, keyed on a spawn serial. + // [port] Stable scope per emitter + per particle. Slot index plus + // a coarse age bucket: two consecutive frames of the same particle + // land in the same bucket, so they pair. When expiry swaps a new + // particle into the slot its age resets to ~0 — different bucket, + // no false pair with the dead particle. Spawn-field hashing alone + // failed for sparkles (shared emitter, zero-width scale/lifetime + // ranges → every particle had the same hash → visible flashing). FrameInterpolation_RecordOpenChild("part_emit", FrameInterpolation_GetId(this)); for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){ - FrameInterpolation_RecordOpenChildHash3("part", (uint64_t)iPtr->portSerial, 0, 0); + FrameInterpolation_RecordOpenChildHash3("part", + (uint64_t)(uintptr_t)(iPtr - this->pList_start_124), + (uint64_t)(iPtr->age_48 * 2.0f), + 0); position[0] = iPtr->position[0] + this->unk4[0]; position[1] = iPtr->position[1] + this->unk4[1]; position[2] = iPtr->position[2] + this->unk4[2]; @@ -215,10 +217,13 @@ void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, V flat_rotation[0] = 90.0f; flat_rotation[1] = 0.0f; flat_rotation[2] = 0.0f; - // [port] Same spawn-serial identity as the model branch above. + // [port] Same slot+age-bucket identity as the model branch above. FrameInterpolation_RecordOpenChild("part_emit", FrameInterpolation_GetId(this)); for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){ - FrameInterpolation_RecordOpenChildHash3("part", (uint64_t)iPtr->portSerial, 0, 0); + FrameInterpolation_RecordOpenChildHash3("part", + (uint64_t)(uintptr_t)(iPtr - this->pList_start_124), + (uint64_t)(iPtr->age_48 * 2.0f), + 0); gDPSetPrimColor((*gfx)++, 0, 0, this->rgb[0], this->rgb[1], this->rgb[2], iPtr->fade*this->alpha); position[0] = iPtr->position[0] + this->unk4[0]; position[1] = iPtr->position[1] + this->unk4[1]; diff --git a/src/core2/particle/positionset.c b/src/core2/particle/positionset.c index 5bd1eecd4..1d493cc40 100644 --- a/src/core2/particle/positionset.c +++ b/src/core2/particle/positionset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_CD0A0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/samplerate.c b/src/core2/particle/samplerate.c index 4774b0c0c..ee9ebdf7a 100644 --- a/src/core2/particle/samplerate.c +++ b/src/core2/particle/samplerate.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6D490.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/scale1.c b/src/core2/particle/scale1.c index 13e9c8f2b..79802f1d3 100644 --- a/src/core2/particle/scale1.c +++ b/src/core2/particle/scale1.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_66D90.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/scale2.c b/src/core2/particle/scale2.c index d6bac730b..7fded4f8c 100644 --- a/src/core2/particle/scale2.c +++ b/src/core2/particle/scale2.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_66FB0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/spawn.c b/src/core2/particle/spawn.c index a2c1eb9fa..8b467a3ca 100644 --- a/src/core2/particle/spawn.c +++ b/src/core2/particle/spawn.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6D030.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/typeindex.c b/src/core2/particle/typeindex.c index 5feded98f..88a45f0b9 100644 --- a/src/core2/particle/typeindex.c +++ b/src/core2/particle/typeindex.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6AEF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/velocityrange.c b/src/core2/particle/velocityrange.c index 45bbcbf13..e810851a5 100644 --- a/src/core2/particle/velocityrange.c +++ b/src/core2/particle/velocityrange.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6B030.c #include "core1/core1.h" #include "functions.h" #include "variables.h" diff --git a/src/core2/particle/velocityset.c b/src/core2/particle/velocityset.c index 5728381ee..83d883c84 100644 --- a/src/core2/particle/velocityset.c +++ b/src/core2/particle/velocityset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_6D270.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/playerutils.c b/src/core2/playerutils.c index 6fc927ff6..524aa9a47 100644 --- a/src/core2/playerutils.c +++ b/src/core2/playerutils.c @@ -40,7 +40,7 @@ s32 can_climb(void){ return ability_hasLearned(ABILITY_5_CLIMB); } -bool can_dive(void){ +int can_dive(void){ return ability_hasLearned(ABILITY_F_DIVE) && !isPlayerInHazard() && 100.0f < floor_getCurrentFloorYPosition() - func_80294438(); @@ -50,7 +50,7 @@ s32 can_egg(void){ return ability_hasLearned(ABILITY_6_EGGS); } -bool can_feathery_flap(void){ +int can_feathery_flap(void){ return baflag_isFalse(BA_FLAG_12_HAS_FLAPPED) && baflag_isFalse(BA_FLAG_5_HAS_PECKED) && ability_hasLearned(ABILITY_7_FEATHERY_FLAP); @@ -68,18 +68,18 @@ s32 can_control_jump_height(void){ return ability_hasLearned(ABILITY_A_HOLD_A_JUMP_HIGHER); } -bool can_peck(void){ +int can_peck(void){ return baflag_isFalse(BA_FLAG_5_HAS_PECKED) && baflag_isFalse(BA_FLAG_12_HAS_FLAPPED) && ability_hasLearned(ABILITY_B_RATATAT_RAP); } -bool func_8028ABB8(void){ +int func_8028ABB8(void){ if(baflag_isTrue(BA_FLAG_14_LOSE_BOGGY_RACE) || baflag_isTrue(BA_FLAG_19_SHOULD_TRANSFORM)) - return false; + return 0; if(bs_getState() == BS_56_RECOIL) - return false; - return true; + return 0; + return 1; } s32 can_roll(void){ @@ -106,32 +106,32 @@ s32 can_wonderwing(void){ return ability_hasLearned(ABILITY_12_WONDERWING); } -bool can_view_first_person(void){ +int can_view_first_person(void){ if( gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK && mapSpecificFlags_get(0xd)){ - return false; + return 0; } - if(ncba1p_getState() == FIRSTPERSON_STATE_3_EXIT) - return false; + if(ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_3_EXIT) + return 0; if(!player_isStable() && !player_inWater()) - return false; - return true; + return 0; + return 1; } -bool dummy_player_is_ant(void){ +int dummy_player_is_ant(void){ return bsant_inSet(bs_getState()); } -bool dummy_player_is_pumpkin(void){ +int dummy_player_is_pumpkin(void){ return bspumpkin_inSet(bs_getState()); } -bool func_8028ADB4(void){ +int func_8028ADB4(void){ return func_8032190C() && gsworld_getMap() != MAP_1_SM_SPIRAL_MOUNTAIN; } -bool wishyWashyFlag_get(void){ +int wishyWashyFlag_get(void){ return volatileFlag_get(VOLATILE_FLAG_9D_SANDCASTLE_WISHY_WASHY); } @@ -141,7 +141,7 @@ bool dummy_player_withinIdealYaw(void) { f32 position[3]; f32 ideal_yaw; - playerPosition_get(position); + _player_getPosition(position); ideal_yaw = yaw_getIdeal(); right_angle = viewport_adjustAngleToRight(position, 90.0f); left_angle = viewport_adjustAngleToRight(position, 270.0f); @@ -153,37 +153,37 @@ bool dummy_player_withinIdealYaw(void) { } } -bool func_8028AED4(f32 src_position[3], f32 arg1) { - f32 player_position[3]; - f32 yaw; +bool func_8028AED4(f32 arg0[3], f32 arg1) { + f32 position[3]; + f32 sp28; u16 sp26; u16 sp24; s32 temp_v1; s32 phi_a0; - playerPosition_get(player_position); - func_80257F18(src_position, player_position, &yaw); - sp26 = (u16) (yaw * 182.044444); + _player_getPosition(position); + func_80257F18(arg0, position, &sp28); + sp26 = (u16) (sp28 * 182.044444); sp24 = (u16) (player_getYaw() * 182.044444); sp26 = (u16)((sp26 - sp24)); - temp_v1 = 0x8000 - sp26; // Flip sign? + temp_v1 = 0x8000 - sp26; phi_a0 = (temp_v1 >= 0) ? temp_v1 : -temp_v1; return (phi_a0 < arg1 * 182.044444); } -bool player_shouldFall(void){ - return (60.0f < playerPosition_getY() - func_80294438()); +int player_shouldFall(void){ + return (60.0f < player_getYPosition() - func_80294438()); } -bool player_isInHorizontalRadius(f32 arg0[3], f32 arg1){ +int player_isInHorizontalRadius(f32 arg0[3], f32 arg1){ f32 sp1C[3]; - playerPosition_get(sp1C); + _player_getPosition(sp1C); return ml_vec3f_point_within_horizontal_distance(sp1C, arg0[0], arg0[2], arg1); } s32 func_8028B120(void){return 0;} -bool player_isOnDangerousGround(void){ +int player_isOnDangerousGround(void){ return baflag_isTrue(BA_FLAG_13_TOUCHING_DANGEROUS_GROUND); } @@ -194,29 +194,29 @@ bool player_isInRBB(void){ bool player_isInVerticalRange(f32 position[3], f32 range) { f32 plyr_pos[3]; - playerPosition_get(plyr_pos); + _player_getPosition(plyr_pos); return (((position[1] - range) <= plyr_pos[1]) && (plyr_pos[1] <= (position[1] + range))); } -bool player_shouldSlideTrot(void){ +int player_shouldSlideTrot(void){ return stateTimer_isActive(STATE_TIMER_6_UNKNOWN) || (1.0 == get_slope_timer() && func_80294610(0x40)); } bool func_8028B254(s32 arg0) { - return (player_isStable() || (baphysics_get_vertical_velocity() < 0.0f && (playerPosition_getY() - func_80294438()) < (f32) arg0)); + return (player_isStable() || (baphysics_get_vertical_velocity() < 0.0f && (player_getYPosition() - func_80294438()) < (f32) arg0)); } -bool player_isStable(void){ +int player_isStable(void){ return D_8037BF60 && baphysics_get_vertical_velocity() < 0.0f; } -bool player_isSliding(void){ +int player_isSliding(void){ return stateTimer_isActive(STATE_TIMER_5_UNKNOWN) || 1.0 == get_slope_timer(); } -bool func_8028B394(void){ +int func_8028B394(void){ return func_8029CF20(4); } @@ -261,15 +261,15 @@ bool player_isSwimming(void){ return out; } -bool func_8028B4C4(void){ +int func_8028B4C4(void){ return 135.0f < mlAbsF(mlDiffDegF(yaw_getIdeal(), yaw_get())); } -bool player_inWater(void){ +int player_inWater(void){ return D_8037BF61; } -bool func_8028B528(void){ +int func_8028B528(void){ return D_8037BF62; } @@ -290,9 +290,9 @@ void func_8028B59C(void) { sp24 = D_8037BF61; if (D_8037BF61) { - D_8037BF61 = (func_80294554() && playerPosition_getY() < ((floor_getCurrentFloorYPosition() - 50.0f) + 2.0f)); + D_8037BF61 = (func_80294554() && player_getYPosition() < ((floor_getCurrentFloorYPosition() - 50.0f) + 2.0f)); } else { - D_8037BF61 = (func_80294554() && playerPosition_getY() < ((floor_getCurrentFloorYPosition() - 50.0f) - 2.0f)); + D_8037BF61 = (func_80294554() && player_getYPosition() < ((floor_getCurrentFloorYPosition() - 50.0f) - 2.0f)); } if (gsworld_getMap() == MAP_6_TTC_NIPPERS_SHELL) { D_8037BF61 = false; diff --git a/src/core2/propModelList.c b/src/core2/prop_assetcache.c similarity index 99% rename from src/core2/propModelList.c rename to src/core2/prop_assetcache.c index 7dd8feb07..9db6a69a2 100644 --- a/src/core2/propModelList.c +++ b/src/core2/prop_assetcache.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/propModelList.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/quiz/quizquestionaskedbitfield.c b/src/core2/quiz/bitfield.c similarity index 81% rename from src/core2/quiz/quizquestionaskedbitfield.c rename to src/core2/quiz/bitfield.c index 466c4a9d7..cd7d27584 100644 --- a/src/core2/quiz/quizquestionaskedbitfield.c +++ b/src/core2/quiz/bitfield.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/quizquestionaskedbitfield.c #include #include "functions.h" #include "variables.h" @@ -10,7 +9,7 @@ u8* quizQuestionAskedBitfield; /* .code */ bool quizQuestionAskedBitfield_get(s32 index){ - return bitfieldarray_getBit(quizQuestionAskedBitfield, index); + return bitfield_get_bit(quizQuestionAskedBitfield, index); } void quizQuestionAskedBitfield_free(void){ @@ -27,7 +26,7 @@ void quizQuestionAskedBitfield_init(void){ } void quizQuestionAskedBitfield_set(s32 index, bool value){ - bitfieldarray_setBit(quizQuestionAskedBitfield, index, value); + bitfield_set_bit(quizQuestionAskedBitfield, index, value); } void quizQuestionAskedBitfield_defrag(void){ diff --git a/src/core2/quiz/game.c b/src/core2/quiz/game.c index a058abd6e..fc740563c 100644 --- a/src/core2/quiz/game.c +++ b/src/core2/quiz/game.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_4C020.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -13,28 +12,25 @@ extern void func_802F9D38(s32); extern void func_802EE2E8(Actor *arg0, s32 arg1, s32 cnt, s32 arg3, f32 arg4, f32 arg5, f32 arg6); extern void gcquiz_func_80319EA4(void); -extern void port_lairWater_onRiseTrigger(int32_t waterMap, int32_t levelFlag); -extern int32_t port_lairWater_targetLevel(int32_t map, int32_t flagLevel); - -void chMMMBreakableWooden_update(Actor *this); -void gWorldExitPad_update(Actor *this); -Actor *gWorldExitPad_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chSnsEgg_update(Actor *this); -Actor *chSnsEgg_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chIceKey_update(Actor *this); -void chMumboSwitch_update(Actor *this); -Actor *chMumboSwitch_draw(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); -void chFFTeleportPad_Update(Actor *this); -void chMMWitchSwitch_update(Actor *this); -void chCCWitchSwitch_update(Actor *this); -void chBGSWitchSwitch_update(Actor *this); -void chGVWitchSwitch_update(Actor *this); -void chMMMWitchSwitch_update(Actor *this); -void chTTCWitchSwitch_update(Actor *this); -void chRBBWitchSwitch_update(Actor *this); -void chCCWWitchSwitch_update(Actor *this); -void chFPWitchSwitch_update(Actor *this); -void code_4C020_setHourglassTimer(s32 seconds); +void func_802D3D54(Actor *this); +void func_802D3DA4(Actor *this); +Actor *func_802D3F48(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void func_802D3FD4(Actor *this); +Actor *func_802D41C4(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void func_802D4250(Actor *this); +void func_802D4388(Actor *this); +Actor *func_802D4588(ActorMarker *this, Gfx **gdl, Mtx **mptr, Vtx **arg3); +void func_802D4680(Actor *this); +void func_802D4B94(Actor *this); +void func_802D4BBC(Actor *this); +void func_802D4BE4(Actor *this); +void func_802D4C0C(Actor *this); +void func_802D4C34(Actor *this); +void func_802D4C5C(Actor *this); +void func_802D4C84(Actor *this); +void func_802D4CAC(Actor *this); +void func_802D4CD4(Actor *this); +void func_802D68F0(s32 seconds); typedef struct { s16 unk0; @@ -57,7 +53,7 @@ f32 D_803676A4 = 0.0f; s32 D_803676A8 = 0; u8 D_803676AC = 0; -ActorAnimationInfo gSwitchAnimations[] = { +ActorAnimationInfo D_803676B0[] = { {0x000, 0.0f}, {0x000, 0.0f}, {ASSET_D4_ANIM_SWITCH_DOWN, 0.15f}, @@ -82,67 +78,24 @@ ActorAnimationInfo gSwitchAnimations[] = { {ASSET_217_ANIM_UNKNOWN, 0.3f} }; -ActorInfo D_80367760 = { - MARKER_26E_UNKNOWN, ACTOR_2D9_UNKNOWN, ASSET_3B4_MODEL_UNUSED, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo D_80367784 = { - MARKER_26F_UNKNOWN, ACTOR_2DA_UNKNOWN, ASSET_3B5_MODEL_UNUSED, - 0x1, NULL, - chMMMBreakableWooden_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chIceKey = { - MARKER_168_ICE_KEY, ACTOR_25D_ICE_KEY, ASSET_50C_MODEL_ICE_KEY, - 0x1, NULL, - chIceKey_update, actor_update_func_80326224, actor_drawFullDepth, - 0, 0, 0.0f, 0 -}; - -ActorInfo chMumboSwitch = { - MARKER_233_MUMBO_SWITCH, ACTOR_23D_MUMBO_SWITCH, ASSET_4DD_MODEL_MUMBO_SWITCH, - 0x12, gSwitchAnimations, - chMumboSwitch_update, actor_update_func_80326224, chMumboSwitch_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chFFTeleportPad = { - MARKER_16A_FF_TELEPORT_PAD, ACTOR_242_FF_TELEPORT_PAD, 0x0, - 0x0, NULL, - chFFTeleportPad_Update, NULL, func_80325340, - 0, 0, 0.0f, 0 -}; - -ActorInfo chSnsEgg = { - MARKER_169_SNS_EGG, ACTOR_25E_SNS_EGG, ASSET_50D_MODEL_SNS_EGG, - 0x1, NULL, - chSnsEgg_update, NULL, chSnsEgg_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo gWorldExitPad = { - MARKER_265_WORLD_EXIT_PAD, ACTOR_2E4_WORLD_EXIT_PAD, ASSET_55A_MODEL_WORLD_EXIT_PAD, - 0x1, NULL, - gWorldExitPad_update, NULL, gWorldExitPad_draw, - 0, 0, 0.0f, 0 -}; - -ActorInfo chMMWitchSwitch = { MARKER_103_MM_WITCH_SWITCH, ACTOR_204_MM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chMMWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chMMMWitchSwitch = { MARKER_104_MMM_WITCH_SWITCH, ACTOR_206_MMM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chMMMWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chTTCWitchSwitch = { MARKER_105_TTC_WITCH_SWITCH, ACTOR_208_TTC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chTTCWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chRBBWitchSwitch = { MARKER_106_RBB_WITCH_SWITCH, ACTOR_20B_RBB_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chRBBWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chCCWWitchSwitch = { MARKER_22A_CCW_WITCH_SWITCH, ACTOR_237_CCW_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chCCWWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chFPWitchSwitch = { MARKER_22B_FP_WITCH_SWITCH, ACTOR_239_FP_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chFPWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chCCWitchSwitch = { MARKER_166_CC_WITCH_SWITCH, ACTOR_25B_CC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chCCWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chBGSWitchSwitch = { MARKER_162_BGS_WITCH_SWITCH, ACTOR_257_BGS_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chBGSWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; -ActorInfo chGVWitchSwitch = { MARKER_161_GV_WITCH_SWITCH, ACTOR_256_GV_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, gSwitchAnimations, chGVWitchSwitch_update, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367760 = { 0x26E, 0x2D9, 0x3B4, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_80367784 = { 0x26F, 0x2DA, 0x3B5, 0x1, NULL, func_802D3D54, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_803677A8 = { MARKER_168_ICE_KEY, ACTOR_25D_ICE_KEY, ASSET_50C_MODEL_ICE_KEY, 0x1, NULL, func_802D4250, actor_update_func_80326224, actor_drawFullDepth, 0, 0, 0.0f, 0}; +ActorInfo D_803677CC = { 0x233, 0x23D, 0x4DD, 0x12, D_803676B0, func_802D4388, actor_update_func_80326224, func_802D4588, 0, 0, 0.0f, 0}; +ActorInfo D_803677F0 = { 0x16A, 0x242, 0x0, 0x0, NULL, func_802D4680, NULL, func_80325340, 0, 0, 0.0f, 0}; +ActorInfo D_80367814 = { MARKER_169_SNS_EGG, ACTOR_25E_SNS_EGG, ASSET_50D_MODEL_SNS_EGG, 0x1, NULL, func_802D3FD4, NULL, func_802D41C4, 0, 0, 0.0f, 0}; +ActorInfo D_80367838 = { 0x265, 0x2E4, 0x55A, 0x1, NULL, func_802D3DA4, NULL, func_802D3F48, 0, 0, 0.0f, 0}; +ActorInfo D_8036785C = { MARKER_103_MM_WITCH_SWITCH, ACTOR_204_MM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4B94, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367880 = { MARKER_104_MMM_WITCH_SWITCH, ACTOR_206_MMM_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C34, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_803678A4 = { MARKER_105_TTC_WITCH_SWITCH, ACTOR_208_TTC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C5C, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_803678C8 = { MARKER_106_RBB_WITCH_SWITCH, ACTOR_20B_RBB_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C84, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_803678EC = { MARKER_22A_CCW_WITCH_SWITCH, ACTOR_237_CCW_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4CAC, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367910 = { MARKER_22B_FP_WITCH_SWITCH, ACTOR_239_FP_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4CD4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367934 = { MARKER_166_CC_WITCH_SWITCH, ACTOR_25B_CC_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4BBC, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_80367958 = { MARKER_162_BGS_WITCH_SWITCH, ACTOR_257_BGS_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4BE4, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; +ActorInfo D_8036797C = { MARKER_161_GV_WITCH_SWITCH, ACTOR_256_GV_WITCH_SWITCH, ASSET_4DC_MODEL_WITCH_SWITCH, 0x1, D_803676B0, func_802D4C0C, actor_update_func_80326224, actor_draw, 0, 0, 0.0f, 0}; s32 D_803679A0[4] = {0x87, 0x87, 0x87, 0xA0}; - s16 D_803679B0[] = { FILEPROG_5_BLUE_EGG_TEXT, FILEPROG_90_PAID_TERMITE_COST, @@ -162,7 +115,6 @@ Struct_core2_4C020_0 D_803679C8[] = { {-580, 0, 1550, 2200}, {150, 460, 1625, 2100}, }; - s16 D_803679E0[] = {-50, -100, 200}; /* .bss */ @@ -196,349 +148,226 @@ void func_802D2FB0(Actor *this, s32 arg1, s32 arg2, s32 arg3, f32 arg4, s32 arg5 // collision function if player shoots egg at spider webs void func_802D3138(ActorMarker *marker, ActorMarker *other_marker) { - if(marker->id == MARKER_224_BREAKABLE_FLOOR_COBWEB - || marker->id == MARKER_225_BREAKABLE_WALL_COBWEB) - { + if(marker->id == MARKER_224_BREAKABLE_FLOOR_COBWEB || marker->id == MARKER_225_BREAKABLE_WALL_COBWEB) { comusic_playTrack(COMUSIC_2B_DING_B); } } // called from collision die function below, set according file flag and despawns object -void code_4C020_breakableObjectSetFlag(ActorMarker *marker, enum file_progress_e prog_flag_id) { - fileProgressFlag_set(prog_flag_id, TRUE); +void func_802D317C(ActorMarker *marker, enum file_progress_e prog_flag_id) { + fileProgressFlag_set(prog_flag_id, true); marker_despawn(marker); } -extern void port_breakable_broadcastBreak(s32 markerId, s32 x, s32 y, s32 z); -extern s32 port_breakable_isBroken(s32 map, s32 markerId, s32 x, s32 y, s32 z); - // collision die function for several objects in Lair -void code_4C020_breakableObjectSfx(ActorMarker *marker, ActorMarker *other_marker) { - Actor *actor; - - actor = marker_getActor(marker); - marker->collidable = FALSE; - switch (marker->id) { - case MARKER_9F_CHURCH_GATE_LEFT_LOCK: - case MARKER_A0_HEDGE_GATE_RIGHT_LOCK_1: - case MARKER_FF_HEDGE_GATE_RIGHT_LOCK_2: - gcsfx_play(SFX_82_METAL_BREAK); - subaddie_set_state(actor, 4); - port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); +void func_802D31AC(ActorMarker *arg0, ActorMarker * arg1) { + Actor *sp2C; + + sp2C = marker_getActor(arg0); + arg0->collidable = false; + switch (arg0->id) { + case 0x9F: + case 0xA0: + case 0xFF: + gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); + subaddie_set_state(sp2C, 4); break; - case MARKER_17D_IRON_GATE_NO_LOCK: + case 0x17D: FUNC_8030E624(SFX_82_METAL_BREAK, 0.7f, 32736); FUNC_8030E624(SFX_82_METAL_BREAK, 0.6f, 32736); - func_802D2FB0(actor, 0x14, -0x1E, 0x190, 3.0f, 0x15E, 0x50, 0x96); - actor->lifetime_value = 1.0f; + func_802D2FB0(sp2C, 0x14, -0x1E, 0x190, 3.0f, 0x15E, 0x50, 0x96); + sp2C->lifetime_value = 1.0f; fileProgressFlag_set(FILEPROG_A5_LAIR_CRYPT_GATE_OPEN, 1); break; case MARKER_109_BREAKABLE_BRICK_WALL: func_8030E6D4(SFX_114_BRICKWALL_BREAKING); - gcsfx_playAtSampleRate(SFX_11_WOOD_BREAKING_1, 28000); - subaddie_set_state_looped(actor, 9); - fileProgressFlag_set((actor->actorTypeSpecificField == 1) ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN, TRUE); + sfxsource_play(SFX_11_WOOD_BREAKING_1, 28000); + subaddie_set_state_looped(sp2C, 9); + fileProgressFlag_set((sp2C->actorTypeSpecificField == 1) ? FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN : FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN, true); break; - case MARKER_107_ENGINE_ROOM_DOOR: - gcsfx_play(SFX_82_METAL_BREAK); - func_802EE278(actor, 0xE, 0xF, 0x46, 0.8f, 0.7f); - port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); - marker_despawn(marker); + case 0x107: + gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); + func_802EE278(sp2C, 0xE, 0xF, 0x46, 0.8f, 0.7f); + marker_despawn(arg0); break; case MARKER_224_BREAKABLE_FLOOR_COBWEB: comusic_playTrack(COMUSIC_2B_DING_B); - gcsfx_playWithPitch(SFX_129_SWOOSH, (actor->scale < 0.45) ? 1.0 : 0.8, 0x7FF8); - subaddie_set_state_looped(actor, 0xC); - func_802D2FB0(actor, 8, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); - fileProgressFlag_set((actor->actorTypeSpecificField== 1) ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN, 1); + gcsfx_playWithPitch(SFX_129_SWOOSH, (sp2C->scale < 0.45) ? 1.0 : 0.8, 0x7FF8); + subaddie_set_state_looped(sp2C, 0xC); + func_802D2FB0(sp2C, 8, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); + fileProgressFlag_set((sp2C->actorTypeSpecificField== 1) ? FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN : FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN, 1); break; case MARKER_225_BREAKABLE_WALL_COBWEB: comusic_playTrack(COMUSIC_2B_DING_B); - gcsfx_play(SFX_129_SWOOSH); - subaddie_set_state_looped(actor, 0xF); - func_802D2FB0(actor, 0xE, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); + gcsfx_playAtSampleRate(SFX_129_SWOOSH); + subaddie_set_state_looped(sp2C, 0xF); + func_802D2FB0(sp2C, 0xE, -0x3C, 0xC8, 2.0f, 0xFA, 0x3C, 0x64); fileProgressFlag_set(FILEPROG_CA_COBWEB_BLOCKING_PURPLE_CAULDRON_BROKEN, 1); break; - case MARKER_163_CRYPT_COFFIN_LID: - if (actor->unk10_12 == 0) { - actor->unk10_12 = TRUE; + case 0x163: + if (sp2C->unk10_12 == 0) { + sp2C->unk10_12 = true; timed_playSfx(0.5f, SFX_3F9_UNKNOWN, 1.0f, 32000); FUNC_8030E624(SFX_114_BRICKWALL_BREAKING, 0.8f, 32000); } break; - case MARKER_9A_1881_BARREL_TOP: - case MARKER_9C_SHACK_DOOR: - case MARKER_9D_MANSION_DOOR: - case MARKER_9E_CELLAR_HATCH: - case MARKER_A1_BLUBBER_SHIP_TOP_HATCH: - case MARKER_E7_DINING_DOOR: - case MARKER_EA_LIGHTHOUSE_DOOR: - case MARKER_108_CABIN_CLOSET_DOOR: - case MARKER_263_CCW_WHIPCRACK_ROOM_DOOR: - if ((marker->id == MARKER_9D_MANSION_DOOR) || (marker->id == MARKER_E7_DINING_DOOR)) { + case 0x9A: + case 0x9C: + case 0x9D: + case 0x9E: + case 0xA1: + case 0xE7: + case 0xEA: + case 0x108: + case 0x263: + if ((arg0->id == 0x9D) || (arg0->id == 0xE7)) { levelSpecificFlags_set(LEVEL_FLAG_2E_MMM_UNKNOWN, 1); } - if (marker->id == MARKER_263_CCW_WHIPCRACK_ROOM_DOOR) { + if (arg0->id == 0x263) { levelSpecificFlags_set(LEVEL_FLAG_38_CCW_UNKNOWN, 1); } - func_802D2FB0(actor, 5, -0x28, 0xC8, 0.85f, 0xDC, 0x3C, 0x64); - gcsfx_play(SFX_D_EGGSHELL_BREAKING); - gcsfx_play(SFX_11_WOOD_BREAKING_1); - switch (marker->id) { - case MARKER_9E_CELLAR_HATCH: - func_802EE278(actor, 0xD, 9, 0x82, 0.34f, 1.0f); + func_802D2FB0(sp2C, 5, -0x28, 0xC8, 0.85f, 0xDC, 0x3C, 0x64); + gcsfx_playAtSampleRate(SFX_D_EGGSHELL_BREAKING); + gcsfx_playAtSampleRate(SFX_11_WOOD_BREAKING_1); + switch (arg0->id) { + case 0x9E: + func_802EE278(sp2C, 0xD, 9, 0x82, 0.34f, 1.0f); break; - case MARKER_9D_MANSION_DOOR: - case MARKER_E7_DINING_DOOR: - case MARKER_108_CABIN_CLOSET_DOOR: - func_802EE278(actor, 7, 6, 0x32, 0.4f, 1.1f); - func_802EE278(actor, 7, 6, 0xB4, 0.4f, 1.1f); + case 0x9D: + case 0xE7: + case 0x108: + func_802EE278(sp2C, 7, 6, 0x32, 0.4f, 1.1f); + func_802EE278(sp2C, 7, 6, 0xB4, 0.4f, 1.1f); break; - case MARKER_9A_1881_BARREL_TOP: - case MARKER_9C_SHACK_DOOR: - case MARKER_263_CCW_WHIPCRACK_ROOM_DOOR: - func_802EE278(actor, 7, 0xA, 0x82, 0.3f, 0.8f); + case 0x9A: + case 0x9C: + case 0x263: + func_802EE278(sp2C, 7, 0xA, 0x82, 0.3f, 0.8f); break; - case MARKER_A1_BLUBBER_SHIP_TOP_HATCH: - func_802EE278(actor, 7, 9, 0x82, 0.3f, 0.6f); + case 0xA1: + func_802EE278(sp2C, 7, 9, 0x82, 0.3f, 0.6f); break; - case MARKER_EA_LIGHTHOUSE_DOOR: - func_802EE278(actor, 3, 9, 0x82, 0.21f, 0.8f); + case 0xEA: + func_802EE278(sp2C, 3, 9, 0x82, 0.21f, 0.8f); break; default: - func_802EE278(actor, 7, 0x19, 0x82, 0.17f, 0.8f); + func_802EE278(sp2C, 7, 0x19, 0x82, 0.17f, 0.8f); break; } - port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); - marker_despawn(marker); + marker_despawn(arg0); break; - case MARKER_11F_RAREWARE_BOX: - gcsfx_play(SFX_D9_WOODEN_CRATE_BREAKING_1); - func_802EE2E8(actor, 7, 9, 0x78, 0.43f, 1.3f, 3.0f); - func_802EE2E8(actor, 3, 6, 0x78, 0.43f, 1.3f, 3.0f); - code_4C020_breakableObjectSetFlag(marker, FILEPROG_C5_RAREWARE_BOX_BROKEN); + case 0x11F: + gcsfx_playAtSampleRate(SFX_D9_WOODEN_CRATE_BREAKING_1); + func_802EE2E8(sp2C, 7, 9, 0x78, 0.43f, 1.3f, 3.0f); + func_802EE2E8(sp2C, 3, 6, 0x78, 0.43f, 1.3f, 3.0f); + func_802D317C(arg0, FILEPROG_C5_RAREWARE_BOX_BROKEN); break; - case MARKER_11A_GRATE_TO_RBB_PUZZLE: - gcsfx_play(SFX_82_METAL_BREAK); - func_802EE278(actor, 0xE, 0xD, 0x32, 0.8f, 0.9f); - func_802EE278(actor, 0xE, 0xD, 0xAA, 0.8f, 0.9f); - code_4C020_breakableObjectSetFlag(marker, FILEPROG_C2_GRATE_TO_RBB_PUZZLE_OPEN); + case 0x11A: + gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); + func_802EE278(sp2C, 0xE, 0xD, 0x32, 0.8f, 0.9f); + func_802EE278(sp2C, 0xE, 0xD, 0xAA, 0.8f, 0.9f); + func_802D317C(arg0, FILEPROG_C2_GRATE_TO_RBB_PUZZLE_OPEN); break; - case MARKER_118_GRATE_TO_LEVEL_3_WATER_SWITCH: - gcsfx_play(SFX_82_METAL_BREAK); - func_802EE278(actor, 0xE, 0xD, 0x50, 1.2f, 0.9f); - func_802EE278(actor, 0xE, 0xD, 0xB4, 1.2f, 0.9f); - code_4C020_breakableObjectSetFlag(marker, FILEPROG_CD_GRATE_TO_WATER_SWITCH_3_OPEN); + case 0x118: + gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); + func_802EE278(sp2C, 0xE, 0xD, 0x50, 1.2f, 0.9f); + func_802EE278(sp2C, 0xE, 0xD, 0xB4, 1.2f, 0.9f); + func_802D317C(arg0, FILEPROG_CD_GRATE_TO_WATER_SWITCH_3_OPEN); break; - case MARKER_119_GRATE_BETWEEN_MMM_AND_RBB_PUZZLES: - gcsfx_play(SFX_82_METAL_BREAK); - func_802EE278(actor, 0xE, 9, 0x50, 1.2f, 0.9f); - func_802EE278(actor, 0xE, 9, 0xAA, 1.2f, 0.9f); - func_802EE278(actor, 0xE, 9, 0x104, 1.2f, 0.9f); - code_4C020_breakableObjectSetFlag(marker, FILEPROG_CE_GRATE_TO_MMM_PUZZLE_OPEN); + case 0x119: + gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); + func_802EE278(sp2C, 0xE, 9, 0x50, 1.2f, 0.9f); + func_802EE278(sp2C, 0xE, 9, 0xAA, 1.2f, 0.9f); + func_802EE278(sp2C, 0xE, 9, 0x104, 1.2f, 0.9f); + func_802D317C(arg0, FILEPROG_CE_GRATE_TO_MMM_PUZZLE_OPEN); break; - case MARKER_22D_SHIP_SHADOW_WINDOW: - case MARKER_22E_SHIP_SUNNY_WINDOW: - gcsfx_play(SFX_82_METAL_BREAK); - gcsfx_play(SFX_B6_GLASS_BREAKING_1); - func_802EE278(actor, 4, 0x23, 0x1E, 0.7f, 0.6f); - port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); - marker_despawn(marker); + case 0x22D: + case 0x22E: + gcsfx_playAtSampleRate(SFX_82_METAL_BREAK); + gcsfx_playAtSampleRate(SFX_B6_GLASS_BREAKING_1); + func_802EE278(sp2C, 4, 0x23, 0x1E, 0.7f, 0.6f); + marker_despawn(arg0); break; - case MARKER_123_WINDOW: - case MARKER_1F2_WIDE_WINDOW: - case MARKER_1F3_TALL_WINDOW: - case MARKER_235_CRACKED_SKYLIGHT: - case MARKER_236_CCW_UNKNOWN_NABNUT_WINDOW: - case MARKER_237_CCW_AUTUMN_NABNUT_WINDOW: - case MARKER_238_CCW_WINTER_NABNUT_WINDOW: - case MARKER_239_CCW_UNKNOWN_NABNUT_WINDOW: - gcsfx_play(SFX_13A_GLASS_BREAKING_7); - func_802EE278(actor, 4, 0x2D, 0x82, 1.0f, 1.0f); - if (marker->id == MARKER_1F3_TALL_WINDOW) { - func_802EE278(actor, 4, 0x2D, 0x104, 1.0f, 1.0f); + case 0x123: + case 0x1F2: + case 0x1F3: + case 0x235: + case 0x236: + case 0x237: + case 0x238: + case 0x239: + gcsfx_playAtSampleRate(SFX_13A_GLASS_BREAKING_7); + func_802EE278(sp2C, 4, 0x2D, 0x82, 1.0f, 1.0f); + if (arg0->id == 0x1F3) { + func_802EE278(sp2C, 4, 0x2D, 0x104, 1.0f, 1.0f); } - port_breakable_broadcastBreak(marker->id, (s32)actor->position[0], (s32)actor->position[1], (s32)actor->position[2]); - marker_despawn(marker); + marker_despawn(arg0); break; - case MARKER_11E_ICE_BALL_TO_CHEATO: - gcsfx_play(SFX_B6_GLASS_BREAKING_1); - func_802EE278(actor, 4, 0x32, 0x50, 1.0f, 1.4f); - func_802EE278(actor, 4, 0x32, 0xA0, 1.0f, 1.4f); - func_802EE278(actor, 4, 0x1E, 0xF0, 0.8f, 1.1f); - code_4C020_breakableObjectSetFlag(marker, FILEPROG_C3_ICE_BALL_TO_CHEATO_BROKEN); + case 0x11E: + gcsfx_playAtSampleRate(SFX_B6_GLASS_BREAKING_1); + func_802EE278(sp2C, 4, 0x32, 0x50, 1.0f, 1.4f); + func_802EE278(sp2C, 4, 0x32, 0xA0, 1.0f, 1.4f); + func_802EE278(sp2C, 4, 0x1E, 0xF0, 0.8f, 1.1f); + func_802D317C(arg0, FILEPROG_C3_ICE_BALL_TO_CHEATO_BROKEN); break; case MARKER_121_GLASS_EYE: - gcsfx_play(SFX_B6_GLASS_BREAKING_1); - func_802EE2E8(actor, 1, 0x32, 0x14, 1.2f, 1.4f, 2.2f); - func_802EE2E8(actor, 1, 0x3C, 0x64, 1.6f, 1.8f, 2.2f); - func_802EE2E8(actor, 1, 0x32, 0xB4, 1.2f, 1.4f, 2.2f); - code_4C020_breakableObjectSetFlag(marker, FILEPROG_C4_STATUE_EYE_BROKEN); + gcsfx_playAtSampleRate(SFX_B6_GLASS_BREAKING_1); + func_802EE2E8(sp2C, 1, 0x32, 0x14, 1.2f, 1.4f, 2.2f); + func_802EE2E8(sp2C, 1, 0x3C, 0x64, 1.6f, 1.8f, 2.2f); + func_802EE2E8(sp2C, 1, 0x32, 0xB4, 1.2f, 1.4f, 2.2f); + func_802D317C(arg0, FILEPROG_C4_STATUE_EYE_BROKEN); break; - case MARKER_164_GL_GRUNTY_FLOOR_PICTURE_EYE_1: - case MARKER_165_GL_GRUNTY_FLOOR_PICTURE_EYE_2: - if (actor->unk1C[1] == actor->position[1]) { - gcsfx_playAtSampleRate(SFX_9B_BOULDER_BREAKING_1, 25000); - actor->unk1C[0] = 1.0f; + case 0x164: + case 0x165: + if (sp2C->unk1C[1] == sp2C->position[1]) { + sfxsource_play(SFX_9B_BOULDER_BREAKING_1, 25000); + sp2C->unk1C[0] = 1.0f; } break; default: - gcsfx_play(SFX_D_EGGSHELL_BREAKING); - gcsfx_play(SFX_11_WOOD_BREAKING_1); - marker_despawn(marker); + gcsfx_playAtSampleRate(SFX_D_EGGSHELL_BREAKING); + gcsfx_playAtSampleRate(SFX_11_WOOD_BREAKING_1); + marker_despawn(arg0); break; } } -// unused -void code_4C020_unusedBreakableObjectSfx(ActorMarker *marker){ - code_4C020_breakableObjectSfx(marker, NULL); +void func_802D3CC8(ActorMarker *marker){ + func_802D31AC(marker, NULL); } // used as init function void func_802D3CE8(Actor *this){ if(!this->initialized){ - marker_setCollisionScripts(this->marker, NULL, func_802D3138, code_4C020_breakableObjectSfx); - this->marker->propPtr->unk8_3 = TRUE; - this->initialized = TRUE; - if (port_breakable_isBroken((s32)gsworld_getMap(), this->marker->id, (s32)this->position[0], - (s32)this->position[1], (s32)this->position[2])) { - marker_despawn(this->marker); - } - } -} - -extern ActorArray *suBaddieActorArray; - -// fieldSel picks between two markers sharing an id: 0 = any, 1 = actorTypeSpecificField==1, 2 = !=1. -typedef struct { - s16 flag; - s16 markerId; - s8 fieldSel; -} LairBreakable; - -static const LairBreakable D_lairBreakables[] = { - { FILEPROG_A5_LAIR_CRYPT_GATE_OPEN, 0x17D, 0 }, - { FILEPROG_C2_GRATE_TO_RBB_PUZZLE_OPEN, 0x11A, 0 }, - { FILEPROG_C3_ICE_BALL_TO_CHEATO_BROKEN, 0x11E, 0 }, - { FILEPROG_C4_STATUE_EYE_BROKEN, MARKER_121_GLASS_EYE, 0 }, - { FILEPROG_C5_RAREWARE_BOX_BROKEN, 0x11F, 0 }, - { FILEPROG_C8_LAIR_BRICKWALL_TO_WADINGBOOTS_BROKEN, MARKER_109_BREAKABLE_BRICK_WALL, 1 }, - { FILEPROG_C9_LAIR_BRICKWALL_TO_SHOCKJUMP_PAD_BROKEN, MARKER_109_BREAKABLE_BRICK_WALL, 2 }, - { FILEPROG_CA_COBWEB_BLOCKING_PURPLE_CAULDRON_BROKEN, MARKER_225_BREAKABLE_WALL_COBWEB, 0 }, - { FILEPROG_CB_LAIR_COBWEB_OVER_FLIGHTPAD_BROKEN, MARKER_224_BREAKABLE_FLOOR_COBWEB, 1 }, - { FILEPROG_CC_LAIR_COBWEB_OVER_GREEN_CAULDRON_BROKEN, MARKER_224_BREAKABLE_FLOOR_COBWEB, 2 }, - { FILEPROG_CD_GRATE_TO_WATER_SWITCH_3_OPEN, 0x118, 0 }, - { FILEPROG_CE_GRATE_TO_MMM_PUZZLE_OPEN, 0x119, 0 }, -}; - -void port_breakable_remoteBreak(s32 progressFlag) { - s32 i; - s16 markerId = -1; - s8 fieldSel = 0; - - for (i = 0; i < (s32) (sizeof(D_lairBreakables) / sizeof(D_lairBreakables[0])); i++) { - if (D_lairBreakables[i].flag == progressFlag) { - markerId = D_lairBreakables[i].markerId; - fieldSel = D_lairBreakables[i].fieldSel; - break; - } - } - if (markerId < 0 || suBaddieActorArray == NULL) { - return; - } - for (i = 0; i < suBaddieActorArray->cnt; i++) { - Actor *actor = &suBaddieActorArray->data[i]; - if (actor->marker == NULL || actor->marker->id != markerId) { - continue; - } - if ((fieldSel == 1 && actor->actorTypeSpecificField != 1) || - (fieldSel == 2 && actor->actorTypeSpecificField == 1)) { - continue; - } - code_4C020_breakableObjectSfx(actor->marker, NULL); - return; - } -} - -void port_breakable_remoteBreakAt(s32 markerId, s32 x, s32 y, s32 z) { - s32 i; - - if (suBaddieActorArray == NULL) { - return; - } - for (i = 0; i < suBaddieActorArray->cnt; i++) { - Actor *actor = &suBaddieActorArray->data[i]; - if (actor->marker == NULL || actor->marker->id != markerId) { - continue; - } - if ((s32)actor->position[0] != x || (s32)actor->position[1] != y || (s32)actor->position[2] != z) { - continue; - } - code_4C020_breakableObjectSfx(actor->marker, NULL); - return; - } -} - -static bool port_breakable_survivesBreak(s32 markerId) { - switch (markerId) { - case MARKER_34_CEMETARY_POT: // flowers - case MARKER_66_ORANGE_PAD: // stays, marked hit - return TRUE; - default: - return FALSE; - } -} - -// [port] Iterates backward: despawn swap-removes from the end. -void port_breakable_despawnBrokenRestores(s32 map) { - s32 i; - - if (suBaddieActorArray == NULL) { - return; - } - for (i = suBaddieActorArray->cnt - 1; i >= 0; i--) { - Actor *actor = &suBaddieActorArray->data[i]; - if (actor->marker == NULL || actor->despawn_flag) { - continue; - } - if (port_breakable_survivesBreak(actor->marker->id)) { - continue; - } - if (port_breakable_isBroken(map, actor->marker->id, (s32)actor->position[0], (s32)actor->position[1], - (s32)actor->position[2])) { - marker_despawn(actor->marker); - } + marker_setCollisionScripts(this->marker, NULL, func_802D3138, func_802D31AC); + this->marker->propPtr->unk8_3 = true; + this->initialized = true; } } -s32 port_cutsceneWarp_getReturnMap(void) { - return D_80367694; -} - -void chMMMBreakableWooden_update(Actor *this){ +void func_802D3D54(Actor *this){ func_802D3CE8(this); } @@ -548,8 +377,8 @@ void func_802D3D74(Actor *this){ actor_collisionOff(this); } -void gWorldExitPad_update(Actor *this) { - f32 player_position[3]; +void func_802D3DA4(Actor *this) { + f32 sp24[3]; s32 phi_v0; // [port] anti-tamper: dereferences raw N64 physical address 0x22C — crashes on PC @@ -565,29 +394,20 @@ void gWorldExitPad_update(Actor *this) { this->marker->propPtr->unk8_3 = true; this->unk38_31 = 0; } - player_getPosition(player_position); - phi_v0 = - ( - (this->position[1] - 5.0f) <= player_position[1]) - && (player_position[1] <= (this->position[1] + 30.0f) - ) - && (( - (player_position[0] - this->position[0]) - * (player_position[0] - this->position[0]) - + (player_position[2] - this->position[2]) - * (player_position[2] - this->position[2]) - ) < 3025.0f); + player_getPosition(sp24); + phi_v0 = ((this->position[1] - 5.0f) <= sp24[1]) && (sp24[1] <= (this->position[1] + 30.0f)) + && (((sp24[0] - this->position[0])*(sp24[0] - this->position[0]) + (sp24[2] - this->position[2])*(sp24[2] - this->position[2])) < 3025.0f); if ((this->unk38_31 == 0) && (phi_v0 == 0)) { this->unk38_31 = 1; } if ((this->unk38_31 == 1) && (phi_v0 == 1) - && player_isStableWithExtraSteps() && (func_8028F66C(BS_INTR_37) == 2)) { + && func_8028F20C() && (func_8028F66C(BS_INTR_37) == 2)) { this->unk38_31 = 2; } } -Actor *gWorldExitPad_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ +Actor *func_802D3F48(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ s32 phi_s2; Actor *this; s32 i; @@ -595,12 +415,12 @@ Actor *gWorldExitPad_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ this = marker_getActor(marker); phi_s2 = this->actorTypeSpecificField; for(i = 0; i < 9; i++){ - modelRender_setAppendageVisibility(i + 1, i + 1 == phi_s2); + func_8033A45C(i + 1, i+1 == phi_s2); } return actor_drawFullDepth(marker, gfx, mtx, vtx); } -void chSnsEgg_update(Actor *this){ +void func_802D3FD4(Actor *this){ if(!this->initialized){ this->initialized = true; func_802D3CE8(this); @@ -654,21 +474,21 @@ void chSnsEgg_update(Actor *this){ } } -Actor *chSnsEgg_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ - s32 actor_type_specific_field; +Actor *func_802D41C4(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){ + s32 sp2C; Actor *this; s32 i; this = marker_getActor(marker); - actor_type_specific_field = this->actorTypeSpecificField; + sp2C = this->actorTypeSpecificField; for(i = 0; i < 6; i++){ - modelRender_setAppendageVisibility(i + 1, FALSE); + func_8033A45C(i+1, false); } - modelRender_setAppendageVisibility(actor_type_specific_field, TRUE); + func_8033A45C(sp2C, true); return actor_drawFullDepth(marker, gfx, mtx, vtx); } -void chIceKey_update(Actor *this){ +void func_802D4250(Actor *this){ if(!this->initialized){ this->initialized = true; func_802D3CE8(this); @@ -688,7 +508,8 @@ void chIceKey_update(Actor *this){ bool func_802D42F8(Actor *this) { s32 i; - for(i = 0; D_803679B0[i] != -1 && this->actorTypeSpecificField != D_803679B0[i]; i+=2){} + for(i = 0; D_803679B0[i] != -1 && this->actorTypeSpecificField != D_803679B0[i]; i+=2){ + } if (D_803679B0[i] == -1) { return false; @@ -699,10 +520,10 @@ bool func_802D42F8(Actor *this) { } -void chMumboSwitch_update(Actor *this){ +void func_802D4388(Actor *this){ func_802D3CE8(this); this->unk38_0 = BOOL(gsworld_getMap() == MAP_7A_GL_CRYPT || item_getCount(ITEM_1C_MUMBO_TOKEN) >= this->actorTypeSpecificField || func_802D42F8(this)); - mapSpecificFlags_set(0x1F, (player_isStableWithExtraSteps() && func_8028FB48(0x78000000)) || player_movementGroup() == BSGROUP_D_TRANSFORMING); + mapSpecificFlags_set(0x1F, (func_8028F20C() && func_8028FB48(0x78000000)) || player_movementGroup() == BSGROUP_D_TRANSFORMING); switch(this->state){ case 0x12: //L802D4468 if(this->unk38_0 && mapSpecificFlags_get(0x1F)){ @@ -734,11 +555,11 @@ void chMumboSwitch_update(Actor *this){ mapSpecificFlags_set(0x1F, false); } -Actor *chMumboSwitch_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { +Actor *func_802D4588(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) { s32 phi_a1; phi_a1 = (marker_getActor(marker)->unk38_0) ? ((globalTimer_getTime() & 4) != 0) ? 1 : 2 : 2; - modelRender_setAppendageVisibility(1, phi_a1); + func_8033A45C(1, phi_a1); return actor_draw(marker, gfx, mtx, vtx); } @@ -755,7 +576,7 @@ void func_802D4614(enum map_e map_id){ timedFunc_set_2(1.0f, (GenFunction_2) func_8031CC40, map_id, 2); } -void chFFTeleportPad_Update(Actor *this){ +void func_802D4680(Actor *this){ f32 sp1C[3]; player_getPosition(sp1C); @@ -767,7 +588,7 @@ void chFFTeleportPad_Update(Actor *this){ } break; case 1: - if(ml_vec3f_horizontal_distance_zero_likely(this->position, sp1C) < 150.0f && player_isStableWithExtraSteps()){ + if(ml_vec3f_horizontal_distance_zero_likely(this->position, sp1C) < 150.0f && func_8028F20C()){ if(player_movementGroup() == BSGROUP_0_NONE || player_movementGroup() == BSGROUP_8_TROT){ if(gsworld_getMap() == MAP_8E_GL_FURNACE_FUN){ volatileFlag_set(VOLATILE_FLAG_0_IN_FURNACE_FUN_QUIZ, 0); @@ -863,39 +684,39 @@ void func_802D4AC0(Actor *this, s32 arg1, enum file_progress_e arg2) { } -void chMMWitchSwitch_update(Actor *this){ +void func_802D4B94(Actor *this){ func_802D4AC0(this, 0x4000b6, FILEPROG_18_MM_WITCH_SWITCH_JIGGY_PRESSED); } -void chCCWitchSwitch_update(Actor *this){ +void func_802D4BBC(Actor *this){ func_802D4AC0(this, 0x4000bc, FILEPROG_9A_CC_WITCH_SWITCH_PRESSED); } -void chBGSWitchSwitch_update(Actor *this){ +void func_802D4BE4(Actor *this){ func_802D4AC0(this, 0x4000bd, FILEPROG_9F_BGS_WITCH_SWITCH_JIGGY_PRESSED); } -void chGVWitchSwitch_update(Actor *this){ +void func_802D4C0C(Actor *this){ func_802D4AC0(this, 0x4000be, FILEPROG_A0_GV_WITCH_SWITCH_JIGGY_PRESSED); } -void chMMMWitchSwitch_update(Actor *this){ +void func_802D4C34(Actor *this){ func_802D4AC0(this, 0x4000b7, FILEPROG_19_MMM_WITCH_SWITCH_JIGGY_PRESSED); } -void chTTCWitchSwitch_update(Actor *this){ +void func_802D4C5C(Actor *this){ func_802D4AC0(this, 0x4000b8, FILEPROG_1A_TTC_WITCH_SWITCH_JIGGY_PRESSED); } -void chRBBWitchSwitch_update(Actor *this){ +void func_802D4C84(Actor *this){ func_802D4AC0(this, 0x4000b9, FILEPROG_1C_RBB_WITCH_SWITCH_JIGGY_PRESSED); } -void chCCWWitchSwitch_update(Actor *this){ +void func_802D4CAC(Actor *this){ func_802D4AC0(this, 0x4000ba, FILEPROG_46_CCW_WITCH_SWITCH_JIGGY_PRESSED); } -void chFPWitchSwitch_update(Actor *this){ +void func_802D4CD4(Actor *this){ if(gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK){ if(maSlalom_isActive()){ this->unk58_0 = false; @@ -982,8 +803,8 @@ void func_getCameraViewFromLevel(enum map_e map_id, s32 arg1, bool arg2) { } -s32 func_802D5140(ActorMarker *caller, enum asset_e text_id, s32 arg2){ - return itemscore_noteScores_get(volatileFlag_getN(VOLATILE_FLAG_19_CURRENT_LEVEL_ID, 4)); +void func_802D5140(ActorMarker *caller, enum asset_e text_id, s32 arg2){ + itemscore_noteScores_get(volatileFlag_getN(VOLATILE_FLAG_19_CURRENT_LEVEL_ID, 4)); } void func_802D5178(s32 arg0, enum file_progress_e arg1, s32 arg2, enum map_e arg3, s32 arg4, s32 arg5, enum actor_e arg6, s32 arg7){ @@ -1002,9 +823,6 @@ void func_802D520C(Gfx **gfx, Mtx **mtx, Vtx **vtx){ } } -// [port] Map the lair water was last levelled for, so re-entry snaps instead of ramping. -static s32 sLairWaterMap = -1; - void func_802D5260(void) { s32 sp3C; Struct70s *sp38; @@ -1017,7 +835,6 @@ void func_802D5260(void) { : -1; if (sp3C == -1) { - sLairWaterMap = -1; // [port] see above levelSpecificFlags_set(LEVEL_FLAG_3C_LAIR_UNKNOWN, false); fileProgressFlag_set(FILEPROG_26_WATER_SWITCH_3_PRESSED, false); fileProgressFlag_set(FILEPROG_27_LAIR_WATER_LEVEL_3, false); @@ -1029,7 +846,7 @@ void func_802D5260(void) { && !levelSpecificFlags_get(LEVEL_FLAG_3D_LAIR_UNKNOWN) && !levelSpecificFlags_get(LEVEL_FLAG_3C_LAIR_UNKNOWN) ) { - code_4C020_setHourglassTimer(30); + func_802D68F0(30); item_set(ITEM_6_HOURGLASS, true); levelSpecificFlags_set(LEVEL_FLAG_3D_LAIR_UNKNOWN, true); } @@ -1064,27 +881,14 @@ void func_802D5260(void) { if (levelSpecificFlags_get(LEVEL_FLAG_3C_LAIR_UNKNOWN) != false) { sp34 = D_803679C8[sp3C].unk6 + D_803676A4; } else { - s32 lvl = (fileProgressFlag_get(FILEPROG_27_LAIR_WATER_LEVEL_3)) ? 3 - : (fileProgressFlag_get(FILEPROG_25_LAIR_WATER_LEVEL_2)) ? 2 - : (fileProgressFlag_get(FILEPROG_23_LAIR_WATER_LEVEL_1)) ? 1 - : 0; - lvl = port_lairWater_targetLevel(gsworld_getMap(), lvl); - sp34 = ((s16 *)&D_803679C8[sp3C])[lvl]; - } - s32 curMap = gsworld_getMap(); - if (sLairWaterMap != curMap || levelSpecificFlags_get(LEVEL_FLAG_3C_LAIR_UNKNOWN)) { - sLairWaterMap = curMap; - } else { - f32 curY = sp38->type_6D.unk8; - f32 step = 240.0f * time_getDelta(); - f32 diff = sp34 - curY; - if (diff > step) sp34 = curY + step; - else if (diff < -step) sp34 = curY - step; - // within a step of the target: let sp34 stand. + sp34 = ((s16 *)&D_803679C8[sp3C])[(fileProgressFlag_get(FILEPROG_27_LAIR_WATER_LEVEL_3)) ? 3 + : (fileProgressFlag_get(FILEPROG_25_LAIR_WATER_LEVEL_2)) ? 2 + : (fileProgressFlag_get(FILEPROG_23_LAIR_WATER_LEVEL_1)) ? 1 + : 0]; } func_8034DEB4(&sp38->type_6D, sp34); player_getPosition(sp28); - + fxRipple_802F363C(sp34 + ((sp3C != -1) ? (D_803679E0[sp3C] + ((sp3C == 2) ? (6600.0f < sp28[0]) ? -200 : 0 : 0)) : 0)); } } @@ -1239,7 +1043,7 @@ void func_802D5628(void){ func_802D5178(LEVEL_FLAG_22_MMM_OPEN, 0x2E, 0x36, MAP_75_GL_MMM_LOBBY, 0xC, 0x6, ACTOR_228_MMM_ENTRANCE_DOOR, 0xA); func_802D5178(LEVEL_FLAG_24_CCW_OPEN, 0x30, 0x37, MAP_79_GL_CCW_LOBBY, 0xF, 0xB, ACTOR_234_CCW_ENTRANCE_DOOR, 0xA); func_802D5178(LEVEL_FLAG_20_FP_OPEN, 0x2C, 0x38, MAP_6F_GL_FP_LOBBY, 0x11, 0xA, ACTOR_235_FP_ENTRANCE_DOOR_LEFT, 0xA); - func_802D5178(LEVEL_FLAG_3F_LAIR_GRUNTY_DOOR_OPEN, 0xE2, 0x40, MAP_93_GL_DINGPOT, 0x10, 0xA, ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE, 0x28); + func_802D5178(LEVEL_FLAG_3F_LAIR_GRUNTY_DOOR_OPEN, 0xE2, 0x40, MAP_93_GL_DINGPOT, 0x10, 0xA, ACTOR_2E5_DOOR_OF_GRUNTY, 0x28); if(volatileFlag_get(VOLATILE_FLAG_18)){ if(!fileProgressFlag_get(FILEPROG_99_PAST_50_NOTE_DOOR_TEXT)){ gcdialog_showDialogConditional(0xF75, 0xE, NULL, NULL, NULL, NULL, (s32(*)(ActorMarker*,s32,s32))func_802D5140); @@ -1317,13 +1121,11 @@ int func_802D60C4(void){ } void func_802D6114(void){ - s32 sp24; + s32 sp24; s32 sp20; - s32 camScript; sp24 = D_80367694;\ sp20 = D_80367698; - camScript = D_80367688; if(D_8036769C) fileProgressFlag_set(D_8036769C, true); func_802D6344(); @@ -1340,10 +1142,6 @@ void func_802D6114(void){ else{//L802D61DC func_80347A14(1); gcpausemenu_80314AC8(1); - // [port] Anchor: exit the camera manually; 0x30 (MM) and 0x40 (Door of Grunty) schedule their own exit. - if (camScript != 0x30 && camScript != 0x40) { - ncStaticCamera_exit(); - } } } @@ -1366,8 +1164,6 @@ void func_802D6264(f32 delay, enum map_e map_id, s32 arg2, s32 arg3, s32 arg4, e D_8036769C = arg5; D_803676A0 = 0; - port_lairWater_onRiseTrigger(map_id, arg5); - if(map_id != D_80367694){ timedFunc_set_1(delay, (GenFunction_1) func_802D61FC, map_id); } @@ -1433,7 +1229,7 @@ void func_802D6494(void){ if( (!D_80367684 || (D_80367684 && (gsworld_getMap() == D_80367684))) ){ switch(D_803676A0){ - case ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE: + case ACTOR_2E5_DOOR_OF_GRUNTY: break; case ACTOR_20E_MM_ENTRANCE_DOOR:// L802D6510 FUNC_8030E624(SFX_6B_LOCKUP_OPENING, 0.6f, 32000); @@ -1552,7 +1348,7 @@ int func_802D68B4(void){ //BREAK???? //set_hourglass_timer_seconds -void code_4C020_setHourglassTimer(s32 seconds){ +void func_802D68F0(s32 seconds){ item_set(ITEM_0_HOURGLASS_TIMER, seconds*60 - 1); } diff --git a/src/core2/quiz/minigame.c b/src/core2/quiz/minigamemanager.c similarity index 98% rename from src/core2/quiz/minigame.c rename to src/core2/quiz/minigamemanager.c index f757868dc..64bac6e59 100644 --- a/src/core2/quiz/minigame.c +++ b/src/core2/quiz/minigamemanager.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/minigame.c #include #include "functions.h" #include "variables.h" @@ -110,7 +109,7 @@ void __chMinigame_textCallback1(ActorMarker *marker, enum asset_e text_id, s32 a void __chMinigame_transformToCroc(ActorMarker *marker, enum asset_e text_id, s32 arg2){ if(arg2 == 1){ - player_transform(TRANSFORM_5_CROC); + func_8028FB88(TRANSFORM_5_CROC); } } diff --git a/src/core2/quiz/questionmanager.c b/src/core2/quiz/questionmanager.c index 1fcac24dc..98c01add9 100644 --- a/src/core2/quiz/questionmanager.c +++ b/src/core2/quiz/questionmanager.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_91E10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/quiz/storage.c b/src/core2/quiz/storage.c index 34b7d3cc4..1bface1cc 100644 --- a/src/core2/quiz/storage.c +++ b/src/core2/quiz/storage.c @@ -1,9 +1,8 @@ -// BanjoDecomp: core2/code_C9E70.c #include #include "functions.h" #include "variables.h" -#include "core2/quiz/storage.h" +#include "core2/quiz_storage.h" extern struct FF_StorageStruct *ffStorage; diff --git a/src/core2/savedata.c b/src/core2/savedata.c index f35e6d712..e5c89ed91 100644 --- a/src/core2/savedata.c +++ b/src/core2/savedata.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B5040.c #include #include "core1/core1.h" #include "functions.h" @@ -387,7 +386,7 @@ void saveData_load(void *savedata_){ func_8033C4E4((u8*)savedata); __savedata_load_abilities((u8*)savedata); for(i = 0; D_80370A20[i].unk0 != -1; i++){ - volatileFlag_setEx(D_80370A20[i].unk0, fileProgressFlag_get(D_80370A20[i].unk2), 0); + volatileFlag_set(D_80370A20[i].unk0, fileProgressFlag_get(D_80370A20[i].unk2)); } CALL_EVENT(OnSaveLoad, savedata); } @@ -396,7 +395,7 @@ void saveData_create(void *savedata_){ SaveData *savedata = (SaveData *)savedata_; int i; for(i = 0; D_80370A20[i].unk0 != -1; i++){ - fileProgressFlag_setEx(D_80370A20[i].unk2, volatileFlag_get(D_80370A20[i].unk0), 0); + fileProgressFlag_set(D_80370A20[i].unk2, volatileFlag_get(D_80370A20[i].unk0)); } savedata_clear((u8*)savedata); __savedata_save_magic((u8*)savedata); diff --git a/src/core2/honeycombscore.c b/src/core2/score_honeycomb.c similarity index 97% rename from src/core2/honeycombscore.c rename to src/core2/score_honeycomb.c index 6667b3310..420d64983 100644 --- a/src/core2/honeycombscore.c +++ b/src/core2/score_honeycomb.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/honeycombscore.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/jiggyscore.c b/src/core2/score_jiggy.c similarity index 90% rename from src/core2/jiggyscore.c rename to src/core2/score_jiggy.c index 6d7d9c46f..32bfbc41b 100644 --- a/src/core2/jiggyscore.c +++ b/src/core2/score_jiggy.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/jiggyscore.c #include #include "functions.h" #include "variables.h" @@ -84,12 +83,6 @@ s32 jiggyscore_leveltotal(s32 lvl) { s32 start; s32 end; s32 cnt; - s32 override_total = 0; - - // [port] Romhack gate: listeners can supply the whole per-level tally. - if (!EventSystem_Should(VB_JIGGYSCORE_LEVEL_TOTAL, true, lvl, &override_total)) { - return override_total; - } if (lvl <= 0 || lvl == 0xB || lvl >= 0xB) return 0; diff --git a/src/core2/mumboscore.c b/src/core2/score_mumbo.c similarity index 97% rename from src/core2/mumboscore.c rename to src/core2/score_mumbo.c index d0a0b8248..e0d6a820e 100644 --- a/src/core2/mumboscore.c +++ b/src/core2/score_mumbo.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/mumboscore.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/dispatch.c b/src/core2/scorequeue/dispatch.c index 83d83a796..fc9d41a8d 100644 --- a/src/core2/scorequeue/dispatch.c +++ b/src/core2/scorequeue/dispatch.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_74090.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/airscore.c b/src/core2/scorequeue/drawui_air.c similarity index 99% rename from src/core2/scorequeue/airscore.c rename to src/core2/scorequeue/drawui_air.c index 9c37b1e4c..b45bde3c4 100644 --- a/src/core2/scorequeue/airscore.c +++ b/src/core2/scorequeue/drawui_air.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/airscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/healthscore.c b/src/core2/scorequeue/drawui_health.c similarity index 99% rename from src/core2/scorequeue/healthscore.c rename to src/core2/scorequeue/drawui_health.c index 5796e717e..3673b3feb 100644 --- a/src/core2/scorequeue/healthscore.c +++ b/src/core2/scorequeue/drawui_health.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/healthscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/honeycarrierscore.c b/src/core2/scorequeue/drawui_honeycarrier.c similarity index 99% rename from src/core2/scorequeue/honeycarrierscore.c rename to src/core2/scorequeue/drawui_honeycarrier.c index e68b39820..8ce9e90d4 100644 --- a/src/core2/scorequeue/honeycarrierscore.c +++ b/src/core2/scorequeue/drawui_honeycarrier.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/honeycarrierscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/jinjoscore.c b/src/core2/scorequeue/drawui_jinjo.c similarity index 99% rename from src/core2/scorequeue/jinjoscore.c rename to src/core2/scorequeue/drawui_jinjo.c index f2c8486b6..3a613a4f6 100644 --- a/src/core2/scorequeue/jinjoscore.c +++ b/src/core2/scorequeue/drawui_jinjo.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/jinjoscore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/lifescore.c b/src/core2/scorequeue/drawui_lives.c similarity index 99% rename from src/core2/scorequeue/lifescore.c rename to src/core2/scorequeue/drawui_lives.c index 0dbf6df22..b59a2139f 100644 --- a/src/core2/scorequeue/lifescore.c +++ b/src/core2/scorequeue/drawui_lives.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/lifescore.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/scorequeue/common3score.c b/src/core2/scorequeue/drawui_models.c similarity index 89% rename from src/core2/scorequeue/common3score.c rename to src/core2/scorequeue/drawui_models.c index e63b6e40b..df0f941ad 100644 --- a/src/core2/scorequeue/common3score.c +++ b/src/core2/scorequeue/drawui_models.c @@ -1,15 +1,13 @@ -// BanjoDecomp: core2/fx/common3score.c #include #include "core1/core1.h" #include "functions.h" #include "port/Patches/Patches.h" #include "variables.h" #include "port/Engine.h" -#include "port/Interpolation/FrameInterpolation.h" - -extern void depthbuffer_clearRegion(Gfx **gdl, s32 x, s32 y, s32 w, s32 h, void *color_buffer); +extern f32 vtxList_getGlobalNorm(BKVertexList *); +extern void func_80253208(Gfx **gdl, s32 x, s32 y, s32 w, s32 h, void *color_buffer); extern f32 func_802FB0E4(struct8s*); @@ -194,7 +192,6 @@ void fxcommon3score_draw(enum item_e item_id, void *arg1, Gfx **gfx, Mtx **mtx, sp40 = func_802FB0E4(arg1)*a1->unk54 + a1->unk34; if(a1->model != NULL && func_802FB0D4(arg1)){ - FrameInterpolation_RecordOpenChild("score_model", (uintptr_t)item_id); draw_x = a1->unk30 + port_hudOrthoShift(a1->unk30); a1->value_string[0] = '\0'; strIToA(a1->value_string, itemPrint_getValue(item_id)); @@ -214,15 +211,11 @@ void fxcommon3score_draw(enum item_e item_id, void *arg1, Gfx **gfx, Mtx **mtx, if(a1->unk6C == 0.0f){ a1->unk6C = 1.1*(vtxList_getGlobalNorm(modelbin_getVtxList(a1->model)) * a1->unk3C); } - // [port] Clear against draw_x, not unk30: the model is drawn at the widescreen-anchored - // position, so the depth hole has to move with it or the icon gets z-clipped by the world. - // depthbuffer_clearRegion(gfx, a1->unk30 - a1->unk6C, sp40 - a1->unk6C, 2*a1->unk6C, 2*a1->unk6C, gFramebuffers[getActiveFramebuffer()]); - depthbuffer_clearRegion(gfx, draw_x - a1->unk6C, sp40 - a1->unk6C, 2*a1->unk6C, 2*a1->unk6C, gFramebuffers[getActiveFramebuffer()]); + func_80253208(gfx, draw_x - a1->unk6C, sp40 - a1->unk6C, 2*a1->unk6C, 2*a1->unk6C, gFramebuffers[getActiveFramebuffer()]); if(a1->anim_ctrl != NULL){ anctrl_drawSetup(a1->anim_ctrl, sp5C, 1); } modelRender_draw(gfx, mtx, sp5C, sp68, a1->unk3C*sp3C, sp44, a1->model); - FrameInterpolation_RecordCloseChild(); }//L80300BA4 } diff --git a/src/core2/scorequeue/common2score.c b/src/core2/scorequeue/drawui_sprites.c similarity index 97% rename from src/core2/scorequeue/common2score.c rename to src/core2/scorequeue/drawui_sprites.c index 53d02db77..ba439e554 100644 --- a/src/core2/scorequeue/common2score.c +++ b/src/core2/scorequeue/drawui_sprites.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/common2score.c #include #include "core1/core1.h" #include "functions.h" @@ -226,7 +225,7 @@ void fxcommon2score_update(s32 arg0, struct8s * arg1){ phi_f16 = 0.333f; } if(arg0 < 6){ - if(item_getCount(arg0) < VER_SELECT(30, 25, 0, 0)){ + if(item_getCount(arg0) < 30){ arg1->unk28 |= 8; } else{ @@ -235,11 +234,11 @@ void fxcommon2score_update(s32 arg0, struct8s * arg1){ } if((arg1->unk28 & 4) == 0){ tmpf = arg1->unk2C; - arg1->unk60 = time_getDelta() * (arg1->unk34 * arg1->unk30) * VER_SELECT(60.0f, 50.0f, 0, 0) * phi_f16 + arg1->unk60; + arg1->unk60 = time_getDelta() * (arg1->unk34 * arg1->unk30) * 60.0f * phi_f16 + arg1->unk60; if(arg1->unk2C <= arg1->unk60){ if(arg1->unk28 & 1){ arg1->unk34 *= -1.0f; - arg1->unk60 -= two* arg1->unk30 * time_getDelta() * VER_SELECT(60.0f, 50.0f, 0, 0); + arg1->unk60 -= two* arg1->unk30 * time_getDelta() * 60.0f; } else{ arg1->unk60 -= arg1->unk2C; @@ -253,7 +252,7 @@ void fxcommon2score_update(s32 arg0, struct8s * arg1){ if(arg1->unk60 < 0.0){ if(arg1->unk28 & 1){ arg1->unk34 *= -1.0f; - arg1->unk60 += two * arg1->unk30 * time_getDelta() * VER_SELECT(60.0f, 50.0f, 0, 0); + arg1->unk60 += two * arg1->unk30 * time_getDelta() * 60.0f; } else{ arg1->unk60 += arg1->unk2C; @@ -282,7 +281,7 @@ void fxcommon2score_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **m } } if(item_id < 6){ - sp38 = ((sp38)? 1: 0) + sp38/FRAMERATE; + sp38 = ((sp38)? 1: 0) + sp38/60; }//L802FDBA8 if(item_id == ITEM_1B_VILE_VILE_SCORE && 9 < sp38){ sp34 = -16.0f; diff --git a/src/core2/scorequeue/common1score.c b/src/core2/scorequeue/drawui_stub.c similarity index 91% rename from src/core2/scorequeue/common1score.c rename to src/core2/scorequeue/drawui_stub.c index 677f4b307..bdee37f9a 100644 --- a/src/core2/scorequeue/common1score.c +++ b/src/core2/scorequeue/drawui_stub.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/fx/common1score.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/manager.c b/src/core2/scorequeue/manager.c index 2e62963f9..6b6dfd362 100644 --- a/src/core2/scorequeue/manager.c +++ b/src/core2/scorequeue/manager.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_73640.c #include #include "functions.h" #include "variables.h" @@ -191,13 +190,13 @@ void itemPrint_update(void) { } -void itemPrint_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) { +void itemPrint_draw(Gfx **gdl, Mtx ** mptr, Vtx **vptr){ s32 i; if(D_803810B0 && level_get() != LEVEL_D_CUTSCENE){ for(i = 0; i < 0x2C; i++){ if(!func_802E4A08() || i < 6){ if(func_802FB0D4(D_803692F8[i].unk14)){ - D_803692F8[i].unk8(i, D_803692F8[i].unk14, gfx, mtx, vtx); + D_803692F8[i].unk8(i, D_803692F8[i].unk14, gdl, mptr, vptr); } } } diff --git a/src/core2/scorequeue/queue_collectibles.c b/src/core2/scorequeue/queue_collectibles.c index 8c3f38467..3089b0774 100644 --- a/src/core2/scorequeue/queue_collectibles.c +++ b/src/core2/scorequeue/queue_collectibles.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_74910.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_honeycombs.c b/src/core2/scorequeue/queue_honeycombs.c index 731c31de5..a4387833c 100644 --- a/src/core2/scorequeue/queue_honeycombs.c +++ b/src/core2/scorequeue/queue_honeycombs.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_74420.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_lives.c b/src/core2/scorequeue/queue_lives.c index 6422a6de6..f208e68bc 100644 --- a/src/core2/scorequeue/queue_lives.c +++ b/src/core2/scorequeue/queue_lives.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_75E90.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_major_items.c b/src/core2/scorequeue/queue_major_items.c index 8a8ac6010..1d9ebc511 100644 --- a/src/core2/scorequeue/queue_major_items.c +++ b/src/core2/scorequeue/queue_major_items.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_74ED0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_notes.c b/src/core2/scorequeue/queue_notes.c index c6237e4e0..d16a25e5d 100644 --- a/src/core2/scorequeue/queue_notes.c +++ b/src/core2/scorequeue/queue_notes.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_74290.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_timers.c b/src/core2/scorequeue/queue_timers.c index af1211b4a..00ed40b63 100644 --- a/src/core2/scorequeue/queue_timers.c +++ b/src/core2/scorequeue/queue_timers.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_75930.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/scorequeue/queue_totals.c b/src/core2/scorequeue/queue_totals.c index 7ee54a8c9..74f538ea2 100644 --- a/src/core2/scorequeue/queue_totals.c +++ b/src/core2/scorequeue/queue_totals.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_75480.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/weather_snow.c b/src/core2/sfx/filedata.c similarity index 78% rename from src/core2/fx/weather_snow.c rename to src/core2/sfx/filedata.c index 894ecfe53..b338eb09a 100644 --- a/src/core2/fx/weather_snow.c +++ b/src/core2/sfx/filedata.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_72060.c #include #include "core1/core1.h" #include "functions.h" @@ -29,22 +28,22 @@ Gfx D_80369290[] = gsSPEndDisplayList(), }; -// [port] The flake model reaches these render modes through segment 3 at fixed byte -// offsets; one 2D array guarantees the contiguity three separate globals did not. -Gfx D_803692B0[][2] = +Gfx D_803692B0[] = { - { - gsDPSetRenderMode(Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1)), - gsSPEndDisplayList(), - }, - { - gsDPSetRenderMode(AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | G_RM_PASS, AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)), - gsSPEndDisplayList(), - }, - { - gsDPSetRenderMode(Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)), - gsSPEndDisplayList(), - }, + gsDPSetRenderMode(Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1)), + gsSPEndDisplayList(), +}; + +Gfx D_803692C0[] = +{ + gsDPSetRenderMode(AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | G_RM_PASS, AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM)), + gsSPEndDisplayList(), +}; + +Gfx D_803692D0[] = +{ + gsDPSetRenderMode(Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | G_RM_PASS, Z_CMP | IM_RD | CVG_DST_FULL | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)), + gsSPEndDisplayList(), }; /* .bss */ @@ -57,7 +56,6 @@ f32 D_80381080[3]; f32 D_8038108C; Gfx *D_80381090; Struct_core2_72060_0 *D_80381094; -static u32 sSnowNextId = 0; // [port] Monotonic spawn id bool func_802F989C(Gfx **gfx, Mtx **mtx, f32 arg2[3]); @@ -180,7 +178,6 @@ void func_802F919C(void) { sp40->unkC[0] = 0.0f; sp40->unkC[1] = randf2(-150.0f, -50.0f); sp40->unkC[2] = 0.0f; - sp40->id = ++sSnowNextId; } } } @@ -208,19 +205,20 @@ void func_802F962C(Gfx **gfx, Mtx **mtx, Vtx **vtx) { func_80349AD0(); gSPSegment((*gfx)++, 1, osVirtualToPhysical(temp_s3 + 1)); gSPSegment((*gfx)++, 0x02, osVirtualToPhysical((void*)((uintptr_t)D_80369288 + D_80369288->texture_list_offset + sizeof(BKTextureList) + sizeof(BKTextureInfo)))); - // [port] Vanilla only sets G_ZBUFFER here, inheriting the rest of the RSP/RDP state - // from whatever drew last. GraphicsPatches.cpp substitutes a self-contained preamble. - if (EventSystem_Should(VB_SNOW_RENDER_STATE, true, gfx)) { - gSPSetGeometryMode((*gfx)++, G_ZBUFFER); - } + gSPSetGeometryMode((*gfx)++, G_ZBUFFER); gSPDisplayList((*gfx)++, D_80369290); - gSPSegment((*gfx)++, 0x03, osVirtualToPhysical(D_803692B0)); + gSPSegment((*gfx)++, 0x03, osVirtualToPhysical(&D_803692B0)); D_80381094 = (Struct_core2_72060_0 *)((uintptr_t)D_80369288 + D_80369288->geo_list_offset); for(phi_s0 = D_80369280->unk1C; phi_s0 < D_80369280->unk1C + D_80369284; phi_s0++) { - // [port] Scope keyed on spawn id - FrameInterpolation_RecordOpenChild("weather_snow", phi_s0->id); + // [port] Scope keyed on position — array shrinks below the + // height threshold and frustum culls inside func_802F989C, so + // index-based pairing would mismatch surviving items. + FrameInterpolation_RecordOpenChildHash3("grass_item", + FrameInterpolation_FloatBits(phi_s0->unk0[0]), + FrameInterpolation_FloatBits(phi_s0->unk0[1]), + FrameInterpolation_FloatBits(phi_s0->unk0[2])); if ((func_802F989C(gfx, mtx, phi_s0->unk0) == 0) && (phi_s0->unk0[1] < D_8038104C)) { func_802F9134(phi_s0 - D_80369280->unk1C); phi_s0--; @@ -244,12 +242,8 @@ bool func_802F989C(Gfx **gfx, Mtx **mtx, f32 arg2[3]) { mlMtxApply(*mtx); mlMtx_apply_vec3f_restricted(D_80381080, D_80381094->unkC); func_80251B5C(D_80381080[0], D_80381080[1], D_80381080[2]); - // [port] Cancelled by PerfPatches.cpp, which applies the same rotations - // with the trig cached across flakes. - if (EventSystem_Should(VB_SNOW_CAMERA_ROTATION, true, D_80381060)) { - mlMtx_rotate_yaw_deg(D_80381060[1]); - mlMtx_rotate_pitch_deg(D_80381060[0]); - } + mlMtx_rotate_yaw_deg(D_80381060[1]); + mlMtx_rotate_pitch_deg(D_80381060[0]); func_80252A38(-(D_80381094->unkC[0]), -(D_80381094->unkC[1]), -(D_80381094->unkC[2])); mlMtxApply(*mtx); gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW); diff --git a/src/core2/fx/weather.c b/src/core2/sfx/init.c similarity index 98% rename from src/core2/fx/weather.c rename to src/core2/sfx/init.c index c59dc5f8a..65b251fa2 100644 --- a/src/core2/fx/weather.c +++ b/src/core2/sfx/init.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_70C30.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/instruments.c b/src/core2/sfx/instruments.c index 410004a40..4566c01bd 100644 --- a/src/core2/sfx/instruments.c +++ b/src/core2/sfx/instruments.c @@ -1,10 +1,12 @@ -// BanjoDecomp: core2/code_AE290.c #include #include "functions.h" #include "variables.h" #include extern ALBank *music_get_sound_bank(void); +extern OSIoMesg *func_802405D0(void); +extern OSMesgQueue *func_802405C4(void); +extern ALHeap *func_802405B8(void); extern void func_80243070(void *arg0); extern u8 *soundfont1ctl_ROM_START; @@ -38,7 +40,7 @@ void sfxInstruments_init(void){ D_803835F0.unk4 = 0x100; D_803835F0.unk10 = 0x40; D_803835F0.unk8 = 0x18; - D_803835F0.unkC = audioManager_getALHeapInfo(); + D_803835F0.unkC = func_802405B8(); func_80243070(&D_803835F0); sfx_sound_bank = bnk; } diff --git a/src/core2/sfx/pitched.c b/src/core2/sfx/pitched.c index 613667518..c70bb9b87 100644 --- a/src/core2/sfx/pitched.c +++ b/src/core2/sfx/pitched.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_599E0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/fx/weather_leaves.c b/src/core2/sfx/playstate.c similarity index 97% rename from src/core2/fx/weather_leaves.c rename to src/core2/sfx/playstate.c index 557496177..a3d5020d8 100644 --- a/src/core2/fx/weather_leaves.c +++ b/src/core2/sfx/playstate.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_71820.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -23,7 +22,7 @@ void func_802F87B0(struct6s *this){ return; player_getPosition(plyrPos); - viewport_getLookVector(camNorm); + viewport_getLookbk_vector(camNorm); viewport_getRotation_vec3f(camRot); ptr = bk_vector_pushBackNew(&this->unk1C); f20 = randf2(50.0f, 1200.0f); @@ -80,7 +79,7 @@ void func_802F8A90(struct6s *this, Gfx **gdl, Mtx **mptr, Vtx **vptr){ struct5s * endPtr = bk_vector_getEnd(this->unk1C); for(iPtr = startPtr; iPtr < endPtr; iPtr++){ // [port] Stable scope per entry; vector count fluctuates. - FrameInterpolation_RecordOpenChild("weather_leaf", (uintptr_t)(iPtr - startPtr)); + FrameInterpolation_RecordOpenChild("playstate", (uintptr_t)(iPtr - startPtr)); modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); modelRender_draw(gdl, mptr, iPtr->unk4, iPtr->unk1C, 1.0f, NULL, iPtr->unk0); iPtr->unk34 = modelRender_func_8033A170(); diff --git a/src/core2/sfx/randompitch.c b/src/core2/sfx/randompitch.c index 333e5423a..2ed9a5317 100644 --- a/src/core2/sfx/randompitch.c +++ b/src/core2/sfx/randompitch.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_72B10.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/sequenceindex.c b/src/core2/sfx/sequenceindex.c index b888aff1c..7f4298e94 100644 --- a/src/core2/sfx/sequenceindex.c +++ b/src/core2/sfx/sequenceindex.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_857B0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/soundsource.c b/src/core2/sfx/soundsource.c index 06f8c5e02..088874b78 100644 --- a/src/core2/sfx/soundsource.c +++ b/src/core2/sfx/soundsource.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/ch/soundsource.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sfx/source.c b/src/core2/sfx/source.c index 3cd50ef42..2b46b5988 100644 --- a/src/core2/sfx/source.c +++ b/src/core2/sfx/source.c @@ -1,9 +1,7 @@ -// BanjoDecomp: core2/code_85800.c #include #include "core1/core1.h" #include "functions.h" #include "variables.h" -#include "port/ShipUtils.h" // gPortResetPending #include extern void func_80335394(intptr_t, f32); @@ -222,7 +220,7 @@ s32 func_8030CDE4(SfxSource *arg0){ f32 pad; viewport_getPosition_vec3f(sp44); - viewport_getLookVector(sp38); + viewport_getLookbk_vector(sp38); sp2C[0] = arg0->position[0] - sp44[0]; sp2C[1] = arg0->position[1] - sp44[1]; sp2C[2] = arg0->position[2] - sp44[2]; @@ -861,12 +859,8 @@ void sfxsource_play(enum sfx_e uid, s32 sampleRate){ func_8030D6C4(uid, 1.0f, sampleRate, 0, 2); } -void gcsfx_playAtSampleRate(enum sfx_e uid, s32 sampleRate){ - sfxsource_play(uid, sampleRate); -} - -void gcsfx_play(enum sfx_e uid){ - gcsfx_playAtSampleRate(uid, 0x7FF8); +void gcsfx_playAtSampleRate(enum sfx_e uid){ + sfxsource_play(uid, 0x7ff8); } void func_8030E560(enum sfx_e uid, s32 arg1){ diff --git a/src/core2/fx/weather_rain.c b/src/core2/sfx/streamctrl.c similarity index 97% rename from src/core2/fx/weather_rain.c rename to src/core2/sfx/streamctrl.c index b43602f00..af3324508 100644 --- a/src/core2/fx/weather_rain.c +++ b/src/core2/sfx/streamctrl.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_70F20.c #include #include "core1/core1.h" #include "functions.h" @@ -21,7 +20,7 @@ void func_802F7EB0(struct3s *this){ return; player_getPosition(plyrPos); - viewport_getLookVector(camNorm); + viewport_getLookbk_vector(camNorm); viewport_getRotation_vec3f(camRot); sp50 = bk_vector_pushBackNew(&this->unk20); tmpf = randf2(50.0f, 1100.0f); @@ -69,7 +68,7 @@ void func_802F8110(struct3s *this, Gfx **gdl, Mtx **mptr, u32 arg3){ endPtr = bk_vector_getEnd(this->unk20); for(iPtr = startPtr; iPtr < endPtr; iPtr++){ // [port] Per-entry stable scope — vector count varies, indices shift. - FrameInterpolation_RecordOpenChild("weather_rain", (uintptr_t)(iPtr - startPtr)); + FrameInterpolation_RecordOpenChild("streamctrl", (uintptr_t)(iPtr - startPtr)); modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE); modelRender_draw(gdl, mptr, iPtr->unk0, 0, 1.0f, 0, this->unk2C); iPtr->unk18 = modelRender_func_8033A170(); diff --git a/src/core2/sfx/trackmanager.c b/src/core2/sfx/trackmanager.c index e65939774..155ddf472 100644 --- a/src/core2/sfx/trackmanager.c +++ b/src/core2/sfx/trackmanager.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_9B650.c #include #include "core1/core1.h" #include "functions.h" diff --git a/src/core2/sfx/volume.c b/src/core2/sfx/volume.c index f775cf9c8..6fa3d6690 100644 --- a/src/core2/sfx/volume.c +++ b/src/core2/sfx/volume.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C8760.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/snackerctl.c b/src/core2/snacker_ctl.c similarity index 95% rename from src/core2/snackerctl.c rename to src/core2/snacker_ctl.c index e016ff6bc..1f8b5bdb7 100644 --- a/src/core2/snackerctl.c +++ b/src/core2/snacker_ctl.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/snackerctl.c #include "core2/snackerctl.h" #include @@ -12,7 +11,7 @@ #define SNACKER_BB_DIALOG_0 VER_SELECT(0xe26, 0xa68, 0xa68, 0xa68) #define SNACKER_BB_DIALOG_1 VER_SELECT(0xe33, 0xa75, 0xa75, 0xa75) -void ncba1p_getZoomedInRotation(f32 *); +void ncFirstPersonCamera_getZoomedInRotation(f32 *); extern u8 D_8037DCCA; extern u8 D_8037DCCB; @@ -33,7 +32,7 @@ void snackerctl_reset(void){ static s32 __snackerctl_player_within_distance(f32 x, f32 z, f32 dist){ f32 player_position[3]; - playerPosition_get(player_position); + _player_getPosition(player_position); return ml_vec3f_point_within_horizontal_distance(player_position, x, z, dist); } @@ -41,7 +40,7 @@ static SnackerCtlState __snackerctl_update_ttc(void){ SnackerCtlState nextState = 0; f32 player_position[3]; - playerPosition_get(player_position); + _player_getPosition(player_position); if(player_isSwimming() || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)){ //(swimming || ???) if(player_position[1] < 600.0f && !__snackerctl_player_within_distance(2478.0f, 4586.0f, 1750.0f) //within 1750 of sandcastle center @@ -102,7 +101,7 @@ static SnackerCtlState _snackerctl_update_bottles_bonus(void){ chBottleBonusPuzzleIndex = 1; }//L8028A764 else if(jiggyscore_isCollected(0x10)){ - ncba1p_getZoomedInRotation(sp30); + ncFirstPersonCamera_getZoomedInRotation(sp30); if( (((D_8036361C[0] <= sp30[0])? (sp30[0] - D_8036361C[0]) : -(sp30[0] - D_8036361C[0])) < 4.0f) && (((D_8036361C[1] <= sp30[1])? (sp30[1] - D_8036361C[1]) : -(sp30[1] - D_8036361C[1])) < 20.0f) ){ diff --git a/src/core2/spawnqueue.c b/src/core2/spawn_queue.c similarity index 61% rename from src/core2/spawnqueue.c rename to src/core2/spawn_queue.c index 2e039a1c8..d7a7aed28 100644 --- a/src/core2/spawnqueue.c +++ b/src/core2/spawn_queue.c @@ -1,14 +1,11 @@ -// BanjoDecomp: core2/spawnqueue.c #include #include "core1/core1.h" #include "functions.h" -#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "actor.h" #include "prop.h" #include "functions.h" #include "core2/ch/snacker.h" -#include "port/Patches/Patches.h" // port_getDrawDistanceLevel #include "port/Romhack/RomhackConfig.h" void spawnQueue_unlock(void); @@ -19,11 +16,11 @@ Actor *func_802D75B4(s32 *, s32, ActorInfo*, u32); Actor *func_802D7610(s32 *, s32, ActorInfo*, u32); Actor *chBottlesBonus_new(s32 *, s32, ActorInfo*, u32); -extern ActorInfo gameSelect_banjoSleeping; //banjo.without_right_hand -extern ActorInfo gameSelect_banjoGameboy; //banjo.playing_gameboy -extern ActorInfo gameSelect_banjoCooking; //banjo.cooking -extern ActorInfo fxWadingBootsTouchSparkle; -extern ActorInfo fxTurboTrainersTouchSparkle; //turbotrainers +extern ActorInfo D_80365E58; //banjo.without_right_hand +extern ActorInfo D_80365EAC; //banjo.playing_gameboy +extern ActorInfo D_80365F00; //banjo.cooking +extern ActorInfo D_80365F60; +extern ActorInfo D_80365F84; //turbotrainers extern ActorInfo D_80365FB0; //shrapnel extern ActorInfo chBubble; extern ActorInfo chBigbutt; //bigbutt @@ -38,8 +35,8 @@ extern ActorInfo D_803663D0; extern ActorInfo D_803663F4; extern ActorInfo chExtraLife; //extralife extern ActorInfo sumusicNote; //music_note -extern ActorInfo chEmptyHoneycomb; //chhoneycarrier -extern ActorInfo chHoneycomb; //chhoney +extern ActorInfo D_80366C80; //chhoneycarrier +extern ActorInfo D_80366CA4; //chhoney extern ActorInfo chTrainers; extern ActorInfo D_80366EF0; //large_shadow extern ActorInfo chShockJump; //chshockjump @@ -47,7 +44,7 @@ extern ActorInfo chFlightPad; //flight_pad extern ActorInfo chSnippet; //snippet extern ActorInfo chBlackSnippet; //black_snippet extern ActorInfo chMutieSnippet; //mutie_snippet -extern ActorInfo chBuzzbomb; //buzzbomb +extern ActorInfo D_80367130; //buzzbomb extern ActorInfo D_80367160; extern ActorInfo D_80367184; extern ActorInfo chJinjoBlue; //jingo_blue @@ -56,109 +53,109 @@ extern ActorInfo chJinjoYellow; //jingo_yellow extern ActorInfo chJinjoPink; //jingo_pink extern ActorInfo chJinjoOrange; //jingo_orange extern ActorInfo chBeehive; //chbeehive -extern ActorInfo chBeeSwarm; //chswarm +extern ActorInfo D_80367310; //chswarm extern ActorInfo D_80367390; //chwaterfallfx extern ActorInfo chShrapnelDescription; //scrapnel extern ActorInfo chGloop; //gloop -extern ActorInfo chMumbo; //mumbo -extern ActorInfo chMumboSign5; //mumbo_token_sign.5 -extern ActorInfo chMumboSign10; //mumbo_toke_sign.10 -extern ActorInfo chMumboSign15; //mumbo_toke_sign.15 -extern ActorInfo chMumboSign20; //mumbo_toke_sign.20 -extern ActorInfo chMumboSign25; //mumbo_toke_sign.25 +extern ActorInfo D_803674E0; //mumbo +extern ActorInfo D_80367530; //mumbo_token_sign.5 +extern ActorInfo D_80367554; //mumbo_toke_sign.10 +extern ActorInfo D_80367578; //mumbo_toke_sign.15 +extern ActorInfo D_8036759C; //mumbo_toke_sign.20 +extern ActorInfo D_803675C0; //mumbo_toke_sign.25 extern ActorInfo D_803675F0; extern ActorInfo D_80367760; extern ActorInfo D_80367784; -extern ActorInfo chIceKey; //ice_key -extern ActorInfo chMumboSwitch; //mumbo_transform_pad -extern ActorInfo chFFTeleportPad; -extern ActorInfo chSnsEgg; //SnS_egg -extern ActorInfo gWorldExitPad; //level_entry_disk -extern ActorInfo chMMWitchSwitch; //witch_switch.mm; -extern ActorInfo chMMMWitchSwitch; //witch_switch.mmm -extern ActorInfo chTTCWitchSwitch; //witch_switch.ttc -extern ActorInfo chRBBWitchSwitch; //witch_switch.rbb -extern ActorInfo chCCWWitchSwitch; //witch_switch.ccw -extern ActorInfo chFPWitchSwitch; //witch_switch.fp -extern ActorInfo chCCWitchSwitch; //witch_switch.cc -extern ActorInfo chBGSWitchSwitch; //witch_switch.bgs -extern ActorInfo chGVWitchSwitch; //witch_switch.gv -extern ActorInfo chWadingBoots; //wading boots +extern ActorInfo D_803677A8; //ice_key +extern ActorInfo D_803677CC; //mumbo_transform_pad +extern ActorInfo D_803677F0; +extern ActorInfo D_80367814; //SnS_egg +extern ActorInfo D_80367838; //level_entry_disk +extern ActorInfo D_8036785C; //witch_switch.mm; +extern ActorInfo D_80367880; //witch_switch.mmm +extern ActorInfo D_803678A4; //witch_switch.ttc +extern ActorInfo D_803678C8; //witch_switch.rbb +extern ActorInfo D_803678EC; //witch_switch.ccw +extern ActorInfo D_80367910; //witch_switch.fp +extern ActorInfo D_80367934; //witch_switch.cc +extern ActorInfo D_80367958; //witch_switch.bgs +extern ActorInfo D_8036797C; //witch_switch.gv +extern ActorInfo D_80367A20; //wading boots extern ActorInfo chBadShad; //chbadshad extern ActorInfo gDummyPlayerAnchorInfo; //dummy player anchor (port) extern ActorInfo D_80367AB0; extern ActorInfo D_80367AD4; extern ActorInfo D_80367AF8; extern ActorInfo D_80367B20; //chclimbbase -extern ActorInfo chOrangeCollectible; //orange -extern ActorInfo chGoldBullion; //gold_bullion -extern ActorInfo chBluePresentCollectible; -extern ActorInfo chGreenPresentCollectible; -extern ActorInfo chRedPresentCollectible; -extern ActorInfo chPiranhaWaterParticles; -extern ActorInfo fxSpentRedFeather; //spent_redfeather -extern ActorInfo fxSpentGoldFeather; //spent_goldfeather -extern ActorInfo chBlueEgg; //egg -extern ActorInfo chRedFeather; //redfeather -extern ActorInfo chGoldFeather; //goldfeather +extern ActorInfo D_80367B80; //orange +extern ActorInfo D_80367BA4; //gold_bullion +extern ActorInfo D_80367BC8; +extern ActorInfo D_80367BEC; +extern ActorInfo D_80367C10; +extern ActorInfo D_80367C60; +extern ActorInfo D_80367C90; //spent_redfeather +extern ActorInfo D_80367CB4; //spent_goldfeather +extern ActorInfo D_80367D00; //egg +extern ActorInfo D_80367D24; //redfeather +extern ActorInfo D_80367D48; //goldfeather extern ActorInfo gChMole; //bottles -extern ActorInfo chMolehill; //chmolehill +extern ActorInfo D_80367E20; //chmolehill extern ActorInfo D_80367E70; extern ActorInfo D_80367F30; -extern ActorInfo gcGameOverSign;//GAME_OVER -extern ActorInfo gcTheEndSign;//THE_END -extern ActorInfo gcBanjoKazooieSign;//player_KAZOOIE +extern ActorInfo D_8036804C;//GAME_OVER +extern ActorInfo D_8036807C;//THE_END +extern ActorInfo D_803680AC;//player_KAZOOIE extern ActorInfo chOverlayCopyrightDescription;//copyright_info -extern ActorInfo chOverlayPressStart;//PRESS_START -extern ActorInfo chOverlayNoController;//NO_CONTROLLER) +extern ActorInfo D_80368124;//PRESS_START +extern ActorInfo D_80368174;//NO_CONTROLLER) extern ActorInfo chBottlesBonusDescription; //jiggy_picture -extern ActorInfo chMumbosHandWithPicture; +extern ActorInfo D_8036833C; extern ActorInfo D_8036838C; -extern ActorInfo chBottlesBonusCursor; //banjos_hand_BB -extern ActorInfo chFireSparkle; //fire_sparkle -extern ActorInfo chBanjoCurtains; -extern ActorInfo chBanjoHouseDoor; -extern ActorInfo chFishbowl; //roysten -extern ActorInfo chCuckooClock; //cuckoo_clock +extern ActorInfo D_80368418; //banjos_hand_BB +extern ActorInfo D_80368450; //fire_sparkle +extern ActorInfo D_80368474; +extern ActorInfo D_80368498; +extern ActorInfo D_803684BC; //roysten +extern ActorInfo D_803684E0; //cuckoo_clock extern ActorInfo D_80368504; extern ActorInfo D_80368528; extern ActorInfo D_8036854C; extern ActorInfo D_80368570; -extern ActorInfo chMumboToken; //mumbotoken +extern ActorInfo D_803685A0; //mumbotoken extern ActorInfo chSnowman; //sirslush extern ActorInfo chSnowball; //snowball extern ActorInfo chSnowmanHat; //sir_slush_hat extern ActorInfo D_80372810; extern ActorInfo D_80372840; //grillchompa extern ActorInfo chClucker; //clucker -extern ActorInfo chScarabBeetle; //scarab +extern ActorInfo D_803728A0; //scarab extern ActorInfo chMinigame; //boombox -extern ActorInfo leafEmitterCCWAutumn; //leaf_particle -extern ActorInfo leafEmitterCCWHub; -extern ActorInfo rainEmitterCCWSpring; //rain -extern ActorInfo rainEmitterCCWHub; -extern ActorInfo snowEmitterCCWWinter; //snow -extern ActorInfo snowEmitterCCWHub; +extern ActorInfo D_80372970; //leaf_particle +extern ActorInfo D_80372994; +extern ActorInfo D_803729B8; //rain +extern ActorInfo D_803729DC; +extern ActorInfo D_80372A00; //snow +extern ActorInfo D_80372A24; extern ActorInfo D_80372A48; extern ActorInfo D_80372A6C; extern ActorInfo gChFireFxInfo; //fire extern ActorInfo gChDripsInfo;//water_drops extern ActorInfo chIcecubeA; extern ActorInfo chIcecubeB;//ice_cube -extern ActorInfo chTeeHee; //teehee +extern ActorInfo D_80372C18; //teehee extern ActorInfo chFlotsam; //floatsam extern ActorInfo D_80372D78; //limbo extern ActorInfo D_80372DF8; //grublin_hood extern ActorInfo chMumMum; //mummum -extern ActorInfo chChumpFish; +extern ActorInfo D_80372EE0; extern ActorInfo chTermite; //ticker extern ActorInfo D_80372FC0; extern ActorInfo D_80372FE4; extern ActorInfo gChBat; //nibbly extern ActorInfo chWhipcrack; -extern ActorInfo chBetaVent1; -extern ActorInfo chBetaVent2; -extern ActorInfo lairBottlesDialog; +extern ActorInfo D_80373134; +extern ActorInfo D_80373158; +extern ActorInfo D_803731B0; extern ActorInfo D_803732E0; extern ActorInfo D_80373DC0; @@ -182,32 +179,18 @@ u8 spawnQueueLength = 0; FunctionQueue *spawnQueue = NULL; /* .code */ -// [port] N64 used 15 entries, sized for the N64's draw distance. -// Scales with the Draw Distance enhancement. +// [port] N64 used 15 entries. If this overflows, find the root cause — +// something is adding entries faster than they're being flushed. #define SPAWN_QUEUE_DEFAULT_SIZE 15 #define SPAWN_QUEUE_GL_SIZE 50 -// [port] Capacity of the live allocation. -static u32 sSpawnQueueMax = 0; - static u32 __spawnQueue_getMax(void) { -#if 0 return (gsworld_getMap() == MAP_90_GL_BATTLEMENTS) ? SPAWN_QUEUE_GL_SIZE : SPAWN_QUEUE_DEFAULT_SIZE; -#endif - return sSpawnQueueMax; } void spawnQueue_malloc(void){ -#if 0 u32 tmp = __spawnQueue_getMax(); spawnQueue = (FunctionQueue *) bk_malloc(tmp * sizeof(FunctionQueue)); -#endif - u32 base = (gsworld_getMap() == MAP_90_GL_BATTLEMENTS) ? SPAWN_QUEUE_GL_SIZE : SPAWN_QUEUE_DEFAULT_SIZE; - // [port] The setting, not the render-time level: this runs during a map load, where - // port_getDrawDistanceLevel() clamps to 1x and would under-size the queue for the - // gameplay that follows. - sSpawnQueueMax = base * (u32) port_getDrawDistanceSetting(); - spawnQueue = (FunctionQueue *) bk_malloc(sSpawnQueueMax * sizeof(FunctionQueue)); } void spawnQueue_reset(void){ @@ -240,9 +223,9 @@ void spawnQueue_reset(void){ spawnableActorList_add(&D_803675F0, actor_new, ACTOR_FLAG_UNKNOWN_6); spawnableActorList_add(&chBigbutt, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25); spawnableActorList_add(&chSmallBull, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_8); - spawnableActorList_add(&chMumbo, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); + spawnableActorList_add(&D_803674E0, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chBeehive, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&chBeeSwarm, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_17); + spawnableActorList_add(&D_80367310, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_17); spawnableActorList_add(&D_80367390, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_19); spawnableActorList_add(&chJinjoYellow, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chJinjoOrange, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); @@ -251,12 +234,12 @@ void spawnQueue_reset(void){ spawnableActorList_add(&chJinjoGreen, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); spawnableActorList_add(&chJiggy, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21); spawnableActorList_add(&chJigsawDance, actor_new, ACTOR_FLAG_UNKNOWN_2); - spawnableActorList_add(&chPiranhaWaterParticles, actor_new, ACTOR_FLAG_UNKNOWN_2); - spawnableActorList_add(&chWadingBoots, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chEmptyHoneycomb, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoneycarrier - spawnableActorList_add(&chHoneycomb, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoney + spawnableActorList_add(&D_80367C60, actor_new, ACTOR_FLAG_UNKNOWN_2); + spawnableActorList_add(&D_80367A20, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_80366C80, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoneycarrier + spawnableActorList_add(&D_80366CA4, actor_new, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21); //chhoney spawnableActorList_add(&sumusicNote, actor_new, ACTOR_FLAG_UNKNOWN_21); //music_note - spawnableActorList_add(&chBlueEgg, actor_new, ACTOR_FLAG_UNKNOWN_21); //egg + spawnableActorList_add(&D_80367D00, actor_new, ACTOR_FLAG_UNKNOWN_21); //egg spawnableActorList_add(&D_80366340, func_802C8A54, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&D_80366364, func_802C8AA8, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&D_80366388, func_802C8AF8, ACTOR_FLAG_UNKNOWN_2); @@ -267,102 +250,103 @@ void spawnQueue_reset(void){ spawnableActorList_add(&D_80367AD4, func_802D75B4, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&D_80367AF8, func_802D7610, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&chTrainers, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&fxWadingBootsTouchSparkle, actor_new, ACTOR_FLAG_UNKNOWN_2); - spawnableActorList_add(&fxTurboTrainersTouchSparkle, actor_new, ACTOR_FLAG_UNKNOWN_2); //turbotrainers + spawnableActorList_add(&D_80365F60, actor_new, ACTOR_FLAG_UNKNOWN_2); + spawnableActorList_add(&D_80365F84, actor_new, ACTOR_FLAG_UNKNOWN_2); //turbotrainers spawnableActorList_add(&D_80367184, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&chExtraLife, actor_new, ACTOR_FLAG_UNKNOWN_21); //extralife spawnableActorList_add(&D_80365FB0, actor_new, ACTOR_FLAG_UNKNOWN_2); //shrapnel spawnableActorList_add(&chBadShad, actor_new, ACTOR_FLAG_UNKNOWN_2); //chbadshad - spawnableActorList_add(&chMumboToken, actor_new, ACTOR_FLAG_UNKNOWN_6); //mumbotoken + spawnableActorList_add(&gDummyPlayerAnchorInfo, actor_new, ACTOR_FLAG_UNKNOWN_2); //dummy player anchor + spawnableActorList_add(&D_803685A0, actor_new, ACTOR_FLAG_UNKNOWN_6); //mumbotoken spawnableActorList_add(&D_80367F30, actor_new, ACTOR_FLAG_UNKNOWN_10); spawnableActorList_add(&chBubble, actor_new, ACTOR_FLAG_UNKNOWN_2); spawnableActorList_add(&chGloop, actor_new, ACTOR_FLAG_UNKNOWN_1 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_7); //gloop spawnableActorList_add(&chShockJump, actor_new, ACTOR_FLAG_NONE); //chshockjump spawnableActorList_add(&chFlightPad, actor_new, ACTOR_FLAG_NONE); //flight_pad - spawnableActorList_add(&chRedFeather, actor_new, ACTOR_FLAG_UNKNOWN_21); //redfeather - spawnableActorList_add(&chGoldFeather, actor_new, ACTOR_FLAG_UNKNOWN_21); //goldfeather - spawnableActorList_add(&fxSpentRedFeather, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_redfeather - spawnableActorList_add(&fxSpentGoldFeather, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_goldfeather + spawnableActorList_add(&D_80367D24, actor_new, ACTOR_FLAG_UNKNOWN_21); //redfeather + spawnableActorList_add(&D_80367D48, actor_new, ACTOR_FLAG_UNKNOWN_21); //goldfeather + spawnableActorList_add(&D_80367C90, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_redfeather + spawnableActorList_add(&D_80367CB4, actor_new, ACTOR_FLAG_UNKNOWN_2); //spent_goldfeather spawnableActorList_add(&gChMole, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8); //bottles - spawnableActorList_add(&chMolehill, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6); //chmolehill + spawnableActorList_add(&D_80367E20, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6); //chmolehill spawnableActorList_add(&D_80373DC0, actor_new, ACTOR_FLAG_UNKNOWN_19); spawnableActorList_add(&D_80367E70, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&gChSnacker, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_16); //snacker spawnableActorList_add(&D_80366EF0, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_17); //large_shadow spawnableActorList_add(&D_80367B20, actor_new, ACTOR_FLAG_UNKNOWN_7); //chclimbbase - spawnableActorList_add(&chGoldBullion, actor_new, ACTOR_FLAG_UNKNOWN_6); //gold_bullion - spawnableActorList_add(&chOrangeCollectible, actor_new, ACTOR_FLAG_UNKNOWN_1); //orange - spawnableActorList_add(&leafEmitterCCWAutumn, actor_new, ACTOR_FLAG_UNKNOWN_7); //leaf_particle - spawnableActorList_add(&leafEmitterCCWHub, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&rainEmitterCCWSpring, actor_new, ACTOR_FLAG_UNKNOWN_7); //rain - spawnableActorList_add(&rainEmitterCCWHub, actor_new, ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&snowEmitterCCWWinter, actor_new, ACTOR_FLAG_UNKNOWN_7); //snow - spawnableActorList_add(&snowEmitterCCWHub, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80367BA4, actor_new, ACTOR_FLAG_UNKNOWN_6); //gold_bullion + spawnableActorList_add(&D_80367B80, actor_new, ACTOR_FLAG_UNKNOWN_1); //orange + spawnableActorList_add(&D_80372970, actor_new, ACTOR_FLAG_UNKNOWN_7); //leaf_particle + spawnableActorList_add(&D_80372994, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_803729B8, actor_new, ACTOR_FLAG_UNKNOWN_7); //rain + spawnableActorList_add(&D_803729DC, actor_new, ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80372A00, actor_new, ACTOR_FLAG_UNKNOWN_7); //snow + spawnableActorList_add(&D_80372A24, actor_new, ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&D_80372A48, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&D_80372A6C, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7); spawnableActorList_add(&chMinigame, actor_new, ACTOR_FLAG_UNKNOWN_7); //boombox - spawnableActorList_add(&chIceKey, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //ice_key - spawnableActorList_add(&chSnsEgg, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //SnS_egg + spawnableActorList_add(&D_803677A8, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //ice_key + spawnableActorList_add(&D_80367814, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //SnS_egg spawnableActorList_add(&gChFireFxInfo, actor_new, ACTOR_FLAG_NONE); //fire - spawnableActorList_add(&gWorldExitPad, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //level_entry_disk + spawnableActorList_add(&D_80367838, actor_new, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); //level_entry_disk spawnableActorList_add(&D_80367760, actor_new, ACTOR_FLAG_UNKNOWN_12); spawnableActorList_add(&D_80367784, actor_new, ACTOR_FLAG_UNKNOWN_12); - spawnableActorList_add(&gameSelect_banjoSleeping, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.without_right_hand - spawnableActorList_add(&gameSelect_banjoGameboy, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.playing_gameboy - spawnableActorList_add(&gameSelect_banjoCooking, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.cooking - spawnableActorList_add(&chMumboSwitch, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15);//mumbo_transform_pad - spawnableActorList_add(&chFFTeleportPad, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); - spawnableActorList_add(&lairBottlesDialog, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_80365E58, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.without_right_hand + spawnableActorList_add(&D_80365EAC, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.playing_gameboy + spawnableActorList_add(&D_80365F00, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_17); //banjo.cooking + spawnableActorList_add(&D_803677CC, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15);//mumbo_transform_pad + spawnableActorList_add(&D_803677F0, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15); + spawnableActorList_add(&D_803731B0, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&chSnowball, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_20);//snowball spawnableActorList_add(&chSnowmanHat, actor_new, ACTOR_FLAG_UNKNOWN_2);//sir_slush_hat spawnableActorList_add(&gChDripsInfo, actor_new, ACTOR_FLAG_UNKNOWN_10);//water_drops spawnableActorList_add(&chIcecubeB, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_25);//ice_cube - spawnableActorList_add(&gcGameOverSign, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//GAME_OVER - spawnableActorList_add(&gcTheEndSign, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//THE_END - spawnableActorList_add(&gcBanjoKazooieSign, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//player_KAZOOIE + spawnableActorList_add(&D_8036804C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//GAME_OVER + spawnableActorList_add(&D_8036807C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//THE_END + spawnableActorList_add(&D_803680AC, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//player_KAZOOIE spawnableActorList_add(&chOverlayCopyrightDescription, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//copyright_info - spawnableActorList_add(&chOverlayPressStart, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//PRESS_START + spawnableActorList_add(&D_80368124, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//PRESS_START spawnableActorList_add(&chBottlesBonusDescription, chBottlesBonus_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//jiggy_picture - spawnableActorList_add(&chMumbosHandWithPicture, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22); + spawnableActorList_add(&D_8036833C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22); spawnableActorList_add(&D_8036838C, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22); - spawnableActorList_add(&chBottlesBonusCursor, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//banjos_hand_BB - spawnableActorList_add(&chOverlayNoController, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//NO_CONTROLLER); - spawnableActorList_add(&chMumboSign5, actor_new, ACTOR_FLAG_NONE);//mumbo_token_sign.5 - spawnableActorList_add(&chMumboSign10, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.10 - spawnableActorList_add(&chMumboSign15, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.15 - spawnableActorList_add(&chMumboSign20, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.20 - spawnableActorList_add(&chMumboSign25, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.25 - spawnableActorList_add(&chMMWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.mm; - spawnableActorList_add(&chMMMWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.mmm - spawnableActorList_add(&chTTCWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.ttc - spawnableActorList_add(&chRBBWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.rbb - spawnableActorList_add(&chCCWWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.ccw - spawnableActorList_add(&chFPWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.fp - spawnableActorList_add(&chCCWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.cc - spawnableActorList_add(&chBGSWitchSwitch, actor_new, ACTOR_FLAG_NONE);//witch_switch.bgs - spawnableActorList_add(&chGVWitchSwitch, actor_new, ACTOR_FLAG_UNKNOWN_10);//witch_switch.gv - spawnableActorList_add(&chFireSparkle, actor_new, ACTOR_FLAG_UNKNOWN_17);//fire_sparkle - spawnableActorList_add(&chFishbowl, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8);//roysten - spawnableActorList_add(&chCuckooClock, actor_new, ACTOR_FLAG_NONE);//cuckoo_clock + spawnableActorList_add(&D_80368418, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//banjos_hand_BB + spawnableActorList_add(&D_80368174, actor_new, ACTOR_FLAG_UNKNOWN_2 | ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 | ACTOR_FLAG_UNKNOWN_20 | ACTOR_FLAG_UNKNOWN_22);//NO_CONTROLLER); + spawnableActorList_add(&D_80367530, actor_new, ACTOR_FLAG_NONE);//mumbo_token_sign.5 + spawnableActorList_add(&D_80367554, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.10 + spawnableActorList_add(&D_80367578, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.15 + spawnableActorList_add(&D_8036759C, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.20 + spawnableActorList_add(&D_803675C0, actor_new, ACTOR_FLAG_NONE);//mumbo_toke_sign.25 + spawnableActorList_add(&D_8036785C, actor_new, ACTOR_FLAG_NONE);//witch_switch.mm; + spawnableActorList_add(&D_80367880, actor_new, ACTOR_FLAG_NONE);//witch_switch.mmm + spawnableActorList_add(&D_803678A4, actor_new, ACTOR_FLAG_NONE);//witch_switch.ttc + spawnableActorList_add(&D_803678C8, actor_new, ACTOR_FLAG_NONE);//witch_switch.rbb + spawnableActorList_add(&D_803678EC, actor_new, ACTOR_FLAG_NONE);//witch_switch.ccw + spawnableActorList_add(&D_80367910, actor_new, ACTOR_FLAG_NONE);//witch_switch.fp + spawnableActorList_add(&D_80367934, actor_new, ACTOR_FLAG_NONE);//witch_switch.cc + spawnableActorList_add(&D_80367958, actor_new, ACTOR_FLAG_NONE);//witch_switch.bgs + spawnableActorList_add(&D_8036797C, actor_new, ACTOR_FLAG_UNKNOWN_10);//witch_switch.gv + spawnableActorList_add(&D_80368450, actor_new, ACTOR_FLAG_UNKNOWN_17);//fire_sparkle + spawnableActorList_add(&D_803684BC, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8);//roysten + spawnableActorList_add(&D_803684E0, actor_new, ACTOR_FLAG_NONE);//cuckoo_clock spawnableActorList_add(&D_80368504, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_80368528, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_8036854C, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_80368570, actor_new, ACTOR_FLAG_NONE); - spawnableActorList_add(&chBanjoCurtains, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7); - spawnableActorList_add(&chBanjoHouseDoor, actor_new, ACTOR_FLAG_NONE); + spawnableActorList_add(&D_80368474, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7); + spawnableActorList_add(&D_80368498, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_803732E0, actor_new, ACTOR_FLAG_NONE); spawnableActorList_add(&D_80372810, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_23); spawnableActorList_add(&chWhipcrack, actor_new, ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_23 | ACTOR_FLAG_UNKNOWN_25); - spawnableActorList_add(&chBetaVent1, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chBetaVent2, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); - spawnableActorList_add(&chChumpFish, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25); + spawnableActorList_add(&D_80373134, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_80373158, actor_new, ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_11); + spawnableActorList_add(&D_80372EE0, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25); spawnableActorList_addIfMapVisited(&chTermite, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_2_MM_MUMBOS_MOUNTAIN); //ticker spawnableActorList_addIfMapVisited(&chFlotsam, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_31_RBB_RUSTY_BUCKET_BAY); //floatsam - spawnableActorList_addIfMapVisited(&chTeeHee, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17, MAP_1B_MMM_MAD_MONSTER_MANSION); //teehee + spawnableActorList_addIfMapVisited(&D_80372C18, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_17, MAP_1B_MMM_MAD_MONSTER_MANSION); //teehee spawnableActorList_addIfMapVisited(&D_80372FC0, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); spawnableActorList_addIfMapVisited(&D_80372FE4, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); spawnableActorList_addIfMapVisited(&gChBat, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_21 |ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); //nibbly - spawnableActorList_addIfMapVisited(&chBuzzbomb, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_D_BGS_BUBBLEGLOOP_SWAMP); //buzzbomb + spawnableActorList_addIfMapVisited(&D_80367130, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_3 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_D_BGS_BUBBLEGLOOP_SWAMP); //buzzbomb spawnableActorList_addIfMapVisited(&chIcecubeA, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_17 | ACTOR_FLAG_UNKNOWN_25, MAP_27_FP_FREEZEEZY_PEAK); spawnableActorList_addIfMapVisited(&chShrapnelDescription, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_25, MAP_7_TTC_TREASURE_TROVE_COVE); //scrapnel spawnableActorList_addIfMapVisited(&D_80372D78, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_16 | ACTOR_FLAG_UNKNOWN_24 | ACTOR_FLAG_UNKNOWN_25, MAP_1B_MMM_MAD_MONSTER_MANSION); //limbo @@ -373,7 +357,7 @@ void spawnQueue_reset(void){ spawnableActorList_addIfMapVisited(&chBlackSnippet, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_24 | ACTOR_FLAG_UNKNOWN_25, MAP_7_TTC_TREASURE_TROVE_COVE); //black_snippet spawnableActorList_addIfMapVisited(&chMutieSnippet, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_12 | ACTOR_FLAG_UNKNOWN_24 | ACTOR_FLAG_UNKNOWN_25, MAP_7_TTC_TREASURE_TROVE_COVE); //mutie_snippet spawnableActorList_addIfMapVisited(&chClucker, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_23 |ACTOR_FLAG_UNKNOWN_25, MAP_40_CCW_HUB); //clucker - spawnableActorList_addIfMapVisited(&chScarabBeetle, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_12_GV_GOBIS_VALLEY); //scarab + spawnableActorList_addIfMapVisited(&D_803728A0, actor_new, ACTOR_FLAG_UNKNOWN_0 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_8 | ACTOR_FLAG_UNKNOWN_11 | ACTOR_FLAG_UNKNOWN_25, MAP_12_GV_GOBIS_VALLEY); //scarab spawnableActorList_addIfMapVisited(&chSnowman, actor_new, ACTOR_FLAG_UNKNOWN_5 | ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_25, MAP_27_FP_FREEZEEZY_PEAK); //sirslush switch(loaded_asm_file){ default: @@ -406,23 +390,23 @@ void spawnQueue_reset(void){ MM_func_803888B0(); break; case OVERLAY_7_SWAMP: - bgs_updateSpawnableActors(); + BGS_func_8038F1E0(); break; case OVERLAY_8_SHIP: RBB_func_80386C48(); break; case OVERLAY_9_SNOW: FP_func_80391324(); - spawnableActorList_add(&chBluePresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chGreenPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chRedPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&D_80367BC8, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&D_80367BEC, actor_new, ACTOR_FLAG_UNKNOWN_3); + spawnableActorList_add(&D_80367C10, actor_new, ACTOR_FLAG_UNKNOWN_3); break; case OVERLAY_A_TREE: CCW_func_8038DB6C(); break; } - // Romhacks globalize all overlays so any actor can spawn on any map. + // BB romhacks globalize all overlays so any actor can spawn on any map. // Register actors from every overlay that wasn't already handled above. if (port_isRomhack()) { if (loaded_asm_file != OVERLAY_D_WITCH) { lair_func_8038A0C4(); } @@ -434,14 +418,9 @@ void spawnQueue_reset(void){ if (loaded_asm_file != OVERLAY_4_DESERT) { GV_func_8038F154(); } if (loaded_asm_file != OVERLAY_5_BEACH) { code26D0_resetSpawnableActorsForTTC(); } if (loaded_asm_file != OVERLAY_6_JUNGLE) { MM_func_803888B0(); } - if (loaded_asm_file != OVERLAY_7_SWAMP) { bgs_updateSpawnableActors(); } + if (loaded_asm_file != OVERLAY_7_SWAMP) { BGS_func_8038F1E0(); } if (loaded_asm_file != OVERLAY_8_SHIP) { RBB_func_80386C48(); } - if (loaded_asm_file != OVERLAY_9_SNOW) { - FP_func_80391324(); - spawnableActorList_add(&chBluePresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chGreenPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); - spawnableActorList_add(&chRedPresentCollectible, actor_new, ACTOR_FLAG_UNKNOWN_3); - } + if (loaded_asm_file != OVERLAY_9_SNOW) { FP_func_80391324(); } if (loaded_asm_file != OVERLAY_A_TREE) { CCW_func_8038DB6C(); } } @@ -460,14 +439,13 @@ void spawnQueue_free(void){ bk_free(spawnQueue); spawnQueue = NULL; spawnQueueLength = 0; - sSpawnQueueMax = 0; // [port] no capacity without an allocation } void spawnQueue_func_802C39D4(void){ func_803268B4(); if(!levelSpecificFlags_validateCRC2()){ - eeprom_writeBlocks(0, 0, (void *)(uintptr_t) PHYS_TO_K0(0x00749530), EEPROM_MAXBLOCKS); + eeprom_writeBlocks(0, 0, (void *)(uintptr_t)0x80749530, EEPROM_MAXBLOCKS); } } @@ -507,68 +485,68 @@ void spawnQueue_flush(void){ func_803283D4(); } -void spawnQueue_unlock(void) { - spawnQueueLock = FALSE; +void spawnQueue_unlock(void){ + spawnQueueLock = 0; } -void spawnQueue_lock(void) { - spawnQueueLock = TRUE; +void spawnQueue_lock(void){ + spawnQueueLock = 1; } -void __spawnQueue_add_0(GenFunction_0 arg0){ +void __spawnQueue_add_0(void (* arg0)(void)){ u32 tmp = __spawnQueue_getMax(); - if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp + if(tmp != spawnQueueLength){ spawnQueue[spawnQueueLength].func0 = arg0; spawnQueue[spawnQueueLength].arg_cnt = 0; spawnQueueLength++; } else { - BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_0 entry", tmp); + BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_0 entry", tmp); } } void __spawnQueue_add_1(GenFunction_1 arg0, uintptr_t arg1){ u32 tmp = __spawnQueue_getMax(); - if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp - spawnQueue[spawnQueueLength].func1 = arg0; + if(tmp != spawnQueueLength){ + spawnQueue[spawnQueueLength].func0 = (void (*)(void))arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg_cnt = 1; spawnQueueLength++; } else { - BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_1 entry", tmp); + BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_1 entry", tmp); } } -void __spawnQueue_add_2(GenFunction_2 arg0, uintptr_t arg1, uintptr_t arg2){ +void __spawnQueue_add_2(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2){ u32 tmp = __spawnQueue_getMax(); - if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp - spawnQueue[spawnQueueLength].func2 = arg0; + if(tmp != spawnQueueLength){ + spawnQueue[spawnQueueLength].func0 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg_cnt = 2; spawnQueueLength++; } else { - BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_2 entry", tmp); + BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_2 entry", tmp); } } -void __spawnQueue_add_3(GenFunction_3 arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3){ +void __spawnQueue_add_3(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2, uintptr_t arg3){ u32 tmp = __spawnQueue_getMax(); - if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp - spawnQueue[spawnQueueLength].func3 = arg0; + if(tmp != spawnQueueLength){ + spawnQueue[spawnQueueLength].func0 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg[2] = arg3; spawnQueue[spawnQueueLength].arg_cnt = 3; spawnQueueLength++; } else { - BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_3 entry", tmp); + BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_3 entry", tmp); } } void __spawnQueue_add_4(GenFunction_4 arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4){ u32 tmp = __spawnQueue_getMax(); - if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp - spawnQueue[spawnQueueLength].func4 = arg0; + if(tmp != spawnQueueLength){ + spawnQueue[spawnQueueLength].func0 = (void (*)(void))arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg[2] = arg3; @@ -576,14 +554,14 @@ void __spawnQueue_add_4(GenFunction_4 arg0, uintptr_t arg1, uintptr_t arg2, uint spawnQueue[spawnQueueLength].arg_cnt = 4; spawnQueueLength++; } else { - BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_4 entry", tmp); + BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_4 entry", tmp); } } -void __spawnQueue_add_5(GenFunction_5 arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5){ +void __spawnQueue_add_5(void (* arg0)(void), uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5){ u32 tmp = __spawnQueue_getMax(); - if(tmp > spawnQueueLength){ // [port] decomp used !=; < also holds if length ever exceeds tmp - spawnQueue[spawnQueueLength].func5 = arg0; + if(tmp != spawnQueueLength){ + spawnQueue[spawnQueueLength].func0 = arg0; spawnQueue[spawnQueueLength].arg[0] = arg1; spawnQueue[spawnQueueLength].arg[1] = arg2; spawnQueue[spawnQueueLength].arg[2] = arg3; @@ -592,7 +570,7 @@ void __spawnQueue_add_5(GenFunction_5 arg0, uintptr_t arg1, uintptr_t arg2, uint spawnQueue[spawnQueueLength].arg_cnt = 5; spawnQueueLength++; } else { - BK_LOG_WARN("spawnQueue FULL (%d entries) — dropped add_5 entry", tmp); + BK_LOG_WARN("[port] spawnQueue FULL (%d entries) — dropped add_5 entry", tmp); } } diff --git a/src/core2/spline_bezier.c b/src/core2/spline_bezier.c index bdc4a40d1..60b98db21 100644 --- a/src/core2/spline_bezier.c +++ b/src/core2/spline_bezier.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C31A0.c #include "functions.h" #include "variables.h" #include diff --git a/src/core2/spline_pathfollow.c b/src/core2/spline_pathfollow.c index 271422d9c..f9a7dc596 100644 --- a/src/core2/spline_pathfollow.c +++ b/src/core2/spline_pathfollow.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B9770.c #include #include "functions.h" #include "variables.h" @@ -926,8 +925,8 @@ f32 func_80342260(s32 arg0, f32 arg1, s32 arg2){ return func_803234FC(func_80342038(arg0), arg1, 1.0f) / ((f32)arg2 /4); } -s32 func_803422AC(ActorMarker *caller, enum asset_e text_id, s32 arg2){ - return jiggyscore_total(); +void func_803422AC(ActorMarker *caller, enum asset_e text_id, s32 arg2){ + jiggyscore_total(); } s32 func_803422D4(Actor *arg0, Union_glspline *arg1, SplineList *arg2){ @@ -962,11 +961,6 @@ s32 func_803422D4(Actor *arg0, Union_glspline *arg1, SplineList *arg2){ break; case 3: - // [port] Path sfx nodes fire for whichever actor is walking the spline; listeners - // get the actor so a single actor's path sounds can be muted. - if (!EventSystem_Should(VB_SPLINE_PATH_SFX, true, arg0)) { - break; - } sp78 = arg1->t0.unk4.common.bit31; sp7C = arg1->t0.unk8.bit31 / 8.388608e6f; sp74 = arg1->t0.unk4.common.bit15 * 8; diff --git a/src/core2/sprite/render.c b/src/core2/sprite/render.c index 688853f8c..7424da231 100644 --- a/src/core2/sprite/render.c +++ b/src/core2/sprite/render.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_BD100.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -56,7 +55,7 @@ void func_80344138(BKSpriteDisplayData *self, s32 frame, s32 mirrored, f32 posit FrameInterpolation_RecordOpenChild("sprite_viewport", (uintptr_t)self); viewport_getPosition_vec3f(sp6C); - viewport_getLookVector(sp60); + viewport_getLookbk_vector(sp60); sp50[0] = position[0] - sp6C[0]; sp50[1] = position[1] - sp6C[1]; sp50[2] = position[2] - sp6C[2]; @@ -130,7 +129,7 @@ void func_80344424(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 posi FrameInterpolation_RecordOpenChild("sprite_viewport_rot", (uintptr_t)arg0); viewport_getPosition_vec3f(sp6C); - viewport_getLookVector(sp60); + viewport_getLookbk_vector(sp60); sp50[0] = position[0] - sp6C[0]; sp50[1] = position[1] - sp6C[1]; sp50[2] = position[2] - sp6C[2]; @@ -205,7 +204,7 @@ void func_80344720(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 posi // the caller rather than billboarded against the camera. FrameInterpolation_RecordOpenChild("sprite_3d", (uintptr_t)arg0); viewport_getPosition_vec3f(sp5C); - viewport_getLookVector(sp50); + viewport_getLookbk_vector(sp50); sp40[0] = position[0] - sp5C[0]; sp40[1] = position[1] - sp5C[1]; sp40[2] = position[2] - sp5C[2]; diff --git a/src/core2/sprite/rendertex.c b/src/core2/sprite/rendertex.c index 29e33f5bf..7933db4f3 100644 --- a/src/core2/sprite/rendertex.c +++ b/src/core2/sprite/rendertex.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C0E60.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/sprite/screenoverlay.c b/src/core2/sprite/screenoverlay.c index 55a166e8e..81e63673d 100644 --- a/src/core2/sprite/screenoverlay.c +++ b/src/core2/sprite/screenoverlay.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_AEDA0.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -206,9 +205,7 @@ void codeAEDA0_drawSprite( Gfx **gfx ) D_80370338[0] = 1; } - // [port] Vanilla only disarms G_AC_THRESHOLD when the draw-mode global still reads - // 0x0E. SpritePatches.cpp forces it so a mode change cannot leak it into later draws. - if (EventSystem_Should(VB_SPRITE_RESTORE_ALPHA_COMPARE, D_80383634 == 0x0E, gfx)) { + if(D_80383634 == 0x0E){ gDPSetAlphaCompare((*gfx)++, G_AC_NONE); } } @@ -288,7 +285,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr sp1B4 = *gfx; sp1B0 = var_a3; if(segment != 0){ - gSPVertexSeg((*gfx)++, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, 0, 0); + gSPVertex((*gfx)++, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), 0, 0); }else{ gSPVertex((*gfx)++, (uintptr_t)sp1B0, 0, 0); } @@ -338,7 +335,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr if (i_vtx == 0x10) { i_vtx = 0; if(segment != 0){ - gSPVertexSeg(sp1B4, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, 16, 0); + gSPVertex(sp1B4, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), 16, 0); }else{ gSPVertex(sp1B4, (uintptr_t)sp1B0, 16, 0); } @@ -346,7 +343,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr sp1B4 = *gfx; sp1B0 = var_a3; if (segment) { - gSPVertexSeg((*gfx)++, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, 0, 0); + gSPVertex((*gfx)++, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), 0, 0); } else { gSPVertex((*gfx)++, (uintptr_t)sp1B0, 0, 0); } @@ -360,7 +357,7 @@ void spriteRender_drawWithSegment(Gfx **gfx, Vtx **vtx, BKSprite *sprite, u32 fr //rewrite vtx seg start with correct vtx count if (i_vtx > 0) { if(segment != 0){ - gSPVertexSeg(sp1B4, segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start, i_vtx, 0); + gSPVertex(sp1B4, SEGMENT_ADDR(segment, (uintptr_t)sp1B0 - (uintptr_t)vtx_start), i_vtx, 0); }else{ if(1); gSPVertex(sp1B4, (uintptr_t)sp1B0, i_vtx, 0); diff --git a/src/core2/sprite/texblock.c b/src/core2/sprite/texblock.c index b1f56c843..877da6005 100644 --- a/src/core2/sprite/texblock.c +++ b/src/core2/sprite/texblock.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B8020.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/statetimer.c b/src/core2/state_timer.c similarity index 97% rename from src/core2/statetimer.c rename to src/core2/state_timer.c index 43ec68385..cc4132e0e 100644 --- a/src/core2/statetimer.c +++ b/src/core2/state_timer.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/statetimer.c #include "core2/statetimer.h" #include "bk_time.h" diff --git a/src/core2/texture_dataaccess.c b/src/core2/texture_dataaccess.c index 918f00c50..164e942ed 100644 --- a/src/core2/texture_dataaccess.c +++ b/src/core2/texture_dataaccess.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_63690.c #include #include "functions.h" #include "variables.h" @@ -52,12 +51,12 @@ s32 textureInfo_getPaletteSize(BKTextureInfo *this){ } // texture_getOffset -s32 textureInfo_getOffset(BKTextureInfo *this){ +s32 func_802EA6DC(BKTextureInfo *this){ return this->offset; } //texture_getSize -s32 textureInfo_getTextureSize(BKTextureInfo *this){ +s32 func_802EA6E4(BKTextureInfo *this){ s32 palette_size = textureInfo_getPaletteSize(this); s32 pixel_size = textureInfo_getBitDepth(this); @@ -65,6 +64,6 @@ s32 textureInfo_getTextureSize(BKTextureInfo *this){ } //textureList_getTexture -BKTextureInfo *textureList_getTextureInfo(BKTextureList *arg0, s32 indx){ +BKTextureInfo *func_802EA748(BKTextureList *arg0, s32 indx){ return (BKTextureInfo *)(arg0 +1) + indx; } diff --git a/src/core2/time.c b/src/core2/time.c index 120493fa5..fa7e9f224 100644 --- a/src/core2/time.c +++ b/src/core2/time.c @@ -1,7 +1,6 @@ #include "bk_time.h" #include "core1/vimgr.h" -#include "version.h" #ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) @@ -27,7 +26,7 @@ void time_reset(void){ void time_setDeltaReal_sec(f32 d_seconds){ if(d_seconds != 0.0f){ - s_dTimeReal_sec = MIN(d_seconds, VER_SELECT(0.05, 0.06, 0.05, 0.05)); + s_dTimeReal_sec = MIN(d_seconds, 0.05); } else{ s_dTimeReal_sec = 0.01f; @@ -36,7 +35,7 @@ void time_setDeltaReal_sec(f32 d_seconds){ void time_setDeltaReal_frames(s32 d_frames){ s_dTimeReal_frames = MAX(MIN(0xf, d_frames) , 1); - time_setDeltaReal_sec(s_dTimeReal_frames*(1.0/FRAMERATE)); + time_setDeltaReal_sec(s_dTimeReal_frames*(1/60.0)); } s32 time_getDeltaReal_frames(void){ @@ -48,11 +47,11 @@ f32 time_getDelta(void){ } f32 time_func_8033DDB8(void){ - return viMgr_func_8024BD94()*(1.0/FRAMERATE); + return viMgr_func_8024BD94()*(1/60.0); } f32 time_getDelta_frames(void){ - return time_getDelta()*(FRAMERATE/2.0); + return time_getDelta()*30.0; } void time_setMultiplier(f32 multiplier){ diff --git a/src/core2/time_framedelta.c b/src/core2/time_framedelta.c index 525731e34..d9ac652ca 100644 --- a/src/core2/time_framedelta.c +++ b/src/core2/time_framedelta.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_B6C60.c #include #include "functions.h" #include "variables.h" @@ -29,7 +28,22 @@ f32 func_8033DC20(void){ u64 now = SDL_GetPerformanceCounter(); u64 freq = SDL_GetPerformanceFrequency(); f32 out; - D_80384470 = viMgr_func_8024BD94(); - out = (1.0 / FRAMERATE)*D_80384470; + + if (last_ticks == 0) { + last_ticks = now; + out = 1.0f / 30.0f; // first frame: assume 1/30 (N64 rate) + } else { + out = (f32)(now - last_ticks) / (f32)freq; + last_ticks = now; + } + + // Cap at 50ms (matching time_setDeltaReal_sec cap) + if (out > 0.05f) out = 0.05f; + if (out <= 0.0f) out = 1.0f / 60.0f; + + // Keep D_80384470 updated for anything that reads it + D_80384470 = (s32)(out * 60.0f + 0.5f); + if (D_80384470 < 1) D_80384470 = 1; + return out; } diff --git a/src/core2/timedfuncqueue.c b/src/core2/timed_funcqueue.c similarity index 99% rename from src/core2/timedfuncqueue.c rename to src/core2/timed_funcqueue.c index 7bb527941..6fb994e18 100644 --- a/src/core2/timedfuncqueue.c +++ b/src/core2/timed_funcqueue.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/timedfuncqueue.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vla.c b/src/core2/vector.c similarity index 92% rename from src/core2/vla.c rename to src/core2/vector.c index d8c6e284a..ddb6dc37b 100644 --- a/src/core2/vla.c +++ b/src/core2/vector.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/vla.c #include #include "functions.h" #include "core2/vla.h" @@ -81,9 +80,7 @@ void bk_vector_remove(VLA *this, u32 indx){ uintptr_t nextOffset = (uintptr_t)this->begin + (indx + 1) * this->elem_size;\ uintptr_t size = (uintptr_t)this->end - (uintptr_t)this->begin; - // [port] source and destination overlap when removing anywhere but the tail; - // memcpy on overlapping buffers is UB on PC toolchains. - memmove((void *)elemOffset, (void *)nextOffset, size - (indx + 1) * this->elem_size); + memcpy((void *)elemOffset, (void *)nextOffset, size - (indx + 1) * this->elem_size); this->end = (void *)((uintptr_t)this->end - this->elem_size); } diff --git a/src/core2/vtx/alphablend.c b/src/core2/vtx/alphablend.c index bed705f72..32ee43d7e 100644 --- a/src/core2/vtx/alphablend.c +++ b/src/core2/vtx/alphablend.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C76D0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/colorapply.c b/src/core2/vtx/colorapply.c index deaa3182d..81ab464a1 100644 --- a/src/core2/vtx/colorapply.c +++ b/src/core2/vtx/colorapply.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C4F40.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/colorintensity.c b/src/core2/vtx/colorintensity.c index c6582ad65..a27db662d 100644 --- a/src/core2/vtx/colorintensity.c +++ b/src/core2/vtx/colorintensity.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C8230.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/colorset.c b/src/core2/vtx/colorset.c index 0675a34dd..c881d926f 100644 --- a/src/core2/vtx/colorset.c +++ b/src/core2/vtx/colorset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C5AF0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/convert.c b/src/core2/vtx/convert.c index bfe05a056..9d530a9c3 100644 --- a/src/core2/vtx/convert.c +++ b/src/core2/vtx/convert.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C61C0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/gclights.c b/src/core2/vtx/lighting.c similarity index 94% rename from src/core2/vtx/gclights.c rename to src/core2/vtx/lighting.c index 67f3e0b65..ccf12fa17 100644 --- a/src/core2/vtx/gclights.c +++ b/src/core2/vtx/lighting.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/gclights.c #include "functions.h" #include "variables.h" #include @@ -166,7 +165,7 @@ static void __lighting_setPosition(s32 index , f32 *position) { TUPLE_COPY(v0->position, position) } -static void __lighting_setFadeRadii(s32 index , f32 *unk18_and_unk1c) { +static void __lighting_setUnk18AndUnk1C(s32 index , f32 *unk18_and_unk1c) { Lighting *v0 = bk_vector_at(sLightingbk_vectorList.bk_vector_ptr, index-1); v0->fade_radius_min_unscaled = unk18_and_unk1c[0]; v0->fade_radius_max_unscaled = unk18_and_unk1c[1]; @@ -191,7 +190,7 @@ void lightingVectorList_fromFile(File *file_ptr) { ) { lighting_ptr = __lighting_create(); __lighting_setPosition(lighting_ptr, position); - __lighting_setFadeRadii(lighting_ptr, unk18_and_unk1c); + __lighting_setUnk18AndUnk1C(lighting_ptr, unk18_and_unk1c); __lighting_setRgb(lighting_ptr, rgb); } } @@ -233,12 +232,6 @@ void gclights_recolor_vertices(BKVertexList *vertex_list, f32 position[3], f32 r ref_ptr = vtxList_getVertices(ref_vertex_list); vtxList_getVtxRange(vertex_list, &i_ptr, &end_ptr); - // [port] Cancelled by PerfPatches.cpp, which runs this same loop with a - // squared-distance early-out so out-of-range lights never pay the sqrt. - if (!EventSystem_Should(VB_GCLIGHTS_RECOLOR, true, i_ptr, end_ptr, ref_ptr, &sLightingbk_vectorList.unk4[0], - sLightingbk_vectorList.unk44)) { - return; - } for(i_ptr = i_ptr; i_ptr < end_ptr; i_ptr++, ref_ptr++) { rgb_modifier[0] = rgb_modifier[1] = rgb_modifier[2] = 0.0f; TUPLE_COPY(vtx_position, ref_ptr->v.ob); diff --git a/src/core2/vtx/list.c b/src/core2/vtx/list.c index 59eb775d5..eac054e13 100644 --- a/src/core2/vtx/list.c +++ b/src/core2/vtx/list.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_654C0.c #include "core1/core1.h" #include "functions.h" #include "variables.h" @@ -42,7 +41,7 @@ void vtxList_getBounds_f32(BKVertexList *vtxList, f32 min[3], f32 max[3]){ max[2] = (f32) vtxList->maxCoord[2]; } -void vtxList_getBoundsTransformed(BKVertexList *self, f32 min[3], f32 max[3]) { +void vtxList_getBoundsMlMtxTransformed(BKVertexList *self, f32 min[3], f32 max[3]) { Vtx *start_vtx; Vtx *end_vtx; Vtx *i_vtx; @@ -76,7 +75,7 @@ void vtxList_getBoundsTransformed(BKVertexList *self, f32 min[3], f32 max[3]) { } } -void vtxList_func_802EC680(BKVertexList *self, s32 arg1, f32 arg2[3], f32 arg3[3]) { +void func_802EC680(BKVertexList *self, s32 arg1, f32 arg2[3], f32 arg3[3]) { Vtx *start_vtx; Vtx *end_vtx; Vtx *i_vtx; @@ -228,7 +227,7 @@ void vtxList_func_802ECBD4(BKVertexList *dst, BKVertexList *src, f32 position[3] s32 pad40; viewport_getPosition_vec3f(vp_position); - viewport_getLookVector(vp_look); + viewport_getLookbk_vector(vp_look); mlMtxIdent(); func_80252CC4(position, rotation, 1.0f, NULL); mlMtx_apply_vec3f(vp_position, vp_position); diff --git a/src/core2/vtx/listutils.c b/src/core2/vtx/listutils.c index 5c028c7dc..f484b58bd 100644 --- a/src/core2/vtx/listutils.c +++ b/src/core2/vtx/listutils.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_5FD90.c #include #include "functions.h" #include "variables.h" @@ -205,8 +204,8 @@ bool func_802E74A0(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3[3]) { f32 sp24[3]; f32 sp20; - if (arg1 <= ml_vec3f_distance_to_point(arg2, arg3, arg0)) { - return FALSE; + if (arg1 <= ml_func_802560D0(arg2, arg3, arg0)) { + return false; } sp24[0] = (arg2[0] + arg3[0]) / 2; sp24[1] = (arg2[1] + arg3[1]) / 2; @@ -218,7 +217,6 @@ bool func_802E74A0(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3[3]) { return true; } -// Unused bool func_802E7588(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3) { return (ml_vec3f_distance(arg0, arg2) < (arg1 + arg3)); } diff --git a/src/core2/vtx/meshcount.c b/src/core2/vtx/meshcount.c index 393fd29e0..3d553ebd1 100644 --- a/src/core2/vtx/meshcount.c +++ b/src/core2/vtx/meshcount.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_62FD0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/normalset.c b/src/core2/vtx/normalset.c index e31a5efd0..786ce7efb 100644 --- a/src/core2/vtx/normalset.c +++ b/src/core2/vtx/normalset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C5F00.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/positionset.c b/src/core2/vtx/positionset.c index 0c560f4f0..49b2cb594 100644 --- a/src/core2/vtx/positionset.c +++ b/src/core2/vtx/positionset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C8490.c #include #include "functions.h" #include "variables.h" @@ -17,7 +16,7 @@ void func_8034F434(Struct76s *arg0, s32 arg1) { arg0->alpha = 0; arg0->unk2 = randi2(200, 255); arg0->unk4 = (s32) (arg0->unk4 + 1); - arg0->unk14 = arg0->unk10 = randf2(VER_SELECT(0.08f, 0.12f, 0.0f, 0.0f), VER_SELECT(0.12f, 0.18f, 0.0f, 0.0f)); + arg0->unk14 = arg0->unk10 = randf2(0.08f, 0.12f); if ((arg0->unk4 == 1) && func_8034C4CC()) { gcsfx_playWithPitch(SFX_B5_THUNDERBOLT, randf2(0.9f, 1.1f), randi2(10000, 20000)); } @@ -57,13 +56,13 @@ void func_8034F5B0(Struct76s *arg0, BKModel *arg1, s32 arg2){ func_8034F434(arg0, 1); } if (arg0->unkC == 1) { - if (arg0->unk10 <= VER_SELECT(0.04, 0.06, 0.0, 0.0)) { - arg0->alpha = (arg0->unk10 / VER_SELECT(0.04, 0.06, 0.0, 0.0)) * arg0->unk2; + if (arg0->unk10 <= 0.04) { + arg0->alpha = (arg0->unk10 / 0.04) * arg0->unk2; } else { - if (arg0->unk10 < (arg0->unk14 - VER_SELECT(0.04, 0.06, 0.0, 0.0))) { + if (arg0->unk10 < (arg0->unk14 - 0.04)) { arg0->alpha = arg0->unk2; } else { - arg0->alpha = ((arg0->unk14 - arg0->unk10) / VER_SELECT(0.04, 0.06, 0.0, 0.0)) * arg0->unk2; + arg0->alpha = ((arg0->unk14 - arg0->unk10) / 0.04) * arg0->unk2; } } if (ml_timer_update(&arg0->unk10, sp24)) { diff --git a/src/core2/vtx/renderstart.c b/src/core2/vtx/renderstart.c index f20ff1171..b48c8919e 100644 --- a/src/core2/vtx/renderstart.c +++ b/src/core2/vtx/renderstart.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C62B0.c #include #include "functions.h" #include "variables.h" @@ -247,7 +246,7 @@ void func_8034E120(Struct6Ds *arg0, f32 arg1, f32 arg2, f32 arg3,s32 arg4){ } void func_8034E174(Struct6Ds *arg0){ - func_8034E1A4(arg0, SFX_3EC_CCW_DOOR_OPENING, 0.7f, 0.9f); + func_8034E1A4(arg0, 0x3ec, 0.7f, 0.9f); } void func_8034E1A4(Struct6Ds *arg0, enum sfx_e sfx_id, f32 arg2, f32 arg3){ diff --git a/src/core2/vtx/scale.c b/src/core2/vtx/scale.c index f72955fea..f0111ce62 100644 --- a/src/core2/vtx/scale.c +++ b/src/core2/vtx/scale.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C7CC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/core2/vtx/transform.c b/src/core2/vtx/transform.c index f737f7104..d36550580 100644 --- a/src/core2/vtx/transform.c +++ b/src/core2/vtx/transform.c @@ -1,7 +1,5 @@ -// BanjoDecomp: core2/code_C5440.c #include #include "functions.h" -#include "port/ShipUtils.h" // BK_LOG_*, port_shapeControllerInput #include "variables.h" #include "model.h" #include diff --git a/src/core2/vtx/uvset.c b/src/core2/vtx/uvset.c index dc4e191e3..57a578bec 100644 --- a/src/core2/vtx/uvset.c +++ b/src/core2/vtx/uvset.c @@ -1,4 +1,3 @@ -// BanjoDecomp: core2/code_C5CC0.c #include #include "functions.h" #include "variables.h" diff --git a/src/cutscenes/cutscenesspawnqueue.c b/src/cutscenes/actor_spawninit.c similarity index 99% rename from src/cutscenes/cutscenesspawnqueue.c rename to src/cutscenes/actor_spawninit.c index d3a35cd79..ab09fe0e4 100644 --- a/src/cutscenes/cutscenesspawnqueue.c +++ b/src/cutscenes/actor_spawninit.c @@ -1,4 +1,4 @@ -// BanjoDecomp: cutscenes/cutscenesspawnqueue.c +// BanjoDecomp: code_60F0.c #include #include "functions.h" #include "variables.h" diff --git a/src/cutscenes/bss_pad.c b/src/cutscenes/bss_pad.c new file mode 100644 index 000000000..598952dc5 --- /dev/null +++ b/src/cutscenes/bss_pad.c @@ -0,0 +1,2 @@ +// BanjoDecomp: bss_pad.c +char pad_cutscenes_8038E9E0[0x10]; diff --git a/src/cutscenes/theendsign.c b/src/cutscenes/character_parade.c similarity index 79% rename from src/cutscenes/theendsign.c rename to src/cutscenes/character_parade.c index 3b1665620..8948202fb 100644 --- a/src/cutscenes/theendsign.c +++ b/src/cutscenes/character_parade.c @@ -1,18 +1,17 @@ -// BanjoDecomp: core2/gc/theendsign.c +// BanjoDecomp: (core2 origin - unknown exact file) #include #include "functions.h" #include "variables.h" Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); -void gcTheEndSign_update(Actor *this); +void func_802DC67C(Actor *this); /* .data */ f32 D_80368070[3] = {0.0f, 0.0f, 0.0f}; - -ActorInfo gcTheEndSign = { - MARKER_17C_MODEL_THE_END_SIGN, ACTOR_19C_MODEL_THE_END_SIGN, ASSET_56C_MODEL_THE_END_SIGN, - 0x1, NULL, - gcTheEndSign_update, actor_update_func_80326224, func_802DC320, +ActorInfo D_8036807C = { + 0x17C, 0x19C, 0x56C, + 0x1, NULL, + func_802DC67C, actor_update_func_80326224, func_802DC320, 0, 0, 0.0f, 0 }; @@ -25,7 +24,7 @@ void func_802DC650(Actor * this){ func_8025A7DC(COMUSIC_AC_GOOD_ENDING); } -void gcTheEndSign_update(Actor *this){ +void func_802DC67C(Actor *this){ if(!this->initialized){ this->initialized = true; diff --git a/src/cutscenes/checksums.c b/src/cutscenes/checksums.c deleted file mode 100644 index 6514c7fd6..000000000 --- a/src/cutscenes/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: cutscenes/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsCutscenes; diff --git a/src/cutscenes/cutscene_trigger.c b/src/cutscenes/cutscene_trigger.c index 253557059..9c9ba8858 100644 --- a/src/cutscenes/cutscene_trigger.c +++ b/src/cutscenes/cutscene_trigger.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/ch/code_468E0.c +// BanjoDecomp: (core2 origin - unknown exact file) #include #include "core1/core1.h" #include "functions.h" diff --git a/src/cutscenes/glow_sparkle.c b/src/cutscenes/fx/glow_sparkle.c similarity index 100% rename from src/cutscenes/glow_sparkle.c rename to src/cutscenes/fx/glow_sparkle.c diff --git a/src/cutscenes/smoke.c b/src/cutscenes/fx/smoke.c similarity index 100% rename from src/cutscenes/smoke.c rename to src/cutscenes/fx/smoke.c diff --git a/src/cutscenes/sparkle.c b/src/cutscenes/fx/sparkle.c similarity index 100% rename from src/cutscenes/sparkle.c rename to src/cutscenes/fx/sparkle.c diff --git a/src/emptyLvl/checksums.c b/src/emptyLvl/checksums.c deleted file mode 100644 index 3475b09b2..000000000 --- a/src/emptyLvl/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: emptyLvl/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsEmptyLvl; diff --git a/src/fight/checksums.c b/src/fight/checksums.c deleted file mode 100644 index 3bc3a4bea..000000000 --- a/src/fight/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: fight/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsFight; diff --git a/src/lair/checksums.c b/src/lair/checksums.c deleted file mode 100644 index dd033ff12..000000000 --- a/src/lair/checksums.c +++ /dev/null @@ -1,7 +0,0 @@ -// BanjoDecomp: lair/checksums.c -#include -#include "checksums.h" - -// !! THIS FILE MUST BE LINKED FIRST FOR THIS OVERLAY !! - -/* bss */ struct overlay_checksums_s gChecksumsLair; diff --git a/src/lair/jigsawpicture.h b/src/lair/jigsawpicture.h deleted file mode 100644 index 9e940ac34..000000000 --- a/src/lair/jigsawpicture.h +++ /dev/null @@ -1,11 +0,0 @@ -// BanjoDecomp: lair/jigsawpicture.h -typedef enum { - JIGSAW_PICTURE_LEAVE_PODIUM = 1, - JIGSAW_PICTURE_ENTER_PODIUM = 2, - JIGSAW_PICTURE_INSTRUCTIONS = 3, - JIGSAW_PICTURE_WAITING = 4, - JIGSAW_PICTURE_ADD_PIECE = 5, - JIGSAW_PICTURE_ADD_ALL = 6, - JIGSAW_PICTURE_COMPLETE = 7, - JIGSAW_PICTURE_REMOVE_PIECE = 8 -} JigsawPictureState; diff --git a/src/emptyLvl/empty_level.c b/src/overlay_stub/empty_level.c similarity index 75% rename from src/emptyLvl/empty_level.c rename to src/overlay_stub/empty_level.c index 532935b68..dbc493fde 100644 --- a/src/emptyLvl/empty_level.c +++ b/src/overlay_stub/empty_level.c @@ -1,5 +1,5 @@ // BanjoDecomp: emptyLvl/code_0.c unsigned char emptyLvl = 0; -unsigned char emptyLvlBss[0x10]; +unsigned char emptyLvlBss[0x20]; void emptyLvl_func_803863F0(void){} diff --git a/src/port/Audio/AudioSync.cpp b/src/port/Audio/AudioSync.cpp index 435de1960..c349e5986 100644 --- a/src/port/Audio/AudioSync.cpp +++ b/src/port/Audio/AudioSync.cpp @@ -7,9 +7,6 @@ // thread-shared section with osSetIntMask(OS_IM_NONE)/restore. Routing those brackets to this // lock protects all of them with no edits to the audio code. -#include -#include -#include #include extern "C" { @@ -21,26 +18,6 @@ std::recursive_mutex gAudioLock; thread_local int gAudioMaskDepth = 0; } // namespace -// Window-freeze audio hold -namespace { -constexpr int64_t kCushionMs = 100; -std::atomic sAllowedUntilMs{ 0 }; - -int64_t NowMs() { - return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) - .count(); -} -} // namespace - -extern "C" void port_noteMainLoopAlive(void) { - sAllowedUntilMs.store(NowMs() + kCushionMs, std::memory_order_relaxed); -} - -extern "C" int port_audioStallHold(void) { - const int64_t allowedUntil = sAllowedUntilMs.load(std::memory_order_relaxed); - return allowedUntil != 0 && NowMs() > allowedUntil; -} - extern "C" void port_lockAudio(void) { gAudioLock.lock(); } diff --git a/src/port/Audio/mixer.h b/src/port/Audio/mixer.h index c7358a110..4420a159a 100644 --- a/src/port/Audio/mixer.h +++ b/src/port/Audio/mixer.h @@ -36,20 +36,20 @@ void aSetVolumeImpl(uint8_t flags, int16_t v, int16_t t, int16_t r); void aPoleFilterImpl(uint8_t flags, uint16_t gain, uint8_t dmem_shift, void* state); void aDisableImpl(uint16_t outp, uint32_t b, uint32_t c); -#define aDisable(pkt, o, b, c) ((void)(pkt), aDisableImpl(o, b, c)) -#define aClearBuffer(pkt, d, c) ((void)(pkt), aClearBufferImpl(d, c)) -#define aLoadBuffer(pkt, c, d, s) ((void)(pkt), aLoadBufferImpl((void*)(s), d, c)) -#define aSaveBuffer(pkt, c, s, d) ((void)(pkt), aSaveBufferImpl(s, (int16_t*)(d), c)) -#define aLoadADPCM(pkt, c, d) ((void)(pkt), aLoadADPCMImpl(c, (int16_t*)(d))) -#define aDMEMMove(pkt, i, o, c) ((void)(pkt), aDMEMMoveImpl(i, o, c)) -#define aSetLoop(pkt, a) ((void)(pkt), aSetLoopImpl((void*)(a))) -#define aADPCMdec(pkt, s, f, c, i, o) ((void)(pkt), aADPCMdecImpl(f, (void*)(s), c, i, o)) -#define aResample(pkt, s, f, p, i, o) ((void)(pkt), aResampleImpl(f, p, (void*)(s), i, o)) -#define aInterleave(pkt) ((void)(pkt), aInterleaveImpl()) -#define aMix(pkt, f, g, i, o) ((void)(pkt), aMixImpl(f, g, i, o)) -#define aEnvMixer(pkt, f, t, s) ((void)(pkt), aEnvMixerImpl(f, (void*)(s), t)) -#define aSetVolume(pkt, f, v, t, r) ((void)(pkt), aSetVolumeImpl(f, v, t, r)) -#define aPoleFilter(pkt, f, g, t, s) ((void)(pkt), aPoleFilterImpl(f, g, t, s)) -#define aPlayMP3(pkt, a, b, c, r) ((void)(pkt), aPlayMP3Impl((void*)(a), b, (void*)(c), r)) +#define aDisable(pkt, o, b, c) aDisableImpl(o, b, c) +#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c) +#define aLoadBuffer(pkt, c, d, s) aLoadBufferImpl((void*)(s), d, c) +#define aSaveBuffer(pkt, c, s, d) aSaveBufferImpl(s, (int16_t*)(d), c) +#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, (int16_t*)(d)) +#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c) +#define aSetLoop(pkt, a) aSetLoopImpl((void*)(a)) +#define aADPCMdec(pkt, s, f, c, i, o) aADPCMdecImpl(f, (void*)(s), c, i, o) +#define aResample(pkt, s, f, p, i, o) aResampleImpl(f, p, (void*)(s), i, o) +#define aInterleave(pkt) aInterleaveImpl() +#define aMix(pkt, f, g, i, o) aMixImpl(f, g, i, o) +#define aEnvMixer(pkt, f, t, s) aEnvMixerImpl(f, (void*)(s), t) +#define aSetVolume(pkt, f, v, t, r) aSetVolumeImpl(f, v, t, r) +#define aPoleFilter(pkt, f, g, t, s) aPoleFilterImpl(f, g, t, s) +#define aPlayMP3(pkt, a, b, c, r) aPlayMP3Impl((void*)(a), b, (void*)(c), r) #endif diff --git a/src/port/Controller/ControlSchemes.cpp b/src/port/Controller/ControlSchemes.cpp index 75a725da3..05c55e9e1 100644 --- a/src/port/Controller/ControlSchemes.cpp +++ b/src/port/Controller/ControlSchemes.cpp @@ -17,14 +17,13 @@ #include #include #include +#include #include #include #include #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Camera/FreeLookCamera.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" #include "port/ShipUtils.h" #include "ControlSchemes.h" @@ -32,7 +31,6 @@ extern "C" { #include "enums.h" int bs_getState(void); int bsbtrot_inSet(int state); // nonzero if `state` is one of the Talon Trot states -s32 getGameMode(void); } using namespace Ship; @@ -93,40 +91,20 @@ void BindButtonToLeftStick(const std::shared_ptr& controller, Direct stick->SaveAxisDirectionMappingIdsToConfig(); } -// How many of a button's mappings are physically active right now. Lets a -// scheme tell one binding for a button apart from another without reaching past -// the mapper to poll hardware that the player may have unbound. -int CountActiveMappings(const std::shared_ptr& controller, CONTROLLERBUTTONS_T bitmask) { +// True if the given C-button is currently driven by a stick axis (the right +// stick), as opposed to a face button. Drives which directions the shaping pass +// regenerates from the raw right stick. +bool CButtonIsAxis(const std::shared_ptr& controller, CONTROLLERBUTTONS_T bitmask) { auto button = controller->GetButton(bitmask); if (button == nullptr) { - return 0; + return false; } - int active = 0; for (auto& [id, mapping] : button->GetAllButtonMappings()) { - uint16_t held = 0; - mapping->UpdatePad(held); - if (held != 0) { - active++; - } - } - return active; -} - -// Splits a C-button's mappings into the two kinds the shaping pass cares about. -void CollectCButtonSources(const std::shared_ptr& controller, CONTROLLERBUTTONS_T bitmask, - uint16_t& axisMask, uint16_t& otherHeld) { - auto button = controller->GetButton(bitmask); - if (button == nullptr) { - return; - } - for (auto& [id, mapping] : button->GetAllButtonMappings()) { - auto axis = dynamic_cast(mapping.get()); - if (axis != nullptr && axis->AxisIsStick()) { - axisMask |= bitmask; - } else { - mapping->UpdatePad(otherHeld); + if (dynamic_cast(mapping.get()) != nullptr) { + return true; } } + return false; } } // namespace @@ -152,8 +130,6 @@ void ControlSchemes_Apply(int scheme) { ClearButtonSDL(controller, BTN_CUP); BindButton(controller, BTN_CUP, SDL_CONTROLLER_BUTTON_Y); BindButton(controller, BTN_CDOWN, SDL_CONTROLLER_BUTTON_B); - BindAxisToButton(controller, BTN_CLEFT, SDL_CONTROLLER_AXIS_RIGHTX, -1); - BindAxisToButton(controller, BTN_CRIGHT, SDL_CONTROLLER_AXIS_RIGHTX, 1); // Recenter camera ClearButtonSDL(controller, BTN_R); @@ -201,11 +177,8 @@ void ControlSchemes_Apply(int scheme) { ClearButtonSDL(controller, BTN_CDOWN); BindButton(controller, BTN_CDOWN, SDL_CONTROLLER_BUTTON_B); - // Tip-toe / Talon Trot trigger. Recentering moves to a B hold, which - // frees R to carry Pocket's extra gesture as a real, rebindable - // binding instead of the shaping pass polling the trigger itself. + // Recenter camera ClearButtonSDL(controller, BTN_R); - BindAxisToButton(controller, BTN_R, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 1); // Crouch / Talon Trot ClearButtonSDL(controller, BTN_Z); @@ -227,15 +200,6 @@ void ControlSchemes_Apply(int scheme) { } } -// Frames of C-Down passthrough left for a jigsaw podium. -static int32_t sJigsawPodiumTTL = 0; - -void RegisterControlSchemes_Init() { - COND_HOOK(OnJigsawPodiumInput, EVENT_PRIORITY_NORMAL, true, [](IEvent*) { sJigsawPodiumTTL = 4; }); -} - -static RegisterShipInitFunc initControlSchemes(RegisterControlSchemes_Init); - extern "C" void port_shapeControllerInput(void* contPad) { auto* pad = static_cast(contPad); if (pad == nullptr) { @@ -250,70 +214,84 @@ extern "C" void port_shapeControllerInput(void* contPad) { return; } - const int scheme = CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO); - const bool modern = (scheme == CONTROL_SCHEME_MODERN); - const bool pocket = (scheme == CONTROL_SCHEME_POCKET); - const bool crouched = (bs_getState() == BS_7_CROUCH); + const bool modern = CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_MODERN; + const bool crouched = (bs_getState() == BS_CROUCH); const bool eggPooping = (bs_getState() == BS_A_EGG_ASS); - // Pocket takes its tip-toe / Talon Trot gesture from R and its crouch from - // Z, so both follow whatever the player has bound. Sample them here, before - // the blocks below start injecting synthetic R and Z bits, and consume R - - // in Pocket that button is the gesture channel, not the camera recenter. - bool pocketGesture = false; - bool pocketCrouch = false; - if (pocket) { - pocketGesture = (pad->button & BTN_R) != 0; - pocketCrouch = (pad->button & BTN_Z) != 0; - pad->button &= ~BTN_R; - } - int32_t rx = pad->right_stick_x; int32_t ry = pad->right_stick_y; int32_t arx = (rx < 0) ? -rx : rx; int32_t ary = (ry < 0) ? -ry : ry; - const bool onJigsawPodium = (sJigsawPodiumTTL > 0); - if (sJigsawPodiumTTL > 0) { - sJigsawPodiumTTL--; - } - if (modern) { - if (!crouched && !eggPooping && !onJigsawPodium) { + if (!crouched && !eggPooping) { pad->button &= ~BTN_CDOWN; } - const s32 mode = getGameMode(); - const bool picturePuzzle = (mode == GAME_MODE_8_BOTTLES_BONUS || mode == GAME_MODE_A_SNS_PICTURE); - if (!picturePuzzle) { - const uint16_t stickC = pad->button & (BTN_CLEFT | BTN_CRIGHT); - uint16_t allow = 0; - - // One action per push, so holding the stick cannot repeat Wonderwing. - static bool sStickArmed = true; - if (stickC == 0) { - sStickArmed = true; - } else if (crouched && (stickC & BTN_CRIGHT) && arx >= ary && sStickArmed) { - allow = BTN_CRIGHT; - sStickArmed = false; + // Read the raw right stick straight from SDL + int32_t sdlX = 0; + int32_t sdlY = 0; + { + auto ctx = Ship::Context::GetRawInstance(); + auto controlDeck = ctx != nullptr ? ctx->GetControlDeck() : nullptr; + auto deviceManager = controlDeck != nullptr ? controlDeck->GetConnectedPhysicalDeviceManager() : nullptr; + if (deviceManager != nullptr) { + for (auto& [instanceId, gamepad] : deviceManager->GetConnectedSDLGamepadsForPort(0)) { + if (gamepad == nullptr) { + continue; + } + int32_t x = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTX); + int32_t y = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTY); + if ((x < 0 ? -x : x) > (sdlX < 0 ? -sdlX : sdlX)) { + sdlX = x; + } + if ((y < 0 ? -y : y) > (sdlY < 0 ? -sdlY : sdlY)) { + sdlY = y; + } + } } - pad->button = (pad->button & ~(BTN_CLEFT | BTN_CRIGHT)) | allow; + } + int32_t asx = (sdlX < 0) ? -sdlX : sdlX; + int32_t asy = (sdlY < 0) ? -sdlY : sdlY; + + // Edge press with hysteresis + static bool sStickArmed = true; + const int32_t onThreshold = 12000; + const int32_t offThreshold = 6000; + + // Standing, the camera owns the right stick + // Crouched, it yields one action + uint16_t want = 0; + if (crouched && sdlX > onThreshold && asx >= asy) { + want = BTN_CRIGHT; // stick-right -> Wonderwing + } + + if (want != 0 && sStickArmed) { + pad->button |= want; + sStickArmed = false; + } + if ((crouched ? asx : asy) < offThreshold) { + sStickArmed = true; } } else { uint16_t axisMask = 0; - uint16_t otherHeld = 0; - static const CONTROLLERBUTTONS_T kCButtons[] = { BTN_CRIGHT, BTN_CLEFT, BTN_CDOWN, BTN_CUP }; - for (CONTROLLERBUTTONS_T cButton : kCButtons) { - CollectCButtonSources(controller, cButton, axisMask, otherHeld); + if (CButtonIsAxis(controller, BTN_CRIGHT)) { + axisMask |= BTN_CRIGHT; + } + if (CButtonIsAxis(controller, BTN_CLEFT)) { + axisMask |= BTN_CLEFT; + } + if (CButtonIsAxis(controller, BTN_CDOWN)) { + axisMask |= BTN_CDOWN; + } + if (CButtonIsAxis(controller, BTN_CUP)) { + axisMask |= BTN_CUP; } - // Directions the stick owns outright; anything a second binding is - // holding stays put instead of being cleared and regenerated. - const uint16_t clearMask = axisMask & ~otherHeld; static uint16_t sLatchDir = 0; static int32_t sLatchTTL = 0; - if (port_freeLook_isEnabled() && !onJigsawPodium) { + if (port_freeLook_isEnabled()) { uint16_t stickBits = 0; if (arx * arx + ary * ary > 24 * 24) { if (arx >= ary) { @@ -322,11 +300,11 @@ extern "C" void port_shapeControllerInput(void* contPad) { stickBits = (ry > 0) ? BTN_CUP : BTN_CDOWN; } } - pad->button &= ~(stickBits & clearMask); + pad->button &= ~(stickBits & axisMask); sLatchDir = 0; sLatchTTL = 0; } else if (axisMask != 0) { - pad->button &= ~clearMask; + pad->button &= ~axisMask; if (arx * arx + ary * ary > 24 * 24) { uint16_t dir; @@ -366,20 +344,44 @@ extern "C" void port_shapeControllerInput(void* contPad) { } // Modern Talon Trot - // - // Crouch gets bound to both triggers, and pressing the second one while the - // first is held starts the trot. Counting how many crouch bindings are live - // expresses that without naming a trigger: whatever the player has on Z is - // what works, and a trigger they have unbound does nothing. - static int sPrevCrouchBindings = 0; + static bool sPrevLeftTrigger = false; + static bool sPrevRightTrigger = false; + if (modern) { - const int crouchBindings = CountActiveMappings(controller, BTN_Z); - if (crouched && crouchBindings >= 2 && crouchBindings > sPrevCrouchBindings) { - pad->button |= BTN_CLEFT; + const Sint16 kTriggerThreshold = 8000; + bool leftTrigger = false; + bool rightTrigger = false; + + auto ctx = Ship::Context::GetRawInstance(); + auto controlDeck = ctx != nullptr ? ctx->GetControlDeck() : nullptr; + auto deviceManager = controlDeck != nullptr ? controlDeck->GetConnectedPhysicalDeviceManager() : nullptr; + if (deviceManager != nullptr) { + for (auto& [instanceId, gamepad] : deviceManager->GetConnectedSDLGamepadsForPort(0)) { + if (gamepad == nullptr) { + continue; + } + if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > kTriggerThreshold) { + leftTrigger = true; + } + if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > kTriggerThreshold) { + rightTrigger = true; + } + } + } + + if (crouched) { + bool leftEdge = leftTrigger && !sPrevLeftTrigger; + bool rightEdge = rightTrigger && !sPrevRightTrigger; + if ((rightEdge && sPrevLeftTrigger) || (leftEdge && sPrevRightTrigger)) { + pad->button |= BTN_CLEFT; + } } - sPrevCrouchBindings = crouchBindings; + + sPrevLeftTrigger = leftTrigger; + sPrevRightTrigger = rightTrigger; } else { - sPrevCrouchBindings = 0; + sPrevLeftTrigger = false; + sPrevRightTrigger = false; } // Toggle Trot @@ -417,7 +419,8 @@ extern "C" void port_shapeControllerInput(void* contPad) { static bool sBWasHeld = false; const int32_t kBHoldFrames = 12; // ~0.2s before a standing press counts as a hold bool bHeld = (pad->button & BTN_CDOWN) != 0; - if (pocket && !crouched && !eggPooping) { + if (CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_POCKET && !crouched && + !eggPooping) { pad->button &= ~BTN_CDOWN; if (bHeld) { if (sBHeldFrames < kBHoldFrames) { @@ -440,25 +443,43 @@ extern "C" void port_shapeControllerInput(void* contPad) { } sBWasHeld = bHeld; - // Pocket: Talon Trot (Z + R) and tip-toe (R) - // Z crouches. While crouched, an R press injects C-Left to start the Talon Trot. - // R on its own (no crouch) lightly touches the analog stick for a tip-toe. - // Both come off the mapped pad, so rebinding either button moves the gesture. + // Pocket: Talon Trot (LT + RT) and tip-toe (RT) + // LT crouches. While crouched, an RT press injects C-Left to start the Talon Trot. + // RT on its own (no crouch) lightly touches the analog stick for a tip-toe. static bool sTipToe = false; - static bool sPrevGesture = false; - if (pocket) { - if (pocketCrouch) { - // Crouching: R is the Talon Trot trigger, not tip-toe. - if (crouched && pocketGesture && !sPrevGesture) { + static bool sPrevR2 = false; + if (CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_POCKET) { + bool r2 = false; + bool l2 = false; + auto ctx = Ship::Context::GetRawInstance(); + auto controlDeck = ctx != nullptr ? ctx->GetControlDeck() : nullptr; + auto deviceManager = controlDeck != nullptr ? controlDeck->GetConnectedPhysicalDeviceManager() : nullptr; + if (deviceManager != nullptr) { + for (auto& [instanceId, gamepad] : deviceManager->GetConnectedSDLGamepadsForPort(0)) { + if (gamepad == nullptr) { + continue; + } + if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > 8000) { + r2 = true; + } + if (SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > 8000) { + l2 = true; + } + } + } + + if (l2) { + // Crouching: RT is the Talon Trot trigger, not tip-toe. + if (crouched && r2 && !sPrevR2) { pad->button |= BTN_CLEFT; // C-Left while crouched starts the Talon Trot } sTipToe = false; } else if (CVarGetInteger(CVAR_SETTING("Controls.PocketTipToeHold"), 0) != 0) { - sTipToe = pocketGesture; // hold mode - } else if (pocketGesture && !sPrevGesture) { + sTipToe = r2; // hold mode + } else if (r2 && !sPrevR2) { sTipToe = !sTipToe; // tap toggles } - sPrevGesture = pocketGesture; + sPrevR2 = r2; if (sTipToe) { const float kTipToeScale = 0.25f; @@ -467,6 +488,6 @@ extern "C" void port_shapeControllerInput(void* contPad) { } } else { sTipToe = false; - sPrevGesture = false; + sPrevR2 = false; } } diff --git a/src/port/Controller/Mapper.cpp b/src/port/Controller/Mapper.cpp deleted file mode 100644 index d2b5bf956..000000000 --- a/src/port/Controller/Mapper.cpp +++ /dev/null @@ -1,1709 +0,0 @@ -#include "Mapper.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/port/Engine.h" -#include "src/port/UI/LighthouseGui.hpp" -#include "src/port/UI/LighthouseMenu.h" -#include "src/port/UI/UIWidgets.hpp" -#include "src/port/UI/cvar_prefixes.h" - -#include - -namespace LighthouseGui { -extern std::shared_ptr mLighthouseMenu; -} - -namespace Mapper { - -using namespace UIWidgets; - -static const char* kUserMappingsFileName = "usergamepadmappings.txt"; - -static const char* kDiagramTextureName = "Gamepad-Mapper-Diagram"; -static const char* kDiagramTexturePath = "textures/mapping-xbox.png"; - -// --------------------------------------------------------------------------------------------------- -// Binding metadata -// --------------------------------------------------------------------------------------------------- - -static const char* kButtonNames[SDL_CONTROLLER_BUTTON_MAX] = { - "A", - "B", - "X", - "Y", - "Back", - "Guide", - "Start", - "Left Stick Click", - "Right Stick Click", - "Left Bumper", - "Right Bumper", - "D-Pad Up", - "D-Pad Down", - "D-Pad Left", - "D-Pad Right", - "Misc 1", - "Paddle 1", - "Paddle 2", - "Paddle 3", - "Paddle 4", - "Touchpad", -}; - -static const char* kAxisNames[AXIS_BINDING_MAX] = { - "Left Stick Left", "Left Stick Right", "Left Stick Up", "Left Stick Down", "Right Stick Left", - "Right Stick Right", "Right Stick Up", "Right Stick Down", "Left Trigger", "Right Trigger", -}; - -const char* BindingName(int32_t binding) { - if (binding < 0 || binding >= BINDING_COUNT) { - return "?"; - } - if (binding < SDL_CONTROLLER_BUTTON_MAX) { - return kButtonNames[binding]; - } - return kAxisNames[binding - SDL_CONTROLLER_BUTTON_MAX]; -} - -struct StickAxisPair { - SDL_GameControllerAxis axis; - int32_t negative; - int32_t positive; -}; - -static const StickAxisPair kStickAxes[] = { - { SDL_CONTROLLER_AXIS_LEFTX, AXIS_LEFTX_NEGATIVE, AXIS_LEFTX_POSITIVE }, - { SDL_CONTROLLER_AXIS_LEFTY, AXIS_LEFTY_NEGATIVE, AXIS_LEFTY_POSITIVE }, - { SDL_CONTROLLER_AXIS_RIGHTX, AXIS_RIGHTX_NEGATIVE, AXIS_RIGHTX_POSITIVE }, - { SDL_CONTROLLER_AXIS_RIGHTY, AXIS_RIGHTY_NEGATIVE, AXIS_RIGHTY_POSITIVE }, -}; - -static const int32_t kCoreBindingOrder[] = { - SDL_CONTROLLER_BUTTON_A, - SDL_CONTROLLER_BUTTON_B, - SDL_CONTROLLER_BUTTON_X, - SDL_CONTROLLER_BUTTON_Y, - SDL_CONTROLLER_BUTTON_BACK, - SDL_CONTROLLER_BUTTON_START, - SDL_CONTROLLER_BUTTON_LEFTSHOULDER, - SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, - SDL_CONTROLLER_BUTTON_LEFTSTICK, - SDL_CONTROLLER_BUTTON_RIGHTSTICK, - SDL_CONTROLLER_BUTTON_DPAD_UP, - SDL_CONTROLLER_BUTTON_DPAD_DOWN, - SDL_CONTROLLER_BUTTON_DPAD_LEFT, - SDL_CONTROLLER_BUTTON_DPAD_RIGHT, - SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_NEGATIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_POSITIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_NEGATIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_POSITIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_NEGATIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_POSITIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_NEGATIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_POSITIVE, - SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT, - SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT, -}; - -static const int32_t kExtraBindings[] = { - SDL_CONTROLLER_BUTTON_GUIDE, SDL_CONTROLLER_BUTTON_MISC1, SDL_CONTROLLER_BUTTON_PADDLE1, - SDL_CONTROLLER_BUTTON_PADDLE2, SDL_CONTROLLER_BUTTON_PADDLE3, SDL_CONTROLLER_BUTTON_PADDLE4, - SDL_CONTROLLER_BUTTON_TOUCHPAD, -}; - -// --------------------------------------------------------------------------------------------------- -// Binding helpers -// --------------------------------------------------------------------------------------------------- - -static ExtendedBind NoBind() { - ExtendedBind bind = {}; - bind.bindType = SDL_CONTROLLER_BINDTYPE_NONE; - return bind; -} - -void ClearBindings(ExtendedBind (&bindings)[BINDING_COUNT]) { - for (int32_t i = 0; i < BINDING_COUNT; i++) { - bindings[i] = NoBind(); - } -} - -bool HasAnyBinding(const ExtendedBind (&bindings)[BINDING_COUNT]) { - for (int32_t i = 0; i < BINDING_COUNT; i++) { - if (bindings[i].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { - return true; - } - } - return false; -} - -static bool IsFullRangeAxis(const ExtendedBind& bind) { - if (bind.bindType != SDL_CONTROLLER_BINDTYPE_AXIS) { - return false; - } - return (bind.value.axis.axisMin == SDL_JOYSTICK_AXIS_MIN && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MAX) || - (bind.value.axis.axisMin == SDL_JOYSTICK_AXIS_MAX && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MIN); -} - -static bool MergeAxisBindings(ExtendedBind (&bindings)[BINDING_COUNT], int32_t negative, int32_t positive) { - ExtendedBind& a = bindings[negative]; - ExtendedBind& b = bindings[positive]; - if (a.bindType == SDL_CONTROLLER_BINDTYPE_AXIS && b.bindType == SDL_CONTROLLER_BINDTYPE_AXIS && - a.value.axis.axis == b.value.axis.axis && a.value.axis.axisMin == b.value.axis.axisMin) { - a.value.axis.axisMin = a.value.axis.axisMax; - a.value.axis.axisMax = b.value.axis.axisMax; - b = NoBind(); - return true; - } - return false; -} - -static std::string EncodeBindElement(const ExtendedBind& bind) { - switch (bind.bindType) { - case SDL_CONTROLLER_BINDTYPE_BUTTON: - return StringHelper::Sprintf("b%d", bind.value.button); - case SDL_CONTROLLER_BINDTYPE_AXIS: - if (bind.value.axis.axisMin == 0 && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MIN) { - return StringHelper::Sprintf("-a%d", bind.value.axis.axis); - } - if (bind.value.axis.axisMin == 0 && bind.value.axis.axisMax == SDL_JOYSTICK_AXIS_MAX) { - return StringHelper::Sprintf("+a%d", bind.value.axis.axis); - } - return StringHelper::Sprintf("a%d%s", bind.value.axis.axis, - bind.value.axis.axisMin > bind.value.axis.axisMax ? "~" : ""); - case SDL_CONTROLLER_BINDTYPE_HAT: - return StringHelper::Sprintf("h%d.%d", bind.value.hat.hat, bind.value.hat.hatMask); - default: - return ""; - } -} - -static const char* HatMaskName(int32_t mask) { - switch (mask) { - case SDL_HAT_UP: - return "Up"; - case SDL_HAT_DOWN: - return "Down"; - case SDL_HAT_LEFT: - return "Left"; - case SDL_HAT_RIGHT: - return "Right"; - case SDL_HAT_LEFTUP: - return "Up-Left"; - case SDL_HAT_RIGHTUP: - return "Up-Right"; - case SDL_HAT_LEFTDOWN: - return "Down-Left"; - case SDL_HAT_RIGHTDOWN: - return "Down-Right"; - default: - return "?"; - } -} - -std::string DescribeBind(const ExtendedBind& bind) { - switch (bind.bindType) { - case SDL_CONTROLLER_BINDTYPE_BUTTON: - return StringHelper::Sprintf("Button %d", bind.value.button); - case SDL_CONTROLLER_BINDTYPE_AXIS: - if (IsFullRangeAxis(bind)) { - return StringHelper::Sprintf("Axis %d%s", bind.value.axis.axis, - bind.value.axis.axisMin > bind.value.axis.axisMax ? " inv" : ""); - } - return StringHelper::Sprintf("Axis %d %s", bind.value.axis.axis, - bind.value.axis.axisMax < bind.value.axis.axisMin ? "-" : "+"); - case SDL_CONTROLLER_BINDTYPE_HAT: - return StringHelper::Sprintf("Hat %d %s", bind.value.hat.hat, HatMaskName(bind.value.hat.hatMask)); - default: - return ""; - } -} - -// --------------------------------------------------------------------------------------------------- -// Mapping string generation / parsing -// --------------------------------------------------------------------------------------------------- - -static std::string SanitizeName(const std::string& name) { - std::string result = name; - std::replace(result.begin(), result.end(), ',', ' '); - return result; -} - -std::string GenerateMappingString(SDL_Joystick* joystick, const ExtendedBind (&bindings)[BINDING_COUNT], - const std::string& nameOverride) { - if (joystick == nullptr) { - return ""; - } - - SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); - uint16_t crc = 0; -#if SDL_VERSION_ATLEAST(2, 26, 0) - SDL_GetJoystickGUIDInfo(guid, nullptr, nullptr, nullptr, &crc); - if (crc != 0) { - guid.data[2] = 0; - guid.data[3] = 0; - } -#endif - - char guidString[33] = ""; - SDL_JoystickGetGUIDString(guid, guidString, sizeof(guidString)); - - const char* rawName = SDL_JoystickName(joystick); - std::string name = SanitizeName(nameOverride); - if (name.find_first_not_of(' ') == std::string::npos) { - name = SanitizeName(rawName != nullptr ? rawName : guidString); - } - - std::string mapping = StringHelper::Sprintf("%s,%s,platform:%s,", guidString, name.c_str(), SDL_GetPlatform()); - if (crc != 0) { - mapping += StringHelper::Sprintf("crc:%.4x,", crc); - } - - ExtendedBind work[BINDING_COUNT]; - for (int32_t i = 0; i < BINDING_COUNT; i++) { - work[i] = bindings[i]; - } - - for (int32_t i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++) { - if (work[i].bindType == SDL_CONTROLLER_BINDTYPE_NONE) { - continue; - } - const char* name = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)i); - if (name == nullptr) { - continue; - } - mapping += StringHelper::Sprintf("%s:%s,", name, EncodeBindElement(work[i]).c_str()); - } - - for (const auto& stick : kStickAxes) { - const int32_t negative = SDL_CONTROLLER_BUTTON_MAX + stick.negative; - const int32_t positive = SDL_CONTROLLER_BUTTON_MAX + stick.positive; - const char* name = SDL_GameControllerGetStringForAxis(stick.axis); - if (name == nullptr) { - continue; - } - - MergeAxisBindings(work, negative, positive); - - if (work[negative].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { - const char* prefix = IsFullRangeAxis(work[negative]) ? "" : "-"; - mapping += StringHelper::Sprintf("%s%s:%s,", prefix, name, EncodeBindElement(work[negative]).c_str()); - } - if (work[positive].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { - mapping += StringHelper::Sprintf("+%s:%s,", name, EncodeBindElement(work[positive]).c_str()); - } - } - - const std::pair triggers[] = { - { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERLEFT }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT }, - }; - for (const auto& trigger : triggers) { - if (work[trigger.first].bindType == SDL_CONTROLLER_BINDTYPE_NONE) { - continue; - } - const char* name = SDL_GameControllerGetStringForAxis(trigger.second); - if (name == nullptr) { - continue; - } - mapping += StringHelper::Sprintf("%s:%s,", name, EncodeBindElement(work[trigger.first]).c_str()); - } - - return mapping; -} - -static int32_t BindingIndexForKey(const std::string& key) { - std::string name = key; - char sign = 0; - if (!name.empty() && (name.front() == '+' || name.front() == '-')) { - sign = name.front(); - name.erase(0, 1); - } - - const SDL_GameControllerAxis axis = SDL_GameControllerGetAxisFromString(name.c_str()); - if (axis != SDL_CONTROLLER_AXIS_INVALID) { - switch (axis) { - case SDL_CONTROLLER_AXIS_LEFTX: - return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_LEFTX_POSITIVE : AXIS_LEFTX_NEGATIVE); - case SDL_CONTROLLER_AXIS_LEFTY: - return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_LEFTY_POSITIVE : AXIS_LEFTY_NEGATIVE); - case SDL_CONTROLLER_AXIS_RIGHTX: - return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_RIGHTX_POSITIVE : AXIS_RIGHTX_NEGATIVE); - case SDL_CONTROLLER_AXIS_RIGHTY: - return SDL_CONTROLLER_BUTTON_MAX + (sign == '+' ? AXIS_RIGHTY_POSITIVE : AXIS_RIGHTY_NEGATIVE); - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: - return SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: - return SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT; - default: - return -1; - } - } - - if (sign != 0) { - return -1; - } - const SDL_GameControllerButton button = SDL_GameControllerGetButtonFromString(name.c_str()); - return button != SDL_CONTROLLER_BUTTON_INVALID ? (int32_t)button : -1; -} - -static bool DecodeBindElement(const std::string& value, ExtendedBind& out) { - std::string element = value; - bool inverted = false; - if (!element.empty() && element.back() == '~') { - inverted = true; - element.pop_back(); - } - - char sign = 0; - if (!element.empty() && (element.front() == '+' || element.front() == '-')) { - sign = element.front(); - element.erase(0, 1); - } - if (element.size() < 2) { - return false; - } - - out = {}; - out.committed = true; - - switch (element.front()) { - case 'b': - out.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON; - out.value.button = std::atoi(element.c_str() + 1); - return true; - case 'a': - out.bindType = SDL_CONTROLLER_BINDTYPE_AXIS; - out.value.axis.axis = std::atoi(element.c_str() + 1); - if (sign == '-') { - out.value.axis.axisMin = 0; - out.value.axis.axisMax = SDL_JOYSTICK_AXIS_MIN; - } else if (sign == '+') { - out.value.axis.axisMin = 0; - out.value.axis.axisMax = SDL_JOYSTICK_AXIS_MAX; - } else { - out.value.axis.axisMin = inverted ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN; - out.value.axis.axisMax = inverted ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX; - } - return true; - case 'h': { - int32_t hat = 0; - int32_t mask = 0; - if (std::sscanf(element.c_str() + 1, "%d.%d", &hat, &mask) != 2) { - return false; - } - out.bindType = SDL_CONTROLLER_BINDTYPE_HAT; - out.value.hat.hat = hat; - out.value.hat.hatMask = mask; - return true; - } - default: - out = NoBind(); - return false; - } -} - -int32_t ParseMappingString(const std::string& mapping, ExtendedBind (&bindings)[BINDING_COUNT]) { - ClearBindings(bindings); - - int32_t recovered = 0; - size_t start = 0; - while (start <= mapping.size()) { - const size_t end = mapping.find(',', start); - const std::string field = mapping.substr(start, end == std::string::npos ? std::string::npos : end - start); - start = end == std::string::npos ? mapping.size() + 1 : end + 1; - - const size_t colon = field.find(':'); - if (colon == std::string::npos) { - continue; - } - - const int32_t index = BindingIndexForKey(field.substr(0, colon)); - if (index < 0) { - continue; - } - if (DecodeBindElement(field.substr(colon + 1), bindings[index])) { - recovered++; - } - } - - for (const auto& stick : kStickAxes) { - const int32_t negative = SDL_CONTROLLER_BUTTON_MAX + stick.negative; - const int32_t positive = SDL_CONTROLLER_BUTTON_MAX + stick.positive; - if (!IsFullRangeAxis(bindings[negative]) || bindings[positive].bindType != SDL_CONTROLLER_BINDTYPE_NONE) { - continue; - } - - const bool axisInverted = bindings[negative].value.axis.axisMin > bindings[negative].value.axis.axisMax; - bindings[positive] = bindings[negative]; - bindings[negative].value.axis.axisMin = 0; - bindings[negative].value.axis.axisMax = axisInverted ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN; - bindings[positive].value.axis.axisMin = 0; - bindings[positive].value.axis.axisMax = axisInverted ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX; - } - - return recovered; -} - -// --------------------------------------------------------------------------------------------------- -// MappingSession -// --------------------------------------------------------------------------------------------------- - -MappingSession::MappingSession() - : mBindings{}, mCurrentStep(0), mPendingAdvanceTime(0), mActive(false), mComplete(false) { - ClearBindings(mBindings); -} - -void MappingSession::Start(SDL_Joystick* joystick, const std::vector& order) { - mOrder = order; - mCurrentStep = 0; - mComplete = mOrder.empty(); - mActive = !mOrder.empty(); - mPendingAdvanceTime = 0; - - const int32_t axisCount = joystick != nullptr ? SDL_JoystickNumAxes(joystick) : 0; - mAxisState.assign(axisCount > 0 ? (size_t)axisCount : 0, AxisState{}); - for (int32_t i = 0; i < axisCount; i++) { - Sint16 initialValue = 0; - mAxisState[i].moving = SDL_JoystickGetAxisInitialState(joystick, i, &initialValue) == SDL_TRUE; - mAxisState[i].lastValue = initialValue; - mAxisState[i].startingValue = initialValue; - mAxisState[i].farthestValue = initialValue; - } - - if (mActive) { - mBindings[mOrder[0]] = NoBind(); - } -} - -void MappingSession::Stop() { - mActive = false; - mComplete = false; - mOrder.clear(); - mAxisState.clear(); - mPendingAdvanceTime = 0; -} - -bool MappingSession::IsActive() const { - return mActive; -} - -bool MappingSession::IsComplete() const { - return mComplete; -} - -int32_t MappingSession::CurrentStep() const { - return mCurrentStep; -} - -int32_t MappingSession::StepCount() const { - return (int32_t)mOrder.size(); -} - -int32_t MappingSession::CurrentBinding() const { - if (mCurrentStep < 0 || mCurrentStep >= (int32_t)mOrder.size()) { - return -1; - } - return mOrder[mCurrentStep]; -} - -void MappingSession::GoToStep(int32_t step) { - if (step < 0) { - return; - } - if (step >= (int32_t)mOrder.size()) { - mComplete = true; - mActive = false; - return; - } - - mCurrentStep = step; - - mBindings[mOrder[mCurrentStep]] = NoBind(); - for (auto& state : mAxisState) { - state.farthestValue = state.startingValue; - } - mPendingAdvanceTime = 0; -} - -void MappingSession::Advance() { - GoToStep(mCurrentStep + 1); -} - -void MappingSession::GoBack() { - GoToStep(mCurrentStep - 1); -} - -const ExtendedBind& MappingSession::GetBinding(int32_t index) const { - return mBindings[index]; -} - -void MappingSession::SetBindings(const ExtendedBind (&bindings)[BINDING_COUNT]) { - for (int32_t i = 0; i < BINDING_COUNT; i++) { - mBindings[i] = bindings[i]; - } -} - -void MappingSession::CopyBindingsTo(ExtendedBind (&out)[BINDING_COUNT]) const { - for (int32_t i = 0; i < BINDING_COUNT; i++) { - out[i] = mBindings[i]; - } -} - -bool MappingSession::BindingContainsBinding(const ExtendedBind& a, const ExtendedBind& b) const { - if (a.bindType != b.bindType) { - return false; - } - - if (a.bindType == SDL_CONTROLLER_BINDTYPE_AXIS) { - if (a.value.axis.axis != b.value.axis.axis || !a.committed) { - return false; - } - const int32_t minA = std::min(a.value.axis.axisMin, a.value.axis.axisMax); - const int32_t maxA = std::max(a.value.axis.axisMin, a.value.axis.axisMax); - const int32_t minB = std::min(b.value.axis.axisMin, b.value.axis.axisMax); - const int32_t maxB = std::max(b.value.axis.axisMin, b.value.axis.axisMax); - return minA <= minB && maxA >= maxB; - } - - return std::memcmp(&a, &b, sizeof(a)) == 0; -} - -void MappingSession::ConfigureBinding(const ExtendedBind& binding) { - const int32_t currentElement = CurrentBinding(); - if (currentElement < 0) { - return; - } - - for (int32_t i = 0; i < BINDING_COUNT; i++) { - if (BindingContainsBinding(mBindings[i], binding)) { - return; - } - } - - ExtendedBind& current = mBindings[currentElement]; - if (current.bindType != SDL_CONTROLLER_BINDTYPE_NONE) { - const bool nativeDPad = - currentElement == SDL_CONTROLLER_BUTTON_DPAD_UP || currentElement == SDL_CONTROLLER_BUTTON_DPAD_DOWN || - currentElement == SDL_CONTROLLER_BUTTON_DPAD_LEFT || currentElement == SDL_CONTROLLER_BUTTON_DPAD_RIGHT; - if (nativeDPad && current.bindType == SDL_CONTROLLER_BINDTYPE_HAT) { - return; - } - - const bool nativeAxis = currentElement >= SDL_CONTROLLER_BUTTON_MAX; - const bool currentIsAxis = current.bindType == SDL_CONTROLLER_BINDTYPE_AXIS; - if (nativeAxis == currentIsAxis && - (binding.bindType != SDL_CONTROLLER_BINDTYPE_AXIS || binding.value.axis.axis != current.value.axis.axis)) { - return; - } - } - - current = binding; - mPendingAdvanceTime = binding.committed ? SDL_GetTicks() : 0; -} - -void MappingSession::ProcessButtonDown(int32_t button) { - if (!mActive) { - return; - } - ExtendedBind binding = {}; - binding.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON; - binding.value.button = button; - binding.committed = true; - ConfigureBinding(binding); -} - -void MappingSession::ProcessHatMotion(int32_t hat, int32_t value) { - if (!mActive || value == SDL_HAT_CENTERED) { - return; - } - ExtendedBind binding = {}; - binding.bindType = SDL_CONTROLLER_BINDTYPE_HAT; - binding.value.hat.hat = hat; - binding.value.hat.hatMask = value; - binding.committed = true; - ConfigureBinding(binding); -} - -static int32_t StandardizeAxisValue(int32_t value) { - if (value > SDL_JOYSTICK_AXIS_MAX / 2) { - return SDL_JOYSTICK_AXIS_MAX; - } - if (value < SDL_JOYSTICK_AXIS_MIN / 2) { - return SDL_JOYSTICK_AXIS_MIN; - } - return 0; -} - -void MappingSession::ProcessAxisMotion(int32_t axis, int32_t value, SDL_Joystick* joystick) { - if (!mActive || axis < 0 || axis >= (int32_t)mAxisState.size()) { - return; - } - - constexpr int32_t MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80; - AxisState& state = mAxisState[axis]; - - if (!state.moving) { - Sint16 initialValue = 0; - state.moving = SDL_JoystickGetAxisInitialState(joystick, axis, &initialValue) == SDL_TRUE; - state.lastValue = value; - state.startingValue = initialValue; - state.farthestValue = initialValue; - } else if (std::abs(value - state.lastValue) <= MAX_ALLOWED_JITTER) { - return; - } else { - state.lastValue = value; - } - - const int32_t currentDistance = std::abs(value - state.startingValue); - int32_t farthestDistance = std::abs(state.farthestValue - state.startingValue); - if (currentDistance > farthestDistance) { - state.farthestValue = value; - farthestDistance = std::abs(state.farthestValue - state.startingValue); - } - - if (farthestDistance < AXIS_COMMIT_DISTANCE) { - return; - } - - ExtendedBind binding = {}; - binding.bindType = SDL_CONTROLLER_BINDTYPE_AXIS; - binding.value.axis.axis = axis; - binding.value.axis.axisMin = StandardizeAxisValue(state.startingValue); - binding.value.axis.axisMax = StandardizeAxisValue(state.farthestValue); - binding.committed = currentDistance <= AXIS_RETURN_DISTANCE; - ConfigureBinding(binding); -} - -void MappingSession::CheckPendingAdvance() { - if (!mActive || mPendingAdvanceTime == 0) { - return; - } - if (SDL_GetTicks() - mPendingAdvanceTime >= PENDING_ADVANCE_DELAY_MS) { - Advance(); - } -} - -// --------------------------------------------------------------------------------------------------- -// usergamepadmappings.txt -// --------------------------------------------------------------------------------------------------- - -std::string GetUserMappingsPath() { - return Ship::Context::GetPathRelativeToAppDirectory(kUserMappingsFileName); -} - -static std::string StripCrcFromGuid(const std::string& guid) { - if (guid.length() < 32) { - return guid; - } - return guid.substr(0, 4) + "0000" + guid.substr(8); -} - -static std::string MappingKey(const std::string& mapping) { - const size_t comma = mapping.find(','); - if (comma == std::string::npos || comma == 0) { - return ""; - } - std::string key = StripCrcFromGuid(mapping.substr(0, comma)); - - const size_t crcPos = mapping.find(",crc:"); - if (crcPos != std::string::npos) { - const size_t valueStart = crcPos + 1; - size_t valueEnd = mapping.find(',', valueStart); - if (valueEnd == std::string::npos) { - valueEnd = mapping.length(); - } - key += "," + mapping.substr(valueStart, valueEnd - valueStart); - } - return key; -} - -static bool IsMappingLine(const std::string& line) { - return !line.empty() && line.front() != '#'; -} - -static std::vector ReadUserMappingLines() { - std::vector lines; - std::ifstream file(GetUserMappingsPath()); - if (!file.is_open()) { - return lines; - } - - std::string line; - while (std::getline(file, line)) { - if (!line.empty() && line.back() == '\r') { - line.pop_back(); - } - lines.push_back(line); - } - return lines; -} - -static bool WriteUserMappingLines(const std::vector& lines) { - const std::string path = GetUserMappingsPath(); - const std::string tempPath = path + ".tmp"; - - { - std::ofstream file(tempPath, std::ios::binary | std::ios::trunc); - if (!file.is_open()) { - SPDLOG_ERROR("Failed to open \"{}\" for writing", tempPath); - return false; - } - file << "# SoH user gamepad mappings, written by the built-in gamepad mapper.\n"; - file << "# Loaded on top of gamecontrollerdb.txt, so entries here win.\n"; - for (const auto& line : lines) { - file << line << "\n"; - } - if (!file.good()) { - SPDLOG_ERROR("Failed while writing \"{}\"", tempPath); - return false; - } - } - - std::error_code error; - std::filesystem::rename(tempPath, path, error); - if (error) { - SPDLOG_ERROR("Failed to move \"{}\" into place: {}", tempPath, error.message()); - std::filesystem::remove(tempPath, error); - return false; - } - return true; -} - -std::string FindUserMapping(const std::string& guid) { - const std::string base = StripCrcFromGuid(guid); - for (const auto& line : ReadUserMappingLines()) { - if (!IsMappingLine(line)) { - continue; - } - const size_t comma = line.find(','); - if (comma != std::string::npos && StripCrcFromGuid(line.substr(0, comma)) == base) { - return line; - } - } - return ""; -} - -std::string MappingName(const std::string& mapping) { - const size_t first = mapping.find(','); - if (first == std::string::npos) { - return ""; - } - const size_t second = mapping.find(',', first + 1); - return mapping.substr(first + 1, second == std::string::npos ? std::string::npos : second - first - 1); -} - -bool LoadUserMappings() { - const std::string path = GetUserMappingsPath(); - - std::error_code error; - if (!std::filesystem::exists(path, error)) { - return false; - } - - const int32_t added = SDL_GameControllerAddMappingsFromFile(path.c_str()); - if (added < 0) { - SPDLOG_ERROR("Failed to add user gamepad mappings from \"{}\": {}", path, SDL_GetError()); - return false; - } - - SPDLOG_INFO("Added {} user gamepad mapping(s) from \"{}\"", added, path); - Ship::Context::GetRawInstance() - ->GetControlDeck() - ->GetConnectedPhysicalDeviceManager() - ->RefreshConnectedSDLGamepads(); - return true; -} - -bool SaveUserMapping(const std::string& mapping) { - const std::string key = MappingKey(mapping); - if (key.empty()) { - SPDLOG_ERROR("Refusing to save a gamepad mapping with no GUID"); - return false; - } - - std::vector lines; - for (const auto& line : ReadUserMappingLines()) { - if (!IsMappingLine(line)) { - continue; - } - if (MappingKey(line) == key) { - continue; - } - lines.push_back(line); - } - lines.push_back(mapping); - - if (!WriteUserMappingLines(lines)) { - return false; - } - - if (SDL_GameControllerAddMapping(mapping.c_str()) < 0) { - SPDLOG_ERROR("SDL rejected the generated mapping \"{}\": {}", mapping, SDL_GetError()); - return false; - } - - Ship::Context::GetRawInstance() - ->GetControlDeck() - ->GetConnectedPhysicalDeviceManager() - ->RefreshConnectedSDLGamepads(); - return true; -} - -bool DeleteUserMapping(const std::string& guid) { - const std::string base = StripCrcFromGuid(guid); - - std::vector lines; - bool found = false; - for (const auto& line : ReadUserMappingLines()) { - if (!IsMappingLine(line)) { - continue; - } - const size_t comma = line.find(','); - if (comma != std::string::npos && StripCrcFromGuid(line.substr(0, comma)) == base) { - found = true; - continue; - } - lines.push_back(line); - } - - if (!found) { - return false; - } - if (!WriteUserMappingLines(lines)) { - return false; - } - - Ship::Context::GetRawInstance() - ->GetControlDeck() - ->GetConnectedPhysicalDeviceManager() - ->RefreshConnectedSDLGamepads(); - return true; -} - -// --------------------------------------------------------------------------------------------------- -// Diagram layout -// --------------------------------------------------------------------------------------------------- - -struct DiagramEntry { - int32_t binding; - ImVec2 hotspot; - bool labelOnRight; -}; - -static constexpr float MAX_IMAGE_SPAN = 0.52f; -static constexpr float MIN_IMAGE_WIDTH = 360.0f; -static constexpr float FALLBACK_ART_ASPECT = 1850.0f / 1302.0f; -static constexpr ImU32 NAME_COLOR = IM_COL32(138, 144, 156, 255); - -static const DiagramEntry kDiagram[] = { - { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERLEFT, ImVec2(0.081f, 0.110f), false }, - { SDL_CONTROLLER_BUTTON_LEFTSHOULDER, ImVec2(0.234f, 0.092f), false }, - { SDL_CONTROLLER_BUTTON_BACK, ImVec2(0.426f, 0.408f), false }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_NEGATIVE, ImVec2(0.241f, 0.315f), false }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_NEGATIVE, ImVec2(0.185f, 0.401f), false }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTX_POSITIVE, ImVec2(0.297f, 0.401f), false }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_LEFTY_POSITIVE, ImVec2(0.241f, 0.487f), false }, - { SDL_CONTROLLER_BUTTON_LEFTSTICK, ImVec2(0.241f, 0.401f), false }, - { SDL_CONTROLLER_BUTTON_DPAD_UP, ImVec2(0.368f, 0.540f), false }, - { SDL_CONTROLLER_BUTTON_DPAD_LEFT, ImVec2(0.310f, 0.614f), false }, - { SDL_CONTROLLER_BUTTON_DPAD_RIGHT, ImVec2(0.416f, 0.614f), false }, - { SDL_CONTROLLER_BUTTON_DPAD_DOWN, ImVec2(0.368f, 0.690f), false }, - - { SDL_CONTROLLER_BUTTON_MAX + AXIS_TRIGGERRIGHT, ImVec2(0.919f, 0.110f), true }, - { SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, ImVec2(0.766f, 0.092f), true }, - { SDL_CONTROLLER_BUTTON_START, ImVec2(0.570f, 0.408f), true }, - { SDL_CONTROLLER_BUTTON_Y, ImVec2(0.752f, 0.328f), true }, - { SDL_CONTROLLER_BUTTON_X, ImVec2(0.689f, 0.412f), true }, - { SDL_CONTROLLER_BUTTON_B, ImVec2(0.816f, 0.412f), true }, - { SDL_CONTROLLER_BUTTON_A, ImVec2(0.752f, 0.497f), true }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_NEGATIVE, ImVec2(0.628f, 0.518f), true }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_NEGATIVE, ImVec2(0.570f, 0.595f), true }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTX_POSITIVE, ImVec2(0.686f, 0.595f), true }, - { SDL_CONTROLLER_BUTTON_MAX + AXIS_RIGHTY_POSITIVE, ImVec2(0.628f, 0.682f), true }, - { SDL_CONTROLLER_BUTTON_RIGHTSTICK, ImVec2(0.628f, 0.595f), true }, -}; - -// --------------------------------------------------------------------------------------------------- -// MapperWindow -// --------------------------------------------------------------------------------------------------- - -#define MAPPER_WINDOW_GAME_INPUT_BLOCK_ID 95237930 - -static constexpr uint32_t DEVICE_SCAN_INTERVAL_MS = 500; -static constexpr uint32_t FILE_WATCH_INTERVAL_MS = 1000; - -MapperWindow::~MapperWindow() { - CloseJoystick(); -} - -void MapperWindow::InitElement() { - ClearBindings(mBindings); -} - -// Records the joystick's current digital state as the baseline for edge detection, so a button already -// held when a prompt appears has to be released and pressed again to count. -void MapperWindow::SnapshotDeviceState() { - mPreviousButtons.clear(); - mPreviousHats.clear(); - if (mJoystick == nullptr) { - return; - } - - SDL_JoystickUpdate(); - for (int32_t i = 0; i < SDL_JoystickNumButtons(mJoystick); i++) { - mPreviousButtons.push_back(SDL_JoystickGetButton(mJoystick, i)); - } - for (int32_t i = 0; i < SDL_JoystickNumHats(mJoystick); i++) { - mPreviousHats.push_back(SDL_JoystickGetHat(mJoystick, i)); - } -} - -void MapperWindow::PollDeviceForSession() { - if (mJoystick == nullptr) { - return; - } - - if (SDL_JoystickGetAttached(mJoystick) == SDL_FALSE) { - EndSession(false); - mStatusMessage = "Device disconnected during mapping."; - return; - } - - SDL_JoystickUpdate(); - - const int32_t buttonCount = SDL_JoystickNumButtons(mJoystick); - mPreviousButtons.resize((size_t)std::max(buttonCount, 0), 0); - for (int32_t i = 0; i < buttonCount; i++) { - const uint8_t state = SDL_JoystickGetButton(mJoystick, i); - if (state != 0 && mPreviousButtons[i] == 0) { - mSession.ProcessButtonDown(i); - } - mPreviousButtons[i] = state; - } - - const int32_t hatCount = SDL_JoystickNumHats(mJoystick); - mPreviousHats.resize((size_t)std::max(hatCount, 0), SDL_HAT_CENTERED); - for (int32_t i = 0; i < hatCount; i++) { - const uint8_t state = SDL_JoystickGetHat(mJoystick, i); - if (state != mPreviousHats[i] && state != SDL_HAT_CENTERED) { - mSession.ProcessHatMotion(i, state); - } - mPreviousHats[i] = state; - } - - for (int32_t i = 0; i < SDL_JoystickNumAxes(mJoystick); i++) { - mSession.ProcessAxisMotion(i, SDL_JoystickGetAxis(mJoystick, i), mJoystick); - } -} - -void MapperWindow::CloseJoystick() { - if (mJoystick != nullptr) { - SDL_JoystickClose(mJoystick); - mJoystick = nullptr; - } - mPreviousButtons.clear(); - mPreviousHats.clear(); -} - -void MapperWindow::RefreshDeviceList() { - const SDL_JoystickID previousInstanceId = - mSelectedDevice >= 0 && mSelectedDevice < (int32_t)mDevices.size() ? mDevices[mSelectedDevice].instanceId : -1; - - mDevices.clear(); - - const std::vector userLines = ReadUserMappingLines(); - - for (int32_t i = 0; i < SDL_NumJoysticks(); i++) { - char guidString[33] = ""; - SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guidString, sizeof(guidString)); - - DeviceInfo info = {}; - info.deviceIndex = i; - info.instanceId = SDL_JoystickGetDeviceInstanceID(i); - const char* name = SDL_JoystickNameForIndex(i); - info.name = name != nullptr ? name : guidString; - info.guid = guidString; - info.hasMapping = SDL_IsGameController(i) == SDL_TRUE; - info.hasUserMapping = false; - - const std::string base = StripCrcFromGuid(info.guid); - for (const auto& line : userLines) { - if (!IsMappingLine(line)) { - continue; - } - const size_t comma = line.find(','); - if (comma != std::string::npos && StripCrcFromGuid(line.substr(0, comma)) == base) { - info.hasUserMapping = true; - break; - } - } - - mDevices.push_back(info); - } - - for (int32_t i = 0; i < (int32_t)mDevices.size(); i++) { - if (mDevices[i].instanceId == previousInstanceId) { - mSelectedDevice = i; - return; - } - } - - SelectDevice(mDevices.empty() ? -1 : 0); -} - -void MapperWindow::SelectDevice(int32_t listIndex) { - if (mSession.IsActive()) { - EndSession(false); - } - - CloseJoystick(); - ClearBindings(mBindings); - mDirty = false; - mStatusMessage.clear(); - mSelectedDevice = listIndex; - - if (listIndex < 0 || listIndex >= (int32_t)mDevices.size()) { - return; - } - - mJoystick = SDL_JoystickOpen(mDevices[listIndex].deviceIndex); - if (mJoystick == nullptr) { - mStatusMessage = StringHelper::Sprintf("Could not open device: %s", SDL_GetError()); - return; - } - - LoadBindingsForDevice(); -} - -void MapperWindow::LoadBindingsForDevice() { - ClearBindings(mBindings); - mCustomName.clear(); - if (mJoystick == nullptr) { - return; - } - - char guidString[33] = ""; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(mJoystick), guidString, sizeof(guidString)); - - const std::string userMapping = FindUserMapping(guidString); - if (!userMapping.empty()) { - ParseMappingString(userMapping, mBindings); - mCustomName = MappingName(userMapping); - return; - } - - const char* joystickName = SDL_JoystickName(mJoystick); - mCustomName = joystickName != nullptr ? joystickName : ""; - - char* existing = SDL_GameControllerMappingForGUID(SDL_JoystickGetGUID(mJoystick)); - if (existing == nullptr) { - return; - } - ParseMappingString(existing, mBindings); - SDL_free(existing); -} - -void MapperWindow::StartSession(const std::vector& order) { - if (mJoystick == nullptr || order.empty()) { - return; - } - - mStatusMessage.clear(); - mSession.SetBindings(mBindings); - mSession.Start(mJoystick, order); - SnapshotDeviceState(); - - Ship::Context::GetRawInstance()->GetControlDeck()->BlockGameInput(MAPPER_WINDOW_GAME_INPUT_BLOCK_ID); - Ship::Context::GetRawInstance()->GetWindow()->GetGui()->BlockGamepadNavigation(); -} - -void MapperWindow::EndSession(bool applyResult) { - if (applyResult) { - mSession.CopyBindingsTo(mBindings); - mDirty = true; - } - mSession.Stop(); - mPreviousButtons.clear(); - mPreviousHats.clear(); - - mGameInputBlockTimer = 20; - Ship::Context::GetRawInstance()->GetWindow()->GetGui()->UnblockGamepadNavigation(); -} - -void MapperWindow::UpdateElement() { - const uint32_t now = SDL_GetTicks(); - - if (now - mLastUserFileCheckTicks >= FILE_WATCH_INTERVAL_MS || mLastUserFileCheckTicks == 0) { - mLastUserFileCheckTicks = now; - - std::error_code error; - const std::filesystem::path path = GetUserMappingsPath(); - if (std::filesystem::exists(path, error)) { - const auto writeTime = std::filesystem::last_write_time(path, error); - const uint64_t stamp = (uint64_t)writeTime.time_since_epoch().count(); - if (!error && stamp != mLastUserFileWriteTime) { - const bool firstLoad = mLastUserFileWriteTime == 0; - mLastUserFileWriteTime = stamp; - LoadUserMappings(); - if (!firstLoad && !mSession.IsActive() && !mDirty) { - LoadBindingsForDevice(); - } - } - } else { - mLastUserFileWriteTime = 0; - } - } - - if (mGameInputBlockTimer != INT32_MAX && !mSession.IsActive()) { - mGameInputBlockTimer--; - if (mGameInputBlockTimer <= 0) { - Ship::Context::GetRawInstance()->GetControlDeck()->UnblockGameInput(MAPPER_WINDOW_GAME_INPUT_BLOCK_ID); - mGameInputBlockTimer = INT32_MAX; - } - } - - if (!IsVisible()) { - if (mSession.IsActive()) { - EndSession(false); - } - if (mJoystick != nullptr) { - CloseJoystick(); - mSelectedDevice = -1; - mDevices.clear(); - } - return; - } - - if (!mSession.IsActive() && (mDevices.empty() || now - mLastDeviceScanTicks >= DEVICE_SCAN_INTERVAL_MS)) { - mLastDeviceScanTicks = now; - RefreshDeviceList(); - } - - if (mSession.IsActive()) { - Ship::Context::GetRawInstance()->GetControlDeck()->BlockGameInput(MAPPER_WINDOW_GAME_INPUT_BLOCK_ID); - Ship::Context::GetRawInstance()->GetWindow()->GetGui()->BlockGamepadNavigation(); - - PollDeviceForSession(); - mSession.CheckPendingAdvance(); - - if (mSession.IsComplete()) { - EndSession(true); - mStatusMessage = "Mapping captured. Check the diagram, then Save Mapping."; - } - } -} - -bool MapperWindow::IsBindingLive(int32_t binding) const { - if (mJoystick == nullptr || binding < 0 || binding >= BINDING_COUNT) { - return false; - } - - const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(binding) : mBindings[binding]; - - switch (bind.bindType) { - case SDL_CONTROLLER_BINDTYPE_BUTTON: - return SDL_JoystickGetButton(mJoystick, bind.value.button) != 0; - case SDL_CONTROLLER_BINDTYPE_AXIS: { - const int32_t value = SDL_JoystickGetAxis(mJoystick, bind.value.axis.axis); - if (IsFullRangeAxis(bind)) { - Sint16 rest = 0; - SDL_JoystickGetAxisInitialState(mJoystick, bind.value.axis.axis, &rest); - return std::abs(value - rest) > SDL_JOYSTICK_AXIS_MAX / 2; - } - // A half-axis counts as active once the reading is most of the way toward axisMax. - const int32_t threshold = bind.value.axis.axisMax / 2; - return bind.value.axis.axisMax < 0 ? value <= threshold : value >= threshold; - } - case SDL_CONTROLLER_BINDTYPE_HAT: - return (SDL_JoystickGetHat(mJoystick, bind.value.hat.hat) & bind.value.hat.hatMask) == - bind.value.hat.hatMask; - default: - return false; - } -} - -// --------------------------------------------------------------------------------------------------- -// Drawing -// --------------------------------------------------------------------------------------------------- - -void MapperWindow::DrawDeviceSelector() { - ImGui::AlignTextToFramePadding(); - ImGui::Text("Device"); - ImGui::SameLine(); - - std::string preview = "No joysticks detected"; - if (mSelectedDevice >= 0 && mSelectedDevice < (int32_t)mDevices.size()) { - preview = mDevices[mSelectedDevice].name; - } - - ImGui::BeginDisabled(mSession.IsActive() || mDevices.empty()); - PushStyleCombobox(THEME_COLOR); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.6f); - if (ImGui::BeginCombo("##mapperDevice", preview.c_str())) { - for (int32_t i = 0; i < (int32_t)mDevices.size(); i++) { - const DeviceInfo& device = mDevices[i]; - const char* status = device.hasUserMapping ? " [user mapping]" : (device.hasMapping ? "" : " [unmapped]"); - if (ImGui::Selectable(StringHelper::Sprintf("%s%s##dev%d", device.name.c_str(), status, i).c_str(), - i == mSelectedDevice)) { - SelectDevice(i); - } - } - ImGui::EndCombo(); - } - PopStyleCombobox(); - ImGui::EndDisabled(); - - if (mSelectedDevice < 0 || mSelectedDevice >= (int32_t)mDevices.size()) { - ImGui::TextDisabled("Connect a gamepad to get started."); - return; - } - - const DeviceInfo& device = mDevices[mSelectedDevice]; - ImGui::TextDisabled("GUID %s", device.guid.c_str()); - if (mJoystick != nullptr) { - ImGui::SameLine(); - ImGui::TextDisabled("| %d buttons, %d axes, %d hats", SDL_JoystickNumButtons(mJoystick), - SDL_JoystickNumAxes(mJoystick), SDL_JoystickNumHats(mJoystick)); - } - - if (!device.hasMapping) { - ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.2f, 1.0f), - "This device has no SDL mapping, so the game cannot see it yet. Map it below."); - } else if (device.hasUserMapping) { - ImGui::TextColored(ImVec4(0.4f, 0.85f, 0.4f, 1.0f), "Using a mapping from %s.", kUserMappingsFileName); - } -} - -void MapperWindow::DrawDiagram() { - auto gui = std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()); - const bool haveArt = gui != nullptr && gui->HasTextureByName(kDiagramTextureName); - - float artAspect = FALLBACK_ART_ASPECT; - if (haveArt) { - const ImVec2 artSize = gui->GetTextureSize(kDiagramTextureName); - if (artSize.x > 0.0f && artSize.y > 0.0f) { - artAspect = artSize.x / artSize.y; - } - } - - std::string values[IM_ARRAYSIZE(kDiagram)]; - int32_t rowsPerGutter[2] = { 0, 0 }; - float widestName = 0.0f; - float widestValue = 0.0f; - for (int32_t i = 0; i < (int32_t)IM_ARRAYSIZE(kDiagram); i++) { - const DiagramEntry& entry = kDiagram[i]; - const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(entry.binding) : mBindings[entry.binding]; - values[i] = bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE ? DescribeBind(bind) : "-"; - widestValue = std::max(widestValue, ImGui::CalcTextSize(values[i].c_str()).x); - widestName = std::max(widestName, ImGui::CalcTextSize(BindingName(entry.binding)).x); - rowsPerGutter[entry.labelOnRight ? 1 : 0]++; - } - const int32_t maxRows = std::max(rowsPerGutter[0], rowsPerGutter[1]); - - const float valueColumnWidth = std::max(widestValue, ImGui::GetFontSize() * 6.0f); - - const float valueGap = ImGui::CalcTextSize(" ").x; - - const float gutterWidth = widestName + valueColumnWidth + valueGap + ImGui::GetFontSize() * 3.0f; - const float width = std::max(ImGui::GetContentRegionAvail().x, gutterWidth * 2.0f + MIN_IMAGE_WIDTH); - const float imageWidth = std::min(width - gutterWidth * 2.0f, width * MAX_IMAGE_SPAN); - const float imageHeight = imageWidth / artAspect; - const float rowHeight = ImGui::GetTextLineHeightWithSpacing() * 1.35f; - const float height = std::max(imageHeight, rowHeight * maxRows); - - const ImVec2 origin = ImGui::GetCursorScreenPos(); - const ImVec2 canvas(width, height); - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - const ImVec2 imageMin(origin.x + (width - imageWidth) * 0.5f, origin.y + (height - imageHeight) * 0.5f); - const ImVec2 imageMax(imageMin.x + imageWidth, imageMin.y + imageHeight); - - const auto toArt = [&](const ImVec2& uv) { - return ImVec2(imageMin.x + uv.x * imageWidth, imageMin.y + uv.y * imageHeight); - }; - - if (haveArt) { - drawList->AddImage(gui->GetTextureByName(kDiagramTextureName), imageMin, imageMax); - } else { - drawList->AddRectFilled(imageMin, imageMax, IM_COL32(40, 44, 52, 255), 12.0f); - drawList->AddRect(imageMin, imageMax, IM_COL32(90, 96, 110, 255), 12.0f, 0, 2.0f); - const char* placeholder = "controller image"; - const ImVec2 textSize = ImGui::CalcTextSize(placeholder); - drawList->AddText( - ImVec2((imageMin.x + imageMax.x - textSize.x) * 0.5f, (imageMin.y + imageMax.y - textSize.y) * 0.5f), - IM_COL32(120, 126, 140, 255), placeholder); - } - - const int32_t currentBinding = mSession.IsActive() ? mSession.CurrentBinding() : -1; - const float pulse = 0.55f + 0.45f * std::sin((float)ImGui::GetTime() * 6.0f); - - int32_t rowUsed[2] = { 0, 0 }; - for (int32_t i = 0; i < (int32_t)IM_ARRAYSIZE(kDiagram); i++) { - const DiagramEntry& entry = kDiagram[i]; - const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(entry.binding) : mBindings[entry.binding]; - const bool bound = bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE; - const bool active = entry.binding == currentBinding; - const bool live = IsBindingLive(entry.binding); - - const bool onRight = entry.labelOnRight; - const float lineHeight = ImGui::GetTextLineHeight(); - const ImVec2 valueSize = ImGui::CalcTextSize(values[i].c_str()); - - const int32_t gutter = onRight ? 1 : 0; - const int32_t row = rowUsed[gutter]++; - const float rowCenterY = origin.y + (row + 0.5f) * (height / rowsPerGutter[gutter]); - - const float run = ImGui::GetFontSize(); - const float elbowX = - onRight ? imageMax.x + ImGui::GetFontSize() * 0.6f : imageMin.x - ImGui::GetFontSize() * 0.6f; - const float valueEdgeX = onRight ? elbowX + run + valueGap : elbowX - run - valueGap; - - const ImVec2 cellMin(onRight ? valueEdgeX : valueEdgeX - valueColumnWidth, - rowCenterY - lineHeight * 0.5f - 2.0f); - const ImVec2 cellMax(cellMin.x + valueColumnWidth, cellMin.y + lineHeight + 4.0f); - - ImGui::SetCursorScreenPos(cellMin); - ImGui::InvisibleButton(StringHelper::Sprintf("##mapperRow%d", i).c_str(), - ImVec2(cellMax.x - cellMin.x, cellMax.y - cellMin.y), - ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - const bool hovered = ImGui::IsItemHovered(); - if (hovered && !mSession.IsActive() && mJoystick != nullptr) { - Tooltip("Click to map this control. Right-click to clear it."); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - StartSession({ entry.binding }); - } else if (ImGui::IsItemClicked(ImGuiMouseButton_Right) && bound) { - mBindings[entry.binding] = NoBind(); - mDirty = true; - } - } - - ImU32 color; - if (active) { - color = IM_COL32(255, (int32_t)(200.0f * pulse), 60, 255); - } else if (live) { - color = IM_COL32(110, 220, 110, 255); - } else if (bound) { - color = IM_COL32(215, 220, 230, 255); - } else { - color = IM_COL32(130, 135, 145, 255); - } - - if (hovered) { - drawList->AddRectFilled(cellMin, cellMax, IM_COL32(255, 255, 255, 24), 3.0f); - } - - const ImVec2 hotspot = toArt(entry.hotspot); - const float lineStartX = onRight ? cellMin.x - valueGap : cellMax.x + valueGap; - const ImU32 lineColor = active ? color : (bound ? IM_COL32(150, 156, 168, 255) : IM_COL32(90, 94, 104, 255)); - drawList->AddLine(ImVec2(lineStartX, rowCenterY), ImVec2(elbowX, rowCenterY), lineColor, 1.5f); - drawList->AddLine(ImVec2(elbowX, rowCenterY), hotspot, lineColor, 1.5f); - drawList->AddCircleFilled(hotspot, active || live ? 5.0f : 3.5f, color); - - drawList->AddText(ImVec2(onRight ? cellMin.x : cellMax.x - valueSize.x, rowCenterY - valueSize.y * 0.5f), color, - values[i].c_str()); - - const char* name = BindingName(entry.binding); - const ImVec2 nameSize = ImGui::CalcTextSize(name); - drawList->AddText( - ImVec2(onRight ? origin.x + width - 4.0f - nameSize.x : origin.x + 4.0f, rowCenterY - nameSize.y * 0.5f), - NAME_COLOR, name); - } - - ImGui::SetCursorScreenPos(ImVec2(origin.x, origin.y + canvas.y)); - ImGui::Dummy(ImVec2(1.0f, 0.0f)); - - if (!mIncludeExtraButtons) { - return; - } - - ImGui::SeparatorText("Extra buttons"); - for (int32_t i = 0; i < (int32_t)IM_ARRAYSIZE(kExtraBindings); i++) { - const int32_t binding = kExtraBindings[i]; - const ExtendedBind& bind = mSession.IsActive() ? mSession.GetBinding(binding) : mBindings[binding]; - const bool bound = bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE; - const bool active = mSession.IsActive() && mSession.CurrentBinding() == binding; - - ImGui::BeginDisabled(mSession.IsActive() || mJoystick == nullptr); - PushStyleButton(active ? Colors::Orange : THEME_COLOR); - if (ImGui::Button(StringHelper::Sprintf("%s: %s##extra%d", BindingName(binding), - bound ? DescribeBind(bind).c_str() : "-", i) - .c_str())) { - StartSession({ binding }); - } - PopStyleButton(); - ImGui::EndDisabled(); - if (i % 3 != 2 && i != (int32_t)IM_ARRAYSIZE(kExtraBindings) - 1) { - ImGui::SameLine(); - } - } -} - -void MapperWindow::DrawSessionPrompt() { - if (!mSession.IsActive()) { - return; - } - - const int32_t binding = mSession.CurrentBinding(); - const ImGuiStyle& style = ImGui::GetStyle(); - - PushStyleButton(THEME_COLOR); - const float buttonHeight = ImGui::GetFrameHeight(); - PopStyleButton(); - - const float promptHeight = - style.WindowPadding.y * 2.0f + ImGui::GetTextLineHeightWithSpacing() * 2.0f + buttonHeight; - - ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.16f, 0.14f, 0.06f, 1.0f)); - ImGui::BeginChild("##mapperPrompt", ImVec2(0.0f, promptHeight), true, ImGuiWindowFlags_NoScrollbar); - - ImGui::Text("Press or move: %s", binding >= 0 ? BindingName(binding) : "?"); - if (mSession.StepCount() > 1) { - ImGui::SameLine(); - ImGui::TextDisabled("(%d / %d)", mSession.CurrentStep() + 1, mSession.StepCount()); - } - ImGui::TextDisabled("Sticks and triggers: push all the way, then let go. Space skips, Escape cancels."); - - PushStyleButton(THEME_COLOR); - const bool skip = ImGui::Button("Skip") || ImGui::IsKeyPressed(ImGuiKey_Space, false); - ImGui::SameLine(); - ImGui::BeginDisabled(mSession.CurrentStep() == 0); - const bool back = ImGui::Button("Back"); - ImGui::EndDisabled(); - ImGui::SameLine(); - const bool cancel = ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape, false); - PopStyleButton(); - - ImGui::EndChild(); - ImGui::PopStyleColor(); - - if (cancel) { - EndSession(false); - mStatusMessage = "Mapping cancelled; nothing was changed."; - } else if (back) { - mSession.GoBack(); - } else if (skip) { - mSession.Advance(); - if (mSession.IsComplete()) { - EndSession(true); - mStatusMessage = "Mapping captured. Check the diagram, then Save Mapping."; - } - } -} - -void MapperWindow::DrawActionButtons() { - const bool haveDevice = mJoystick != nullptr; - const bool busy = mSession.IsActive(); - - char nameBuffer[128] = ""; - SDL_strlcpy(nameBuffer, mCustomName.c_str(), sizeof(nameBuffer)); - ImGui::BeginDisabled(busy || !haveDevice); - PushStyleInput(THEME_COLOR); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.45f); - if (ImGui::InputText("Controller Name", nameBuffer, sizeof(nameBuffer))) { - mCustomName = nameBuffer; - mDirty = true; - } - PopStyleInput(); - ImGui::EndDisabled(); - Tooltip("Name saved into usergamepadmappings.txt for this device. Commas are replaced with spaces."); - - ImGui::BeginDisabled(busy || !haveDevice); - PushStyleButton(THEME_COLOR); - if (ImGui::Button("Map All")) { - std::vector order(std::begin(kCoreBindingOrder), std::end(kCoreBindingOrder)); - if (mIncludeExtraButtons) { - order.insert(order.end(), std::begin(kExtraBindings), std::end(kExtraBindings)); - } - StartSession(order); - } - PopStyleButton(); - ImGui::EndDisabled(); - Tooltip(haveDevice ? "Walks every control on the pad, asking for one input at a time." : "Select a device first."); - - ImGui::SameLine(); - ImGui::BeginDisabled(busy || !haveDevice || !mDirty); - PushStyleButton(THEME_COLOR); - if (ImGui::Button("Save Mapping")) { - char guidString[33] = ""; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(mJoystick), guidString, sizeof(guidString)); - - bool ok; - if (!HasAnyBinding(mBindings)) { - ok = DeleteUserMapping(guidString); - mStatusMessage = - ok ? StringHelper::Sprintf("Removed from %s. SDL keeps the device registered until you restart.", - kUserMappingsFileName) - : "Nothing to remove; this device has no saved mapping."; - ok = true; - } else { - const std::string mapping = GenerateMappingString(mJoystick, mBindings, mCustomName); - ok = !mapping.empty() && SaveUserMapping(mapping); - mStatusMessage = ok ? StringHelper::Sprintf("Saved to %s.", kUserMappingsFileName) - : "Failed to save the mapping; see the log for details."; - } - - if (ok) { - mDirty = false; - std::error_code error; - const auto writeTime = std::filesystem::last_write_time(GetUserMappingsPath(), error); - if (!error) { - mLastUserFileWriteTime = (uint64_t)writeTime.time_since_epoch().count(); - } - RefreshDeviceList(); - } - } - PopStyleButton(); - ImGui::EndDisabled(); - - ImGui::SameLine(); - ImGui::BeginDisabled(busy || !haveDevice); - PushStyleButton(THEME_COLOR); - if (ImGui::Button("Revert")) { - LoadBindingsForDevice(); - mDirty = false; - mStatusMessage = "Reverted to the mapping SDL is currently using."; - } - PopStyleButton(); - ImGui::EndDisabled(); - Tooltip("Discards unsaved changes and reloads the mapping SDL is using for this device."); - - ImGui::SameLine(); - ImGui::BeginDisabled(busy || !haveDevice); - PushStyleButton(THEME_COLOR); - if (ImGui::Button("Clear All Bindings")) { - ClearBindings(mBindings); - mDirty = true; - } - PopStyleButton(); - ImGui::EndDisabled(); - - const bool haveUserMapping = - mSelectedDevice >= 0 && mSelectedDevice < (int32_t)mDevices.size() && mDevices[mSelectedDevice].hasUserMapping; - - ImGui::BeginDisabled(busy || !haveUserMapping); - PushStyleButton(Colors::DarkRed); - if (ImGui::Button("Delete Saved Mapping")) { - if (DeleteUserMapping(mDevices[mSelectedDevice].guid)) { - mStatusMessage = StringHelper::Sprintf("Removed from %s. Restart to fall back to gamecontrollerdb.txt.", - kUserMappingsFileName); - RefreshDeviceList(); - } else { - mStatusMessage = "No saved mapping to remove."; - } - } - PopStyleButton(); - ImGui::EndDisabled(); - Tooltip("SDL keeps the mapping in memory until the game restarts, so the device stays usable this session."); - - ImGui::SameLine(); - ImGui::BeginDisabled(busy); - PushStyleButton(THEME_COLOR); - if (ImGui::Button("Reload From File")) { - if (LoadUserMappings()) { - LoadBindingsForDevice(); - mDirty = false; - RefreshDeviceList(); - mStatusMessage = StringHelper::Sprintf("Reloaded %s.", kUserMappingsFileName); - } else { - mStatusMessage = StringHelper::Sprintf("No %s to load.", kUserMappingsFileName); - } - } - PopStyleButton(); - ImGui::EndDisabled(); - - ImGui::SameLine(); - ImGui::BeginDisabled(busy); - Checkbox("Include extra buttons", &mIncludeExtraButtons, - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Adds Guide, Misc and paddle/touchpad buttons - which most pads do not have - to the " - "diagram and the Map All walk.")); - ImGui::EndDisabled(); -} - -void MapperWindow::DrawMappingStringPreview() { - if (mJoystick == nullptr || !ImGui::CollapsingHeader("Mapping string")) { - return; - } - - const std::string mapping = GenerateMappingString(mJoystick, mBindings, mCustomName); - ImGui::TextWrapped("%s", mapping.c_str()); - PushStyleButton(THEME_COLOR); - if (ImGui::Button("Copy to Clipboard")) { - ImGui::SetClipboardText(mapping.c_str()); - mStatusMessage = "Mapping string copied to the clipboard."; - } - PopStyleButton(); -} - -void MapperWindow::DrawElement() { - static bool sDiagramTextureRequested = false; - if (!sDiagramTextureRequested) { - sDiagramTextureRequested = true; - auto gui = std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()); - auto archives = Ship::Context::GetRawInstance()->GetResourceManager()->GetArchiveManager(); - if (gui != nullptr && archives != nullptr && archives->HasFile(kDiagramTexturePath)) { - gui->LoadTextureFromRawImage(kDiagramTextureName, kDiagramTexturePath); - } - } - - ImGui::PushFont(GameEngine::Instance->fontMonoLarger); - - DrawDeviceSelector(); - Separator(); - DrawDiagram(); - DrawSessionPrompt(); - Separator(); - DrawActionButtons(); - - if (mDirty) { - ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.2f, 1.0f), "Unsaved changes."); - } - if (!mStatusMessage.empty()) { - ImGui::TextWrapped("%s", mStatusMessage.c_str()); - } - - DrawMappingStringPreview(); - - ImGui::PopFont(); -} - -// --------------------------------------------------------------------------------------------------- -// Menu registration -// --------------------------------------------------------------------------------------------------- - -static void RegisterMapperWidgets() { - WidgetPath path = { "Settings", "Controls", SECTION_COLUMN_2 }; - LighthouseGui::mLighthouseMenu->AddWidget(path, "Gamepad Mapper", WIDGET_SEPARATOR_TEXT); - LighthouseGui::mLighthouseMenu->AddWidget(path, "Open Gamepad Mapper", WIDGET_WINDOW_BUTTON) - .CVar(CVAR_WINDOW("GamepadMapper")) - .RaceDisable(false) - .WindowName("Gamepad Mapper") - .HideInSearch(true) - .Options(WindowButtonOptions() - .Tooltip("Build an SDL mapping for a gamepad the game does not recognize, or fix one that is " - "mapped wrong. Saves to usergamepadmappings.txt.") - .EmbedWindow(false)); -} - -static RegisterMenuInitFunc menuInitFunc(RegisterMapperWidgets); - -} // namespace Mapper diff --git a/src/port/Controller/Mapper.h b/src/port/Controller/Mapper.h deleted file mode 100644 index 0d0d41bb3..000000000 --- a/src/port/Controller/Mapper.h +++ /dev/null @@ -1,182 +0,0 @@ -#pragma once - -// Built-in SDL gamepad mapper. -// -// Produces `gamecontrollerdb.txt`-style mapping strings for a raw SDL joystick and persists them to -// `usergamepadmappings.txt` in the app directory. That file is loaded at boot (and whenever it changes on -// disk) on top of the bundled `gamecontrollerdb.txt`, so a user-authored mapping always wins. -// -// The binding state machine (axis commit/return distances, binding override rules, mapping string layout) -// is adapted from https://github.com/General-Arcade/sdl2-gamepad-tool (MIT), which in turn follows SDL's -// own `controllermap` test program. - -#include -#include -#include - -#include -#include -#include - -namespace Mapper { -enum AxisBinding { - AXIS_LEFTX_NEGATIVE, - AXIS_LEFTX_POSITIVE, - AXIS_LEFTY_NEGATIVE, - AXIS_LEFTY_POSITIVE, - AXIS_RIGHTX_NEGATIVE, - AXIS_RIGHTX_POSITIVE, - AXIS_RIGHTY_NEGATIVE, - AXIS_RIGHTY_POSITIVE, - AXIS_TRIGGERLEFT, - AXIS_TRIGGERRIGHT, - AXIS_BINDING_MAX, -}; - -constexpr int32_t BINDING_COUNT = SDL_CONTROLLER_BUTTON_MAX + AXIS_BINDING_MAX; - -struct ExtendedBind { - SDL_GameControllerBindType bindType; - union { - int32_t button; - - struct { - int32_t axis; - int32_t axisMin; - int32_t axisMax; - } axis; - - struct { - int32_t hat; - int32_t hatMask; - } hat; - } value; - bool committed; -}; - -struct AxisState { - bool moving; - int32_t lastValue; - int32_t startingValue; - int32_t farthestValue; -}; - -class MappingSession { -public: - static constexpr int32_t AXIS_COMMIT_DISTANCE = 16000; - static constexpr int32_t AXIS_RETURN_DISTANCE = 10000; - static constexpr uint32_t PENDING_ADVANCE_DELAY_MS = 100; - - MappingSession(); - - void Start(SDL_Joystick* joystick, const std::vector& order); - void Stop(); - - bool IsActive() const; - bool IsComplete() const; - - int32_t CurrentStep() const; - int32_t StepCount() const; - int32_t CurrentBinding() const; - - void GoToStep(int32_t step); - void Advance(); - void GoBack(); - - void ProcessButtonDown(int32_t button); - void ProcessHatMotion(int32_t hat, int32_t value); - void ProcessAxisMotion(int32_t axis, int32_t value, SDL_Joystick* joystick); - - void CheckPendingAdvance(); - - const ExtendedBind& GetBinding(int32_t index) const; - void SetBindings(const ExtendedBind (&bindings)[BINDING_COUNT]); - void CopyBindingsTo(ExtendedBind (&out)[BINDING_COUNT]) const; - -private: - void ConfigureBinding(const ExtendedBind& binding); - bool BindingContainsBinding(const ExtendedBind& a, const ExtendedBind& b) const; - - ExtendedBind mBindings[BINDING_COUNT]; - std::vector mOrder; - std::vector mAxisState; - int32_t mCurrentStep; - uint32_t mPendingAdvanceTime; - bool mActive; - bool mComplete; -}; - -void ClearBindings(ExtendedBind (&bindings)[BINDING_COUNT]); -bool HasAnyBinding(const ExtendedBind (&bindings)[BINDING_COUNT]); -std::string GenerateMappingString(SDL_Joystick* joystick, const ExtendedBind (&bindings)[BINDING_COUNT], - const std::string& nameOverride = ""); -int32_t ParseMappingString(const std::string& mapping, ExtendedBind (&bindings)[BINDING_COUNT]); -std::string DescribeBind(const ExtendedBind& bind); -const char* BindingName(int32_t binding); -std::string GetUserMappingsPath(); -std::string FindUserMapping(const std::string& guid); -std::string MappingName(const std::string& mapping); -bool LoadUserMappings(); -bool SaveUserMapping(const std::string& mapping); -bool DeleteUserMapping(const std::string& guid); - -class MapperWindow final : public Ship::GuiWindow { -public: - using GuiWindow::GuiWindow; - ~MapperWindow(); - -protected: - void InitElement() override; - void UpdateElement() override; - void DrawElement() override; - -private: - struct DeviceInfo { - int32_t deviceIndex; - SDL_JoystickID instanceId; - std::string name; - std::string guid; - bool hasMapping; - bool hasUserMapping; - }; - - void RefreshDeviceList(); - void SelectDevice(int32_t listIndex); - void CloseJoystick(); - void LoadBindingsForDevice(); - - void StartSession(const std::vector& order); - void EndSession(bool applyResult); - - void PollDeviceForSession(); - void SnapshotDeviceState(); - - void DrawDeviceSelector(); - void DrawDiagram(); - void DrawSessionPrompt(); - void DrawActionButtons(); - void DrawMappingStringPreview(); - - bool IsBindingLive(int32_t binding) const; - - std::vector mDevices; - int32_t mSelectedDevice = -1; - SDL_Joystick* mJoystick = nullptr; - - ExtendedBind mBindings[BINDING_COUNT] = {}; - MappingSession mSession; - bool mDirty = false; - bool mIncludeExtraButtons = false; - std::string mStatusMessage; - std::string mCustomName; - - std::vector mPreviousButtons; - std::vector mPreviousHats; - - int32_t mGameInputBlockTimer = INT32_MAX; - uint32_t mLastDeviceScanTicks = 0; - uint64_t mLastUserFileWriteTime = 0; - uint32_t mLastUserFileCheckTicks = 0; -}; - -} // namespace Mapper diff --git a/src/port/Controller/ModernCamera.cpp b/src/port/Controller/ModernCamera.cpp index 4a097d403..e350082c5 100644 --- a/src/port/Controller/ModernCamera.cpp +++ b/src/port/Controller/ModernCamera.cpp @@ -1,21 +1,16 @@ // Modern control scheme camera - -#include +// +// The right stick orbits the camera in yaw around the player (no pitch). It runs +// on the shared orbit core; this file is just the modern-scheme policy. #include #include "port/UI/cvar_prefixes.h" #include "ControlSchemes.h" #include "ModernCamera.h" -#include "port/Enhancements/Camera/FreeLookCamera.h" +#include "port/Enhancements/Camera/OrbitCameraCore.h" extern "C" { -// Math helpers -void func_80256E24(float dst[3], float pitch, float yaw, float x, float y, float z); -void ml_vec3f_add(float dst[3], float a[3], float b[3]); -void ml_vec3f_clear(float dst[3]); -float mlNormalizeAngle(float deg); - extern unsigned char D_8037C061; // current zoom level extern int D_8037C07C; // level-3 distance x; 0 means level 3 is unavailable @@ -29,66 +24,33 @@ int balookat_getState(void); // nonzero while the look-around camera is activ int player_movementGroup(void); // enum bsgroup_e int ncDynamicCamera_getState(void); -void ncDynamicCamera_setState(int state); -void ncDynamicCamera_setRotation(float src[3]); -int func_8029147C(void); // current ba camera mode -void func_80291488(int mode); // set the ba camera mode -void func_802914CC(int state); // force a dynamic camera state (mode 1) int bainput_should_rotate_camera_left(void); int bainput_should_rotate_camera_right(void); int bainput_should_look_first_person_camera(void); void controller_getRightStick(int controller_index, float dst[2]); - -// Vanilla follow-camera machinery -extern float D_8037DB70; // dynamicCamB.c: orbit yaw, degrees -extern float D_8037D9C8[3]; // dynamicCamera.c: rotation spring velocity - -void func_802C0150(int mode); // select the focus target -void func_802C0370(void); // record the pre-move position (anti-flip guard) -void func_802C0394(float target[3]); // record the ideal target (anti-flip guard) -void func_802C03BC(void); // undo a collision resolve that crossed over -void func_802C0490(float dst[3]); // focus/orbit center -void func_802C04B0(void); // re-derive D_8037DB70 from the live camera - -float func_802BD51C(void); // target camera height -float func_802BD8D4(void); // target orbit distance (zoom level) -void func_802BE190(float target[3]); // position spring toward target -void func_802BE230(float gain, float damp); // position spring tuning -int func_802BE60C(void); // swept camera collision + slide -int func_802BC84C(int mode); // occluded-too-long recovery -void func_802BE6FC(float rotOut[3], float focus[3]); // look-at from the live position } -#include "enums.h" // BS_7_CROUCH +#include "enums.h" // BS_CROUCH #include "port/ShipUtils.h" namespace { bool ModernSchemeActive() { - return CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_MODERN && - !port_freeLook_isEnabled(); + return CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO) == CONTROL_SCHEME_MODERN; } -constexpr int kClimbCamState = 0x10; -constexpr int kSwivelCamMode = 8; -constexpr int kFollowCamMode = 2; constexpr float kYawDeadzone = 0.2f; constexpr float kYawEnter = 0.3f; constexpr float kYawSpeed = 160.0f; constexpr float kZoomOn = 0.49f; constexpr float kZoomOff = 0.21f; -constexpr float kPosSpringGain = 20.0f; -constexpr float kPosSpringDamp = 80.0f; -constexpr float kHeightRate = 3.0f; -constexpr float kAimHeightRate = 8.0f; +constexpr float kPosSmoothRate = 40.0f; -bool sActive = false; -bool sHeightValid = false; -bool sAimValid = false; -float sHeight = 0.0f; -float sAimY = 0.0f; +// Flat (pitch-locked) orbit on the shared core. +OrbitCamera sModern = { /*stateId*/ MODERN_ORBIT_CAM_STATE, /*allowPitch*/ 0, + /*minPitch*/ 0.0f, /*maxPitch*/ 0.0f, /*smoothRate*/ kPosSmoothRate }; float clampf(float v, float lo, float hi) { return v < lo ? lo : (v > hi ? hi : v); @@ -119,85 +81,38 @@ bool ManualCameraControl() { bainput_should_look_first_person_camera(); } -bool Climbing() { - return player_movementGroup() == BSGROUP_5_CLIMB; -} - -// Give the mode back -void ReleaseSwivelMode() { - if (func_8029147C() != kSwivelCamMode) { - return; - } - if (Climbing()) { - func_802914CC(kClimbCamState); - } else { - func_80291488(kFollowCamMode); - } -} - -// Take the camera over. Everything the vanilla follow camera would set up on init is -// set up here, except that the position spring velocity is deliberately left alone. -void EnterOrbit() { - func_802C0150(2); - func_802BE230(kPosSpringGain, kPosSpringDamp); - func_802C04B0(); - - // We drive the rotation directly, so nothing services the rotation spring while we - // own the camera. Park its velocity so it cannot kick the aim when camB resumes. - ml_vec3f_clear(D_8037D9C8); - - sHeightValid = false; - sAimValid = false; - sActive = true; - ncDynamicCamera_setState(MODERN_ORBIT_CAM_STATE); -} - -void ExitOrbit() { - sActive = false; - if (ncDynamicCamera_getState() == MODERN_ORBIT_CAM_STATE) { - ncDynamicCamera_setState(0xB); - } - ReleaseSwivelMode(); -} - } // namespace extern "C" int port_modernCamera_handleYaw(void) { - bool schemeOk = ModernSchemeActive() && bs_getState() != BS_7_CROUCH && !IsDemoMode(); + bool schemeOk = ModernSchemeActive() && bs_getState() != BS_CROUCH && !IsDemoMode(); if (!schemeOk) { - if (sActive) { - ExitOrbit(); + if (sModern.active) { + OrbitCamera_Exit(&sModern); } return 0; } int state = ncDynamicCamera_getState(); - if (sActive) { + if (sModern.active) { // A scripted/special camera took the state out from under us; drop the // orbit and let that camera run. if (state != MODERN_ORBIT_CAM_STATE) { - sActive = false; + sModern.active = 0; return 0; } if (ManualCameraControl()) { - ExitOrbit(); + OrbitCamera_Exit(&sModern); return 0; } - if (!Climbing()) { - ReleaseSwivelMode(); - } return 1; } float x; float y; ReadStickNorm(x, y); - if (std::fabs(x) > kYawEnter) { - EnterOrbit(); - if (state == kClimbCamState) { - func_80291488(kSwivelCamMode); - } + if (x > kYawEnter || x < -kYawEnter) { + OrbitCamera_Enter(&sModern); return 1; } return 0; @@ -208,77 +123,33 @@ extern "C" void port_modernCamera_update(void) { // Drive yaw from the stick. Freeze it during look-around so it doesn't drift // while the first-person view overrides the camera. - if (!balookat_getState()) { + float yawDelta = 0.0f; + if (!sModern.justEntered && !balookat_getState()) { float x; float y; ReadStickNorm(x, y); - D_8037DB70 = mlNormalizeAngle(D_8037DB70 + YawInput(x) * kYawSpeed * dt * port_cameraInvertXSign()); - } - - // From here down this is ncDynamicCamB_update with our own yaw and height filter. - float focus[3]; - float offset[3]; - float target[3]; - - func_802C0370(); - func_802C0490(focus); - func_80256E24(offset, 0.0f, D_8037DB70, 0.0f, 0.0f, func_802BD8D4()); - ml_vec3f_add(target, focus, offset); - - float wantHeight = func_802BD51C(); - if (!sHeightValid) { - sHeight = wantHeight; - sHeightValid = true; - } else { - sHeight += (wantHeight - sHeight) * clampf(kHeightRate * dt, 0.0f, 1.0f); - } - target[1] = sHeight; - - func_802C0394(target); - func_802BE190(target); - - if (func_802BE60C()) { - // Occluded too long: func_802BC84C relocates the camera outright. Otherwise - // discard a resolve that pushed the camera back the way it came. - if (!func_802BC84C(1)) { - func_802C03BC(); - } - func_802C04B0(); // the camera slid along geometry; carry the orbit yaw with it - } - - // Aim straight at the focus from wherever the spring left the camera. The position - // is already smooth, so the look-at inherits that smoothness exactly and the player - // stays centered. - func_802C0490(focus); - if (!sAimValid) { - sAimY = focus[1]; - sAimValid = true; - } else { - sAimY += (focus[1] - sAimY) * clampf(kAimHeightRate * dt, 0.0f, 1.0f); + yawDelta = YawInput(x) * kYawSpeed * dt * port_cameraInvertXSign(); } - focus[1] = sAimY; - float rot[3]; - func_802BE6FC(rot, focus); - ncDynamicCamera_setRotation(rot); + OrbitCamera_Update(&sModern, yawDelta, 0.0f); } extern "C" int port_camera_suppressVanillaZoom(void) { - if (IsDemoMode() || port_freeLook_isEnabled()) { + if (IsDemoMode()) { return 0; } int scheme = CVarGetInteger(CVAR_SETTING("Controls.Scheme"), CONTROL_SCHEME_RETRO); if (scheme == CONTROL_SCHEME_MODERN) { return 1; } - if (scheme == CONTROL_SCHEME_POCKET && bs_getState() == BS_7_CROUCH) { + if (scheme == CONTROL_SCHEME_POCKET && bs_getState() == BS_CROUCH) { return 1; } return 0; } extern "C" void port_modernCamera_handleZoom(void) { - if (!ModernSchemeActive() || bs_getState() == BS_7_CROUCH || IsDemoMode()) { + if (!ModernSchemeActive() || bs_getState() == BS_CROUCH || IsDemoMode()) { return; } diff --git a/src/port/DevTools/DevSequences.cpp b/src/port/DevTools/DevSequences.cpp index fc9d07cd0..26758347c 100644 --- a/src/port/DevTools/DevSequences.cpp +++ b/src/port/DevTools/DevSequences.cpp @@ -14,7 +14,6 @@ extern "C" { void gcparade_beginFFParade(void); void gcparade_beginFinalParade(void); void func_8034BA7C(enum map_e map_id, int exit_id); // warp (B&K demo uses MAP_1, exit 93) -void transitionToMap(enum map_e map, int exit, int transition); void func_8034B968(void); // start the attract demo selected by D_80386110 (sets transition + D_80386114) extern int D_80386110; // attract-demo cycle index void func_8025A55C(int, int, int); // fade the active music track @@ -73,9 +72,6 @@ void RegisterDevSequences_Init() { func_8034BA7C(MAP_1_SM_SPIRAL_MOUNTAIN, 93); sPending = SEQ_MODE9_DIALOG; break; - case SEQ_ENDING_ALL_100: - transitionToMap(MAP_95_CS_END_ALL_100, 0, 1); - break; default: D_80386110 = seq - SEQ_ATTRACT_BASE; func_8034B968(); diff --git a/src/port/DevTools/DevSequences.h b/src/port/DevTools/DevSequences.h index 1ee871283..fb850057d 100644 --- a/src/port/DevTools/DevSequences.h +++ b/src/port/DevTools/DevSequences.h @@ -9,7 +9,6 @@ enum DevSequenceId { SEQ_PARADE_FINAL, SEQ_MODE9_BK, SEQ_MODE9_DIALOG, - SEQ_ENDING_ALL_100, SEQ_ATTRACT_BASE, }; diff --git a/src/port/DevTools/FlagTracer.cpp b/src/port/DevTools/FlagTracer.cpp deleted file mode 100644 index 81dc27564..000000000 --- a/src/port/DevTools/FlagTracer.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// Flag Tracer -// -// Logs every game-flag write with its enum name, optionally with the call stack -// that set it. A flag index alone is a bare number shared by unrelated actors. - -#include -#include -#include - -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" -#include "port/UI/cvar_prefixes.h" - -#include "FlagNames.generated.h" - -#include -#include -#include - -#if defined(_WIN32) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#include -#pragma comment(lib, "dbghelp.lib") -#define LH_FLAGTRACE_STACKS_WIN 1 -#elif defined(__linux__) || defined(__APPLE__) -#include -#include -#include -#include -#define LH_FLAGTRACE_STACKS_POSIX 1 -#endif - -extern "C" { -#include "functions.h" -} - -#define CVAR_FLAG_TRACE CVAR_DEVELOPER_TOOLS("FlagTrace") -#define CVAR_FLAG_TRACE_STACKS CVAR_DEVELOPER_TOOLS("FlagTraceStacks") -#define CVAR_FLAG_TRACE_SPACE CVAR_DEVELOPER_TOOLS("FlagTraceSpace") - -namespace { - -constexpr int32_t kSpaceAll = 0; - -const char* SpaceName(int32_t flagSpace) { - switch (flagSpace) { - case ANCHOR_FLAGSPACE_FILE_PROGRESS: - return "File Progress"; - case ANCHOR_FLAGSPACE_VOLATILE: - return "Volatile"; - case ANCHOR_FLAGSPACE_LEVEL_SPECIFIC: - return "Level"; - case ANCHOR_FLAGSPACE_MAP_SPECIFIC: - return "Map"; - case ANCHOR_FLAGSPACE_RANDO_INF: - return "Rando"; - default: - return "Unknown"; - } -} - -const char* LookupIn(const FlagName* table, int count, int index) { - for (int i = 0; i < count; i++) { - if (table[i].index == index) { - return table[i].name; - } - } - return nullptr; -} - -template const char* LookupIn(const FlagName (&table)[N], int index) { - return LookupIn(table, N, index); -} - -// The enum name behind a flag index, or "" when the decomp hasn't named it. -std::string FlagLabel(int32_t flagSpace, int32_t index) { - const char* name = nullptr; - switch (flagSpace) { - case ANCHOR_FLAGSPACE_FILE_PROGRESS: - name = LookupIn(kFileProgressNames, index); - break; - case ANCHOR_FLAGSPACE_VOLATILE: - name = LookupIn(kVolatileNames, index); - break; - case ANCHOR_FLAGSPACE_LEVEL_SPECIFIC: - name = LookupIn(kLevelNames, index); - break; - case ANCHOR_FLAGSPACE_MAP_SPECIFIC: { - const int level = (int)map_getLevel(gsworld_getMap()); - std::string joined; - for (const auto& group : kMapFlagGroups) { - if (group.level != level) { - continue; - } - if (const char* candidate = LookupIn(group.names, group.count, index)) { - if (!joined.empty()) { - joined += " | "; - } - joined += candidate; - } - } - return joined; - } - default: - break; - } - return name != nullptr ? name : ""; -} - -// Symbolized stack of whatever led here. -std::string CaptureCallerStack(int maxFrames) { - auto isPlumbing = [](const char* name) { - static const char* kPlumbing[] = { "FlagTrace", "EventSystem", "CallEvent", "Flag_set", "Flags_set", - "Flag_setEx", "Flags_setEx", "Flag_setN", "Flags_setN", "Flag_getAndSet", - "Flags_getSet", "invoke", "std::", "lambda" }; - for (const char* p : kPlumbing) { - if (std::strstr(name, p) != nullptr) { - return true; - } - } - return false; - }; - -#if defined(LH_FLAGTRACE_STACKS_WIN) - static std::once_flag symOnce; - static std::mutex symMutex; - HANDLE proc = GetCurrentProcess(); - std::call_once(symOnce, [proc] { - SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); - SymInitialize(proc, nullptr, TRUE); - }); - - void* frames[48] = {}; - const USHORT captured = CaptureStackBackTrace(1, 48, frames, nullptr); - - // dbghelp is not thread safe and its handles are process-wide. - std::lock_guard lock(symMutex); - - alignas(SYMBOL_INFO) char symBuf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME] = {}; - auto* sym = reinterpret_cast(symBuf); - sym->SizeOfStruct = sizeof(SYMBOL_INFO); - sym->MaxNameLen = MAX_SYM_NAME; - - std::string out; - int shown = 0; - for (USHORT i = 0; i < captured && shown < maxFrames; i++) { - DWORD64 disp = 0; - if (!SymFromAddr(proc, (DWORD64)frames[i], &disp, sym)) { - continue; - } - if (out.empty() && isPlumbing(sym->Name)) { - continue; - } - IMAGEHLP_LINE64 line = {}; - line.SizeOfStruct = sizeof(line); - DWORD lineDisp = 0; - if (SymGetLineFromAddr64(proc, (DWORD64)frames[i], &lineDisp, &line)) { - const char* file = std::strrchr(line.FileName, '\\'); - file = file ? file + 1 : line.FileName; - out += fmt::format("\n {} ({}:{})", sym->Name, file, line.LineNumber); - } else { - out += fmt::format("\n {}", sym->Name); - } - shown++; - } - return out; - -#elif defined(LH_FLAGTRACE_STACKS_POSIX) - void* frames[48] = {}; - const int captured = backtrace(frames, 48); - - std::string out; - int shown = 0; - for (int i = 1; i < captured && shown < maxFrames; i++) { - Dl_info info = {}; - if (dladdr(frames[i], &info) == 0 || info.dli_sname == nullptr) { - out += fmt::format("\n {}", frames[i]); - shown++; - continue; - } - - int status = 0; - char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); - const char* name = (status == 0 && demangled != nullptr) ? demangled : info.dli_sname; - const bool skip = out.empty() && isPlumbing(name); - if (!skip) { - out += fmt::format("\n {}", name); - shown++; - } - std::free(demangled); - } - return out; - -#else - (void)maxFrames; - (void)isPlumbing; - return "\n (call stacks are unavailable on this platform)"; -#endif -} - -} // namespace - -void RegisterFlagTracer_Init() { - const bool enabled = CVarGetInteger(CVAR_FLAG_TRACE, 0) != 0; - - COND_HOOK(OnGameFlagSet, EVENT_PRIORITY_NORMAL, enabled, [](IEvent* event) { - auto* ev = reinterpret_cast(event); - - const int32_t spaceFilter = CVarGetInteger(CVAR_FLAG_TRACE_SPACE, kSpaceAll); - if (spaceFilter != kSpaceAll && ev->flagSpace != (spaceFilter - 1)) { - return; - } - - std::string where; - if (ev->length > 1) { - where = fmt::format("0x{:X}-0x{:X}", ev->index, ev->index + ev->length - 1); - } else { - const std::string label = FlagLabel(ev->flagSpace, ev->index); - where = label.empty() ? fmt::format("0x{:X}", ev->index) : fmt::format("0x{:X} {}", ev->index, label); - } - - std::string stack; - if (CVarGetInteger(CVAR_FLAG_TRACE_STACKS, 0)) { - stack = fmt::format("\n set by:{}", CaptureCallerStack(6)); - } - - SPDLOG_INFO("[Flag] {:<13} {} -> {}{}", SpaceName(ev->flagSpace), where, ev->value ? "ON" : "off", stack); - }); - - COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, enabled, [](IEvent* event) { - auto* ev = reinterpret_cast(event); - SPDLOG_INFO("[Flag] ===== map 0x{:X} -> 0x{:X} (level 0x{:X}, exit {}) =====", (int)ev->prevMap, - (int)ev->nextMap, (int)map_getLevel((enum map_e)ev->nextMap), ev->exit); - }); -} - -static RegisterShipInitFunc initFlagTracer(RegisterFlagTracer_Init, { CVAR_FLAG_TRACE }); diff --git a/src/port/DevTools/OcclusionDebug.cpp b/src/port/DevTools/OcclusionDebug.cpp index a21a8f8ff..0c3b72519 100644 --- a/src/port/DevTools/OcclusionDebug.cpp +++ b/src/port/DevTools/OcclusionDebug.cpp @@ -16,7 +16,9 @@ #include "port/ShipInit.hpp" #include "port/Enhancements/Events/Hooks/Events.h" +extern "C" { #include "functions.h" // gsworld_getMap, mapModel_getModelBin +} // mapModel_getModelBin returns BKModelBin*; the debugger only compares it as an opaque // pointer, so reinterpret to const void* at the call sites. @@ -41,7 +43,8 @@ const char* CmdTypeName(int type) { } } -// Each command is keyed by (model part, byte offset within the model's geo command list). +// Each command is keyed by (model part, byte offset within the model bin). The offset is +// fixed per asset, so it never shifts when force-drawing reveals more geometry. struct Key { int part; int offset; @@ -154,7 +157,7 @@ void OcclusionDebugWindow::DrawElement() { } ImGui::TextWrapped( "Flip 'Force draw all' on for a moment to walk every cull command and populate the list (the " - "screen will look broken - that is expected), then turn it off and tick 'Force Draw' on " + "screen will look broken — that is expected), then turn it off and tick 'Force Draw' on " "individual rows to find the chunk(s) that reveal the target scenery. Offsets are stable, so the " "list never shifts. Dump the chosen set to the log when done."); diff --git a/src/port/DevTools/ThreadWatchdog.cpp b/src/port/DevTools/ThreadWatchdog.cpp deleted file mode 100644 index 6a0bf17be..000000000 --- a/src/port/DevTools/ThreadWatchdog.cpp +++ /dev/null @@ -1,580 +0,0 @@ -#include "ThreadWatchdog.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "port/OS/OS.h" - -#if defined(_WIN32) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#include -#pragma comment(lib, "dbghelp.lib") -#define LH_WATCHDOG_STACKS 1 -#endif - -extern "C" { -#include "libultraship/libultra/types.h" -#include "libultraship/libultra/message.h" -u32 osDpGetStatus(void); -void* osViGetCurrentFramebuffer(void); -void* osViGetNextFramebuffer(void); -OSMesgQueue* thread5_getTaskQueue(void); -OSMesgQueue* thread5_getSyncQueue(void); -OSMesgQueue* pfsManager_getFrameMesgQ(void); -OSMesgQueue* pfsManager_getFrameReplyQ(void); -OSMesgQueue* pfsManager_getSiLockQueue(void); -int pfsManager_isBusy(void); -OSMesgQueue* audioManager_getFrameMesgQueue(void); -OSMesgQueue* audioManager_getReplyMesgQueue(void); -OSMesgQueue* baMotor_getRetraceQueue(void); -OSMesgQueue* viMgr_getRetraceQueue(void); -OSMesgQueue* viMgr_getFrameTokenQueue(void); -OSMesgQueue* viMgr_getTickRetraceQueue(void); -int port_audioHeld(void); -int port_renderServicePending(void); -// Repro context -int gsworld_getMap(void); -int gsworld_getExit(void); -int getGameMode(void); -extern char gBuildVersion[]; -extern char gGitBranch[]; -extern char gGitCommitHash[]; -} - -namespace { - -using Clock = std::chrono::steady_clock; - -constexpr const char* kThreadNames[WATCHDOG_NUM_THREADS] = { - "vi-ticker", "main-loop", "game-tick", "thread5", "vimgr", "pfsmanager", "audio-mgr", "rumble", -}; - -// Blocking points in each loop that are not message-queue waits. A stall with -// no queue park is in one of these; naming them gives the reader somewhere to -// look when no symbols were available to resolve a stack. -constexpr const char* kThreadNonQueueWaits[WATCHDOG_NUM_THREADS] = { - "sleep_until; OS_SendEventMesg -> sMesgMutex", - "HandleEvents (SDL/window), ProcessGfxCommands (renderer present/DXGI wait), DrainRenderService callback, " - "OS_SiService -> ControlDeck", - "port_runOnRenderThread sSvcCv handoff; port_lockAudio (gAudioLock); ProcessGfxCommands std::async waits; " - "map-load I/O", - "sMesgMutex; a handler blocking in osSendMesg on a full queue", - "sMesgMutex", - "func_8024F450 -> D_802816E8 wait; port_shapeControllerInput; CALL_EVENT(OnControllerUpdate)", - "port_lockAudio (gAudioLock) in audioManager_handleFrameMsg", - "func_8024F450 -> D_802816E8 wait via __baMotor_startRumble/stopRumble/func_80250930; __osMotorAccess -> " - "ControlDeck rumble", -}; - -// Entry point each heartbeat belongs to. -constexpr const char* kThreadLoops[WATCHDOG_NUM_THREADS] = { - "osCreateViManager ticker (OS_VI.cpp)", - "SDL_main service loop (Game.cpp)", - "push_frame -> mainLoop (Game.cpp)", - "thread5_entry (graphics_thread.c)", - "viMgr_entry (vimgr.c)", - "pfsManager_entry (pfsmanager.c)", - "audioManagerThread_entry (audio_manager.c)", - "rumbleThread_entry (bamotor.c)", -}; - -// The audio thread legitimately idles through demo audio holds, and the -// pfsmanager thread races the game tick for the same polling queue, so both -// get a longer leash than the frame-paced threads. -constexpr auto kStallAfter = std::chrono::seconds(5); -constexpr auto kRelaxedStallAfter = std::chrono::seconds(10); -constexpr auto kSampleEvery = std::chrono::milliseconds(500); -constexpr auto kRedumpEvery = std::chrono::seconds(10); - -struct Heartbeat { - std::atomic count{ 0 }; - std::atomic tid{ 0 }; // SDL thread id, recorded on first beat - // Real (non-pseudo) thread handle, so the watcher can walk this thread's - // stack when it stalls. Recorded on first beat alongside the tid. - std::atomic handle{ nullptr }; - // Watcher-thread state - uint64_t lastCount = 0; - Clock::time_point lastBeat{}; - bool started = false; -}; - -Heartbeat sBeats[WATCHDOG_NUM_THREADS]; -std::atomic sStalledFlags[WATCHDOG_NUM_THREADS] = {}; -std::thread sWatcher; -std::atomic sWatcherRun{ false }; - -// Non-zero while a serviced thread is blocked on purpose. -std::atomic sExpectedStallDepth{ 0 }; -std::atomic sExpectedStallReason{ nullptr }; - -std::string DescribeUnkFlag1(int32_t f) { - switch (f) { - case 0x04: - return "AUDIO_TASK"; - case 0x10: - return "NO_TASK"; - case 0x20: - return "TASK_YIELDED"; - default: - break; - } - if (f & 0x08) { - return fmt::format("GFX_TASK|{:#x}", f & ~0x08); - } - return fmt::format("{:#x}?", f); -} - -std::string HumanDuration(std::chrono::milliseconds ms) { - if (ms.count() < 1000) { - return fmt::format("{}ms", ms.count()); - } - return fmt::format("{:.1f}s", ms.count() / 1000.0); -} - -// A queue's name and its producers, so a blocked wait names the code to audit. -struct QueueInfo { - bool known; - const char* name; - const char* fedBy; -}; - -QueueInfo DescribeQueue(OSMesgQueue* mq) { - if (mq == thread5_getTaskQueue()) { - return { true, "sThread5MesgQueue (graphics_thread.c)", - "thread5_sendTaskToQueue, osSetTimer cbs, viMgr_entry retrace, OS_SendEventMesg(SP/DP) from " - "ServiceRcp" }; - } - if (mq == thread5_getSyncQueue()) { - return { true, "sThread5SyncMesgQueue (graphics_thread.c)", - "thread5_handleSyncEvent/handleDPEvent/handleSPEvent/handleVIRetraceEvent; all need " - "sUnkFlag1==NO_TASK + gfx ring drained" }; - } - if (mq == viMgr_getRetraceQueue()) { - return { true, "sMesgQueue1 (vimgr.c)", "OS_VI ticker via OS_EVENT_VI" }; - } - if (mq == viMgr_getFrameTokenQueue()) { - return { true, "sMesgQueue2 (vimgr.c)", - "viMgr_func_8024BFAC <- thread5_handleDPEvent (needs sUnkFlag2 bit30), func_80253FE8" }; - } - if (mq == viMgr_getTickRetraceQueue()) { - return { true, "sMesgQueue3 (vimgr.c)", "viMgr_entry" }; - } - if (mq == pfsManager_getFrameMesgQ()) { - return { true, "pfsManagerContPollingMsqQ (pfsmanager.c)", - "OS_EVENT_SI <- OS_SiService (window thread) after osContStartReadData" }; - } - if (mq == pfsManager_getFrameReplyQ()) { - return { true, "pfsManagerContReplyMsgQ (pfsmanager.c)", "pfsManager_entry when !pfsManagerBusy" }; - } - if (mq == pfsManager_getSiLockQueue()) { - return { true, "D_802816E8 (pfsmanager.c)", "func_8024F4AC via func_8024F35C(0)" }; - } - if (mq == baMotor_getRetraceQueue()) { - return { true, "D_80282390 (bamotor.c)", "viMgr_entry retrace signal (NOBLOCK, so extras drop)" }; - } - if (mq == audioManager_getFrameMesgQueue()) { - return { true, "audioFrameMsgQ (audio_manager.c)", - "thread5_handleAudioTimerEvent (skipped while port_audioHeld)" }; - } - if (mq == audioManager_getReplyMesgQueue()) { - return { true, "audioReplyMsgQ (audio_manager.c)", - "thread5_handleSPEvent when sUnkFlag1==UNKFLAG1_AUDIO_TASK" }; - } - return { false, "unmapped queue", "unknown" }; -} - -// Repo source root, derived from this file's own build-time path so the check -// holds wherever the repo was cloned. The PDB records paths from the same -// compiler invocation, so our translation units share this prefix while the -// CRT/STL ones (which also contain "\src\") do not. -const std::string& ProjectSourceRoot() { - static const std::string root = [] { - const std::string self = __FILE__; - const size_t pos = self.rfind("src"); - // Only usable if __FILE__ came through absolute; otherwise mark nothing - // rather than risk the false positives a looser match produces. - if (pos == std::string::npos || self.find(':') == std::string::npos) { - return std::string(); - } - return self.substr(0, pos); - }(); - return root; -} - -// Stack of the stalled thread, symbolized against the shipped PDB. Nothing else -// in the report can be reconstructed after the fact: by the time a maintainer -// reads the log the process is gone, so capture it here rather than asking for -// a debugger they cannot attach. -// -// Addresses are collected while the target is suspended and symbolized only -// after it resumes, to keep the window in which it is held as narrow as -// possible. See the caller for the hang risk this still carries. -std::string CaptureStalledStack(int threadIdx) { -#if defined(LH_WATCHDOG_STACKS) - HANDLE thread = (HANDLE)sBeats[threadIdx].handle.load(std::memory_order_relaxed); - if (thread == nullptr) { - return {}; - } - - HANDLE proc = GetCurrentProcess(); - static std::once_flag symOnce; - std::call_once(symOnce, [proc] { - SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); - SymInitialize(proc, nullptr, TRUE); - }); - - if (SuspendThread(thread) == (DWORD)-1) { - return {}; - } - - CONTEXT ctx = {}; - ctx.ContextFlags = CONTEXT_FULL; - DWORD64 frames[32]; - int numFrames = 0; - if (GetThreadContext(thread, &ctx)) { - STACKFRAME64 sf = {}; -#if defined(_M_X64) - const DWORD machine = IMAGE_FILE_MACHINE_AMD64; - sf.AddrPC.Offset = ctx.Rip; - sf.AddrFrame.Offset = ctx.Rbp; - sf.AddrStack.Offset = ctx.Rsp; -#elif defined(_M_ARM64) - const DWORD machine = IMAGE_FILE_MACHINE_ARM64; - sf.AddrPC.Offset = ctx.Pc; - sf.AddrFrame.Offset = ctx.Fp; - sf.AddrStack.Offset = ctx.Sp; -#else - const DWORD machine = IMAGE_FILE_MACHINE_I386; - sf.AddrPC.Offset = ctx.Eip; - sf.AddrFrame.Offset = ctx.Ebp; - sf.AddrStack.Offset = ctx.Esp; -#endif - sf.AddrPC.Mode = sf.AddrFrame.Mode = sf.AddrStack.Mode = AddrModeFlat; - // Addresses only while suspended; symbol lookup happens after resume. - while (numFrames < 32 && - StackWalk64(machine, proc, thread, &sf, &ctx, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, - nullptr) && - sf.AddrPC.Offset != 0) { - frames[numFrames++] = sf.AddrPC.Offset; - } - } - ResumeThread(thread); - - if (numFrames == 0) { - return {}; - } - - const std::string& srcRoot = ProjectSourceRoot(); - std::string out = "Stack:\n"; - alignas(SYMBOL_INFO) char symBuf[sizeof(SYMBOL_INFO) + 256] = {}; - auto* sym = reinterpret_cast(symBuf); - sym->SizeOfStruct = sizeof(SYMBOL_INFO); - sym->MaxNameLen = 255; - for (int i = 0; i < numFrames; i++) { - DWORD64 symDisp = 0; - DWORD lineDisp = 0; - IMAGEHLP_LINE64 line = {}; - line.SizeOfStruct = sizeof(line); - if (SymFromAddr(proc, frames[i], &symDisp, sym)) { - if (SymGetLineFromAddr64(proc, frames[i], &lineDisp, &line)) { - // Only frames under this repo's source root are ours; CRT and - // STL paths contain "\src\" as well and must not match. - const bool ours = !srcRoot.empty() && _strnicmp(line.FileName, srcRoot.c_str(), srcRoot.size()) == 0; - out += fmt::format("{} #{:02} {}+0x{:x} ({}:{})\n", ours ? ">" : " ", i, sym->Name, symDisp, - line.FileName, line.LineNumber); - } else { - out += fmt::format(" #{:02} {}+0x{:x}\n", i, sym->Name, symDisp); - } - } else { - // No symbols (plain Release with no PDB alongside): emit - // module+offset, which stays resolvable later against a matching - // build. A raw address is meaningless once ASLR is factored in. - DWORD64 base = SymGetModuleBase64(proc, frames[i]); - char modPath[MAX_PATH] = {}; - const char* modName = "?"; - if (base != 0 && GetModuleFileNameA((HMODULE)(uintptr_t)base, modPath, MAX_PATH) != 0) { - const char* slash = strrchr(modPath, '\\'); - modName = slash != nullptr ? slash + 1 : modPath; - } - if (base != 0) { - out += fmt::format(" #{:02} {}+0x{:x}\n", i, modName, frames[i] - base); - } else { - out += fmt::format(" #{:02} 0x{:x}\n", i, frames[i]); - } - } - } - return out; -#else - (void)threadIdx; - return {}; -#endif -} - -std::string BuildDump(const bool* stalled, Clock::time_point now, const std::string& stack) { - OS_BlockedWait waits[16]; - const int numWaits = OS_MesgSnapshotBlockedWaits(waits, 16); - auto waitFor = [&](int threadIdx) -> const OS_BlockedWait* { - unsigned long tid = sBeats[threadIdx].tid.load(std::memory_order_relaxed); - for (int i = 0; i < numWaits; i++) { - if (waits[i].tid == tid) { - return &waits[i]; - } - } - return nullptr; - }; - auto ageOf = [&](int threadIdx) { - return std::chrono::duration_cast(now - sBeats[threadIdx].lastBeat); - }; - - std::string out; - - // Downstream threads stall behind the one that actually broke, so the - // longest-stalled thread is the best root-cause guess. - int firstStalled = -1; - int numStalled = 0; - if (stalled != nullptr) { - for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { - if (!stalled[i]) { - continue; - } - numStalled++; - if (firstStalled < 0 || sBeats[i].lastBeat < sBeats[firstStalled].lastBeat) { - firstStalled = i; - } - } - } - - if (firstStalled < 0) { - out += "===== Thread Watchdog: snapshot, no stall =====\n"; - } else { - out += fmt::format("===== Thread Watchdog: STALL DETECTED =====\n" - "{} has not reported for {} (tid {}){}\n" - "In loop: {}\n", - kThreadNames[firstStalled], HumanDuration(ageOf(firstStalled)), - sBeats[firstStalled].tid.load(std::memory_order_relaxed), - numStalled > 1 ? fmt::format(", {} stalled total, this one first", numStalled) : "", - kThreadLoops[firstStalled]); - if (const OS_BlockedWait* w = waitFor(firstStalled)) { - QueueInfo qi = DescribeQueue(w->mq); - out += fmt::format("Parked at: {} on {} {}/{}\n", w->isSend ? "osSendMesg (full)" : "osRecvMesg (empty)", - qi.name, w->mq->validCount, w->mq->msgCount); - out += fmt::format("Producers: {}\n", qi.fedBy); - } else if (!stack.empty()) { - out += "Parked at: no queue wait; see Stack below\n"; - } else { - out += fmt::format("Parked at: no queue wait, so loop/mutex/condvar. Candidates: {}\n", - kThreadNonQueueWaits[firstStalled]); - if (firstStalled == WATCHDOG_GAME_TICK && port_renderServicePending()) { - out += "Note: port_runOnRenderThread call is pending, so sSvcCv is the prime suspect\n"; - } - } - } - - for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { - const Heartbeat& hb = sBeats[i]; - uint64_t count = hb.count.load(std::memory_order_relaxed); - if (count == 0) { - out += fmt::format(" {:<11} never started\n", kThreadNames[i]); - continue; - } - std::string age = (hb.lastBeat == Clock::time_point{}) ? std::string("?") : HumanDuration(ageOf(i)); - std::string park; - if (const OS_BlockedWait* w = waitFor(i)) { - QueueInfo qi = DescribeQueue(w->mq); - park = - fmt::format(" {} {} {}/{}", w->isSend ? "send" : "recv", qi.name, w->mq->validCount, w->mq->msgCount); - } - out += fmt::format(" {:<11} {:<7} {:>6} tid {:<6} {} beats{}\n", kThreadNames[i], - (stalled != nullptr && stalled[i]) ? "STALLED" : "ok", age, - hb.tid.load(std::memory_order_relaxed), count, park); - } - - Thread5WatchdogState t5; - thread5_getWatchdogState(&t5); - ViMgrWatchdogState vi; - viMgr_getWatchdogState(&vi); - const u32 dpStatus = osDpGetStatus(); - void* curFb = osViGetCurrentFramebuffer(); - void* nextFb = osViGetNextFramebuffer(); - - out += fmt::format("Pipeline: sUnkFlag1={} sUnkFlag2={:#x}/saved={:#x} sSyncCounter={} task7={} " - "gfxRing={}->{} audioRing={}->{} taskQ={}/{} syncQ={}/{} FREEZE={} pendingSpTask={} " - "fb cur{}next{}\n", - DescribeUnkFlag1(t5.unkFlag1), t5.unkFlag2, t5.unkFlag2Saved, t5.syncCounter, t5.task7Handled, - t5.gfxActiveId, t5.gfxSelectedId, t5.audioActiveId, t5.audioSelectedId, t5.taskQueueCount, - t5.taskQueueCap, t5.syncQueueCount, t5.syncQueueCap, (dpStatus & 0x2) ? 1 : 0, - OS_SpPeekPendingTask() != nullptr ? "yes" : "no", - curFb == nextFb ? "==" : "!=", OS_ViBlackActive() ? " viBlack" : ""); - out += fmt::format("Frame pacing: D_802808D8={}{} frameTokenQ={} tickRetraceQ={} retraceQ={}\n", vi.retraceCount, - vi.retraceCount > 10 ? " (accumulating)" : "", vi.q2Count, vi.q3Count, vi.q1Count); - - OSMesgQueue* pfsPoll = pfsManager_getFrameMesgQ(); - OSMesgQueue* audioFrame = audioManager_getFrameMesgQueue(); - OSMesgQueue* audioReply = audioManager_getReplyMesgQueue(); - out += fmt::format("SI/audio: pfsBusy={} pollingQ={} audioFrameQ={} audioReplyQ={} audioHeld={} svcPending={}\n", - pfsManager_isBusy(), pfsPoll->validCount, audioFrame->validCount, audioReply->validCount, - port_audioHeld(), port_renderServicePending()); - out += fmt::format("Context: map={:#x} exit={:#x} gameMode={} build={} {}@{}", gsworld_getMap(), gsworld_getExit(), - getGameMode(), (char*)gBuildVersion, (char*)gGitBranch, (char*)gGitCommitHash); - - if (!stack.empty()) { - out += "\n" + stack; - } - return out; -} - -void Watcher() { - auto lastSample = Clock::now(); - auto lastReport = Clock::time_point{}; - bool wasStalled = false; - bool wasExpected = false; - - while (sWatcherRun.load(std::memory_order_relaxed)) { - std::this_thread::sleep_for(kSampleEvery); - auto now = Clock::now(); - - // A debugger pause (or system sleep) suspends every thread including - // this one; a stale "last beat" then isn't a stall. Rebaseline. - const bool suspended = (now - lastSample) > kSampleEvery * 4; - lastSample = now; - const bool expected = sExpectedStallDepth.load(std::memory_order_acquire) > 0; - const bool rebaseline = suspended || expected || wasExpected; - wasExpected = expected; - - bool stalled[WATCHDOG_NUM_THREADS] = {}; - bool anyStalled = false; - for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { - Heartbeat& hb = sBeats[i]; - uint64_t cur = hb.count.load(std::memory_order_relaxed); - if (!hb.started) { - if (cur == 0) { - continue; // thread not running yet; don't judge it - } - hb.started = true; - } - if (cur != hb.lastCount || rebaseline) { - hb.lastCount = cur; - hb.lastBeat = now; - continue; - } - const auto limit = - (i == WATCHDOG_AUDIO_MANAGER || i == WATCHDOG_PFSMANAGER) ? kRelaxedStallAfter : kStallAfter; - if (now - hb.lastBeat > limit) { - stalled[i] = true; - anyStalled = true; - } - } - for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { - sStalledFlags[i].store(stalled[i], std::memory_order_relaxed); - } - - if (!anyStalled) { - wasStalled = false; - continue; - } - // One dump when a stall appears, then a refresher while it persists. - if (wasStalled && (now - lastReport) < kRedumpEvery) { - continue; - } - const bool firstReportOfEpisode = !wasStalled; - wasStalled = true; - lastReport = now; - - int root = -1; - for (int i = 0; i < WATCHDOG_NUM_THREADS; i++) { - if (stalled[i] && (root < 0 || sBeats[i].lastBeat < sBeats[root].lastBeat)) { - root = i; - } - } - - // The stack is folded into the report below so the diagnosis is one - // block, but walking a thread means suspending it, which can hang if it - // holds a DbgHelp or loader lock and would take this watcher with it. - // Leave a breadcrumb first so a hang still names the stalled thread. - std::string stack; - if (firstReportOfEpisode && root >= 0) { - SPDLOG_ERROR("[Watchdog] {} stalled, collecting state", kThreadNames[root]); - stack = CaptureStalledStack(root); - } - SPDLOG_ERROR("{}", BuildDump(stalled, now, stack)); - } -} - -} // namespace - -extern "C" void ThreadWatchdog_Beat(WatchdogThread id) { - Heartbeat& hb = sBeats[id]; - hb.count.fetch_add(1, std::memory_order_relaxed); - if (hb.tid.load(std::memory_order_relaxed) == 0) { -#if defined(LH_WATCHDOG_STACKS) - // GetCurrentThread is a pseudo-handle only valid on this thread, so - // duplicate it into one the watcher can use. Leaked by design: it must - // outlive the thread's own loop for the whole session. - HANDLE dup = nullptr; - DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &dup, - THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, 0); - hb.handle.store(dup, std::memory_order_relaxed); -#endif - hb.tid.store((unsigned long)SDL_ThreadID(), std::memory_order_relaxed); - } -} - -extern "C" void ThreadWatchdog_Start(void) { - if (sWatcherRun.exchange(true)) { - return; - } - sWatcher = std::thread(Watcher); -} - -extern "C" void ThreadWatchdog_Stop(void) { - if (!sWatcherRun.exchange(false)) { - return; - } - if (sWatcher.joinable()) { - sWatcher.join(); - } -} - -extern "C" void ThreadWatchdog_DumpNow(void) { - SPDLOG_INFO("{}", BuildDump(nullptr, Clock::now(), std::string())); -} - -extern "C" int ThreadWatchdog_IsStalled(WatchdogThread id) { - return sStalledFlags[id].load(std::memory_order_relaxed) ? 1 : 0; -} - -extern "C" void ThreadWatchdog_BeginExpectedStall(const char* reason) { - if (sExpectedStallDepth.fetch_add(1, std::memory_order_acq_rel) == 0) { - sExpectedStallReason.store(reason, std::memory_order_relaxed); - SPDLOG_DEBUG("[Watchdog] stall reporting suppressed: {}", reason ? reason : "?"); - } -} - -extern "C" void ThreadWatchdog_EndExpectedStall(void) { - const int prev = sExpectedStallDepth.fetch_sub(1, std::memory_order_acq_rel); - if (prev <= 0) { - // Unbalanced release would leave the counter negative and suppress - // every future stall, which is worse than the false positive. - sExpectedStallDepth.store(0, std::memory_order_release); - SPDLOG_WARN("[Watchdog] ThreadWatchdog_EndExpectedStall without a matching Begin"); - return; - } - if (prev == 1) { - const char* reason = sExpectedStallReason.load(std::memory_order_relaxed); - SPDLOG_DEBUG("[Watchdog] stall reporting resumed: {}", reason ? reason : "?"); - sExpectedStallReason.store(nullptr, std::memory_order_relaxed); - } -} diff --git a/src/port/DevTools/ThreadWatchdog.h b/src/port/DevTools/ThreadWatchdog.h deleted file mode 100644 index 35a644985..000000000 --- a/src/port/DevTools/ThreadWatchdog.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef PORT_THREAD_WATCHDOG_H -#define PORT_THREAD_WATCHDOG_H - -#include - -// Heartbeat watchdog over the revived decomp threads. -// -// Every serviced loop beats once per iteration and a watcher thread samples the -// counters. When a thread that has already proven alive stops beating while the -// wall clock keeps moving, the watcher logs the pipeline state: thread5's flag -// words and task rings, every queue depth, who is parked where, and the stalled -// thread's stack. - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum WatchdogThread { - WATCHDOG_VI_TICKER = 0, // retrace source (OS_VI.cpp); everything below is paced by it - WATCHDOG_MAIN_LOOP, // window thread: event pump + RCP service (Game.cpp) - WATCHDOG_GAME_TICK, // push_frame loop (Game.cpp) - WATCHDOG_THREAD5, // decomp graphics thread (graphics_thread.c) - WATCHDOG_VIMGR, // decomp VI manager thread (vimgr.c) - WATCHDOG_PFSMANAGER, // controller thread (pfsmanager.c) - WATCHDOG_AUDIO_MANAGER, // audio thread (audio_manager.c); idles during demo audio holds - WATCHDOG_RUMBLE, // motor thread (bamotor.c); one beat per retrace signal - WATCHDOG_NUM_THREADS -} WatchdogThread; - -// Called once per loop iteration; one relaxed atomic increment. -void ThreadWatchdog_Beat(WatchdogThread id); - -// Started once the decomp threads exist, stopped before shutdown teardown. -void ThreadWatchdog_Start(void); -void ThreadWatchdog_Stop(void); - -// Log the pipeline state immediately, stalled or not. -void ThreadWatchdog_DumpNow(void); - -// Bracket a section that blocks a serviced thread on purpose. -void ThreadWatchdog_BeginExpectedStall(const char* reason); -void ThreadWatchdog_EndExpectedStall(void); - -// Whether the watcher currently considers this thread stalled. The gui only -// draws inside serviced frames, so the main loop uses this to keep drawing -// while the tick is down instead of freezing ImGui along with it. -int ThreadWatchdog_IsStalled(WatchdogThread id); - -// Diagnostic snapshots served by the decomp thread owners; plain structs so -// the C side fills them without knowing about the watchdog's internals. -typedef struct Thread5WatchdogState { - int32_t unkFlag1; // 0x04 audio task, 0x08 gfx task, 0x10 idle, 0x20 yielded - int32_t unkFlag2; - int32_t unkFlag2Saved; - int32_t syncCounter; - int32_t task7Handled; - int32_t gfxActiveId; - int32_t gfxSelectedId; - int32_t audioActiveId; - int32_t audioSelectedId; - int32_t taskQueueCount; - int32_t taskQueueCap; - int32_t syncQueueCount; - int32_t syncQueueCap; -} Thread5WatchdogState; -void thread5_getWatchdogState(Thread5WatchdogState* out); - -typedef struct ViMgrWatchdogState { - int32_t retraceCount; // D_802808D8: retraces seen since the tick last consumed them - int32_t q1Count; // retrace event queue (viMgr_entry parks here) - int32_t q2Count; // frame token queue (the tick parks here) - int32_t q3Count; // tick retrace queue -} ViMgrWatchdogState; -void viMgr_getWatchdogState(ViMgrWatchdogState* out); - -#ifdef __cplusplus -} - -namespace Lighthouse { -class ExpectedStall { -public: - explicit ExpectedStall(const char* reason) { - ThreadWatchdog_BeginExpectedStall(reason); - } - ~ExpectedStall() { - ThreadWatchdog_EndExpectedStall(); - } - ExpectedStall(const ExpectedStall&) = delete; - ExpectedStall& operator=(const ExpectedStall&) = delete; -}; -} // namespace Lighthouse -#endif - -#endif // PORT_THREAD_WATCHDOG_H diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp index d8aca8698..8d8bf5e22 100644 --- a/src/port/Engine.cpp +++ b/src/port/Engine.cpp @@ -1,9 +1,7 @@ #include "Engine.h" -#include #include #include #include -#include #if defined(__linux__) || defined(__APPLE__) #include #include @@ -33,10 +31,8 @@ #include "Audio/GameAudio.h" #include "build.h" #include "Extractor/GameExtractor.h" -#include "ship/window/gui/FileBrowserWindow.h" +#include "Interpolation/AdaptiveFps.h" #include "Interpolation/FrameInterpolation.h" -#include "Nametag/Nametag.h" -#include "OS/OS.h" #include "Network/Anchor/Anchor.h" #include "port/Enhancements/Events/PortEnhancements.h" #include "port/Patches/Patches.h" @@ -53,7 +49,6 @@ #include "src/port/Enhancements/Events/Hooks/Events.h" #include "UI/LighthouseGui.hpp" #include "UI/LighthouseModMenuWindow.h" -#include "LaunchArgs.h" #ifdef __SWITCH__ #include @@ -77,6 +72,14 @@ extern s32 D_80275610; bool prevAltAssets = false; // bool gEnableGammaBoost = true; +// Audio synthesis entry point (decomp n_synthesizer.c) +Acmd* n_alAudioFrame(Acmd* cmdList, s32* cmdLen, s16* outBuf, s32 outLen); +// DMA cache cleanup (decomp audio_manager.c) +void func_802403F0(void); +void func_80250650(void); +// Game mode helper +bool func_802E4A08(void); + // Soundfont ROM symbols — loaded from OTR in LoadSoundfonts() u8* soundfont1ctl_ROM_START = NULL; u8* soundfont1ctl_ROM_END = NULL; @@ -120,9 +123,10 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { return version; } -// Reads the port version recorded in the named o2r. A missing file yields INT16_MAX in every -// field; an o2r that opens without a portVersion record yields zeros. +// Checks the program version stored in the otr and compares the major value to soh +// For Windows/Mac/Linux if the version doesn't match, offer to OTRVersion DetectOTRVersion(std::string fileName) { + bool isOtrOld = false; std::string otrPath = Ship::Context::LocateFileAcrossAppDirs(fileName); // Doesn't exist so nothing to do here @@ -178,7 +182,6 @@ GameEngine::GameEngine() { lhFast3dWindow = std::make_shared(std::vector>({})); this->context->InitWindow(lhFast3dWindow); - this->context->InitAudio({ .SampleRate = 22000, .SampleLength = 736, .DesiredBuffered = 2208 }); LighthouseGui::SetupMenu(); @@ -209,7 +212,6 @@ typedef enum PromptSteps { PS_FILE_CHECK, PS_LOCAL, PS_FIRST, - PS_FIRST_WAIT, // waiting for the async file-pick result (resolves immediately on the native path) PS_WAIT, PS_NONE, } PromptSteps; @@ -226,7 +228,7 @@ bool IsSubpath(const std::filesystem::path& path, const std::filesystem::path& b return !rel.empty() && rel.native()[0] != '.'; } -bool PathTestCleanup() { +bool PathTestCleanup(FILE* tfile) { try { if (std::filesystem::exists("./text.txt")) std::filesystem::remove("./text.txt"); @@ -246,8 +248,7 @@ void CheckAndCreateModFolder() { if (std::filesystem::create_directories(modsPath)) { std::ofstream(filePath).close(); std::filesystem::create_directories(modsPath + "/~romhacks"); // BK romhacks go here - std::filesystem::create_directories(modsPath + "/~lang"); // Language packs go here - std::filesystem::create_directories(modsPath + "/~shared"); // Mods usable by everything go here + std::filesystem::create_directories(modsPath + "/shared"); // Mods usable by everything go here } } } catch (std::filesystem::filesystem_error const&) { @@ -326,7 +327,7 @@ static void LoadLooseModDirectories(const std::string& patches_path) { continue; } const std::string dirName = p.path().filename().generic_string(); - if (dirName == "~romhacks" || dirName == "~shared" || dirName == "~lang" || IsScopedModFolderName(dirName)) { + if (dirName == "~romhacks" || dirName == "shared" || dirName == "lang" || IsScopedModFolderName(dirName)) { continue; } SPDLOG_INFO("Found mod directory: {}", p.path().generic_string()); @@ -335,9 +336,9 @@ static void LoadLooseModDirectories(const std::string& patches_path) { } } -// Load every .o2r language pack from mods/~lang into the ArchiveManager. +// Load every .o2r language pack from mods/lang into the ArchiveManager. static void LoadLanguagePacks() { - const std::string lang_path = Ship::Context::GetPathRelativeToAppDirectory("mods/~lang"); + const std::string lang_path = Ship::Context::GetPathRelativeToAppDirectory("mods/lang"); if (lang_path.empty() || !std::filesystem::is_directory(lang_path)) { return; } @@ -363,9 +364,6 @@ void GameEngine::FinishInit() { std::filesystem::create_directories(patches_path); } - // Apply `-hack ` before the scan. - Lighthouse::ApplyLaunchHack(); - // Load enabled mod o2rs into the ArchiveManager. UpdateModFiles(true); LoadLooseModDirectories(patches_path); @@ -382,21 +380,17 @@ void GameEngine::FinishInit() { Ship::Context::GetRawInstance()->GetLogger()->set_pattern("[%H:%M:%S.%e] [%s:%#] [%l] %v"); SPDLOG_INFO("Starting Lighthouse version {} (Branch: {} | Commit: {})", (char*)gBuildVersion, (char*)gGitBranch, (char*)gGitCommitHash); - Lighthouse::FlushLaunchHackLog(); context->InitFileDropMgr(); context->InitCrashHandler(); context->InitEventSystem(); + this->context->InitAudio({ .SampleRate = 22000, .SampleLength = 736, .DesiredBuffered = 2208 }); + lhFast3dWindow->SetTargetFps(60); lhFast3dWindow->SetMaximumFrameLatency(1); lhFast3dWindow->SetRendererUCode(ucode_f3d); - // Opt-in to memoization - if (auto interpreter = lhFast3dWindow->GetInterpreterWeak().lock()) { - interpreter->SetResolvedResourceCacheEnabled(true); - } - #ifdef USE_NETWORKING SDLNet_Init(); #endif @@ -409,16 +403,13 @@ void GameEngine::FinishInit() { Lighthouse::RescanLanguages(); LighthouseGui::SetupGuiElements(); - // Undo the -hack override only now: LighthouseModMenuWindow::InitElement() - // re-runs UpdateModFiles(true) during SetupGuiElements and would otherwise - // re-read the restored CVars and reload the persisted hack over the override. - Lighthouse::RestoreModSelectionAfterLaunchHack(); // If UpdateModFiles(true) above quarantined conflicting romhack overlays, // surface that to the user now that the modal window is alive. MaybeShowModConflictPopup(); // Likewise if it refused romhack overlays due to a non-v1.0 base. MaybeShowRomhackBaseMismatchPopup(); Instance->AudioInit(); + AdaptiveFps_Configure(30); // BK ticks at 30 Hz // Instance->LoadDictionary(); // Instance->LoadPlayerAnims(); #if defined(__SWITCH__) || defined(__WIIU__) @@ -451,17 +442,10 @@ void GameEngine::RunExtract(int argc, char* argv[]) { std::filesystem::path ownPath; std::vector args; - for (int i = 1; i < argc; i++) { - std::string arg = argv[i]; - std::string inlineValue; - bool takesValue = false; - if (Lighthouse::IsLaunchHackFlag(arg, inlineValue, takesValue)) { - if (takesValue) { - i++; - } - continue; + if (argc > 1) { + for (int i = 1; i < argc; i++) { + args.push_back(argv[argc]); } - args.push_back(arg); } GameExtractor extract; PromptSteps promptStep = PS_FILE_CHECK; @@ -469,11 +453,6 @@ void GameEngine::RunExtract(int argc, char* argv[]) { bool extractStarted = false; std::atomic extractCount{ 0 }, totalExtract{ 0 }; - // Async ROM selection: the result callback fires on this thread during the render step below, so - // these plain locals are safe to capture by reference. - bool romLoaded = false; - bool romResultReady = false; - std::string installPath = Ship::Context::GetAppBundlePath(); std::string file; @@ -532,7 +511,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) { GameExtractor::sCustomCodePromptActive = false; }); } - if (LighthouseGui::PopupsQueued() > 0 || extracting || Ship::FileBrowserWindow::IsOpen()) { + if (LighthouseGui::PopupsQueued() > 0 || extracting) { goto render; } @@ -618,10 +597,8 @@ void GameEngine::RunExtract(int argc, char* argv[]) { "Lighthouse does not have proper file permissions.\nPlease move it to a " "folder that does and run again.", "OK", "", [&]() { - if (tfile != NULL) { - fclose(tfile); - } - PathTestCleanup(); + fclose(tfile); + PathTestCleanup(tfile); threadPool = nullptr; lhFast3dWindow = nullptr; context = nullptr; @@ -629,7 +606,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) { }); } else { fclose(tfile); - if (!PathTestCleanup()) { + if (!PathTestCleanup(tfile)) { LighthouseGui::RegisterPopup( "Lighthouse Permissions Error", "Lighthouse does not have proper file permissions.\nPlease move it to a " @@ -748,17 +725,10 @@ void GameEngine::RunExtract(int argc, char* argv[]) { } case PS_LOCAL: { extract = GameExtractor(); - const std::string appDir = Ship::Context::GetAppDirectoryPath("bk"); - std::error_code sameDirEc; - const bool sameDir = std::filesystem::equivalent(installPath, appDir, sameDirEc); extract.SetSearchPath(installPath); extract.GetRoms(args); - if (sameDirEc || !sameDir) { - extract.SetSearchPath(appDir); - extract.GetRoms(args); - } - std::sort(args.begin(), args.end()); - args.erase(std::unique(args.begin(), args.end()), args.end()); + extract.SetSearchPath(Ship::Context::GetAppDirectoryPath("bk")); + extract.GetRoms(args); if (!args.empty()) { promptStep = PS_WAIT; LighthouseGui::RegisterPopup( @@ -774,30 +744,8 @@ void GameEngine::RunExtract(int argc, char* argv[]) { continue; } case PS_FIRST: { - if (args.empty()) { - // Skip the picker entirely if a baserom.us.z64 is sitting in the app - // directory: load it and go straight to extraction. - std::string baserom = Ship::Context::GetPathRelativeToAppDirectory("baserom.us.z64"); - if (std::filesystem::exists(baserom) && extract.LoadRomFromPath(baserom)) { - extracting = true; - extractStarted = true; - file = extract.GetRomPath(); - (void)threadPool->submit_task([&]() -> void { - extract.GenerateOTR(extractCount, totalExtract, "bk"); - extracting = false; - }); - continue; // stay in PS_FIRST; the completion check fires when done - } - // Otherwise open the picker (native dialog on desktop, ImGui browser on - // consoles/arm). For the browser, the IsOpen() gate above keeps the loop - // rendering until the user picks or cancels; the ROM loads before the callback. - romResultReady = false; - romLoaded = false; - extract.SelectGameFromUI([&](bool ok) { - romLoaded = ok; - romResultReady = true; - }); - promptStep = PS_FIRST_WAIT; + if (args.empty() && !extract.SelectGameFromUI()) { + promptStep = PS_FILE_CHECK; continue; } extracting = true; @@ -809,25 +757,6 @@ void GameEngine::RunExtract(int argc, char* argv[]) { }); continue; } - case PS_FIRST_WAIT: { - if (!romResultReady) { - goto render; // browser still open; keep drawing it - } - romResultReady = false; - if (!romLoaded) { - promptStep = PS_FILE_CHECK; // cancelled or failed to load - continue; - } - extracting = true; - extractStarted = true; - file = extract.GetRomPath(); - promptStep = PS_FIRST; // so the ES_EXTRACT/PS_FIRST completion check fires - (void)threadPool->submit_task([&]() -> void { - extract.GenerateOTR(extractCount, totalExtract, "bk"); - extracting = false; - }); - continue; - } default: break; } @@ -1032,7 +961,6 @@ void GameEngine::ScaleImGui() { } void GameEngine::Create(int argc, char* argv[]) { - Lighthouse::ParseLaunchArgs(argc, argv); const auto instance = Instance = new GameEngine(); // instance->AudioInit(); // DisplayListPatch::Run(); @@ -1078,6 +1006,7 @@ void GameEngine::Destroy() { // Flush all resource refs so destructors run while spdlog is still active. // sResourceRefCache holds shared_ptrs that outlive the LUS cache otherwise. + AudioExit(); ResourceHelpers_ClearRefCache(); AudioDma_Clear(); ReleaseSoundfonts(); @@ -1104,7 +1033,7 @@ void GameEngine::StartFrame() const { case KbScancode::LUS_KB_TAB: { // Toggle HD Assets CVarSetInteger(CVAR_SETTING("Mods.AlternateAssets"), - !CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 1)); + !CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 0)); break; } case KbScancode::LUS_KB_F4: { @@ -1159,19 +1088,33 @@ void GameEngine::RelaunchIfRequested(int argc, char* argv[]) { #endif } -#define SAMPLES_PER_FRAME (560 * 2 * 2) +#if 0 +// Values for 44100 hz +#define SAMPLES_HIGH 752 +#define SAMPLES_LOW 720 +#else +// Values for 32000 hz +#define SAMPLES_HIGH 560 +#define SAMPLES_LOW 528 -// 2 VIs per game frame (30fps) -#define gVIsPerFrame 2 +#endif +#define NUM_AUDIO_CHANNELS 2 +#define SAMPLES_PER_FRAME (SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 2) extern "C" uint32_t GameEngine_GetSamplesPerFrame() { return SAMPLES_PER_FRAME; } +// 2 VIs per game frame (30fps) +#define gVIsPerFrame 2 + +// 736 samples per audio update (44000/60, aligned to 184-sample boundary) +#define AlFrameSize 736 + // Attract-demo audio hold static std::atomic sHoldAudio{ false }; -static constexpr int kDemoAudioHoldFrames = 2; // drawn ticks to stay held after the load -static int sHoldFramesRemaining = 0; // game thread only +static constexpr int kDemoAudioHoldFrames = 2; // frames to stay held after the load +static int sHoldFramesRemaining = 0; // game-thread countdown extern "C" void port_beginDemoAudioHold(void) { if (kDemoAudioHoldFrames <= 0) { @@ -1181,14 +1124,50 @@ extern "C" void port_beginDemoAudioHold(void) { sHoldAudio.store(true); } -extern "C" void port_tickDemoAudioHold(void) { - if (sHoldAudio.load() && --sHoldFramesRemaining <= 0) { - sHoldAudio.store(false); +void GameEngine::HandleAudioThread() { + int16_t audioBuffer[AlFrameSize * 2]; + Acmd cmdList[0x800]; + + // Free-run: continuously keep the backend queue topped up, real-time paced and + // decoupled from the game frame, so a long game frame can't starve the device. + while (audio.running) { + if (audio.ready) { + while (audio.running && AudioPlayerBuffered() < AudioPlayerGetDesiredBuffered()) { + int samplesToGen = AlFrameSize * 2 * sizeof(int16_t); + + memset(audioBuffer, 0, samplesToGen); + + // While held, leave the buffer as silence and do NOT advance the engine. + if (!sHoldAudio) { + int32_t cmdLen = 0; + // Lock only the engine work; the volume scale and backend submit touch + // worker-local / backend state, not the synth. + port_lockAudio(); + func_802403F0(); + n_alAudioFrame(cmdList, &cmdLen, audioBuffer, AlFrameSize); + func_80250650(); + port_unlockAudio(); + + float master_vol = CVarGetInteger(CVAR_SETTING("Volume.Master"), 100) / 100.0f; + for (u32 i = 0; i < AlFrameSize * 2; i++) { + audioBuffer[i] = static_cast(audioBuffer[i] * master_vol); + } + } + AudioPlayerPlayFrame((uint8_t*)audioBuffer, samplesToGen); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(2)); } } -extern "C" int port_audioHeld(void) { - return sHoldAudio.load() ? 1 : 0; +void GameEngine::StartAudioFrame() { + // Worker free-runs now; this only marks the engine initialized (first call is after + // audio init, once the game loop is running). + audio.ready = true; +} + +void GameEngine::EndAudioFrame() { + // No-op: audio generation is decoupled from the game frame. } static std::vector> sSoundfontResources; @@ -1237,20 +1216,31 @@ void GameEngine::AudioInit() { LoadSoundfonts(); } -// Local timer helper for the per-sub-frame cost measurement. +void GameEngine::AudioStartThread() { + if (!audio.running) { + audio.running = true; + audio.thread = std::thread(HandleAudioThread); +#ifdef _WIN32 + SetThreadPriority(audio.thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL); +#endif + } +} + +void GameEngine::AudioExit() { + // Free-run worker checks `running` each loop (~every 2 ms), so just clear it and join. + audio.running = false; + if (audio.thread.joinable()) { + audio.thread.join(); + } +} + +// Local timer helper for the per-sub-frame measurement we feed into +// AdaptiveFps_Sample. namespace { using Clock = std::chrono::steady_clock; inline long long NsSince(Clock::time_point t0) { return std::chrono::duration_cast(Clock::now() - t0).count(); } - -// In-flight async builds of interpolated sub-frame replacement maps -std::vector> sMapBuildFutures; - -// Cost of the most recent sub-frame, and the wall time this pass may spend: -// subframes/paceFps is exactly the game time one task represents. -long long sLastSubFrameNs = 0; -long long sPassBudgetNs = 0; } // namespace void GameEngine::RunCommands(Gfx* Commands, const std::vector>& mtx_replacements, @@ -1272,51 +1262,35 @@ void GameEngine::RunCommands(Gfx* Commands, const std::vectorGetWindow(); - const auto passT0 = Clock::now(); for (size_t frameIdx = 0; frameIdx < frameCount; frameIdx++) { - if (frameIdx >= 1 && frameIdx - 1 < sMapBuildFutures.size()) { - sMapBuildFutures[frameIdx - 1].wait(); - } - // Stop once another sub-frame no longer fits in what the tick's worth - // of wall time has left. - if (frameIdx > 0 && sLastSubFrameNs > 0 && (sPassBudgetNs - NsSince(passT0)) < sLastSubFrameNs) { - break; - } const auto& m = mtx_replacements[frameIdx]; - // Vertex-animated models blend into one buffer per draw, so unlike the - // matrix maps this can't be precomputed per sub-frame. It has to land - // right before the pass that reads it. - const float subframeBlend = (frameCount > 1) ? (float)(frameIdx + 1) / (float)frameCount : 1.0f; - if (frameCount > 1) { - FrameInterpolation_ApplyAnimVertices(subframeBlend); - } - // Overlays drawn by the Gui pass below place themselves per tick, so they need the - // same blend the geometry is being posed with or they step while the world glides. - Nametag::SetSubframeBlend(subframeBlend); bool isFinalFrame = (frameIdx == frameCount - 1); + // Bypass IsFrameReady() when interpolation is active — render all + // frames per tick and let vsync pace them. if (frameCount > 1 || wndBase->IsFrameReady()) { - // Sample the full CPU cost of producing this sub-frame. - auto runT0 = Clock::now(); auto gui = wndBase->GetGui(); wndBase->GetMouseStateManager()->StartFrame(); gui->StartDraw(); interpreter->StartFrame(); + auto runT0 = Clock::now(); interpreter->Run(Commands, m); - if (OS_ViBlackActive()) { + AdaptiveFps_Sample(NsSince(runT0)); + // Emulate N64 osViBlack to prevent a flicker when the scene is drawn + // for the falling jiggy transition framebuffer capture. + if (port_isViBlack()) { interpreter->mGfxFrameBuffer = 0; auto rapi = interpreter->GetCurrentRenderingAPI(); rapi->StartDrawToFramebuffer(0, 1.0f); rapi->ClearFramebuffer(true, false); } gui->EndDraw(); - sLastSubFrameNs = NsSince(runT0); interpreter->EndFrame(); CALL_EVENT(FrameDrawEnd); } interpreter->mInterpolationIndex++; } - bool curAltAssets = CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 1); + bool curAltAssets = CVarGetInteger(CVAR_SETTING("Mods.AlternateAssets"), 0); if (prevAltAssets != curAltAssets) { prevAltAssets = curAltAssets; Ship::Context::GetRawInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets); @@ -1335,12 +1309,25 @@ namespace { struct SubframePacing { int subframes; // renders to emit this tick (>= 1) int fps; // target present fps for this tick - int viPerTick; // VIs of game time this tick covers }; SubframePacing ComputeSubframePacing() { int target_fps = (int)GameEngine::Instance->GetInterpolationFPS(); + // Demo/replay modes render at the native rate + const bool replayMode = func_802E4A08(); + if (!replayMode) { + if (CVarGetInteger(CVAR_SETTING("AdaptiveFPS"), 1)) { + target_fps = (int)AdaptiveFps_Cap((uint32_t)target_fps); + } + + // Some music-synced cutscenes cap interpolation at native 30 + int fpsCap = port_getInterpolationFpsCap(); + if (fpsCap > 0 && target_fps > fpsCap) { + target_fps = fpsCap; + } + } + // Game-logic VI per tick: gVIsPerFrame (=2 -> 30 Hz) normally; demo // replay and cutscene stutter raise it for slow N64 frames. int viPerTick = port_getDemoViCount(); @@ -1350,12 +1337,6 @@ SubframePacing ComputeSubframePacing() { if (viPerTick < gVIsPerFrame) { viPerTick = gVIsPerFrame; } - // time_setDeltaReal_frames() clamps the demo's recorded VI count to 15, so the - // tick never advances more than that no matter what the demo asks for. Match it - // here or a bogus recorded value would scale the sub-frame count with it. - if (viPerTick > 15) { - viPerTick = 15; - } int effective_logic_fps = 60 / viPerTick; if (effective_logic_fps < 1) { @@ -1370,16 +1351,18 @@ SubframePacing ComputeSubframePacing() { subframesPerTick = 1; } - // paceFps drives DXGI's per-present wait so that subframes * 1/paceFps = - // viPerTick/60 wall (= game time per tick). Derived from viPerTick rather than - // effective_logic_fps: the latter is truncated (VI=7 -> 8, not 8.57), which would - // stretch wall time on the odd VI counts demo playback hands us every tick. - int fps = subframesPerTick * 60 / viPerTick; - if (fps < 1) { - fps = 1; + // Replay modes never interpolate: one render per tick, held to viPerTick/60 by the floor. + if (replayMode) { + subframesPerTick = 1; } - return { subframesPerTick, fps, viPerTick }; + // paceFps drives DXGI's per-present wait so that subframes * 1/paceFps = + // viPerTick/60 wall (= game time per tick). When viPerTick == gVIsPerFrame + // and target_fps is a multiple of eff, paceFps == target_fps and stays + // constant. Otherwise it varies per tick to keep wall == game. + int fps = subframesPerTick * effective_logic_fps; + + return { subframesPerTick, fps }; } } // namespace @@ -1411,26 +1394,16 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { mtx_replacements.resize(subframesPerTick); } size_t activeFrames = 0; - sMapBuildFutures.clear(); for (int i = 1; i <= subframesPerTick; i++) { if (i < subframesPerTick) { float t = (float)i / (float)subframesPerTick; - if (i == 1) { - FrameInterpolation_Interpolate(t, mtx_replacements[activeFrames]); - } else { - auto* map = &mtx_replacements[activeFrames]; - sMapBuildFutures.push_back( - std::async(std::launch::async, [t, map] { FrameInterpolation_Interpolate(t, *map); })); - } + FrameInterpolation_Interpolate(t, mtx_replacements[activeFrames]); } else { mtx_replacements[activeFrames].clear(); } activeFrames++; } - // Wall time this tick is worth, straight from its VI count. - sPassBudgetNs = 1000000000LL * pacing.viPerTick / 60; - if (wnd != nullptr) { wnd->SetTargetFps(fps); // Hardcoded: CVarGetInteger crashes due to heap corruption in debug builds. @@ -1447,14 +1420,10 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { RunCommands(commands, mtx_replacements, activeFrames); - // Drain any builds the render loop didn't consume (debugger path, early - // return) before the next tick's StartRecord resets the trees they read. - for (auto& f : sMapBuildFutures) { - if (f.valid()) { - f.wait(); - } + // [port] Release the demo audio hold after kDemoAudioHoldFrames rendered frames. + if (sHoldAudio.load() && --sHoldFramesRemaining <= 0) { + sHoldAudio.store(false); } - sMapBuildFutures.clear(); } uint32_t GameEngine::GetInterpolationFPS() { diff --git a/src/port/Engine.h b/src/port/Engine.h index c6e1b9a34..477a785e9 100644 --- a/src/port/Engine.h +++ b/src/port/Engine.h @@ -42,7 +42,12 @@ class GameEngine { GameEngine(); void StartFrame() const; static void Create(int argc, char* argv[]); + static void HandleAudioThread(); + static void StartAudioFrame(); + static void EndAudioFrame(); static void AudioInit(); + static void AudioStartThread(); + static void AudioExit(); void FinishInit(); void RunExtract(int argc, char* argv[]); // Render a GUI-only frame (no game tick). Used to keep the ImGui progress diff --git a/src/port/Enhancements/Backports/EggAim.cpp b/src/port/Enhancements/Backports/EggAim.cpp index 4b4cf0d2a..ef977e452 100644 --- a/src/port/Enhancements/Backports/EggAim.cpp +++ b/src/port/Enhancements/Backports/EggAim.cpp @@ -13,10 +13,12 @@ #include "port/ShipInit.hpp" #include "EggAim.h" +extern "C" { #include "enums.h" #include "functions.h" #include "core2/commonParticle.h" #include "core2/abilityprogress.h" +} #define CVAR_NAME CVAR_ENHANCEMENT("Backports.EggAim") @@ -213,10 +215,6 @@ const uint8_t sCrosshairTextureData[32 * 32 * 4] = { int sFiring = 0; int sOverlayShown = 0; -bool canAimEggs() { - return can_egg() && player_getTransformation() == TRANSFORM_1_BANJO; -} - } // namespace void RegisterEggAimSpawn_Init() { @@ -226,7 +224,7 @@ void RegisterEggAimSpawn_Init() { } auto* ev = reinterpret_cast(event); float rotation[3]; - ncba1p_getZoomedInRotation(rotation); + ncFirstPersonCamera_getZoomedInRotation(rotation); *ev->pitch = -rotation[0]; *ev->spawnHeight = 100.0f; *ev->minVerticalVelocity = -99999.0f; @@ -245,11 +243,11 @@ void RegisterEggAim_Init() { return; } - if (!canAimEggs()) { + if (!can_egg()) { return; } - if (ncba1p_getState() == FIRSTPERSON_STATE_2_IDLE) { + if (ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_2_IDLE) { if (sOverlayShown < kOverlayFadeDuration) { sOverlayShown++; } @@ -305,7 +303,7 @@ void EggAimCrosshairWindow::Draw() { tex.ImageDataSize = sizeof(sCrosshairTextureData); tex.ImageData = new uint8_t[sizeof(sCrosshairTextureData)]; std::memcpy(tex.ImageData, sCrosshairTextureData, sizeof(sCrosshairTextureData)); - gui->LoadGuiTexture(kCrosshairTexture, tex, "", ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); + gui->LoadGuiTexture(kCrosshairTexture, tex, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); } const float t = (float)sOverlayShown / (float)kOverlayFadeDuration; // 0..1 diff --git a/src/port/Enhancements/Backports/FastSwim.cpp b/src/port/Enhancements/Backports/FastSwim.cpp index 614c12c4c..bb0d3e060 100644 --- a/src/port/Enhancements/Backports/FastSwim.cpp +++ b/src/port/Enhancements/Backports/FastSwim.cpp @@ -8,7 +8,9 @@ // Include C decomp headers with C linkage before C++ headers to prevent // transitive includes from giving them C++ name mangling. +extern "C" { #include "core2/bonetransform.h" +} #include #include "port/UI/cvar_prefixes.h" diff --git a/src/port/Enhancements/Backports/Honeyback.cpp b/src/port/Enhancements/Backports/Honeyback.cpp index 3ae509d0f..1f1f41a04 100644 --- a/src/port/Enhancements/Backports/Honeyback.cpp +++ b/src/port/Enhancements/Backports/Honeyback.cpp @@ -7,9 +7,11 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +extern "C" { #include "enums.h" #include "functions.h" #include "gc/gctransition.h" +} #define CVAR_NAME CVAR_ENHANCEMENT("Backports.Honeyback") diff --git a/src/port/Enhancements/Backports/TooieJiggyDance.cpp b/src/port/Enhancements/Backports/TooieJiggyDance.cpp index 3c9da21e8..8846ed8c5 100644 --- a/src/port/Enhancements/Backports/TooieJiggyDance.cpp +++ b/src/port/Enhancements/Backports/TooieJiggyDance.cpp @@ -8,14 +8,14 @@ #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -#include "port/Rando/Rando.h" -#include "functions.h" extern "C" { #include "enums.h" +#include "functions.h" #include "core2/particle.h" ParticleEmitter* __fxSparkle_create(s16 position[3], f32 height, enum asset_e sprite_id); +f32 player_getYaw(void); } #define CVAR_TOOIE_JIGGY_DANCE CVAR_ENHANCEMENT("Backports.JiggyAnimation") @@ -114,7 +114,7 @@ void emitSparkle(f32 x, f32 y, f32 z) { } } -extern "C" void spawnOrbit() { +void spawnOrbit() { clearOrbit(); f32 banjo[3]; @@ -137,8 +137,6 @@ extern "C" void spawnOrbit() { } actor->state = 0; actor_collisionOff(actor); - actor->unk44_2 = 1; // Keep this jiggy out of jiggylist_map_actors - actor->unk10_1 = 0; // Keep this jiggy out of map savestate sfxsource_playHighPriority(SFX_3E9_UNKNOWN); sMarker = (void*)actor->marker; } @@ -266,15 +264,11 @@ void updateOrbit() { } // namespace -// Romhacks that bundle wedarobi's jiggy dance should have it on by default. -// The hack may depend on the retained player motion that the animation provides. -static bool sJiggyDanceForced = false; - void RegisterJiggyCollect_Init() { clearOrbit(); const bool skip = CVarGetInteger(CVAR_SKIP_JIGGY_DANCE, 0); - const bool tooie = CVarGetInteger(CVAR_TOOIE_JIGGY_DANCE, 0) || sJiggyDanceForced; - const bool playOrbit = (tooie && !skip) || IS_RANDO; + const bool tooie = CVarGetInteger(CVAR_TOOIE_JIGGY_DANCE, 0); + const bool playOrbit = tooie && !skip; COND_VB_SHOULD(VB_PLAY_JIGGY_DANCE, EVENT_PRIORITY_NORMAL, skip || tooie, { *should = false; }); @@ -283,10 +277,5 @@ void RegisterJiggyCollect_Init() { COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, playOrbit, [](IEvent*) { forgetOrbit(); }); } -void TooieJiggyDance_ForceEnable() { - sJiggyDanceForced = true; - RegisterJiggyCollect_Init(); -} - static RegisterShipInitFunc initJiggyCollect(RegisterJiggyCollect_Init, - { CVAR_TOOIE_JIGGY_DANCE, CVAR_SKIP_JIGGY_DANCE, "IS_RANDO" }); + { CVAR_TOOIE_JIGGY_DANCE, CVAR_SKIP_JIGGY_DANCE }); diff --git a/src/port/Enhancements/Camera/FreeLookCamera.cpp b/src/port/Enhancements/Camera/FreeLookCamera.cpp index a4b51e96f..46381bd59 100644 --- a/src/port/Enhancements/Camera/FreeLookCamera.cpp +++ b/src/port/Enhancements/Camera/FreeLookCamera.cpp @@ -1,49 +1,21 @@ -// Free look camera - -#include - #include #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Camera/FreeLookCamera.h" +#include "port/Enhancements/Camera/OrbitCameraCore.h" +// Vanilla camera / input entry points (decomp C API). extern "C" { -// Math helpers -void func_80256E24(float dst[3], float pitch, float yaw, float x, float y, float z); -void ml_vec3f_add(float dst[3], float a[3], float b[3]); -void ml_vec3f_clear(float dst[3]); -float mlNormalizeAngle(float deg); +int ncDynamicCamera_getState(void); float time_getDelta(void); +float gu_sqrtf(float x); void controller_getRightStick(int controller_index, float dst[2]); int bainput_should_rotate_camera_left(void); int bainput_should_rotate_camera_right(void); int bainput_should_look_first_person_camera(void); - -int ncDynamicCamera_getState(void); -void ncDynamicCamera_setState(int state); -void ncDynamicCamera_getPosition(float dst[3]); -void ncDynamicCamera_setRotation(float src[3]); - -// Vanilla follow-camera machinery -extern float D_8037DB70; // dynamicCamB.c: orbit yaw, degrees -extern float D_8037D9C8[3]; // dynamicCamera.c: rotation spring velocity - -void func_802C0150(int mode); // select the focus target -void func_802C0370(void); // record the pre-move position (anti-flip guard) -void func_802C0394(float target[3]); // record the ideal target (anti-flip guard) -void func_802C03BC(void); // undo a collision resolve that crossed over -void func_802C0490(float dst[3]); // focus/orbit center -void func_802C04B0(void); // re-derive D_8037DB70 from the live camera - -float func_802BD8D4(void); // target orbit distance (zoom level) -void func_802BE190(float target[3]); // position spring toward target -void func_802BE230(float gain, float damp); // position spring tuning -int func_802BE60C(void); // swept camera collision + slide -int func_802BC84C(int mode); // occluded-too-long recovery -void func_802BE6FC(float rotOut[3], float focus[3]); // look-at from the live position } namespace { @@ -54,90 +26,50 @@ namespace { #define CVAR_FREELOOK_INVERT_Y CVAR_ENHANCEMENT("Camera.FreeLook.InvertY") #define CVAR_FREELOOK_SMOOTH_RATE CVAR_ENHANCEMENT("Camera.FreeLook.SmoothRate") -constexpr float kDeadzone = 0.15f; -constexpr float kEnterThreshold = 0.30f; -constexpr float kYawSpeed = 160.0f; -constexpr float kPitchSpeed = 100.0f; +// Tuning +constexpr float deadzone = 0.15f; +constexpr float enterThreshold = 0.30f; +constexpr float horizontalSpeed = 160.0f; +constexpr float verticalSpeed = 100.0f; -constexpr float kMinPitch = -85.0f; -constexpr float kMaxPitch = 40.0f; +constexpr float minPitch = -85.0f; // high overhead, looking down +constexpr float maxPitch = 40.0f; // low, looking up at the player -constexpr float kAimHeightRate = 8.0f; -constexpr float kDefaultSmooth = 40.0f; -constexpr float kSmoothToGain = 0.5f; -constexpr float kDampRatio = 4.0f; +// position smoothing rate (1/sec); higher = snappier +constexpr float defaultSmoothRate = 40.0f; -constexpr float kRadToDeg = 57.29577951308232f; +// Pitch-enabled orbit on the shared core. Distance tracks the vanilla zoom level +// (same as the modern-scheme camera) so the normal follow distances are honored. +OrbitCamera sFreeLook = { /*stateId*/ FREELOOK_CAM_STATE, /*allowPitch*/ 1, + /*minPitch*/ minPitch, /*maxPitch*/ maxPitch, /*smoothRate*/ defaultSmoothRate }; -bool sActive = false; -bool sAimValid = false; -float sPitch = 0.0f; -float sAimY = 0.0f; - -float clampf(float v, float lo, float hi) { - return v < lo ? lo : (v > hi ? hi : v); -} - -float SpringGain() { - return CVarGetFloat(CVAR_FREELOOK_SMOOTH_RATE, kDefaultSmooth) * kSmoothToGain; -} - -float ReadStick(float out[2]) { +// Right stick with a radial deadzone, rescaled so motion ramps from 0 at the +// deadzone edge to 1 at full deflection. +float readStick(float out[2]) { controller_getRightStick(0, out); - float mag = std::sqrt(out[0] * out[0] + out[1] * out[1]); - if (mag < kDeadzone) { + float mag = gu_sqrtf(out[0] * out[0] + out[1] * out[1]); + if (mag < deadzone) { out[0] = out[1] = 0.0f; return 0.0f; } if (mag > 1.0f) { mag = 1.0f; } - float scaled = (mag - kDeadzone) / (1.0f - kDeadzone); + float scaled = (mag - deadzone) / (1.0f - deadzone); float k = scaled / mag; out[0] *= k; out[1] *= k; return scaled; } -bool ManualCameraControl() { +// Explicit camera commands hand the frame back to the normal camera. Zoom is not +// one of them: it adjusts the vanilla zoom level, which free look tracks, so the +// player can re-zoom without dropping out of free look. +bool cButtonCameraControl() { return bainput_should_rotate_camera_left() || bainput_should_rotate_camera_right() || bainput_should_look_first_person_camera(); } -float CapturePitch() { - float camPos[3]; - float focus[3]; - ncDynamicCamera_getPosition(camPos); - func_802C0490(focus); - - float diff[3] = { camPos[0] - focus[0], camPos[1] - focus[1], camPos[2] - focus[2] }; - float dist = std::sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); - if (dist < 1.0f) { - return 0.0f; - } - return clampf(std::asin(clampf(-diff[1] / dist, -1.0f, 1.0f)) * kRadToDeg, kMinPitch, kMaxPitch); -} - -void EnterOrbit() { - func_802C0150(2); - func_802BE230(SpringGain(), SpringGain() * kDampRatio); - func_802C04B0(); - sPitch = CapturePitch(); - - ml_vec3f_clear(D_8037D9C8); - - sAimValid = false; - sActive = true; - ncDynamicCamera_setState(FREELOOK_CAM_STATE); -} - -void ExitOrbit() { - sActive = false; - if (ncDynamicCamera_getState() == FREELOOK_CAM_STATE) { - ncDynamicCamera_setState(0xB); - } -} - } // namespace extern "C" int port_freeLook_isEnabled(void) { @@ -146,37 +78,38 @@ extern "C" int port_freeLook_isEnabled(void) { extern "C" int port_freeLook_handle(void) { if (!port_freeLook_isEnabled()) { - if (sActive) { - ExitOrbit(); + if (sFreeLook.active) { + OrbitCamera_Exit(&sFreeLook); } return 0; } int state = ncDynamicCamera_getState(); - if (sActive) { + if (sFreeLook.active) { if (state != FREELOOK_CAM_STATE) { - sActive = false; + sFreeLook.active = 0; return 0; } - if (ManualCameraControl()) { - ExitOrbit(); + if (cButtonCameraControl()) { + OrbitCamera_Exit(&sFreeLook); return 0; } - return 1; + return 1; // hold the angle; consume the frame } - if (ManualCameraControl()) { + if (cButtonCameraControl()) { return 0; } + // Only enter from a normal follow/orbit camera. if (state != 0xB && state != 0x1 && state != 0xA) { return 0; } float stick[2]; - if (ReadStick(stick) >= kEnterThreshold) { - EnterOrbit(); + if (readStick(stick) >= enterThreshold) { + OrbitCamera_Enter(&sFreeLook); return 1; } @@ -185,47 +118,23 @@ extern "C" int port_freeLook_handle(void) { extern "C" void port_freeLookCamera_update(void) { float dt = time_getDelta(); - - float stick[2]; - ReadStick(stick); - - float yawSens = CVarGetFloat(CVAR_FREELOOK_YAW_SENS, 1.0f); - float pitchSens = CVarGetFloat(CVAR_FREELOOK_PITCH_SENS, 1.0f); - bool invertX = CVarGetInteger(CVAR_FREELOOK_INVERT_X, 0) != 0; - bool invertY = CVarGetInteger(CVAR_FREELOOK_INVERT_Y, 0) != 0; - - D_8037DB70 = mlNormalizeAngle(D_8037DB70 + (invertX ? -stick[0] : stick[0]) * kYawSpeed * yawSens * dt); - sPitch = clampf(sPitch + (invertY ? stick[1] : -stick[1]) * kPitchSpeed * pitchSens * dt, kMinPitch, kMaxPitch); - - float focus[3]; - float offset[3]; - float target[3]; - - func_802C0370(); - func_802C0490(focus); - func_80256E24(offset, sPitch, D_8037DB70, 0.0f, 0.0f, func_802BD8D4()); - ml_vec3f_add(target, focus, offset); - - func_802C0394(target); - func_802BE190(target); - - if (func_802BE60C()) { - if (!func_802BC84C(1)) { - func_802C03BC(); - } - func_802C04B0(); - } - - func_802C0490(focus); - if (!sAimValid) { - sAimY = focus[1]; - sAimValid = true; - } else { - sAimY += (focus[1] - sAimY) * clampf(kAimHeightRate * dt, 0.0f, 1.0f); + sFreeLook.smoothRate = CVarGetFloat(CVAR_FREELOOK_SMOOTH_RATE, defaultSmoothRate); + + float yawDelta = 0.0f; + float pitchDelta = 0.0f; + if (!sFreeLook.justEntered) { + float stick[2]; + readStick(stick); + + float yawSens = CVarGetFloat(CVAR_FREELOOK_YAW_SENS, 1.0f); + float pitchSens = CVarGetFloat(CVAR_FREELOOK_PITCH_SENS, 1.0f); + bool invertX = CVarGetInteger(CVAR_FREELOOK_INVERT_X, 0) != 0; + bool invertY = CVarGetInteger(CVAR_FREELOOK_INVERT_Y, 0) != 0; + + yawDelta = (invertX ? -stick[0] : stick[0]) * horizontalSpeed * yawSens * dt; + // Default: push up -> camera rises and looks down (overhead). InvertY flips it. + pitchDelta = (invertY ? stick[1] : -stick[1]) * verticalSpeed * pitchSens * dt; } - focus[1] = sAimY; - float rot[3]; - func_802BE6FC(rot, focus); - ncDynamicCamera_setRotation(rot); + OrbitCamera_Update(&sFreeLook, yawDelta, pitchDelta); } diff --git a/src/port/Enhancements/Camera/OrbitCameraCore.cpp b/src/port/Enhancements/Camera/OrbitCameraCore.cpp new file mode 100644 index 000000000..3ca4e8d3d --- /dev/null +++ b/src/port/Enhancements/Camera/OrbitCameraCore.cpp @@ -0,0 +1,157 @@ +// Shared right-stick orbit camera core. See OrbitCameraCore.h. + +#include "port/Enhancements/Camera/OrbitCameraCore.h" + +extern "C" { +// Vanilla camera / math entry points used to drive the orbit state. +void ncDynamicCamera_getPosition(float dst[3]); +void ncDynamicCamera_setPosition(float src[3]); +void ncDynamicCamera_setRotation(float src[3]); +int ncDynamicCamera_getState(void); +void ncDynamicCamera_setState(int state); + +void func_802C02D4(float center[3]); // camera focus/orbit center +void func_80256E24(float dst[3], float pitch, float yaw, float x, float y, float z); // spherical -> offset +int func_8025801C(float vec[3], float* yaw); // vector -> yaw (degrees) +void func_802BC434(float rotOut[3], float fromPos[3], float targetPos[3]); // look-at rotation +int func_802BE60C(void); // swept camera collision + slide +float func_802BD8D4(void); // target orbit distance (zoom level) +float func_802BD51C(void); // target camera height + +float ml_acosf(float x); +float mlNormalizeAngle(float deg); +float gu_sqrtf(float x); +float time_getDelta(void); +} + +namespace { + +// 1/sec; how fast distance chases the zoom-level target. +constexpr float kDistanceRate = 8.0f; +// 1/sec; vertical follow (flat-pitch mode only). Matched to the vanilla camera, +// whose Y lerp is target*dt*2, so the camera stays mostly put during a jump +// (Banjo rises in frame) instead of choppily chasing the parabola up and down. +constexpr float kHeightRate = 2.0f; +// 1/sec; how fast the look-at target's Y chases its raw value. The orbit center +// Y is derived from the floor height under the player, which snaps up in discrete +// steps on stairs; smoothing it de-steps the aim pitch the way the vanilla camera's +// rotation tracker (func_802BD904) does, without adding lag to the stick-driven yaw. +constexpr float kAimHeightRate = 8.0f; + +float clampf(float v, float lo, float hi) { + return v < lo ? lo : (v > hi ? hi : v); +} + +} // namespace + +extern "C" void OrbitCamera_Capture(OrbitCamera* c) { + float camPos[3]; + float center[3]; + ncDynamicCamera_getPosition(camPos); + func_802C02D4(center); + + float diff[3] = { camPos[0] - center[0], camPos[1] - center[1], camPos[2] - center[2] }; + + c->yaw = 0.0f; + func_8025801C(diff, &c->yaw); + + if (c->allowPitch) { + float dist = gu_sqrtf(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); + c->distance = dist; + float sinPitch = clampf(-diff[1] / dist, -1.0f, 1.0f); + float pitchMag = ml_acosf(sinPitch); + c->pitch = clampf(sinPitch < 0.0f ? -pitchMag : pitchMag, c->minPitch, c->maxPitch); + } else { + c->distance = gu_sqrtf(diff[0] * diff[0] + diff[2] * diff[2]); + c->height = camPos[1]; + c->pitch = 0.0f; + } + + c->justEntered = 1; + c->smoothValid = 0; + c->aimValid = 0; +} + +extern "C" void OrbitCamera_Enter(OrbitCamera* c) { + OrbitCamera_Capture(c); + c->active = 1; + ncDynamicCamera_setState(c->stateId); +} + +extern "C" void OrbitCamera_Exit(OrbitCamera* c) { + c->active = 0; + if (ncDynamicCamera_getState() == c->stateId) { + ncDynamicCamera_setState(0xB); // hand back to the normal follow camera + } +} + +extern "C" void OrbitCamera_Update(OrbitCamera* c, float yawDelta, float pitchDelta) { + float dt = time_getDelta(); + float center[3]; + func_802C02D4(center); + + c->yaw = mlNormalizeAngle(c->yaw + yawDelta); + if (c->allowPitch) { + c->pitch = clampf(c->pitch + pitchDelta, c->minPitch, c->maxPitch); + } + c->justEntered = 0; + + // Track the vanilla zoom-level distance so the normal zoom controls still take + // effect while orbiting. + float distTrack = clampf(kDistanceRate * dt, 0.0f, 1.0f); + c->distance += (func_802BD8D4() - c->distance) * distTrack; + + float offset[3]; + func_80256E24(offset, c->allowPitch ? c->pitch : 0.0f, c->yaw, 0.0f, 0.0f, c->distance); + + float pos[3]; + pos[0] = center[0] + offset[0]; + pos[2] = center[2] + offset[2]; + if (c->allowPitch) { + // Pitch carries the vertical offset. + pos[1] = center[1] + offset[1]; + } else { + // Flat orbit: height follows the vanilla target, more slowly than distance + // so jumps read as natural rather than choppy. + float heightTrack = clampf(kHeightRate * dt, 0.0f, 1.0f); + c->height += (func_802BD51C() - c->height) * heightTrack; + pos[1] = c->height; + } + ncDynamicCamera_setPosition(pos); + + // Resolve geometry. + func_802BE60C(); + + float resolved[3]; + ncDynamicCamera_getPosition(resolved); + + if (!c->smoothValid) { + c->smoothPos[0] = resolved[0]; + c->smoothPos[1] = resolved[1]; + c->smoothPos[2] = resolved[2]; + c->smoothValid = 1; + } else { + // Smooth the resolved position to prevent hitching on edges. + float f = clampf(c->smoothRate * dt, 0.0f, 1.0f); + c->smoothPos[0] += (resolved[0] - c->smoothPos[0]) * f; + c->smoothPos[1] += (resolved[1] - c->smoothPos[1]) * f; + c->smoothPos[2] += (resolved[2] - c->smoothPos[2]) * f; + } + ncDynamicCamera_setPosition(c->smoothPos); + + // Aim back at the player from the smoothed position. Smooth only the target's + // Y: the orbit center Y steps with the floor height under the player. + // X/Z follow the player directly so horizontal aim stays responsive. + if (!c->aimValid) { + c->aimCenterY = center[1]; + c->aimValid = 1; + } else { + float aimTrack = clampf(kAimHeightRate * dt, 0.0f, 1.0f); + c->aimCenterY += (center[1] - c->aimCenterY) * aimTrack; + } + float aimCenter[3] = { center[0], c->aimCenterY, center[2] }; + + float rot[3]; + func_802BC434(rot, aimCenter, c->smoothPos); + ncDynamicCamera_setRotation(rot); +} diff --git a/src/port/Enhancements/Camera/OrbitCameraCore.h b/src/port/Enhancements/Camera/OrbitCameraCore.h new file mode 100644 index 000000000..ba10397dc --- /dev/null +++ b/src/port/Enhancements/Camera/OrbitCameraCore.h @@ -0,0 +1,59 @@ +#ifndef PORT_ORBIT_CAMERA_CORE_H +#define PORT_ORBIT_CAMERA_CORE_H + +// Shared right-stick orbit camera core. +// +// Both the modern control scheme's yaw orbit and the Free Look enhancement are +// configurations of the same machinery: capture the current camera, drive yaw +// (and optionally pitch) from the right stick, track the vanilla zoom-level +// distance, resolve geometry collision, smooth, and aim back at the player. +// +// The two only differ in policy (when to enter/hold/hand back, how the stick is +// read, whether pitch is live) and in a couple of tuning values. Each owns an +// OrbitCamera instance and supplies those via the config fields below; the core +// owns the per-frame math so the behavior stays identical between them. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + // // Config (set by the owner) + int stateId; // dynamic camera state this orbit runs as + int allowPitch; // 1: stick Y drives pitch and feeds the vertical offset. + // 0: pitch is locked flat and height tracks the vanilla target. + float minPitch; // pitch clamp, degrees (only used when allowPitch) + float maxPitch; + float smoothRate; // position smoothing rate, 1/sec + + // Runtime state + int active; + int justEntered; + int smoothValid; + int aimValid; // aimCenterY has been seeded + float yaw; + float pitch; + float distance; // spherical radius; tracks the vanilla zoom-level target + float height; // absolute Y, only used when !allowPitch + float aimCenterY; // smoothed Y of the look-at target (de-steps stairs) + float smoothPos[3]; +} OrbitCamera; + +// Seed yaw/pitch/distance(/height) from wherever the live camera currently sits, +// so the orbit starts without a jump. +void OrbitCamera_Capture(OrbitCamera* c); + +// Capture and take ownership of the camera state. +void OrbitCamera_Enter(OrbitCamera* c); + +// Release the camera state back to the normal follow camera (state 0xB). +void OrbitCamera_Exit(OrbitCamera* c); + +// Advance one frame. +void OrbitCamera_Update(OrbitCamera* c, float yawDelta, float pitchDelta); + +#ifdef __cplusplus +} +#endif + +#endif // PORT_ORBIT_CAMERA_CORE_H diff --git a/src/port/Enhancements/Cheats/Cheats.cpp b/src/port/Enhancements/Cheats/Cheats.cpp index 178e3faa8..2de8b7d81 100644 --- a/src/port/Enhancements/Cheats/Cheats.cpp +++ b/src/port/Enhancements/Cheats/Cheats.cpp @@ -5,16 +5,20 @@ #include #include "port/UI/cvar_prefixes.h" #include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/RomhackConfig.h" #include "port/ShipInit.hpp" #include "port/ShipUtils.h" +extern "C" { #include "enums.h" #include "core2/statetimer.h" -#include "core2/ba/physics.h" #include "bs_funcs.h" #include "functions.h" +s32 port_getRomhackMaxEggs(void); +s32 port_getRomhackMaxGoldFeathers(void); +s32 port_getRomhackMaxRedFeathers(void); +} + // ============================================================================ // CVAR DEFINITIONS // ============================================================================ @@ -137,7 +141,7 @@ void RegisterTalonTrotCycle_Init() { // D-pad cycling - only works while Talon Trot is active if (bakey_pressed(BUTTON_D_RIGHT) || bakey_pressed(BUTTON_D_LEFT)) { s32 currentState = bs_getState(); - bool inTalonTrot = bsbtrot_inSet(currentState) || bslongleg_inSet(currentState); + bool inTalonTrot = bsbtrot_inSet((enum bs_e)currentState) || bslongleg_inSet(0); // Also in longleg state if (inTalonTrot) { bool inBoots = stateTimer_isActive(STATE_TIMER_2_LONGLEG); @@ -180,28 +184,23 @@ void RegisterTalonTrotCycle_Init() { // MOVEMENT CHEATS // ============================================================================ -// Levitate — Hold L to float straight up; tapping L out of a damaging fall cancels the fall. +// Levitate — Hold L to float upward with gravity disabled void RegisterLevitate_Init() { - static const f32 LEVITATE_VELOCITY = 500.0f; static bool levitateActive = false; COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_LEVITATE, 0), [](IEvent* event) { - // Suspend levitation while dialog is up. - // Cancel fall damage and the tumble/splat animation if pressed mid-fall. - if (bakey_held(BUTTON_L) && !gcdialog_hasCurrentTextId()) { - if (bakey_pressed(BUTTON_L) && !player_isStable()) { - s32 fallDamage = 0; - if (bafalldamage_get_damage(&fallDamage) != 0) { - bafalldamage_start(); - bs_setState(BS_1_IDLE); - } - } + if (bakey_held(BUTTON_L)) { baphysics_set_gravity(0.0f); - baphysics_set_vertical_velocity(LEVITATE_VELOCITY); + f32 pos[3]; + player_getPosition(pos); + pos[1] += 20.0f; + player_setPosition(pos); levitateActive = true; - } else if (levitateActive) { - // Only reset gravity once when L is released, not every frame. - baphysics_reset_gravity(); - levitateActive = false; + } else { + // Only reset gravity once when L is released, not every frame + if (levitateActive) { + baphysics_reset_gravity(); + levitateActive = false; + } } }); } @@ -210,14 +209,9 @@ void RegisterLevitate_Init() { // TRANSFORMATION CHEATS // ============================================================================ -static const s32 BAANIM_WISHYWASHY = 0x80; -static bool isWishyWashyUnlocked() { - return (baanim_getActiveBottlesBonusMask() & BAANIM_WISHYWASHY) != 0; -} - // Transformation cycling with D-pad Up/Down -// D-pad Up: Cycle forward through transformations (Banjo -> Termite -> ... -> Bee -> [Wishy] -> Banjo) -// D-pad Down: Cycle backward through transformations (Banjo -> [Wishy] -> Bee -> ... -> Termite -> Banjo) +// D-pad Up: Cycle forward through transformations (Banjo -> Mumbo -> Termite -> ... -> Wishy -> Banjo) +// D-pad Down: Cycle backward through transformations (Banjo -> Wishy -> ... -> Termite -> Mumbo -> Banjo) void RegisterCycleTransform_Init() { COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_CYCLE_TRANSFORM, 0), [](IEvent* event) { s32 currentTransform = (s32)player_getTransformation(); @@ -228,10 +222,7 @@ void RegisterCycleTransform_Init() { if (currentTransform > TRANSFORM_7_WISHWASHY) { currentTransform = TRANSFORM_1_BANJO; } - if (currentTransform == TRANSFORM_7_WISHWASHY && !isWishyWashyUnlocked()) { - currentTransform = TRANSFORM_1_BANJO; // skip Wishy Washy -> wrap to Banjo - } - player_transform((enum transformation_e)currentTransform); + func_8028FB88((enum transformation_e)currentTransform); } // D-pad Down: Cycle backward through transformations else if (bakey_pressed(BUTTON_D_DOWN)) { @@ -239,56 +230,11 @@ void RegisterCycleTransform_Init() { if (currentTransform < TRANSFORM_1_BANJO) { currentTransform = TRANSFORM_7_WISHWASHY; } - if (currentTransform == TRANSFORM_7_WISHWASHY && !isWishyWashyUnlocked()) { - currentTransform = TRANSFORM_6_BEE; // skip Wishy Washy -> step to Bee - } - player_transform((enum transformation_e)currentTransform); + func_8028FB88((enum transformation_e)currentTransform); } }); } -// Copies of chMumbo_update state 5's 0.01 and 0.999 beats minus the audio; keep in step with it. -extern "C" { -void chMumbo_func_802D1B8C(Actor* actor, enum transformation_e transform_id); -extern u8 D_8037DDF0; // the transformation this hut offers -} - -static bool sMumboFastXformStarted = false; - -static bool FastTransform_startHutTransform(Actor* actor) { - if (actor->has_met_before || (actor->unk10_12 == 0 && (s32)player_getTransformation() != TRANSFORM_1_BANJO && - (s32)player_getTransformation() != romhack_mumboWishwashyId())) { - return romhack_mumboTransform(TRANSFORM_1_BANJO); - } - if (romhack_mumboTransform(D_8037DDF0)) { - if (D_8037DDF0 != romhack_mumboWishwashyId()) { - enum file_progress_e paidFlag = - (enum file_progress_e)((D_8037DDF0 - TRANSFORM_2_TERMITE) + FILEPROG_90_PAID_TERMITE_COST); - if (fileProgressFlag_getAndSet(paidFlag, true)) { - actor->velocity[0] = 1.0f; - } - actor->unk38_31 = 0; - } - if (actor->unk10_12 == 1) { - actor->unk10_12 = 0; - } - return true; - } - return false; -} - -// No has_met_before branch: those sequences are left to vanilla below. -static void FastTransform_endHutTransform(Actor* actor) { - func_8028F918(0); // pops the look-at lock state 4 pushed - if ((s32)player_getTransformation() != TRANSFORM_1_BANJO) { - subaddie_set_state(actor, 3); - chMumbo_func_802D1B8C(actor, (enum transformation_e)D_8037DDF0); - return; - } - gcpausemenu_80314AC8(1); - subaddie_set_state(actor, 4); -} - // Fast Transformation — speeds up Mumbo transformation animation by 3x void RegisterFastTransform_Init() { COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), [](IEvent* event) { @@ -302,27 +248,6 @@ void RegisterFastTransform_Init() { } } }); - - // Hut transforms ignore that timer; Mumbo's state 5 paces off his own 7.5s animation instead. - COND_VB_SHOULD(VB_MUMBO_HUT_TRANSFORM_CUTSCENE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), { - Actor* actor = va_arg(args, Actor*); - // T-Rex/mistake gags end in a dialog wired to a callback private to mumbo.c. - if (actor != nullptr && !actor->has_met_before) { - // Only latch once the spell has been accepted. Gags don't count as valid. - if (!sMumboFastXformStarted) { - sMumboFastXformStarted = FastTransform_startHutTransform(actor); - } else if (!baflag_isTrue(BA_FLAG_1B_TRANSFORMING)) { - // Safe to read as "the transformation ended" only because of the latch above. - sMumboFastXformStarted = false; - FastTransform_endHutTransform(actor); - } - *should = false; - } - }); - - // A map torn down mid-transform would leave the next one thinking it had already run. - COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), - [](IEvent* event) { sMumboFastXformStarted = false; }); } // ============================================================================ @@ -331,8 +256,12 @@ void RegisterFastTransform_Init() { // Disable Mumbo untransform when going too far void RegisterNoMumboUntransform_Init() { - COND_VB_SHOULD(VB_MUMBO_DETRANSFORM, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_MUMBO_UNTRANSFORM, 0), - { *should = false; }); + COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_MUMBO_UNTRANSFORM, 0), [](IEvent* event) { + // Prevent Mumbo from triggering untransform dialog/warn + // These functions check game state and show dialog + // We disable them by setting a flag they check + volatileFlag_set((enum volatile_flags_e)207, 1); // Prevents detransform warning + }); } // ============================================================================ diff --git a/src/port/Enhancements/Cosmetics/PlayerColors.cpp b/src/port/Enhancements/Cosmetics/PlayerColors.cpp deleted file mode 100644 index e625e0971..000000000 --- a/src/port/Enhancements/Cosmetics/PlayerColors.cpp +++ /dev/null @@ -1,480 +0,0 @@ -#include "PlayerColors.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "port/UI/cvar_prefixes.h" - -extern "C" { -#include "model.h" -#include "enums.h" -#include "core2/modelRender.h" -s32 port_anchor_isConnected(void); -} - -namespace { - -// --------------------------------------------------------------------------- -// Part tables -// -// Derived from the two player model bins: every CI4 texture and every distinct -// vertex colour was attributed to a bone (via the geo layout) and to a body -// region, then grouped by part. Textures are listed per model because the -// low- and high-poly bins have different texture counts and orderings. -// --------------------------------------------------------------------------- - -struct ChannelInfo { - u8 vanilla[3]; - float minSaturation; - float minHueDeg, maxHueDeg; -}; - -const ChannelInfo kChannels[] = { - /* BANJO_FUR */ { { 0x83, 0x32, 0x03 }, 0.50f, 5.0f, 50.0f }, - /* BANJO_SHORTS */ { { 0xFF, 0xF6, 0x20 }, 0.50f, 0.0f, 70.0f }, - /* KAZOOIE_FEATHERS */ { { 0xF6, 0x10, 0x00 }, 0.50f, 0.0f, 70.0f }, - /* KAZOOIE_BEAK */ { { 0xFE, 0xA1, 0x31 }, 0.12f, 0.0f, 70.0f }, - /* BANJO_BACKPACK */ { { 0x00, 0x4A, 0xE0 }, 0.35f, 190.0f, 250.0f }, - /* BANJO_SKIN */ { { 0xEB, 0x83, 0x6D }, 0.15f, 0.0f, 60.0f }, -}; - -struct TextureTable { - const s16* index; - s32 count; -}; - -// ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY -const s16 kLowFur[] = { 12, 13, 15, 18 }; -const s16 kLowShorts[] = { 5, 6 }; -const s16 kLowFeathers[] = { 14 }; -const s16 kLowBeak[] = { 19, 20 }; -const s16 kLowSkin[] = { 2, 7 }; - -// ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY -const s16 kHighFur[] = { 13, 14, 16, 19 }; -const s16 kHighShorts[] = { 6, 7 }; -const s16 kHighFeathers[] = { 15 }; -const s16 kHighBeak[] = { 20, 21 }; -const s16 kHighSkin[] = { 3, 8 }; - -#define TEXTABLE(array) \ - { array, (s32)(sizeof(array) / sizeof((array)[0])) } - -// The backpack is shaded entirely by vertex colour. The only blue palettes in -// the model belong to the eyes and Banjo's claws, which must stay put. -const TextureTable kLowTextures[] = { TEXTABLE(kLowFur), TEXTABLE(kLowShorts), TEXTABLE(kLowFeathers), - TEXTABLE(kLowBeak), { nullptr, 0 }, TEXTABLE(kLowSkin) }; -const TextureTable kHighTextures[] = { TEXTABLE(kHighFur), TEXTABLE(kHighShorts), TEXTABLE(kHighFeathers), - TEXTABLE(kHighBeak), { nullptr, 0 }, TEXTABLE(kHighSkin) }; - -#undef TEXTABLE - -const u32 kFurVerts[] = { 0xFA6F12, 0xCC560B, 0xAE4707, 0x833203, 0x632501, 0x411700, 0x270E00 }; -const u32 kShortsVerts[] = { 0xFFFF28, 0xEAEA00, 0xF6B400, 0xCE8700, 0xBA5500, 0x874708 }; -const u32 kFeatherVerts[] = { 0xFF3300, 0xD00000, 0x880000, 0x520000, 0xFF5F00, 0xFF8900 }; -const u32 kBeakVerts[] = { 0xFFFF9F, 0xFFCF3D, 0xFFC700, 0xFEA131, 0xBA7F4B, 0x923900, 0xC74700, 0x662300 }; -const u32 kBackpackVerts[] = { 0x7FA9FF, 0x558DFF, 0x2B71FF, 0x004AE0, 0x003092, 0x002268, 0x001A4E }; -const u32 kSkinVerts[] = { 0xFFEAB4, 0xFFBE97, 0xFFA385, 0xEB836D, 0xC66E5C, 0x995447, 0x66372F, 0x45251F }; - -struct VertexTable { - const u32* color; - s32 count; -}; - -#define VTXTABLE(array) \ - { array, (s32)(sizeof(array) / sizeof((array)[0])) } -const VertexTable kVertexTables[] = { VTXTABLE(kFurVerts), VTXTABLE(kShortsVerts), VTXTABLE(kFeatherVerts), - VTXTABLE(kBeakVerts), VTXTABLE(kBackpackVerts), VTXTABLE(kSkinVerts) }; -#undef VTXTABLE - -// --------------------------------------------------------------------------- -// Color math -// --------------------------------------------------------------------------- - -struct Hsv { - float hue; // degrees, 0..360 - float saturation, value; -}; - -Hsv ToHsv(float red, float green, float blue) { - const float maxComponent = std::max({ red, green, blue }); - const float minComponent = std::min({ red, green, blue }); - const float chroma = maxComponent - minComponent; - Hsv hsv{ 0.0f, maxComponent > 0.0f ? chroma / maxComponent : 0.0f, maxComponent }; - if (chroma > 0.0f) { - if (maxComponent == red) { - hsv.hue = 60.0f * std::fmod((green - blue) / chroma, 6.0f); - } else if (maxComponent == green) { - hsv.hue = 60.0f * (((blue - red) / chroma) + 2.0f); - } else { - hsv.hue = 60.0f * (((red - green) / chroma) + 4.0f); - } - if (hsv.hue < 0.0f) { - hsv.hue += 360.0f; - } - } - return hsv; -} - -void FromHsv(const Hsv& hsv, float* red, float* green, float* blue) { - const float chroma = hsv.value * hsv.saturation; - const float sector = std::fmod(std::fmod(hsv.hue, 360.0f) + 360.0f, 360.0f) / 60.0f; - const float ramp = chroma * (1.0f - std::fabs(std::fmod(sector, 2.0f) - 1.0f)); - float highest = 0.0f, middle = 0.0f, lowest = 0.0f; - switch ((int)sector) { - case 0: - highest = chroma; - middle = ramp; - break; - case 1: - highest = ramp; - middle = chroma; - break; - case 2: - middle = chroma; - lowest = ramp; - break; - case 3: - middle = ramp; - lowest = chroma; - break; - case 4: - highest = ramp; - lowest = chroma; - break; - default: - highest = chroma; - lowest = ramp; - break; - } - const float offset = hsv.value - chroma; - *red = highest + offset; - *green = middle + offset; - *blue = lowest + offset; -} - -float Clamp01(float value) { - return value < 0.0f ? 0.0f : (value > 1.0f ? 1.0f : value); -} - -// Re-tints one source colour so the channel's vanilla colour lands exactly on `target` and -// every other shade of the part keeps its position in the shading ramp. -void Recolor(const ChannelInfo& channel, const BKColorChannelSetting& target, u8 sourceRed, u8 sourceGreen, - u8 sourceBlue, u8* outRed, u8* outGreen, u8* outBlue) { - const Hsv source = ToHsv(sourceRed / 255.0f, sourceGreen / 255.0f, sourceBlue / 255.0f); - const Hsv vanilla = ToHsv(channel.vanilla[0] / 255.0f, channel.vanilla[1] / 255.0f, channel.vanilla[2] / 255.0f); - const Hsv chosen = ToHsv(target.r / 255.0f, target.g / 255.0f, target.b / 255.0f); - - float hueOffset = source.hue - vanilla.hue; - while (hueOffset > 180.0f) { - hueOffset -= 360.0f; - } - while (hueOffset < -180.0f) { - hueOffset += 360.0f; - } - const float rampPosition = std::min(std::fabs(hueOffset), 45.0f) / 45.0f; - - Hsv result; - result.hue = chosen.hue + (hueOffset < 0.0f ? -1.0f : 1.0f) * rampPosition * 8.0f; - result.saturation = - vanilla.saturation > 0.001f ? chosen.saturation * (source.saturation / vanilla.saturation) : chosen.saturation; - result.value = vanilla.value > 0.001f ? chosen.value * (source.value / vanilla.value) : chosen.value; - result.saturation = Clamp01(result.saturation * (1.0f - 0.55f * rampPosition)); - result.value = Clamp01(result.value * (1.0f + 0.55f * rampPosition)); - - float red, green, blue; - FromHsv(result, &red, &green, &blue); - *outRed = (u8)std::lround(Clamp01(red) * 255.0f); - *outGreen = (u8)std::lround(Clamp01(green) * 255.0f); - *outBlue = (u8)std::lround(Clamp01(blue) * 255.0f); -} - -bool PassesFilter(const ChannelInfo& channel, u8 red, u8 green, u8 blue) { - const Hsv hsv = ToHsv(red / 255.0f, green / 255.0f, blue / 255.0f); - if (hsv.value <= 0.0f || hsv.saturation < channel.minSaturation) { - return false; - } - return hsv.hue >= channel.minHueDeg && hsv.hue <= channel.maxHueDeg; -} - -// --------------------------------------------------------------------------- -// Per-owner recolored copies -// --------------------------------------------------------------------------- - -constexpr size_t kPaletteArenaWords = 128 * 1024; // 1 MiB - -void* PaletteArenaTake(size_t bytes) { - static std::unique_ptr arena; - static size_t usedWords = 0; - - const size_t wordCount = (bytes + 7) / 8; - if (wordCount > kPaletteArenaWords) { - return nullptr; - } - if (arena == nullptr) { - arena = std::make_unique(kPaletteArenaWords); - } - if (usedWords + wordCount > kPaletteArenaWords) { - usedWords = 0; - } - u64* region = arena.get() + usedWords; - usedWords += wordCount; - return region; -} - -struct Variant { - const void* sourceBin = nullptr; - u64 colorHash = 0; - // Palettes live in the ring arena above; vertices are read fresh every draw and are not - // cached by address, so they can be rebuilt in place. - void* textures = nullptr; - std::unique_ptr vertices; -}; - -std::unordered_map sVariants; - -u64 VariantKey(u32 ownerKey, s32 modelId) { - return ((u64)ownerKey << 32) | (u32)modelId; -} - -u64 HashColors(const BKPlayerColorSet& colors) { - u64 hash = 1469598103934665603ull; - const u8* bytes = (const u8*)&colors; - for (size_t index = 0; index < sizeof(colors); index++) { - hash = (hash ^ bytes[index]) * 1099511628211ull; - } - return hash; -} - -bool AnyEnabled(const BKPlayerColorSet& colors) { - for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { - if (colors.channel[channelIndex].enabled) { - return true; - } - } - return false; -} - -const TextureTable* TexturesForModel(s32 modelId) { - switch (modelId) { - case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: - return kLowTextures; - case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: - return kHighTextures; - default: - return nullptr; - } -} - -void RecolorTextures(void* textureBlob, const TextureTable* textureTable, const BKPlayerColorSet& colors) { - BKTextureList* textureList = (BKTextureList*)textureBlob; - u8* pixelBase = (u8*)textureList + sizeof(BKTextureList) + (size_t)textureList->count * sizeof(BKTextureInfo); - - for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { - if (!colors.channel[channelIndex].enabled) { - continue; - } - const ChannelInfo& channel = kChannels[channelIndex]; - for (s32 entry = 0; entry < textureTable[channelIndex].count; entry++) { - const s16 textureIndex = textureTable[channelIndex].index[entry]; - if (textureIndex < 0 || textureIndex >= textureList->count) { - continue; - } - BKTextureInfo* texture = &textureList->texture_infos[textureIndex]; - const s32 paletteBytes = textureInfo_getPaletteSize(texture); - if (paletteBytes <= 0) { - continue; - } - if ((size_t)texture->offset + (size_t)paletteBytes > (size_t)textureList->size) { - continue; - } - // TLUT entries are big-endian RGBA5551, matching what the RDP (and Fast3D's - // CI4 importer) reads out of DRAM. - u8* palette = pixelBase + texture->offset; - for (s32 paletteEntry = 0; paletteEntry < paletteBytes / 2; paletteEntry++) { - const u16 packedColor = (u16)((palette[paletteEntry * 2] << 8) | palette[paletteEntry * 2 + 1]); - const u8 red = (u8)(((packedColor >> 11) & 0x1F) * 255 / 31); - const u8 green = (u8)(((packedColor >> 6) & 0x1F) * 255 / 31); - const u8 blue = (u8)(((packedColor >> 1) & 0x1F) * 255 / 31); - if (!PassesFilter(channel, red, green, blue)) { - continue; - } - u8 newRed, newGreen, newBlue; - Recolor(channel, colors.channel[channelIndex], red, green, blue, &newRed, &newGreen, &newBlue); - const u16 recolored = (u16)(((newRed * 31 / 255) << 11) | ((newGreen * 31 / 255) << 6) | - ((newBlue * 31 / 255) << 1) | (packedColor & 1)); - palette[paletteEntry * 2] = (u8)(recolored >> 8); - palette[paletteEntry * 2 + 1] = (u8)(recolored & 0xFF); - } - } - } -} - -void RecolorVertices(void* vertexBlob, const BKPlayerColorSet& colors) { - BKVertexList* vertexList = (BKVertexList*)vertexBlob; - Vtx* vertices = vertexList->vertices; - const s32 vertexCount = vertexList->count; - - for (s32 vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { - Vtx_t& vertex = vertices[vertexIndex].v; - const u32 packedColor = ((u32)vertex.cn[0] << 16) | ((u32)vertex.cn[1] << 8) | (u32)vertex.cn[2]; - for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { - if (!colors.channel[channelIndex].enabled) { - continue; - } - const VertexTable& vertexColors = kVertexTables[channelIndex]; - bool matched = false; - for (s32 entry = 0; entry < vertexColors.count; entry++) { - if (vertexColors.color[entry] == packedColor) { - matched = true; - break; - } - } - if (!matched) { - continue; - } - u8 newRed, newGreen, newBlue; - Recolor(kChannels[channelIndex], colors.channel[channelIndex], vertex.cn[0], vertex.cn[1], vertex.cn[2], - &newRed, &newGreen, &newBlue); - vertex.cn[0] = newRed; - vertex.cn[1] = newGreen; - vertex.cn[2] = newBlue; - break; - } - } -} - -Variant* BuildVariant(u32 ownerKey, s32 modelId, BKModelBin* modelBin, const BKPlayerColorSet& colors) { - const TextureTable* textureTable = TexturesForModel(modelId); - if (textureTable == nullptr || modelBin == nullptr || modelBin->texture_list_offset == 0 || - modelBin->vtx_list_offset == 0) { - return nullptr; - } - - Variant& variant = sVariants[VariantKey(ownerKey, modelId)]; - const u64 colorHash = HashColors(colors); - if (variant.sourceBin == modelBin && variant.colorHash == colorHash && variant.textures != nullptr) { - return &variant; - } - - const BKTextureList* sourceTextures = modelbin_getTextureList(modelBin); - const BKVertexList* sourceVertices = modelbin_getVtxList(modelBin); - if (sourceTextures == nullptr || sourceVertices == nullptr) { - return nullptr; - } - - const size_t textureBytes = - sizeof(BKTextureList) + (size_t)sourceTextures->count * sizeof(BKTextureInfo) + (size_t)sourceTextures->size; - const size_t vertexBytes = sizeof(BKVertexList) + (size_t)sourceVertices->count * sizeof(Vtx); - - void* textures = PaletteArenaTake(textureBytes); - if (textures == nullptr) { - return nullptr; - } - std::memcpy(textures, sourceTextures, textureBytes); - - variant.vertices = std::make_unique((vertexBytes + 7) / 8); - std::memcpy(variant.vertices.get(), sourceVertices, vertexBytes); - - variant.sourceBin = modelBin; - variant.colorHash = colorHash; - variant.textures = textures; - - RecolorTextures(variant.textures, textureTable, colors); - RecolorVertices(variant.vertices.get(), colors); - return &variant; -} - -const char* kChannelCVars[] = { - CVAR_REMOTE_ANCHOR("Colors.BanjoFur"), CVAR_REMOTE_ANCHOR("Colors.BanjoShorts"), - CVAR_REMOTE_ANCHOR("Colors.KazooieFeathers"), CVAR_REMOTE_ANCHOR("Colors.KazooieBeak"), - CVAR_REMOTE_ANCHOR("Colors.BanjoBackpack"), CVAR_REMOTE_ANCHOR("Colors.BanjoSkin"), -}; - -#define CHANNEL_TABLE_COMPLETE(table) \ - static_assert(sizeof(table) / sizeof((table)[0]) == BK_COLOR_CHANNEL_COUNT, #table) -CHANNEL_TABLE_COMPLETE(kChannelCVars); -CHANNEL_TABLE_COMPLETE(kChannels); -CHANNEL_TABLE_COMPLETE(kVertexTables); -CHANNEL_TABLE_COMPLETE(kLowTextures); -CHANNEL_TABLE_COMPLETE(kHighTextures); -#undef CHANNEL_TABLE_COMPLETE - -} // namespace - -extern "C" { - -const char* PlayerColors_getChannelCVar(s32 channel) { - if (channel < 0 || channel >= BK_COLOR_CHANNEL_COUNT) { - return nullptr; - } - return kChannelCVars[channel]; -} - -void PlayerColors_getVanilla(s32 channel, u8* red, u8* green, u8* blue) { - if (channel < 0 || channel >= BK_COLOR_CHANNEL_COUNT) { - return; - } - *red = kChannels[channel].vanilla[0]; - *green = kChannels[channel].vanilla[1]; - *blue = kChannels[channel].vanilla[2]; -} - -void PlayerColors_getLocal(BKPlayerColorSet* out) { - if (out == nullptr) { - return; - } - for (int channelIndex = 0; channelIndex < BK_COLOR_CHANNEL_COUNT; channelIndex++) { - const ChannelInfo& channel = kChannels[channelIndex]; - const std::string valueCVar = std::string(kChannelCVars[channelIndex]) + ".Value"; - const std::string enabledCVar = std::string(kChannelCVars[channelIndex]) + ".Enabled"; - const Color_RGBA8 vanilla = { channel.vanilla[0], channel.vanilla[1], channel.vanilla[2], 255 }; - const Color_RGBA8 chosen = CVarGetColor(valueCVar.c_str(), vanilla); - out->channel[channelIndex].enabled = CVarGetInteger(enabledCVar.c_str(), 0) ? 1 : 0; - out->channel[channelIndex].r = chosen.r; - out->channel[channelIndex].g = chosen.g; - out->channel[channelIndex].b = chosen.b; - } -} - -void PlayerColors_applyForDraw(u32 ownerKey, s32 modelId, void* modelBin, const BKPlayerColorSet* colors) { - if (!port_anchor_isConnected()) { - return; - } - if (colors == nullptr || modelBin == nullptr || !AnyEnabled(*colors)) { - return; - } - Variant* variant = BuildVariant(ownerKey, modelId, (BKModelBin*)modelBin, *colors); - if (variant == nullptr) { - return; - } - modelRender_setTextureList((BKTextureList*)variant->textures); - modelRender_setVertexList((BKVertexList*)variant->vertices.get()); -} - -void PlayerColors_applyLocalForDraw(s32 modelId, void* modelBin) { - if (TexturesForModel(modelId) == nullptr) { - return; - } - BKPlayerColorSet colors; - PlayerColors_getLocal(&colors); - PlayerColors_applyForDraw(BK_COLORS_LOCAL_OWNER, modelId, modelBin, &colors); -} - -void PlayerColors_forgetOwner(u32 ownerKey) { - for (auto entry = sVariants.begin(); entry != sVariants.end();) { - entry = ((u32)(entry->first >> 32) == ownerKey) ? sVariants.erase(entry) : std::next(entry); - } -} - -void PlayerColors_reset(void) { - sVariants.clear(); -} - -} // extern "C" diff --git a/src/port/Enhancements/Cosmetics/PlayerColors.h b/src/port/Enhancements/Cosmetics/PlayerColors.h deleted file mode 100644 index c7aae365c..000000000 --- a/src/port/Enhancements/Cosmetics/PlayerColors.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef PORT_ENHANCEMENTS_COSMETICS_PLAYERCOLORS_H -#define PORT_ENHANCEMENTS_COSMETICS_PLAYERCOLORS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - BK_COLOR_BANJO_FUR = 0, - BK_COLOR_BANJO_SHORTS, - BK_COLOR_KAZOOIE_FEATHERS, - BK_COLOR_KAZOOIE_BEAK, - BK_COLOR_BANJO_BACKPACK, - BK_COLOR_BANJO_SKIN, - BK_COLOR_CHANNEL_COUNT -} BKColorChannel; - -typedef struct { - u8 enabled; - u8 r, g, b; -} BKColorChannelSetting; - -typedef struct { - BKColorChannelSetting channel[BK_COLOR_CHANNEL_COUNT]; -} BKPlayerColorSet; - -#define BK_COLORS_LOCAL_OWNER 0u - -void PlayerColors_getVanilla(s32 channel, u8* red, u8* green, u8* blue); -const char* PlayerColors_getChannelCVar(s32 channel); -void PlayerColors_applyForDraw(u32 ownerKey, s32 modelId, void* modelBin, const BKPlayerColorSet* colors); -void PlayerColors_applyLocalForDraw(s32 modelId, void* modelBin); -void PlayerColors_getLocal(BKPlayerColorSet* out); -void PlayerColors_forgetOwner(u32 ownerKey); -void PlayerColors_reset(void); - -#ifdef __cplusplus -} -#endif - -#endif /* PORT_ENHANCEMENTS_COSMETICS_PLAYERCOLORS_H */ diff --git a/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp b/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp index 3d32eea8d..b22e94f9b 100644 --- a/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp +++ b/src/port/Enhancements/Cutscenes/CutsceneSkips.cpp @@ -15,15 +15,12 @@ enum level_e level_get(void); int volatileFlag_get(enum volatile_flags_e index); int func_8028F070(void); void gcparade_beginFFParade(void); -void baflag_clear(enum misc_flag_e arg0); -void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume); } #define CVAR_SKIP_BOOT_LOGOS CVAR_ENHANCEMENT("Cutscenes.SkipBootLogos") #define CVAR_SKIP_INTRO CVAR_ENHANCEMENT("Cutscenes.StartSkipIntro") #define CVAR_SKIP_MISC_CUTSCENES CVAR_ENHANCEMENT("Cutscenes.SkipMiscCutscenes") #define CVAR_SKIP_CLUCKER_CUTSCENE CVAR_ENHANCEMENT("Cutscenes.SkipCluckerCutscene") -#define CVAR_SKIP_NOTEDOOR_DANCE CVAR_ENHANCEMENT("Cutscenes.SkipNoteDoorDance") #define CVAR_TRIGGER_FF_PARADE CVAR_DEVELOPER_TOOLS("TriggerFFParade") void RegisterSkipBootLogos_Init() { @@ -55,16 +52,6 @@ void RegisterSkipCluckerCutscene_Init() { }); } -void RegisterSkipNoteDoorDance_Init() { - COND_VB_SHOULD(VB_PLAY_NOTEDOOR_DANCE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_SKIP_NOTEDOOR_DANCE, 0), { - // Clear the flag so the (per-frame) state check doesn't retrigger, and still play the - // opening fanfare so the door-opened cue is preserved, then skip the dance state. - baflag_clear(BA_FLAG_1A_OPEN_NOTEDOOR); - // coMusicPlayer_playMusic(COMUSIC_42_NOTEDOOR_OPENING_FANFARE, -1); - *should = false; - }); -} - void RegisterTriggerFFParade_Init() { COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_TRIGGER_FF_PARADE, 0), [](IEvent* event) { if (getGameMode() != GAME_MODE_3_NORMAL || level_get() <= 0 || !func_8028F070()) { @@ -83,5 +70,4 @@ static RegisterShipInitFunc initSkipIntroFunc(RegisterSkipIntroCutscene_Init, { static RegisterShipInitFunc initSkipMiscCutscenesFunc(RegisterSkipMiscCutscenes_Init, { CVAR_SKIP_MISC_CUTSCENES }); static RegisterShipInitFunc initSkipCluckerCutsceneFunc(RegisterSkipCluckerCutscene_Init, { CVAR_SKIP_CLUCKER_CUTSCENE }); -static RegisterShipInitFunc initSkipNoteDoorDanceFunc(RegisterSkipNoteDoorDance_Init, { CVAR_SKIP_NOTEDOOR_DANCE }); static RegisterShipInitFunc initTriggerFFParadeFunc(RegisterTriggerFFParade_Init, { CVAR_TRIGGER_FF_PARADE }); diff --git a/src/port/Enhancements/Cutscenes/IntroLogos.cpp b/src/port/Enhancements/Cutscenes/IntroLogos.cpp deleted file mode 100644 index 7ff2ec4f0..000000000 --- a/src/port/Enhancements/Cutscenes/IntroLogos.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include - -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" -#include "port/UI/cvar_prefixes.h" -#include "port/UI/enhancementTypes.h" - -#include - -extern "C" { -#include "enums.h" -int port_getBootSequence(void); -void ResourceMgr_RegisterAssetOverride(uint32_t assetId, const char* customPath); -} - -namespace { - -constexpr const char* kXylophoneNintendoTex = "assets/model/ASSET_3B1_UNNAMED_tex_6"; -constexpr const char* kXylophoneReplacementTex = "textures/intro/xylophone"; -constexpr const char* kIntroCubeReplacementModel = "models/lighthouse"; -constexpr uint32_t kAssetNintendoWalkAnim = 0x8F; -constexpr uint32_t kAssetNintendoShrugAnim = 0x90; -constexpr const char* kIntroCubeWalkAnim = "anim/lighthouse_walk"; -constexpr const char* kIntroCubeShrugAnim = "anim/lighthouse_shrug"; - -bool bootSequenceIsDefault() { - return port_getBootSequence() == BOOTSEQUENCE_DEFAULT; -} - -void stripXylophoneNintendoLogo() { - auto& rm = *Ship::Context::GetRawInstance()->GetResourceManager(); - if (!rm.GetArchiveManager()->HasFile(kXylophoneReplacementTex)) { - return; - } - auto replacement = rm.LoadResource(kXylophoneReplacementTex); - if (replacement != nullptr && std::static_pointer_cast(replacement)->ImageData != nullptr) { - rm.CacheExternalResource(kXylophoneNintendoTex, replacement); - } -} - -} // namespace - -void RegisterIntroLogos_Init() { - COND_HOOK(OnMapLoad, EVENT_PRIORITY_NORMAL, bootSequenceIsDefault(), [](IEvent* event) { - auto* ev = (OnMapLoad*)event; - ResourceMgr_RegisterAssetOverride(ASSET_3A6_MODEL_INTRO_N64_CUBE, kIntroCubeReplacementModel); - ResourceMgr_RegisterAssetOverride(kAssetNintendoWalkAnim, kIntroCubeWalkAnim); - ResourceMgr_RegisterAssetOverride(kAssetNintendoShrugAnim, kIntroCubeShrugAnim); - - if (ev->nextMap == MAP_1E_CS_START_NINTENDO || ev->nextMap == MAP_1F_CS_START_RAREWARE) { - stripXylophoneNintendoLogo(); - } - }); -} - -static RegisterShipInitFunc introLogosInit(RegisterIntroLogos_Init, { CVAR_SETTING("BootSequence") }); diff --git a/src/port/Enhancements/Events/Hooks/Events.h b/src/port/Enhancements/Events/Hooks/Events.h index fe10572df..2e6699ded 100644 --- a/src/port/Enhancements/Events/Hooks/Events.h +++ b/src/port/Enhancements/Events/Hooks/Events.h @@ -6,30 +6,19 @@ #include -// Grouped by the system that listens for them. Nothing depends on the numeric values -- -// every reference is by name at compile time and none are serialized -- so ids can be -// added to the group they belong to rather than to the end. typedef enum VBehaviorID { - // Return to Lair restoration, and the pause-menu adjustments VB_INIT_RETURN_TO_LAIR, VB_PAUSE_MENU_PORTRAIT_DEPTH, VB_ZOOMBOX_TEXT_ADJUST, // text scale (shrink pause text) + X nudge (JP kana clearance) - - // Camera behavior VB_STATIC_CAMERA_SET, VB_STATIC_CAMERA_EXIT, VB_CAMERA_LIVE_ASPECT, VB_CAMERA_FOLLOW, - VB_CAMERA_APPLY_SHAKE, - - // Cutscene and celebration skips + VB_GRUNTY_DEFEATED_FLAG_BOSS, + VB_PLAY_JIGGY_DANCE, VB_PLAY_BOOT_LOGOS, VB_PLAY_INTRO_CUTSCENE, - VB_PLAY_JIGGY_DANCE, - VB_PLAY_NOTEDOOR_DANCE, - - // Vanilla bug fixes and corrections - VB_GRUNTY_DEFEATED_FLAG_BOSS, + VB_DISABLE_SNACKER, VB_VOID_OUT_GAME_OVER, VB_CCW_GNAWTY_SPRING_ROCK, VB_CCW_FLOWER_REPLANT, @@ -37,100 +26,32 @@ typedef enum VBehaviorID { VB_CLAW_SWIPE_SLIDE, VB_BOGGY_RACE_GAME_OVER, VB_JINJO_CHARGE_SOUND, - VB_ENEMY_BECOME_BUNDLE, VB_YUMYUM_DROP, - VB_MM_CHIMPY_STUMP_RUMBLE, - VB_MM_CHIMPY_NOISE, - VB_SPLINE_PATH_SFX, - VB_MAP_SAVESTATE_USE, - - // Gameplay options and cheats - VB_DISABLE_SNACKER, - VB_SAVE_AND_EXIT, - VB_MUMBO_HUT_TRANSFORM_CUTSCENE, - VB_MUMBO_DETRANSFORM, - - // Rando object behavior VB_OVERRIDE_BOTTLES_TEXT_CALLBACK, VB_OVERRIDE_MOLEHILL_ABILITY, VB_OVERRIDE_JIGGY_SPAWN, VB_OVERRIDE_PROP_SPAWN, VB_OVERRIDE_BUNDLE_SPAWN, - VB_BUNDLE_SPAWN_SET_ACTOR_DATA, - VB_NAPPER_SET_JIGGY_POSITION, VB_OVERRIDE_SNS_MAP_CHECK, VB_OVERRIDE_TIMED_DIALOGUE, + VB_ENEMY_BECOME_BUNDLE, VB_UPDATE_JINJO_HUD, VB_SET_JINJO_COUNT, - - // Dialog and localization + VB_BUNDLE_SPAWN_SET_ACTOR_DATA, + VB_NAPPER_SET_JIGGY_POSITION, VB_RESET_DIALOG_LANGUAGE, + // Cancellable at the single dialog choke point (gcdialog_showDialogConditional). + // Listeners receive the dialog's text_id; returning should=true suppresses the popup. VB_OVERRIDE_DIALOG_SHOW, - - // Rendering and performance - VB_CUBE_PROP_SORT, - VB_GCLIGHTS_RECOLOR, - VB_SNOW_CAMERA_ROTATION, - VB_SNOW_RENDER_STATE, - VB_MODEL_DRAWDIST_FADE_ALPHA, - VB_SPRITE_RESTORE_ALPHA_COMPARE, - VB_DRAWDIST_BOX_CULL, - VB_PICTUREBOX_TARGET_FB, - VB_PICTUREBOX_SUBMIT_FRAME, - - // Anchor + // Mr. Vile minigame (Anchor authority gating): cancelled on clients following a + // remote authority so local random logic yields to network state. VB_VILE_YUMBLIE_EMERGE, VB_VILE_YUMBLIE_HIDE, VB_VILE_PLAYER_EAT_PIECE, VB_VILE_GAME_UPDATE, VB_VILE_CPU_AI, - VB_CCW_FLOWER_REMOTE_GROW, // Lets a remotely-watered CCW flower grow without local camera/fanfare/jiggy. - VB_FP_TWINKLY_START, // Gates FP twinkly minigame start so only one client owns a run at a time. - VB_SM_TUTORIAL_CHOICE_OPEN, // True while the SM tutorial choice is still open to the local player. - VB_SM_MOLEHILL_ACTIVE, // SM ability molehills stay inert until the tutorial choice is made. - VB_DOOR_OPEN_CAMERA, // Suppresses door-open camera lock when the flag came from a teammate, not us. - VB_CC_RINGS_SNAP_WATER, // CC rings water snap on run teardown: suppressed when a teammate finished the rings. - VB_LEVELDOOR_REMOTE_OPEN_DONE, // Lair door remote-open "already handled" test. - VB_CCW_PODIUM_DESPAWN, // Despawn the unrevealed CCW puzzle podium: suppressed so a teammate's switch press can - // reveal it live. - VB_JIGSAW_PICTURE_RESYNC, // Rebuild a lair podium's cached piece state when the synced flags disagree with it. - - // Romhack port gates - VB_JIGGYSCORE_LEVEL_TOTAL, - VB_PAUSEMENU_LEVEL_TO_PAGE, - VB_PAUSEMENU_SET_NEXT_PAGE, - VB_PAUSEMENU_DRAW_JOYSTICKS, - VB_PAUSEMENU_BOLD_FONT_TEXTURE, - VB_PAUSEMENU_LEVEL_NAME_X, - VB_PAUSEMENU_ROW_VISIBLE, - VB_MAP_CHANGE_REQUEST, - VB_MAP_TRANSITION_IN_INDEX, - VB_VOID_OUT_RESPAWN_TRANSITION, - VB_EGG_FIRE_SFX, - VB_WARP_KEEPS_MUSIC, - VB_BUMP_REBOUNDS_PLAYER, - VB_WARP_DISPATCH, - VB_GAMESELECT_START_NEW_GAME, - VB_NOTEDOOR_DRAW_NUMBER, - VB_JIGGY_COLLECT_TUTORIAL, - VB_HONEYCOMB_PUMPKIN_REQUIREMENT, // also read by rando - VB_BRENTILDA_HEAL_DIALOG, - VB_SKY_UPDATE, - VB_SKY_DRAW_BACKDROP_RECT, - VB_GROUND_HAZARD_ACTIVE, - VB_CCW_SEASON_SWITCH_PRESSED_INIT, - VB_XMAS_TREE_ICE_UPDATE, - VB_BOGGY_HOME_VISIBLE, } VBehaviorID; -typedef enum DoorCameraId { - GV_DOOR_CAM_SUN, // sun switch (flag 3) - GV_DOOR_CAM_STAR, // star switch / trapdoor (flag 5) - GV_DOOR_CAM_KAZOOIE, // beak-bomb door (flag 6) - GV_DOOR_CAM_JINXY, // Jinxy sneeze (flags 0, 1) - MMM_DOOR_CAM_CHURCH, // church door, Tumblar challenge (flag 0) -} DoorCameraId; - DEFINE_EVENT(VanillaBehavior, VBehaviorID id; bool* should; va_list * originalArgs;); #ifdef __cplusplus diff --git a/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h b/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h index 458e9073c..2d43b2418 100644 --- a/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/BehaviorEvent.h @@ -20,7 +20,6 @@ DEFINE_EVENT(OnGruntyJinjonatorComplete) DEFINE_EVENT(OnIntroCutsceneCheck, bool* skipIntro;) DEFINE_EVENT(OnMiscCutscenesCheck, bool* skipMiscCutscenes;) DEFINE_EVENT(OnTooieJiggyCollect, f32* position;) -DEFINE_EVENT(OnJigsawPodiumInput, s32 podiumId;) DEFINE_EVENT(OnMumboTokenUpdate, Actor* actor;) DEFINE_EVENT(OnMumboTokenIdResolve, s32* tokenId; s32 * position; s32 mapId;) DEFINE_EVENT(OnPlayerAnimChange, AssetID anim_id; f32 duration; AnimControl control; f32 start_position; diff --git a/src/port/Enhancements/Events/Hooks/List/EngineEvent.h b/src/port/Enhancements/Events/Hooks/List/EngineEvent.h index 20cdb1dfc..b01226a3b 100644 --- a/src/port/Enhancements/Events/Hooks/List/EngineEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/EngineEvent.h @@ -14,22 +14,12 @@ extern "C" { DEFINE_EVENT(GameFrameUpdate); DEFINE_EVENT(FrameDrawEnd); -DEFINE_EVENT(OnControllerUpdate); DEFINE_EVENT(OnMapLoad, GameMap prevMap; GameMap nextMap; s32 exit;); DEFINE_EVENT(OnDialogLoaded, s32 textId; char* text;); DEFINE_EVENT(OnModelLoad, s32 modelId; void* modelInfo; s32 * reload;); - -// Declared texture dimensions from a model's BKTextureInfo table. -typedef struct { - u8 width; - u8 height; -} ModelTexSize; - -DEFINE_EVENT(OnModelDisplayListLoad, const char* path; u32 * dlWords; u32 dlWordCount; const ModelTexSize* texSizes; - u16 texCount;); DEFINE_EVENT(ViewportFrustumUpdate, float* frustumX; float* frustumY;); DEFINE_EVENT(OnTransitionModelScale, Gfx** gfx; Mtx * *mtx; s32 uid; f32 * scale;); DEFINE_EVENT(OnTransitionStateUpdate, s32 modelId; s32 uid; s32 substate;); @@ -54,5 +44,4 @@ DEFINE_EVENT(ParadeCreditDialogId, int32_t index; int32_t * dialogId;); DEFINE_EVENT(ResolveBoldFontSlot, int32_t* slot; int32_t * letterId;); DEFINE_EVENT(OnWorldDraw, Gfx** gfx; Mtx * *mtx; Vtx * *vtx;); DEFINE_EVENT(OnPlayerDraw, Gfx** gfx; Mtx * *mtx; Vtx * *vtx;); -DEFINE_EVENT(OnHudDraw, Gfx** gfx; Mtx * *mtx; Vtx * *vtx;); DEFINE_EVENT(OnReset); \ No newline at end of file diff --git a/src/port/Enhancements/Events/Hooks/List/GameEvent.h b/src/port/Enhancements/Events/Hooks/List/GameEvent.h index 6f682b5c6..e53254847 100644 --- a/src/port/Enhancements/Events/Hooks/List/GameEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/GameEvent.h @@ -3,22 +3,8 @@ #include DEFINE_EVENT(OnActorDestroy, Actor* actor;) -DEFINE_EVENT(OnPlayerDeath) -DEFINE_EVENT(OnGameFileErase, int32_t gamenum;) DEFINE_EVENT(OnGameSave, int32_t fileNum;) DEFINE_EVENT(OnGameLoad, int32_t fileNum;) -DEFINE_EVENT(OnGameErase, int32_t gameNum;) -// flagSpace = AnchorFlagSpace; length = 1 for single sets, bit count for setN. -DEFINE_EVENT(OnGameFlagSet, int32_t flagSpace; int32_t index; int32_t value; int32_t length;) -// count is the resulting absolute value. -DEFINE_EVENT(OnItemCountChanged, int32_t item; int32_t count;) -// kind = AnchorCollectibleSpace. -DEFINE_EVENT(OnCollectibleCollected, int32_t kind; int32_t id;) -// move = ability_e; value = 1 learned, 0 cleared. -DEFINE_EVENT(OnAbilityLearned, int32_t move; int32_t value;) -DEFINE_EVENT(OnJiggySpawned, int32_t jiggyId; float x; float y; float z;) -DEFINE_EVENT(OnHoneycombDropSpawn, int32_t honeycombId; int32_t bundleId; float x; float y; float z;) -DEFINE_EVENT(OnTimedJiggyExpired, int32_t jiggyId;) DEFINE_EVENT(OnPropInit, Prop* propPtr;) DEFINE_EVENT(OnBottlesBonusComplete, int32_t index;) DEFINE_EVENT(OnSaveFileLoad, int32_t fileNum; void* saveBuffer; int32_t result;) @@ -28,16 +14,10 @@ DEFINE_EVENT(OnSaveFileSave, void* saveBuffer; int32_t fileNum; int32_t * result typedef enum WarpId { WARP_ID_SM_EXIT_BANJOS_HOUSE = 1, WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL = 2, - // Also lands in the MM Lobby, but from the post-cutscene branch of a different - // dispatcher. Listeners that treat both lair entrances alike should match on 2 || 3. - WARP_ID_LAIR_ENTER_LAIR_FROM_SM_LEVEL = 3, } WarpId; DEFINE_EVENT(OnWarpResolveDest, int32_t warpId; int32_t defaultDest; int32_t bkcfOverride; int32_t * dest;) DEFINE_EVENT(OnNewGame, int32_t* skipIntro;) -// The file-select commit, for both new game and continue. Unlike OnGameLoad this -// does not fire for the zoombox preview. -DEFINE_EVENT(OnGameStart) DEFINE_EVENT(EggHeadSpawn, float* pitch; float* spawnHeight; float* minVerticalVelocity; float* yawBias; int32_t * flattenTrajectory;) diff --git a/src/port/Enhancements/Events/Hooks/List/RandoEvent.h b/src/port/Enhancements/Events/Hooks/List/RandoEvent.h index 4b2da34a9..cdb556cd6 100644 --- a/src/port/Enhancements/Events/Hooks/List/RandoEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/RandoEvent.h @@ -46,8 +46,6 @@ DEFINE_EVENT(OnIsJiggyScoreSpawned, int32_t jiggyId; int32_t result;) DEFINE_EVENT(SetRandoInfFlag, int32_t flagId; int32_t flagState;) -DEFINE_EVENT(OnRandoCheckObtained, int32_t randoCheckId; int32_t map;) - DEFINE_EVENT(OnIsHoneycombScoreCollected, int32_t honeycombId; int32_t result;) DEFINE_EVENT(ClearBundleDespawnQueue); diff --git a/src/port/Enhancements/Events/PortEnhancements.cpp b/src/port/Enhancements/Events/PortEnhancements.cpp index 05c4dac0a..f369bb3be 100644 --- a/src/port/Enhancements/Events/PortEnhancements.cpp +++ b/src/port/Enhancements/Events/PortEnhancements.cpp @@ -19,12 +19,10 @@ void PortEnhancements_Register() { // Register engine events REGISTER_EVENT(GameFrameUpdate); REGISTER_EVENT(FrameDrawEnd); - REGISTER_EVENT(OnControllerUpdate); REGISTER_EVENT(VanillaBehavior); REGISTER_EVENT(OnMapLoad); REGISTER_EVENT(OnDialogLoaded); REGISTER_EVENT(OnModelLoad); - REGISTER_EVENT(OnModelDisplayListLoad); REGISTER_EVENT(ViewportFrustumUpdate); REGISTER_EVENT(OnTransitionModelScale); REGISTER_EVENT(OnTransitionStateUpdate); @@ -51,7 +49,6 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnBoldFontReset); REGISTER_EVENT(OnWorldDraw); REGISTER_EVENT(OnPlayerDraw); - REGISTER_EVENT(OnHudDraw); // Register behavior events REGISTER_EVENT(OnBeakSwimVelocitySet); @@ -63,7 +60,6 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnIntroCutsceneCheck); REGISTER_EVENT(OnMiscCutscenesCheck); REGISTER_EVENT(OnTooieJiggyCollect); - REGISTER_EVENT(OnJigsawPodiumInput); REGISTER_EVENT(OnMumboTokenUpdate); REGISTER_EVENT(OnMumboTokenIdResolve); REGISTER_EVENT(OnNametagDraw); @@ -76,18 +72,8 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnVileGameStateChange); // Register game events - REGISTER_EVENT(OnGameFlagSet); - REGISTER_EVENT(OnItemCountChanged); - REGISTER_EVENT(OnCollectibleCollected); - REGISTER_EVENT(OnAbilityLearned); - REGISTER_EVENT(OnJiggySpawned); - REGISTER_EVENT(OnHoneycombDropSpawn); - REGISTER_EVENT(OnTimedJiggyExpired); - REGISTER_EVENT(OnPlayerDeath); - REGISTER_EVENT(OnGameFileErase); REGISTER_EVENT(OnGameLoad); REGISTER_EVENT(OnGameSave); - REGISTER_EVENT(OnGameErase); REGISTER_EVENT(OnBottlesBonusComplete); REGISTER_EVENT(OnSaveFileLoad); REGISTER_EVENT(OnSaveFileSave); @@ -95,7 +81,6 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnPropInit); REGISTER_EVENT(OnWarpResolveDest); REGISTER_EVENT(OnNewGame); - REGISTER_EVENT(OnGameStart); REGISTER_EVENT(EggHeadSpawn); REGISTER_EVENT(OnActorDestroy); REGISTER_EVENT(OnCheckSpiralMountainAbilities); @@ -119,7 +104,6 @@ void PortEnhancements_Register() { REGISTER_EVENT(OnIsJiggyScoreCollected); REGISTER_EVENT(OnIsJiggyScoreSpawned); REGISTER_EVENT(SetRandoInfFlag); - REGISTER_EVENT(OnRandoCheckObtained); REGISTER_EVENT(OnIsHoneycombScoreCollected); REGISTER_EVENT(ClearBundleDespawnQueue); REGISTER_EVENT(OnIsMumboTokenScoreCollected); diff --git a/src/port/Enhancements/Fixes/GameFixes.cpp b/src/port/Enhancements/Fixes/GameFixes.cpp index 113f16768..d4d5c8dc4 100644 --- a/src/port/Enhancements/Fixes/GameFixes.cpp +++ b/src/port/Enhancements/Fixes/GameFixes.cpp @@ -8,9 +8,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" -#include "functions.h" extern "C" { #include "enums.h" +#include "functions.h" enum map_e gsworld_getMap(void); } @@ -34,7 +34,6 @@ extern "C" int port_isInCharacterParade(void) { #define CVAR_JINJO_SOUND CVAR_ENHANCEMENT("Fixes.JinjoChargeSound") #define CVAR_GRUNTY_BOUNCE CVAR_ENHANCEMENT("Fixes.GruntyBounce") #define CVAR_CONGA_TEXT CVAR_ENHANCEMENT("Fixes.CongaText") -#define CVAR_STUMP_RUMBLE CVAR_ENHANCEMENT("Fixes.ChimpyStumpRumble") void RegisterVoidOutGameOver_Init() { COND_VB_SHOULD(VB_VOID_OUT_GAME_OVER, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_VOID_OUT, 0), @@ -141,29 +140,6 @@ void RegisterCongaDialog_Init() { }); } -// MM Chimpy stump: Chimpy respawns and walks off again on every entry to MM once his jiggy has -// spawned, so the stump drops in low and grinds back up with the rumble sfx each time. Mute the -// rumble for those replays only; the first rise (jiggy spawns 2.9s after the shake starts, so it -// isn't marked spawned yet) keeps its sound. -static bool IsChimpyWalkOffReplay() { - return jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY) && - !mapSpecificFlags_get(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED); -} - -void RegisterChimpyStumpRumble_Init() { - COND_VB_SHOULD(VB_MM_CHIMPY_STUMP_RUMBLE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_STUMP_RUMBLE, 1), - { *should = !jiggyscore_isSpawned(JIGGY_9_MM_CHIMPY); }); - COND_VB_SHOULD(VB_MM_CHIMPY_NOISE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_STUMP_RUMBLE, 1), - { *should = !IsChimpyWalkOffReplay(); }); - COND_VB_SHOULD(VB_SPLINE_PATH_SFX, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_STUMP_RUMBLE, 1), { - Actor* pathWalker = va_arg(args, Actor*); - if (pathWalker != NULL && pathWalker->actor_info != NULL && pathWalker->actor_info->actorId == ACTOR_F_CHIMPY && - IsChimpyWalkOffReplay()) { - *should = false; - } - }); -} - // Mumbo token duplicate-id fix: rewrite the resolved id for the two tokens that share an id. void RegisterMumboTokenIdResolve_Init() { COND_HOOK(OnMumboTokenIdResolve, EVENT_PRIORITY_NORMAL, @@ -182,23 +158,6 @@ void RegisterMumboTokenIdResolve_Init() { }); } -// Map savestates and demo playback -static bool isPlaybackMode(s32 mode) { - return (mode == GAME_MODE_5_UNKNOWN) || (mode == GAME_MODE_6_FILE_PLAYBACK) || (mode == GAME_MODE_7_ATTRACT_DEMO) || - (mode == GAME_MODE_8_BOTTLES_BONUS) || (mode == GAME_MODE_9_BANJO_AND_KAZOOIE) || - (mode == GAME_MODE_A_SNS_PICTURE); -} - -void RegisterMapSavestatePlayback_Init() { - REGISTER_VB_SHOULD(VB_MAP_SAVESTATE_USE, EVENT_PRIORITY_NORMAL, { - s32 mode = va_arg(args, s32); - if (isPlaybackMode(mode)) { - *should = false; - } - }); -} - -static RegisterShipInitFunc initMapSavestatePlaybackFunc(RegisterMapSavestatePlayback_Init); static RegisterShipInitFunc initVoidOutFunc(RegisterVoidOutGameOver_Init, { CVAR_VOID_OUT }); static RegisterShipInitFunc initFurnaceFunDialogFunc(RegisterFurnaceFunDialog_Init, { CVAR_FF_DIALOG }); static RegisterShipInitFunc initGruntyDefeatedFlagFunc(RegisterGruntyDefeatedFlag_Init, { CVAR_GRUNTY_FLAG }); @@ -212,6 +171,5 @@ static RegisterShipInitFunc initJinjoChargeSoundFunc(RegisterJinjoChargeSound_In static RegisterShipInitFunc initGruntyBounceFunc(RegisterGruntyBounce_Init, { CVAR_GRUNTY_BOUNCE }); static RegisterShipInitFunc initYumYumDropFunc(RegisterYumYumDrop_Init); static RegisterShipInitFunc initCongaDialogFunc(RegisterCongaDialog_Init, { CVAR_CONGA_TEXT }); -static RegisterShipInitFunc initChimpyStumpRumbleFunc(RegisterChimpyStumpRumble_Init, { CVAR_STUMP_RUMBLE }); static RegisterShipInitFunc initMumboTokenIdResolveFunc(RegisterMumboTokenIdResolve_Init, { CVAR_TOKEN_MMM, CVAR_TOKEN_CCW }); diff --git a/src/port/Enhancements/Fixes/TransientLevelState.cpp b/src/port/Enhancements/Fixes/TransientLevelState.cpp deleted file mode 100644 index 3c81868e2..000000000 --- a/src/port/Enhancements/Fixes/TransientLevelState.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Transient Level State -// -// The per-level stores Anchor replicates (huts, breakables, egg tolls, puzzle steps, carried -// collectibles) are written unconditionally by decomp, but only Anchor's sweep ever cleared -// them — offline, a smashed hut survived a level exit that should have restored it. -// -// Per level, not per map, so sub-area hops keep their state like the actor savestate did. - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include "functions.h" -extern "C" { -#include "enums.h" -s32 port_anchor_isWorldSyncActive(void); -} - -void port_breakable_clearForLevel(int32_t levelId); -void port_hutSmash_clearForLevel(int32_t levelId); -void port_eggToll_clearForLevel(int32_t levelId); -void port_puzzleStep_clearForLevel(int32_t levelId); -void port_carriedSync_clearForLevel(int32_t levelId); - -namespace { - -int32_t sCurrentLevel = -1; - -// 0 for maps outside the section table; map_getLevel would deref null on those. -int32_t levelOfMap(int32_t map) { - if (map <= 0 || map >= MAP_NUM_MAPS) { - return 0; - } - return (int32_t)map_getLevel((enum map_e)map); -} - -} // namespace - -void RegisterTransientLevelState_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { sCurrentLevel = -1; }); - - // HIGH so the stores are empty before this event's NORMAL listeners read them for the new - // map (port_breakable_despawnBrokenRestores). - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_HIGH, [](IEvent* event) { - OnMapLoad* ev = (OnMapLoad*)event; - int32_t nextLevel = levelOfMap((int32_t)ev->nextMap); - if (nextLevel == 0 || nextLevel == sCurrentLevel) { - return; - } - sCurrentLevel = nextLevel; - if (port_anchor_isWorldSyncActive()) { - return; - } - port_breakable_clearForLevel(nextLevel); - port_hutSmash_clearForLevel(nextLevel); - port_eggToll_clearForLevel(nextLevel); - port_puzzleStep_clearForLevel(nextLevel); - port_carriedSync_clearForLevel(nextLevel); - }); -} - -static RegisterShipInitFunc initTransientLevelState(RegisterTransientLevelState_Init, {}); diff --git a/src/port/Enhancements/Gameplay/DamageScale.cpp b/src/port/Enhancements/Gameplay/DamageScale.cpp new file mode 100644 index 000000000..7893a0f2f --- /dev/null +++ b/src/port/Enhancements/Gameplay/DamageScale.cpp @@ -0,0 +1,13 @@ +#include +#include "port/UI/cvar_prefixes.h" + +extern "C" int port_scalePlayerDamage(int damage) { + if (damage <= 0) { + return damage; + } + int mode = CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.Difficulty"), 1); + if (mode >= 4) { + return 9999; + } + return damage * (mode < 1 ? 1 : mode); +} \ No newline at end of file diff --git a/src/port/Enhancements/Gameplay/Difficulty.cpp b/src/port/Enhancements/Gameplay/Difficulty.cpp deleted file mode 100644 index fdf918b3e..000000000 --- a/src/port/Enhancements/Gameplay/Difficulty.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include "port/UI/cvar_prefixes.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" -#include "port/Romhack/RomhackConfig.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -} - -static bool sSaveErased = false; - -extern "C" int port_scalePlayerDamage(int damage) { - if (damage <= 0) { - return damage; - } - int mode = CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.Difficulty"), 1); - if (mode >= 4) { - return 9999; - } - return damage * (mode < 1 ? 1 : mode); -} - -void RegisterDifficulty_Init() { - // Permadeath, ignore lives and game over with file erase - COND_HOOK(OnPlayerDeath, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.Permadeath"), 0), - [](IEvent* event) { - if (port_isRomhack()) { - return; - } - item_adjustByDiffWithoutHud(ITEM_16_LIFE, -item_getCount(ITEM_16_LIFE)); - - s32 gamenum = gameSelect_getGameNumber(); - if (gamenum == -1) { - return; - } - - gameFile_clear(gamenum); - gameFile_8033CFD4(gamenum); - sSaveErased = true; - }); - - COND_HOOK(OnGameLoad, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { sSaveErased = false; }); - - COND_VB_SHOULD(VB_SAVE_AND_EXIT, EVENT_PRIORITY_NORMAL, true, { - if (sSaveErased) { - *should = false; - } - }); -} - -static RegisterShipInitFunc initFunc(RegisterDifficulty_Init, { CVAR_ENHANCEMENT("Gameplay.Permadeath") }); diff --git a/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp b/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp index f422874be..26fbfc32e 100644 --- a/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp +++ b/src/port/Enhancements/Gameplay/EasierBoggyRaces.cpp @@ -7,7 +7,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +extern "C" { #include "enums.h" +} #define CVAR_NAME CVAR_ENHANCEMENT("EasierBoggyRaces") #define CVAR CVarGetInteger(CVAR_NAME, 0) diff --git a/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp b/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp index f76860273..b53ea3979 100644 --- a/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp +++ b/src/port/Enhancements/Gameplay/FurnaceFunMoves.cpp @@ -4,9 +4,11 @@ #include "port/ShipInit.hpp" #include "port/Romhack/RomhackConfig.h" +extern "C" { #include "enums.h" #include "functions.h" #include "core2/abilityprogress.h" +} #define CVAR_NAME CVAR_ENHANCEMENT("Gameplay.FurnaceFunMoves") @@ -21,12 +23,7 @@ void RegisterFurnaceFunMoves_Init() { continue; } ability_unlock(static_cast(ability)); - ability_setHasUsed(static_cast(ability)); } - // Outside the loop's range. Without it the note doors never open and Bottles - // force-triggers his tutorial on approach to the 50-note door. - ability_unlock(ABILITY_13_1ST_NOTEDOOR); - ability_setHasUsed(ABILITY_13_1ST_NOTEDOOR); }); } diff --git a/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp b/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp index 6c7ee0cc0..749413da7 100644 --- a/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp +++ b/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp @@ -3,11 +3,12 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" #include "port/Romhack/RomhackConfig.h" -#include "port/Rando/Rando.h" +extern "C" { #include "enums.h" #include "functions.h" #include "core2/abilityprogress.h" +} extern "C" float D_80386000[]; @@ -35,23 +36,20 @@ void RegisterSkipSMTutorial_Init() { } auto* ev = reinterpret_cast(event); - if (!IS_RANDO) { - for (ability_e ability : kSpiralMountainAbilities) { - ability_unlock(ability); - } - - for (ability_used move : kSpiralMountainUsedMoves) { - ability_setHasUsed(static_cast(move)); - } - - for (int honeycomb = HONEYCOMB_13_SM_STUMP; honeycomb <= HONEYCOMB_18_SM_QUARRIES; honeycomb++) { - honeycombscore_set((honeycomb_e)honeycomb, true); - } - func_8034789C(); - item_adjustByDiffWithoutHud(ITEM_14_HEALTH, - item_getCount(ITEM_15_HEALTH_TOTAL) - item_getCount(ITEM_14_HEALTH)); + for (ability_e ability : kSpiralMountainAbilities) { + ability_unlock(ability); + } + + for (ability_used move : kSpiralMountainUsedMoves) { + ability_setHasUsed(static_cast(move)); } + for (int honeycomb = HONEYCOMB_13_SM_STUMP; honeycomb <= HONEYCOMB_18_SM_QUARRIES; honeycomb++) { + honeycombscore_set((honeycomb_e)honeycomb, true); + } + func_8034789C(); + item_adjustByDiffWithoutHud(ITEM_14_HEALTH, + item_getCount(ITEM_15_HEALTH_TOTAL) - item_getCount(ITEM_14_HEALTH)); fileProgressFlag_set(FILEPROG_BD_ENTER_LAIR_CUTSCENE, 1); D_80386000[LEVEL_B_SPIRAL_MOUNTAIN] = 122.0f; // Average speedrun time for SM completion (2:02) diff --git a/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp b/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp index ad5748a71..f5e185807 100644 --- a/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp +++ b/src/port/Enhancements/Gameplay/WaterPyramidTimer.cpp @@ -7,7 +7,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +extern "C" { #include "enums.h" +} #define CVAR_NAME CVAR_ENHANCEMENT("Gameplay.WaterPyramidTimer") diff --git a/src/port/Enhancements/JinjoRetention/JinjoRetention.cpp b/src/port/Enhancements/JinjoRetention/JinjoRetention.cpp new file mode 100644 index 000000000..4eb3ba567 --- /dev/null +++ b/src/port/Enhancements/JinjoRetention/JinjoRetention.cpp @@ -0,0 +1,195 @@ +// Jinjo Collection Retention +// +// Vanilla resets ITEM_12_JINJOS on every level entry (itemscore_levelReset), so jinjos +// respawn each visit and must all be collected in one go to earn the jiggy. This persists +// the per-level set of collected jinjo colors so individually collected jinjos stay +// collected across visits. +// +// How it works: +// - Saving is ALWAYS ON: collecting a jinjo records its color bit for the current +// level (same 5-bit layout as ITEM_12_JINJOS). +// - Application is behind an enhancement toggle (default off): when on, ITEM_12_JINJOS +// is seeded on level load from the saved bits, and already collected jinjos are not +// respawned. Collecting the remaining jinjos then completes the vanilla 0x1f mask and +// spawns the jiggy as usual. +// +// Stranded-jiggy guard: if all 5 of a level's jinjos are recorded but that level's jinjo +// jiggy has not been obtained (player got all 5 but skipped the jiggy), retention is not +// applied for that level -- the jinjos respawn so the jiggy can still be earned. +// +#include +#include + +#include "port/UI/cvar_prefixes.h" +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Enhancements/JinjoRetention/JinjoRetention.h" +#include "port/Rando/Rando.h" + +extern "C" { +#include "enums.h" +#include "actor.h" +#include "prop.h" +#include "functions.h" +} + +#define CVAR_JINJO_RETENTION CVAR_ENHANCEMENT("Gameplay.JinjoRetention") +#define CVAR_VALUE CVarGetInteger(CVAR_JINJO_RETENTION, 0) + +constexpr u8 kAllJinjos = 0x1F; // all five color bits collected + +// gameFile_saveData index of the live save slot for the current game, or -1. +int32_t activeSlot() { + if (selectedFileNum == DEFAULT_FILE_NUM || selectedFileNum < 0 || selectedFileNum >= 4) { + return -1; + } + return (int32_t)selectedFileNum; +} + +// Don't run during demos, Bottles bonus games, or rando files. +bool systemActive() { + int32_t slot = activeSlot(); + if (slot < 0 || gameFile_saveData[slot].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { + return false; + } + switch (getGameMode()) { + case GAME_MODE_7_ATTRACT_DEMO: + case GAME_MODE_8_BOTTLES_BONUS: + case GAME_MODE_9_BANJO_AND_KAZOOIE: + case GAME_MODE_A_SNS_PICTURE: + return false; + default: + return true; + } +} + +bool applyEnabled() { + return CVarGetInteger(CVAR_JINJO_RETENTION, 0) != 0; +} + +JinjoRetentionSaveData* store() { + int32_t slot = activeSlot(); + return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.jinjoRetention : nullptr; +} + +bool levelInRange(int32_t level) { + return level > 0 && level < JINJO_RETENTION_LEVEL_SLOTS; +} + +u8 collectedBits(int32_t level) { + JinjoRetentionSaveData* s = store(); + return (s != nullptr && levelInRange(level)) ? s->collected[level] : 0; +} + +u8 jinjoBitFromMarker(int32_t markerId) { + switch (markerId) { + case MARKER_5A_JINJO_BLUE: + case MARKER_5B_JINJO_GREEN: + case MARKER_5C_JINJO_ORANGE: + case MARKER_5D_JINJO_PINK: + case MARKER_5E_JINJO_YELLOW: + return (u8)(1 << ((markerId + 6) & 0x1F)); + default: + return 0; + } +} + +u8 jinjoBitFromActor(int32_t actorId) { + switch (actorId) { + case ACTOR_60_JINJO_BLUE: + return 1 << 0; + case ACTOR_62_JINJO_GREEN: + return 1 << 1; + case ACTOR_5F_JINJO_ORANGE: + return 1 << 2; + case ACTOR_61_JINJO_PINK: + return 1 << 3; + case ACTOR_5E_JINJO_YELLOW: + return 1 << 4; + default: + return 0; + } +} + +// Whether retention should seed/suppress jinjos for this level. False when retention is +// off, and false in the stranded-jiggy case so the jinjos respawn and the jiggy is still +// earnable. Seeding and suppression both gate on this so ITEM_12_JINJOS stays consistent. +bool retentionActiveForLevel(int32_t level) { + if (!applyEnabled() || !levelInRange(level)) { + return false; + } + if (collectedBits(level) == kAllJinjos && !jiggyscore_isCollected((enum jiggy_e)(10 * level - 9))) { + return false; + } + return true; +} + +void RegisterJinjoRetention_Init() { + // Record collection. Don't cancel: vanilla still updates ITEM_12_JINJOS / spawns the + // jiggy and despawns the jinjo. + COND_HOOK(OnActorCollision, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnActorCollision* ev = (OnActorCollision*)event; + if (!systemActive() || !ev->propId->markerFlag) { + return; + } + ActorMarker* marker = ev->propId->actorProp.marker; + if (marker == nullptr) { + return; + } + u8 bit = jinjoBitFromMarker(marker->id); + if (bit == 0) { + return; + } + int32_t level = level_get(); + JinjoRetentionSaveData* s = store(); + if (s != nullptr && levelInRange(level)) { + s->collected[level] |= bit; + } + }); + + // Seed ITEM_12_JINJOS from the saved bits so prior progress carries across visits and + // the HUD reflects it. Mirrors note retention's OnSetJiggyList seeding. + COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnSetJiggyList* ev = (OnSetJiggyList*)event; + if (!systemActive() || !retentionActiveForLevel(ev->levelId)) { + return; + } + u8 bits = collectedBits(ev->levelId); + if (bits != 0) { + item_set(ITEM_12_JINJOS, bits); + } + }); + + // Suppress respawning already-collected jinjos. OnActorSpawn is cancellable; returning + // a null result with Cancelled means no actor spawns. + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnActorSpawn* ev = (OnActorSpawn*)event; + if (!systemActive()) { + return; + } + u8 bit = jinjoBitFromActor(ev->actorId); + if (bit == 0) { + return; + } + int32_t level = level_get(); + if (!retentionActiveForLevel(level) || !(collectedBits(level) & bit)) { + return; + } + ev->result = nullptr; + event->Cancelled = true; + }); + + // The engine's save double-buffers into a scratch slot via bcopy, which doesn't carry + // our bits. Sync the live slot's jinjoRetention into the buffer about to be serialized. + COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, CVAR_VALUE, [](IEvent* event) { + OnSaveFileSave* ev = (OnSaveFileSave*)event; + SaveData* buf = (SaveData*)ev->saveBuffer; + JinjoRetentionSaveData* live = store(); + if (buf != nullptr && live != nullptr && &buf->shipSaveData.jinjoRetention != live) { + buf->shipSaveData.jinjoRetention = *live; + } + }); +} + +static RegisterShipInitFunc initJinjoRetention(RegisterJinjoRetention_Init, { CVAR_JINJO_RETENTION }); diff --git a/src/port/Enhancements/JinjoRetention/JinjoRetention.h b/src/port/Enhancements/JinjoRetention/JinjoRetention.h new file mode 100644 index 000000000..91363c9d8 --- /dev/null +++ b/src/port/Enhancements/JinjoRetention/JinjoRetention.h @@ -0,0 +1,8 @@ +#ifndef PORT_JINJO_RETENTION_H +#define PORT_JINJO_RETENTION_H + +// Jinjo Collection Retention is implemented entirely with port event listeners +// (collection, level-load seeding, spawn suppression) and needs no engine-side hooks, +// so this header only marks the module's presence for consistency with NoteRetention. + +#endif diff --git a/src/port/Enhancements/NoteRetention/NoteRetention.cpp b/src/port/Enhancements/NoteRetention/NoteRetention.cpp new file mode 100644 index 000000000..0f5651ff2 --- /dev/null +++ b/src/port/Enhancements/NoteRetention/NoteRetention.cpp @@ -0,0 +1,425 @@ +// Note Collection Retention +// +// Persists which individual music notes the player has collected so they don't respawn +// on revisit. Works for vanilla and romhacks because each note is identified +// by (mapId, spawn-order index) within the map's deterministic cube-prop parse. +// +// How it works: +// - Static note sprite-props are replaced with ACTOR_51_MUSIC_NOTE actors so a +// stable spawn-order index can be attached to each via ObjectExtension. +// - Dynamically-spawned note bundles (hut/switch triggers) are also replaced with +// our own actors, given indices that continue AFTER the static notes for the map. +// Their identity resides in actor->local (not ObjectExtension) because bundle notes +// persist across sub-area save/restore, which copies the actor struct but assigns +// a fresh marker, so a marker-keyed extension wouldn't survive. +// - Saving is ALWAYS ON: collecting a note records (mapId, index) to the save. +// - Application is behind an enhancement toggle (default off): when on, already +// collected notes are not respawned, and ITEM_C_NOTE is seeded on level load +// from the collected count so totals stay reachable. Note-door logic is left +// to the vanilla per-level high score, unchanged. +// +#include "port/ObjectExtension/ObjectExtension.h" +#include +#include + +#include "port/UI/cvar_prefixes.h" +#include "port/ShipInit.hpp" +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/Enhancements/NoteRetention/NoteRetention.h" +#include "port/Rando/Rando.h" +#include "port/Rando/CustomObject/CustomObject.h" + +#include +#include + +extern "C" { +#include "enums.h" +#include "actor.h" +#include "prop.h" +#include "functions.h" + +extern f32 gBundle_yaw; +extern ActorInfo sumusicNote; +} + +namespace { + +#define CVAR_NOTE_RETENTION CVAR_ENHANCEMENT("Gameplay.NoteRetention") +#define CVAR_VALUE CVarGetInteger(CVAR_NOTE_RETENTION, 0) + +// The note sprite asset id passed through VB_OVERRIDE_PROP_SPAWN identifies notes. +constexpr s32 kNoteSpriteAsset = ASSET_6D6_SPRITE_MUSIC_NOTE; + +// Per-actor note identity, attached via ObjectExtension. The constructor lets us +// build instances with parentheses, since brace-init commas break the event macros. +struct NoteRetentionData { + int32_t mapId; + int32_t noteIndex; + NoteRetentionData(int32_t map = 0, int32_t index = 0) : mapId(map), noteIndex(index) { + } +}; +ObjectExtension::Register NoteRetentionDataRegister; + +// Identity for bundle notes, stored in the actor's local data block. Unlike static +// notes, bundle notes are restored across sub-area transitions by the engine's actor +// save-state, which memcpy's the whole Actor struct (so local survives) but assigns +// a new marker (so an extension wouldn't). +// magic distinguishes our data from the uninitialized garbage actor_new leaves +// in local, and from notes we didn't spawn. +constexpr uint32_t kNoteLocalMagic = 0x4E4F5445u; // 'NOTE' +struct NoteLocal { + uint32_t magic; + int32_t mapId; + int32_t noteIndex; +}; + +NoteLocal* bundleNoteLocal(Actor* actor) { + if (actor == nullptr) { + return nullptr; + } + NoteLocal* nl = reinterpret_cast(actor->local); + return (nl->magic == kNoteLocalMagic) ? nl : nullptr; +} + +struct QueuedNote { + int32_t pos[3]; + int32_t mapId; + int32_t noteIndex; + bool spawned; +}; + +int32_t noteCounter = 0; +std::vector noteActorQueue; +std::unordered_map activeNoteSet; + +int64_t noteKey(int32_t mapId, int32_t noteIndex) { + return ((int64_t)mapId << 32) | (uint32_t)noteIndex; +} + +// Active slot is wobbly +int32_t activeSlot() { + if (selectedFileNum == DEFAULT_FILE_NUM || selectedFileNum < 0 || selectedFileNum >= 4) { + return -1; + } + return (int32_t)selectedFileNum; +} + +bool fileValid() { + return activeSlot() >= 0; +} + +// Don't run during demos, Bottles bonus games, or rando files +bool systemActive() { + int32_t slot = activeSlot(); + if (slot < 0 || gameFile_saveData[slot].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { + return false; + } + switch (getGameMode()) { + case GAME_MODE_7_ATTRACT_DEMO: + case GAME_MODE_8_BOTTLES_BONUS: + case GAME_MODE_9_BANJO_AND_KAZOOIE: + case GAME_MODE_A_SNS_PICTURE: + return false; + default: + return true; + } +} + +bool applyEnabled() { + return CVarGetInteger(CVAR_NOTE_RETENTION, 0) != 0; +} + +NoteRetentionSaveData* store() { + int32_t slot = activeSlot(); + return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.noteRetention : nullptr; +} + +bool indexInRange(int32_t mapId, int32_t index) { + return mapId >= 0 && mapId < NOTE_RETENTION_MAP_SLOTS && index >= 0 && index < NOTE_RETENTION_NOTES_PER_MAP; +} + +bool isCollected(int32_t mapId, int32_t index) { + NoteRetentionSaveData* s = store(); + if (s == nullptr || !indexInRange(mapId, index)) { + return false; + } + return (s->collected[mapId][index >> 3] >> (index & 7)) & 1; +} + +void setCollected(int32_t mapId, int32_t index) { + NoteRetentionSaveData* s = store(); + if (s == nullptr || !indexInRange(mapId, index)) { + return; + } + s->collected[mapId][index >> 3] |= (uint8_t)(1 << (index & 7)); +} + +int32_t countCollectedForLevel(int32_t levelId) { + NoteRetentionSaveData* s = store(); + if (s == nullptr) { + return 0; + } + int32_t total = 0; + for (int32_t mapId = 0; mapId < NOTE_RETENTION_MAP_SLOTS; mapId++) { + // Count this map's collected bits first; only real maps that have been + // played ever get bits set. Skipping empties keeps us from calling + // map_getLevel on non-existent map ids (e.g. MAP_0_UNKNOWN), which crashes. + int32_t mapTotal = 0; + for (int32_t b = 0; b < NOTE_RETENTION_BYTES_PER_MAP; b++) { + uint8_t byte = s->collected[mapId][b]; + while (byte) { + mapTotal += byte & 1; + byte >>= 1; + } + } + if (mapTotal == 0) { + continue; + } + if (map_getLevel((enum map_e)mapId) == (enum level_e)levelId) { + total += mapTotal; + } + } + return total; +} + +} // namespace + +// Called from gsworld_load (the single entry that parses a map's cubes) before any +// cube is read. This is the reliable once-per-parse-pass signal -- it fires on every +// map load AND on intra-level warps/sub-area transitions that re-parse the cubes, +// even when OnMapLoad doesn't. Resetting the counter here keeps spawn-order indices +// stable across re-parses. The live-actor set is NOT cleared here: our note actors +// persist across map changes (they're only torn down by actorArray_free), so the set +// must persist too, or returning to a map would duplicate its still-live notes. +extern "C" void port_noteRetention_beginMapLoad(int32_t mapId) { + (void)mapId; + noteCounter = 0; + noteActorQueue.clear(); +} + +// Called from actorArray_free. At this point every note actor is gone, so drop the +// live-actor set and detach the ObjectExtension data. +extern "C" void port_noteRetention_onActorsFreed(void) { + for (auto& [key, marker] : activeNoteSet) { + ObjectExtension::GetInstance().Remove(marker); + } + activeNoteSet.clear(); + noteActorQueue.clear(); +} + +void RegisterNoteRetention_Init() { + COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { + s16* spawnPosition = va_arg(args, s16*); + s32 spriteAsset = va_arg(args, s32); + + if (!systemActive() || spriteAsset != kNoteSpriteAsset) { + return; + } + + int32_t mapId = (int32_t)gsworld_getMap(); + int32_t noteIndex = noteCounter++; + if (!indexInRange(mapId, noteIndex)) { + return; // out of addressable range: leave as a vanilla sprite prop + } + + // From here we own this note: suppress the static sprite prop. + *should = true; + + if (activeNoteSet.count(noteKey(mapId, noteIndex))) { + return; // a live actor already exists (re-parse): don't duplicate it + } + + if (applyEnabled() && isCollected(mapId, noteIndex)) { + return; // already collected and retention on: don't respawn it + } + + QueuedNote queued; + queued.pos[0] = spawnPosition[0]; + queued.pos[1] = spawnPosition[1]; + queued.pos[2] = spawnPosition[2]; + queued.mapId = mapId; + queued.noteIndex = noteIndex; + queued.spawned = false; + noteActorQueue.push_back(queued); + }); + + // Flush queued notes into actors. actor_new does not re-fire OnActorSpawn, so no recursion. + COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + if (!systemActive() || noteActorQueue.empty()) { + return; + } + for (auto& q : noteActorQueue) { + if (q.spawned) { + continue; + } + int32_t pos[3]; + pos[0] = q.pos[0]; + pos[1] = q.pos[1]; + pos[2] = q.pos[2]; + Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); + ActorMarker* marker = (note != nullptr) ? note->marker : nullptr; + if (marker != nullptr) { + // Key on the marker (stable across the actor's life and what the collision event hands us). + ObjectExtension::GetInstance().Set(marker, NoteRetentionData(q.mapId, q.noteIndex)); + activeNoteSet[noteKey(q.mapId, q.noteIndex)] = marker; + } + q.spawned = true; + } + }); + + // Note bundles get spawn-order indices that continue after the map's static + // note count. We override the vanilla bundle spawn to substitute our own actor (carrying + // identity in local) and re-apply the vanilla fly-out physics. Detection is by the + // bundle's spawned actor type, so it stays romhack-agnostic. + COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, true, { + bundle_e bundleId = (bundle_e)va_arg(args, int); + BundleInfo* bundleInfo = va_arg(args, BundleInfo*); + va_arg(args, s32); // index within the bundle (unused: we use our own counter) + f32* position = va_arg(args, f32*); + Actor** actorOut = va_arg(args, Actor**); + + if (!systemActive() || bundleInfo == nullptr || bundleInfo->actor_id != ACTOR_51_MUSIC_NOTE) { + return; // not our note bundle: leave it to vanilla (or rando) + } + + int32_t mapId = (int32_t)gsworld_getMap(); + int32_t noteIndex = noteCounter++; + if (!indexInRange(mapId, noteIndex)) { + return; // out of addressable range: let vanilla spawn it normally + } + + // From here we own this note: suppress the vanilla bundle spawn. + *should = true; + + int64_t key = noteKey(mapId, noteIndex); + if (activeNoteSet.count(key)) { + return; // a live actor already exists (re-trigger this load): don't duplicate + } + if (applyEnabled() && isCollected(mapId, noteIndex)) { + return; // already collected and retention on: don't respawn it + } + + int32_t pos[3]; + pos[0] = (int32_t)position[0]; + pos[1] = (int32_t)position[1]; + pos[2] = (int32_t)position[2]; + Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); + if (note == nullptr) { + return; + } + NoteLocal* nl = reinterpret_cast(note->local); + nl->magic = kNoteLocalMagic; + nl->mapId = mapId; + nl->noteIndex = noteIndex; + + ApplyBundleActorPhysics(note, (int32_t)bundleId, bundleInfo, gBundle_yaw); + + activeNoteSet[key] = note->marker; + *actorOut = note; + }); + + // Prevent restoration from save states, as actors get re-added by the cubeprop parse. + COND_HOOK(OnLoadActorSaveState, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnLoadActorSaveState* ev = (OnLoadActorSaveState*)event; + if (!systemActive() || ev->actor == nullptr) { + return; + } + if ((int32_t)ev->actor->modelCacheIndex != ACTOR_51_MUSIC_NOTE) { + return; + } + if (ev->actor->is_bundle && bundleNoteLocal(ev->actor) != nullptr) { + return; // keep restored bundle notes alive + } + event->Cancelled = true; + }); + + // Record collection. Don't cancel: vanilla still increments ITEM_C_NOTE and despawns. + COND_HOOK(OnActorCollision, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnActorCollision* ev = (OnActorCollision*)event; + if (!systemActive() || !ev->propId->markerFlag) { + return; + } + ActorMarker* marker = ev->propId->actorProp.marker; + if (marker == nullptr || marker->id != MARKER_5F_MUSIC_NOTE) { + return; + } + int32_t mapId; + int32_t noteIndex; + NoteRetentionData* data = ObjectExtension::GetInstance().Get(marker); + if (data != nullptr) { + mapId = data->mapId; + noteIndex = data->noteIndex; + ObjectExtension::GetInstance().Remove(marker); + } else if (NoteLocal* nl = bundleNoteLocal(marker_getActor(marker))) { + mapId = nl->mapId; + noteIndex = nl->noteIndex; + nl->magic = 0; // consumed + } else { + return; // not one of ours + } + setCollected(mapId, noteIndex); + activeNoteSet.erase(noteKey(mapId, noteIndex)); + }); + + // Seed the level's note counter from collected notes so totals stay reachable. + COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnSetJiggyList* ev = (OnSetJiggyList*)event; + if (!systemActive() || !applyEnabled()) { + return; + } + item_set(ITEM_C_NOTE, countCollectedForLevel(ev->levelId)); + }); + + // With retention applied, the vanilla note-score messages become misleading or fire + // spuriously (seeding ITEM_C_NOTE on load re-triggers the high-score milestones), so + // suppress them while the CVar is on. + COND_VB_SHOULD(VB_OVERRIDE_DIALOG_SHOW, EVENT_PRIORITY_NORMAL, true, { + s32 textId = va_arg(args, s32); + if (!applyEnabled()) { + return; + } + switch (textId) { + case 0xD9C: // Bottles' first-note text: "you can't take notes with you" + case 0xF76: // "you just beat your high score" + case 0xF74: // milestone: 50 notes (Mumbo's Mountain) + *should = true; + break; + default: + break; + } + }); + + // Clean up per-marker data when actors are destroyed (marker pointers get reused). + COND_HOOK(OnActorDestroy, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { + OnActorDestroy* ev = (OnActorDestroy*)event; + if (ev->actor == nullptr) { + return; + } + if (ev->actor->marker != nullptr) { + NoteRetentionData* data = ObjectExtension::GetInstance().Get(ev->actor->marker); + if (data != nullptr) { + activeNoteSet.erase(noteKey(data->mapId, data->noteIndex)); + } + ObjectExtension::GetInstance().Remove(ev->actor->marker); + } + if (NoteLocal* nl = bundleNoteLocal(ev->actor)) { + activeNoteSet.erase(noteKey(nl->mapId, nl->noteIndex)); + nl->magic = 0; + } + }); + + // The engine's save double-buffers into a scratch slot via bcopy, which doesn't + // reliably carry our note bits. Sync the live active slot's noteRetention into the + // buffer about to be serialized. + COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, CVAR_VALUE, [](IEvent* event) { + OnSaveFileSave* ev = (OnSaveFileSave*)event; + SaveData* buf = (SaveData*)ev->saveBuffer; + NoteRetentionSaveData* live = store(); + if (buf != nullptr && live != nullptr && &buf->shipSaveData.noteRetention != live) { + buf->shipSaveData.noteRetention = *live; + } + }); +} + +static RegisterShipInitFunc initNoteRetention(RegisterNoteRetention_Init); diff --git a/src/port/Enhancements/NoteRetention/NoteRetention.h b/src/port/Enhancements/NoteRetention/NoteRetention.h new file mode 100644 index 000000000..9022e9bef --- /dev/null +++ b/src/port/Enhancements/NoteRetention/NoteRetention.h @@ -0,0 +1,17 @@ +#ifndef PORT_NOTE_RETENTION_H +#define PORT_NOTE_RETENTION_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void port_noteRetention_beginMapLoad(int32_t mapId); +void port_noteRetention_onActorsFreed(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/port/Enhancements/Restorations/ReturnToLair.cpp b/src/port/Enhancements/Restorations/ReturnToLair.cpp index b19587756..8de5916f2 100644 --- a/src/port/Enhancements/Restorations/ReturnToLair.cpp +++ b/src/port/Enhancements/Restorations/ReturnToLair.cpp @@ -8,9 +8,9 @@ #include "include/core2/anctrl.h" #include "include/core2/gc/zoombox.h" -#include "functions.h" - -extern "C" struct1Bs D_8036C560[]; // not declared in variables.h +extern "C" struct1Bs D_8036C560[]; +extern "C" enum level_e level_get(void); +extern "C" bool fileProgressFlag_get(enum file_progress_e index); typedef struct struct_1A_s { f32 delay; diff --git a/src/port/Enhancements/Retention/JinjoRetention.cpp b/src/port/Enhancements/Retention/JinjoRetention.cpp deleted file mode 100644 index e280ed9e5..000000000 --- a/src/port/Enhancements/Retention/JinjoRetention.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// Jinjo Collection Retention -// -// Vanilla resets ITEM_12_JINJOS (per-level jinjo count) every level entry; this persists -// per-level collected colors across visits. -// -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Enhancements/Retention/Retention.h" -#include "port/Rando/Rando.h" -#include "port/Rando/CustomObject/CustomObject.h" - -#include "enums.h" -#include "actor.h" -#include "prop.h" -#include "functions.h" - -extern "C" int32_t port_jiggySpawn_isRecorded(int32_t jiggyId); - -static bool sForcedByAnchor = false; -#define CVAR_JINJO_RETENTION CVAR_ENHANCEMENT("Gameplay.JinjoRetention") -#define CVAR_VALUE (CVarGetInteger(CVAR_JINJO_RETENTION, 0) || sForcedByAnchor) - -constexpr u8 kAllJinjos = 0x1F; // all five color bits collected - -using retention::activeSlot; -using retention::systemActive; - -static bool applyEnabled() { - return CVAR_VALUE; -} - -extern "C" void port_jinjoRetention_setForced(int32_t forced) { - sForcedByAnchor = forced != 0; - ShipInit::Init(CVAR_JINJO_RETENTION); -} - -static JinjoRetentionSaveData* store() { - int32_t slot = activeSlot(); - return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.jinjoRetention : nullptr; -} - -extern "C" void port_jinjoRetention_getSizeAndPtr(int32_t* size, uint8_t** addr) { - JinjoRetentionSaveData* s = store(); - if (s == nullptr) { - *size = 0; - *addr = nullptr; - return; - } - *size = (int32_t)sizeof(JinjoRetentionSaveData); - *addr = (uint8_t*)s; -} - -static bool levelInRange(int32_t level) { - return level > 0 && level < JINJO_RETENTION_LEVEL_SLOTS; -} - -uint8_t collectedBits(int32_t level) { - JinjoRetentionSaveData* s = store(); - return (s != nullptr && levelInRange(level)) ? s->collected[level] : 0; -} - -void setCollectedBits(int32_t level, u8 bits) { - JinjoRetentionSaveData* s = store(); - if (s != nullptr && levelInRange(level)) { - s->collected[level] = bits; - } -} - -static enum jiggy_e jinjoJiggy(int32_t level) { - return (enum jiggy_e)(10 * level - 9); -} - -static u8 jinjoBitFromMarker(int32_t markerId) { - switch (markerId) { - case MARKER_5A_JINJO_BLUE: - case MARKER_5B_JINJO_GREEN: - case MARKER_5C_JINJO_ORANGE: - case MARKER_5D_JINJO_PINK: - case MARKER_5E_JINJO_YELLOW: - return (u8)(1 << ((markerId + 6) & 0x1F)); - default: - return 0; - } -} - -uint8_t jinjoBitFromActor(int32_t actorId) { - switch (actorId) { - case ACTOR_60_JINJO_BLUE: - return 1 << 0; - case ACTOR_62_JINJO_GREEN: - return 1 << 1; - case ACTOR_5F_JINJO_ORANGE: - return 1 << 2; - case ACTOR_61_JINJO_PINK: - return 1 << 3; - case ACTOR_5E_JINJO_YELLOW: - return 1 << 4; - default: - return 0; - } -} - -static int32_t jinjoActorFromBit(u8 bit) { - switch (bit) { - case 1 << 0: - return ACTOR_60_JINJO_BLUE; - case 1 << 1: - return ACTOR_62_JINJO_GREEN; - case 1 << 2: - return ACTOR_5F_JINJO_ORANGE; - case 1 << 3: - return ACTOR_61_JINJO_PINK; - case 1 << 4: - return ACTOR_5E_JINJO_YELLOW; - default: - return 0; - } -} - -extern "C" int32_t port_jinjoRetention_debugPickLive(void) { - static const enum actor_e kJinjoActors[] = { ACTOR_60_JINJO_BLUE, ACTOR_62_JINJO_GREEN, ACTOR_5F_JINJO_ORANGE, - ACTOR_61_JINJO_PINK, ACTOR_5E_JINJO_YELLOW }; - for (enum actor_e id : kJinjoActors) { - Actor* a = actorArray_findActorFromActorId(id); - if (a != nullptr && a->marker != nullptr) { - return jinjoBitFromActor(id); - } - } - return 0; -} - -extern "C" void port_jinjoRetention_applyRemoteCollect(int32_t map, int32_t bit, int32_t sameMap) { - int32_t level = map_getLevel((enum map_e)map); - JinjoRetentionSaveData* s = store(); - if (s != nullptr && levelInRange(level)) { - s->collected[level] |= (u8)bit; - } - // ITEM_12_JINJOS is per-level, not per-map; sub-areas are separate maps but share the count. - if (level == (int32_t)level_get()) { - item_set(ITEM_12_JINJOS, collectedBits(level)); - } - if (sameMap) { - int32_t actorId = jinjoActorFromBit((u8)bit); - if (actorId != 0) { - Actor* a = actorArray_findActorFromActorId((enum actor_e)actorId); - if (a != nullptr && a->marker != nullptr) { - marker_despawn(a->marker); - } - } - } -} - -// Called from the actual pickup (__chJinjo_802CDBA8), not broad-phase collision. -extern "C" void port_jinjoRetention_onLocalJinjoCollected(int32_t markerId) { - if (!systemActive()) { - return; - } - u8 bit = jinjoBitFromMarker(markerId); - if (bit == 0) { - return; - } - int32_t level = level_get(); - JinjoRetentionSaveData* s = store(); - bool wasSet = (s != nullptr) && levelInRange(level) && ((s->collected[level] & bit) != 0); - if (s != nullptr && levelInRange(level)) { - s->collected[level] |= bit; - } - if (!wasSet) { - CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_JINJO, bit); - } -} - -// False when retention is off, or when the jiggy is stranded (all 5 recorded but not -// collected/spawned). -static bool retentionActiveForLevel(int32_t level) { - if (!applyEnabled() || !levelInRange(level)) { - return false; - } - if (collectedBits(level) == kAllJinjos && !jiggyscore_isCollected(jinjoJiggy(level)) && - !jiggyscore_isSpawned(jinjoJiggy(level)) && !port_jiggySpawn_isRecorded(jinjoJiggy(level))) { - return false; - } - return true; -} - -void RegisterJinjoRetention_Init() { - // Seed ITEM_12_JINJOS from saved bits on entry. - COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnSetJiggyList* ev = (OnSetJiggyList*)event; - if (!systemActive() || !applyEnabled() || !levelInRange(ev->levelId)) { - return; - } - int32_t level = ev->levelId; - if (jiggyscore_isCollected(jinjoJiggy(level))) { - // Jiggy earned but record out of sync — force all five. - if (collectedBits(level) != kAllJinjos) { - setCollectedBits(level, kAllJinjos); - } - } else if (collectedBits(level) == kAllJinjos && !jiggyscore_isSpawned(jinjoJiggy(level)) && - !port_jiggySpawn_isRecorded(jinjoJiggy(level))) { - // Orphaned: all recorded but jiggy neither collected nor spawned. - setCollectedBits(level, 0); - } - if (!retentionActiveForLevel(level)) { - return; - } - u8 bits = collectedBits(ev->levelId); - if (bits != 0) { - item_adjustByDiffWithoutHud(ITEM_12_JINJOS, bits - item_getCount(ITEM_12_JINJOS)); - } - }); - - // Suppress respawn of already-collected jinjos; null result + Cancelled = no spawn. - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - if (!systemActive()) { - return; - } - u8 bit = jinjoBitFromActor(ev->actorId); - if (bit == 0) { - return; - } - int32_t level = level_get(); - if (!retentionActiveForLevel(level) || !(collectedBits(level) & bit)) { - return; - } - ev->result = nullptr; - event->Cancelled = true; - }); - - COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, CVAR_VALUE, { - (void)va_arg(args, int); - BundleInfo* bundleInfo = va_arg(args, BundleInfo*); - (void)va_arg(args, s32); - (void)va_arg(args, f32*); - (void)va_arg(args, Actor**); - - if (!systemActive() || bundleInfo == nullptr) { - return; - } - u8 bit = jinjoBitFromActor(bundleInfo->actor_id); - if (bit == 0) { - return; - } - int32_t level = level_get(); - if (!retentionActiveForLevel(level) || !(collectedBits(level) & bit)) { - return; - } - *should = true; - }); -} - -static RegisterShipInitFunc initJinjoRetention(RegisterJinjoRetention_Init, { CVAR_JINJO_RETENTION }); - -static void RegisterRetentionSaving_Init() { - // bcopy's scratch-slot save buffer doesn't carry our bits; sync them in. - COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { - OnSaveFileSave* ev = (OnSaveFileSave*)event; - SaveData* buf = (SaveData*)ev->saveBuffer; - JinjoRetentionSaveData* live = store(); - if (buf != nullptr && live != nullptr && &buf->shipSaveData.jinjoRetention != live) { - buf->shipSaveData.jinjoRetention = *live; - } - }); -} - -static RegisterShipInitFunc initRetentionSaving(RegisterRetentionSaving_Init); diff --git a/src/port/Enhancements/Retention/NoteRetention.cpp b/src/port/Enhancements/Retention/NoteRetention.cpp deleted file mode 100644 index 4c4d23bac..000000000 --- a/src/port/Enhancements/Retention/NoteRetention.cpp +++ /dev/null @@ -1,495 +0,0 @@ -// Note Collection Retention -// -// Notes are identified by (mapId, spawn-order index) from the map's deterministic cube parse. -// Bundle notes store identity in actor->local (survives sub-area save/restore, which copies -// the actor struct but assigns a new marker). -// -#include "port/ObjectExtension/ObjectExtension.h" -#include -#include - -#include "port/UI/cvar_prefixes.h" -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Enhancements/Retention/Retention.h" -#include "port/Romhack/RomhackConfig.h" -#include "port/Rando/Rando.h" -#include "port/Rando/CustomObject/CustomObject.h" - -#include -#include -#include - -#include "functions.h" -extern "C" { -#include "enums.h" -#include "actor.h" -#include "prop.h" - -extern f32 gBundle_yaw; -extern ActorInfo sumusicNote; -} - -namespace { - -#define CVAR_NOTE_RETENTION CVAR_ENHANCEMENT("Gameplay.NoteRetention") -static bool sForcedByAnchor = false; -#define CVAR_VALUE (CVarGetInteger(CVAR_NOTE_RETENTION, 0) || sForcedByAnchor) - -constexpr s32 kNoteSpriteAsset = ASSET_6D6_SPRITE_MUSIC_NOTE; - -// Per-actor note identity. Parenthesized ctor avoids brace-init commas breaking event macros. -struct NoteRetentionData { - int32_t mapId; - int32_t noteIndex; - NoteRetentionData(int32_t map = 0, int32_t index = 0) : mapId(map), noteIndex(index) { - } -}; -ObjectExtension::Register NoteRetentionDataRegister; - -// Identity for bundle notes, stored in actor->local (survives sub-area restore; a new marker -// is assigned, so an extension wouldn't). magic distinguishes our data from garbage. -constexpr uint32_t kNoteLocalMagic = 0x4E4F5445u; // 'NOTE' -struct NoteLocal { - uint32_t magic; - int32_t mapId; - int32_t noteIndex; -}; - -NoteLocal* bundleNoteLocal(Actor* actor) { - if (actor == nullptr) { - return nullptr; - } - NoteLocal* nl = reinterpret_cast(actor->local); - return (nl->magic == kNoteLocalMagic) ? nl : nullptr; -} - -struct QueuedNote { - int32_t pos[3]; - int32_t mapId; - int32_t noteIndex; - bool spawned; -}; - -int32_t noteCounter = 0; -std::vector noteActorQueue; -std::unordered_map activeNoteSet; - -// Notes taken since entering this level: reproduces the prop "taken" bit they lost to actors. -std::unordered_set collectedThisVisit; -int32_t sVisitLevel = -1; - -int64_t noteKey(int32_t mapId, int32_t noteIndex) { - return ((int64_t)mapId << 32) | (uint32_t)noteIndex; -} - -// 0 for maps outside the section table; map_getLevel would deref null on those. -int32_t levelOfMap(int32_t map) { - if (map <= 0 || map >= MAP_NUM_MAPS) { - return 0; - } - return (int32_t)map_getLevel((enum map_e)map); -} - -using retention::activeSlot; -using retention::systemActive; - -// Level whose note count is waiting to be seeded; -1 when nothing is pending. -int32_t sPendingSeedLevel = -1; - -bool applyEnabled() { - return CVAR_VALUE; -} - -// Rando drives note props on this same VB when they're shuffled, writing *should for every one -// of them — hand the class over rather than race it on listener order. -bool randoOwnsNoteProps() { - return IS_RANDO && RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue; -} - -NoteRetentionSaveData* store() { - int32_t slot = activeSlot(); - return slot >= 0 ? &gameFile_saveData[slot].shipSaveData.noteRetention : nullptr; -} - -bool indexInRange(int32_t mapId, int32_t index) { - return mapId >= 0 && mapId < NOTE_RETENTION_MAP_SLOTS && index >= 0 && index < NOTE_RETENTION_NOTES_PER_MAP; -} - -bool isCollected(int32_t mapId, int32_t index) { - NoteRetentionSaveData* s = store(); - if (s == nullptr || !indexInRange(mapId, index)) { - return false; - } - return (s->collected[mapId][index >> 3] >> (index & 7)) & 1; -} - -void setCollected(int32_t mapId, int32_t index) { - NoteRetentionSaveData* s = store(); - if (s == nullptr || !indexInRange(mapId, index)) { - return; - } - s->collected[mapId][index >> 3] |= (uint8_t)(1 << (index & 7)); -} - -int32_t countCollectedForLevel(int32_t levelId) { - NoteRetentionSaveData* s = store(); - if (s == nullptr) { - return 0; - } - int32_t total = 0; - for (int32_t mapId = 0; mapId < NOTE_RETENTION_MAP_SLOTS; mapId++) { - // Skip empty maps: map_getLevel crashes on non-existent ids (e.g. MAP_0_UNKNOWN). - int32_t mapTotal = 0; - for (int32_t b = 0; b < NOTE_RETENTION_BYTES_PER_MAP; b++) { - uint8_t byte = s->collected[mapId][b]; - while (byte) { - mapTotal += byte & 1; - byte >>= 1; - } - } - if (mapTotal == 0) { - continue; - } - if (map_getLevel((enum map_e)mapId) == (enum level_e)levelId) { - total += mapTotal; - } - } - return total; -} - -bool isInParade() { - return volatileFlag_get(VOLATILE_FLAG_1F_IN_CHARACTER_PARADE) || - volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE); -} - -} // namespace - -extern "C" void port_noteRetention_getSizeAndPtr(int32_t* size, uint8_t** addr) { - NoteRetentionSaveData* s = store(); - if (s == nullptr) { - *size = 0; - *addr = nullptr; - return; - } - *size = (int32_t)sizeof(NoteRetentionSaveData); - *addr = (uint8_t*)s; -} - -// Called from the actual pickup (MARKER_5F_MUSIC_NOTE), not broad-phase collision. -extern "C" void port_noteRetention_onLocalNoteCollected(void* markerPtr) { - if (!systemActive()) { - return; - } - ActorMarker* marker = (ActorMarker*)markerPtr; - if (marker == nullptr || marker->id != MARKER_5F_MUSIC_NOTE) { - return; - } - int32_t mapId; - int32_t noteIndex; - NoteRetentionData* data = ObjectExtension::GetInstance().Get(marker); - if (data != nullptr) { - mapId = data->mapId; - noteIndex = data->noteIndex; - ObjectExtension::GetInstance().Remove(marker); - } else if (NoteLocal* nl = bundleNoteLocal(marker_getActor(marker))) { - mapId = nl->mapId; - noteIndex = nl->noteIndex; - nl->magic = 0; // consumed - } else { - return; // not one of ours - } - bool wasCollected = isCollected(mapId, noteIndex); - setCollected(mapId, noteIndex); - collectedThisVisit.insert(noteKey(mapId, noteIndex)); - activeNoteSet.erase(noteKey(mapId, noteIndex)); - if (!wasCollected) { - CALL_EVENT(OnCollectibleCollected, ANCHOR_COLLECTIBLE_NOTE, noteIndex); - } -} - -extern "C" void port_noteRetention_applyRemoteCollect(int32_t mapId, int32_t noteIndex, int32_t sameMap) { - bool already = isCollected(mapId, noteIndex); - setCollected(mapId, noteIndex); - if (!already) { - // ITEM_C_NOTE is per-level; item_inc also bumps the high score and pause total. - int32_t level = map_getLevel((enum map_e)mapId); - if (level == (int32_t)level_get()) { - item_inc(ITEM_C_NOTE); - } else { - // Different level: can't touch live ITEM_C_NOTE, still bump its high score. - itemscore_noteScores_setLevel((enum level_e)level, countCollectedForLevel(level)); - } - } - if (sameMap) { - // Erase before despawn: OnActorDestroy's hook also erases this key. - auto it = activeNoteSet.find(noteKey(mapId, noteIndex)); - if (it != activeNoteSet.end()) { - ActorMarker* m = it->second; - activeNoteSet.erase(it); - if (m != nullptr) { - marker_despawn(m); - } - } - } -} - -// Called from gsworld_load before cube parsing; fires on every re-parse (map load, intra- -// level warps). Resets the index counter. -extern "C" void port_noteRetention_beginMapLoad(int32_t mapId) { - noteCounter = 0; - noteActorQueue.clear(); - // Sub-area hops stay within the visit; only a real level change lets notes come back. - int32_t level = levelOfMap(mapId); - if (level != sVisitLevel) { - sVisitLevel = level; - collectedThisVisit.clear(); - } -} - -extern "C" void port_noteRetention_onActorsFreed(void) { - for (auto& [key, marker] : activeNoteSet) { - ObjectExtension::GetInstance().Remove(marker); - } - activeNoteSet.clear(); - noteActorQueue.clear(); -} - -extern "C" void port_noteRetention_setForced(int32_t forced) { - sForcedByAnchor = forced != 0; - ShipInit::Init(CVAR_NOTE_RETENTION); -} - -extern "C" int32_t port_noteRetention_debugPickLive(int32_t mapId) { - for (auto& [key, marker] : activeNoteSet) { - int32_t keyMap = (int32_t)(key >> 32); - int32_t index = (int32_t)(uint32_t)(key & 0xFFFFFFFF); - if (keyMap == mapId && !isCollected(keyMap, index)) { - return index; - } - } - return -1; -} - -void RegisterNoteRetention_Init() { - // Bundle notes continue the map's index counter; identity stored in actor->local. - COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, true, { - bundle_e bundleId = (bundle_e)va_arg(args, int); - BundleInfo* bundleInfo = va_arg(args, BundleInfo*); - va_arg(args, s32); // index within the bundle (unused) - f32* position = va_arg(args, f32*); - Actor** actorOut = va_arg(args, Actor**); - - if (!systemActive() || bundleInfo == nullptr || bundleInfo->actor_id != ACTOR_51_MUSIC_NOTE) { - return; // not our note bundle - } - - int32_t mapId = (int32_t)gsworld_getMap(); - int32_t noteIndex = noteCounter++; - if (!indexInRange(mapId, noteIndex)) { - return; // out of addressable range - } - - // We own this note: suppress the vanilla bundle spawn. - *should = true; - - int64_t key = noteKey(mapId, noteIndex); - if (activeNoteSet.count(key)) { - return; // a live actor already exists (re-trigger this load) - } - if ((applyEnabled() && isCollected(mapId, noteIndex)) || collectedThisVisit.count(key)) { - return; - } - - int32_t pos[3]; - pos[0] = (int32_t)position[0]; - pos[1] = (int32_t)position[1]; - pos[2] = (int32_t)position[2]; - Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); - if (note == nullptr) { - return; - } - NoteLocal* nl = reinterpret_cast(note->local); - nl->magic = kNoteLocalMagic; - nl->mapId = mapId; - nl->noteIndex = noteIndex; - - ApplyBundleActorPhysics(note, (int32_t)bundleId, bundleInfo, gBundle_yaw); - - activeNoteSet[key] = note->marker; - *actorOut = note; - }); - - // Seed the level's note counter from collected notes. - COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent* event) { - OnSetJiggyList* ev = (OnSetJiggyList*)event; - sPendingSeedLevel = ev->levelId; - }); - - COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVAR_VALUE, [](IEvent*) { - if (sPendingSeedLevel < 0) { - return; - } - if (getGameMode() != GAME_MODE_3_NORMAL) { - // Demo or playback: drop the seed, its score state is scratch. Anything else - // (transition, pause) just waits for normal play to resume. - if (func_802E4A08()) { - sPendingSeedLevel = -1; - } - return; - } - const int32_t level = sPendingSeedLevel; - sPendingSeedLevel = -1; - if (!systemActive() || !applyEnabled() || isInParade()) { - return; - } - item_adjustByDiffWithoutHud(ITEM_C_NOTE, countCollectedForLevel(level) - item_getCount(ITEM_C_NOTE)); - }); - - // Seeding ITEM_C_NOTE re-triggers vanilla high-score dialogs; suppress them. - COND_VB_SHOULD(VB_OVERRIDE_DIALOG_SHOW, EVENT_PRIORITY_NORMAL, true, { - s32 textId = va_arg(args, s32); - // Bottles' 50-note-door line assumes vanilla note-door costs, which - // romhacks retune, so it is wrong for them whether or not retention is - // on. In vanilla it stays: it's an aide for new players. - if (textId == 0xF74 && port_isRomhack()) { - *should = true; - } else if (applyEnabled()) { - switch (textId) { - case 0xD9C: // Bottles' first-note text: "you can't take notes with you" - case 0xF76: // "you just beat your high score" - // 0xF78 (every note in the level) is left alone here; hacks that - // want it gone suppress it per-hack, as Gruntch does. - *should = true; - break; - default: - break; - } - } - }); -} - -static RegisterShipInitFunc initNoteRetention(RegisterNoteRetention_Init, { CVAR_NOTE_RETENTION }); - -// Always registered: the sprite-prop pickup path has no marker to record through, so notes must -// be actors even when the enhancement isn't applying. Only the suppression below is gated. -static void RegisterRetentionSaving_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { - collectedThisVisit.clear(); - sVisitLevel = -1; - }); - - // The cube parse rebuilds static notes every map load, so a restored copy would double them - // on a sub-area round trip. Bundle notes have no parse to come from and must survive. - REGISTER_LISTENER(OnLoadActorSaveState, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnLoadActorSaveState* ev = (OnLoadActorSaveState*)event; - if (!systemActive() || ev->actor == nullptr) { - return; - } - if ((int32_t)ev->actor->modelCacheIndex != ACTOR_51_MUSIC_NOTE) { - return; - } - if (ev->actor->is_bundle && bundleNoteLocal(ev->actor) != nullptr) { - return; // keep restored bundle notes alive - } - event->Cancelled = true; - }); - - COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { - s16* spawnPosition = va_arg(args, s16*); - s32 spriteAsset = va_arg(args, s32); - - if (!systemActive() || spriteAsset != kNoteSpriteAsset) { - return; - } - - int32_t mapId = (int32_t)gsworld_getMap(); - int32_t noteIndex = noteCounter++; - if (!indexInRange(mapId, noteIndex)) { - return; // out of addressable range - } - - // Counter already advanced, so indices stay aligned; rando spawns these itself. - if (randoOwnsNoteProps()) { - return; - } - - // We own this note: suppress the static sprite prop. - *should = true; - - if (activeNoteSet.count(noteKey(mapId, noteIndex))) { - return; // a live actor already exists (re-parse) - } - - if ((applyEnabled() && isCollected(mapId, noteIndex)) || collectedThisVisit.count(noteKey(mapId, noteIndex))) { - return; - } - - QueuedNote queued; - queued.pos[0] = spawnPosition[0]; - queued.pos[1] = spawnPosition[1]; - queued.pos[2] = spawnPosition[2]; - queued.mapId = mapId; - queued.noteIndex = noteIndex; - queued.spawned = false; - noteActorQueue.push_back(queued); - }); - - // Flush queued notes into actors. actor_new does not re-fire OnActorSpawn. - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { - if (!systemActive() || noteActorQueue.empty()) { - return; - } - for (auto& q : noteActorQueue) { - if (q.spawned) { - continue; - } - int32_t pos[3]; - pos[0] = q.pos[0]; - pos[1] = q.pos[1]; - pos[2] = q.pos[2]; - Actor* note = actor_new(pos, 0, &sumusicNote, ACTOR_FLAG_UNKNOWN_21); - if (note != nullptr) { - note->unk124_6 = 0; - } - ActorMarker* marker = (note != nullptr) ? note->marker : nullptr; - if (marker != nullptr) { - // Key on the marker (stable across the actor's life). - ObjectExtension::GetInstance().Set(marker, NoteRetentionData(q.mapId, q.noteIndex)); - activeNoteSet[noteKey(q.mapId, q.noteIndex)] = marker; - } - q.spawned = true; - } - }); - - COND_HOOK(OnActorDestroy, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { - OnActorDestroy* ev = (OnActorDestroy*)event; - if (ev->actor == nullptr) { - return; - } - if (ev->actor->marker != nullptr) { - NoteRetentionData* data = ObjectExtension::GetInstance().Get(ev->actor->marker); - if (data != nullptr) { - activeNoteSet.erase(noteKey(data->mapId, data->noteIndex)); - } - ObjectExtension::GetInstance().Remove(ev->actor->marker); - } - if (NoteLocal* nl = bundleNoteLocal(ev->actor)) { - activeNoteSet.erase(noteKey(nl->mapId, nl->noteIndex)); - nl->magic = 0; - } - }); - - // bcopy's scratch-slot save buffer doesn't carry our bits; sync them in. - COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { - OnSaveFileSave* ev = (OnSaveFileSave*)event; - SaveData* buf = (SaveData*)ev->saveBuffer; - NoteRetentionSaveData* live = store(); - if (buf != nullptr && live != nullptr && &buf->shipSaveData.noteRetention != live) { - buf->shipSaveData.noteRetention = *live; - } - }); -} - -static RegisterShipInitFunc initRetentionSaving(RegisterRetentionSaving_Init); diff --git a/src/port/Enhancements/Retention/Retention.cpp b/src/port/Enhancements/Retention/Retention.cpp deleted file mode 100644 index 0c26dfc39..000000000 --- a/src/port/Enhancements/Retention/Retention.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Helpers shared by the note and jinjo retention systems. -// -// libultraship must precede the decomp headers: core2/timedfunc.h (via functions.h) defines a -// C-compat `reinterpret_cast` macro that breaks the MSVC C++ standard library. -#include -#include "port/Enhancements/Retention/Retention.h" -#include "port/Rando/Rando.h" // selectedFileNum, gameFile_saveData, DEFAULT_FILE_NUM, FILE_TYPE_SAVE_RANDO - -#include "functions.h" -extern "C" { -#include "enums.h" -} - -namespace retention { - -int32_t activeSlot() { - if (selectedFileNum == DEFAULT_FILE_NUM || selectedFileNum < 0 || selectedFileNum >= 4) { - return -1; - } - return (int32_t)selectedFileNum; -} - -bool systemActive() { - int32_t slot = activeSlot(); - if (slot < 0 || gameFile_saveData[slot].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { - return false; - } - return !func_802E4A08(); -} - -} // namespace retention diff --git a/src/port/Enhancements/Retention/Retention.h b/src/port/Enhancements/Retention/Retention.h deleted file mode 100644 index 63a19352a..000000000 --- a/src/port/Enhancements/Retention/Retention.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef PORT_RETENTION_H -#define PORT_RETENTION_H - -// Shared header for the vanilla collectible-retention systems (notes and jinjos). - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// --- Note retention --- - -void port_noteRetention_beginMapLoad(int32_t mapId); -void port_noteRetention_onActorsFreed(void); - -// Live slot's note-retention bytes for Anchor team-state sync (size 0 / null if no slot). -void port_noteRetention_getSizeAndPtr(int32_t* size, uint8_t** addr); - -void port_noteRetention_applyRemoteCollect(int32_t mapId, int32_t noteIndex, int32_t sameMap); - -// Record + broadcast a local note pickup (marker is ActorMarker*, void* to avoid engine types). -void port_noteRetention_onLocalNoteCollected(void* marker); - -// Force retention on/off regardless of the user CVar (Anchor uses this while connected). -void port_noteRetention_setForced(int32_t forced); - -// --- Jinjo retention --- - -// Live slot's jinjo-retention bytes for Anchor team-state sync (size 0 / null if no slot). -void port_jinjoRetention_getSizeAndPtr(int32_t* size, uint8_t** addr); - -void port_jinjoRetention_applyRemoteCollect(int32_t map, int32_t bit, int32_t sameMap); - -// Record + broadcast a local jinjo pickup. Call from the actual collection, not proximity. -void port_jinjoRetention_onLocalJinjoCollected(int32_t markerId); - -// Force retention on/off regardless of the user CVar (Anchor uses this while connected). -void port_jinjoRetention_setForced(int32_t forced); - -// --- CCW carried-collectible live-despawn sync (worms for Eyrie, acorns for Nabnut) --- -// -// Carried count is ITEM_22/23. Object identity is a hash of its fixed spawn position. `kind` = -// ANCHOR_COLLECTIBLE_WORM/_ACORN; marker is ActorMarker* (void* to avoid engine types). - -void port_carriedSync_beginMapLoad(int32_t mapId); - -// Registers a world object, attaching spawn-position identity to the marker. Sets *suppress -// non-zero if a teammate already collected it. -void port_carriedSync_register(int32_t kind, void* marker, int32_t x, int32_t y, int32_t z, int32_t* suppress); - -void port_carriedSync_onLocalCollect(int32_t kind, void* marker); - -// Broadcast a local spend (feeding Eyrie/Nabnut): -1 to the shared pool. -void port_carriedSync_onLocalSpend(int32_t kind); - -// Apply a teammate's pickup (id = spawn-position hash): marks it collected. -void port_carriedSync_applyRemoteCollect(int32_t kind, int32_t mapId, int32_t id, int32_t sameMap); - -// True if a teammate collected this object (caller should despawn). -int32_t port_carriedSync_consumeRemoteDespawn(int32_t kind, void* marker); - -int32_t port_carriedSync_collectedCount(int32_t kind); - -void setCollectedBits(int32_t level, u8 bits); -uint8_t jinjoBitFromActor(int32_t actorId); -uint8_t collectedBits(int32_t level); - -#ifdef __cplusplus -} - -namespace retention { -// Active save slot index (0-3) for the current game, or -1 (default/demo file). -int32_t activeSlot(); -// False during demos, Bottles bonus games, and rando files. -bool systemActive(); -} // namespace retention -#endif - -#endif diff --git a/src/port/Enhancements/Retention/WormSync.cpp b/src/port/Enhancements/Retention/WormSync.cpp deleted file mode 100644 index b2716fd09..000000000 --- a/src/port/Enhancements/Retention/WormSync.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// CCW Carried-Collectible Live-Despawn Sync (worms for Eyrie, acorns for Nabnut). -// -// Carried count is ITEM_22/23. Object identity is a hash of its fixed spawn position, keyed -// with (kind, mapId, hash). -// -#include -#include "port/ObjectExtension/ObjectExtension.h" -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Enhancements/Retention/Retention.h" - -#include -#include - -#include "functions.h" -extern "C" { -#include "enums.h" -#include "actor.h" -} - -namespace { - -// Per-object identity. Parenthesized ctor avoids brace-init commas breaking event macros. -struct CarriedSpawnData { - int32_t mapId; - int32_t hash; - CarriedSpawnData(int32_t m = 0, int32_t h = 0) : mapId(m), hash(h) { - } -}; -ObjectExtension::Register CarriedSpawnDataRegister; - -// (slot, mapId, hash) of every carried collectible the team has picked up this session. -std::set> sCollected; - -int32_t slotForKind(int32_t kind) { - switch (kind) { - case ANCHOR_COLLECTIBLE_WORM: - return 0; - case ANCHOR_COLLECTIBLE_ACORN: - return 1; - case ANCHOR_COLLECTIBLE_PRESENT_BLUE: - return 2; - case ANCHOR_COLLECTIBLE_PRESENT_GREEN: - return 3; - case ANCHOR_COLLECTIBLE_PRESENT_RED: - return 4; - case ANCHOR_COLLECTIBLE_GOLD: - return 5; - case ANCHOR_COLLECTIBLE_ORANGE: - return 6; - default: - return -1; - } -} - -// Identity from spawn position; masked non-negative to avoid the -1 spend sentinel. -int32_t spawnHash(int32_t x, int32_t y, int32_t z) { - uint32_t h = (uint32_t)x * 73856093u ^ (uint32_t)y * 19349663u ^ (uint32_t)z * 83492791u; - return (int32_t)(h & 0x7FFFFFFFu); -} - -bool isCollected(int32_t slot, int32_t mapId, int32_t hash) { - return sCollected.count({ slot, mapId, hash }) != 0; -} - -// Gold and the presents feed a credit-back reconcile that rebuilds carried counts as -// collected-minus-delivered. Respawn suppression and that credit must fire together -// or a collected item is lost across a reload, so both are scoped to the consumer's -// level; outside it, neither runs and the collectible simply respawns, as on hardware. -bool kindAllowedFor(int32_t kind, int32_t mapId) { - switch (kind) { - case ANCHOR_COLLECTIBLE_GOLD: - return (int32_t)map_getLevel((enum map_e)mapId) == LEVEL_2_TREASURE_TROVE_COVE; - case ANCHOR_COLLECTIBLE_PRESENT_BLUE: - case ANCHOR_COLLECTIBLE_PRESENT_GREEN: - case ANCHOR_COLLECTIBLE_PRESENT_RED: - return (int32_t)map_getLevel((enum map_e)mapId) == LEVEL_5_FREEZEEZY_PEAK; - default: - return true; - } -} - -bool inDemoPlayback() { - return func_802E4A08() != 0; -} - -} // namespace - -extern "C" void port_carriedSync_beginMapLoad(int32_t mapId) { - (void)mapId; -} - -extern "C" void port_carriedSync_register(int32_t kind, void* marker, int32_t x, int32_t y, int32_t z, - int32_t* suppress) { - *suppress = 0; - int32_t slot = slotForKind(kind); - if (slot < 0 || marker == nullptr) { - return; - } - int32_t mapId = (int32_t)gsworld_getMap(); - int32_t hash = spawnHash(x, y, z); - ObjectExtension::GetInstance().Set(marker, CarriedSpawnData(mapId, hash)); - if (!inDemoPlayback() && kindAllowedFor(kind, mapId) && isCollected(slot, mapId, hash)) { - *suppress = 1; - } -} - -extern "C" void port_carriedSync_onLocalCollect(int32_t kind, void* marker) { - int32_t slot = slotForKind(kind); - if (slot < 0 || inDemoPlayback()) { - return; - } - CarriedSpawnData* d = ObjectExtension::GetInstance().Get(marker); - if (d == nullptr) { - return; - } - sCollected.insert({ slot, d->mapId, d->hash }); - CALL_EVENT(OnCollectibleCollected, kind, d->hash); -} - -extern "C" void port_carriedSync_onLocalSpend(int32_t kind) { - if (slotForKind(kind) < 0 || inDemoPlayback()) { - return; - } - // A spend (feeding Eyrie/Nabnut) is -1 to the shared pool. - CALL_EVENT(OnCollectibleCollected, kind, -1); -} - -extern "C" void port_carriedSync_applyRemoteCollect(int32_t kind, int32_t mapId, int32_t id, int32_t sameMap) { - (void)sameMap; - int32_t slot = slotForKind(kind); - if (slot < 0 || id < 0) { - return; - } - sCollected.insert({ slot, mapId, id }); -} - -// Snapshot/restore as flat [slot, mapId, hash] tuples. -std::vector port_carriedSync_snapshotCollected() { - std::vector flat; - flat.reserve(sCollected.size() * 3); - for (const auto& e : sCollected) { - flat.insert(flat.end(), e.begin(), e.end()); - } - return flat; -} - -void port_carriedSync_restoreCollected(const std::vector& flat) { - sCollected.clear(); - for (size_t i = 0; i + 3 <= flat.size(); i += 3) { - sCollected.insert({ flat[i], flat[i + 1], flat[i + 2] }); - } -} - -extern "C" int32_t port_carriedSync_collectedCount(int32_t kind) { - int32_t slot = slotForKind(kind); - if (slot < 0) { - return 0; - } - int32_t count = 0; - for (const auto& e : sCollected) { - if (e[0] == slot && kindAllowedFor(kind, e[1])) { - count++; - } - } - return count; -} - -void port_carriedSync_clearForLevel(int32_t levelId) { - std::erase_if(sCollected, [levelId](const std::array& e) { - return (int32_t)map_getLevel((enum map_e)e[1]) == levelId; - }); -} - -extern "C" int32_t port_carriedSync_consumeRemoteDespawn(int32_t kind, void* marker) { - int32_t slot = slotForKind(kind); - if (slot < 0) { - return 0; - } - CarriedSpawnData* d = ObjectExtension::GetInstance().Get(marker); - if (d == nullptr) { - return 0; - } - return isCollected(slot, d->mapId, d->hash) ? 1 : 0; -} - -void RegisterWormSync_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sCollected.clear(); }); - - REGISTER_LISTENER(OnActorDestroy, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnActorDestroy* ev = (OnActorDestroy*)event; - if (ev->actor != nullptr && ev->actor->marker != nullptr) { - ObjectExtension::GetInstance().Remove(ev->actor->marker); - } - }); -} - -static RegisterShipInitFunc initWormSync(RegisterWormSync_Init, {}); diff --git a/src/port/Enhancements/Trackers/DisplayOverlay.cpp b/src/port/Enhancements/Trackers/DisplayOverlay.cpp index 97a97f822..bc8bdf4be 100644 --- a/src/port/Enhancements/Trackers/DisplayOverlay.cpp +++ b/src/port/Enhancements/Trackers/DisplayOverlay.cpp @@ -10,12 +10,20 @@ #include "save.h" #include "enums.h" -#include "functions.h" extern "C" { +enum map_e gsworld_getMap(void); +enum level_e map_getLevel(enum map_e map); +u16 itemscore_timeScores_get(enum level_e level_id); + +uint64_t GetUnixTimestamp(); extern SaveData gameFile_saveData[4]; } +float windowScale = 1.0f; +ImVec4 windowBG = ImVec4(0, 0, 0, 0.5f); +static constexpr ImVec4 tintColor = {}; + const std::vector timerDisplayOptions = { "Display Off", // TIMER_DISPLAY_NONE "Real-Time", // TIMER_DISPLAY_RTA @@ -31,7 +39,7 @@ int64_t DisplayOverlay_GetTotalInGameTime() { } void DisplayOverlayWindow::Draw() { - if (gsworld_getMap() == MAP_91_FILE_SELECT) { + if (!IsVisible() || gsworld_getMap() == MAP_91_FILE_SELECT) { return; } diff --git a/src/port/Extractor/GameExtractor.cpp b/src/port/Extractor/GameExtractor.cpp index d20911f0e..cb82abfb3 100644 --- a/src/port/Extractor/GameExtractor.cpp +++ b/src/port/Extractor/GameExtractor.cpp @@ -14,7 +14,6 @@ #include #include "ship/Context.h" -#include "port/FilePicker.h" #include "spdlog/spdlog.h" #include @@ -28,7 +27,10 @@ #ifndef __SWITCH__ #include "Companion.h" #include "factories/bk64/ConfigFactory.h" -#include "port/Romhack/RomhackTable.h" + +#if !defined(__IOS__) && !defined(__ANDROID__) && !defined(__SWITCH__) +#include "portable-file-dialogs.h" +#endif std::string GameExtractor::sStatusText; std::string GameExtractor::sLastError; @@ -95,21 +97,53 @@ bool GameExtractor::RunStandalone(std::string rom) { return true; } -// Load a ROM from disk into mGameData. The caller does the picking (asynchronously on the boot path — -// see Engine.cpp PS_FIRST/PS_FIRST_WAIT), so this is just the read. -bool GameExtractor::LoadRomFromPath(const std::string& romPath) { - if (!std::filesystem::exists(romPath)) { - SPDLOG_ERROR("Failed to find ROM at path: {}", romPath); +bool GameExtractor::SelectGameFromUI() { + //// Store both path and already-read data + std::string romPath; + std::vector romData; + +#if !defined(__IOS__) && !defined(__ANDROID__) && !defined(__SWITCH__) + // Desktop: fallback to file dialogue if no baserom found + // if (!foundGame) { + if (!pfd::settings::available()) { + SPDLOG_ERROR("portable-file-dialogs is not available on this system."); return false; } - std::ifstream inFile(romPath, std::ios::binary); - if (!inFile.is_open()) { + auto selection = pfd::open_file("Select a file", ".", { "N64 Roms", "*.z64" }).result(); + if (selection.empty()) { return false; } - std::vector romData(std::istreambuf_iterator(inFile), {}); - inFile.close(); + romPath = selection[0]; + //} +#else + // Mobile: fallback to baserom.us.z64 + if (/*!foundGame && */ !std::filesystem::exists(Ship::Context::GetPathRelativeToAppDirectory("baserom.us.z64"))) { + SPDLOG_ERROR("baserom not found"); + return false; + } + + // if (!foundGame) { + romPath = Ship::Context::GetPathRelativeToAppDirectory("baserom.us.z64"); + //} +#endif + + // Load file if it is not already open + if (romData.empty()) { + if (!std::filesystem::exists(romPath)) { + SPDLOG_ERROR("Failed to find ROM at path: {}", romPath); + return false; + } + + std::ifstream inFile(romPath, std::ios::binary); + if (!inFile.is_open()) { + return false; + } + + romData = std::vector(std::istreambuf_iterator(inFile), {}); + inFile.close(); + } this->mGamePath = romPath; this->mGameData = std::move(romData); @@ -134,7 +168,7 @@ void GameExtractor::GetRoms(std::vector& roms) { // Check for any standard N64 rom file extensions. if (ext != NULL && (strcmp(ext, ".z64") == 0) /* || (strcmp(ext, ".n64") == 0) || (strcmp(ext, ".v64") == 0)*/) - roms.push_back(mSearchPath + "/" + ffd.cFileName); + roms.push_back(ffd.cFileName); } } while (FindNextFileA(h, &ffd) != 0); FindClose(h); @@ -148,23 +182,20 @@ void GameExtractor::GetRoms(std::vector& roms) { while ((dir = readdir(d)) != NULL) { struct stat path; - // Against the full path: a bare name would be resolved relative to the - // working directory, so searching anywhere else stat'd the wrong file (or - // nothing) and left path uninitialised for the S_ISREG test below. - const std::string fullPath = mSearchPath + "/" + dir->d_name; - if (stat(fullPath.c_str(), &path) != 0 || !S_ISREG(path.st_mode)) { - continue; - } + // Check if current entry is not folder + stat(dir->d_name, &path); + if (S_ISREG(path.st_mode)) { - // Get the position of the extension character. - char* ext = strrchr(dir->d_name, '.'); - if (ext != NULL && - (strcmp(ext, ".z64") == 0 /* || strcmp(ext, ".n64") == 0 || strcmp(ext, ".v64") == 0*/)) { - roms.push_back(fullPath); + // Get the position of the extension character. + char* ext = strrchr(dir->d_name, '.'); + if (ext != NULL && + (strcmp(ext, ".z64") == 0 /* || strcmp(ext, ".n64") == 0 || strcmp(ext, ".v64") == 0*/)) { + roms.push_back(dir->d_name); + } } } - closedir(d); } + closedir(d); #else for (const auto& file : std::filesystem::directory_iterator(mSearchPath)) { if (file.is_directory()) { @@ -308,31 +339,9 @@ bool GameExtractor::GenerateOTR(std::atomic& assetCount, std::atomicmGameData, ccKind, ccSha1); - const bool rebuiltOverlay = BK64::ClassifyRomhack(this->mGameData) == BK64::RomhackKind::CustomBuild; - bool promptCustomCode = rebuiltOverlay; - if (!promptCustomCode && hasBlob) { - if (const auto* entry = Lighthouse::LookupRomhackEntry(ccSha1)) { - // Known blob: the table's verdict beats the location heuristic — an - // isPorted=false row means analysis found real un-ported code even - // inside a globalization-kind blob (e.g. Nostalgia 64). - promptCustomCode = !entry->isPorted; - if (!promptCustomCode) { - SPDLOG_INFO("[GameExtractor] Custom code blob {} is ported ({}); no warning needed.", ccSha1, - entry->identifier); - } - } else { - // Unknown blob: only injected blobs warrant the prompt; the stock - // globalization framework is covered by the statically linked build. - promptCustomCode = (ccKind == BK64::CustomCodeKind::BB_INJECTED); - } - } - if (promptCustomCode) { - SPDLOG_WARN("[GameExtractor] Romhack ships custom code ({}); prompting user before extraction.", - rebuiltOverlay ? "rebuilt code overlay, non-BB build" : "injected MIPS code blob"); + // Detect non-BB custom MIPS code injection + if (BK64::HasCustomCodeBlob(this->mGameData)) { + SPDLOG_WARN("[GameExtractor] Custom MIPS code detected in ROM; prompting user before extraction."); sCustomCodePromptResult = -1; sCustomCodePromptActive = true; sCustomCodePromptRequested = true; @@ -391,7 +400,7 @@ std::optional GameExtractor::ValidateChecksum() const { return std::nullopt; } -bool GameExtractor::LoadRomFromPath(const std::string& romPath) { +bool GameExtractor::SelectGameFromUI() { return false; } @@ -407,18 +416,3 @@ void GameExtractor::WritePortVersion() { // None } #endif - -// No #ifdef needed: Lighthouse::PickFile picks the backend (native dialog on desktop, ImGui browser -// on consoles/arm). The N64-ROM title/filters live here so libultraship stays game-agnostic. -void GameExtractor::SelectGameFromUI(std::function onComplete) { - Ship::FileBrowserRequest req; - req.Title = "Select a N64 ROM"; - req.Filters = { { "N64 ROMs (.z64, .n64, .v64)", { "*.z64", "*.n64", "*.v64" } }, { "All files", { "*" } } }; - Lighthouse::PickFile(std::move(req), - [this, onComplete = std::move(onComplete)](std::optional path) { - const bool ok = path.has_value() && LoadRomFromPath(path->string()); - if (onComplete) { - onComplete(ok); - } - }); -} diff --git a/src/port/Extractor/GameExtractor.h b/src/port/Extractor/GameExtractor.h index c754938f7..faa77dfcc 100644 --- a/src/port/Extractor/GameExtractor.h +++ b/src/port/Extractor/GameExtractor.h @@ -2,8 +2,6 @@ #include "Companion.h" #include -#include -#include #include #include #include @@ -13,11 +11,7 @@ class GameExtractor { static bool GenAssetFile(); std::optional ValidateChecksum() const; bool RunStandalone(std::string rom); - bool LoadRomFromPath(const std::string& romPath); - // Open the file picker for an N64 ROM, then load the choice into this extractor. onComplete - // reports whether a ROM was both picked and loaded. Treat as async: the extractor must outlive - // the pick (the boot flow keeps a long-lived instance; the Mod Menu holds a shared_ptr). - void SelectGameFromUI(std::function onComplete); + bool SelectGameFromUI(); void SetSearchPath(const std::string& path); void GetRoms(std::vector& roms); std::string GetRomPath(); diff --git a/src/port/FilePicker.cpp b/src/port/FilePicker.cpp deleted file mode 100644 index 438c242df..000000000 --- a/src/port/FilePicker.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "port/FilePicker.h" - -#if LIGHTHOUSE_NATIVE_FILE_DIALOG -#include -#include -#include "portable-file-dialogs.h" -#include "port/DevTools/ThreadWatchdog.h" -#endif - -namespace fs = std::filesystem; - -namespace Lighthouse { - -#if LIGHTHOUSE_NATIVE_FILE_DIALOG -// portable-file-dialogs takes a flat filter list: { label, "*.a *.b", label2, "*.c", ... }. -static std::vector ToPfdFilters(const std::vector& filters) { - std::vector out; - for (const auto& filter : filters) { - out.push_back(filter.Label); - std::string patterns; - for (const auto& pattern : filter.Patterns) { - if (!patterns.empty()) { - patterns += " "; - } - patterns += pattern; - } - out.push_back(patterns); - } - if (out.empty()) { - out = { "All Files", "*" }; - } - return out; -} -#endif - -void PickFile(Ship::FileBrowserRequest request, std::function)> onResult) { -#if LIGHTHOUSE_NATIVE_FILE_DIALOG - const std::string startDir = request.StartDir.empty() ? "." : request.StartDir.string(); - const std::vector filters = ToPfdFilters(request.Filters); - - std::optional result; - { - Lighthouse::ExpectedStall watchdogPause("native file dialog"); - if (request.Save) { - const std::string defaultPath = (fs::path(startDir) / request.DefaultName).string(); - std::string selection = pfd::save_file(request.Title, defaultPath, filters).result(); - if (!selection.empty()) { - result = fs::path(selection); - } - } else { - std::vector selection = pfd::open_file(request.Title, startDir, filters).result(); - if (!selection.empty()) { - result = fs::path(selection.front()); - } - } - } - if (onResult) { - onResult(result); - } -#else - request.OnResult = std::move(onResult); - Ship::FileBrowserWindow::Open(std::move(request)); -#endif -} - -} // namespace Lighthouse diff --git a/src/port/FilePicker.h b/src/port/FilePicker.h deleted file mode 100644 index 2cb6ff821..000000000 --- a/src/port/FilePicker.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "ship/window/gui/FileBrowserWindow.h" - -// Desktop platforms have a usable native file dialog (portable-file-dialogs). Consoles and Linux -// handhelds (arm) generally lack a native dialog / display server, so they fall back to -// libultraship's in-game ImGui file browser. Define LIGHTHOUSE_NATIVE_FILE_DIALOG to override. -#ifndef LIGHTHOUSE_NATIVE_FILE_DIALOG -#if defined(__SWITCH__) || defined(__WIIU__) || (defined(__linux__) && (defined(__aarch64__) || defined(__arm__))) -#define LIGHTHOUSE_NATIVE_FILE_DIALOG 0 -#else -#define LIGHTHOUSE_NATIVE_FILE_DIALOG 1 -#endif -#endif - -namespace Lighthouse { - -// Show a file picker described by @p request and deliver the chosen path (std::nullopt on cancel) to -// @p onResult. -// -// - Native builds (desktop): a blocking portable-file-dialogs dialog. onResult fires synchronously -// on the calling thread before PickFile returns. -// - ImGui builds (consoles / arm-linux): libultraship's FileBrowserWindow. onResult fires later on -// the render thread; PickFile returns immediately and is safe to call from any thread. -// -// Callers written for the async form (kick off, then poll a flag the callback sets) work with both -// backends unchanged: the native path just sets that flag before returning. -void PickFile(Ship::FileBrowserRequest request, std::function)> onResult); - -} // namespace Lighthouse diff --git a/src/port/Game.cpp b/src/port/Game.cpp index 05a50561e..9cf767564 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -1,13 +1,8 @@ #include "Engine.h" -#include -#include #include #include #include #include -#include -#include -#include #include #include @@ -18,15 +13,12 @@ #endif #include -#include "DevTools/ThreadWatchdog.h" #include "GameStatus.h" +#include "Interpolation/AdaptiveFps.h" #include "Interpolation/FrameInterpolation.h" -#include "Nametag/Nametag.h" #include "Network/Anchor/Anchor.h" -#include "OS/OS.h" #include "Patches/Patches.h" #include "ShipUtils.h" -#include "ShipInit.hpp" #include "src/port/Enhancements/Events/Hooks/Events.h" #include "UI/LighthouseModMenuWindow.h" @@ -34,219 +26,47 @@ extern "C" { #include "enums.h" #include "core1/core1.h" #include "core1/main.h" -#include "core1/thread5.h" -void viMgr_entry(void* arg); -void thread5_entry(void* arg); -void audioManagerThread_entry(void* arg); -void core1_15B30_sendMesg3ToRenderThread(void); -OSMesgQueue* thread5_getTaskQueue(void); -OSMesgQueue* thread5_getSyncQueue(void); -} - -// The game tick runs on its own thread and submits display lists through the -// decomp's thread5 queue; this thread stays behind as the RCP and event pump. -namespace { -std::atomic sGameThreadDone{ false }; -std::thread sGameThread; -thread_local bool tIsGameThread = false; - -// The interpolation pair a submitted list was built from, carried to whoever -// renders it. At most a couple are live at once. -struct InterpPair { - int prev = -1; - int curr = -1; - bool should = false; - uint64_t serial = 0; -}; -std::mutex sInterpMutex; -std::map sTaskInterp; -uint64_t sInterpSerial = 0; -// Submissions of slack before an unrendered pair is assumed dropped. The ring is -// 4 slots, so by then its trees have been recycled regardless. -constexpr uint64_t kInterpStaleAfter = 4; - -// Renderer calls made from tick code, run by the main loop between services. -std::mutex sSvcMutex; -std::condition_variable sSvcCv; -void (*sSvcFn)(void*) = nullptr; -void* sSvcArg = nullptr; -std::atomic sShutdownRequested{ false }; - -int sTitleMap = 0; - -void DrainRenderService() { - std::unique_lock lock(sSvcMutex); - if (sSvcFn != nullptr) { - auto* fn = sSvcFn; - void* arg = sSvcArg; - lock.unlock(); - fn(arg); - lock.lock(); - sSvcFn = nullptr; - sSvcCv.notify_all(); - } -} - -// False on the window thread, including everything that runs during init -// before the tick thread exists. -bool OnGameThread() { - return tIsGameThread; -} -} // namespace - -// A list is submitted while its tick is still recording, so the pair is -// captured here and travels with the task. -extern "C" void port_thread5_onSubmit(void* taskData) { - if (!OnGameThread() || (uintptr_t)taskData < 100) { - return; - } - struct ucode_task_data_s* task = (struct ucode_task_data_s*)taskData; - if (task->task_type != UCODE_TASK_TYPE_F3DEX && task->task_type != UCODE_TASK_TYPE_L3DEX) { - return; - } - InterpPair pair; - FrameInterpolation_GetRecordingPair(&pair.prev, &pair.curr, &pair.should); - FrameInterpolation_ClaimPair(pair.prev, pair.curr); - FrameInterpolation_StopRecord(); - Nametag::SubmitFrame(task->data_ptr); - std::lock_guard lock(sInterpMutex); - pair.serial = ++sInterpSerial; - auto [it, inserted] = sTaskInterp.emplace(task->data_ptr, pair); - if (!inserted) { - FrameInterpolation_ReleasePair(it->second.prev, it->second.curr); - it->second = pair; - } - - // Anything still here after a full trip round the ring can no longer be - // blended against a live tree, so its claim is only holding a slot hostage. - // Dropping the entry leaves RenderTask with a -1 pair, which renders - // uninterpolated rather than against a recycled tree. - for (auto stale = sTaskInterp.begin(); stale != sTaskInterp.end();) { - if (stale->second.serial + kInterpStaleAfter < pair.serial) { - FrameInterpolation_ReleasePair(stale->second.prev, stale->second.curr); - stale = sTaskInterp.erase(stale); - } else { - ++stale; - } - } -} - -namespace { -void RenderTask(void* dlStart) { - InterpPair pair; - { - std::lock_guard lock(sInterpMutex); - auto it = sTaskInterp.find(dlStart); - if (it != sTaskInterp.end()) { - pair = it->second; - sTaskInterp.erase(it); - } - } - FrameInterpolation_BeginRenderPass(pair.prev, pair.curr, pair.should); - Nametag::BeginRenderPass(dlStart, pair.should); - GameEngine::ProcessGfxCommands((Gfx*)dlStart); - FrameInterpolation_ReleasePair(pair.prev, pair.curr); -} - -// This thread plays the RCP: thread5 hands over a task, -// we run it and raise SP then DP. -int ServiceRcp() { - OSTask* task = OS_SpTakePendingTask(); - if (task == nullptr) { - return 0; - } - RenderTask(task->t.data_ptr); - OS_SendEventMesg(OS_EVENT_SP); - OS_SendEventMesg(OS_EVENT_DP); - return 1; -} - -// Called before core1_init, which is where these threads are created. -void EnableThread5() { - OS_EnableThreadEntry((void*)thread5_entry); - OS_SetQueueBlocking(thread5_getTaskQueue(), 1); - OS_SetQueueBlocking(thread5_getSyncQueue(), 1); - // The controller manager parks on its polling queue waiting for OS_EVENT_SI. - OS_EnableThreadEntry((void*)pfsManager_entry); - OS_SetQueueBlocking(pfsManager_getFrameMesgQ(), 1); - OS_EnableThreadEntry((void*)audioManagerThread_entry); - OS_SetQueueBlocking(audioManager_getFrameMesgQueue(), 1); - OS_SetQueueBlocking(audioManager_getReplyMesgQueue(), 1); -} -} // namespace - -// Drain submitted lists for safety. -static void RegisterThread5MapSync_Init() { - COND_HOOK(OnMapLoad, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { - (void)event; - port_pipelineSyncPoint(); - }); -} - -static RegisterShipInitFunc sThread5MapSyncInit(RegisterThread5MapSync_Init); - -// Whether a tick-side renderer call is waiting on the window thread. The -// handshake below is a condvar rather than a message queue, so it is the one -// park the watchdog's blocked-wait registry cannot see. -extern "C" int port_renderServicePending(void) { - return sSvcFn != nullptr; -} - -// Renderer calls from tick code come through here; D3D11 hangs if they run -// off the window thread. Inline when there is no separate tick thread. -extern "C" void port_runOnRenderThread(void (*fn)(void*), void* arg) { - if (!OnGameThread()) { - fn(arg); - return; - } - std::unique_lock lock(sSvcMutex); - auto done = [] { return sSvcFn == nullptr || sShutdownRequested.load(std::memory_order_acquire); }; - if (sShutdownRequested.load(std::memory_order_acquire)) { - return; - } - sSvcCv.wait(lock, done); - if (sShutdownRequested.load(std::memory_order_acquire)) { - return; - } - sSvcFn = fn; - sSvcArg = arg; - sSvcCv.wait(lock, done); -} - -// Barrier before the tick frees or reads memory an in-flight list references. -// The game's own EVENT_SYNC handshake is the RDP-done wait. -extern "C" void port_pipelineSyncPoint(void) { - if (OnGameThread()) { - core1_15B30_sendMesg3ToRenderThread(); - } +// Non-interactive demo/playback modes (attract demo, file playback, etc.) -- decomp gameloop.c +bool func_802E4A08(void); } // Tracks whether mainLoop actually fed the renderer this iteration. // BK's gameloop conditionally skips game_draw during scene transitions. static bool sFrameRendered = false; -// The list itself reaches the renderer through thread5's task queue, submitted -// by core1_15B30_addF3DEXTaskData right after this call; all that is left here -// is noting that the tick drew. +// Start of this tick. The gap until drawing begins is how long the game spent +// updating; Adaptive FPS uses it to budget how many interpolated frames fit. +static std::chrono::steady_clock::time_point sTickStart; + extern "C" void Graphics_PushFrame(Gfx* data) { - (void)data; + // Only measure the first draw of the tick. + if (!sFrameRendered) { + auto logicNs = + std::chrono::duration_cast(std::chrono::steady_clock::now() - sTickStart).count(); + AdaptiveFps_SampleTick((long long)logicNs); + } sFrameRendered = true; + GameEngine::ProcessGfxCommands(data); } void push_frame() { static int sTitleCounter = 0; sFrameRendered = false; - // The window thread keeps the progress modal alive while an inline mod - // extraction runs; the tick just idles so the extractor gets the machine. + // While an inline mod extraction runs on its worker thread, freeze the game + // and render only the GUI so the progress modal stays live and the extractor + // gets the machine instead of fighting a full-speed game loop. The delay + // keeps the otherwise-idle main thread from busy-spinning a core. if (IsInlineModExtractionBusy()) { + GameEngine::Instance->RenderGuiFrame(); SDL_Delay(16); return; } + sTickStart = std::chrono::steady_clock::now(); GameEngine::Instance->StartFrame(); - port_animVtx_beginTick(); - const bool recordInterpolation = GameEngine::IsInterpolationEnabled(); + // Demo/playback modes render at native rate with no interpolation, so skip recording it. + const bool recordInterpolation = GameEngine::IsInterpolationEnabled() && !func_802E4A08(); if (recordInterpolation) { FrameInterpolation_StartRecord(); } @@ -254,16 +74,13 @@ void push_frame() { if (recordInterpolation) { FrameInterpolation_StopRecord(); } - if (sFrameRendered) { - port_tickDemoAudioHold(); - } + GameEngine::StartAudioFrame(); + GameEngine::EndAudioFrame(); - // Refresh window title stats once per second (every 30 game ticks). The - // window belongs to the other thread, so hand the call over. + // Refresh window title stats once per second (every 30 game ticks) if (++sTitleCounter >= 30) { sTitleCounter = 0; - sTitleMap = gsworld_getMap(); - port_runOnRenderThread([](void*) { port_setWindowTitle(sTitleMap); }, nullptr); + port_setWindowTitle(gsworld_getMap()); } if (!sFrameRendered) { @@ -285,13 +102,8 @@ int SDL_main(int argc, char* argv[]) { // when SHIP_HOME is not in use std::error_code ec; const char* shipHome = std::getenv("SHIP_HOME"); - const char* appImage = std::getenv("APPIMAGE"); if (shipHome != nullptr && shipHome[0] != '\0') { std::filesystem::current_path(shipHome, ec); - } else if (appImage != nullptr && appImage[0] != '\0') { - // Running from an AppImage: the executable lives in a read-only squashfs - // mount under /tmp, so anchor to the .AppImage file's directory instead. - std::filesystem::current_path(std::filesystem::path(appImage).parent_path(), ec); } else { std::string base = Ship::Context::GetAppBundlePath(); if (!base.empty() && base != ".") { @@ -300,64 +112,11 @@ int SDL_main(int argc, char* argv[]) { } GameEngine::Create(argc, argv); - // Both threads are created during core1_init, so allowlist them first. - OS_EnableThreadEntry((void*)viMgr_entry); - EnableThread5(); core1_init(); - ThreadWatchdog_Start(); - - sGameThread = std::thread([] { - tIsGameThread = true; - while (WindowIsRunning()) { - ThreadWatchdog_Beat(WATCHDOG_GAME_TICK); - push_frame(); - } - sGameThreadDone.store(true); - }); - while (WindowIsRunning() || !sGameThreadDone.load()) { - ThreadWatchdog_Beat(WATCHDOG_MAIN_LOOP); - port_noteMainLoopAlive(); - // Pump events every iteration: a task-starved pass must not starve - // input and window messages. - Ship::Context::GetRawInstance()->GetWindow()->HandleEvents(); - OS_SiService(); - if (IsInlineModExtractionBusy()) { - GameEngine::Instance->RenderGuiFrame(); - SDL_Delay(16); - continue; - } - DrainRenderService(); - if (!ServiceRcp()) { - // The gui only draws inside serviced frames, so a stalled game - // thread would freeze ImGui with it. Render gui-only frames during - // a stall so the menu (and the watchdog dump) stays reachable. - if (ThreadWatchdog_IsStalled(WATCHDOG_GAME_TICK)) { - GameEngine::Instance->RenderGuiFrame(); - SDL_Delay(16); - continue; - } - SDL_Delay(1); - } - } - // Ask first, then release: a thread woken before the request is set would just - // park again. - OS_RequestThreadExit(); - { - std::lock_guard lock(sSvcMutex); - sShutdownRequested.store(true, std::memory_order_release); - sSvcFn = nullptr; - } - sSvcCv.notify_all(); - OS_BeginShutdown(); - if (sGameThread.joinable()) { - sGameThread.join(); + while (WindowIsRunning()) { + push_frame(); } - // Before Destroy: these threads draw and play audio through the engine. - OS_JoinDecompThreads(); - ThreadWatchdog_Stop(); - OS_StopViTicker(); - OS_StopTimerWorker(); #ifdef USE_NETWORKING Anchor::GetInstance()->Disable(); SDLNet_Quit(); diff --git a/src/port/GameStatus.cpp b/src/port/GameStatus.cpp index b316614da..fd67e994a 100644 --- a/src/port/GameStatus.cpp +++ b/src/port/GameStatus.cpp @@ -2,73 +2,28 @@ #include "ShipUtils.h" #include #include -#include #ifdef _WIN32 #include -#include -#include #endif #include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Patches/Patches.h" -#include "port/Romhack/RomhackConfig.h" #include "port/ShipInit.hpp" -#ifdef _WIN32 -namespace { -HWND ResolveGameWindow() { - static HWND sCached = nullptr; - if (sCached != nullptr && IsWindow(sCached)) { - return sCached; - } - for (Uint32 id = 1; id <= 16 && sCached == nullptr; id++) { - SDL_Window* window = SDL_GetWindowFromID(id); - if (window == nullptr) { - continue; - } - SDL_SysWMinfo info; - SDL_VERSION(&info.version); - if (SDL_GetWindowWMInfo(window, &info) == SDL_TRUE && info.subsystem == SDL_SYSWM_WINDOWS) { - sCached = info.info.win.window; - } - } - if (sCached == nullptr) { - struct Search { - DWORD pid; - HWND gameWindow; - HWND fallback; - }; - Search search{ GetCurrentProcessId(), nullptr, nullptr }; - EnumWindows( - [](HWND hwnd, LPARAM param) -> BOOL { - Search* s = reinterpret_cast(param); - DWORD pid = 0; - GetWindowThreadProcessId(hwnd, &pid); - if (pid != s->pid || GetWindow(hwnd, GW_OWNER) != nullptr || !IsWindowVisible(hwnd)) { - return TRUE; - } - char cls[64] = { 0 }; - GetClassNameA(hwnd, cls, (int)sizeof(cls)); - if (strcmp(cls, "N64GAME") == 0) { - s->gameWindow = hwnd; - return FALSE; - } - if (s->fallback == nullptr && strcmp(cls, "ConsoleWindowClass") != 0) { - s->fallback = hwnd; - } - return TRUE; - }, - reinterpret_cast(&search)); - sCached = (search.gameWindow != nullptr) ? search.gameWindow : search.fallback; - } - return sCached; -} -} // namespace -#endif - -#include "functions.h" extern "C" { #include "enums.h" +enum level_e map_getLevel(enum map_e map); +s32 itemscore_noteScores_get(enum level_e lvl_id); +s32 jiggyscore_leveltotal(s32 lvl); +s32 honeycombscore_get_level_total(enum level_e level_id); +u16 itemscore_timeScores_get(enum level_e level_id); +int port_getRomhackNotesMax(void); +int port_getRomhackJiggiesPerWorld(void); +int port_getRomhackHoneycombsPerWorld(void); +int port_getRomhackSpecialLevel(void); +int port_getRomhackExtraHcStart(void); +int port_getRomhackHideCollectiblesLevel(void); +int port_getRomhackHideJiggiesLevel(void); +const char* port_getRomhackLevelName(int level_index); // Pause menu level name table (supports romhack string patches via Torch config) typedef struct { @@ -196,20 +151,17 @@ extern "C" void port_setWindowTitle(int map_id) { noteStr, jiggyStr, hcStr, timeStr); #ifdef _WIN32 - HWND hwnd = ResolveGameWindow(); + HWND hwnd = GetActiveWindow(); if (hwnd) { SetWindowTextA(hwnd, title); } #endif } -static int sPendingTitleMap = 0; - void RegisterGameStatus_Init() { COND_HOOK(OnMapLoad, EVENT_PRIORITY_LOW, true, [](IEvent* event) { OnMapLoad* ev = (OnMapLoad*)event; - sPendingTitleMap = ev->nextMap; - port_runOnRenderThread([](void*) { port_setWindowTitle(sPendingTitleMap); }, nullptr); + port_setWindowTitle(ev->nextMap); }); } diff --git a/src/port/GameVersion/AssetVersionRemap.h b/src/port/GameVersion/AssetVersionRemap.h index 5d17eb6f1..395ecdf5e 100644 --- a/src/port/GameVersion/AssetVersionRemap.h +++ b/src/port/GameVersion/AssetVersionRemap.h @@ -4,580 +4,575 @@ #include #include -// v1.0 -> v1.1 asset ID remap table. 1313 entries. +// v1.0 -> v1.1 asset ID remap table. 1300 entries. static const std::unordered_map sV10toV11Remap = { { 2468, 2212 }, { 2469, 2213 }, { 2470, 2214 }, { 2471, 2215 }, { 2472, 2268 }, { 2473, 2269 }, { 2474, 2218 }, { 2475, 2219 }, { 2476, 2220 }, { 2477, 2221 }, { 2478, 2274 }, { 2481, 2277 }, { 2483, 2279 }, { 2484, 2228 }, { 2485, 2229 }, { 2487, 2283 }, { 2488, 2232 }, { 2489, 2233 }, { 2490, 2234 }, { 2491, 2235 }, { 2498, 2294 }, - { 2504, 2248 }, { 2508, 2252 }, { 2511, 2255 }, { 2513, 2257 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, - { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, - { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, - { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, - { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, - { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, - { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, - { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, - { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, - { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, - { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, - { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, - { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2878, 2396 }, - { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, - { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, - { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, - { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, - { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, - { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, - { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, - { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, - { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, - { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, - { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, - { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, - { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, - { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, - { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, - { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, - { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, - { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, - { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, - { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, - { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, - { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, - { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, - { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, - { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, { 3382, 2569 }, { 3383, 2570 }, { 3384, 2571 }, - { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, - { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, - { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, - { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, - { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, - { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, - { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, - { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, - { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, - { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, - { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, - { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, - { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, - { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, - { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, - { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, - { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, - { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, - { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, - { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, - { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, - { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, - { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, - { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, - { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, - { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, - { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, - { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, - { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, - { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, - { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, - { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, - { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, - { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, - { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, - { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, - { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, - { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, - { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, - { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, - { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, - { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, - { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, - { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, - { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, - { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, - { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, - { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, - { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, - { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, - { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, - { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, - { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, - { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, - { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, - { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, - { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, - { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, - { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, - { 4400, 2994 }, { 4401, 2995 }, { 4402, 2996 }, { 4403, 2997 }, { 4404, 2998 }, { 4405, 2999 }, { 4406, 3000 }, - { 4407, 3001 }, { 4408, 3002 }, { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, - { 4414, 3008 }, { 4415, 3009 }, { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, - { 4421, 3015 }, { 4422, 3016 }, { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4427, 3021 }, - { 4428, 3022 }, { 4429, 3023 }, { 4430, 3024 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, { 4434, 3028 }, - { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, { 4441, 3035 }, - { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, { 4448, 3042 }, - { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, { 4531, 3049 }, - { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, { 4538, 3056 }, - { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, { 4545, 3063 }, - { 4546, 3064 }, { 4547, 3065 }, { 4548, 3066 }, { 4549, 3067 }, { 4550, 3068 }, { 4551, 3069 }, { 4552, 3070 }, - { 4553, 3071 }, { 4627, 3072 }, { 4628, 3073 }, { 4629, 3074 }, { 4630, 3075 }, { 4631, 3076 }, { 4632, 3077 }, - { 4633, 3078 }, { 4634, 3079 }, { 4635, 3080 }, { 4636, 3081 }, { 4637, 3082 }, { 4638, 3083 }, { 4639, 3084 }, - { 4640, 3085 }, { 4641, 3086 }, { 4642, 3087 }, { 4643, 3088 }, { 4644, 3089 }, { 4645, 3090 }, { 4646, 3091 }, - { 4647, 3092 }, { 4648, 3093 }, { 4649, 3094 }, { 4650, 3095 }, { 4651, 3096 }, { 4652, 3097 }, { 4653, 3098 }, - { 4654, 3099 }, { 4655, 3100 }, { 4656, 3101 }, { 4657, 3102 }, { 4658, 3103 }, { 4659, 3104 }, { 4660, 3105 }, - { 4661, 3106 }, { 4662, 3107 }, { 4663, 3108 }, { 4664, 3109 }, { 4665, 3110 }, { 4666, 3111 }, { 4667, 3112 }, - { 4668, 3113 }, { 4669, 3114 }, { 4670, 3115 }, { 4671, 3116 }, { 4672, 3117 }, { 4673, 3118 }, { 4674, 3119 }, - { 4675, 3120 }, { 4676, 3121 }, { 4677, 3122 }, { 4678, 3123 }, { 4679, 3124 }, { 4680, 3125 }, { 4681, 3126 }, - { 4682, 3127 }, { 4683, 3128 }, { 4684, 3129 }, { 4685, 3130 }, { 4686, 3131 }, { 4687, 3132 }, { 4688, 3133 }, - { 4689, 3134 }, { 4690, 3135 }, { 4691, 3136 }, { 4692, 3137 }, { 4693, 3138 }, { 4694, 3139 }, { 4695, 3140 }, - { 4696, 3141 }, { 4697, 3142 }, { 4698, 3143 }, { 4699, 3144 }, { 4700, 3145 }, { 4701, 3146 }, { 4702, 3147 }, - { 4703, 3148 }, { 4704, 3149 }, { 4705, 3150 }, { 4706, 3151 }, { 4707, 3152 }, { 4708, 3153 }, { 4709, 3154 }, - { 4710, 3155 }, { 4711, 3156 }, { 4712, 3157 }, { 4713, 3158 }, { 4714, 3159 }, { 4715, 3160 }, { 4716, 3161 }, - { 4717, 3162 }, { 4718, 3163 }, { 4719, 3164 }, { 4720, 3165 }, { 4721, 3166 }, { 4722, 3167 }, { 4723, 3168 }, - { 4724, 3169 }, { 4725, 3170 }, { 4726, 3171 }, { 4827, 3172 }, { 4828, 3173 }, { 4829, 3174 }, { 4830, 3175 }, - { 4831, 3176 }, { 4832, 3177 }, { 4833, 3178 }, { 4834, 3179 }, { 4835, 3180 }, { 4836, 3181 }, { 4837, 3182 }, - { 4838, 3183 }, { 4839, 3184 }, { 4840, 3185 }, { 4841, 3186 }, { 4842, 3187 }, { 4843, 3188 }, { 4844, 3189 }, - { 4845, 3190 }, { 5027, 3191 }, { 5028, 3192 }, { 5029, 3193 }, { 5030, 3194 }, { 5031, 3195 }, { 5032, 3196 }, - { 5033, 3197 }, { 5034, 3198 }, { 5035, 3199 }, { 5036, 3200 }, { 5037, 3201 }, { 5038, 3202 }, { 5039, 3203 }, - { 5040, 3204 }, { 5041, 3205 }, { 5042, 3206 }, { 5043, 3207 }, { 5044, 3208 }, { 5045, 3209 }, { 5046, 3210 }, - { 5047, 3211 }, { 5048, 3212 }, { 5049, 3213 }, { 5050, 3214 }, { 5051, 3215 }, { 5052, 3216 }, { 5053, 3217 }, - { 5054, 3218 }, { 5055, 3219 }, { 5056, 3220 }, { 5057, 3221 }, { 5058, 3222 }, { 5059, 3223 }, { 5060, 3224 }, - { 5061, 3225 }, { 5062, 3226 }, { 5063, 3227 }, { 5064, 3228 }, { 5065, 3229 }, { 5066, 3230 }, { 5067, 3231 }, - { 5068, 3232 }, { 5069, 3233 }, { 5070, 3234 }, { 5071, 3235 }, { 5072, 3236 }, { 5073, 3237 }, { 5074, 3238 }, - { 5075, 3239 }, { 5076, 3240 }, { 5077, 3241 }, { 5127, 3242 }, { 5128, 3243 }, { 5129, 3244 }, { 5130, 3245 }, - { 5131, 3246 }, { 5132, 3247 }, { 5133, 3248 }, { 5134, 3249 }, { 5135, 3250 }, { 5136, 3251 }, { 5137, 3252 }, - { 5138, 3253 }, { 5139, 3254 }, { 5140, 3255 }, { 5141, 3256 }, { 5142, 3257 }, { 5143, 3258 }, { 5144, 3259 }, - { 5145, 3260 }, { 5146, 3261 }, { 5147, 3262 }, { 5148, 3263 }, { 5149, 3264 }, { 5150, 3265 }, { 5151, 3266 }, - { 5152, 3267 }, { 5153, 3268 }, { 5154, 3269 }, { 5155, 3270 }, { 5156, 3271 }, { 5227, 3272 }, { 5228, 3273 }, - { 5229, 3274 }, { 5230, 3275 }, { 5231, 3276 }, { 5232, 3277 }, { 5233, 3278 }, { 5234, 3279 }, { 5235, 3280 }, - { 5236, 3281 }, { 5237, 3282 }, { 5238, 3283 }, { 5240, 3285 }, { 5241, 3286 }, { 5242, 3287 }, { 5243, 3288 }, - { 5244, 3289 }, { 5245, 3290 }, { 5246, 3291 }, { 5247, 3292 }, { 5248, 3293 }, { 5249, 3294 }, { 5250, 3295 }, - { 5251, 3296 }, { 5252, 3297 }, { 5253, 3298 }, { 5254, 3299 }, { 5255, 3300 }, { 5256, 3301 }, { 5257, 3302 }, - { 5258, 3303 }, { 5259, 3304 }, { 5260, 3305 }, { 5261, 3306 }, { 5262, 3307 }, { 5263, 3308 }, { 5264, 3309 }, - { 5265, 3310 }, { 5266, 3311 }, { 5267, 3312 }, { 5268, 3313 }, { 5269, 3314 }, { 5270, 3315 }, { 5271, 3316 }, - { 5272, 3317 }, { 5273, 3318 }, { 5274, 3319 }, { 5275, 3320 }, { 5276, 3321 }, { 5277, 3322 }, { 5278, 3323 }, - { 5279, 3324 }, { 5280, 3325 }, { 5281, 3326 }, { 5282, 3327 }, { 5283, 3328 }, { 5284, 3329 }, { 5285, 3330 }, - { 5286, 3331 }, { 5288, 3333 }, { 5289, 3334 }, { 5290, 3335 }, { 5291, 3336 }, { 5292, 3337 }, { 5293, 3338 }, - { 5294, 3339 }, { 5296, 3341 }, { 5297, 3342 }, { 5298, 3343 }, { 5299, 3344 }, { 5300, 3345 }, { 5301, 3346 }, - { 5302, 3347 }, { 5303, 3348 }, { 5304, 3349 }, { 5305, 3350 }, { 5306, 3351 }, { 5307, 3352 }, { 5308, 3353 }, - { 5309, 3354 }, { 5310, 3355 }, { 5311, 3356 }, { 5312, 3357 }, { 5313, 3358 }, { 5314, 3359 }, { 5315, 3360 }, - { 5316, 3361 }, { 5317, 3362 }, { 5318, 3363 }, { 5319, 3364 }, { 5320, 3365 }, { 5321, 3366 }, { 5322, 3367 }, - { 5323, 3368 }, { 5324, 3369 }, { 5325, 3370 }, { 5326, 3371 }, { 5327, 3372 }, { 5328, 3373 }, { 5329, 3374 }, - { 5330, 3375 }, { 5331, 3376 }, { 5332, 3377 }, { 5333, 3378 }, { 5336, 3381 }, { 5337, 3382 }, { 5338, 3383 }, - { 5339, 3384 }, { 5340, 3385 }, { 5341, 3386 }, { 5342, 3387 }, { 5343, 3388 }, { 5344, 3389 }, { 5345, 3390 }, - { 5346, 3391 }, { 5347, 3392 }, { 5348, 3393 }, { 5349, 3394 }, { 5350, 3395 }, { 5351, 3396 }, { 5352, 3397 }, - { 5357, 3402 }, { 5358, 3403 }, { 5359, 3404 }, { 5360, 3405 }, { 5361, 3406 }, { 5362, 3407 }, { 5363, 3408 }, - { 5364, 3409 }, { 5365, 3410 }, { 5366, 3411 }, { 5367, 3412 }, { 5368, 3413 }, { 5369, 3414 }, { 5370, 3415 }, - { 5371, 3416 }, { 5372, 3417 }, { 5373, 3418 }, { 5374, 3419 }, { 5375, 3420 }, { 5376, 3421 }, { 5377, 3422 }, - { 5378, 3423 }, { 5379, 3424 }, { 5380, 3425 }, { 5381, 3426 }, { 5382, 3427 }, { 5383, 3428 }, { 5384, 3429 }, - { 5385, 3430 }, { 5386, 3431 }, { 5387, 3432 }, { 5388, 3433 }, { 5389, 3434 }, { 5390, 3435 }, { 5391, 3436 }, - { 5392, 3437 }, { 5393, 3438 }, { 5394, 3439 }, { 5395, 3440 }, { 5396, 3441 }, { 5397, 3442 }, { 5398, 3443 }, - { 5399, 3444 }, { 5400, 3445 }, { 5401, 3446 }, { 5402, 3447 }, { 5403, 3448 }, { 5404, 3449 }, { 5405, 3450 }, - { 5406, 3451 }, { 5407, 3452 }, { 5408, 3453 }, { 5409, 3454 }, { 5410, 3455 }, { 5411, 3456 }, { 5412, 3457 }, - { 5413, 3458 }, { 5414, 3459 }, { 5415, 3460 }, { 5416, 3461 }, { 5417, 3462 }, { 5418, 3463 }, { 5419, 3464 }, - { 5420, 3465 }, { 5421, 3466 }, { 5422, 3467 }, { 5423, 3468 }, { 5424, 3469 }, { 5425, 3470 }, { 5426, 3471 }, - { 5427, 3472 }, { 5428, 3473 }, { 5429, 3474 }, { 5430, 3475 }, { 5431, 3476 }, { 5432, 3477 }, { 5433, 3478 }, - { 5434, 3479 }, { 5435, 3480 }, { 5436, 3481 }, { 5437, 3482 }, { 5438, 3483 }, { 5439, 3484 }, { 5440, 3485 }, - { 5441, 3486 }, { 5442, 3487 }, { 5443, 3488 }, { 5444, 3489 }, { 5445, 3490 }, { 5446, 3491 }, { 5447, 3492 }, - { 5448, 3493 }, { 5449, 3494 }, { 5450, 3495 }, { 5451, 3496 }, { 5452, 3497 }, { 5453, 3498 }, { 5454, 3499 }, - { 5455, 3500 }, { 5456, 3501 }, { 5457, 3502 }, { 5458, 3503 }, { 5459, 3504 }, { 5460, 3505 }, { 5461, 3506 }, - { 5462, 3507 }, { 5463, 3508 }, { 5464, 3509 }, { 5465, 3510 }, { 5466, 3511 }, { 5467, 3512 }, { 5468, 3513 }, - { 5469, 3514 }, { 5470, 3515 }, { 5471, 3516 }, { 5472, 3517 }, { 5473, 3518 }, { 5474, 3519 }, { 5475, 3520 }, - { 5476, 3521 }, { 5477, 3522 }, { 5478, 3523 }, { 5479, 3524 }, { 5480, 3525 }, { 5481, 3526 }, { 5482, 3527 }, - { 5483, 3528 }, { 5484, 3529 }, { 5485, 3530 }, { 5486, 3531 }, { 5487, 3532 }, { 5488, 3533 }, { 5489, 3534 }, - { 5490, 3535 }, { 5491, 3536 }, { 5492, 3537 }, { 5493, 3538 }, { 5494, 3539 }, { 5495, 3540 }, { 5496, 3541 }, - { 5497, 3542 }, { 5498, 3543 }, { 5499, 3544 }, { 5500, 3545 }, { 5501, 3546 }, { 5502, 3547 }, { 5503, 3548 }, - { 5504, 3549 }, { 5505, 3550 }, { 5506, 3551 }, { 5507, 3552 }, { 5508, 3553 }, { 5509, 3554 }, { 5510, 3555 }, - { 5511, 3556 }, { 5512, 3557 }, { 5513, 3558 }, { 5514, 3559 }, { 5515, 3560 }, { 5516, 3561 }, { 5517, 3562 }, - { 5518, 3563 }, { 5519, 3564 }, { 5520, 3565 }, { 5521, 3566 }, { 5522, 3567 }, { 5523, 3568 }, { 5524, 3569 }, - { 5525, 3570 }, { 5526, 3571 }, { 5527, 3572 }, { 5528, 3573 }, { 5529, 3574 }, { 5530, 3575 }, { 5531, 3576 }, - { 5532, 3577 }, { 5533, 3578 }, { 5534, 3579 }, { 5535, 3580 }, { 5536, 3581 }, { 5537, 3582 }, { 5538, 3583 }, - { 5539, 3584 }, { 5540, 3585 }, { 5541, 3586 }, { 5542, 3587 }, { 5543, 3588 }, { 5544, 3589 }, { 5545, 3590 }, - { 5546, 3591 }, { 5547, 3592 }, { 5548, 3593 }, { 5549, 3594 }, { 5550, 3595 }, { 5551, 3596 }, { 5552, 3597 }, - { 5553, 3598 }, { 5554, 3599 }, { 5555, 3600 }, { 5556, 3601 }, { 5557, 3602 }, { 5558, 3603 }, { 5559, 3604 }, - { 5560, 3605 }, { 5561, 3606 }, { 5562, 3607 }, { 5563, 3608 }, { 5564, 3609 }, { 5565, 3610 }, { 5566, 3611 }, - { 5567, 3612 }, { 5568, 3613 }, { 5569, 3614 }, { 5570, 3615 } + { 2504, 2248 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, + { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, + { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, + { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, + { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, + { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, + { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, + { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, + { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, + { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, + { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, + { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, + { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, + { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, + { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, + { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, + { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, + { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, + { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, + { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, + { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, + { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, + { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, + { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, + { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, + { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, + { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, + { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, + { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, + { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, + { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, + { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, + { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, + { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, + { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, + { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, + { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, + { 3382, 2569 }, { 3383, 2570 }, { 3384, 3024 }, { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, + { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, + { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, + { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, + { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, + { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, + { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, + { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, + { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, + { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, + { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, + { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, + { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, + { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, + { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, + { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, + { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, + { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, + { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, + { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, + { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, + { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, + { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, + { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, + { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, + { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, + { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, + { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, + { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, + { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, + { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, + { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, + { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, + { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, + { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, + { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, + { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, + { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, + { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, + { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, + { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, + { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, + { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, + { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, + { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, + { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, + { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, + { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, + { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, + { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, + { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, + { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, + { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, + { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, + { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, + { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, + { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, + { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, + { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, + { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, { 4400, 2994 }, { 4406, 3000 }, { 4407, 3001 }, { 4408, 3002 }, + { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, { 4414, 3008 }, { 4415, 3009 }, + { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, { 4421, 3015 }, { 4422, 3016 }, + { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, + { 4434, 3028 }, { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, + { 4441, 3035 }, { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, + { 4448, 3042 }, { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, + { 4531, 3049 }, { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, + { 4538, 3056 }, { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, + { 4545, 3063 }, { 4546, 3064 }, { 4547, 3065 }, { 4548, 3066 }, { 4549, 3067 }, { 4550, 3068 }, { 4551, 3069 }, + { 4552, 3070 }, { 4553, 3071 }, { 4627, 3072 }, { 4628, 3073 }, { 4629, 3074 }, { 4630, 3075 }, { 4631, 3076 }, + { 4632, 3077 }, { 4633, 3078 }, { 4634, 3079 }, { 4635, 3080 }, { 4636, 3081 }, { 4637, 3082 }, { 4638, 3083 }, + { 4639, 3084 }, { 4640, 3085 }, { 4641, 3086 }, { 4642, 3087 }, { 4643, 3088 }, { 4644, 3089 }, { 4645, 3090 }, + { 4646, 3091 }, { 4647, 3092 }, { 4648, 3093 }, { 4649, 3094 }, { 4650, 3095 }, { 4651, 3096 }, { 4652, 3097 }, + { 4653, 3098 }, { 4654, 3099 }, { 4655, 3100 }, { 4656, 3101 }, { 4657, 3102 }, { 4658, 3103 }, { 4659, 3104 }, + { 4660, 3105 }, { 4661, 3106 }, { 4662, 3107 }, { 4663, 3108 }, { 4664, 3109 }, { 4665, 3110 }, { 4666, 3111 }, + { 4667, 3112 }, { 4668, 3113 }, { 4669, 3114 }, { 4670, 3115 }, { 4671, 3116 }, { 4672, 3117 }, { 4673, 3118 }, + { 4674, 3119 }, { 4675, 3120 }, { 4676, 3121 }, { 4677, 3122 }, { 4678, 3123 }, { 4679, 3124 }, { 4680, 3125 }, + { 4681, 3126 }, { 4682, 3127 }, { 4683, 3128 }, { 4684, 3129 }, { 4685, 3130 }, { 4686, 3131 }, { 4687, 3132 }, + { 4688, 3133 }, { 4689, 3134 }, { 4690, 3135 }, { 4691, 3136 }, { 4692, 3137 }, { 4693, 3138 }, { 4694, 3139 }, + { 4695, 3140 }, { 4696, 3141 }, { 4697, 3142 }, { 4698, 3143 }, { 4699, 3144 }, { 4700, 3145 }, { 4701, 3146 }, + { 4702, 3147 }, { 4703, 3148 }, { 4704, 3149 }, { 4705, 3150 }, { 4706, 3151 }, { 4707, 3152 }, { 4708, 3153 }, + { 4709, 3154 }, { 4710, 3155 }, { 4711, 3156 }, { 4712, 3157 }, { 4713, 3158 }, { 4714, 3159 }, { 4715, 3160 }, + { 4716, 3161 }, { 4717, 3162 }, { 4718, 3163 }, { 4719, 3164 }, { 4720, 3165 }, { 4721, 3166 }, { 4722, 3167 }, + { 4723, 3168 }, { 4724, 3169 }, { 4725, 3170 }, { 4726, 3171 }, { 4827, 3172 }, { 4828, 3173 }, { 4829, 3174 }, + { 4830, 3175 }, { 4831, 3176 }, { 4832, 3177 }, { 4833, 3178 }, { 4834, 3179 }, { 4835, 3180 }, { 4836, 3181 }, + { 4837, 3182 }, { 4838, 3183 }, { 4839, 3184 }, { 4840, 3185 }, { 4841, 3186 }, { 4842, 3187 }, { 4843, 3188 }, + { 4844, 3189 }, { 4845, 3190 }, { 5027, 3191 }, { 5028, 3192 }, { 5029, 3193 }, { 5030, 3194 }, { 5031, 3195 }, + { 5032, 3196 }, { 5033, 3197 }, { 5034, 3198 }, { 5035, 3199 }, { 5036, 3200 }, { 5037, 3201 }, { 5038, 3202 }, + { 5039, 3203 }, { 5040, 3204 }, { 5041, 3205 }, { 5042, 3206 }, { 5043, 3207 }, { 5044, 3208 }, { 5045, 3209 }, + { 5046, 3210 }, { 5047, 3211 }, { 5048, 3212 }, { 5049, 3213 }, { 5050, 3214 }, { 5051, 3215 }, { 5052, 3216 }, + { 5053, 3217 }, { 5054, 3218 }, { 5055, 3219 }, { 5056, 3220 }, { 5057, 3221 }, { 5058, 3222 }, { 5059, 3223 }, + { 5060, 3224 }, { 5061, 3225 }, { 5062, 3226 }, { 5063, 3227 }, { 5064, 3228 }, { 5065, 3229 }, { 5066, 3230 }, + { 5067, 3231 }, { 5068, 3232 }, { 5069, 3233 }, { 5070, 3234 }, { 5071, 3235 }, { 5072, 3236 }, { 5073, 3237 }, + { 5074, 3238 }, { 5075, 3239 }, { 5076, 3240 }, { 5077, 3241 }, { 5127, 3242 }, { 5128, 3243 }, { 5129, 3244 }, + { 5130, 3245 }, { 5131, 3246 }, { 5132, 3247 }, { 5133, 3248 }, { 5134, 3249 }, { 5135, 3250 }, { 5136, 3251 }, + { 5137, 3252 }, { 5138, 3253 }, { 5139, 3254 }, { 5140, 3255 }, { 5141, 3256 }, { 5142, 3257 }, { 5143, 3258 }, + { 5144, 3259 }, { 5145, 3260 }, { 5146, 3261 }, { 5147, 3262 }, { 5148, 3263 }, { 5149, 3264 }, { 5150, 3265 }, + { 5151, 3266 }, { 5152, 3267 }, { 5153, 3268 }, { 5154, 3269 }, { 5155, 3270 }, { 5156, 3271 }, { 5227, 3272 }, + { 5228, 3273 }, { 5229, 3274 }, { 5230, 3275 }, { 5231, 3276 }, { 5232, 3277 }, { 5233, 3278 }, { 5234, 3279 }, + { 5235, 3280 }, { 5236, 3281 }, { 5237, 3282 }, { 5238, 3283 }, { 5240, 3285 }, { 5241, 3286 }, { 5242, 3287 }, + { 5243, 3288 }, { 5244, 3289 }, { 5245, 3290 }, { 5246, 3291 }, { 5247, 3292 }, { 5248, 3293 }, { 5249, 3294 }, + { 5250, 3295 }, { 5251, 3296 }, { 5252, 3297 }, { 5253, 3298 }, { 5254, 3299 }, { 5255, 3300 }, { 5256, 3301 }, + { 5257, 3302 }, { 5258, 3303 }, { 5259, 3304 }, { 5260, 3305 }, { 5261, 3306 }, { 5262, 3307 }, { 5263, 3308 }, + { 5264, 3309 }, { 5265, 3310 }, { 5266, 3311 }, { 5267, 3312 }, { 5268, 3313 }, { 5269, 3314 }, { 5270, 3315 }, + { 5271, 3316 }, { 5272, 3317 }, { 5273, 3318 }, { 5274, 3319 }, { 5275, 3320 }, { 5276, 3321 }, { 5277, 3322 }, + { 5278, 3323 }, { 5279, 3324 }, { 5280, 3325 }, { 5281, 3326 }, { 5282, 3327 }, { 5283, 3328 }, { 5284, 3329 }, + { 5285, 3330 }, { 5286, 3331 }, { 5288, 3333 }, { 5289, 3334 }, { 5290, 3335 }, { 5291, 3336 }, { 5292, 3337 }, + { 5293, 3338 }, { 5294, 3339 }, { 5296, 3341 }, { 5297, 3342 }, { 5298, 3343 }, { 5299, 3344 }, { 5300, 3345 }, + { 5301, 3346 }, { 5302, 3347 }, { 5303, 3348 }, { 5304, 3349 }, { 5305, 3350 }, { 5306, 3351 }, { 5307, 3352 }, + { 5308, 3353 }, { 5309, 3354 }, { 5310, 3355 }, { 5311, 3356 }, { 5312, 3357 }, { 5313, 3358 }, { 5314, 3359 }, + { 5315, 3360 }, { 5316, 3361 }, { 5317, 3362 }, { 5318, 3363 }, { 5319, 3364 }, { 5320, 3365 }, { 5321, 3366 }, + { 5322, 3367 }, { 5323, 3368 }, { 5324, 3369 }, { 5325, 3370 }, { 5326, 3371 }, { 5327, 3372 }, { 5328, 3373 }, + { 5329, 3374 }, { 5330, 3375 }, { 5331, 3376 }, { 5332, 3377 }, { 5333, 3378 }, { 5336, 3381 }, { 5337, 3382 }, + { 5338, 3383 }, { 5339, 3384 }, { 5340, 3385 }, { 5341, 3386 }, { 5342, 3387 }, { 5343, 3388 }, { 5344, 3389 }, + { 5345, 3390 }, { 5346, 3391 }, { 5347, 3392 }, { 5348, 3393 }, { 5349, 3394 }, { 5350, 3395 }, { 5351, 3396 }, + { 5352, 3397 }, { 5357, 3402 }, { 5358, 3403 }, { 5359, 3404 }, { 5360, 3405 }, { 5361, 3406 }, { 5362, 3407 }, + { 5363, 3408 }, { 5364, 3409 }, { 5365, 3410 }, { 5366, 3411 }, { 5367, 3412 }, { 5368, 3413 }, { 5369, 3414 }, + { 5370, 3415 }, { 5371, 3416 }, { 5372, 3417 }, { 5373, 3418 }, { 5374, 3419 }, { 5375, 3420 }, { 5376, 3421 }, + { 5377, 3422 }, { 5378, 3423 }, { 5379, 3424 }, { 5380, 3425 }, { 5381, 3426 }, { 5382, 3427 }, { 5383, 3428 }, + { 5384, 3429 }, { 5385, 3430 }, { 5386, 3431 }, { 5387, 3432 }, { 5388, 3433 }, { 5389, 3434 }, { 5390, 3435 }, + { 5391, 3436 }, { 5392, 3437 }, { 5393, 3438 }, { 5394, 3439 }, { 5395, 3440 }, { 5396, 3441 }, { 5397, 3442 }, + { 5398, 3443 }, { 5399, 3444 }, { 5400, 3445 }, { 5401, 3446 }, { 5402, 3447 }, { 5403, 3448 }, { 5404, 3449 }, + { 5405, 3450 }, { 5406, 3451 }, { 5407, 3452 }, { 5408, 3453 }, { 5409, 3454 }, { 5410, 3455 }, { 5411, 3456 }, + { 5412, 3457 }, { 5413, 3458 }, { 5414, 3459 }, { 5415, 3460 }, { 5416, 3461 }, { 5417, 3462 }, { 5418, 3463 }, + { 5419, 3464 }, { 5420, 3465 }, { 5421, 3466 }, { 5422, 3467 }, { 5423, 3468 }, { 5424, 3469 }, { 5425, 3470 }, + { 5426, 3471 }, { 5427, 3472 }, { 5428, 3473 }, { 5429, 3474 }, { 5430, 3475 }, { 5431, 3476 }, { 5432, 3477 }, + { 5433, 3478 }, { 5434, 3479 }, { 5435, 3480 }, { 5436, 3481 }, { 5437, 3482 }, { 5438, 3483 }, { 5439, 3484 }, + { 5440, 3485 }, { 5441, 3486 }, { 5442, 3487 }, { 5443, 3488 }, { 5444, 3489 }, { 5445, 3490 }, { 5446, 3491 }, + { 5447, 3492 }, { 5448, 3493 }, { 5449, 3494 }, { 5450, 3495 }, { 5451, 3496 }, { 5452, 3497 }, { 5453, 3498 }, + { 5454, 3499 }, { 5455, 3500 }, { 5456, 3501 }, { 5457, 3502 }, { 5458, 3503 }, { 5459, 3504 }, { 5460, 3505 }, + { 5461, 3506 }, { 5462, 3507 }, { 5463, 3508 }, { 5464, 3509 }, { 5465, 3510 }, { 5466, 3511 }, { 5467, 3512 }, + { 5468, 3513 }, { 5469, 3514 }, { 5470, 3515 }, { 5471, 3516 }, { 5472, 3517 }, { 5473, 3518 }, { 5474, 3519 }, + { 5475, 3520 }, { 5476, 3521 }, { 5477, 3522 }, { 5478, 3523 }, { 5479, 3524 }, { 5480, 3525 }, { 5481, 3526 }, + { 5482, 3527 }, { 5483, 3528 }, { 5484, 3529 }, { 5485, 3530 }, { 5486, 3531 }, { 5487, 3532 }, { 5488, 3533 }, + { 5489, 3534 }, { 5490, 3535 }, { 5491, 3536 }, { 5492, 3537 }, { 5493, 3538 }, { 5494, 3539 }, { 5495, 3540 }, + { 5496, 3541 }, { 5497, 3542 }, { 5498, 3543 }, { 5499, 3544 }, { 5500, 3545 }, { 5501, 3546 }, { 5502, 3547 }, + { 5503, 3548 }, { 5504, 3549 }, { 5505, 3550 }, { 5506, 3551 }, { 5507, 3552 }, { 5508, 3553 }, { 5509, 3554 }, + { 5510, 3555 }, { 5511, 3556 }, { 5512, 3557 }, { 5513, 3558 }, { 5514, 3559 }, { 5515, 3560 }, { 5516, 3561 }, + { 5517, 3562 }, { 5518, 3563 }, { 5519, 3564 }, { 5520, 3565 }, { 5521, 3566 }, { 5522, 3567 }, { 5523, 3568 }, + { 5524, 3569 }, { 5525, 3570 }, { 5526, 3571 }, { 5527, 3572 }, { 5528, 3573 }, { 5529, 3574 }, { 5530, 3575 }, + { 5531, 3576 }, { 5532, 3577 }, { 5533, 3578 }, { 5534, 3579 }, { 5535, 3580 }, { 5536, 3581 }, { 5537, 3582 }, + { 5538, 3583 }, { 5539, 3584 }, { 5540, 3585 }, { 5541, 3586 }, { 5542, 3587 }, { 5543, 3588 }, { 5544, 3589 }, + { 5545, 3590 }, { 5546, 3591 }, { 5547, 3592 }, { 5548, 3593 }, { 5549, 3594 }, { 5550, 3595 }, { 5551, 3596 }, + { 5552, 3597 }, { 5553, 3598 }, { 5554, 3599 }, { 5555, 3600 }, { 5556, 3601 }, { 5557, 3602 }, { 5558, 3603 }, + { 5559, 3604 }, { 5560, 3605 }, { 5561, 3606 }, { 5562, 3607 }, { 5563, 3608 }, { 5564, 3609 }, { 5565, 3610 }, + { 5566, 3611 }, { 5567, 3612 }, { 5568, 3613 }, { 5569, 3614 }, { 5570, 3615 } }; -// v1.0 -> PAL asset ID remap table. 1314 entries. +// v1.0 -> PAL asset ID remap table. 1300 entries. static const std::unordered_map sV10toPALRemap = { { 2468, 2212 }, { 2469, 2213 }, { 2470, 2214 }, { 2471, 2215 }, { 2472, 2268 }, { 2473, 2269 }, { 2474, 2218 }, { 2475, 2219 }, { 2476, 2220 }, { 2477, 2221 }, { 2478, 2274 }, { 2481, 2277 }, { 2483, 2279 }, { 2484, 2228 }, { 2485, 2229 }, { 2487, 2283 }, { 2488, 2232 }, { 2489, 2233 }, { 2490, 2234 }, { 2491, 2235 }, { 2498, 2294 }, - { 2504, 2248 }, { 2508, 2252 }, { 2511, 2255 }, { 2513, 2257 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, - { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, - { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, - { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, - { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, - { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, - { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, - { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, - { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, - { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, - { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, - { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, - { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2878, 2396 }, - { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, - { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, - { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, - { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, - { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, - { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, - { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, - { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, - { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, - { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, - { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, - { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, - { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, - { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, - { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, - { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, - { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, - { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, - { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, - { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, - { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, - { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, - { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, - { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, - { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, { 3382, 2569 }, { 3383, 2570 }, { 3384, 2571 }, - { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, - { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, - { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, - { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, - { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, - { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, - { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, - { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, - { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, - { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, - { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, - { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, - { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, - { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, - { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, - { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, - { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, - { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, - { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, - { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, - { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, - { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, - { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, - { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, - { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, - { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, - { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, - { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, - { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, - { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, - { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, - { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, - { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, - { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, - { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, - { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, - { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, - { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, - { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, - { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, - { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, - { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, - { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, - { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, - { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, - { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, - { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, - { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, - { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, - { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, - { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, - { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, - { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, - { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, - { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, - { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, - { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, - { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, - { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, - { 4400, 2994 }, { 4401, 2995 }, { 4402, 2996 }, { 4403, 2997 }, { 4404, 2998 }, { 4405, 2999 }, { 4406, 3000 }, - { 4407, 3001 }, { 4408, 3002 }, { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, - { 4414, 3008 }, { 4415, 3009 }, { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, - { 4421, 3015 }, { 4422, 3016 }, { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4427, 3021 }, - { 4428, 3022 }, { 4429, 3023 }, { 4430, 3024 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, { 4434, 3028 }, - { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, { 4441, 3035 }, - { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, { 4448, 3042 }, - { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, { 4531, 3049 }, - { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, { 4538, 3056 }, - { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, { 4545, 3063 }, - { 4546, 3064 }, { 4547, 3066 }, { 4548, 3067 }, { 4549, 3068 }, { 4550, 3069 }, { 4551, 3070 }, { 4552, 3071 }, - { 4553, 3072 }, { 4627, 3073 }, { 4628, 3074 }, { 4629, 3075 }, { 4630, 3076 }, { 4631, 3077 }, { 4632, 3078 }, - { 4633, 3079 }, { 4634, 3080 }, { 4635, 3081 }, { 4636, 3082 }, { 4637, 3083 }, { 4638, 3084 }, { 4639, 3085 }, - { 4640, 3086 }, { 4641, 3087 }, { 4642, 3088 }, { 4643, 3089 }, { 4644, 3090 }, { 4645, 3091 }, { 4646, 3092 }, - { 4647, 3093 }, { 4648, 3094 }, { 4649, 3095 }, { 4650, 3096 }, { 4651, 3097 }, { 4652, 3098 }, { 4653, 3099 }, - { 4654, 3100 }, { 4655, 3101 }, { 4656, 3102 }, { 4657, 3103 }, { 4658, 3104 }, { 4659, 3105 }, { 4660, 3106 }, - { 4661, 3107 }, { 4662, 3108 }, { 4663, 3109 }, { 4664, 3110 }, { 4665, 3111 }, { 4666, 3112 }, { 4667, 3113 }, - { 4668, 3114 }, { 4669, 3115 }, { 4670, 3116 }, { 4671, 3117 }, { 4672, 3118 }, { 4673, 3119 }, { 4674, 3120 }, - { 4675, 3121 }, { 4676, 3122 }, { 4677, 3123 }, { 4678, 3124 }, { 4679, 3125 }, { 4680, 3126 }, { 4681, 3127 }, - { 4682, 3128 }, { 4683, 3129 }, { 4684, 3130 }, { 4685, 3131 }, { 4686, 3132 }, { 4687, 3133 }, { 4688, 3134 }, - { 4689, 3135 }, { 4690, 3136 }, { 4691, 3137 }, { 4692, 3138 }, { 4693, 3139 }, { 4694, 3140 }, { 4695, 3141 }, - { 4696, 3142 }, { 4697, 3143 }, { 4698, 3144 }, { 4699, 3145 }, { 4700, 3146 }, { 4701, 3147 }, { 4702, 3148 }, - { 4703, 3149 }, { 4704, 3150 }, { 4705, 3151 }, { 4706, 3152 }, { 4707, 3153 }, { 4708, 3154 }, { 4709, 3155 }, - { 4710, 3156 }, { 4711, 3157 }, { 4712, 3158 }, { 4713, 3159 }, { 4714, 3160 }, { 4715, 3161 }, { 4716, 3162 }, - { 4717, 3163 }, { 4718, 3164 }, { 4719, 3165 }, { 4720, 3166 }, { 4721, 3167 }, { 4722, 3168 }, { 4723, 3169 }, - { 4724, 3170 }, { 4725, 3171 }, { 4726, 3172 }, { 4827, 3173 }, { 4828, 3174 }, { 4829, 3175 }, { 4830, 3176 }, - { 4831, 3177 }, { 4832, 3178 }, { 4833, 3179 }, { 4834, 3180 }, { 4835, 3181 }, { 4836, 3182 }, { 4837, 3183 }, - { 4838, 3184 }, { 4839, 3185 }, { 4840, 3186 }, { 4841, 3187 }, { 4842, 3188 }, { 4843, 3189 }, { 4844, 3190 }, - { 4845, 3191 }, { 5027, 3192 }, { 5028, 3193 }, { 5029, 3194 }, { 5030, 3195 }, { 5031, 3196 }, { 5032, 3197 }, - { 5033, 3198 }, { 5034, 3199 }, { 5035, 3200 }, { 5036, 3201 }, { 5037, 3202 }, { 5038, 3203 }, { 5039, 3204 }, - { 5040, 3205 }, { 5041, 3206 }, { 5042, 3207 }, { 5043, 3208 }, { 5044, 3209 }, { 5045, 3210 }, { 5046, 3211 }, - { 5047, 3212 }, { 5048, 3213 }, { 5049, 3214 }, { 5050, 3215 }, { 5051, 3216 }, { 5052, 3217 }, { 5053, 3218 }, - { 5054, 3219 }, { 5055, 3220 }, { 5056, 3221 }, { 5057, 3222 }, { 5058, 3223 }, { 5059, 3224 }, { 5060, 3225 }, - { 5061, 3226 }, { 5062, 3227 }, { 5063, 3228 }, { 5064, 3229 }, { 5065, 3230 }, { 5066, 3231 }, { 5067, 3232 }, - { 5068, 3233 }, { 5069, 3234 }, { 5070, 3235 }, { 5071, 3236 }, { 5072, 3237 }, { 5073, 3238 }, { 5074, 3239 }, - { 5075, 3240 }, { 5076, 3241 }, { 5077, 3242 }, { 5127, 3243 }, { 5128, 3244 }, { 5129, 3245 }, { 5130, 3246 }, - { 5131, 3247 }, { 5132, 3248 }, { 5133, 3249 }, { 5134, 3250 }, { 5135, 3251 }, { 5136, 3252 }, { 5137, 3253 }, - { 5138, 3254 }, { 5139, 3255 }, { 5140, 3256 }, { 5141, 3257 }, { 5142, 3258 }, { 5143, 3259 }, { 5144, 3260 }, - { 5145, 3261 }, { 5146, 3262 }, { 5147, 3263 }, { 5148, 3264 }, { 5149, 3265 }, { 5150, 3266 }, { 5151, 3267 }, - { 5152, 3268 }, { 5153, 3269 }, { 5154, 3270 }, { 5155, 3271 }, { 5156, 3272 }, { 5227, 3273 }, { 5228, 3274 }, - { 5229, 3275 }, { 5230, 3276 }, { 5231, 3277 }, { 5232, 3278 }, { 5233, 3279 }, { 5234, 3280 }, { 5235, 3281 }, - { 5236, 3282 }, { 5237, 3283 }, { 5238, 3284 }, { 5240, 3286 }, { 5241, 3287 }, { 5242, 3288 }, { 5243, 3289 }, - { 5244, 3290 }, { 5245, 3291 }, { 5246, 3292 }, { 5247, 3293 }, { 5248, 3294 }, { 5249, 3295 }, { 5250, 3296 }, - { 5251, 3297 }, { 5252, 3298 }, { 5253, 3299 }, { 5254, 3300 }, { 5255, 3301 }, { 5256, 3302 }, { 5257, 3303 }, - { 5258, 3304 }, { 5259, 3305 }, { 5260, 3306 }, { 5261, 3307 }, { 5262, 3308 }, { 5263, 3309 }, { 5264, 3310 }, - { 5265, 3311 }, { 5266, 3312 }, { 5267, 3313 }, { 5268, 3314 }, { 5269, 3315 }, { 5270, 3316 }, { 5271, 3317 }, - { 5272, 3318 }, { 5273, 3319 }, { 5274, 3320 }, { 5275, 3321 }, { 5276, 3322 }, { 5277, 3323 }, { 5278, 3324 }, - { 5279, 3325 }, { 5280, 3326 }, { 5281, 3327 }, { 5282, 3328 }, { 5283, 3329 }, { 5284, 3330 }, { 5285, 3331 }, - { 5286, 3332 }, { 5288, 3334 }, { 5289, 3335 }, { 5290, 3336 }, { 5291, 3337 }, { 5292, 3338 }, { 5293, 3339 }, - { 5294, 3340 }, { 5296, 3342 }, { 5297, 3343 }, { 5298, 3344 }, { 5299, 3345 }, { 5300, 3346 }, { 5301, 3347 }, - { 5302, 3348 }, { 5303, 3349 }, { 5304, 3350 }, { 5305, 3351 }, { 5306, 3352 }, { 5307, 3353 }, { 5308, 3354 }, - { 5309, 3355 }, { 5310, 3356 }, { 5311, 3357 }, { 5312, 3358 }, { 5313, 3359 }, { 5314, 3360 }, { 5315, 3361 }, - { 5316, 3362 }, { 5317, 3363 }, { 5318, 3364 }, { 5319, 3365 }, { 5320, 3366 }, { 5321, 3367 }, { 5322, 3368 }, - { 5323, 3369 }, { 5324, 3370 }, { 5325, 3371 }, { 5326, 3372 }, { 5327, 3373 }, { 5328, 3374 }, { 5329, 3375 }, - { 5330, 3376 }, { 5331, 3377 }, { 5332, 3378 }, { 5333, 3379 }, { 5336, 3382 }, { 5337, 3383 }, { 5338, 3384 }, - { 5339, 3385 }, { 5340, 3386 }, { 5341, 3387 }, { 5342, 3388 }, { 5343, 3389 }, { 5344, 3390 }, { 5345, 3391 }, - { 5346, 3392 }, { 5347, 3393 }, { 5348, 3394 }, { 5349, 3395 }, { 5350, 3396 }, { 5351, 3397 }, { 5352, 3398 }, - { 5357, 3403 }, { 5358, 3404 }, { 5359, 3405 }, { 5360, 3406 }, { 5361, 3407 }, { 5362, 3408 }, { 5363, 3409 }, - { 5364, 3410 }, { 5365, 3411 }, { 5366, 3412 }, { 5367, 3413 }, { 5368, 3414 }, { 5369, 3415 }, { 5370, 3416 }, - { 5371, 3417 }, { 5372, 3418 }, { 5373, 3419 }, { 5374, 3420 }, { 5375, 3421 }, { 5376, 3422 }, { 5377, 3423 }, - { 5378, 3424 }, { 5379, 3425 }, { 5380, 3426 }, { 5381, 3427 }, { 5382, 3428 }, { 5383, 3429 }, { 5384, 3430 }, - { 5385, 3431 }, { 5386, 3432 }, { 5387, 3433 }, { 5388, 3434 }, { 5389, 3435 }, { 5390, 3436 }, { 5391, 3437 }, - { 5392, 3438 }, { 5393, 3439 }, { 5394, 3440 }, { 5395, 3441 }, { 5396, 3442 }, { 5397, 3443 }, { 5398, 3444 }, - { 5399, 3445 }, { 5400, 3446 }, { 5401, 3447 }, { 5402, 3448 }, { 5403, 3449 }, { 5404, 3450 }, { 5405, 3451 }, - { 5406, 3452 }, { 5407, 3453 }, { 5408, 3454 }, { 5409, 3455 }, { 5410, 3456 }, { 5411, 3457 }, { 5412, 3458 }, - { 5413, 3459 }, { 5414, 3460 }, { 5415, 3461 }, { 5416, 3462 }, { 5417, 3463 }, { 5418, 3464 }, { 5419, 3465 }, - { 5420, 3466 }, { 5421, 3467 }, { 5422, 3468 }, { 5423, 3469 }, { 5424, 3470 }, { 5425, 3471 }, { 5426, 3472 }, - { 5427, 3473 }, { 5428, 3474 }, { 5429, 3475 }, { 5430, 3476 }, { 5431, 3477 }, { 5432, 3478 }, { 5433, 3479 }, - { 5434, 3480 }, { 5435, 3481 }, { 5436, 3482 }, { 5437, 3483 }, { 5438, 3484 }, { 5439, 3485 }, { 5440, 3486 }, - { 5441, 3487 }, { 5442, 3488 }, { 5443, 3489 }, { 5444, 3490 }, { 5445, 3491 }, { 5446, 3492 }, { 5447, 3493 }, - { 5448, 3494 }, { 5449, 3495 }, { 5450, 3496 }, { 5451, 3497 }, { 5452, 3498 }, { 5453, 3499 }, { 5454, 3500 }, - { 5455, 3501 }, { 5456, 3502 }, { 5457, 3503 }, { 5458, 3504 }, { 5459, 3505 }, { 5460, 3506 }, { 5461, 3507 }, - { 5462, 3508 }, { 5463, 3509 }, { 5464, 3510 }, { 5465, 3511 }, { 5466, 3512 }, { 5467, 3513 }, { 5468, 3514 }, - { 5469, 3515 }, { 5470, 3516 }, { 5471, 3517 }, { 5472, 3518 }, { 5473, 3519 }, { 5474, 3520 }, { 5475, 3521 }, - { 5476, 3522 }, { 5477, 3523 }, { 5478, 3524 }, { 5479, 3525 }, { 5480, 3526 }, { 5481, 3527 }, { 5482, 3528 }, - { 5483, 3529 }, { 5484, 3530 }, { 5485, 3531 }, { 5486, 3532 }, { 5487, 3533 }, { 5488, 3534 }, { 5489, 3535 }, - { 5490, 3536 }, { 5491, 3537 }, { 5492, 3538 }, { 5493, 3539 }, { 5494, 3540 }, { 5495, 3541 }, { 5496, 3542 }, - { 5497, 3543 }, { 5498, 3544 }, { 5499, 3545 }, { 5500, 3546 }, { 5501, 3547 }, { 5502, 3548 }, { 5503, 3549 }, - { 5504, 3550 }, { 5505, 3551 }, { 5506, 3552 }, { 5507, 3553 }, { 5508, 3554 }, { 5509, 3555 }, { 5510, 3556 }, - { 5511, 3557 }, { 5512, 3558 }, { 5513, 3559 }, { 5514, 3560 }, { 5515, 3561 }, { 5516, 3562 }, { 5517, 3563 }, - { 5518, 3564 }, { 5519, 3565 }, { 5520, 3566 }, { 5521, 3567 }, { 5522, 3568 }, { 5523, 3569 }, { 5524, 3570 }, - { 5525, 3571 }, { 5526, 3572 }, { 5527, 3573 }, { 5528, 3574 }, { 5529, 3575 }, { 5530, 3576 }, { 5531, 3577 }, - { 5532, 3578 }, { 5533, 3579 }, { 5534, 3580 }, { 5535, 3581 }, { 5536, 3582 }, { 5537, 3583 }, { 5538, 3584 }, - { 5539, 3585 }, { 5540, 3586 }, { 5541, 3587 }, { 5542, 3588 }, { 5543, 3589 }, { 5544, 3590 }, { 5545, 3591 }, - { 5546, 3592 }, { 5547, 3593 }, { 5548, 3594 }, { 5549, 3595 }, { 5550, 3596 }, { 5551, 3597 }, { 5552, 3598 }, - { 5553, 3599 }, { 5554, 3600 }, { 5555, 3601 }, { 5556, 3602 }, { 5557, 3603 }, { 5558, 3604 }, { 5559, 3605 }, - { 5560, 3606 }, { 5561, 3607 }, { 5562, 3608 }, { 5563, 3609 }, { 5564, 3610 }, { 5565, 3611 }, { 5566, 3612 }, - { 5567, 3613 }, { 5568, 3614 }, { 5569, 3615 }, { 5570, 3616 }, { 4554, 3065 }, + { 2504, 2248 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, { 2528, 2311 }, { 2529, 2312 }, { 2571, 2315 }, + { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, + { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, + { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, + { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, + { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, + { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, + { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, + { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, + { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, + { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, + { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, + { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, + { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, + { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, + { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, + { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, + { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, + { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, + { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, + { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, + { 3103, 2457 }, { 3104, 2458 }, { 3105, 2459 }, { 3106, 2460 }, { 3107, 2461 }, { 3108, 2462 }, { 3109, 2463 }, + { 3110, 2464 }, { 3111, 2465 }, { 3112, 2466 }, { 3113, 2467 }, { 3114, 2468 }, { 3115, 2469 }, { 3171, 2470 }, + { 3172, 2471 }, { 3173, 2472 }, { 3174, 2473 }, { 3175, 2474 }, { 3176, 2475 }, { 3177, 2476 }, { 3178, 2477 }, + { 3179, 2478 }, { 3180, 2479 }, { 3181, 2480 }, { 3182, 2481 }, { 3183, 2482 }, { 3184, 2483 }, { 3185, 2484 }, + { 3186, 2485 }, { 3187, 2486 }, { 3188, 2487 }, { 3189, 2488 }, { 3190, 2489 }, { 3191, 2490 }, { 3192, 2491 }, + { 3193, 2492 }, { 3194, 2493 }, { 3195, 2494 }, { 3196, 2495 }, { 3197, 2496 }, { 3198, 2497 }, { 3199, 2498 }, + { 3200, 2499 }, { 3201, 2500 }, { 3202, 2501 }, { 3203, 2502 }, { 3204, 2503 }, { 3205, 2504 }, { 3206, 2505 }, + { 3207, 2506 }, { 3208, 2507 }, { 3209, 2508 }, { 3210, 2509 }, { 3211, 2510 }, { 3212, 2511 }, { 3213, 2512 }, + { 3214, 2513 }, { 3215, 2514 }, { 3216, 2515 }, { 3217, 2516 }, { 3218, 2517 }, { 3219, 2518 }, { 3220, 2519 }, + { 3221, 2520 }, { 3222, 2521 }, { 3223, 2522 }, { 3224, 2523 }, { 3271, 2524 }, { 3272, 2525 }, { 3273, 2526 }, + { 3274, 2527 }, { 3275, 2528 }, { 3276, 2529 }, { 3277, 2530 }, { 3278, 2531 }, { 3279, 2532 }, { 3280, 2533 }, + { 3281, 2534 }, { 3282, 2535 }, { 3283, 2536 }, { 3284, 2537 }, { 3285, 2538 }, { 3286, 2539 }, { 3287, 2540 }, + { 3288, 2541 }, { 3289, 2542 }, { 3290, 2543 }, { 3291, 2544 }, { 3292, 2545 }, { 3293, 2546 }, { 3294, 2547 }, + { 3295, 2548 }, { 3296, 2549 }, { 3297, 2550 }, { 3298, 2551 }, { 3299, 2552 }, { 3300, 2553 }, { 3301, 2554 }, + { 3302, 2555 }, { 3303, 2556 }, { 3304, 2557 }, { 3371, 2558 }, { 3372, 2559 }, { 3373, 2560 }, { 3374, 2561 }, + { 3375, 2562 }, { 3376, 2563 }, { 3377, 2564 }, { 3378, 2565 }, { 3379, 2566 }, { 3380, 2567 }, { 3381, 2568 }, + { 3382, 2569 }, { 3383, 2570 }, { 3384, 3024 }, { 3385, 2572 }, { 3471, 2573 }, { 3472, 2574 }, { 3473, 2575 }, + { 3474, 2576 }, { 3475, 2577 }, { 3476, 2578 }, { 3477, 2579 }, { 3478, 2580 }, { 3479, 2581 }, { 3480, 2582 }, + { 3481, 2583 }, { 3482, 2584 }, { 3483, 2585 }, { 3484, 2586 }, { 3485, 2587 }, { 3486, 2588 }, { 3487, 2589 }, + { 3488, 2590 }, { 3489, 2591 }, { 3490, 2592 }, { 3491, 2593 }, { 3492, 2594 }, { 3493, 2595 }, { 3494, 2596 }, + { 3495, 2597 }, { 3496, 2598 }, { 3497, 2599 }, { 3498, 2600 }, { 3499, 2601 }, { 3500, 2602 }, { 3501, 2603 }, + { 3502, 2604 }, { 3503, 2605 }, { 3504, 2606 }, { 3505, 2607 }, { 3506, 2608 }, { 3507, 2609 }, { 3508, 2610 }, + { 3509, 2611 }, { 3510, 2612 }, { 3571, 2613 }, { 3572, 2614 }, { 3573, 2615 }, { 3574, 2616 }, { 3575, 2617 }, + { 3576, 2618 }, { 3577, 2619 }, { 3578, 2620 }, { 3579, 2621 }, { 3580, 2622 }, { 3581, 2623 }, { 3582, 2624 }, + { 3583, 2625 }, { 3584, 2626 }, { 3585, 2627 }, { 3586, 2628 }, { 3587, 2629 }, { 3588, 2630 }, { 3589, 2631 }, + { 3590, 2632 }, { 3591, 2633 }, { 3592, 2634 }, { 3593, 2635 }, { 3594, 2636 }, { 3595, 2637 }, { 3596, 2638 }, + { 3597, 2639 }, { 3598, 2640 }, { 3599, 2641 }, { 3600, 2642 }, { 3601, 2643 }, { 3602, 2644 }, { 3603, 2645 }, + { 3604, 2646 }, { 3605, 2647 }, { 3606, 2648 }, { 3607, 2649 }, { 3608, 2650 }, { 3609, 2651 }, { 3610, 2652 }, + { 3611, 2653 }, { 3612, 2654 }, { 3613, 2655 }, { 3614, 2656 }, { 3615, 2657 }, { 3616, 2658 }, { 3617, 2659 }, + { 3618, 2660 }, { 3619, 2661 }, { 3620, 2662 }, { 3621, 2663 }, { 3622, 2664 }, { 3623, 2665 }, { 3624, 2666 }, + { 3625, 2667 }, { 3626, 2668 }, { 3627, 2669 }, { 3628, 2670 }, { 3629, 2671 }, { 3630, 2672 }, { 3631, 2673 }, + { 3632, 2674 }, { 3633, 2675 }, { 3634, 2676 }, { 3635, 2677 }, { 3636, 2678 }, { 3637, 2679 }, { 3638, 2680 }, + { 3639, 2681 }, { 3640, 2682 }, { 3641, 2683 }, { 3642, 2684 }, { 3643, 2685 }, { 3644, 2686 }, { 3645, 2687 }, + { 3646, 2688 }, { 3671, 2689 }, { 3672, 2690 }, { 3673, 2691 }, { 3674, 2692 }, { 3675, 2693 }, { 3676, 2694 }, + { 3677, 2695 }, { 3678, 2696 }, { 3679, 2697 }, { 3680, 2698 }, { 3681, 2699 }, { 3682, 2700 }, { 3683, 2701 }, + { 3684, 2702 }, { 3685, 2703 }, { 3686, 2704 }, { 3687, 2705 }, { 3688, 2706 }, { 3689, 2707 }, { 3690, 2708 }, + { 3691, 2709 }, { 3692, 2710 }, { 3693, 2711 }, { 3694, 2712 }, { 3695, 2713 }, { 3696, 2714 }, { 3697, 2715 }, + { 3698, 2716 }, { 3699, 2717 }, { 3700, 2718 }, { 3701, 2719 }, { 3702, 2720 }, { 3703, 2721 }, { 3704, 2722 }, + { 3705, 2723 }, { 3706, 2724 }, { 3707, 2725 }, { 3708, 2726 }, { 3709, 2727 }, { 3710, 2728 }, { 3711, 2729 }, + { 3712, 2730 }, { 3713, 2731 }, { 3714, 2732 }, { 3715, 2733 }, { 3716, 2734 }, { 3717, 2735 }, { 3718, 2736 }, + { 3719, 2737 }, { 3720, 2738 }, { 3721, 2739 }, { 3722, 2740 }, { 3723, 2741 }, { 3724, 2742 }, { 3725, 2743 }, + { 3726, 2744 }, { 3727, 2745 }, { 3728, 2746 }, { 3729, 2747 }, { 3730, 2748 }, { 3927, 2749 }, { 3928, 2750 }, + { 3929, 2751 }, { 3930, 2752 }, { 3931, 2753 }, { 3932, 2754 }, { 3933, 2755 }, { 3934, 2756 }, { 3940, 2762 }, + { 3941, 2763 }, { 3942, 2764 }, { 3943, 2765 }, { 3944, 2766 }, { 3945, 2767 }, { 3946, 2768 }, { 3947, 2769 }, + { 3948, 2770 }, { 3949, 2771 }, { 3950, 2772 }, { 3951, 2773 }, { 3952, 2774 }, { 3953, 2775 }, { 3954, 2776 }, + { 3955, 2777 }, { 3956, 2778 }, { 3957, 2779 }, { 3958, 2780 }, { 3959, 2781 }, { 3960, 2782 }, { 3961, 2783 }, + { 3962, 2784 }, { 3963, 2785 }, { 3964, 2786 }, { 3965, 2787 }, { 3966, 2788 }, { 3967, 2789 }, { 3968, 2790 }, + { 3969, 2791 }, { 3970, 2792 }, { 3971, 2793 }, { 3972, 2794 }, { 3973, 2795 }, { 3974, 2796 }, { 3975, 2797 }, + { 3976, 2798 }, { 3977, 2799 }, { 3978, 2800 }, { 3979, 2801 }, { 3980, 2802 }, { 3981, 2803 }, { 3982, 2804 }, + { 3983, 2805 }, { 3984, 2806 }, { 3985, 2807 }, { 3986, 2808 }, { 3987, 2809 }, { 3988, 2810 }, { 3989, 2811 }, + { 3990, 2812 }, { 3991, 2813 }, { 3992, 2814 }, { 3993, 2815 }, { 3994, 2816 }, { 3995, 2817 }, { 3996, 2818 }, + { 3997, 2819 }, { 3998, 2820 }, { 3999, 2821 }, { 4000, 2822 }, { 4001, 2823 }, { 4002, 2824 }, { 4003, 2825 }, + { 4004, 2826 }, { 4005, 2827 }, { 4006, 2828 }, { 4007, 2829 }, { 4008, 2830 }, { 4009, 2831 }, { 4010, 2832 }, + { 4011, 2833 }, { 4012, 2834 }, { 4013, 2835 }, { 4014, 2836 }, { 4015, 2837 }, { 4016, 2838 }, { 4017, 2839 }, + { 4018, 2840 }, { 4019, 2841 }, { 4020, 2842 }, { 4021, 2843 }, { 4022, 2844 }, { 4023, 2845 }, { 4024, 2846 }, + { 4025, 2847 }, { 4026, 2848 }, { 4027, 2849 }, { 4028, 2850 }, { 4029, 2851 }, { 4030, 2852 }, { 4031, 2853 }, + { 4032, 2854 }, { 4127, 2855 }, { 4128, 2856 }, { 4129, 2857 }, { 4130, 2858 }, { 4131, 2859 }, { 4132, 2860 }, + { 4133, 2861 }, { 4134, 2862 }, { 4135, 2863 }, { 4136, 2864 }, { 4137, 2865 }, { 4138, 2866 }, { 4139, 2867 }, + { 4140, 2868 }, { 4145, 2873 }, { 4146, 2874 }, { 4147, 2875 }, { 4148, 2876 }, { 4149, 2877 }, { 4150, 2878 }, + { 4151, 2879 }, { 4152, 2880 }, { 4153, 2881 }, { 4154, 2882 }, { 4155, 2883 }, { 4156, 2884 }, { 4157, 2885 }, + { 4158, 2886 }, { 4159, 2887 }, { 4160, 2888 }, { 4227, 2889 }, { 4228, 2890 }, { 4229, 2891 }, { 4230, 2892 }, + { 4231, 2893 }, { 4232, 2894 }, { 4233, 2895 }, { 4234, 2896 }, { 4235, 2897 }, { 4236, 2898 }, { 4237, 2899 }, + { 4238, 2900 }, { 4239, 2901 }, { 4240, 2902 }, { 4241, 2903 }, { 4242, 2904 }, { 4243, 2905 }, { 4244, 2906 }, + { 4245, 2907 }, { 4246, 2908 }, { 4247, 2909 }, { 4248, 2910 }, { 4249, 2911 }, { 4250, 2912 }, { 4251, 2913 }, + { 4252, 2914 }, { 4253, 2915 }, { 4254, 2916 }, { 4255, 2917 }, { 4256, 2918 }, { 4257, 2919 }, { 4258, 2920 }, + { 4327, 2921 }, { 4328, 2922 }, { 4329, 2923 }, { 4330, 2924 }, { 4331, 2925 }, { 4332, 2926 }, { 4333, 2927 }, + { 4334, 2928 }, { 4335, 2929 }, { 4336, 2930 }, { 4337, 2931 }, { 4338, 2932 }, { 4339, 2933 }, { 4340, 2934 }, + { 4341, 2935 }, { 4342, 2936 }, { 4343, 2937 }, { 4344, 2938 }, { 4345, 2939 }, { 4346, 2940 }, { 4347, 2941 }, + { 4348, 2942 }, { 4349, 2943 }, { 4350, 2944 }, { 4351, 2945 }, { 4352, 2946 }, { 4353, 2947 }, { 4354, 2948 }, + { 4355, 2949 }, { 4356, 2950 }, { 4357, 2951 }, { 4358, 2952 }, { 4359, 2953 }, { 4360, 2954 }, { 4361, 2955 }, + { 4362, 2956 }, { 4363, 2957 }, { 4364, 2958 }, { 4365, 2959 }, { 4366, 2960 }, { 4367, 2961 }, { 4368, 2962 }, + { 4369, 2963 }, { 4370, 2964 }, { 4371, 2965 }, { 4372, 2966 }, { 4373, 2967 }, { 4374, 2968 }, { 4375, 2969 }, + { 4376, 2970 }, { 4377, 2971 }, { 4378, 2972 }, { 4379, 2973 }, { 4380, 2974 }, { 4381, 2975 }, { 4382, 2976 }, + { 4383, 2977 }, { 4384, 2978 }, { 4385, 2979 }, { 4386, 2980 }, { 4387, 2981 }, { 4388, 2982 }, { 4389, 2983 }, + { 4390, 2984 }, { 4391, 2985 }, { 4392, 2986 }, { 4393, 2987 }, { 4394, 2988 }, { 4395, 2989 }, { 4396, 2990 }, + { 4397, 2991 }, { 4398, 2992 }, { 4399, 2993 }, { 4400, 2994 }, { 4406, 3000 }, { 4407, 3001 }, { 4408, 3002 }, + { 4409, 3003 }, { 4410, 3004 }, { 4411, 3005 }, { 4412, 3006 }, { 4413, 3007 }, { 4414, 3008 }, { 4415, 3009 }, + { 4416, 3010 }, { 4417, 3011 }, { 4418, 3012 }, { 4419, 3013 }, { 4420, 3014 }, { 4421, 3015 }, { 4422, 3016 }, + { 4423, 3017 }, { 4424, 3018 }, { 4425, 3019 }, { 4426, 3020 }, { 4431, 3025 }, { 4432, 3026 }, { 4433, 3027 }, + { 4434, 3028 }, { 4435, 3029 }, { 4436, 3030 }, { 4437, 3031 }, { 4438, 3032 }, { 4439, 3033 }, { 4440, 3034 }, + { 4441, 3035 }, { 4442, 3036 }, { 4443, 3037 }, { 4444, 3038 }, { 4445, 3039 }, { 4446, 3040 }, { 4447, 3041 }, + { 4448, 3042 }, { 4449, 3043 }, { 4450, 3044 }, { 4527, 3045 }, { 4528, 3046 }, { 4529, 3047 }, { 4530, 3048 }, + { 4531, 3049 }, { 4532, 3050 }, { 4533, 3051 }, { 4534, 3052 }, { 4535, 3053 }, { 4536, 3054 }, { 4537, 3055 }, + { 4538, 3056 }, { 4539, 3057 }, { 4540, 3058 }, { 4541, 3059 }, { 4542, 3060 }, { 4543, 3061 }, { 4544, 3062 }, + { 4545, 3063 }, { 4546, 3064 }, { 4547, 3066 }, { 4548, 3067 }, { 4549, 3068 }, { 4550, 3069 }, { 4551, 3070 }, + { 4552, 3071 }, { 4553, 3072 }, { 4627, 3073 }, { 4628, 3074 }, { 4629, 3075 }, { 4630, 3076 }, { 4631, 3077 }, + { 4632, 3078 }, { 4633, 3079 }, { 4634, 3080 }, { 4635, 3081 }, { 4636, 3082 }, { 4637, 3083 }, { 4638, 3084 }, + { 4639, 3085 }, { 4640, 3086 }, { 4641, 3087 }, { 4642, 3088 }, { 4643, 3089 }, { 4644, 3090 }, { 4645, 3091 }, + { 4646, 3092 }, { 4647, 3093 }, { 4648, 3094 }, { 4649, 3095 }, { 4650, 3096 }, { 4651, 3097 }, { 4652, 3098 }, + { 4653, 3099 }, { 4654, 3100 }, { 4655, 3101 }, { 4656, 3102 }, { 4657, 3103 }, { 4658, 3104 }, { 4659, 3105 }, + { 4660, 3106 }, { 4661, 3107 }, { 4662, 3108 }, { 4663, 3109 }, { 4664, 3110 }, { 4665, 3111 }, { 4666, 3112 }, + { 4667, 3113 }, { 4668, 3114 }, { 4669, 3115 }, { 4670, 3116 }, { 4671, 3117 }, { 4672, 3118 }, { 4673, 3119 }, + { 4674, 3120 }, { 4675, 3121 }, { 4676, 3122 }, { 4677, 3123 }, { 4678, 3124 }, { 4679, 3125 }, { 4680, 3126 }, + { 4681, 3127 }, { 4682, 3128 }, { 4683, 3129 }, { 4684, 3130 }, { 4685, 3131 }, { 4686, 3132 }, { 4687, 3133 }, + { 4688, 3134 }, { 4689, 3135 }, { 4690, 3136 }, { 4691, 3137 }, { 4692, 3138 }, { 4693, 3139 }, { 4694, 3140 }, + { 4695, 3141 }, { 4696, 3142 }, { 4697, 3143 }, { 4698, 3144 }, { 4699, 3145 }, { 4700, 3146 }, { 4701, 3147 }, + { 4702, 3148 }, { 4703, 3149 }, { 4704, 3150 }, { 4705, 3151 }, { 4706, 3152 }, { 4707, 3153 }, { 4708, 3154 }, + { 4709, 3155 }, { 4710, 3156 }, { 4711, 3157 }, { 4712, 3158 }, { 4713, 3159 }, { 4714, 3160 }, { 4715, 3161 }, + { 4716, 3162 }, { 4717, 3163 }, { 4718, 3164 }, { 4719, 3165 }, { 4720, 3166 }, { 4721, 3167 }, { 4722, 3168 }, + { 4723, 3169 }, { 4724, 3170 }, { 4725, 3171 }, { 4726, 3172 }, { 4827, 3173 }, { 4828, 3174 }, { 4829, 3175 }, + { 4830, 3176 }, { 4831, 3177 }, { 4832, 3178 }, { 4833, 3179 }, { 4834, 3180 }, { 4835, 3181 }, { 4836, 3182 }, + { 4837, 3183 }, { 4838, 3184 }, { 4839, 3185 }, { 4840, 3186 }, { 4841, 3187 }, { 4842, 3188 }, { 4843, 3189 }, + { 4844, 3190 }, { 4845, 3191 }, { 5027, 3192 }, { 5028, 3193 }, { 5029, 3194 }, { 5030, 3195 }, { 5031, 3196 }, + { 5032, 3197 }, { 5033, 3198 }, { 5034, 3199 }, { 5035, 3200 }, { 5036, 3201 }, { 5037, 3202 }, { 5038, 3203 }, + { 5039, 3204 }, { 5040, 3205 }, { 5041, 3206 }, { 5042, 3207 }, { 5043, 3208 }, { 5044, 3209 }, { 5045, 3210 }, + { 5046, 3211 }, { 5047, 3212 }, { 5048, 3213 }, { 5049, 3214 }, { 5050, 3215 }, { 5051, 3216 }, { 5052, 3217 }, + { 5053, 3218 }, { 5054, 3219 }, { 5055, 3220 }, { 5056, 3221 }, { 5057, 3222 }, { 5058, 3223 }, { 5059, 3224 }, + { 5060, 3225 }, { 5061, 3226 }, { 5062, 3227 }, { 5063, 3228 }, { 5064, 3229 }, { 5065, 3230 }, { 5066, 3231 }, + { 5067, 3232 }, { 5068, 3233 }, { 5069, 3234 }, { 5070, 3235 }, { 5071, 3236 }, { 5072, 3237 }, { 5073, 3238 }, + { 5074, 3239 }, { 5075, 3240 }, { 5076, 3241 }, { 5077, 3242 }, { 5127, 3243 }, { 5128, 3244 }, { 5129, 3245 }, + { 5130, 3246 }, { 5131, 3247 }, { 5132, 3248 }, { 5133, 3249 }, { 5134, 3250 }, { 5135, 3251 }, { 5136, 3252 }, + { 5137, 3253 }, { 5138, 3254 }, { 5139, 3255 }, { 5140, 3256 }, { 5141, 3257 }, { 5142, 3258 }, { 5143, 3259 }, + { 5144, 3260 }, { 5145, 3261 }, { 5146, 3262 }, { 5147, 3263 }, { 5148, 3264 }, { 5149, 3265 }, { 5150, 3266 }, + { 5151, 3267 }, { 5152, 3268 }, { 5153, 3269 }, { 5154, 3270 }, { 5155, 3271 }, { 5156, 3272 }, { 5227, 3273 }, + { 5228, 3274 }, { 5229, 3275 }, { 5230, 3276 }, { 5231, 3277 }, { 5232, 3278 }, { 5233, 3279 }, { 5234, 3280 }, + { 5235, 3281 }, { 5236, 3282 }, { 5237, 3283 }, { 5238, 3284 }, { 5240, 3286 }, { 5241, 3287 }, { 5242, 3288 }, + { 5243, 3289 }, { 5244, 3290 }, { 5245, 3291 }, { 5246, 3292 }, { 5247, 3293 }, { 5248, 3294 }, { 5249, 3295 }, + { 5250, 3296 }, { 5251, 3297 }, { 5252, 3298 }, { 5253, 3299 }, { 5254, 3300 }, { 5255, 3301 }, { 5256, 3302 }, + { 5257, 3303 }, { 5258, 3304 }, { 5259, 3305 }, { 5260, 3306 }, { 5261, 3307 }, { 5262, 3308 }, { 5263, 3309 }, + { 5264, 3310 }, { 5265, 3311 }, { 5266, 3312 }, { 5267, 3313 }, { 5268, 3314 }, { 5269, 3315 }, { 5270, 3316 }, + { 5271, 3317 }, { 5272, 3318 }, { 5273, 3319 }, { 5274, 3320 }, { 5275, 3321 }, { 5276, 3322 }, { 5277, 3323 }, + { 5278, 3324 }, { 5279, 3325 }, { 5280, 3326 }, { 5281, 3327 }, { 5282, 3328 }, { 5283, 3329 }, { 5284, 3330 }, + { 5285, 3331 }, { 5286, 3332 }, { 5288, 3334 }, { 5289, 3335 }, { 5290, 3336 }, { 5291, 3337 }, { 5292, 3338 }, + { 5293, 3339 }, { 5294, 3340 }, { 5296, 3342 }, { 5297, 3343 }, { 5298, 3344 }, { 5299, 3345 }, { 5300, 3346 }, + { 5301, 3347 }, { 5302, 3348 }, { 5303, 3349 }, { 5304, 3350 }, { 5305, 3351 }, { 5306, 3352 }, { 5307, 3353 }, + { 5308, 3354 }, { 5309, 3355 }, { 5310, 3356 }, { 5311, 3357 }, { 5312, 3358 }, { 5313, 3359 }, { 5314, 3360 }, + { 5315, 3361 }, { 5316, 3362 }, { 5317, 3363 }, { 5318, 3364 }, { 5319, 3365 }, { 5320, 3366 }, { 5321, 3367 }, + { 5322, 3368 }, { 5323, 3369 }, { 5324, 3370 }, { 5325, 3371 }, { 5326, 3372 }, { 5327, 3373 }, { 5328, 3374 }, + { 5329, 3375 }, { 5330, 3376 }, { 5331, 3377 }, { 5332, 3378 }, { 5333, 3379 }, { 5336, 3382 }, { 5337, 3383 }, + { 5338, 3384 }, { 5339, 3385 }, { 5340, 3386 }, { 5341, 3387 }, { 5342, 3388 }, { 5343, 3389 }, { 5344, 3390 }, + { 5345, 3391 }, { 5346, 3392 }, { 5347, 3393 }, { 5348, 3394 }, { 5349, 3395 }, { 5350, 3396 }, { 5351, 3397 }, + { 5352, 3398 }, { 5357, 3403 }, { 5358, 3404 }, { 5359, 3405 }, { 5360, 3406 }, { 5361, 3407 }, { 5362, 3408 }, + { 5363, 3409 }, { 5364, 3410 }, { 5365, 3411 }, { 5366, 3412 }, { 5367, 3413 }, { 5368, 3414 }, { 5369, 3415 }, + { 5370, 3416 }, { 5371, 3417 }, { 5372, 3418 }, { 5373, 3419 }, { 5374, 3420 }, { 5375, 3421 }, { 5376, 3422 }, + { 5377, 3423 }, { 5378, 3424 }, { 5379, 3425 }, { 5380, 3426 }, { 5381, 3427 }, { 5382, 3428 }, { 5383, 3429 }, + { 5384, 3430 }, { 5385, 3431 }, { 5386, 3432 }, { 5387, 3433 }, { 5388, 3434 }, { 5389, 3435 }, { 5390, 3436 }, + { 5391, 3437 }, { 5392, 3438 }, { 5393, 3439 }, { 5394, 3440 }, { 5395, 3441 }, { 5396, 3442 }, { 5397, 3443 }, + { 5398, 3444 }, { 5399, 3445 }, { 5400, 3446 }, { 5401, 3447 }, { 5402, 3448 }, { 5403, 3449 }, { 5404, 3450 }, + { 5405, 3451 }, { 5406, 3452 }, { 5407, 3453 }, { 5408, 3454 }, { 5409, 3455 }, { 5410, 3456 }, { 5411, 3457 }, + { 5412, 3458 }, { 5413, 3459 }, { 5414, 3460 }, { 5415, 3461 }, { 5416, 3462 }, { 5417, 3463 }, { 5418, 3464 }, + { 5419, 3465 }, { 5420, 3466 }, { 5421, 3467 }, { 5422, 3468 }, { 5423, 3469 }, { 5424, 3470 }, { 5425, 3471 }, + { 5426, 3472 }, { 5427, 3473 }, { 5428, 3474 }, { 5429, 3475 }, { 5430, 3476 }, { 5431, 3477 }, { 5432, 3478 }, + { 5433, 3479 }, { 5434, 3480 }, { 5435, 3481 }, { 5436, 3482 }, { 5437, 3483 }, { 5438, 3484 }, { 5439, 3485 }, + { 5440, 3486 }, { 5441, 3487 }, { 5442, 3488 }, { 5443, 3489 }, { 5444, 3490 }, { 5445, 3491 }, { 5446, 3492 }, + { 5447, 3493 }, { 5448, 3494 }, { 5449, 3495 }, { 5450, 3496 }, { 5451, 3497 }, { 5452, 3498 }, { 5453, 3499 }, + { 5454, 3500 }, { 5455, 3501 }, { 5456, 3502 }, { 5457, 3503 }, { 5458, 3504 }, { 5459, 3505 }, { 5460, 3506 }, + { 5461, 3507 }, { 5462, 3508 }, { 5463, 3509 }, { 5464, 3510 }, { 5465, 3511 }, { 5466, 3512 }, { 5467, 3513 }, + { 5468, 3514 }, { 5469, 3515 }, { 5470, 3516 }, { 5471, 3517 }, { 5472, 3518 }, { 5473, 3519 }, { 5474, 3520 }, + { 5475, 3521 }, { 5476, 3522 }, { 5477, 3523 }, { 5478, 3524 }, { 5479, 3525 }, { 5480, 3526 }, { 5481, 3527 }, + { 5482, 3528 }, { 5483, 3529 }, { 5484, 3530 }, { 5485, 3531 }, { 5486, 3532 }, { 5487, 3533 }, { 5488, 3534 }, + { 5489, 3535 }, { 5490, 3536 }, { 5491, 3537 }, { 5492, 3538 }, { 5493, 3539 }, { 5494, 3540 }, { 5495, 3541 }, + { 5496, 3542 }, { 5497, 3543 }, { 5498, 3544 }, { 5499, 3545 }, { 5500, 3546 }, { 5501, 3547 }, { 5502, 3548 }, + { 5503, 3549 }, { 5504, 3550 }, { 5505, 3551 }, { 5506, 3552 }, { 5507, 3553 }, { 5508, 3554 }, { 5509, 3555 }, + { 5510, 3556 }, { 5511, 3557 }, { 5512, 3558 }, { 5513, 3559 }, { 5514, 3560 }, { 5515, 3561 }, { 5516, 3562 }, + { 5517, 3563 }, { 5518, 3564 }, { 5519, 3565 }, { 5520, 3566 }, { 5521, 3567 }, { 5522, 3568 }, { 5523, 3569 }, + { 5524, 3570 }, { 5525, 3571 }, { 5526, 3572 }, { 5527, 3573 }, { 5528, 3574 }, { 5529, 3575 }, { 5530, 3576 }, + { 5531, 3577 }, { 5532, 3578 }, { 5533, 3579 }, { 5534, 3580 }, { 5535, 3581 }, { 5536, 3582 }, { 5537, 3583 }, + { 5538, 3584 }, { 5539, 3585 }, { 5540, 3586 }, { 5541, 3587 }, { 5542, 3588 }, { 5543, 3589 }, { 5544, 3590 }, + { 5545, 3591 }, { 5546, 3592 }, { 5547, 3593 }, { 5548, 3594 }, { 5549, 3595 }, { 5550, 3596 }, { 5551, 3597 }, + { 5552, 3598 }, { 5553, 3599 }, { 5554, 3600 }, { 5555, 3601 }, { 5556, 3602 }, { 5557, 3603 }, { 5558, 3604 }, + { 5559, 3605 }, { 5560, 3606 }, { 5561, 3607 }, { 5562, 3608 }, { 5563, 3609 }, { 5564, 3610 }, { 5565, 3611 }, + { 5566, 3612 }, { 5567, 3613 }, { 5568, 3614 }, { 5569, 3615 }, { 5570, 3616 }, { 4554, 3065 }, }; -// v1.0 -> JP asset ID remap table. 1312 entries. +// v1.0 -> JP asset ID remap table. 1309 entries. static const std::unordered_map sV10toJPRemap = { { 2468, 2212 }, { 2469, 2213 }, { 2470, 2214 }, { 2471, 2215 }, { 2472, 2216 }, { 2473, 2217 }, { 2474, 2218 }, { 2475, 2219 }, { 2476, 2220 }, { 2477, 2221 }, { 2478, 2222 }, { 2481, 2225 }, { 2483, 2227 }, { 2484, 2228 }, { 2485, 2229 }, { 2487, 2231 }, { 2488, 2232 }, { 2489, 2233 }, { 2490, 2234 }, { 2491, 2235 }, { 2498, 2242 }, - { 2504, 2248 }, { 2508, 2252 }, { 2511, 2255 }, { 2513, 2257 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, - { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, - { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, - { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, - { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, - { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, - { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, - { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, - { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, - { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, - { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, - { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, - { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, { 2877, 2395 }, { 2878, 2396 }, { 2879, 2397 }, { 2880, 2398 }, - { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, - { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, - { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, - { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, - { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, - { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, - { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, - { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, - { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, { 3104, 2463 }, { 3105, 2464 }, { 3106, 2466 }, { 3107, 2467 }, - { 3108, 2468 }, { 3109, 2469 }, { 3110, 2470 }, { 3111, 2471 }, { 3112, 2472 }, { 3113, 2473 }, { 3114, 2474 }, - { 3115, 2475 }, { 3171, 2476 }, { 3172, 2477 }, { 3173, 2478 }, { 3174, 2479 }, { 3175, 2480 }, { 3176, 2481 }, - { 3177, 2482 }, { 3178, 2483 }, { 3179, 2484 }, { 3180, 2485 }, { 3181, 2486 }, { 3182, 2487 }, { 3183, 2488 }, - { 3184, 2489 }, { 3185, 2490 }, { 3186, 2491 }, { 3187, 2492 }, { 3188, 2493 }, { 3189, 2494 }, { 3190, 2495 }, - { 3191, 2496 }, { 3192, 2497 }, { 3193, 2498 }, { 3194, 2499 }, { 3195, 2500 }, { 3196, 2501 }, { 3197, 2502 }, - { 3198, 2503 }, { 3199, 2504 }, { 3200, 2505 }, { 3201, 2506 }, { 3202, 2507 }, { 3203, 2508 }, { 3204, 2509 }, - { 3205, 2510 }, { 3206, 2511 }, { 3207, 2512 }, { 3208, 2513 }, { 3209, 2514 }, { 3210, 2515 }, { 3211, 2516 }, - { 3212, 2517 }, { 3213, 2518 }, { 3214, 2519 }, { 3215, 2520 }, { 3216, 2521 }, { 3217, 2522 }, { 3218, 2523 }, - { 3219, 2524 }, { 3220, 2525 }, { 3221, 2526 }, { 3222, 2527 }, { 3223, 2528 }, { 3224, 2529 }, { 3271, 2530 }, - { 3272, 2531 }, { 3273, 2532 }, { 3274, 2533 }, { 3275, 2534 }, { 3276, 2535 }, { 3277, 2536 }, { 3278, 2537 }, - { 3279, 2538 }, { 3280, 2539 }, { 3281, 2540 }, { 3282, 2541 }, { 3283, 2542 }, { 3284, 2543 }, { 3285, 2544 }, - { 3286, 2545 }, { 3287, 2546 }, { 3288, 2547 }, { 3289, 2548 }, { 3290, 2549 }, { 3291, 2550 }, { 3292, 2551 }, - { 3293, 2552 }, { 3294, 2553 }, { 3295, 2554 }, { 3296, 2555 }, { 3297, 2556 }, { 3298, 2557 }, { 3299, 2558 }, - { 3300, 2559 }, { 3301, 2560 }, { 3302, 2561 }, { 3303, 2562 }, { 3304, 2563 }, { 3371, 2564 }, { 3372, 2565 }, - { 3373, 2566 }, { 3374, 2567 }, { 3375, 2568 }, { 3376, 2569 }, { 3377, 2570 }, { 3378, 2571 }, { 3379, 2572 }, - { 3380, 2573 }, { 3381, 2574 }, { 3382, 2575 }, { 3383, 2576 }, { 3384, 2577 }, { 3385, 2578 }, { 3471, 2579 }, - { 3472, 2580 }, { 3473, 2581 }, { 3474, 2582 }, { 3475, 2583 }, { 3476, 2584 }, { 3477, 2585 }, { 3478, 2586 }, - { 3479, 2587 }, { 3480, 2588 }, { 3481, 2589 }, { 3482, 2590 }, { 3483, 2591 }, { 3484, 2592 }, { 3485, 2593 }, - { 3486, 2594 }, { 3487, 2595 }, { 3488, 2596 }, { 3489, 2597 }, { 3490, 2598 }, { 3491, 2599 }, { 3492, 2600 }, - { 3493, 2601 }, { 3494, 2602 }, { 3495, 2603 }, { 3496, 2604 }, { 3497, 2605 }, { 3498, 2606 }, { 3499, 2607 }, - { 3500, 2608 }, { 3501, 2609 }, { 3502, 2610 }, { 3503, 2611 }, { 3504, 2612 }, { 3505, 2613 }, { 3506, 2614 }, - { 3507, 2615 }, { 3508, 2616 }, { 3509, 2617 }, { 3510, 2618 }, { 3571, 2619 }, { 3572, 2620 }, { 3573, 2621 }, - { 3574, 2622 }, { 3575, 2623 }, { 3576, 2624 }, { 3577, 2625 }, { 3578, 2626 }, { 3579, 2627 }, { 3580, 2628 }, - { 3581, 2629 }, { 3582, 2630 }, { 3583, 2631 }, { 3584, 2632 }, { 3585, 2633 }, { 3586, 2634 }, { 3587, 2635 }, - { 3588, 2636 }, { 3589, 2637 }, { 3590, 2638 }, { 3591, 2639 }, { 3592, 2640 }, { 3593, 2641 }, { 3594, 2642 }, - { 3595, 2643 }, { 3596, 2644 }, { 3597, 2645 }, { 3598, 2646 }, { 3599, 2647 }, { 3600, 2648 }, { 3601, 2649 }, - { 3602, 2650 }, { 3603, 2651 }, { 3604, 2652 }, { 3605, 2653 }, { 3606, 2654 }, { 3607, 2655 }, { 3608, 2656 }, - { 3609, 2657 }, { 3610, 2658 }, { 3611, 2659 }, { 3612, 2660 }, { 3613, 2661 }, { 3614, 2662 }, { 3615, 2663 }, - { 3616, 2664 }, { 3617, 2665 }, { 3618, 2666 }, { 3619, 2667 }, { 3620, 2668 }, { 3621, 2669 }, { 3622, 2670 }, - { 3623, 2671 }, { 3624, 2672 }, { 3625, 2673 }, { 3626, 2674 }, { 3627, 2675 }, { 3628, 2676 }, { 3629, 2677 }, - { 3630, 2678 }, { 3631, 2679 }, { 3632, 2680 }, { 3633, 2681 }, { 3634, 2682 }, { 3635, 2683 }, { 3636, 2684 }, - { 3637, 2685 }, { 3638, 2686 }, { 3639, 2687 }, { 3640, 2688 }, { 3641, 2689 }, { 3642, 2690 }, { 3643, 2691 }, - { 3644, 2692 }, { 3645, 2693 }, { 3646, 2694 }, { 3671, 2696 }, { 3672, 2697 }, { 3673, 2698 }, { 3674, 2699 }, - { 3675, 2700 }, { 3676, 2701 }, { 3677, 2702 }, { 3678, 2703 }, { 3679, 2704 }, { 3680, 2705 }, { 3681, 2706 }, - { 3682, 2707 }, { 3683, 2708 }, { 3684, 2709 }, { 3685, 2710 }, { 3686, 2711 }, { 3687, 2712 }, { 3688, 2713 }, - { 3689, 2714 }, { 3690, 2715 }, { 3691, 2716 }, { 3692, 2717 }, { 3693, 2718 }, { 3694, 2719 }, { 3695, 2720 }, - { 3696, 2721 }, { 3697, 2722 }, { 3698, 2723 }, { 3699, 2724 }, { 3700, 2725 }, { 3701, 2726 }, { 3702, 2727 }, - { 3703, 2728 }, { 3704, 2729 }, { 3705, 2730 }, { 3706, 2731 }, { 3707, 2732 }, { 3708, 2733 }, { 3709, 2734 }, - { 3710, 2735 }, { 3711, 2736 }, { 3712, 2737 }, { 3713, 2738 }, { 3714, 2739 }, { 3715, 2740 }, { 3716, 2741 }, - { 3717, 2742 }, { 3718, 2743 }, { 3719, 2744 }, { 3720, 2745 }, { 3721, 2746 }, { 3722, 2747 }, { 3723, 2748 }, - { 3724, 2749 }, { 3725, 2750 }, { 3726, 2751 }, { 3727, 2752 }, { 3728, 2753 }, { 3729, 2754 }, { 3730, 2755 }, - { 3927, 2756 }, { 3928, 2757 }, { 3929, 2758 }, { 3930, 2759 }, { 3931, 2760 }, { 3932, 2761 }, { 3933, 2762 }, - { 3934, 2763 }, { 3940, 2769 }, { 3941, 2770 }, { 3942, 2771 }, { 3943, 2772 }, { 3944, 2773 }, { 3945, 2774 }, - { 3946, 2775 }, { 3947, 2776 }, { 3948, 2777 }, { 3949, 2778 }, { 3950, 2779 }, { 3951, 2780 }, { 3952, 2781 }, - { 3953, 2782 }, { 3954, 2783 }, { 3955, 2784 }, { 3956, 2785 }, { 3957, 2786 }, { 3958, 2787 }, { 3959, 2788 }, - { 3960, 2789 }, { 3961, 2790 }, { 3962, 2791 }, { 3963, 2792 }, { 3964, 2793 }, { 3965, 2794 }, { 3966, 2795 }, - { 3967, 2796 }, { 3968, 2797 }, { 3969, 2798 }, { 3970, 2799 }, { 3971, 2800 }, { 3972, 2801 }, { 3973, 2802 }, - { 3974, 2803 }, { 3975, 2804 }, { 3976, 2805 }, { 3977, 2806 }, { 3978, 2807 }, { 3979, 2808 }, { 3980, 2809 }, - { 3981, 2810 }, { 3982, 2811 }, { 3983, 2812 }, { 3984, 2813 }, { 3985, 2814 }, { 3986, 2815 }, { 3987, 2816 }, - { 3988, 2817 }, { 3989, 2818 }, { 3990, 2819 }, { 3991, 2820 }, { 3992, 2821 }, { 3993, 2822 }, { 3994, 2823 }, - { 3995, 2824 }, { 3996, 2825 }, { 3997, 2826 }, { 3998, 2827 }, { 3999, 2828 }, { 4000, 2829 }, { 4001, 2830 }, - { 4002, 2831 }, { 4003, 2832 }, { 4004, 2833 }, { 4005, 2834 }, { 4006, 2835 }, { 4007, 2836 }, { 4008, 2837 }, - { 4009, 2838 }, { 4010, 2839 }, { 4011, 2840 }, { 4012, 2841 }, { 4013, 2842 }, { 4014, 2843 }, { 4015, 2844 }, - { 4016, 2845 }, { 4017, 2846 }, { 4018, 2847 }, { 4019, 2848 }, { 4020, 2849 }, { 4021, 2850 }, { 4022, 2851 }, - { 4023, 2852 }, { 4024, 2853 }, { 4025, 2854 }, { 4026, 2855 }, { 4027, 2856 }, { 4028, 2857 }, { 4029, 2858 }, - { 4030, 2859 }, { 4031, 2860 }, { 4032, 2861 }, { 4127, 2863 }, { 4128, 2864 }, { 4129, 2865 }, { 4130, 2866 }, - { 4131, 2867 }, { 4132, 2868 }, { 4133, 2869 }, { 4134, 2870 }, { 4135, 2871 }, { 4136, 2872 }, { 4137, 2873 }, - { 4138, 2874 }, { 4139, 2875 }, { 4140, 2876 }, { 4145, 2881 }, { 4146, 2882 }, { 4147, 2883 }, { 4148, 2884 }, - { 4149, 2885 }, { 4150, 2886 }, { 4151, 2887 }, { 4152, 2888 }, { 4153, 2889 }, { 4154, 2890 }, { 4155, 2891 }, - { 4156, 2892 }, { 4157, 2893 }, { 4158, 2894 }, { 4159, 2895 }, { 4160, 2896 }, { 4227, 2897 }, { 4228, 2898 }, - { 4229, 2899 }, { 4230, 2900 }, { 4231, 2901 }, { 4232, 2902 }, { 4233, 2903 }, { 4234, 2904 }, { 4235, 2905 }, - { 4236, 2906 }, { 4237, 2907 }, { 4238, 2908 }, { 4239, 2909 }, { 4240, 2910 }, { 4241, 2911 }, { 4242, 2912 }, - { 4243, 2913 }, { 4244, 2914 }, { 4245, 2915 }, { 4246, 2916 }, { 4247, 2917 }, { 4248, 2918 }, { 4249, 2919 }, - { 4250, 2920 }, { 4251, 2921 }, { 4252, 2922 }, { 4253, 2923 }, { 4254, 2924 }, { 4255, 2925 }, { 4256, 2926 }, - { 4257, 2927 }, { 4258, 2928 }, { 4327, 2929 }, { 4328, 2930 }, { 4329, 2931 }, { 4330, 2932 }, { 4331, 2933 }, - { 4332, 2934 }, { 4333, 2935 }, { 4334, 2936 }, { 4335, 2937 }, { 4336, 2938 }, { 4337, 2939 }, { 4338, 2940 }, - { 4339, 2941 }, { 4340, 2942 }, { 4341, 2943 }, { 4342, 2944 }, { 4343, 2945 }, { 4344, 2946 }, { 4345, 2947 }, - { 4346, 2948 }, { 4347, 2949 }, { 4348, 2950 }, { 4349, 2951 }, { 4350, 2952 }, { 4351, 2953 }, { 4352, 2954 }, - { 4353, 2955 }, { 4354, 2956 }, { 4355, 2957 }, { 4356, 2958 }, { 4357, 2959 }, { 4358, 2960 }, { 4359, 2961 }, - { 4360, 2962 }, { 4361, 2963 }, { 4362, 2964 }, { 4363, 2965 }, { 4364, 2966 }, { 4365, 2967 }, { 4366, 2968 }, - { 4367, 2969 }, { 4368, 2970 }, { 4369, 2971 }, { 4370, 2972 }, { 4371, 2973 }, { 4372, 2974 }, { 4373, 2975 }, - { 4374, 2976 }, { 4375, 2977 }, { 4376, 2978 }, { 4377, 2979 }, { 4378, 2980 }, { 4379, 2981 }, { 4380, 2982 }, - { 4381, 2983 }, { 4382, 2984 }, { 4383, 2985 }, { 4384, 2986 }, { 4385, 2987 }, { 4386, 2988 }, { 4387, 2989 }, - { 4388, 2990 }, { 4389, 2991 }, { 4390, 2992 }, { 4391, 2993 }, { 4392, 2994 }, { 4393, 2995 }, { 4394, 2996 }, - { 4395, 2997 }, { 4396, 2998 }, { 4397, 2999 }, { 4398, 3000 }, { 4399, 3001 }, { 4400, 3002 }, { 4401, 3003 }, - { 4402, 3004 }, { 4403, 3005 }, { 4404, 3006 }, { 4405, 3007 }, { 4406, 3008 }, { 4407, 3009 }, { 4408, 3010 }, - { 4409, 3011 }, { 4410, 3012 }, { 4411, 3013 }, { 4412, 3014 }, { 4413, 3015 }, { 4414, 3016 }, { 4415, 3017 }, - { 4416, 3018 }, { 4417, 3019 }, { 4418, 3020 }, { 4419, 3021 }, { 4420, 3022 }, { 4421, 3023 }, { 4422, 3024 }, - { 4423, 3025 }, { 4424, 3026 }, { 4425, 3027 }, { 4426, 3028 }, { 4427, 3029 }, { 4428, 3030 }, { 4429, 3031 }, - { 4430, 3032 }, { 4431, 3033 }, { 4432, 3034 }, { 4433, 3035 }, { 4434, 3036 }, { 4435, 3037 }, { 4436, 3038 }, - { 4437, 3039 }, { 4438, 3040 }, { 4439, 3041 }, { 4440, 3042 }, { 4441, 3043 }, { 4442, 3044 }, { 4443, 3045 }, - { 4444, 3046 }, { 4445, 3047 }, { 4446, 3048 }, { 4447, 3049 }, { 4448, 3050 }, { 4449, 3051 }, { 4450, 3052 }, - { 4527, 3053 }, { 4528, 3054 }, { 4529, 3055 }, { 4530, 3056 }, { 4531, 3057 }, { 4532, 3058 }, { 4533, 3059 }, - { 4534, 3060 }, { 4535, 3061 }, { 4536, 3062 }, { 4537, 3063 }, { 4538, 3064 }, { 4539, 3065 }, { 4540, 3066 }, - { 4541, 3067 }, { 4542, 3068 }, { 4543, 3069 }, { 4544, 3070 }, { 4545, 3071 }, { 4546, 3072 }, { 4547, 3074 }, - { 4548, 3075 }, { 4549, 3076 }, { 4550, 3077 }, { 4551, 3078 }, { 4552, 3079 }, { 4553, 3080 }, { 4554, 3073 }, - { 4627, 3081 }, { 4628, 3082 }, { 4629, 3083 }, { 4630, 3084 }, { 4631, 3085 }, { 4632, 3086 }, { 4633, 3087 }, - { 4634, 3088 }, { 4635, 3089 }, { 4636, 3090 }, { 4637, 3091 }, { 4638, 3092 }, { 4639, 3093 }, { 4640, 3094 }, - { 4641, 3095 }, { 4642, 3096 }, { 4643, 3097 }, { 4644, 3098 }, { 4645, 3099 }, { 4646, 3100 }, { 4647, 3101 }, - { 4648, 3102 }, { 4649, 3103 }, { 4650, 3104 }, { 4651, 3105 }, { 4652, 3106 }, { 4653, 3107 }, { 4654, 3108 }, - { 4655, 3109 }, { 4656, 3110 }, { 4657, 3111 }, { 4658, 3112 }, { 4659, 3113 }, { 4660, 3114 }, { 4661, 3115 }, - { 4662, 3116 }, { 4663, 3117 }, { 4664, 3118 }, { 4665, 3119 }, { 4666, 3120 }, { 4667, 3121 }, { 4668, 3122 }, - { 4669, 3123 }, { 4670, 3124 }, { 4671, 3125 }, { 4672, 3126 }, { 4673, 3127 }, { 4674, 3128 }, { 4675, 3129 }, - { 4676, 3130 }, { 4677, 3131 }, { 4678, 3132 }, { 4679, 3133 }, { 4680, 3134 }, { 4681, 3135 }, { 4682, 3136 }, - { 4683, 3137 }, { 4684, 3138 }, { 4685, 3139 }, { 4686, 3140 }, { 4687, 3141 }, { 4688, 3142 }, { 4689, 3143 }, - { 4690, 3144 }, { 4691, 3145 }, { 4692, 3146 }, { 4693, 3147 }, { 4694, 3148 }, { 4695, 3149 }, { 4696, 3150 }, - { 4697, 3151 }, { 4698, 3152 }, { 4699, 3153 }, { 4700, 3154 }, { 4701, 3155 }, { 4702, 3156 }, { 4703, 3157 }, - { 4704, 3158 }, { 4705, 3159 }, { 4706, 3160 }, { 4707, 3161 }, { 4708, 3162 }, { 4709, 3163 }, { 4710, 3164 }, - { 4711, 3165 }, { 4712, 3166 }, { 4713, 3167 }, { 4714, 3168 }, { 4715, 3169 }, { 4716, 3170 }, { 4717, 3171 }, - { 4718, 3172 }, { 4719, 3173 }, { 4720, 3174 }, { 4721, 3175 }, { 4722, 3176 }, { 4723, 3177 }, { 4724, 3178 }, - { 4725, 3179 }, { 4726, 3180 }, { 4827, 3181 }, { 4828, 3182 }, { 4829, 3183 }, { 4830, 3184 }, { 4831, 3185 }, - { 4832, 3186 }, { 4833, 3187 }, { 4834, 3188 }, { 4835, 3189 }, { 4836, 3190 }, { 4837, 3191 }, { 4838, 3192 }, - { 4839, 3193 }, { 4840, 3194 }, { 4841, 3195 }, { 4842, 3196 }, { 4843, 3197 }, { 4844, 3198 }, { 4845, 3199 }, - { 5027, 3200 }, { 5028, 3201 }, { 5029, 3202 }, { 5030, 3203 }, { 5031, 3204 }, { 5032, 3205 }, { 5033, 3206 }, - { 5034, 3207 }, { 5035, 3208 }, { 5036, 3209 }, { 5037, 3210 }, { 5038, 3211 }, { 5039, 3212 }, { 5040, 3213 }, - { 5041, 3214 }, { 5042, 3215 }, { 5043, 3216 }, { 5044, 3217 }, { 5045, 3218 }, { 5046, 3219 }, { 5047, 3220 }, - { 5048, 3221 }, { 5049, 3222 }, { 5050, 3223 }, { 5051, 3224 }, { 5052, 3225 }, { 5053, 3226 }, { 5054, 3227 }, - { 5055, 3228 }, { 5056, 3229 }, { 5057, 3230 }, { 5058, 3231 }, { 5059, 3232 }, { 5060, 3233 }, { 5061, 3234 }, - { 5062, 3235 }, { 5063, 3236 }, { 5064, 3237 }, { 5065, 3238 }, { 5066, 3239 }, { 5067, 3240 }, { 5068, 3241 }, - { 5069, 3242 }, { 5070, 3243 }, { 5071, 3244 }, { 5072, 3245 }, { 5073, 3246 }, { 5074, 3247 }, { 5075, 3248 }, - { 5076, 3249 }, { 5077, 3250 }, { 5127, 3251 }, { 5128, 3252 }, { 5129, 3253 }, { 5130, 3254 }, { 5131, 3255 }, - { 5132, 3256 }, { 5133, 3257 }, { 5134, 3258 }, { 5135, 3259 }, { 5136, 3260 }, { 5137, 3261 }, { 5138, 3262 }, - { 5139, 3263 }, { 5140, 3264 }, { 5141, 3265 }, { 5142, 3266 }, { 5143, 3267 }, { 5144, 3268 }, { 5145, 3269 }, - { 5146, 3270 }, { 5147, 3271 }, { 5148, 3272 }, { 5149, 3273 }, { 5150, 3274 }, { 5151, 3275 }, { 5152, 3276 }, - { 5153, 3277 }, { 5154, 3278 }, { 5155, 3279 }, { 5156, 3280 }, { 5227, 3281 }, { 5228, 3282 }, { 5229, 3283 }, - { 5230, 3284 }, { 5231, 3285 }, { 5232, 3286 }, { 5233, 3287 }, { 5234, 3288 }, { 5235, 3289 }, { 5236, 3290 }, - { 5237, 3291 }, { 5238, 3292 }, { 5240, 3294 }, { 5241, 3295 }, { 5242, 3296 }, { 5243, 3297 }, { 5244, 3298 }, - { 5245, 3299 }, { 5246, 3300 }, { 5247, 3301 }, { 5248, 3302 }, { 5249, 3303 }, { 5250, 3304 }, { 5251, 3305 }, - { 5252, 3306 }, { 5253, 3307 }, { 5254, 3308 }, { 5255, 3309 }, { 5256, 3310 }, { 5257, 3311 }, { 5258, 3312 }, - { 5259, 3313 }, { 5260, 3314 }, { 5261, 3315 }, { 5262, 3316 }, { 5263, 3317 }, { 5264, 3318 }, { 5265, 3319 }, - { 5266, 3320 }, { 5267, 3321 }, { 5268, 3322 }, { 5269, 3323 }, { 5270, 3324 }, { 5271, 3325 }, { 5272, 3326 }, - { 5273, 3327 }, { 5274, 3328 }, { 5275, 3329 }, { 5276, 3330 }, { 5277, 3331 }, { 5278, 3332 }, { 5279, 3333 }, - { 5280, 3334 }, { 5281, 3335 }, { 5282, 3336 }, { 5283, 3337 }, { 5284, 3338 }, { 5285, 3339 }, { 5286, 3340 }, - { 5288, 3342 }, { 5289, 3343 }, { 5290, 3344 }, { 5291, 3345 }, { 5292, 3346 }, { 5293, 3347 }, { 5294, 3348 }, - { 5296, 3350 }, { 5297, 3351 }, { 5298, 3352 }, { 5299, 3353 }, { 5300, 3354 }, { 5301, 3355 }, { 5302, 3356 }, - { 5303, 3357 }, { 5304, 3358 }, { 5305, 3359 }, { 5306, 3360 }, { 5307, 3361 }, { 5308, 3362 }, { 5309, 3363 }, - { 5310, 3364 }, { 5311, 3365 }, { 5312, 3366 }, { 5313, 3367 }, { 5314, 3368 }, { 5315, 3369 }, { 5316, 3370 }, - { 5317, 3371 }, { 5318, 3372 }, { 5319, 3373 }, { 5320, 3374 }, { 5321, 3375 }, { 5322, 3376 }, { 5323, 3377 }, - { 5324, 3378 }, { 5325, 3379 }, { 5326, 3380 }, { 5327, 3381 }, { 5328, 3382 }, { 5329, 3383 }, { 5330, 3384 }, - { 5331, 3385 }, { 5332, 3386 }, { 5333, 3387 }, { 5336, 3390 }, { 5337, 3391 }, { 5338, 3392 }, { 5339, 3393 }, - { 5340, 3394 }, { 5341, 3395 }, { 5342, 3396 }, { 5343, 3397 }, { 5344, 3398 }, { 5345, 3399 }, { 5346, 3400 }, - { 5347, 3401 }, { 5348, 3402 }, { 5349, 3403 }, { 5350, 3404 }, { 5351, 3405 }, { 5352, 3406 }, { 5357, 3411 }, - { 5358, 3412 }, { 5359, 3413 }, { 5360, 3414 }, { 5361, 3415 }, { 5362, 3416 }, { 5363, 3417 }, { 5364, 3418 }, - { 5365, 3419 }, { 5366, 3420 }, { 5367, 3421 }, { 5368, 3422 }, { 5369, 3423 }, { 5370, 3424 }, { 5371, 3425 }, - { 5372, 3426 }, { 5373, 3427 }, { 5374, 3428 }, { 5375, 3429 }, { 5376, 3430 }, { 5377, 3431 }, { 5378, 3432 }, - { 5379, 3433 }, { 5380, 3434 }, { 5381, 3435 }, { 5382, 3436 }, { 5383, 3437 }, { 5384, 3438 }, { 5385, 3439 }, - { 5386, 3440 }, { 5387, 3441 }, { 5388, 3442 }, { 5389, 3443 }, { 5390, 3444 }, { 5391, 3445 }, { 5392, 3446 }, - { 5393, 3447 }, { 5394, 3448 }, { 5395, 3449 }, { 5396, 3450 }, { 5397, 3451 }, { 5398, 3452 }, { 5399, 3453 }, - { 5400, 3454 }, { 5401, 3455 }, { 5402, 3456 }, { 5403, 3457 }, { 5404, 3458 }, { 5405, 3459 }, { 5406, 3460 }, - { 5407, 3461 }, { 5408, 3462 }, { 5409, 3463 }, { 5410, 3464 }, { 5411, 3465 }, { 5412, 3466 }, { 5413, 3467 }, - { 5414, 3468 }, { 5415, 3469 }, { 5416, 3470 }, { 5417, 3471 }, { 5418, 3472 }, { 5419, 3473 }, { 5420, 3474 }, - { 5421, 3475 }, { 5422, 3476 }, { 5423, 3477 }, { 5424, 3478 }, { 5425, 3479 }, { 5426, 3480 }, { 5427, 3481 }, - { 5428, 3482 }, { 5429, 3483 }, { 5430, 3484 }, { 5431, 3485 }, { 5432, 3486 }, { 5433, 3487 }, { 5434, 3488 }, - { 5435, 3489 }, { 5436, 3490 }, { 5437, 3491 }, { 5438, 3492 }, { 5439, 3493 }, { 5440, 3494 }, { 5441, 3495 }, - { 5442, 3496 }, { 5443, 3497 }, { 5444, 3498 }, { 5445, 3499 }, { 5446, 3500 }, { 5447, 3501 }, { 5448, 3502 }, - { 5449, 3503 }, { 5450, 3504 }, { 5451, 3505 }, { 5452, 3506 }, { 5453, 3507 }, { 5454, 3508 }, { 5455, 3509 }, - { 5456, 3510 }, { 5457, 3511 }, { 5458, 3512 }, { 5459, 3513 }, { 5460, 3514 }, { 5461, 3515 }, { 5462, 3516 }, - { 5463, 3517 }, { 5464, 3518 }, { 5465, 3519 }, { 5466, 3520 }, { 5467, 3521 }, { 5468, 3522 }, { 5469, 3523 }, - { 5470, 3524 }, { 5471, 3525 }, { 5472, 3526 }, { 5473, 3527 }, { 5474, 3528 }, { 5475, 3529 }, { 5476, 3530 }, - { 5477, 3531 }, { 5478, 3532 }, { 5479, 3533 }, { 5480, 3534 }, { 5481, 3535 }, { 5482, 3536 }, { 5483, 3537 }, - { 5484, 3538 }, { 5485, 3539 }, { 5486, 3540 }, { 5487, 3541 }, { 5488, 3542 }, { 5489, 3543 }, { 5490, 3544 }, - { 5491, 3545 }, { 5492, 3546 }, { 5493, 3547 }, { 5494, 3548 }, { 5495, 3549 }, { 5496, 3550 }, { 5497, 3551 }, - { 5498, 3552 }, { 5499, 3553 }, { 5500, 3554 }, { 5501, 3555 }, { 5502, 3556 }, { 5503, 3557 }, { 5504, 3558 }, - { 5505, 3559 }, { 5506, 3560 }, { 5507, 3561 }, { 5508, 3562 }, { 5509, 3563 }, { 5510, 3564 }, { 5511, 3565 }, - { 5512, 3566 }, { 5513, 3567 }, { 5514, 3568 }, { 5515, 3569 }, { 5516, 3570 }, { 5517, 3571 }, { 5518, 3572 }, - { 5519, 3573 }, { 5520, 3574 }, { 5521, 3575 }, { 5522, 3576 }, { 5523, 3577 }, { 5524, 3578 }, { 5525, 3579 }, - { 5526, 3580 }, { 5527, 3581 }, { 5528, 3582 }, { 5529, 3583 }, { 5530, 3584 }, { 5531, 3585 }, { 5532, 3586 }, - { 5533, 3587 }, { 5534, 3588 }, { 5535, 3589 }, { 5536, 3590 }, { 5537, 3591 }, { 5538, 3592 }, { 5539, 3593 }, - { 5540, 3594 }, { 5541, 3595 }, { 5542, 3596 }, { 5543, 3597 }, { 5544, 3598 }, { 5545, 3599 }, { 5546, 3600 }, - { 5547, 3601 }, { 5548, 3602 }, { 5549, 3603 }, { 5550, 3604 }, { 5551, 3605 }, { 5552, 3606 }, { 5553, 3607 }, - { 5554, 3608 }, { 5555, 3609 }, { 5556, 3610 }, { 5557, 3611 }, { 5558, 3612 }, { 5559, 3613 }, { 5560, 3614 }, - { 5561, 3615 }, { 5562, 3616 }, { 5563, 3617 }, { 5564, 3618 }, { 5565, 3619 }, { 5566, 3620 }, { 5567, 3621 }, - { 5568, 3622 }, { 5569, 3623 }, { 5570, 3624 }, + { 2504, 2248 }, { 2521, 2252 }, { 2524, 2255 }, { 2526, 2257 }, { 2571, 2315 }, { 2572, 2316 }, { 2573, 2317 }, + { 2574, 2318 }, { 2575, 2319 }, { 2576, 2320 }, { 2577, 2321 }, { 2578, 2322 }, { 2579, 2323 }, { 2580, 2324 }, + { 2581, 2325 }, { 2582, 2326 }, { 2583, 2327 }, { 2584, 2328 }, { 2585, 2329 }, { 2586, 2330 }, { 2587, 2331 }, + { 2588, 2332 }, { 2589, 2333 }, { 2590, 2334 }, { 2591, 2335 }, { 2592, 2336 }, { 2593, 2337 }, { 2594, 2338 }, + { 2595, 2339 }, { 2596, 2340 }, { 2597, 2341 }, { 2598, 2342 }, { 2599, 2343 }, { 2600, 2344 }, { 2601, 2345 }, + { 2602, 2346 }, { 2671, 2347 }, { 2672, 2348 }, { 2673, 2349 }, { 2674, 2350 }, { 2675, 2351 }, { 2676, 2352 }, + { 2677, 2353 }, { 2678, 2354 }, { 2679, 2355 }, { 2680, 2356 }, { 2681, 2357 }, { 2682, 2358 }, { 2683, 2359 }, + { 2684, 2360 }, { 2685, 2361 }, { 2686, 2362 }, { 2687, 2363 }, { 2688, 2364 }, { 2689, 2365 }, { 2690, 2366 }, + { 2691, 2367 }, { 2692, 2368 }, { 2693, 2369 }, { 2694, 2370 }, { 2695, 2371 }, { 2696, 2372 }, { 2771, 2373 }, + { 2772, 2374 }, { 2773, 2375 }, { 2774, 2376 }, { 2775, 2377 }, { 2776, 2378 }, { 2777, 2379 }, { 2778, 2380 }, + { 2779, 2381 }, { 2780, 2382 }, { 2781, 2383 }, { 2782, 2384 }, { 2783, 2385 }, { 2784, 2386 }, { 2785, 2387 }, + { 2786, 2388 }, { 2871, 2389 }, { 2872, 2390 }, { 2873, 2391 }, { 2874, 2392 }, { 2875, 2393 }, { 2876, 2394 }, + { 2877, 2395 }, { 2878, 2396 }, { 2879, 2397 }, { 2880, 2398 }, { 2881, 2399 }, { 2882, 2400 }, { 2883, 2401 }, + { 2884, 2402 }, { 2885, 2403 }, { 2886, 2404 }, { 2887, 2405 }, { 2888, 2406 }, { 2889, 2407 }, { 2890, 2408 }, + { 2891, 2409 }, { 2892, 2410 }, { 2893, 2411 }, { 2894, 2412 }, { 2895, 2413 }, { 2896, 2414 }, { 2897, 2415 }, + { 2971, 2416 }, { 2972, 2417 }, { 2973, 2418 }, { 2974, 2419 }, { 2975, 2420 }, { 2976, 2421 }, { 2977, 2422 }, + { 2978, 2423 }, { 2979, 2424 }, { 3071, 2425 }, { 3072, 2426 }, { 3073, 2427 }, { 3074, 2428 }, { 3075, 2429 }, + { 3076, 2430 }, { 3077, 2431 }, { 3078, 2432 }, { 3079, 2433 }, { 3080, 2434 }, { 3081, 2435 }, { 3082, 2436 }, + { 3083, 2437 }, { 3084, 2438 }, { 3085, 2439 }, { 3086, 2440 }, { 3087, 2441 }, { 3088, 2442 }, { 3089, 2443 }, + { 3090, 2444 }, { 3091, 2445 }, { 3092, 2446 }, { 3093, 2447 }, { 3094, 2448 }, { 3095, 2449 }, { 3096, 2450 }, + { 3097, 2451 }, { 3098, 2452 }, { 3099, 2453 }, { 3100, 2454 }, { 3101, 2455 }, { 3102, 2456 }, { 3103, 2457 }, + { 3104, 2463 }, { 3105, 2464 }, { 3106, 2466 }, { 3107, 2467 }, { 3108, 2468 }, { 3109, 2469 }, { 3110, 2470 }, + { 3111, 2471 }, { 3112, 2472 }, { 3113, 2473 }, { 3114, 2474 }, { 3115, 2475 }, { 3171, 2476 }, { 3172, 2477 }, + { 3173, 2478 }, { 3174, 2479 }, { 3175, 2480 }, { 3176, 2481 }, { 3177, 2482 }, { 3178, 2483 }, { 3179, 2484 }, + { 3180, 2485 }, { 3181, 2486 }, { 3182, 2487 }, { 3183, 2488 }, { 3184, 2489 }, { 3185, 2490 }, { 3186, 2491 }, + { 3187, 2492 }, { 3188, 2493 }, { 3189, 2494 }, { 3190, 2495 }, { 3191, 2496 }, { 3192, 2497 }, { 3193, 2498 }, + { 3194, 2499 }, { 3195, 2500 }, { 3196, 2501 }, { 3197, 2502 }, { 3198, 2503 }, { 3199, 2504 }, { 3200, 2505 }, + { 3201, 2506 }, { 3202, 2507 }, { 3203, 2508 }, { 3204, 2509 }, { 3205, 2510 }, { 3206, 2511 }, { 3207, 2512 }, + { 3208, 2513 }, { 3209, 2514 }, { 3210, 2515 }, { 3211, 2516 }, { 3212, 2517 }, { 3213, 2518 }, { 3214, 2519 }, + { 3215, 2520 }, { 3216, 2521 }, { 3217, 2522 }, { 3218, 2523 }, { 3219, 2524 }, { 3220, 2525 }, { 3221, 2526 }, + { 3222, 2527 }, { 3223, 2528 }, { 3224, 2529 }, { 3271, 2530 }, { 3272, 2531 }, { 3273, 2532 }, { 3274, 2533 }, + { 3275, 2534 }, { 3276, 2535 }, { 3277, 2536 }, { 3278, 2537 }, { 3279, 2538 }, { 3280, 2539 }, { 3281, 2540 }, + { 3282, 2541 }, { 3283, 2542 }, { 3284, 2543 }, { 3285, 2544 }, { 3286, 2545 }, { 3287, 2546 }, { 3288, 2547 }, + { 3289, 2548 }, { 3290, 2549 }, { 3291, 2550 }, { 3292, 2551 }, { 3293, 2552 }, { 3294, 2553 }, { 3295, 2554 }, + { 3296, 2555 }, { 3297, 2556 }, { 3298, 2557 }, { 3299, 2558 }, { 3300, 2559 }, { 3301, 2560 }, { 3302, 2561 }, + { 3303, 2562 }, { 3304, 2563 }, { 3371, 2564 }, { 3372, 2565 }, { 3373, 2566 }, { 3374, 2567 }, { 3375, 2568 }, + { 3376, 2569 }, { 3377, 2570 }, { 3378, 2571 }, { 3379, 2572 }, { 3380, 2573 }, { 3381, 2574 }, { 3382, 2575 }, + { 3383, 2576 }, { 3384, 2577 }, { 3385, 2578 }, { 3471, 2579 }, { 3472, 2580 }, { 3473, 2581 }, { 3474, 2582 }, + { 3475, 2583 }, { 3476, 2584 }, { 3477, 2585 }, { 3478, 2586 }, { 3479, 2587 }, { 3480, 2588 }, { 3481, 2589 }, + { 3482, 2590 }, { 3483, 2591 }, { 3484, 2592 }, { 3485, 2593 }, { 3486, 2594 }, { 3487, 2595 }, { 3488, 2596 }, + { 3489, 2597 }, { 3490, 2598 }, { 3491, 2599 }, { 3492, 2600 }, { 3493, 2601 }, { 3494, 2602 }, { 3495, 2603 }, + { 3496, 2604 }, { 3497, 2605 }, { 3498, 2606 }, { 3499, 2607 }, { 3500, 2608 }, { 3501, 2609 }, { 3502, 2610 }, + { 3503, 2611 }, { 3504, 2612 }, { 3505, 2613 }, { 3506, 2614 }, { 3507, 2615 }, { 3508, 2616 }, { 3509, 2617 }, + { 3510, 2618 }, { 3571, 2619 }, { 3572, 2620 }, { 3573, 2621 }, { 3574, 2622 }, { 3575, 2623 }, { 3576, 2624 }, + { 3577, 2625 }, { 3578, 2626 }, { 3579, 2627 }, { 3580, 2628 }, { 3581, 2629 }, { 3582, 2630 }, { 3583, 2631 }, + { 3584, 2632 }, { 3585, 2633 }, { 3586, 2634 }, { 3587, 2635 }, { 3588, 2636 }, { 3589, 2637 }, { 3590, 2638 }, + { 3591, 2639 }, { 3592, 2640 }, { 3593, 2641 }, { 3594, 2642 }, { 3595, 2643 }, { 3596, 2644 }, { 3597, 2645 }, + { 3598, 2646 }, { 3599, 2647 }, { 3600, 2648 }, { 3601, 2649 }, { 3602, 2650 }, { 3603, 2651 }, { 3604, 2652 }, + { 3605, 2653 }, { 3606, 2654 }, { 3607, 2655 }, { 3608, 2656 }, { 3609, 2657 }, { 3610, 2658 }, { 3611, 2659 }, + { 3612, 2660 }, { 3613, 2661 }, { 3614, 2662 }, { 3615, 2663 }, { 3616, 2664 }, { 3617, 2665 }, { 3618, 2666 }, + { 3619, 2667 }, { 3620, 2668 }, { 3621, 2669 }, { 3622, 2670 }, { 3623, 2671 }, { 3624, 2672 }, { 3625, 2673 }, + { 3626, 2674 }, { 3627, 2675 }, { 3628, 2676 }, { 3629, 2677 }, { 3630, 2678 }, { 3631, 2679 }, { 3632, 2680 }, + { 3633, 2681 }, { 3634, 2682 }, { 3635, 2683 }, { 3636, 2684 }, { 3637, 2685 }, { 3638, 2686 }, { 3639, 2687 }, + { 3640, 2688 }, { 3641, 2689 }, { 3642, 2690 }, { 3643, 2691 }, { 3644, 2692 }, { 3645, 2693 }, { 3646, 2694 }, + { 3671, 2696 }, { 3672, 2697 }, { 3673, 2698 }, { 3674, 2699 }, { 3675, 2700 }, { 3676, 2701 }, { 3677, 2702 }, + { 3678, 2703 }, { 3679, 2704 }, { 3680, 2705 }, { 3681, 2706 }, { 3682, 2707 }, { 3683, 2708 }, { 3684, 2709 }, + { 3685, 2710 }, { 3686, 2711 }, { 3687, 2712 }, { 3688, 2713 }, { 3689, 2714 }, { 3690, 2715 }, { 3691, 2716 }, + { 3692, 2717 }, { 3693, 2718 }, { 3694, 2719 }, { 3695, 2720 }, { 3696, 2721 }, { 3697, 2722 }, { 3698, 2723 }, + { 3699, 2724 }, { 3700, 2725 }, { 3701, 2726 }, { 3702, 2727 }, { 3703, 2728 }, { 3704, 2729 }, { 3705, 2730 }, + { 3706, 2731 }, { 3707, 2732 }, { 3708, 2733 }, { 3709, 2734 }, { 3710, 2735 }, { 3711, 2736 }, { 3712, 2737 }, + { 3713, 2738 }, { 3714, 2739 }, { 3715, 2740 }, { 3716, 2741 }, { 3717, 2742 }, { 3718, 2743 }, { 3719, 2744 }, + { 3720, 2745 }, { 3721, 2746 }, { 3722, 2747 }, { 3723, 2748 }, { 3724, 2749 }, { 3725, 2750 }, { 3726, 2751 }, + { 3727, 2752 }, { 3728, 2753 }, { 3729, 2754 }, { 3730, 2755 }, { 3927, 2756 }, { 3928, 2757 }, { 3929, 2758 }, + { 3930, 2759 }, { 3931, 2760 }, { 3932, 2761 }, { 3933, 2762 }, { 3934, 2763 }, { 3940, 2769 }, { 3941, 2770 }, + { 3942, 2771 }, { 3943, 2772 }, { 3944, 2773 }, { 3945, 2774 }, { 3946, 2775 }, { 3947, 2776 }, { 3948, 2777 }, + { 3949, 2778 }, { 3950, 2779 }, { 3951, 2780 }, { 3952, 2781 }, { 3953, 2782 }, { 3954, 2783 }, { 3955, 2784 }, + { 3956, 2785 }, { 3957, 2786 }, { 3958, 2787 }, { 3959, 2788 }, { 3960, 2789 }, { 3961, 2790 }, { 3962, 2791 }, + { 3963, 2792 }, { 3964, 2793 }, { 3965, 2794 }, { 3966, 2795 }, { 3967, 2796 }, { 3968, 2797 }, { 3969, 2798 }, + { 3970, 2799 }, { 3971, 2800 }, { 3972, 2801 }, { 3973, 2802 }, { 3974, 2803 }, { 3975, 2804 }, { 3976, 2805 }, + { 3977, 2806 }, { 3978, 2807 }, { 3979, 2808 }, { 3980, 2809 }, { 3981, 2810 }, { 3982, 2811 }, { 3983, 2812 }, + { 3984, 2813 }, { 3985, 2814 }, { 3986, 2815 }, { 3987, 2816 }, { 3988, 2817 }, { 3989, 2818 }, { 3990, 2819 }, + { 3991, 2820 }, { 3992, 2821 }, { 3993, 2822 }, { 3994, 2823 }, { 3995, 2824 }, { 3996, 2825 }, { 3997, 2826 }, + { 3998, 2827 }, { 3999, 2828 }, { 4000, 2829 }, { 4001, 2830 }, { 4002, 2831 }, { 4003, 2832 }, { 4004, 2833 }, + { 4005, 2834 }, { 4006, 2835 }, { 4007, 2836 }, { 4008, 2837 }, { 4009, 2838 }, { 4010, 2839 }, { 4011, 2840 }, + { 4012, 2841 }, { 4013, 2842 }, { 4014, 2843 }, { 4015, 2844 }, { 4016, 2845 }, { 4017, 2846 }, { 4018, 2847 }, + { 4019, 2848 }, { 4020, 2849 }, { 4021, 2850 }, { 4022, 2851 }, { 4023, 2852 }, { 4024, 2853 }, { 4025, 2854 }, + { 4026, 2855 }, { 4027, 2856 }, { 4028, 2857 }, { 4029, 2858 }, { 4030, 2859 }, { 4031, 2860 }, { 4032, 2861 }, + { 4127, 2863 }, { 4128, 2864 }, { 4129, 2865 }, { 4130, 2866 }, { 4131, 2867 }, { 4132, 2868 }, { 4133, 2869 }, + { 4134, 2870 }, { 4135, 2871 }, { 4136, 2872 }, { 4137, 2873 }, { 4138, 2874 }, { 4139, 2875 }, { 4140, 2876 }, + { 4145, 2881 }, { 4146, 2882 }, { 4147, 2883 }, { 4148, 2884 }, { 4149, 2885 }, { 4150, 2886 }, { 4151, 2887 }, + { 4152, 2888 }, { 4153, 2889 }, { 4154, 2890 }, { 4155, 2891 }, { 4156, 2892 }, { 4157, 2893 }, { 4158, 2894 }, + { 4159, 2895 }, { 4160, 2896 }, { 4227, 2897 }, { 4228, 2898 }, { 4229, 2899 }, { 4230, 2900 }, { 4231, 2901 }, + { 4232, 2902 }, { 4233, 2903 }, { 4234, 2904 }, { 4235, 2905 }, { 4236, 2906 }, { 4237, 2907 }, { 4238, 2908 }, + { 4239, 2909 }, { 4240, 2910 }, { 4241, 2911 }, { 4242, 2912 }, { 4243, 2913 }, { 4244, 2914 }, { 4245, 2915 }, + { 4246, 2916 }, { 4247, 2917 }, { 4248, 2918 }, { 4249, 2919 }, { 4250, 2920 }, { 4251, 2921 }, { 4252, 2922 }, + { 4253, 2923 }, { 4254, 2924 }, { 4255, 2925 }, { 4256, 2926 }, { 4257, 2927 }, { 4258, 2928 }, { 4327, 2929 }, + { 4328, 2930 }, { 4329, 2931 }, { 4330, 2932 }, { 4331, 2933 }, { 4332, 2934 }, { 4333, 2935 }, { 4334, 2936 }, + { 4335, 2937 }, { 4336, 2938 }, { 4337, 2939 }, { 4338, 2940 }, { 4339, 2941 }, { 4340, 2942 }, { 4341, 2943 }, + { 4342, 2944 }, { 4343, 2945 }, { 4344, 2946 }, { 4345, 2947 }, { 4346, 2948 }, { 4347, 2949 }, { 4348, 2950 }, + { 4349, 2951 }, { 4350, 2952 }, { 4351, 2953 }, { 4352, 2954 }, { 4353, 2955 }, { 4354, 2956 }, { 4355, 2957 }, + { 4356, 2958 }, { 4357, 2959 }, { 4358, 2960 }, { 4359, 2961 }, { 4360, 2962 }, { 4361, 2963 }, { 4362, 2964 }, + { 4363, 2965 }, { 4364, 2966 }, { 4365, 2967 }, { 4366, 2968 }, { 4367, 2969 }, { 4368, 2970 }, { 4369, 2971 }, + { 4370, 2972 }, { 4371, 2973 }, { 4372, 2974 }, { 4373, 2975 }, { 4374, 2976 }, { 4375, 2977 }, { 4376, 2978 }, + { 4377, 2979 }, { 4378, 2980 }, { 4379, 2981 }, { 4380, 2982 }, { 4381, 2983 }, { 4382, 2984 }, { 4383, 2985 }, + { 4384, 2986 }, { 4385, 2987 }, { 4386, 2988 }, { 4387, 2989 }, { 4388, 2990 }, { 4389, 2991 }, { 4390, 2992 }, + { 4391, 2993 }, { 4392, 2994 }, { 4393, 2995 }, { 4394, 2996 }, { 4395, 2997 }, { 4396, 2998 }, { 4397, 2999 }, + { 4398, 3000 }, { 4399, 3001 }, { 4400, 3002 }, { 4401, 3003 }, { 4402, 3004 }, { 4403, 3005 }, { 4404, 3006 }, + { 4405, 3007 }, { 4406, 3008 }, { 4407, 3009 }, { 4408, 3010 }, { 4409, 3011 }, { 4410, 3012 }, { 4411, 3013 }, + { 4412, 3014 }, { 4413, 3015 }, { 4414, 3016 }, { 4415, 3017 }, { 4416, 3018 }, { 4417, 3019 }, { 4418, 3020 }, + { 4419, 3021 }, { 4420, 3022 }, { 4421, 3023 }, { 4422, 3024 }, { 4423, 3025 }, { 4424, 3026 }, { 4425, 3027 }, + { 4426, 3028 }, { 4427, 3029 }, { 4428, 3030 }, { 4429, 3031 }, { 4430, 3032 }, { 4431, 3033 }, { 4432, 3034 }, + { 4433, 3035 }, { 4434, 3036 }, { 4435, 3037 }, { 4436, 3038 }, { 4437, 3039 }, { 4438, 3040 }, { 4439, 3041 }, + { 4440, 3042 }, { 4441, 3043 }, { 4442, 3044 }, { 4443, 3045 }, { 4444, 3046 }, { 4445, 3047 }, { 4446, 3048 }, + { 4447, 3049 }, { 4448, 3050 }, { 4449, 3051 }, { 4450, 3052 }, { 4527, 3053 }, { 4528, 3054 }, { 4529, 3055 }, + { 4530, 3056 }, { 4531, 3057 }, { 4532, 3058 }, { 4533, 3059 }, { 4534, 3060 }, { 4535, 3061 }, { 4536, 3062 }, + { 4537, 3063 }, { 4538, 3064 }, { 4539, 3065 }, { 4540, 3066 }, { 4541, 3067 }, { 4542, 3068 }, { 4543, 3069 }, + { 4544, 3070 }, { 4545, 3071 }, { 4546, 3072 }, { 4547, 3074 }, { 4548, 3075 }, { 4549, 3076 }, { 4550, 3077 }, + { 4551, 3078 }, { 4552, 3079 }, { 4553, 3080 }, { 4554, 3073 }, { 4627, 3081 }, { 4628, 3082 }, { 4629, 3083 }, + { 4630, 3084 }, { 4631, 3085 }, { 4632, 3086 }, { 4633, 3087 }, { 4634, 3088 }, { 4635, 3089 }, { 4636, 3090 }, + { 4637, 3091 }, { 4638, 3092 }, { 4639, 3093 }, { 4640, 3094 }, { 4641, 3095 }, { 4642, 3096 }, { 4643, 3097 }, + { 4644, 3098 }, { 4645, 3099 }, { 4646, 3100 }, { 4647, 3101 }, { 4648, 3102 }, { 4649, 3103 }, { 4650, 3104 }, + { 4651, 3105 }, { 4652, 3106 }, { 4653, 3107 }, { 4654, 3108 }, { 4655, 3109 }, { 4656, 3110 }, { 4657, 3111 }, + { 4658, 3112 }, { 4659, 3113 }, { 4660, 3114 }, { 4661, 3115 }, { 4662, 3116 }, { 4663, 3117 }, { 4664, 3118 }, + { 4665, 3119 }, { 4666, 3120 }, { 4667, 3121 }, { 4668, 3122 }, { 4669, 3123 }, { 4670, 3124 }, { 4671, 3125 }, + { 4672, 3126 }, { 4673, 3127 }, { 4674, 3128 }, { 4675, 3129 }, { 4676, 3130 }, { 4677, 3131 }, { 4678, 3132 }, + { 4679, 3133 }, { 4680, 3134 }, { 4681, 3135 }, { 4682, 3136 }, { 4683, 3137 }, { 4684, 3138 }, { 4685, 3139 }, + { 4686, 3140 }, { 4687, 3141 }, { 4688, 3142 }, { 4689, 3143 }, { 4690, 3144 }, { 4691, 3145 }, { 4692, 3146 }, + { 4693, 3147 }, { 4694, 3148 }, { 4695, 3149 }, { 4696, 3150 }, { 4697, 3151 }, { 4698, 3152 }, { 4699, 3153 }, + { 4700, 3154 }, { 4701, 3155 }, { 4702, 3156 }, { 4703, 3157 }, { 4704, 3158 }, { 4705, 3159 }, { 4706, 3160 }, + { 4707, 3161 }, { 4708, 3162 }, { 4709, 3163 }, { 4710, 3164 }, { 4711, 3165 }, { 4712, 3166 }, { 4713, 3167 }, + { 4714, 3168 }, { 4715, 3169 }, { 4716, 3170 }, { 4717, 3171 }, { 4718, 3172 }, { 4719, 3173 }, { 4720, 3174 }, + { 4721, 3175 }, { 4722, 3176 }, { 4723, 3177 }, { 4724, 3178 }, { 4725, 3179 }, { 4726, 3180 }, { 4827, 3181 }, + { 4828, 3182 }, { 4829, 3183 }, { 4830, 3184 }, { 4831, 3185 }, { 4832, 3186 }, { 4833, 3187 }, { 4834, 3188 }, + { 4835, 3189 }, { 4836, 3190 }, { 4837, 3191 }, { 4838, 3192 }, { 4839, 3193 }, { 4840, 3194 }, { 4841, 3195 }, + { 4842, 3196 }, { 4843, 3197 }, { 4844, 3198 }, { 4845, 3199 }, { 5027, 3200 }, { 5028, 3201 }, { 5029, 3202 }, + { 5030, 3203 }, { 5031, 3204 }, { 5032, 3205 }, { 5033, 3206 }, { 5034, 3207 }, { 5035, 3208 }, { 5036, 3209 }, + { 5037, 3210 }, { 5038, 3211 }, { 5039, 3212 }, { 5040, 3213 }, { 5041, 3214 }, { 5042, 3215 }, { 5043, 3216 }, + { 5044, 3217 }, { 5045, 3218 }, { 5046, 3219 }, { 5047, 3220 }, { 5048, 3221 }, { 5049, 3222 }, { 5050, 3223 }, + { 5051, 3224 }, { 5052, 3225 }, { 5053, 3226 }, { 5054, 3227 }, { 5055, 3228 }, { 5056, 3229 }, { 5057, 3230 }, + { 5058, 3231 }, { 5059, 3232 }, { 5060, 3233 }, { 5061, 3234 }, { 5062, 3235 }, { 5063, 3236 }, { 5064, 3237 }, + { 5065, 3238 }, { 5066, 3239 }, { 5067, 3240 }, { 5068, 3241 }, { 5069, 3242 }, { 5070, 3243 }, { 5071, 3244 }, + { 5072, 3245 }, { 5073, 3246 }, { 5074, 3247 }, { 5075, 3248 }, { 5076, 3249 }, { 5077, 3250 }, { 5127, 3251 }, + { 5128, 3252 }, { 5129, 3253 }, { 5130, 3254 }, { 5131, 3255 }, { 5132, 3256 }, { 5133, 3257 }, { 5134, 3258 }, + { 5135, 3259 }, { 5136, 3260 }, { 5137, 3261 }, { 5138, 3262 }, { 5139, 3263 }, { 5140, 3264 }, { 5141, 3265 }, + { 5142, 3266 }, { 5143, 3267 }, { 5144, 3268 }, { 5145, 3269 }, { 5146, 3270 }, { 5147, 3271 }, { 5148, 3272 }, + { 5149, 3273 }, { 5150, 3274 }, { 5151, 3275 }, { 5152, 3276 }, { 5153, 3277 }, { 5154, 3278 }, { 5155, 3279 }, + { 5156, 3280 }, { 5227, 3281 }, { 5228, 3282 }, { 5229, 3283 }, { 5230, 3284 }, { 5231, 3285 }, { 5232, 3286 }, + { 5233, 3287 }, { 5234, 3288 }, { 5235, 3289 }, { 5236, 3290 }, { 5237, 3291 }, { 5238, 3292 }, { 5240, 3294 }, + { 5241, 3295 }, { 5242, 3296 }, { 5243, 3297 }, { 5244, 3298 }, { 5245, 3299 }, { 5246, 3300 }, { 5247, 3301 }, + { 5248, 3302 }, { 5249, 3303 }, { 5250, 3304 }, { 5251, 3305 }, { 5252, 3306 }, { 5253, 3307 }, { 5254, 3308 }, + { 5255, 3309 }, { 5256, 3310 }, { 5257, 3311 }, { 5258, 3312 }, { 5259, 3313 }, { 5260, 3314 }, { 5261, 3315 }, + { 5262, 3316 }, { 5263, 3317 }, { 5264, 3318 }, { 5265, 3319 }, { 5266, 3320 }, { 5267, 3321 }, { 5268, 3322 }, + { 5269, 3323 }, { 5270, 3324 }, { 5271, 3325 }, { 5272, 3326 }, { 5273, 3327 }, { 5274, 3328 }, { 5275, 3329 }, + { 5276, 3330 }, { 5277, 3331 }, { 5278, 3332 }, { 5279, 3333 }, { 5280, 3334 }, { 5281, 3335 }, { 5282, 3336 }, + { 5283, 3337 }, { 5284, 3338 }, { 5285, 3339 }, { 5286, 3340 }, { 5288, 3342 }, { 5289, 3343 }, { 5290, 3344 }, + { 5291, 3345 }, { 5292, 3346 }, { 5293, 3347 }, { 5294, 3348 }, { 5296, 3350 }, { 5297, 3351 }, { 5298, 3352 }, + { 5299, 3353 }, { 5300, 3354 }, { 5301, 3355 }, { 5302, 3356 }, { 5303, 3357 }, { 5304, 3358 }, { 5305, 3359 }, + { 5306, 3360 }, { 5307, 3361 }, { 5308, 3362 }, { 5309, 3363 }, { 5310, 3364 }, { 5311, 3365 }, { 5312, 3366 }, + { 5313, 3367 }, { 5314, 3368 }, { 5315, 3369 }, { 5316, 3370 }, { 5317, 3371 }, { 5318, 3372 }, { 5319, 3373 }, + { 5320, 3374 }, { 5321, 3375 }, { 5322, 3376 }, { 5323, 3377 }, { 5324, 3378 }, { 5325, 3379 }, { 5326, 3380 }, + { 5327, 3381 }, { 5328, 3382 }, { 5329, 3383 }, { 5330, 3384 }, { 5331, 3385 }, { 5332, 3386 }, { 5333, 3387 }, + { 5336, 3390 }, { 5337, 3391 }, { 5338, 3392 }, { 5339, 3393 }, { 5340, 3394 }, { 5341, 3395 }, { 5342, 3396 }, + { 5343, 3397 }, { 5344, 3398 }, { 5345, 3399 }, { 5346, 3400 }, { 5347, 3401 }, { 5348, 3402 }, { 5349, 3403 }, + { 5350, 3404 }, { 5351, 3405 }, { 5352, 3406 }, { 5357, 3411 }, { 5358, 3412 }, { 5359, 3413 }, { 5360, 3414 }, + { 5361, 3415 }, { 5362, 3416 }, { 5363, 3417 }, { 5364, 3418 }, { 5365, 3419 }, { 5366, 3420 }, { 5367, 3421 }, + { 5368, 3422 }, { 5369, 3423 }, { 5370, 3424 }, { 5371, 3425 }, { 5372, 3426 }, { 5373, 3427 }, { 5374, 3428 }, + { 5375, 3429 }, { 5376, 3430 }, { 5377, 3431 }, { 5378, 3432 }, { 5379, 3433 }, { 5380, 3434 }, { 5381, 3435 }, + { 5382, 3436 }, { 5383, 3437 }, { 5384, 3438 }, { 5385, 3439 }, { 5386, 3440 }, { 5387, 3441 }, { 5388, 3442 }, + { 5389, 3443 }, { 5390, 3444 }, { 5391, 3445 }, { 5392, 3446 }, { 5393, 3447 }, { 5394, 3448 }, { 5395, 3449 }, + { 5396, 3450 }, { 5397, 3451 }, { 5398, 3452 }, { 5399, 3453 }, { 5400, 3454 }, { 5401, 3455 }, { 5402, 3456 }, + { 5403, 3457 }, { 5404, 3458 }, { 5405, 3459 }, { 5406, 3460 }, { 5407, 3461 }, { 5408, 3462 }, { 5409, 3463 }, + { 5410, 3464 }, { 5411, 3465 }, { 5412, 3466 }, { 5413, 3467 }, { 5414, 3468 }, { 5415, 3469 }, { 5416, 3470 }, + { 5417, 3471 }, { 5418, 3472 }, { 5419, 3473 }, { 5420, 3474 }, { 5421, 3475 }, { 5422, 3476 }, { 5423, 3477 }, + { 5424, 3478 }, { 5425, 3479 }, { 5426, 3480 }, { 5427, 3481 }, { 5428, 3482 }, { 5429, 3483 }, { 5430, 3484 }, + { 5431, 3485 }, { 5432, 3486 }, { 5433, 3487 }, { 5434, 3488 }, { 5435, 3489 }, { 5436, 3490 }, { 5437, 3491 }, + { 5438, 3492 }, { 5439, 3493 }, { 5440, 3494 }, { 5441, 3495 }, { 5442, 3496 }, { 5443, 3497 }, { 5444, 3498 }, + { 5445, 3499 }, { 5446, 3500 }, { 5447, 3501 }, { 5448, 3502 }, { 5449, 3503 }, { 5450, 3504 }, { 5451, 3505 }, + { 5452, 3506 }, { 5453, 3507 }, { 5454, 3508 }, { 5455, 3509 }, { 5456, 3510 }, { 5457, 3511 }, { 5458, 3512 }, + { 5459, 3513 }, { 5460, 3514 }, { 5461, 3515 }, { 5462, 3516 }, { 5463, 3517 }, { 5464, 3518 }, { 5465, 3519 }, + { 5466, 3520 }, { 5467, 3521 }, { 5468, 3522 }, { 5469, 3523 }, { 5470, 3524 }, { 5471, 3525 }, { 5472, 3526 }, + { 5473, 3527 }, { 5474, 3528 }, { 5475, 3529 }, { 5476, 3530 }, { 5477, 3531 }, { 5478, 3532 }, { 5479, 3533 }, + { 5480, 3534 }, { 5481, 3535 }, { 5482, 3536 }, { 5483, 3537 }, { 5484, 3538 }, { 5485, 3539 }, { 5486, 3540 }, + { 5487, 3541 }, { 5488, 3542 }, { 5489, 3543 }, { 5490, 3544 }, { 5491, 3545 }, { 5492, 3546 }, { 5493, 3547 }, + { 5494, 3548 }, { 5495, 3549 }, { 5496, 3550 }, { 5497, 3551 }, { 5498, 3552 }, { 5499, 3553 }, { 5500, 3554 }, + { 5501, 3555 }, { 5502, 3556 }, { 5503, 3557 }, { 5504, 3558 }, { 5505, 3559 }, { 5506, 3560 }, { 5507, 3561 }, + { 5508, 3562 }, { 5509, 3563 }, { 5510, 3564 }, { 5511, 3565 }, { 5512, 3566 }, { 5513, 3567 }, { 5514, 3568 }, + { 5515, 3569 }, { 5516, 3570 }, { 5517, 3571 }, { 5518, 3572 }, { 5519, 3573 }, { 5520, 3574 }, { 5521, 3575 }, + { 5522, 3576 }, { 5523, 3577 }, { 5524, 3578 }, { 5525, 3579 }, { 5526, 3580 }, { 5527, 3581 }, { 5528, 3582 }, + { 5529, 3583 }, { 5530, 3584 }, { 5531, 3585 }, { 5532, 3586 }, { 5533, 3587 }, { 5534, 3588 }, { 5535, 3589 }, + { 5536, 3590 }, { 5537, 3591 }, { 5538, 3592 }, { 5539, 3593 }, { 5540, 3594 }, { 5541, 3595 }, { 5542, 3596 }, + { 5543, 3597 }, { 5544, 3598 }, { 5545, 3599 }, { 5546, 3600 }, { 5547, 3601 }, { 5548, 3602 }, { 5549, 3603 }, + { 5550, 3604 }, { 5551, 3605 }, { 5552, 3606 }, { 5553, 3607 }, { 5554, 3608 }, { 5555, 3609 }, { 5556, 3610 }, + { 5557, 3611 }, { 5558, 3612 }, { 5559, 3613 }, { 5560, 3614 }, { 5561, 3615 }, { 5562, 3616 }, { 5563, 3617 }, + { 5564, 3618 }, { 5565, 3619 }, { 5566, 3620 }, { 5567, 3621 }, { 5568, 3622 }, { 5569, 3623 }, { 5570, 3624 }, }; #endif // ASSET_VERSION_REMAP_H diff --git a/src/port/GameVersion/BaseGameVersion.cpp b/src/port/GameVersion/BaseGameVersion.cpp index a38b55c0c..43fe141cf 100644 --- a/src/port/GameVersion/BaseGameVersion.cpp +++ b/src/port/GameVersion/BaseGameVersion.cpp @@ -12,22 +12,6 @@ namespace Lighthouse { namespace { -bool IsKnownVersion(uint32_t crc) { - switch (crc) { - case BK_VER_US_10: - case BK_VER_US_11: - case BK_VER_PAL: - case BK_VER_JP: - return true; - default: - return false; - } -} - -uint32_t ByteSwap32(uint32_t v) { - return (v >> 24) | ((v >> 8) & 0x0000FF00u) | ((v << 8) & 0x00FF0000u) | (v << 24); -} - bool ReadStampedCrc(const std::string& archivePath, uint32_t& outCrc) { int err = 0; zip_t* z = zip_open(archivePath.c_str(), ZIP_RDONLY, &err); @@ -39,9 +23,12 @@ bool ReadStampedCrc(const std::string& archivePath, uint32_t& outCrc) { if (zip_int64_t idx = zip_name_locate(z, "version", 0); idx >= 0) { if (zip_file_t* f = zip_fopen_index(z, idx, 0)) { uint8_t buf[5] = {}; - if (zip_fread(f, buf, sizeof(buf)) == sizeof(buf)) { - outCrc = (static_cast(buf[1]) << 24) | (static_cast(buf[2]) << 16) | - (static_cast(buf[3]) << 8) | static_cast(buf[4]); + if (zip_fread(f, buf, sizeof(buf)) == static_cast(sizeof(buf))) { + const bool big = buf[0] != 0; + outCrc = big ? (static_cast(buf[1]) << 24 | static_cast(buf[2]) << 16 | + static_cast(buf[3]) << 8 | static_cast(buf[4])) + : (static_cast(buf[4]) << 24 | static_cast(buf[3]) << 16 | + static_cast(buf[2]) << 8 | static_cast(buf[1])); ok = true; } zip_fclose(f); @@ -52,16 +39,23 @@ bool ReadStampedCrc(const std::string& archivePath, uint32_t& outCrc) { return ok; } -} // namespace - -std::string BaseArchivePath() { - std::string basePath = Ship::Context::LocateFileAcrossAppDirs("bk.o2r", "bk"); - if (basePath.empty() || !std::filesystem::exists(basePath)) { - return std::string(); // not extracted yet +BKVersion ClassifyCrc(uint32_t crc) { + switch (crc) { + case BK_VER_US_11: + return BK_VER_US_11; + case BK_VER_PAL: + return BK_VER_PAL; + case BK_VER_JP: + return BK_VER_JP; + case BK_VER_US_10: + default: + // Vanilla v1.0, a v1.0-based romhack, or an unknown dump. + return BK_VER_US_10; } - return basePath; } +} // namespace + BKVersion GetBaseVersion() { static BKVersion sVersion = BK_VER_US_10; static bool sResolved = false; @@ -69,33 +63,19 @@ BKVersion GetBaseVersion() { return sVersion; } - const std::string basePath = BaseArchivePath(); - if (basePath.empty()) { + std::string basePath = Ship::Context::LocateFileAcrossAppDirs("bk.o2r", "bk"); + if (basePath.empty() || !std::filesystem::exists(basePath)) { return sVersion; // not extracted yet — retry on the next call } uint32_t crc = 0; - BKVersion version = BK_VER_US_10; - if (ReadStampedCrc(basePath, crc) && ClassifyArchiveVersion(crc, version)) { - sVersion = version; + if (ReadStampedCrc(basePath, crc)) { + sVersion = ClassifyCrc(crc); sResolved = true; SPDLOG_INFO("[BaseGameVersion] base bk.o2r CRC 0x{:08X} -> BKVersion 0x{:08X}", crc, static_cast(sVersion)); } - return sVersion; // unstamped or unrecognised: stay on the v1.0 default and retry -} - -bool ClassifyArchiveVersion(uint32_t rawVersion, BKVersion& out) { - if (IsKnownVersion(rawVersion)) { - out = static_cast(rawVersion); - return true; - } - const uint32_t swapped = ByteSwap32(rawVersion); - if (IsKnownVersion(swapped)) { - out = static_cast(swapped); - return true; - } - return false; + return sVersion; } bool BaseGameSupportsRomhacks() { diff --git a/src/port/GameVersion/BaseGameVersion.h b/src/port/GameVersion/BaseGameVersion.h index a6c9ae2f0..4d463b806 100644 --- a/src/port/GameVersion/BaseGameVersion.h +++ b/src/port/GameVersion/BaseGameVersion.h @@ -9,12 +9,6 @@ namespace Lighthouse { // The ROM CRC that Torch inserts into the o2r version file BKVersion GetBaseVersion(); -// Classify a version stamp taken from an archive -bool ClassifyArchiveVersion(uint32_t rawVersion, BKVersion& out); - -// Filesystem path of the base bk.o2r, or empty if it hasn't been extracted yet -std::string BaseArchivePath(); - // Romhacks are generally only supported by US 1.0 bool BaseGameSupportsRomhacks(); diff --git a/src/port/Interpolation/AdaptiveFps.cpp b/src/port/Interpolation/AdaptiveFps.cpp new file mode 100644 index 000000000..c2ad62710 --- /dev/null +++ b/src/port/Interpolation/AdaptiveFps.cpp @@ -0,0 +1,185 @@ +#include "AdaptiveFps.h" + +#include +#include + +namespace { + +using Clock = std::chrono::steady_clock; + +// Tuning knobs + +// How much of each update's time we'll spend drawing once things are steady. +// Raise toward 1.0 if FPS dips in scenes that look fine; lower if it stutters. +constexpr double kSafetySteady = 0.95; + +// Same, but used the moment a scene gets busier (more cautious). Lower if busy +// scenes still hitch; raise if FPS drops more than needed when they start. +constexpr double kSafetyRising = 0.75; + +// How much busier a scene must get to count as "getting busy". Lower reacts +// sooner but trips on normal noise; raise to ignore small bumps. +constexpr double kRisingThreshold = 1.20; + +// How long to stay cautious after a scene gets busy. Raise if FPS wobbles in +// steady scenes; lower if it feels slow to speed back up. +constexpr int kRisingHoldWindows = 3; + +// How often measurements are averaged. Shorter reacts quicker but is jumpier; +// longer is steadier but slower to react. +constexpr auto kSampleWindow = std::chrono::milliseconds(200); + +// How much each new measurement counts vs. past ones when averaging. +// 1.0 = only the latest; 0.0 = never changes. +constexpr double kEmaAlpha = 0.5; + +// How much busier one frame must be than usual to count as a spike. Lower +// reacts harder to one-off heavy frames; raise to ignore them. +constexpr double kSpikeFactor = 1.25; + +// How strongly a spike pulls the estimate up. 1.0 = snap to it instantly; +// 0.0 = ignore spikes. 0.5 lets a sustained busy scene ramp up over a few frames. +constexpr double kSpikeBlend = 0.5; + +// How quickly the busy estimate eases back down each averaging period. 0 = +// never; 1 = drop to the latest right away. Higher recovers FPS faster. +constexpr double kPeakDecay = 0.40; + +// How fast the reserved game-update time follows the latest tick: jump up +// quickly when a scene gets busy, ease back down slowly when it calms. +constexpr double kLogicRiseAlpha = 0.5; +constexpr double kLogicFallAlpha = 0.1; + +// Default game update rate (times per second) if none is given. +constexpr uint32_t kDefaultTickHz = 30; + +struct State { + uint32_t tickHz = kDefaultTickHz; + double tickBudgetUs = 1'000'000.0 / kDefaultTickHz; + double emaPerSubFrameUs = 0.0; // Average time to draw one frame. + double peakPerSubFrameUs = 0.0; // Busiest recent frame; the cap is based on this. + double envLogicUs = 0.0; // Reserved game-update time per tick. + long long winRunNs = 0; // Totals for the current measurement period. + int winSubFrames = 0; + double winMaxUs = 0.0; + Clock::time_point winStart = Clock::now(); + double safety = kSafetySteady; + int risingHoldRemaining = 0; +}; + +State& state() { + static State s; + return s; +} + +} // namespace + +extern "C" { + +void AdaptiveFps_Configure(uint32_t tickHz) { + if (tickHz == 0) { + tickHz = kDefaultTickHz; + } + auto& s = state(); + s.tickHz = tickHz; + s.tickBudgetUs = 1'000'000.0 / tickHz; + s.emaPerSubFrameUs = 0.0; + s.peakPerSubFrameUs = 0.0; + s.envLogicUs = 0.0; + s.winRunNs = 0; + s.winSubFrames = 0; + s.winMaxUs = 0.0; + s.winStart = Clock::now(); + s.safety = kSafetySteady; + s.risingHoldRemaining = 0; +} + +uint32_t AdaptiveFps_Cap(uint32_t userTarget) { + auto& s = state(); + // Base the cap on the busiest recent frame, not the average: every frame we + // promise gets drawn, so the time has to fit the worst one. + double costUs = std::max(s.peakPerSubFrameUs, s.emaPerSubFrameUs); + if (costUs <= 0.0) { + return userTarget; + } + // Set aside the time the game spent updating, then share what's left among + // interpolated frames so a busy scene can't overshoot the tick's budget. + double renderBudgetUs = s.tickBudgetUs - s.envLogicUs; + if (renderBudgetUs <= 0.0) { + return s.tickHz; + } + double maxSubPerTick = (renderBudgetUs * s.safety) / costUs; + if (maxSubPerTick < 1.0) { + return s.tickHz; + } + uint32_t maxFps = (uint32_t)(maxSubPerTick * s.tickHz); + if (maxFps < s.tickHz) { + maxFps = s.tickHz; + } + return std::min(userTarget, maxFps); +} + +void AdaptiveFps_SampleTick(long long logicNs) { + auto& s = state(); + double us = (double)logicNs / 1000.0; + if (us < 0.0) { + return; + } + if (s.envLogicUs == 0.0) { + s.envLogicUs = us; + } else { + // Rise fast when the scene gets busier, fall slow when it calms. + double alpha = us > s.envLogicUs ? kLogicRiseAlpha : kLogicFallAlpha; + s.envLogicUs = alpha * us + (1.0 - alpha) * s.envLogicUs; + } +} + +void AdaptiveFps_Sample(long long runNs) { + auto& s = state(); + double sampleUs = (double)runNs / 1000.0; + + s.winRunNs += runNs; + s.winSubFrames++; + if (sampleUs > s.winMaxUs) { + s.winMaxUs = sampleUs; + } + + // If one frame is suddenly much busier than usual, bump the estimate up + // right away and stay cautious, so the next cap already reflects it. + if (s.peakPerSubFrameUs == 0.0) { + s.peakPerSubFrameUs = sampleUs; + s.safety = kSafetyRising; + s.risingHoldRemaining = kRisingHoldWindows; + } else if (sampleUs > s.peakPerSubFrameUs * kSpikeFactor) { + s.peakPerSubFrameUs = kSpikeBlend * sampleUs + (1.0 - kSpikeBlend) * s.peakPerSubFrameUs; + s.safety = kSafetyRising; + s.risingHoldRemaining = kRisingHoldWindows; + } + + auto now = Clock::now(); + if (now - s.winStart < kSampleWindow) { + return; + } + + // End of a measurement period: refresh the average, decide whether the + // scene is still getting busier, and ease the busy estimate back down. + double mean = (double)s.winRunNs / s.winSubFrames / 1000.0; + s.emaPerSubFrameUs = s.emaPerSubFrameUs == 0.0 ? mean : kEmaAlpha * mean + (1.0 - kEmaAlpha) * s.emaPerSubFrameUs; + + bool rising = s.peakPerSubFrameUs > 0.0 && s.winMaxUs > s.peakPerSubFrameUs * kRisingThreshold; + if (rising) { + s.risingHoldRemaining = kRisingHoldWindows; + } else if (s.risingHoldRemaining > 0) { + s.risingHoldRemaining--; + } + s.safety = s.risingHoldRemaining > 0 ? kSafetyRising : kSafetySteady; + + s.peakPerSubFrameUs = std::max(s.winMaxUs, s.peakPerSubFrameUs * (1.0 - kPeakDecay) + s.winMaxUs * kPeakDecay); + + s.winRunNs = 0; + s.winSubFrames = 0; + s.winMaxUs = 0.0; + s.winStart = now; +} + +} // extern "C" diff --git a/src/port/Interpolation/AdaptiveFps.h b/src/port/Interpolation/AdaptiveFps.h new file mode 100644 index 000000000..c2422b545 --- /dev/null +++ b/src/port/Interpolation/AdaptiveFps.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +// Adaptive interpolation FPS cap. +// +// Drawing each extra interpolated frame is expensive, so asking for too many +// in a busy scene can starve the game and make it stutter. This times how long +// drawing takes and lowers the FPS just enough to keep the game smooth, then +// raises it again once the scene clears. +// +// Call order (from the gfx pipeline): +// AdaptiveFps_Configure(tickHz) // once at startup +// AdaptiveFps_SampleTick(logicNs) // each tick, before Cap +// AdaptiveFps_Cap(userTarget) // pick the allowed FPS +// AdaptiveFps_Sample(runNs) // after each frame is drawn +// +// Defaults assume the game runs at 30 fps native; pass a different rate to +// Configure() if not. On a 60 Hz display the result is either 60 or 30 with +// nothing in between (no whole number of frames fits), so it switches directly. + +#ifdef __cplusplus +extern "C" { +#endif + +// Set how many times per second the game updates. Also clears past +// measurements so a freshly loaded game starts fresh. Safe to call repeatedly. +void AdaptiveFps_Configure(uint32_t tickHz); + +// Returns the highest FPS the current scene can sustain, never above what the +// user asked for nor below the game's update rate. Returns the user's value +// until it has measured at least once. +uint32_t AdaptiveFps_Cap(uint32_t userTarget); + +// Report how long it took to draw one frame (nanoseconds), so the module can +// gauge how heavy the scene is. +void AdaptiveFps_Sample(long long runNs); + +// Report how long the game spent updating this tick before drawing started. +// Adaptive FPS reserves that time so a busy scene can't make it schedule too +// many interpolated frames. Call once per tick, before Cap(). +void AdaptiveFps_SampleTick(long long logicNs); + +#ifdef __cplusplus +} +#endif diff --git a/src/port/Interpolation/FrameInterpolation.cpp b/src/port/Interpolation/FrameInterpolation.cpp index a8d4fd90f..c24118306 100644 --- a/src/port/Interpolation/FrameInterpolation.cpp +++ b/src/port/Interpolation/FrameInterpolation.cpp @@ -1,7 +1,5 @@ #include "FrameInterpolation.h" -#include -#include #include #include #include @@ -9,37 +7,86 @@ #include #include -#include + +// Double-buffered op recorder. Matrix primitives in core1/math/matrix_stack.c +// append into gCurrent between StartRecord/StopRecord; Interpolate(t) pairs +// ops across two consecutive ticks (gPrevious vs gCurrent) by scope-path and +// lerps the inputs. Camera projection rotations and sprite inputs go through +// angle-space lerp (not matrix-lerp) to avoid the paper-fold artifact on fast +// spins. See docs/INTERPOLATION.md for the full design. namespace { -constexpr uint64_t kFnvSeed = 0xcbf29ce484222325ULL; -constexpr uint64_t kSigKindToMtx = 0x1ULL; -constexpr uint64_t kSigKindSprite = 0x2ULL; -constexpr uint64_t kSigKindAnimVtx = 0x3ULL; -constexpr uint64_t kSigKindProjRot = 0x4ULL; -constexpr float kAnimVtxSnapRatio = 0.5f; -constexpr float kSpriteSnapDistSq = 300.0f * 300.0f; -constexpr int kRingSlots = 4; -constexpr uint32_t kAmbiguousSig = UINT32_MAX; +enum class Op : uint8_t { + OpenChild, + CloseChild, + Marker, + + MatrixIdent, + MatrixTranslate, + MatrixRotYaw, + MatrixRotPitch, + MatrixRotRoll, + MatrixScale, + MatrixSet, + MatrixMult, + MatrixToMtx, + + CameraProjectionRotation, + SpriteDraw, +}; + +// Heavy ops (Set/Mult/ToMtx/Camera/Sprite) stash their payload in per-tree +// side vectors and reference it via side_index. +struct OpNode { + Op op; + union { + struct { + float x, y, z; + } vec3; + struct { + float degrees; + } rotate; + struct { + const void* key; + uintptr_t id; + } open_child; + struct { + const char* file; + int line; + } marker; + uint32_t side_index; + }; + + OpNode() : op(Op::Marker), side_index(0) { + } +}; + +struct MatrixSetData { + float m[4][4]; +}; + +struct MatrixMultData { + float l[4][4]; + float r[4][4]; +}; struct ToMtxData { void* dst; float src[4][4]; + // Cross-tick pairing key, built at record time from the live FNV scope + // hash; same scope path on both ticks → same sig → O(1) pair lookup. uint64_t pathSig; + // Sprites flag this so the lerp loop leaves their dst alone — cube + // culling reorders sprites between ticks so index pairing mismatches. bool noInterpolate; - bool camRelFixup; - bool ambiguousSig; -}; - -struct AnimVtxData { - void* dst; - uint32_t count; - uint64_t pathSig; - bool ambiguousSig; - std::vector pos; }; +// Sprites record raw inputs (angles for rotations, linear for pos/scale) +// rather than the final matrix, so replay can lerp in natural spaces and +// rebuild a matrix that stays consistent with the angle-lerped projection. +// Which fields matter depends on kind: billboards use camYaw/camPitch, +// FULL uses rotation[], only BILLBOARD_ROLL cares about spriteRoll. struct SpriteDrawData { void* dst; float camRelPos[3]; @@ -51,9 +98,11 @@ struct SpriteDrawData { uint64_t pathSig; uint8_t kind; bool mirrored; - bool ambiguousSig; }; +// We record the three Euler angles behind BK's projection rotation rather +// than the matrices, so replay can shortest-path angle-lerp and rebuild via +// guRotateF — element-wise lerp on these matrices folds during fast spins. struct CameraProjRotData { void* rollMtx; void* pitchMtx; @@ -61,160 +110,113 @@ struct CameraProjRotData { float rollDeg; float pitchDeg; float yawDeg; - uint64_t pathSig; - bool ambiguousSig; }; struct ScopeFrame { uint64_t pathHash; uint32_t toMtxIdx; uint32_t spriteIdx; - uint32_t animVtxIdx; - uint32_t projRotIdx; - const char* key; - uintptr_t id; }; +constexpr uint64_t kFnvSeed = 0xcbf29ce484222325ULL; +// Disambiguators so a ToMtx and a Sprite at the same in-scope index don't +// collide on a single signature. +constexpr uint64_t kSigKindToMtx = 0x1ULL; +constexpr uint64_t kSigKindSprite = 0x2ULL; + +inline uint64_t fnvMix(uint64_t h, uint64_t v) { + h ^= v; + h *= 0x100000001b3ULL; + return h; +} + +// Sig maps are populated live during recording. After StopRecord swaps +// trees, gPrevious already has its maps and BuildInterpolationCache can +// pair entries with O(1) lookups instead of re-walking the prev tree. struct FrameTree { + std::vector ops; + std::vector sets; + std::vector mults; std::vector toMtxs; std::vector projRots; std::vector sprites; - std::vector animVtxs; std::unordered_map sigToToMtx; std::unordered_map sigToSprite; - std::unordered_map sigToAnimVtx; - std::unordered_map sigToProjRot; std::vector scopeStack; float cameraPos[3] = { 0.0f, 0.0f, 0.0f }; bool hasCameraPos = false; bool valid = false; - uint32_t sigCollisions = 0; - std::atomic generation{ 0 }; void reset() { - generation.fetch_add(1, std::memory_order_release); + ops.clear(); + sets.clear(); + mults.clear(); toMtxs.clear(); projRots.clear(); sprites.clear(); - animVtxs.clear(); sigToToMtx.clear(); sigToSprite.clear(); - sigToAnimVtx.clear(); - sigToProjRot.clear(); scopeStack.clear(); cameraPos[0] = cameraPos[1] = cameraPos[2] = 0.0f; hasCameraPos = false; valid = false; - sigCollisions = 0; } }; -struct PairedToMtx { - uint32_t currIdx; - uint32_t prevIdx; - bool snap; -}; +FrameTree gTreeA; +FrameTree gTreeB; +FrameTree* gCurrent = &gTreeA; +FrameTree* gPrevious = &gTreeB; -struct PairedSprite { - uint32_t currIdx; - uint32_t prevIdx; - bool snap; -}; +bool gRecording = false; +bool gShouldInterpolate = true; +int gNoInterpolateDepth = 0; + +// Monotonic ids for heap pointers that get reused by the allocator. Without +// these, a freed object's address gets reused by the next allocation and +// the new one inherits the dead one's matrix pairing. +std::unordered_map gIdMap; +uint64_t gNextId = 1; -struct PairedAnimVtx { +// Per-tick cache built lazily on the first Interpolate(t) call and reused +// for every sub-frame within the tick. Stores only (curr, prev) pairs whose +// lerped output differs from c.src — no-prev and bit-identical entries are +// skipped because the interpreter's fallback path decodes the DL bytes that +// c.src was already encoded into, producing the same matrix without a map +// lookup. Shrinking the map this way speeds up every interpreter find() +// across the whole DL on top of cheaper inserts. +struct PairedToMtx { uint32_t currIdx; uint32_t prevIdx; + // Hemisphere check is stable across t for a (prev, curr) pair, so we + // do it once at cache build instead of 6 fmuls + cmps per sub-frame. bool snap; }; - -struct PairedProjRot { +struct PairedSprite { uint32_t currIdx; uint32_t prevIdx; }; - struct InterpolationCache { - bool built = false; bool valid = false; std::vector pairedToMtxs; std::vector pairedSprites; - std::vector pairedAnimVtxs; - std::vector pairedProjRots; - std::vector camRelFixups; - float cameraDelta[3] = { 0.0f, 0.0f, 0.0f }; - bool hasCameraDelta = false; bool prevHasCameraPos = false; float prevCameraPos[3] = { 0.0f, 0.0f, 0.0f }; void reset() { - built = false; valid = false; pairedToMtxs.clear(); pairedSprites.clear(); - pairedAnimVtxs.clear(); - pairedProjRots.clear(); - camRelFixups.clear(); - hasCameraDelta = false; prevHasCameraPos = false; } }; - -// Ring of trees -FrameTree gRing[kRingSlots]; -std::atomic gSlotClaims[kRingSlots] = {}; -int gRecordSlot = 0; -int gLastRecordedSlot = -1; -FrameTree* gRecord = &gRing[0]; -FrameTree* gRenderPrev = nullptr; -FrameTree* gRenderCurr = nullptr; -bool gRenderShould = false; - -bool gRecording = false; -bool gShouldInterpolate = true; -int gNoInterpolateDepth = 0; -int gCameraRelativeDepth = 0; - -std::unordered_map gIdMap; -uint64_t gNextId = 1; - InterpolationCache gCache; -// First scope identity to collide this tick, reported once by StopRecord so a -// busy frame cannot flood the log. Cleared per tick in StartRecord; nullptr -// means nothing has collided yet. -const char* gCollidedScopeKey = nullptr; -uintptr_t gCollidedScopeId = 0; -const char* gCollidedParentKey = nullptr; -uintptr_t gCollidedParentId = 0; - -inline uint64_t fnvMix(uint64_t h, uint64_t v) { - h ^= v; - h *= 0x100000001b3ULL; - return h; -} - -template -void recordSigCollision(Map& sigMap, Vec& entries, uint64_t sig, uint32_t idx, uint32_t& collisionCount, - const std::vector& stack) { - const ScopeFrame& scope = stack.back(); - auto [it, inserted] = sigMap.emplace(sig, idx); - if (inserted) { - return; - } - if (it->second < entries.size()) { - entries[it->second].ambiguousSig = true; - } - entries[idx].ambiguousSig = true; - it->second = kAmbiguousSig; - collisionCount++; - if (gCollidedScopeKey == nullptr) { - gCollidedScopeKey = scope.key; - gCollidedScopeId = scope.id; - if (stack.size() >= 2) { - const ScopeFrame& parent = stack[stack.size() - 2]; - gCollidedParentKey = parent.key; - gCollidedParentId = parent.id; - } - } +OpNode& append(Op op) { + gCurrent->ops.emplace_back(); + OpNode& n = gCurrent->ops.back(); + n.op = op; + return n; } } // namespace @@ -222,156 +224,166 @@ void recordSigCollision(Map& sigMap, Vec& entries, uint64_t sig, uint32_t idx, u extern "C" { void FrameInterpolation_StartRecord(void) { - for (int i = 0; i < kRingSlots; i++) { - gRecordSlot = (gRecordSlot + 1) % kRingSlots; - if (gSlotClaims[gRecordSlot].load(std::memory_order_acquire) == 0 && gRecordSlot != gLastRecordedSlot) { - break; - } - } - if (gSlotClaims[gRecordSlot].load(std::memory_order_acquire) != 0) { - // Should be impossible, but if it ever prints, a claim leaked. - SPDLOG_WARN("interp record forced into claimed slot {} claims=[{},{},{},{}]", gRecordSlot, - gSlotClaims[0].load(), gSlotClaims[1].load(), gSlotClaims[2].load(), gSlotClaims[3].load()); - } - gRecord = &gRing[gRecordSlot]; - gCollidedScopeKey = nullptr; - gCollidedScopeId = 0; - gCollidedParentKey = nullptr; - gCollidedParentId = 0; - gRecord->reset(); - gRecord->toMtxs.reserve(512); - gRecord->projRots.reserve(16); - gRecord->sprites.reserve(256); - gRecord->sigToToMtx.reserve(512); - gRecord->sigToSprite.reserve(64); - gRecord->sigToProjRot.reserve(16); - gRecord->scopeStack.push_back({ kFnvSeed, 0, 0, 0, 0, "root", 0 }); + gCurrent->reset(); + // Reserve once; subsequent ticks reuse the existing capacity. + gCurrent->ops.reserve(4096); + gCurrent->sets.reserve(128); + gCurrent->mults.reserve(256); + gCurrent->toMtxs.reserve(512); + gCurrent->projRots.reserve(4); + gCurrent->sprites.reserve(256); + gCurrent->sigToToMtx.reserve(512); + gCurrent->sigToSprite.reserve(64); + gCurrent->scopeStack.push_back({ kFnvSeed, 0, 0 }); gShouldInterpolate = true; gNoInterpolateDepth = 0; - gCameraRelativeDepth = 0; gRecording = true; + // The cache built during the prior render pass references trees that + // are about to be reused for this tick. + gCache.valid = false; } -// Idempotent: a threaded submitter has to close the session early, before the -// tree goes to another thread, so the tick's own call then finds it closed. void FrameInterpolation_StopRecord(void) { - if (!gRecording) { - return; - } gRecording = false; - gRecord->valid = gShouldInterpolate; - gLastRecordedSlot = gRecordSlot; - - // One line per affected tick, not per collision: a scope whose id repeats - // usually repeats for every instance behind it. - if (gRecord->sigCollisions != 0) { - static uint32_t sReported = 0; - if (sReported < 20) { - sReported++; - SPDLOG_WARN("interp scope id collided {}x this tick under \"{}\" id={:#x} > \"{}\" id={:#x} " - "({} matrices, {} sprites)", - gRecord->sigCollisions, gCollidedParentKey != nullptr ? gCollidedParentKey : "?", - gCollidedParentId, gCollidedScopeKey != nullptr ? gCollidedScopeKey : "?", gCollidedScopeId, - gRecord->toMtxs.size(), gRecord->sprites.size()); - } - } + gCurrent->valid = gShouldInterpolate; + // What we just recorded becomes `previous` for the next tick. + std::swap(gCurrent, gPrevious); } -// The pair for the tick being recorded right now, grabbed when a display list -// is handed off so it renders against the trees it was built from. -void FrameInterpolation_GetRecordingPair(int* prevSlot, int* currSlot, bool* shouldInterpolate) { +void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate) { + gShouldInterpolate = shouldInterpolate; +} + +void FrameInterpolation_RecordOpenChild(const void* key, uintptr_t id) { if (!gRecording) { - *prevSlot = -1; - *currSlot = -1; - *shouldInterpolate = false; return; } - *prevSlot = gLastRecordedSlot; - *currSlot = gRecordSlot; - *shouldInterpolate = gShouldInterpolate; + OpNode& n = append(Op::OpenChild); + n.open_child.key = key; + n.open_child.id = id; + uint64_t h = gCurrent->scopeStack.back().pathHash; + h = fnvMix(h, reinterpret_cast(key)); + h = fnvMix(h, static_cast(id)); + gCurrent->scopeStack.push_back({ h, 0, 0 }); } -// Claim and release bracket a pair's render lifetime: claimed on the tick side -// at submission, released once the render (and its workers) are done reading. -void FrameInterpolation_ClaimPair(int prevSlot, int currSlot) { - if (prevSlot >= 0 && prevSlot < kRingSlots) { - gSlotClaims[prevSlot].fetch_add(1, std::memory_order_release); +void FrameInterpolation_RecordCloseChild(void) { + if (!gRecording) { + return; } - if (currSlot >= 0 && currSlot < kRingSlots) { - gSlotClaims[currSlot].fetch_add(1, std::memory_order_release); + append(Op::CloseChild); + if (gCurrent->scopeStack.size() > 1) { + gCurrent->scopeStack.pop_back(); } } -void FrameInterpolation_ReleasePair(int prevSlot, int currSlot) { - if (prevSlot >= 0 && prevSlot < kRingSlots) { - gSlotClaims[prevSlot].fetch_sub(1, std::memory_order_release); +uintptr_t FrameInterpolation_Hash3(uint64_t a, uint64_t b, uint64_t c) { + // Three distinct odd primes keep the three inputs separable even when + // they share most of their bytes. + uint64_t h = a * 0x9E3779B97F4A7C15ULL; + h ^= b * 0x100000001b3ULL; + h ^= c * 0xbf58476d1ce4e5b9ULL; + return static_cast(h); +} + +void FrameInterpolation_RecordOpenChildHash3(const char* key, uint64_t a, uint64_t b, uint64_t c) { + FrameInterpolation_RecordOpenChild(key, FrameInterpolation_Hash3(a, b, c)); +} + +void FrameInterpolation_RecordMarker(const char* file, int line) { + if (!gRecording) { + return; } - if (currSlot >= 0 && currSlot < kRingSlots) { - gSlotClaims[currSlot].fetch_sub(1, std::memory_order_release); + OpNode& n = append(Op::Marker); + n.marker.file = file; + n.marker.line = line; +} + +void FrameInterpolation_RecordMatrixIdent(void) { + if (!gRecording) { + return; } + append(Op::MatrixIdent); } -// Pins the trees this pass blends and drops the previous pass's pairing cache. -void FrameInterpolation_BeginRenderPass(int prevSlot, int currSlot, bool shouldInterpolate) { - gRenderPrev = (prevSlot >= 0 && prevSlot < kRingSlots) ? &gRing[prevSlot] : nullptr; - gRenderCurr = (currSlot >= 0 && currSlot < kRingSlots) ? &gRing[currSlot] : nullptr; - gRenderShould = shouldInterpolate && gRenderCurr != nullptr && gRenderPrev != nullptr; - gCache.built = false; - gCache.valid = false; +void FrameInterpolation_RecordMatrixTranslate(float x, float y, float z) { + if (!gRecording) { + return; + } + OpNode& n = append(Op::MatrixTranslate); + n.vec3.x = x; + n.vec3.y = y; + n.vec3.z = z; } -void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate) { - gShouldInterpolate = shouldInterpolate; +void FrameInterpolation_RecordMatrixRotYaw(float degrees) { + if (!gRecording) { + return; + } + append(Op::MatrixRotYaw).rotate.degrees = degrees; } -void FrameInterpolation_RecordOpenChild(const void* key, uintptr_t id) { +void FrameInterpolation_RecordMatrixRotPitch(float degrees) { if (!gRecording) { return; } - uint64_t h = gRecord->scopeStack.back().pathHash; - h = fnvMix(h, reinterpret_cast(key)); - h = fnvMix(h, static_cast(id)); - gRecord->scopeStack.push_back({ h, 0, 0, 0, 0, static_cast(key), id }); + append(Op::MatrixRotPitch).rotate.degrees = degrees; } -void FrameInterpolation_RecordCloseChild(void) { +void FrameInterpolation_RecordMatrixRotRoll(float degrees) { if (!gRecording) { return; } - if (gRecord->scopeStack.size() > 1) { - gRecord->scopeStack.pop_back(); + append(Op::MatrixRotRoll).rotate.degrees = degrees; +} + +void FrameInterpolation_RecordMatrixScale(float x, float y, float z) { + if (!gRecording) { + return; } + OpNode& n = append(Op::MatrixScale); + n.vec3.x = x; + n.vec3.y = y; + n.vec3.z = z; } -uintptr_t FrameInterpolation_Hash3(uint64_t a, uint64_t b, uint64_t c) { - uint64_t h = a * 0x9E3779B97F4A7C15ULL; - h ^= b * 0x100000001b3ULL; - h ^= c * 0xbf58476d1ce4e5b9ULL; - return static_cast(h); +void FrameInterpolation_RecordMatrixSet(const float src[4][4]) { + if (!gRecording) { + return; + } + gCurrent->sets.emplace_back(); + std::memcpy(gCurrent->sets.back().m, src, sizeof(float) * 16); + append(Op::MatrixSet).side_index = static_cast(gCurrent->sets.size() - 1); } -void FrameInterpolation_RecordOpenChildHash3(const char* key, uint64_t a, uint64_t b, uint64_t c) { - FrameInterpolation_RecordOpenChild(key, FrameInterpolation_Hash3(a, b, c)); +void FrameInterpolation_RecordMatrixMult(const float l[4][4], const float r[4][4]) { + if (!gRecording) { + return; + } + gCurrent->mults.emplace_back(); + MatrixMultData& d = gCurrent->mults.back(); + std::memcpy(d.l, l, sizeof(float) * 16); + std::memcpy(d.r, r, sizeof(float) * 16); + append(Op::MatrixMult).side_index = static_cast(gCurrent->mults.size() - 1); } void FrameInterpolation_RecordMatrixToMtx(void* dst, const float src[4][4]) { if (!gRecording) { return; } - ScopeFrame& scope = gRecord->scopeStack.back(); + ScopeFrame& scope = gCurrent->scopeStack.back(); uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindToMtx), scope.toMtxIdx); scope.toMtxIdx++; - uint32_t idx = static_cast(gRecord->toMtxs.size()); - gRecord->toMtxs.emplace_back(); - ToMtxData& d = gRecord->toMtxs.back(); + uint32_t idx = static_cast(gCurrent->toMtxs.size()); + gCurrent->toMtxs.emplace_back(); + ToMtxData& d = gCurrent->toMtxs.back(); d.dst = dst; std::memcpy(d.src, src, sizeof(float) * 16); d.pathSig = sig; - d.noInterpolate = (gNoInterpolateDepth > 0 || gCameraRelativeDepth > 0); - d.camRelFixup = (gCameraRelativeDepth > 0); - d.ambiguousSig = false; - recordSigCollision(gRecord->sigToToMtx, gRecord->toMtxs, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); + d.noInterpolate = (gNoInterpolateDepth > 0); + gCurrent->sigToToMtx.emplace(sig, idx); + append(Op::MatrixToMtx).side_index = idx; } void FrameInterpolation_RecordCameraProjectionRotation(void* rollMtx, float rollDeg, void* pitchMtx, float pitchDeg, @@ -379,33 +391,25 @@ void FrameInterpolation_RecordCameraProjectionRotation(void* rollMtx, float roll if (!gRecording) { return; } - - ScopeFrame& scope = gRecord->scopeStack.back(); - uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindProjRot), scope.projRotIdx); - scope.projRotIdx++; - - uint32_t idx = static_cast(gRecord->projRots.size()); - gRecord->projRots.emplace_back(); - CameraProjRotData& d = gRecord->projRots.back(); + gCurrent->projRots.emplace_back(); + CameraProjRotData& d = gCurrent->projRots.back(); d.rollMtx = rollMtx; d.pitchMtx = pitchMtx; d.yawMtx = yawMtx; d.rollDeg = rollDeg; d.pitchDeg = pitchDeg; d.yawDeg = yawDeg; - d.pathSig = sig; - d.ambiguousSig = false; - recordSigCollision(gRecord->sigToProjRot, gRecord->projRots, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); + append(Op::CameraProjectionRotation).side_index = static_cast(gCurrent->projRots.size() - 1); } void FrameInterpolation_RecordCameraPosition(const float pos[3]) { if (!gRecording || pos == nullptr) { return; } - gRecord->cameraPos[0] = pos[0]; - gRecord->cameraPos[1] = pos[1]; - gRecord->cameraPos[2] = pos[2]; - gRecord->hasCameraPos = true; + gCurrent->cameraPos[0] = pos[0]; + gCurrent->cameraPos[1] = pos[1]; + gCurrent->cameraPos[2] = pos[2]; + gCurrent->hasCameraPos = true; } void FrameInterpolation_NoInterpolatePush(void) { @@ -418,29 +422,19 @@ void FrameInterpolation_NoInterpolatePop(void) { } } -void FrameInterpolation_CameraRelativePush(void) { - gCameraRelativeDepth++; -} - -void FrameInterpolation_CameraRelativePop(void) { - if (gCameraRelativeDepth > 0) { - gCameraRelativeDepth--; - } -} - void FrameInterpolation_RecordSpriteDraw(int kind, void* dst, const float camRelPos[3], const float scale[3], float camYaw, float camPitch, float spriteRoll, const float rotation[3], int mirrored) { if (!gRecording) { return; } - ScopeFrame& scope = gRecord->scopeStack.back(); + ScopeFrame& scope = gCurrent->scopeStack.back(); uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindSprite), scope.spriteIdx); scope.spriteIdx++; - uint32_t idx = static_cast(gRecord->sprites.size()); - gRecord->sprites.emplace_back(); - SpriteDrawData& d = gRecord->sprites.back(); + uint32_t idx = static_cast(gCurrent->sprites.size()); + gCurrent->sprites.emplace_back(); + SpriteDrawData& d = gCurrent->sprites.back(); d.dst = dst; std::memcpy(d.camRelPos, camRelPos, sizeof(float) * 3); std::memcpy(d.scale, scale, sizeof(float) * 3); @@ -455,41 +449,15 @@ void FrameInterpolation_RecordSpriteDraw(int kind, void* dst, const float camRel d.pathSig = sig; d.kind = static_cast(kind); d.mirrored = (mirrored != 0); - d.ambiguousSig = false; - recordSigCollision(gRecord->sigToSprite, gRecord->sprites, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); -} - -void FrameInterpolation_RecordAnimVertices(void* dst, const void* vertices, int32_t count) { - if (!gRecording || dst == nullptr || vertices == nullptr || count <= 0) { - return; - } - ScopeFrame& scope = gRecord->scopeStack.back(); - uint64_t sig = fnvMix(fnvMix(scope.pathHash, kSigKindAnimVtx), scope.animVtxIdx); - scope.animVtxIdx++; - - uint32_t idx = static_cast(gRecord->animVtxs.size()); - gRecord->animVtxs.emplace_back(); - AnimVtxData& d = gRecord->animVtxs.back(); - d.dst = dst; - d.count = static_cast(count); - d.pathSig = sig; - d.ambiguousSig = false; - d.pos.resize(static_cast(count) * 3); - - // Only ob[] moves; everything else in the Vtx (uv, colour/normal) is what - // the tick's own copy already put in dst. - const Vtx* src = static_cast(vertices); - for (int32_t i = 0; i < count; i++) { - d.pos[i * 3 + 0] = src[i].v.ob[0]; - d.pos[i * 3 + 1] = src[i].v.ob[1]; - d.pos[i * 3 + 2] = src[i].v.ob[2]; - } - recordSigCollision(gRecord->sigToAnimVtx, gRecord->animVtxs, sig, idx, gRecord->sigCollisions, gRecord->scopeStack); + gCurrent->sigToSprite.emplace(sig, idx); + append(Op::SpriteDraw).side_index = idx; } void FrameInterpolation_DontInterpolateCamera(void) { - if (gLastRecordedSlot >= 0) { - gRing[gLastRecordedSlot].valid = false; + // Prev's matrices belong to a scene the camera just left; dropping the + // tree makes the next Interpolate() bail and replay uses curr as-is. + if (gPrevious != nullptr) { + gPrevious->valid = false; } } @@ -510,6 +478,7 @@ uintptr_t FrameInterpolation_GetId(const void* ptr) { if (it != gIdMap.end()) { return static_cast(it->second); } + // Fallback for callers that don't Register; ABA-prone. return reinterpret_cast(ptr); } @@ -524,14 +493,15 @@ void FrameInterpolation_UnregisterId(const void* ptr) { namespace { -// Blending across a >90 degree turn drags the model through itself for a frame; -// snap to the new orientation instead. +// Snap to curr when prev/curr point apart on X or Y (>90° rotation): +// element-wise lerp on those folds the character inside-out. inline bool shouldSnap(const float pa[4][4], const float ca[4][4]) { float dotX = pa[0][0] * ca[0][0] + pa[0][1] * ca[0][1] + pa[0][2] * ca[0][2]; float dotY = pa[1][0] * ca[1][0] + pa[1][1] * ca[1][1] + pa[1][2] * ca[1][2]; return dotX < 0.0f || dotY < 0.0f; } +// Shortest-path angle lerp in degrees. inline float lerpAngleDegSP(float a, float b, float tt) { float d = b - a; d = std::fmod(d + 540.0f, 360.0f) - 180.0f; @@ -540,82 +510,42 @@ inline float lerpAngleDegSP(float a, float b, float tt) { void BuildInterpolationCache() { gCache.reset(); - gCache.built = true; - if (gRenderPrev == nullptr || gRenderCurr == nullptr || !gRenderPrev->valid) { + if (!gPrevious->valid) { return; } - const uint32_t prevGen = gRenderPrev->generation.load(std::memory_order_acquire); - const uint32_t currGen = gRenderCurr->generation.load(std::memory_order_acquire); - gCache.prevHasCameraPos = gRenderPrev->hasCameraPos; + // Snapshot prev's camera pos so Interpolate's cut detector reads only + // gCache for tick-stable state. + gCache.prevHasCameraPos = gPrevious->hasCameraPos; if (gCache.prevHasCameraPos) { - gCache.prevCameraPos[0] = gRenderPrev->cameraPos[0]; - gCache.prevCameraPos[1] = gRenderPrev->cameraPos[1]; - gCache.prevCameraPos[2] = gRenderPrev->cameraPos[2]; - } - - // Same two positions the cut heuristic below compares, so a fixup can never - // shift further than the cut threshold before Interpolate() bails outright. - gCache.hasCameraDelta = false; - if (gRenderPrev->hasCameraPos && gRenderCurr->hasCameraPos) { - for (int k = 0; k < 3; k++) { - gCache.cameraDelta[k] = gRenderCurr->cameraPos[k] - gRenderPrev->cameraPos[k]; - gCache.hasCameraDelta |= (gCache.cameraDelta[k] != 0.0f); - } + gCache.prevCameraPos[0] = gPrevious->cameraPos[0]; + gCache.prevCameraPos[1] = gPrevious->cameraPos[1]; + gCache.prevCameraPos[2] = gPrevious->cameraPos[2]; } - const std::vector& currToMtxs = gRenderCurr->toMtxs; - const std::vector& prevToMtxs = gRenderPrev->toMtxs; - const std::vector& currSprites = gRenderCurr->sprites; - const std::vector& prevSprites = gRenderPrev->sprites; - const std::unordered_map& prevSigMap = gRenderPrev->sigToToMtx; - const std::unordered_map& prevSpriteMap = gRenderPrev->sigToSprite; + const std::vector& currToMtxs = gCurrent->toMtxs; + const std::vector& prevToMtxs = gPrevious->toMtxs; + const std::vector& currSprites = gCurrent->sprites; + const std::vector& prevSprites = gPrevious->sprites; + const std::unordered_map& prevSigMap = gPrevious->sigToToMtx; + const std::unordered_map& prevSpriteMap = gPrevious->sigToSprite; gCache.pairedToMtxs.reserve(currToMtxs.size()); gCache.pairedSprites.reserve(currSprites.size()); - // Camera/viewport projection rotations, matched by path signature. Anything - // without a partner this tick keeps the matrix the game already wrote, which - // is this tick's own end state. - const std::vector& currProjRots = gRenderCurr->projRots; - const std::vector& prevProjRots = gRenderPrev->projRots; - gCache.pairedProjRots.reserve(currProjRots.size()); - for (uint32_t i = 0; i < currProjRots.size(); i++) { - const CameraProjRotData& c = currProjRots[i]; - if (c.ambiguousSig) { - continue; - } - auto it = gRenderPrev->sigToProjRot.find(c.pathSig); - if (it == gRenderPrev->sigToProjRot.end() || it->second >= prevProjRots.size()) { - continue; - } - if (prevProjRots[it->second].ambiguousSig) { - continue; - } - gCache.pairedProjRots.push_back({ i, it->second }); - } - - // Whatever stays out of the cache falls back to the interpreter decoding - // the Mtx bytes the game itself wrote, which already hold the correct - // end-of-tick matrix. Entries with no previous partner, or whose - // matrix didn't change, can simply be dropped here. + // Only pair ToMtxs whose replacement actually differs from the curr + // matrix. The interpreter's fallback path decodes the DL bytes at + // c.dst, which the game wrote from the same float matrix that's now + // c.src — so unpaired AND bit-identical entries decode to the same + // result without a map lookup. Skipping them shrinks the replacement + // map and speeds up every interpreter find() across the whole DL. for (uint32_t i = 0; i < currToMtxs.size(); i++) { const ToMtxData& c = currToMtxs[i]; - if (c.dst == nullptr) { - continue; - } - // Camera-relative fixups skip pairing entirely. - if (c.camRelFixup) { - if (gCache.hasCameraDelta) { - gCache.camRelFixups.push_back(i); - } - continue; - } - if (c.noInterpolate || c.ambiguousSig) { + if (c.dst == nullptr || c.noInterpolate) { continue; } auto it = prevSigMap.find(c.pathSig); - if (it == prevSigMap.end() || it->second >= prevToMtxs.size()) { + if (it == prevSigMap.end()) { continue; } const ToMtxData& p = prevToMtxs[it->second]; @@ -625,93 +555,25 @@ void BuildInterpolationCache() { gCache.pairedToMtxs.push_back({ i, it->second, shouldSnap(p.src, c.src) }); } - // Sprites whose inputs didn't move at all are dropped for the same - // reason; the rest get their matrix rebuilt every sub-frame so billboards - // keep facing the blended camera. + // Sprites always pair (or get a sentinel prev-idx) because the matrix + // must be rebuilt every sub-frame anyway — billboard rotations follow + // the lerped projection. for (uint32_t i = 0; i < currSprites.size(); i++) { const SpriteDrawData& c = currSprites[i]; - if (c.ambiguousSig) { - continue; - } auto it = prevSpriteMap.find(c.pathSig); - if (it == prevSpriteMap.end() || it->second >= prevSprites.size() || prevSprites[it->second].kind != c.kind) { - gCache.pairedSprites.push_back({ i, UINT32_MAX, false }); - continue; - } - const SpriteDrawData& p = prevSprites[it->second]; - if (std::memcmp(p.camRelPos, c.camRelPos, sizeof(c.camRelPos)) == 0 && - std::memcmp(p.scale, c.scale, sizeof(c.scale)) == 0 && p.camYaw == c.camYaw && p.camPitch == c.camPitch && - p.spriteRoll == c.spriteRoll && std::memcmp(p.rotation, c.rotation, sizeof(c.rotation)) == 0 && - p.mirrored == c.mirrored) { - continue; - } - bool snap = false; - if (gRenderPrev->hasCameraPos && gRenderCurr->hasCameraPos) { - float d[3]; - for (int k = 0; k < 3; k++) { - d[k] = (c.camRelPos[k] + gRenderCurr->cameraPos[k]) - (p.camRelPos[k] + gRenderPrev->cameraPos[k]); - } - snap = (d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) > kSpriteSnapDistSq; - } - gCache.pairedSprites.push_back({ i, it->second, snap }); - } - - // Same pairing as the sprite path. A vertex blend can't go degenerate the way - // a matrix lerp does, but blending across an animation cut still drags the - // model through itself, so measure the jump against the model's own size. - const std::vector& currAnimVtxs = gRenderCurr->animVtxs; - const std::vector& prevAnimVtxs = gRenderPrev->animVtxs; - const std::unordered_map& prevAnimVtxMap = gRenderPrev->sigToAnimVtx; - gCache.pairedAnimVtxs.reserve(currAnimVtxs.size()); - for (uint32_t i = 0; i < currAnimVtxs.size(); i++) { - const AnimVtxData& c = currAnimVtxs[i]; - if (c.dst == nullptr || c.ambiguousSig) { - continue; - } - auto it = prevAnimVtxMap.find(c.pathSig); - if (it == prevAnimVtxMap.end() || it->second >= prevAnimVtxs.size()) { - continue; - } - const AnimVtxData& p = prevAnimVtxs[it->second]; - // A different vertex count means the sig landed on a different model. - if (p.count != c.count || p.pos.size() != c.pos.size()) { - continue; - } - if (p.pos == c.pos) { - continue; // pose held still; dst already has it - } - int32_t maxExtent = 0; - int32_t maxDelta = 0; - for (size_t k = 0; k < c.pos.size(); k++) { - int32_t a = std::abs(static_cast(c.pos[k])); - int32_t d = std::abs(static_cast(c.pos[k]) - static_cast(p.pos[k])); - if (a > maxExtent) { - maxExtent = a; - } - if (d > maxDelta) { - maxDelta = d; - } + if (it == prevSpriteMap.end() || prevSprites[it->second].kind != c.kind) { + gCache.pairedSprites.push_back({ i, UINT32_MAX }); + } else { + gCache.pairedSprites.push_back({ i, it->second }); } - bool snap = maxExtent > 0 && static_cast(maxDelta) > kAnimVtxSnapRatio * static_cast(maxExtent); - gCache.pairedAnimVtxs.push_back({ i, it->second, snap }); - } - - // A tree recycled while we walked it means every index above is suspect. - // Drop the pass to uninterpolated and say which slot collided. - if (gRenderPrev->generation.load(std::memory_order_acquire) != prevGen || - gRenderCurr->generation.load(std::memory_order_acquire) != currGen) { - SPDLOG_WARN("interp tree recycled mid-pass: prev={} curr={} record={} last={} claims=[{},{},{},{}]", - (int)(gRenderPrev - gRing), (int)(gRenderCurr - gRing), gRecordSlot, gLastRecordedSlot, - gSlotClaims[0].load(), gSlotClaims[1].load(), gSlotClaims[2].load(), gSlotClaims[3].load()); - gCache.reset(); - gCache.built = true; - return; } + gCache.valid = true; } -// Rebuilds the sprite modelview the same way sprite/render.c composes it, so -// a replayed matrix can't drift from what the game would have written. +// Build a sprite modelview from lerped inputs. Mirrors the decomp +// composition for each kind so the replay matrix stays consistent with +// the record-site one. void emitSprite(const SpriteDrawData& L, std::unordered_map& replacements) { if (L.dst == nullptr) { return; @@ -720,6 +582,7 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace std::memset(m, 0, sizeof(m)); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; + // Rotations match the matrix_stack.c primitives — rows 0-2 only. auto rotYaw = [&](float deg) { if (deg == 0.0f) return; @@ -755,6 +618,8 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace }; if (L.kind == FI_SPRITE_KIND_FULL) { + // FULL: translate first (the game's func_80252330 stomps mf[3]), + // then rotate — rotations only touch rows 0-2. m[3][0] = L.camRelPos[0]; m[3][1] = L.camRelPos[1]; m[3][2] = L.camRelPos[2]; @@ -762,6 +627,8 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace rotPitch(L.rotation[0]); rotRoll(L.rotation[2]); } else { + // Billboard: cam-aligned rotations, optional sprite roll, then + // translate overwrites mf[3]. rotYaw(L.camYaw); rotPitch(L.camPitch); if (L.kind == FI_SPRITE_KIND_BILLBOARD_ROLL) { @@ -772,6 +639,7 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace m[3][2] = L.camRelPos[2]; } + // mlMtxScale_xyz: rows 0-2 only, translation preserved. float sx = L.mirrored ? -L.scale[0] : L.scale[0]; for (int i = 0; i < 3; i++) { m[0][i] *= sx; @@ -785,89 +653,43 @@ void emitSprite(const SpriteDrawData& L, std::unordered_map& replace } // namespace -void FrameInterpolation_ApplyAnimVertices(float t) { - if (!gRenderShould) { - return; - } - if (!gCache.built) { - BuildInterpolationCache(); - } - if (!gCache.valid) { - return; - } - if (gCache.prevHasCameraPos && gRenderCurr->hasCameraPos) { - float dx = gRenderCurr->cameraPos[0] - gCache.prevCameraPos[0]; - float dy = gRenderCurr->cameraPos[1] - gCache.prevCameraPos[1]; - float dz = gRenderCurr->cameraPos[2] - gCache.prevCameraPos[2]; - constexpr float kCutDistSq = 1000.0f * 1000.0f; - if (dx * dx + dy * dy + dz * dz > kCutDistSq) { - return; - } - } - - const std::vector& currAnimVtxs = gRenderCurr->animVtxs; - const std::vector& prevAnimVtxs = gRenderPrev->animVtxs; - const float w = 1.0f - t; - - for (const PairedAnimVtx& pair : gCache.pairedAnimVtxs) { - const AnimVtxData& c = currAnimVtxs[pair.currIdx]; - if (pair.snap) { - continue; // never written, so dst still holds this tick's pose - } - const AnimVtxData& p = prevAnimVtxs[pair.prevIdx]; - Vtx* dst = reinterpret_cast(c.dst); - for (uint32_t i = 0; i < c.count; i++) { - for (int k = 0; k < 3; k++) { - float blended = w * static_cast(p.pos[i * 3 + k]) + t * static_cast(c.pos[i * 3 + k]); - dst[i].v.ob[k] = static_cast(std::lrintf(blended)); - } - } - } -} - void FrameInterpolation_Interpolate(float t, std::unordered_map& replacements) { + // Cache is built lazily by the first sub-frame call per render pass and + // reused; StartRecord clears it for the next tick. Caller owns + // `replacements` so its bucket array persists across sub-frames. replacements.clear(); - if (!gRenderShould) { + if (!gShouldInterpolate) { return; } - if (!gCache.built) { - BuildInterpolationCache(); - } if (!gCache.valid) { - return; + BuildInterpolationCache(); + if (!gCache.valid) { + return; + } } - // A large camera jump means a warp or camera cut. - if (gCache.prevHasCameraPos && gRenderCurr->hasCameraPos) { - float dx = gRenderCurr->cameraPos[0] - gCache.prevCameraPos[0]; - float dy = gRenderCurr->cameraPos[1] - gCache.prevCameraPos[1]; - float dz = gRenderCurr->cameraPos[2] - gCache.prevCameraPos[2]; + // Cut detector: a >1000-unit camera jump means a teleport (warp, + // fixed-cam snap). Lerping across that places the world between two + // scenes for one sub-frame. + if (gCache.prevHasCameraPos && gCurrent->hasCameraPos) { + float dx = gCurrent->cameraPos[0] - gCache.prevCameraPos[0]; + float dy = gCurrent->cameraPos[1] - gCache.prevCameraPos[1]; + float dz = gCurrent->cameraPos[2] - gCache.prevCameraPos[2]; constexpr float kCutDistSq = 1000.0f * 1000.0f; if (dx * dx + dy * dy + dz * dz > kCutDistSq) { return; } } - const std::vector& prevToMtxs = gRenderPrev->toMtxs; - const std::vector& currToMtxs = gRenderCurr->toMtxs; - const std::vector& prevSpritesData = gRenderPrev->sprites; - const std::vector& currSpritesData = gRenderCurr->sprites; + const std::vector& prevToMtxs = gPrevious->toMtxs; + const std::vector& currToMtxs = gCurrent->toMtxs; + const std::vector& prevSpritesData = gPrevious->sprites; + const std::vector& currSpritesData = gCurrent->sprites; - replacements.reserve(gCache.pairedToMtxs.size() + gCache.pairedSprites.size() + gCache.camRelFixups.size() + - gRenderCurr->projRots.size() * 3); + replacements.reserve(gCache.pairedToMtxs.size() + gCache.pairedSprites.size() + gCurrent->projRots.size() * 3); const float w = 1.0f - t; - // Re-aim the frozen matrix at the sub-frame's camera. - for (uint32_t idx : gCache.camRelFixups) { - const ToMtxData& c = currToMtxs[idx]; - MtxF& out = replacements[reinterpret_cast(c.dst)]; - std::memcpy(out.mf, c.src, sizeof(out.mf)); - for (int k = 0; k < 3; k++) { - out.mf[3][k] += w * gCache.cameraDelta[k]; - } - } - for (const PairedToMtx& pair : gCache.pairedToMtxs) { const ToMtxData& c = currToMtxs[pair.currIdx]; const ToMtxData& p = prevToMtxs[pair.prevIdx]; @@ -883,10 +705,12 @@ void FrameInterpolation_Interpolate(float t, std::unordered_map& rep } } + // Even unpaired sprites need a per-sub-frame matrix rebuild because + // their billboard rotations follow the lerped projection. for (const PairedSprite& pair : gCache.pairedSprites) { const SpriteDrawData& c = currSpritesData[pair.currIdx]; SpriteDrawData L = c; - if (pair.prevIdx != UINT32_MAX && !pair.snap) { + if (pair.prevIdx != UINT32_MAX) { const SpriteDrawData& p = prevSpritesData[pair.prevIdx]; for (int k = 0; k < 3; k++) { L.camRelPos[k] = w * p.camRelPos[k] + t * c.camRelPos[k]; @@ -902,21 +726,23 @@ void FrameInterpolation_Interpolate(float t, std::unordered_map& rep emitSprite(L, replacements); } - const std::vector& prevProj = gRenderPrev->projRots; - const std::vector& currProj = gRenderCurr->projRots; - for (const PairedProjRot& pair : gCache.pairedProjRots) { - const CameraProjRotData& c = currProj[pair.currIdx]; - const CameraProjRotData& p = prevProj[pair.prevIdx]; - auto emitProj = [&](void* dst, float deg, float ax, float ay, float az) { - if (dst == nullptr) { - return; - } - MtxF& out = replacements[reinterpret_cast(dst)]; - guRotateF(out.mf, deg, ax, ay, az); - }; - // Axis conventions per viewport.c: roll about -Z, pitch +X, yaw +Y. - emitProj(c.rollMtx, lerpAngleDegSP(p.rollDeg, c.rollDeg, t), 0.0f, 0.0f, -1.0f); - emitProj(c.pitchMtx, lerpAngleDegSP(p.pitchDeg, c.pitchDeg, t), 1.0f, 0.0f, 0.0f); - emitProj(c.yawMtx, lerpAngleDegSP(p.yawDeg, c.yawDeg, t), 0.0f, 1.0f, 0.0f); + const std::vector& prevProj = gPrevious->projRots; + const std::vector& currProj = gCurrent->projRots; + if (prevProj.size() == currProj.size()) { + for (size_t i = 0; i < currProj.size(); i++) { + const CameraProjRotData& p = prevProj[i]; + const CameraProjRotData& c = currProj[i]; + auto emitProj = [&](void* dst, float deg, float ax, float ay, float az) { + if (dst == nullptr) { + return; + } + MtxF& out = replacements[reinterpret_cast(dst)]; + guRotateF(out.mf, deg, ax, ay, az); + }; + // Axes match viewport.c: roll Z-, pitch X+, yaw Y+. + emitProj(c.rollMtx, lerpAngleDegSP(p.rollDeg, c.rollDeg, t), 0.0f, 0.0f, -1.0f); + emitProj(c.pitchMtx, lerpAngleDegSP(p.pitchDeg, c.pitchDeg, t), 1.0f, 0.0f, 0.0f); + emitProj(c.yawMtx, lerpAngleDegSP(p.yawDeg, c.yawDeg, t), 0.0f, 1.0f, 0.0f); + } } } diff --git a/src/port/Interpolation/FrameInterpolation.h b/src/port/Interpolation/FrameInterpolation.h index d462bb3a6..44d05a9bf 100644 --- a/src/port/Interpolation/FrameInterpolation.h +++ b/src/port/Interpolation/FrameInterpolation.h @@ -21,17 +21,10 @@ void FrameInterpolation_StartRecord(void); void FrameInterpolation_StopRecord(void); void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate); -// Which pair of recorded ticks a render pass blends between. The threaded -// path captures the pair when a display list is submitted and applies it when -// that list renders; the single-threaded path uses the live variant. -void FrameInterpolation_GetRecordingPair(int* prevSlot, int* currSlot, bool* shouldInterpolate); -void FrameInterpolation_ClaimPair(int prevSlot, int currSlot); -void FrameInterpolation_ReleasePair(int prevSlot, int currSlot); -void FrameInterpolation_BeginRenderPass(int prevSlot, int currSlot, bool shouldInterpolate); - // Hierarchical scope (cross-tick pairing identity). void FrameInterpolation_RecordOpenChild(const void* key, uintptr_t id); void FrameInterpolation_RecordCloseChild(void); +void FrameInterpolation_RecordMarker(const char* file, int line); // Mix three scalar fields into a stable scope id when no single field is // unique on its own (e.g. modelId+pos, particle spawn randomness). @@ -45,7 +38,15 @@ static inline uint64_t FrameInterpolation_FloatBits(float f) { return (uint64_t)u; } -// Final matrix output of a mlMtxApply — the only matrix event replay needs. +// Low-level matrix primitives (from src/core1/math/matrix_stack.c). +void FrameInterpolation_RecordMatrixIdent(void); +void FrameInterpolation_RecordMatrixTranslate(float x, float y, float z); +void FrameInterpolation_RecordMatrixRotYaw(float degrees); +void FrameInterpolation_RecordMatrixRotPitch(float degrees); +void FrameInterpolation_RecordMatrixRotRoll(float degrees); +void FrameInterpolation_RecordMatrixScale(float x, float y, float z); +void FrameInterpolation_RecordMatrixSet(const float src[4][4]); +void FrameInterpolation_RecordMatrixMult(const float l[4][4], const float r[4][4]); void FrameInterpolation_RecordMatrixToMtx(void* dst, const float src[4][4]); // BK puts camera rotation in projection, not modelview. We record the @@ -66,10 +67,6 @@ void FrameInterpolation_RecordCameraPosition(const float pos[3]); void FrameInterpolation_NoInterpolatePush(void); void FrameInterpolation_NoInterpolatePop(void); -// Like NoInterpolatePush, but keeps the camera half of the transform live. -void FrameInterpolation_CameraRelativePush(void); -void FrameInterpolation_CameraRelativePop(void); - // kind matches the three sprite paths in sprite/render.c: // BILLBOARD — func_80344138. camYaw/camPitch, no spriteRoll. // BILLBOARD_ROLL — func_80344424. camYaw/camPitch + spriteRoll forward. @@ -83,9 +80,6 @@ void FrameInterpolation_RecordSpriteDraw(int kind, void* dst, const float camRel float camYaw, float camPitch, float spriteRoll, const float rotation[3], int mirrored); -void FrameInterpolation_RecordAnimVertices(void* dst, const void* vertices, int32_t count); -void FrameInterpolation_ApplyAnimVertices(float t); - // Drop the prev tree at known camera cuts (map load, camera type change). void FrameInterpolation_DontInterpolateCamera(void); diff --git a/src/port/LaunchArgs.cpp b/src/port/LaunchArgs.cpp deleted file mode 100644 index 33c8c817d..000000000 --- a/src/port/LaunchArgs.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "LaunchArgs.h" - -#include -#include - -#include -#include - -#include "UI/LighthouseModMenuWindow.h" -#include "UI/cvar_prefixes.h" - -namespace Lighthouse { - -namespace { - -// Romhack requested via `-hack `; empty when the flag was not passed. -std::string sLaunchHack; - -// Persisted mod selection captured before the override, so it can be restored. -std::string sSavedEnabledMods; -std::string sSavedDisabledMods; -bool sLaunchHackApplied = false; - -// Everything here runs before context->InitLogging(), so diagnostics are buffered -// and emitted by FlushLaunchHackLog() once the logger is live. -std::string sLaunchHackLog; -bool sLaunchHackLogIsError = false; - -void SetLaunchHackLog(bool isError, std::string message) { - sLaunchHackLog = std::move(message); - sLaunchHackLogIsError = isError; -} - -} // namespace - -bool IsLaunchHackFlag(const std::string& arg, std::string& outInlineValue, bool& outTakesValue) { - static const char* kFlags[] = { "-hack", "--hack", "-romhack", "--romhack" }; - for (const char* flag : kFlags) { - if (arg == flag) { - outTakesValue = true; - return true; - } - const std::string prefix = std::string(flag) + "="; - if (arg.rfind(prefix, 0) == 0) { - outInlineValue = arg.substr(prefix.size()); - outTakesValue = false; - return true; - } - } - return false; -} - -void ParseLaunchArgs(int argc, char* argv[]) { - for (int i = 1; i < argc; i++) { - std::string arg = argv[i]; - std::string inlineValue; - bool takesValue = false; - if (!IsLaunchHackFlag(arg, inlineValue, takesValue)) { - continue; - } - if (takesValue) { - if (i + 1 < argc) { - sLaunchHack = argv[++i]; - } else { - SetLaunchHackLog(true, "[Launch] " + arg + " requires a romhack name"); - } - } else { - sLaunchHack = inlineValue; - } - } -} - -void ApplyLaunchHack() { - if (sLaunchHack.empty()) { - return; - } - - // Only strip the extension when it is actually ".o2r", so a hack whose stem - // contains a dot ("my.hack") still resolves when named without the suffix. - const std::filesystem::path requested(sLaunchHack); - const std::string wanted = StringHelper::IEquals(requested.extension().string(), ".o2r") - ? requested.stem().generic_string() - : requested.filename().generic_string(); - - const std::string modsPath = Ship::Context::GetPathRelativeToAppDirectory("mods"); - if (modsPath.empty() || !std::filesystem::is_directory(modsPath)) { - SetLaunchHackLog(true, "[Launch] -hack '" + sLaunchHack + "': no mods directory to search"); - return; - } - - std::string resolved; - std::string available; - std::error_code ec; - for (const auto& entry : std::filesystem::recursive_directory_iterator( - modsPath, std::filesystem::directory_options::follow_directory_symlink, ec)) { - if (entry.is_directory() || !StringHelper::IEquals(entry.path().extension().string(), ".o2r")) { - continue; - } - const std::string stem = entry.path().stem().generic_string(); - if (!available.empty()) { - available += ", "; - } - available += stem; - if (StringHelper::IEquals(stem, wanted)) { - resolved = stem; - } - } - - if (resolved.empty()) { - SetLaunchHackLog(true, "[Launch] -hack '" + sLaunchHack + "': no matching .o2r under mods/. Available: " + - (available.empty() ? std::string("(none)") : available)); - return; - } - - // Snapshot before overriding so RestoreModSelectionAfterLaunchHack() can put - // the user's own selection back once the archives are loaded. - sSavedEnabledMods = CVarGetString(CVAR_SETTING("EnabledMods"), ""); - sSavedDisabledMods = CVarGetString(CVAR_SETTING("DisabledMods"), ""); - sLaunchHackApplied = true; - - // Validates that the match actually carries an aGameConfig, and disables any - // other overlay so the boot-time conflict check does not quarantine them. - SetLaunchHackLog(false, "[Launch] -hack '" + sLaunchHack + "': enabling romhack overlay '" + resolved + "'"); - SetSoleEnabledRomhack(resolved); -} - -void RestoreModSelectionAfterLaunchHack() { - if (!sLaunchHackApplied) { - return; - } - CVarSetString(CVAR_SETTING("EnabledMods"), sSavedEnabledMods.c_str()); - CVarSetString(CVAR_SETTING("DisabledMods"), sSavedDisabledMods.c_str()); - Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); -} - -void FlushLaunchHackLog() { - if (sLaunchHackLog.empty()) { - return; - } - if (sLaunchHackLogIsError) { - SPDLOG_ERROR("{}", sLaunchHackLog); - } else { - SPDLOG_INFO("{}", sLaunchHackLog); - } - sLaunchHackLog.clear(); -} - -} // namespace Lighthouse diff --git a/src/port/LaunchArgs.h b/src/port/LaunchArgs.h deleted file mode 100644 index 3277382fd..000000000 --- a/src/port/LaunchArgs.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -namespace Lighthouse { - -void ParseLaunchArgs(int argc, char* argv[]); -bool IsLaunchHackFlag(const std::string& arg, std::string& outInlineValue, bool& outTakesValue); -void ApplyLaunchHack(); -void RestoreModSelectionAfterLaunchHack(); -void FlushLaunchHackLog(); - -} // namespace Lighthouse diff --git a/src/port/Localization/Language.cpp b/src/port/Localization/Language.cpp index 85c2a3ef6..4318c10e6 100644 --- a/src/port/Localization/Language.cpp +++ b/src/port/Localization/Language.cpp @@ -8,7 +8,6 @@ #include #include -#include #include "libultraship/libultraship.h" #include "ship/Context.h" @@ -139,61 +138,6 @@ bool ArchiveHasAssetHex(Ship::Archive* archive, uint32_t hex) { return false; } -bool IsLocalizedText(const std::string& path) { - return path.find("/dialog/") != std::string::npos || path.find("/quizq/") != std::string::npos || - path.find("/gruntyq/") != std::string::npos; -} - -bool EntryStamp(zip_t* z, const std::string& entryPath, uint32_t& outCrc, uint64_t& outSize) { - zip_stat_t st; - zip_stat_init(&st); - if (zip_stat(z, entryPath.c_str(), 0, &st) != 0 || !(st.valid & ZIP_STAT_CRC) || !(st.valid & ZIP_STAT_SIZE)) { - return false; - } - outCrc = static_cast(st.crc); - outSize = static_cast(st.size); - return true; -} - -size_t DropUnchangedOverrides(const std::string& packArchivePath, - std::unordered_map& overrides) { - const std::string basePath = BaseArchivePath(); - if (basePath.empty() || packArchivePath.empty()) { - return 0; - } - zip_t* packZip = zip_open(packArchivePath.c_str(), ZIP_RDONLY, nullptr); - if (packZip == nullptr) { - return 0; // a folder-based archive, not a zip: no cheap stamp to compare - } - zip_t* baseZip = zip_open(basePath.c_str(), ZIP_RDONLY, nullptr); - if (baseZip == nullptr) { - zip_close(packZip); - return 0; - } - - size_t dropped = 0; - for (auto it = overrides.begin(); it != overrides.end();) { - if (IsLocalizedText(it->second)) { - ++it; - continue; - } - uint32_t packCrc = 0, baseCrc = 0; - uint64_t packSize = 0, baseSize = 0; - const std::string baseEntry = ResourceHelpers_GetBaseAssetPath(it->first); - if (baseEntry.empty() || !EntryStamp(packZip, it->second, packCrc, packSize) || - !EntryStamp(baseZip, baseEntry, baseCrc, baseSize) || packCrc != baseCrc || packSize != baseSize) { - ++it; - continue; - } - it = overrides.erase(it); - dropped++; - } - - zip_close(baseZip); - zip_close(packZip); - return dropped; -} - const LanguageEntry* FindLanguage(const std::string& name) { for (const auto& e : sLanguages) { if (e.name == name) { @@ -277,14 +221,8 @@ void SetActiveLanguage(const std::string& name) { std::unordered_map dialogOverride; if (entry->source != nullptr) { - // The pack's assets are numbered for the ROM it was extracted from, so they have - // to be translated into the base's v1.0 id space before they can override anything. - const uint32_t rawVersion = static_cast(entry->source->GetGameVersion()); - BKVersion packVersion = BK_VER_US_10; - const bool classified = ClassifyArchiveVersion(rawVersion, packVersion); - const std::unordered_map* remap = nullptr; - switch (packVersion) { + switch (static_cast(entry->source->GetGameVersion())) { case BK_VER_US_11: remap = &sV10toV11Remap; break; @@ -294,20 +232,9 @@ void SetActiveLanguage(const std::string& name) { case BK_VER_JP: remap = &sV10toJPRemap; break; - case BK_VER_US_10: default: break; // pack ids already match v1.0 } - - // Without a recognised stamp there is no way to know which id space the pack is in. - // Installing its assets under their own ids would drop them onto whatever v1.0 asset - // happens to share the number, so leave the language alone instead. - if (!classified) { - SPDLOG_ERROR("[Lang] '{}': pack version stamp {:#010x} matches no known ROM; refusing to apply it " - "(its asset ids cannot be translated to the base game's).", - name, rawVersion); - return; - } std::unordered_map inverse; if (remap != nullptr) { for (const auto& [v10Id, targetId] : *remap) { @@ -336,23 +263,16 @@ void SetActiveLanguage(const std::string& name) { } else if (auto it = inverse.find(packId); it != inverse.end()) { v10Id = it->second; } else { - // Nothing to translate: the asset has no v1.0 counterpart (the JP-only - // font and friends, which the port asks for by their pack id). v10Id = packId; } dialogOverride[v10Id] = path; } - - if (const size_t dropped = DropUnchangedOverrides(entry->source->GetPath(), dialogOverride); dropped > 0) { - SPDLOG_INFO("[Lang] '{}': {} pack asset(s) are identical to the base game and were left un-repointed", name, - dropped); - } } // Hand the computed language to the resource layer const size_t repointed = dialogOverride.size(); ResourceHelpers_ApplyLanguage(std::move(dialogOverride), entry->script == SCRIPT_JP, entry->count, entry->index); - SPDLOG_INFO("[Lang] Active language '{}'", name, repointed); + SPDLOG_INFO("[Lang] Active language '{}' ({} ids re-pointed)", name, repointed); } void RescanLanguages() { diff --git a/src/port/Localization/Localization.cpp b/src/port/Localization/Localization.cpp index 0e0fde746..d5a738d64 100644 --- a/src/port/Localization/Localization.cpp +++ b/src/port/Localization/Localization.cpp @@ -6,14 +6,20 @@ #include #include #include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Patches/Patches.h" -#include "port/ResourceHelpers.h" #include "port/ShipInit.hpp" #include "port/UI/cvar_prefixes.h" typedef unsigned char u8; extern "C" { +int ResourceMgr_IsJapanese(void); +int ResourceMgr_GetDialogLanguageCount(void); // 1 = US, 3 = PAL (EN/FR/DE) +int ResourceMgr_GetDialogLanguage(void); // PAL only: 0=English, 1=French, 2=German +int ResourceMgr_GetLanguageGeneration(void); +int ResourceMgr_IsAssetRepointed(uint32_t assetId); +const char* ResourceMgr_GetLangString(const char* english); // active pack's translation, or the key itself +int ResourceMgr_HasLangStrings(void); // active language is a pack carrying UI overrides + bool gameFile_isNotEmpty(int gamenum); int jiggyscore_total(void); int itemscore_noteScores_getTotal(void); @@ -31,14 +37,15 @@ int code94620_func_8031B5B0(void); // current dialog-language index (0 int func_8031877C(void* zoombox); // clear a zoombox's strings before re-setting // Print font internals -extern void* print_sFontSpriteAssets[]; // BKSprite*[5]: font alphamask assets (slot 2 = JP font) -extern void* print_sFonts[]; // FontLetter*[4]: decoded glyph tables per slot +extern void* D_80380AB8[]; // BKSprite*[5]: font alphamask assets (slot 2 = JP font) +extern void* print_sFonts[]; // FontLetter*[4]: decoded glyph tables per slot void* print_getLettersFromFont(void* alphaMask, void* textureSprite); int print_getCurrentMapBoldFontTexture(void); void print_setBoldFontTexture(int textureId); void* assetcache_get(int assetId); void assetcache_release(void* ptr); void bk_free(void* ptr); +void port_refreshDialogFontGlyphCount(void); } // Live language change reactions @@ -58,39 +65,37 @@ void FreeJpFontSlot() { bk_free(print_sFonts[2]); print_sFonts[2] = nullptr; } - if (print_sFontSpriteAssets[2] != nullptr) { - assetcache_release(print_sFontSpriteAssets[2]); - print_sFontSpriteAssets[2] = nullptr; + if (D_80380AB8[2] != nullptr) { + assetcache_release(D_80380AB8[2]); + D_80380AB8[2] = nullptr; } } void LoadJpFontSlot() { // Bail early if print_init hasn't run to load this slot yet - if (print_sFontSpriteAssets[0] == nullptr) { + if (D_80380AB8[0] == nullptr) { return; } FreeJpFontSlot(); // drop any stale font first (e.g. a different pack) void* tex = assetcache_get(print_getCurrentMapBoldFontTexture()); - print_sFontSpriteAssets[2] = assetcache_get(kJpDialogFontAssetId); - print_sFonts[2] = print_getLettersFromFont(print_sFontSpriteAssets[2], tex); + D_80380AB8[2] = assetcache_get(kJpDialogFontAssetId); + print_sFonts[2] = print_getLettersFromFont(D_80380AB8[2], tex); assetcache_release(tex); } // Re-decode the base dialog font (slot 0) from its current asset. void ReloadDialogFontSlot() { - if (print_sFontSpriteAssets[0] == nullptr) { + if (D_80380AB8[0] == nullptr) { return; // print_init hasn't run yet } void* tex = assetcache_get(print_getCurrentMapBoldFontTexture()); - assetcache_release(print_sFontSpriteAssets[0]); - print_sFontSpriteAssets[0] = assetcache_get(kDialogFontAssetId); + assetcache_release(D_80380AB8[0]); + D_80380AB8[0] = assetcache_get(kDialogFontAssetId); bk_free(print_sFonts[0]); - print_sFonts[0] = print_getLettersFromFont(print_sFontSpriteAssets[0], tex); + print_sFonts[0] = print_getLettersFromFont(D_80380AB8[0], tex); assetcache_release(tex); // A pack may ship an extended dialog font; refresh the reachable glyph count to match. port_refreshDialogFontGlyphCount(); - // Build cross-revision-corrected HD glyph textures for the current base (no-op without a pack). - port_dialogFontHd_rebuild(); } // Per cached-model-slot generation @@ -512,7 +517,8 @@ static void buildPalJpParades() { // present in the active language (sDialogOverride) rather than on the base version. static constexpr uint32_t kMotzandParadeCreditId = 0x11CA; static bool port_useMotzandParade() { - return ResourceMgr_IsJapanese() || ResourceMgr_IsPal() || ResourceMgr_IsAssetRepointed(kMotzandParadeCreditId) != 0; + return ResourceMgr_IsJapanese() || ResourceMgr_GetDialogLanguageCount() > 1 || + ResourceMgr_IsAssetRepointed(kMotzandParadeCreditId) != 0; } // Swap the active parade table for the Motzand variant. @@ -555,7 +561,7 @@ static void RegisterLocalizedText() { if (ResourceMgr_IsJapanese()) { sJpFontFreeDelay = 0; // cancel a pending free; ensure slot 2 is current LoadJpFontSlot(); - } else if (print_sFontSpriteAssets[2] != nullptr) { + } else if (D_80380AB8[2] != nullptr) { sJpFontFreeDelay = kJpFontFreeDelayFrames; } bool fontOverridden = ResourceMgr_IsAssetRepointed(kDialogFontAssetId) != 0; @@ -579,7 +585,7 @@ static void RegisterLocalizedText() { // frame instead of letting the draw dereference a NULL slot. REGISTER_LISTENER(ResolveBoldFontSlot, EVENT_PRIORITY_NORMAL, [](IEvent* event) { auto* ev = (ResolveBoldFontSlot*)event; - if (print_sFontSpriteAssets[*ev->slot] == nullptr) { + if (D_80380AB8[*ev->slot] == nullptr) { *ev->slot = 0; *ev->letterId = 0; } diff --git a/src/port/Nametag/Nametag.cpp b/src/port/Nametag/Nametag.cpp index 3c0a52518..116777e54 100644 --- a/src/port/Nametag/Nametag.cpp +++ b/src/port/Nametag/Nametag.cpp @@ -2,9 +2,7 @@ #include #include -#include #include -#include #include #include @@ -31,61 +29,16 @@ constexpr float kBorderThickness = 1.5f; constexpr float kGameAspect = 4.0f / 3.0f; constexpr float kLowResAspect = 320.0f / 240.0f; -// Distance over which a tag fades out as it reaches the edge of its range. -constexpr float kFadeBand = 500.0f; -constexpr float kMaxFadeShare = 0.25f; - struct Entry { - uint32_t id; - float screen[2]; - bool onScreen; - float alpha; + float pos[3]; std::string text; }; -ImU32 WithAlpha(ImU32 color, float alpha) { - const float scaled = (float)((color >> IM_COL32_A_SHIFT) & 0xFF) * alpha; - const ImU32 value = (ImU32)(scaled < 0.0f ? 0.0f : (scaled > 255.0f ? 255.0f : scaled)); - return (color & ~IM_COL32_A_MASK) | (value << IM_COL32_A_SHIFT); -} - -// Game thread only. -std::vector sRecording; -bool sRecordingStale = false; - -void RetireRecording() { - sRecording.clear(); -} - -struct FrameTags { - uint64_t serial; - std::vector entries; -}; -std::mutex sHandoffMutex; -std::unordered_map sHandoff; -uint64_t sHandoffSerial = 0; -constexpr uint64_t kHandoffStaleAfter = 8; - -// Render thread only. -std::vector sRenderCurr; -std::vector sRenderPrev; -bool sRenderInterpolate = false; -float sSubframeBlend = 1.0f; - +std::vector sQueue; Nametag::ProjectFn sProject = nullptr; -Nametag::DistanceFn sDistance = nullptr; const int* sFbWidth = nullptr; const int* sFbHeight = nullptr; -const Entry* FindPrevious(uint32_t id) { - for (const auto& entry : sRenderPrev) { - if (entry.id == id) { - return &entry; - } - } - return nullptr; -} - // Mirrors LUS Gui::GetIntegerScaleFactor; mGameWindowViewport lags one // frame, matching DrawGame's own read order. int16_t ComputeIntegerScaleFactor(const std::shared_ptr& interp) { @@ -221,28 +174,19 @@ class NametagOverlay : public Ship::GuiWindow { const float scaleY = contentH / static_cast(*sFbHeight); ImDrawList* drawList = ImGui::GetForegroundDrawList(); - for (const auto& entry : sRenderCurr) { - if (!entry.onScreen) { - continue; + for (const auto& entry : sQueue) { + float pos[3] = { entry.pos[0], entry.pos[1], entry.pos[2] }; + float screen[2]; + if (sProject(pos, screen)) { + ImVec2 textSize = ImGui::CalcTextSize(entry.text.c_str()); + ImVec2 anchor(originX + screen[0] * scaleX, originY + screen[1] * scaleY); + ImVec2 textTL(anchor.x - textSize.x * 0.5f, anchor.y - textSize.y * 0.5f); + ImVec2 boxTL(textTL.x - kPaddingX, textTL.y - kPaddingY); + ImVec2 boxBR(textTL.x + textSize.x + kPaddingX, textTL.y + textSize.y + kPaddingY); + drawList->AddRectFilled(boxTL, boxBR, kBgColor, kCornerRadius); + drawList->AddRect(boxTL, boxBR, kBorderColor, kCornerRadius, 0, kBorderThickness); + drawList->AddText(textTL, kTextColor, entry.text.c_str()); } - float screenX = entry.screen[0]; - float screenY = entry.screen[1]; - float alpha = entry.alpha; - const Entry* previous = sRenderInterpolate ? FindPrevious(entry.id) : nullptr; - if (previous != nullptr && previous->onScreen) { - screenX = previous->screen[0] + (screenX - previous->screen[0]) * sSubframeBlend; - screenY = previous->screen[1] + (screenY - previous->screen[1]) * sSubframeBlend; - alpha = previous->alpha + (alpha - previous->alpha) * sSubframeBlend; - } - - ImVec2 textSize = ImGui::CalcTextSize(entry.text.c_str()); - ImVec2 anchor(originX + screenX * scaleX, originY + screenY * scaleY); - ImVec2 textTL(anchor.x - textSize.x * 0.5f, anchor.y - textSize.y * 0.5f); - ImVec2 boxTL(textTL.x - kPaddingX, textTL.y - kPaddingY); - ImVec2 boxBR(textTL.x + textSize.x + kPaddingX, textTL.y + textSize.y + kPaddingY); - drawList->AddRectFilled(boxTL, boxBR, WithAlpha(kBgColor, alpha), kCornerRadius); - drawList->AddRect(boxTL, boxBR, WithAlpha(kBorderColor, alpha), kCornerRadius, 0, kBorderThickness); - drawList->AddText(textTL, WithAlpha(kTextColor, alpha), entry.text.c_str()); } } }; @@ -255,10 +199,6 @@ void SetProjectFn(ProjectFn fn) { sProject = fn; } -void SetDistanceFn(DistanceFn fn) { - sDistance = fn; -} - void SetNativeFramebufferSize(const int* width, const int* height) { sFbWidth = width; sFbHeight = height; @@ -271,88 +211,20 @@ void RegisterOverlay() { overlay->Show(); } -void BeginDraw() { - if (sRecordingStale) { - RetireRecording(); - } - sRecordingStale = true; +void Clear() { + sQueue.clear(); } -void Push(uint32_t id, float x, float y, float z, const char* label, float alpha) { - if (label == nullptr || alpha <= 0.0f || sProject == nullptr) { +void Push(float x, float y, float z, const char* label) { + if (label == nullptr) { return; } - if (sRecordingStale) { - RetireRecording(); - sRecordingStale = false; - } Entry entry; - entry.id = id; - float pos[3] = { x, y, z }; - entry.onScreen = sProject(pos, entry.screen); - entry.alpha = alpha > 1.0f ? 1.0f : alpha; + entry.pos[0] = x; + entry.pos[1] = y; + entry.pos[2] = z; entry.text = label; - sRecording.push_back(std::move(entry)); -} - -// Game thread. A list is submitted while its tick is still recording, so the -// tags travel with the task the same way the interpolation pair does. -void SubmitFrame(const void* key) { - std::lock_guard lock(sHandoffMutex); - const uint64_t serial = ++sHandoffSerial; - auto [it, inserted] = sHandoff.emplace(key, FrameTags{ serial, sRecording }); - if (!inserted) { - it->second.serial = serial; - it->second.entries = sRecording; - } - - // Anything still here after a full trip round the ring will never be picked - // up by a render pass, so drop it rather than grow the map forever. - for (auto stale = sHandoff.begin(); stale != sHandoff.end();) { - if (stale->second.serial + kHandoffStaleAfter < serial) { - stale = sHandoff.erase(stale); - } else { - ++stale; - } - } -} - -// Render thread. Adopt the tags submitted with this list; what the previous -// pass drew stays behind as the interpolation source. -void BeginRenderPass(const void* key, bool interpolate) { - std::vector tags; - { - std::lock_guard lock(sHandoffMutex); - auto it = sHandoff.find(key); - if (it != sHandoff.end()) { - tags = std::move(it->second.entries); - sHandoff.erase(it); - } - } - sRenderPrev = std::move(sRenderCurr); - sRenderCurr = std::move(tags); - sRenderInterpolate = interpolate; -} - -float FadeForDistance(float x, float y, float z, float maxDistance) { - if (sDistance == nullptr) { - return 1.0f; - } - float pos[3] = { x, y, z }; - const float distance = sDistance(pos); - if (distance >= maxDistance) { - return 0.0f; - } - const float band = std::min(kFadeBand, maxDistance * kMaxFadeShare); - const float fadeStart = maxDistance - band; - if (distance <= fadeStart || band <= 0.0f) { - return 1.0f; - } - return (maxDistance - distance) / band; -} - -void SetSubframeBlend(float blend) { - sSubframeBlend = blend < 0.0f ? 0.0f : (blend > 1.0f ? 1.0f : blend); + sQueue.push_back(std::move(entry)); } } // namespace Nametag \ No newline at end of file diff --git a/src/port/Nametag/Nametag.h b/src/port/Nametag/Nametag.h index 32a767787..478fde36a 100644 --- a/src/port/Nametag/Nametag.h +++ b/src/port/Nametag/Nametag.h @@ -10,17 +10,12 @@ namespace Nametag { // World -> native-framebuffer-pixel projector. Writes (screen[0], screen[1]) // and returns true if the point is in front of the camera. using ProjectFn = bool (*)(float pos[3], float* screen); -using DistanceFn = float (*)(float pos[3]); void SetProjectFn(ProjectFn fn); -void SetDistanceFn(DistanceFn fn); void SetNativeFramebufferSize(const int* width, const int* height); void RegisterOverlay(); -void BeginDraw(); -void Push(uint32_t id, float x, float y, float z, const char* label, float alpha = 1.0f); -float FadeForDistance(float x, float y, float z, float maxDistance); -void SetSubframeBlend(float blend); -void SubmitFrame(const void* key); -void BeginRenderPass(const void* key, bool interpolate); + +void Clear(); +void Push(float x, float y, float z, const char* label); } // namespace Nametag \ No newline at end of file diff --git a/src/port/Nametag/NametagBindings.cpp b/src/port/Nametag/NametagBindings.cpp index c3fb481ce..88220be18 100644 --- a/src/port/Nametag/NametagBindings.cpp +++ b/src/port/Nametag/NametagBindings.cpp @@ -1,13 +1,16 @@ -// BK-specific bindings for the portable Nametag overlay: projection, distance, -// FB dimensions, and the per-draw tick listener. +// BK-specific bindings for the portable Nametag overlay: projection, FB +// dimensions, tick-event listeners, and the asset-id -> label table. #include #include "Nametag.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +#include "port/UI/cvar_prefixes.h" +#include "port/ObjectExtension/ObjectExtension.h" extern "C" { +#include "enums.h" #include "core1/viewport.h" extern int gFramebufferWidth; extern int gFramebufferHeight; @@ -15,9 +18,41 @@ extern int gFramebufferHeight; namespace { +struct NametagTableEntry { + int32_t assetId; + const char* label; + float yOffset; +}; + +// Asset-id -> nametag lookup. Shared across the actor / prop / sprite-prop paths. +constexpr NametagTableEntry sNametagTable[] = { + { ASSET_350_MODEL_TERMITE, "Termite", 150.0f }, { ASSET_3C5_MODEL_GRUBLIN, "Grublin", 150.0f }, + { ASSET_353_MODEL_BIGBUTT, "BigButt", 150.0f }, { ASSET_3C0_MODEL_JINJO_BLUE, "Blue Jinjo", 150.0f }, + { ASSET_3C2_MODEL_JINJO_GREEN, "Green Jinjo", 150.0f }, { ASSET_3BC_MODEL_JINJO_ORANGE, "Orange Jinjo", 150.0f }, + { ASSET_3C1_MODEL_JINJO_PINK, "Pink Jinjo", 150.0f }, { ASSET_3BB_MODEL_JINJO_YELLOW, "Yellow Jinjo", 150.0f }, + { ASSET_6D6_SPRITE_MUSIC_NOTE, "Note", 80.0f }, { ASSET_41A_SPRITE_MUMBO_TOKEN, "Mumbo Token", 80.0f }, +}; + +const NametagTableEntry* LookupNametag(int32_t assetId) { + for (const auto& entry : sNametagTable) { + if (entry.assetId == assetId) { + return &entry; + } + } + return nullptr; +} + +static bool inRange(float x, float y, float z) { + float pos[3] = { x, y, z }; + return viewport_getDistance(pos) < CVarGetFloat(CVAR_DEVELOPER_TOOLS("NametagDist"), 3000.0f); +} + +static bool inRange(int16_t pos[3]) { + return inRange((float)pos[0], (float)pos[1], (float)pos[2]); +} + void InitNametagBindings() { Nametag::SetProjectFn(&viewport_func_8024E030); - Nametag::SetDistanceFn(&viewport_getDistance); Nametag::SetNativeFramebufferSize(&gFramebufferWidth, &gFramebufferHeight); Nametag::RegisterOverlay(); } @@ -25,9 +60,6 @@ void InitNametagBindings() { } // namespace static RegisterShipInitFunc initNametagBindings(InitNametagBindings, { "BOOT" }); - -// Tags are queued during the world draw, so the queue turns over on OnPlayerDraw rather than -// on the game tick. Ordering against the producers on this event does not matter. static RegisterShipInitFunc init([]() { - REGISTER_LISTENER(OnPlayerDraw, EVENT_PRIORITY_HIGH, [](IEvent* event) { Nametag::BeginDraw(); }); -}); + REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_HIGH, [](IEvent* event) { Nametag::Clear(); }); +}); \ No newline at end of file diff --git a/src/port/Network/Anchor/Anchor.cpp b/src/port/Network/Anchor/Anchor.cpp index 3b515d58d..f33f51ca1 100644 --- a/src/port/Network/Anchor/Anchor.cpp +++ b/src/port/Network/Anchor/Anchor.cpp @@ -1,16 +1,17 @@ #include "Anchor.h" #include "Authority.h" -#include #include #include #include "port/Engine.h" #include "port/Nametag/Nametag.h" #include "port/Interpolation/FrameInterpolation.h" #include "port/ObjectExtension/ObjectExtension.h" -#include "port/Enhancements/Retention/Retention.h" +extern "C" { #include "variables.h" #include "functions.h" +// extern PlayState* gPlayState; +} // MARK: - Overrides @@ -29,15 +30,7 @@ void Anchor::Enable() { Network::Enable(CVarGetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org"), CVarGetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383)); ownClientId = CVarGetInteger(CVAR_REMOTE_ANCHOR("LastClientId"), 0); - roomState = RoomState{}; -} - -bool Anchor::IsGlobalRoom() { - return strcmp(CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), ""), "lh-global") == 0; -} - -bool Anchor::IsWorldSyncActive() { - return isConnected && !IsGlobalRoom() && roomState.syncItemsAndFlags != 0; + roomState.ownerClientId = 0; } void Anchor::Disable() { @@ -52,7 +45,6 @@ void Anchor::Disable() { } } clients.clear(); - PlayerColors_reset(); RefreshClientActors(); } @@ -60,22 +52,14 @@ void Anchor::OnConnected() { SendPacket_Handshake(); RegisterHooks(); - port_noteRetention_setForced(IsGlobalRoom() ? 0 : 1); - port_jinjoRetention_setForced(IsGlobalRoom() ? 0 : 1); - if (IsSaveLoaded()) { SendPacket_RequestTeamState(); - hasRequestedTeamState = true; - reloadMapOnTeamState = true; } } void Anchor::OnDisconnected() { Authority_Reset(); RegisterHooks(); - - port_noteRetention_setForced(0); - port_jinjoRetention_setForced(0); } void Anchor::ProcessOutgoingPackets() { @@ -98,22 +82,11 @@ void Anchor::ProcessOutgoingPackets() { } } -bool Anchor::AllowedWithoutGameSync(const std::string& packetType) { - return packetType == HANDSHAKE || packetType == ALL_CLIENT_STATE || packetType == UPDATE_CLIENT_STATE || - packetType == UPDATE_ROOM_STATE || packetType == MAP_LOAD || packetType == PLAYER_UPDATE || - packetType == PLAYER_UPDATE_FULL || packetType == PLAYER_ANIM || packetType == PLAYER_SUBRANGE || - packetType == PLAYER_TRANSFORM || packetType == PLAYER_SFX || packetType == SERVER_MESSAGE; -} - void Anchor::SendJsonToRemote(nlohmann::json payload) { if (!isConnected) { return; } - if (!roomState.syncItemsAndFlags && !AllowedWithoutGameSync(payload.value("type", std::string()))) { - return; - } - payload["clientId"] = ownClientId; if (!payload.contains("quiet")) { SPDLOG_DEBUG("[Anchor] Queuing payload:\n{}", payload.dump()); @@ -142,12 +115,6 @@ void Anchor::OnIncomingJson(nlohmann::json payload) { std::string packetType = payload["type"].get(); - // Same rule inbound: a peer on an older build must not push world state into a room - // that isn't syncing it. - if (!roomState.syncItemsAndFlags && !AllowedWithoutGameSync(packetType)) { - return; - } - // Ignore packets from mismatched clients, except for ALL_CLIENT_STATE, UPDATE_CLIENT_STATE, and // PLAYER_UPDATE(_FULL) if (packetType != ALL_CLIENT_STATE && packetType != UPDATE_CLIENT_STATE && packetType != PLAYER_UPDATE && @@ -220,40 +187,6 @@ void Anchor::ProcessIncomingPacketQueue() { HandlePacket_SetCheckStatus(payload); else if (packetType == SET_FLAG) HandlePacket_SetFlag(payload); - else if (packetType == ITEM_COUNT) - HandlePacket_SetItemCount(payload); - else if (packetType == SET_ABILITY) - HandlePacket_SetAbility(payload); - else if (packetType == SCOPED_FLAG) - HandlePacket_ScopedFlag(payload); - else if (packetType == REQUEST_SCOPED_STATE) - HandlePacket_RequestScopedState(payload); - else if (packetType == SCOPED_STATE) - HandlePacket_ScopedState(payload); - else if (packetType == COLLECT_ITEM) - HandlePacket_CollectItem(payload); - else if (packetType == CARRY_THROW) - HandlePacket_CarryThrow(payload); - else if (packetType == BREAK_OBJECT) - HandlePacket_BreakObject(payload); - else if (packetType == EGG_TOLL) - HandlePacket_EggToll(payload); - else if (packetType == PUZZLE_STEP) - HandlePacket_PuzzleStep(payload); - else if (packetType == WATER_RISE) - HandlePacket_WaterRise(payload); - else if (packetType == PUZZLE_COUNT) - HandlePacket_PuzzleCount(payload); - else if (packetType == HUT_SMASH) - HandlePacket_HutSmash(payload); - else if (packetType == JIGGY_CRANE) - HandlePacket_JiggyCrane(payload); - else if (packetType == PEDESTAL_OWNER) - HandlePacket_PedestalOwner(payload); - else if (packetType == JIGGY_SPAWN) - HandlePacket_SpawnJiggy(payload); - else if (packetType == HONEYCOMB_SPAWN) - HandlePacket_SpawnHoneycomb(payload); else if (packetType == TELEPORT_TO) HandlePacket_TeleportTo(payload); else if (packetType == UNSET_FLAG) @@ -274,12 +207,6 @@ void Anchor::ProcessIncomingPacketQueue() { HandlePacket_VileHoleState(payload); else if (packetType == VILE_UPDATE) HandlePacket_VileUpdate(payload); - else if (packetType == FIGHT_UPDATE) - HandlePacket_FightUpdate(payload); - else if (packetType == FIGHT_EVENT) - HandlePacket_FightEvent(payload); - else if (packetType == FIGHT_STATE) - HandlePacket_FightState(payload); } catch (const std::exception& e) { SPDLOG_ERROR("[Anchor] Exception while processing incoming packet {}", e.what()); SPDLOG_ERROR("[Anchor] Packet: {}", payload.dump()); @@ -307,67 +234,26 @@ void Anchor::SetDummyPlayerClientId(const Actor* actor, uint32_t clientId) { ObjectExtension::GetInstance().Set(actor, DummyPlayerClientId{ clientId }); } -// Roughly the top of Banjo's head. -static constexpr f32 kNametagHeight = 155.0f; - -// The menu exposes the nametag range as a multiplier of this, the same way Extended Draw -// Distance scales off its own base. -static constexpr f32 kNametagRangeUnit = 3000.0f; - void Anchor::DrawDummies(OnPlayerDraw* event) { if (!isConnected) return; - const bool showNametags = CVarGetInteger(CVAR_REMOTE_ANCHOR("Nametags"), 1) != 0; - const f32 nametagRange = kNametagRangeUnit * CVarGetFloat(CVAR_REMOTE_ANCHOR("NametagScale"), 1.0f); for (const auto& [id, dummy] : dummies) { FrameInterpolation_RecordOpenChild(clients[id].name.c_str(), 0); dummy->Draw(event->gfx, event->mtx, event->vtx); FrameInterpolation_RecordCloseChild(); - - // A nameless client would otherwise get an empty tag box floating over them. - const std::string label = showNametags ? GetNametagLabel(id) : std::string(); - if (dummy->dummy_isVisible() && !label.empty()) { - f32 position[3]; - dummy->dummy_getPosition(position); - position[1] += kNametagHeight; - const f32 fade = Nametag::FadeForDistance(position[0], position[1], position[2], nametagRange); - Nametag::Push(id, position[0], position[1], position[2], label.c_str(), fade); - } } } void Anchor::ClearDummies() { for (auto& [id, dummy] : dummies) { - dummy->dummy_despawnActor(); // skips if already detached by map teardown + dummy->dummy_detachActor(); } dummies.clear(); } -// Presence only: true in any room, including the global one. For dummy-player visuals. -extern "C" s32 port_anchor_isConnected(void) { - Anchor* anchor = Anchor::GetInstance(); - return (anchor != nullptr && anchor->isConnected) ? 1 : 0; -} - -// Lets decomp gate Anchor-only catch-up paths so single player keeps vanilla behaviour. -extern "C" s32 port_anchor_isWorldSyncActive(void) { - Anchor* anchor = Anchor::GetInstance(); - return (anchor != nullptr && anchor->IsWorldSyncActive()) ? 1 : 0; -} - -// actorArray_free tears down actors/markers without firing OnActorDestroy; forget them all. -extern "C" void port_anchorDummies_onActorsFreed(void) { - Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr) { - return; - } - for (auto& [clientId, client] : anchor->clients) { - if (client.dummy != nullptr) { - client.dummy->dummy_detachActor(); - } - } -} - +// Takes the map explicitly rather than reading gsworld_getMap(): during the +// OnMapLoad event the new map hasn't been committed yet, so gsworld_getMap() +// still reports the map being left. void Anchor::PopulateDummies(GameMap map) { for (const auto& [clientId, client] : clients) { if (client.map == map && !client.self && !dummies.contains(clientId) && client.online) { @@ -390,124 +276,25 @@ void Anchor::UpdateDummies() { } void Anchor::OnActorDestroyed(Actor* actor) { - // Stand-in was destroyed externally; forget its marker, dummy stays registered. - if (actor == nullptr || actor->marker == nullptr) { - return; - } - for (auto& [clientId, client] : clients) { - if (client.dummy != nullptr && client.dummy->dummy_getMarker() == actor->marker) { - client.dummy->dummy_detachActor(); - return; - } - } -} - -// Queues the honeycomb spawn the switch press performs. -extern "C" void __baMarker_8028BA00(s32 honeycombId); - -// The GV cactus and RBB boathouse honeycombs only exist once their switch is -// beak-busted: marker.c sets a map flag and spawns the actor. A teammate's press -// reaches us as flag state, so spawn the same actor the local press would have. -void Anchor::RevealSwitchHoneycomb() { - s32 uid; - s32 flag; - - switch (gsworld_getMap()) { - case MAP_12_GV_GOBIS_VALLEY: - uid = HONEYCOMB_B_GV_CACTUS; - flag = 0xD; - break; - case MAP_36_RBB_BOATHOUSE: - uid = HONEYCOMB_F_RBB_BOAT_HOUSE; - flag = 0; - break; - default: - return; - } - - if (!mapSpecificFlags_get(flag) || honeycombscore_get((enum honeycomb_e)uid)) { - return; - } - __baMarker_8028BA00(uid); + // for (auto& [clientId, client] : clients) { + // if (client.dummy != nullptr && client.dummy->getDummyActor() == actor) { + // client.dummy->dummy_detachActor(); + // RemoveDummy(clientId); + // return; + // } + // } } void Anchor::RemoveDummy(uint32_t clientId) { if (dummies.contains(clientId)) { - dummies[clientId]->dummy_despawnActor(); dummies.erase(clientId); } } -extern "C" s32 port_cutsceneWarp_getReturnMap(void); -extern void port_breakable_clearForLevel(int32_t levelId); -extern void port_hutSmash_clearForLevel(int32_t levelId); -extern void port_eggToll_clearForLevel(int32_t levelId); -extern void port_puzzleStep_clearForLevel(int32_t levelId); -extern void port_carriedSync_clearForLevel(int32_t levelId); - -s32 Anchor_LevelOfMap(s32 map) { - if (map <= 0 || map >= MAP_NUM_MAPS) { - return 0; - } - s32 level = (s32)map_getLevel((enum map_e)map); - return (level > 0 && level < 0x20) ? level : 0; -} - -void Anchor::SweepUnoccupiedLevelState(GameMap selfMap) { - // Nothing is shared without world sync, so these stores hold only our own progress — - // dropping them on a level change would undo single-player state. - if (!IsWorldSyncActive()) { - return; - } - - s32 selfLevel = Anchor_LevelOfMap((s32)selfMap); - if (selfLevel == 0 || selfLevel == (s32)LEVEL_D_CUTSCENE || selfMap == MAP_91_FILE_SELECT) { - return; - } - - bool occupied[0x20] = { false }; // level_e ids are small; matches jinjo retention slot count - auto markOccupied = [&occupied](s32 map) { - s32 level = Anchor_LevelOfMap(map); - if (level != 0) { - occupied[level] = true; - } - }; - markOccupied((s32)selfMap); - markOccupied(port_cutsceneWarp_getReturnMap()); - for (auto& [clientId, client] : clients) { - if (!client.self && client.online && client.isSaveLoaded) { - markOccupied((s32)client.map); - markOccupied(client.cutsceneReturnMap); - } - } - for (s32 level = 1; level < 0x20; level++) { - if (!occupied[level]) { - port_breakable_clearForLevel(level); - port_hutSmash_clearForLevel(level); - port_eggToll_clearForLevel(level); - port_puzzleStep_clearForLevel(level); - port_carriedSync_clearForLevel(level); - } - } -} - void Anchor::RegisterDummy(DummyPlayer* dummy, uint32_t clientID) { dummies.emplace(clientID, dummy); } -// Pushes a client's chosen model colours onto their stand-in so the next draw picks them up. -void Anchor::ApplyClientCosmetics(uint32_t clientId) { - if (!clients.contains(clientId)) { - return; - } - AnchorClient& client = clients[clientId]; - if (client.dummy == nullptr) { - return; - } - client.dummy->dummy_setOwner(clientId); - client.dummy->dummy_setColors(client.colors); -} - void Anchor::EvaluateDummyForClient(uint32_t clientId) { if (!clients.contains(clientId)) return; @@ -536,37 +323,23 @@ void Anchor::RefreshClientActors() { } bool Anchor::IsSaveLoaded() { - s32 gameMode = getGameMode(); - if (gameMode == GAME_MODE_6_FILE_PLAYBACK || gameMode == GAME_MODE_7_ATTRACT_DEMO) { - return false; - } auto map = gsworld_getMap(); return map != MAP_1E_CS_START_NINTENDO && map != MAP_1F_CS_START_RAREWARE && map != MAP_91_FILE_SELECT; -} + /* if (gPlayState == nullptr) { + return false; + } -bool Anchor::ShouldShowNotifications() { - return CVarGetInteger(CVAR_REMOTE_ANCHOR("Notifications"), 1) != 0; -} + if (GET_PLAYER(gPlayState) == nullptr) { + return false; + } -// Public global room shows player number instead of custom name -std::string Anchor::GetNametagLabel(uint32_t clientId) { - auto it = clients.find(clientId); - if (it == clients.end()) { - return ""; - } - if (!IsGlobalRoom()) { - return it->second.name; - } - if (it->second.joinOrder == 0) { - return "Player"; - } - return "Player " + std::to_string(it->second.joinOrder); -} + if (gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) { + return false; + } -std::string Anchor::GetClientName(uint32_t clientId) { - auto it = clients.find(clientId); - if (it != clients.end() && !it->second.name.empty()) { - return it->second.name; - } - return "A teammate"; + if (gSaveContext.gameMode != GAMEMODE_NORMAL) { + return false; + }*/ + + // return true; } diff --git a/src/port/Network/Anchor/Anchor.h b/src/port/Network/Anchor/Anchor.h index f70139bd8..5ffbdbcb7 100644 --- a/src/port/Network/Anchor/Anchor.h +++ b/src/port/Network/Anchor/Anchor.h @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include #include "port/Enhancements/Events/Hooks/Events.h" #include "port/Network/Anchor/DummyPlayer.h" @@ -15,41 +13,40 @@ extern "C" { #include "prop.h" #include "variables.h" +//#include "z64.h" } +// void DummyPlayer_Init(Actor* actor, PlayState* play); +// void DummyPlayer_Update(Actor* actor, PlayState* play); +// void DummyPlayer_Draw(Actor* actor, PlayState* play); +// void DummyPlayer_Destroy(Actor* actor, PlayState* play); + typedef struct { uint32_t clientId; std::string name; - BKPlayerColorSet colors; + // Color_RGB8 color; std::string clientVersion; std::string teamId; bool online; bool self; - uint32_t joinOrder; uint32_t seed; bool isSaveLoaded; bool isGameComplete; GameMap map, prevMap; s32 exit, prevExit; - s32 cutsceneReturnMap; DummyPlayer* dummy; } AnchorClient; -struct RoomState { - uint32_t ownerClientId = 0; - u8 pvpMode = 0; // 0 = off, 1 = on, 2 = on with friendly fire - u8 showLocationsMode = 0; // 0 = none, 1 = team, 2 = all - u8 teleportMode = 0; // 0 = off, 1 = team, 2 = all - u8 syncItemsAndFlags = 0; // 0 = off, 1 = on - u8 shareConsumables = 0; // 0 = off, 1 = on — share egg/feather counts in team state - bool isRomhack = false; +typedef struct { + uint32_t ownerClientId; + u8 pvpMode; // 0 = off, 1 = on, 2 = on with friendly fire + u8 showLocationsMode; // 0 = none, 1 = team, 2 = all + u8 teleportMode; // 0 = off, 1 = team, 2 = all + u8 syncItemsAndFlags; // 0 = off, 1 = on + bool isRomhack; std::string romhackName; - bool isRando = false; - int32_t seed = 0; // rando seed id (0 when the room is vanilla) -}; - -bool Anchor_ScopedFlagExcluded(s32 space, s32 index); +} RoomState; class Anchor : public Network { private: @@ -58,15 +55,12 @@ class Anchor : public Network { bool justLoadedSave = false; bool isHandlingUpdateTeamState = false; bool isProcessingIncomingPacket = false; - bool hasRequestedTeamState = false; std::queue incomingPacketQueue; std::mutex incomingPacketQueueMutex; std::queue outgoingPacketQueue; std::mutex outgoingPacketQueueMutex; std::unordered_map dummies; - void FlushPendingJiggySpawns(); - nlohmann::json PrepClientState(); nlohmann::json PrepRoomState(); void RegisterHooks(); @@ -81,7 +75,6 @@ class Anchor : public Network { void RemoveDummy(uint32_t clientId); void EvaluateDummyForClient(uint32_t clientId); - void ApplyClientCosmetics(uint32_t clientId); void HandlePacket_AllClientState(nlohmann::json& payload); void HandlePacket_AuthorityState(nlohmann::json& payload); @@ -101,26 +94,6 @@ class Anchor : public Network { void HandlePacket_ServerMessage(nlohmann::json& payload); void HandlePacket_SetCheckStatus(nlohmann::json& payload); void HandlePacket_SetFlag(nlohmann::json& payload); - void HandlePacket_SetItemCount(nlohmann::json& payload); - void HandlePacket_SetAbility(nlohmann::json& payload); - void HandlePacket_ScopedFlag(nlohmann::json& payload); - void HandlePacket_RequestScopedState(nlohmann::json& payload); - void HandlePacket_ScopedState(nlohmann::json& payload); - void HandlePacket_CollectItem(nlohmann::json& payload); - void HandlePacket_CarryThrow(nlohmann::json& payload); - void HandlePacket_BreakObject(nlohmann::json& payload); - void HandlePacket_EggToll(nlohmann::json& payload); - void HandlePacket_FightEvent(nlohmann::json& payload); - void HandlePacket_FightState(nlohmann::json& payload); - void HandlePacket_FightUpdate(nlohmann::json& payload); - void HandlePacket_PuzzleStep(nlohmann::json& payload); - void HandlePacket_PuzzleCount(nlohmann::json& payload); - void HandlePacket_WaterRise(nlohmann::json& payload); - void HandlePacket_HutSmash(nlohmann::json& payload); - void HandlePacket_JiggyCrane(nlohmann::json& payload); - void HandlePacket_PedestalOwner(nlohmann::json& payload); - void HandlePacket_SpawnJiggy(nlohmann::json& payload); - void HandlePacket_SpawnHoneycomb(nlohmann::json& payload); void HandlePacket_TeleportTo(nlohmann::json& payload); void HandlePacket_UnsetFlag(nlohmann::json& payload); void HandlePacket_UpdateClientState(nlohmann::json& payload); @@ -134,7 +107,6 @@ class Anchor : public Network { public: uint32_t ownClientId; - bool reloadMapOnTeamState = false; inline static const std::string clientVersion = (char*)gGitCommitHash; // Packet types // @@ -158,26 +130,6 @@ class Anchor : public Network { inline static const std::string SERVER_MESSAGE = "SERVER_MESSAGE"; inline static const std::string SET_CHECK_STATUS = "SET_CHECK_STATUS"; inline static const std::string SET_FLAG = "SET_FLAG"; - inline static const std::string ITEM_COUNT = "ITEM_COUNT"; - inline static const std::string SET_ABILITY = "SET_ABILITY"; - inline static const std::string SCOPED_FLAG = "SCOPED_FLAG"; - inline static const std::string REQUEST_SCOPED_STATE = "REQUEST_SCOPED_STATE"; - inline static const std::string SCOPED_STATE = "SCOPED_STATE"; - inline static const std::string COLLECT_ITEM = "COLLECT_ITEM"; - inline static const std::string CARRY_THROW = "CARRY_THROW"; - inline static const std::string BREAK_OBJECT = "BREAK_OBJECT"; - inline static const std::string EGG_TOLL = "EGG_TOLL"; - inline static const std::string FIGHT_EVENT = "FIGHT_EVENT"; - inline static const std::string FIGHT_STATE = "FIGHT_STATE"; - inline static const std::string FIGHT_UPDATE = "FIGHT_UPDATE"; - inline static const std::string PUZZLE_STEP = "PUZZLE_STEP"; - inline static const std::string PUZZLE_COUNT = "PUZZLE_COUNT"; - inline static const std::string WATER_RISE = "WATER_RISE"; - inline static const std::string HUT_SMASH = "HUT_SMASH"; - inline static const std::string JIGGY_CRANE = "JIGGY_CRANE"; - inline static const std::string PEDESTAL_OWNER = "PEDESTAL_OWNER"; - inline static const std::string JIGGY_SPAWN = "JIGGY_SPAWN"; - inline static const std::string HONEYCOMB_SPAWN = "HONEYCOMB_SPAWN"; inline static const std::string TELEPORT_TO = "TELEPORT_TO"; inline static const std::string UNSET_FLAG = "UNSET_FLAG"; inline static const std::string UPDATE_CLIENT_STATE = "UPDATE_CLIENT_STATE"; @@ -191,9 +143,6 @@ class Anchor : public Network { std::map clients; RoomState roomState; - std::string lastWarnedRomhackLabel; - std::string lastWarnedRandoState; - bool hasCheckedRandoCompat = false; void Enable(); void Disable(); @@ -209,24 +158,10 @@ class Anchor : public Network { uint32_t GetDummyPlayerClientId(const Actor* actor); bool GetCurrentMapPlayers(); - bool IsGlobalRoom(); - - // The single gate for every Anchor behaviour that touches the world. A presence-only - // room (the global room, or a private room with "Sync Items & Flags" off) has to play - // exactly like single player, so only dummy players are allowed past this. - bool IsWorldSyncActive(); - - // Presence/position/plumbing packets, the only ones allowed through when the room - // is not syncing game state. Anything absent is treated as world state and dropped - // at the send and receive choke points, so a new packet type is unsynced by default. - static bool AllowedWithoutGameSync(const std::string& packetType); - - void AdoptRemoteCheck(s32 rc); - void CheckRandoRoomCompatibility(); - - bool ShouldShowNotifications(); - std::string GetClientName(uint32_t clientId); - std::string GetNametagLabel(uint32_t clientId); + void PrepDirectionPayload(nlohmann::json& payload); + void PrepTransformationPayload(nlohmann::json& payload); + void PrepAnimStatePayload(nlohmann::json& payload); + void PrepAnimSubRangePayload(nlohmann::json& payload); void SendPacket_AuthorityState(u8 activity, bool claimed); void SendPacket_ClearTeamState(std::string teamId); @@ -245,31 +180,12 @@ class Anchor : public Network { // client (used to hand a late arrival our current state directly). void SendPacket_PlayerTransformChange(Transformation tf_id, uint32_t targetClientId = 0); void SendPacket_PlayerUpdate(bool full = false, uint32_t targetClientId = 0); - void SendPacket_RequestTeamState(bool force = false); - void SendPacket_RequestTeleport(uint32_t clientId); - void SendPacket_SetCheckStatus(s32 rc, s32 map); - void SendPacket_SetFlag(u8 flagSpace, s16 flag); - void SendPacket_SetItemCount(s16 item, s32 count); - void SendPacket_SetAbility(s16 move, u8 value); - void SendPacket_ScopedFlag(u8 space, s16 index, u8 value); - void SendPacket_RequestScopedState(GameMap map); - void SendPacket_CollectItem(u8 kind, s32 id); - void SendPacket_CarryThrow(s32 markerId, f32 start[3], f32 target[3]); - void SendPacket_BreakObject(s16 markerId, s32 x, s32 y, s32 z, s32 map, bool replay = true); - void SendPacket_EggToll(s16 secondaryId, s32 stage, s32 map); - void SendPacket_FightEvent(s32 ev, s32 a, s32 b, const f32 v0[3], const f32 v1[3], const f32 v2[3]); - void SendPacket_FightState(u32 targetClientId); - void SendPacket_FightUpdate(const f32 pos[3], f32 yaw, s32 state, s32 phase, s32 mirror, s32 vuln); - void SendPacket_PuzzleStep(s32 puzzleId, s32 bits, s32 map, s32 phash = 0); - void SendPacket_PuzzleCount(s32 counterId, s32 delta, s32 map); - void SendPacket_WaterRise(s32 map, s32 kind, s32 p1, s32 p2, f32 duration); - void SendPacket_HutSmash(s32 x, s32 y, s32 z, s32 loot, s32 map); - void SendPacket_JiggyCrane(s32 stage); - void SendPacket_PedestalOwner(s32 id, bool claimed); - void SendPacket_SpawnJiggy(s16 jiggyId, f32 x, f32 y, f32 z); - void SendPacket_SpawnHoneycomb(s16 honeycombId, s32 bundleId, f32 x, f32 y, f32 z); - void SendPacket_TeleportTo(uint32_t clientId); - void SendPacket_UnsetFlag(u8 flagSpace, s16 flag); + void SendPacket_RequestTeamState(); + void SendPacket_RequestTeleport(u32 clientId); + void SendPacket_SetCheckStatus(/*RandomizerCheck rc*/); + void SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag); + void SendPacket_TeleportTo(u32 clientId); + void SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag); void SendPacket_UpdateClientState(); void SendPacket_UpdateRoomState(); void SendPacket_UpdateTeamState(); @@ -279,10 +195,7 @@ class Anchor : public Network { void SendPacket_VileHoleState(u8 holeId, u8 holeState, u8 pieceType, u32 eaterClientId); void SendPacket_VileUpdate(const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 animMode); void OnActorDestroyed(Actor* actor); - void RevealSwitchHoneycomb(); void SendToCurrentMapPlayers(nlohmann::json& payload); - void SendToCurrentLevelPlayers(nlohmann::json& payload); - void SweepUnoccupiedLevelState(GameMap selfMap); static Anchor* GetInstance(); static void Init(); diff --git a/src/port/Network/Anchor/AnchorRoomWindow.cpp b/src/port/Network/Anchor/AnchorRoomWindow.cpp index 47cb82725..589ccd760 100644 --- a/src/port/Network/Anchor/AnchorRoomWindow.cpp +++ b/src/port/Network/Anchor/AnchorRoomWindow.cpp @@ -1,11 +1,11 @@ #include "Anchor.h" #include "port/Engine.h" -#include "port/Rando/Rando.h" -#include "port/GameStatus.h" +extern "C" { #include "variables.h" #include "functions.h" // extern PlayState* gPlayState; +} void AnchorRoomWindow::Draw() { if (!IsVisible() || !Anchor::GetInstance()->isConnected) { @@ -34,7 +34,9 @@ void AnchorRoomWindow::Draw() { } void AnchorRoomWindow::DrawElement() { - if (Anchor::GetInstance()->IsGlobalRoom()) { + bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); + + if (isGlobalRoom) { u32 activeClients = 0; for (auto& [clientId, client] : Anchor::GetInstance()->clients) { if (client.online) { @@ -82,8 +84,9 @@ void AnchorRoomWindow::DrawElement() { (Anchor::GetInstance()->roomState.showLocationsMode == 1 && isOwnTeam)) { if ((client.self ? Anchor::GetInstance()->IsSaveLoaded() : client.isSaveLoaded)) { ImGui::SameLine(); - ImGui::TextColored(ImVec4(1, 1, 1, 0.5f), "- %s", - port_getLevelName((int)(client.self ? gsworld_getMap() : client.map))); + ImGui::TextColored( + ImVec4(1, 1, 1, 0.5f), "- %s", + /*SohUtils::GetSceneName(client.self ? gPlayState->sceneNum : client.sceneNum).c_str()*/ ""); } } @@ -107,7 +110,7 @@ void AnchorRoomWindow::DrawElement() { ImGui::EndTooltip(); } } - uint32_t seed = IS_RANDO ? (uint32_t)RANDO_SEED : 0; + uint32_t seed = /*IS_RANDO ? Rando::Context::GetRawInstance()->GetSeed() :*/ 0; if (client.isSaveLoaded && Anchor::GetInstance()->IsSaveLoaded() && client.seed != seed && client.online && !client.self) { ImGui::SameLine(); diff --git a/src/port/Network/Anchor/Authority.cpp b/src/port/Network/Anchor/Authority.cpp index 7a689f011..0c88144e6 100644 --- a/src/port/Network/Anchor/Authority.cpp +++ b/src/port/Network/Anchor/Authority.cpp @@ -1,11 +1,11 @@ #include "port/Network/Anchor/Authority.h" #include "port/Network/Anchor/Anchor.h" -#include "port/Network/Anchor/JigsawPedestal.h" #include "port/Network/Anchor/VileSync.h" -#include "port/Network/Anchor/FightSync.h" #include +extern "C" { #include "enums.h" +} struct ActivityState { bool claimed = false; @@ -16,10 +16,7 @@ static ActivityState sActivities[NET_ACTIVITY_COUNT]; // The map each activity lives in. A claim is only valid while its owner is in this map. static const int32_t sActivityMap[NET_ACTIVITY_COUNT] = { - MAP_10_BGS_MR_VILE, // NET_ACTIVITY_VILE_MINIGAME - MAP_90_GL_BATTLEMENTS, // NET_ACTIVITY_FINAL_BOSS - MAP_27_FP_FREEZEEZY_PEAK, // NET_ACTIVITY_FP_TWINKLY - MAP_1_SM_SPIRAL_MOUNTAIN, // NET_ACTIVITY_SM_TUTORIAL + MAP_10_BGS_MR_VILE, // NET_ACTIVITY_VILE_MINIGAME }; static bool Authority_IsValidActivity(NetworkActivityId activity) { @@ -32,9 +29,6 @@ static void Authority_OnOwnerChanged(NetworkActivityId activity) { case NET_ACTIVITY_VILE_MINIGAME: VileSync_OnAuthorityChanged(); break; - case NET_ACTIVITY_FINAL_BOSS: - FightSync_OnAuthorityChanged(); - break; default: break; } @@ -48,14 +42,9 @@ static void Authority_ClearClaim(NetworkActivityId activity) { } } -static bool Authority_SyncActive() { - Anchor* anchor = Anchor::GetInstance(); - return anchor != nullptr && anchor->IsWorldSyncActive(); -} - bool NetAuthority_IsSelf(NetworkActivityId activity) { Anchor* anchor = Anchor::GetInstance(); - if (!Authority_SyncActive() || !Authority_IsValidActivity(activity)) { + if (anchor == nullptr || !anchor->isConnected || !Authority_IsValidActivity(activity)) { return true; } const ActivityState& state = sActivities[activity]; @@ -63,7 +52,7 @@ bool NetAuthority_IsSelf(NetworkActivityId activity) { } bool NetAuthority_IsClaimed(NetworkActivityId activity) { - return Authority_SyncActive() && Authority_IsValidActivity(activity) && sActivities[activity].claimed; + return Authority_IsValidActivity(activity) && sActivities[activity].claimed; } uint32_t NetAuthority_GetOwner(NetworkActivityId activity) { @@ -75,11 +64,12 @@ uint32_t NetAuthority_GetOwner(NetworkActivityId activity) { void NetAuthority_Claim(NetworkActivityId activity) { Anchor* anchor = Anchor::GetInstance(); - if (!Authority_SyncActive() || !Authority_IsValidActivity(activity)) { + if (anchor == nullptr || !anchor->isConnected || !Authority_IsValidActivity(activity)) { return; } ActivityState& state = sActivities[activity]; if (state.claimed && state.owner != anchor->ownClientId) { + SPDLOG_WARN("[Authority] Tried to claim activity {} already owned by client {}", (int)activity, state.owner); return; } if (!state.claimed || state.owner != anchor->ownClientId) { @@ -92,7 +82,7 @@ void NetAuthority_Claim(NetworkActivityId activity) { void NetAuthority_Release(NetworkActivityId activity) { Anchor* anchor = Anchor::GetInstance(); - if (!Authority_SyncActive() || !Authority_IsValidActivity(activity)) { + if (anchor == nullptr || !anchor->isConnected || !Authority_IsValidActivity(activity)) { return; } ActivityState& state = sActivities[activity]; @@ -126,9 +116,6 @@ void Authority_ApplyRemote(NetworkActivityId activity, uint32_t clientId, bool c } void Authority_OnClientStateChanged(uint32_t clientId, bool online, int32_t map) { - if (!online) { - JigsawPedestal_ClearClient(clientId); - } for (int32_t i = 0; i < NET_ACTIVITY_COUNT; i++) { ActivityState& state = sActivities[i]; if (state.claimed && state.owner == clientId && (!online || map != sActivityMap[i])) { @@ -138,7 +125,6 @@ void Authority_OnClientStateChanged(uint32_t clientId, bool online, int32_t map) } void Authority_OnPeerMapLoad(uint32_t clientId, int32_t map) { - JigsawPedestal_ClearClient(clientId); Anchor* anchor = Anchor::GetInstance(); for (int32_t i = 0; i < NET_ACTIVITY_COUNT; i++) { ActivityState& state = sActivities[i]; @@ -151,15 +137,11 @@ void Authority_OnPeerMapLoad(uint32_t clientId, int32_t map) { } else if (anchor != nullptr && state.owner == anchor->ownClientId && map == sActivityMap[i]) { // A peer just entered the map of an activity we own; make sure they know. anchor->SendPacket_AuthorityState((uint8_t)i, true); - if (i == NET_ACTIVITY_FINAL_BOSS) { - FightSync_SendSnapshot(clientId); - } } } } void Authority_OnSelfMapChanged(int32_t map) { - JigsawPedestal_ReleaseAllSelf(); Anchor* anchor = Anchor::GetInstance(); if (anchor == nullptr) { return; @@ -173,7 +155,6 @@ void Authority_OnSelfMapChanged(int32_t map) { } void Authority_Reset() { - JigsawPedestal_Reset(); for (int32_t i = 0; i < NET_ACTIVITY_COUNT; i++) { Authority_ClearClaim((NetworkActivityId)i); } diff --git a/src/port/Network/Anchor/Authority.h b/src/port/Network/Anchor/Authority.h index 573d889b9..8aa49d6d4 100644 --- a/src/port/Network/Anchor/Authority.h +++ b/src/port/Network/Anchor/Authority.h @@ -25,9 +25,6 @@ typedef enum NetworkActivityId { NET_ACTIVITY_NONE = -1, NET_ACTIVITY_VILE_MINIGAME, - NET_ACTIVITY_FINAL_BOSS, - NET_ACTIVITY_FP_TWINKLY, - NET_ACTIVITY_SM_TUTORIAL, NET_ACTIVITY_COUNT } NetworkActivityId; @@ -41,7 +38,10 @@ bool NetAuthority_IsSelf(NetworkActivityId activity); bool NetAuthority_IsClaimed(NetworkActivityId activity); // Owning clientId, or 0 when unclaimed. uint32_t NetAuthority_GetOwner(NetworkActivityId activity); +// Claim authority for the local client and broadcast it. No-op offline, or if another +// client already holds the claim. void NetAuthority_Claim(NetworkActivityId activity); +// Release our own claim and broadcast it. No-op unless we are the owner. void NetAuthority_Release(NetworkActivityId activity); #ifdef __cplusplus diff --git a/src/port/Network/Anchor/DummyPlayer.cpp b/src/port/Network/Anchor/DummyPlayer.cpp index 88fe6e033..209a30316 100644 --- a/src/port/Network/Anchor/DummyPlayer.cpp +++ b/src/port/Network/Anchor/DummyPlayer.cpp @@ -1,9 +1,9 @@ #include "Anchor.h" #include "port/Nametag/Nametag.h" -#include "functions.h" extern "C" { #include +#include "functions.h" #include "variables.h" void func_802D729C(Actor* actor, f32 arg1); } @@ -11,22 +11,12 @@ void func_802D729C(Actor* actor, f32 arg1); #include "bk_math.h" #include "port/Patches/Patches.h" -static s32 sActiveDummyBottlesBonus = 0; - -static void dummy_applyBottlesBonus(uintptr_t boneList, uintptr_t arg1) { - baanim_applyBottlesBonusMask(boneList, sActiveDummyBottlesBonus); -} - DummyPlayer::DummyPlayer(){}; void DummyPlayer::dummy_setTransformation(Transformation transform) { dummy_transformation = transform; } -void DummyPlayer::dummy_setBottlesBonus(s32 mask) { - dummyBottlesBonus = mask; -} - Transformation DummyPlayer::dummy_getTransformation() { return dummy_transformation; } @@ -59,28 +49,28 @@ void DummyPlayer::dummy_func_8029DBF0(void) { switch (dummy_getModelId()) { case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: // L8029DC24 case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: // L8029DC24 - temp_s0 = (s32)ml_interpolate_f(dummy_banjoLeftEye, 1.0f, 8.0f); - modelRender_setAppendageVisibility(0x1B, temp_s0); - modelRender_setAppendageVisibility(0x1D, temp_s0); - modelRender_setAppendageVisibility(0x1F, temp_s0); - modelRender_setAppendageVisibility(0x21, temp_s0); - temp_s0 = (s32)ml_interpolate_f(dummy_banjoRightEye, 1.0f, 8.0f); - modelRender_setAppendageVisibility(0x1A, temp_s0); - modelRender_setAppendageVisibility(0x1C, temp_s0); - modelRender_setAppendageVisibility(0x1E, temp_s0); - modelRender_setAppendageVisibility(0x20, temp_s0); + temp_s0 = (s32)ml_interpolate_f(dummy_modelEyeBlendUpper, 1.0f, 8.0f); + func_8033A45C(0x1B, temp_s0); + func_8033A45C(0x1D, temp_s0); + func_8033A45C(0x1F, temp_s0); + func_8033A45C(0x21, temp_s0); + temp_s0 = (s32)ml_interpolate_f(dummy_modelEyeBlendLower, 1.0f, 8.0f); + func_8033A45C(0x1A, temp_s0); + func_8033A45C(0x1C, temp_s0); + func_8033A45C(0x1E, temp_s0); + func_8033A45C(0x20, temp_s0); break; case ASSET_34F_MODEL_BANJO_TERMITE: // L8029DCCC case ASSET_359_MODEL_BANJO_WALRUS: // L8029DCCC case ASSET_36F_MODEL_BANJO_PUMPKIN: // L8029DCCC case ASSET_374_MODEL_BANJO_CROC: // L8029DCCC - modelRender_setAppendageVisibility(0x1B, (s32)ml_interpolate_f(dummy_banjoLeftEye, 1.0f, 6.0f)); - modelRender_setAppendageVisibility(0x1A, (s32)ml_interpolate_f(dummy_banjoRightEye, 1.0f, 6.0f)); + func_8033A45C(0x1B, (s32)ml_interpolate_f(dummy_modelEyeBlendUpper, 1.0f, 6.0f)); + func_8033A45C(0x1A, (s32)ml_interpolate_f(dummy_modelEyeBlendLower, 1.0f, 6.0f)); break; case ASSET_356_MODEL_BANJO_WISHYWASHY: // L8029DD2C - modelRender_setAppendageVisibility(1, (s32)ml_interpolate_f(dummy_banjoRightEye, 1.0f, 4.0f)); + func_8033A45C(1, (s32)ml_interpolate_f(dummy_modelEyeBlendLower, 1.0f, 4.0f)); break; } } @@ -90,59 +80,59 @@ AnimCtrl* DummyPlayer::dummy_getAnimCtrl() { } void DummyPlayer::dummy_setEyeState(bool squint, bool wink, bool isHat) { - dummy_kazooieLower = squint; - dummy_kazooieFeet = wink; + dummy_modelSquint = squint; + dummy_modelWink = wink; dummy_D_8037D230 = 1.0f; dummy_D_8037D234 = isHat; } -void DummyPlayer::modelAppendages_loadAppendage(void) { +void DummyPlayer::func_8029DD6C(void) { s32 temp_s0; // [port] must hold values > 1 for geo selector branches modelRender_func_8033A1FC(); switch (dummy_getModelId()) { case ASSET_34D_MODEL_BANJOKAZOOIE_LOW_POLY: case ASSET_34E_MODEL_BANJOKAZOOIE_HIGH_POLY: - modelRender_setAppendageVisibility(1, dummy_kazooieUpper); - modelRender_setAppendageVisibility(9, dummy_kazooieUpper); - modelRender_setAppendageVisibility(0xC, dummy_kazooieUpper); - modelRender_setAppendageVisibility(0xF, dummy_kazooieUpper); - modelRender_setAppendageVisibility(2, dummy_kazooieFeet); - modelRender_setAppendageVisibility(0xA, dummy_kazooieFeet); - modelRender_setAppendageVisibility(0xD, dummy_kazooieFeet); - modelRender_setAppendageVisibility(0x10, dummy_kazooieFeet); - modelRender_setAppendageVisibility(8, dummy_kazooieLower); - modelRender_setAppendageVisibility(0xB, dummy_kazooieLower); - modelRender_setAppendageVisibility(0xE, dummy_kazooieLower); - modelRender_setAppendageVisibility(0x11, dummy_kazooieLower); - temp_s0 = dummy_kazooieTurbos + 1; - modelRender_setAppendageVisibility(0x12, temp_s0); - modelRender_setAppendageVisibility(0x14, temp_s0); - modelRender_setAppendageVisibility(0x16, temp_s0); - modelRender_setAppendageVisibility(0x18, temp_s0); - modelRender_setAppendageVisibility(0x13, temp_s0); - modelRender_setAppendageVisibility(0x15, temp_s0); - modelRender_setAppendageVisibility(0x17, temp_s0); - modelRender_setAppendageVisibility(0x19, temp_s0); - temp_s0 = dummy_kazooieBoots + 1; - modelRender_setAppendageVisibility(0x22, temp_s0); - modelRender_setAppendageVisibility(0x24, temp_s0); - modelRender_setAppendageVisibility(0x26, temp_s0); - modelRender_setAppendageVisibility(0x28, temp_s0); - modelRender_setAppendageVisibility(0x23, temp_s0); - modelRender_setAppendageVisibility(0x25, temp_s0); - modelRender_setAppendageVisibility(0x27, temp_s0); - modelRender_setAppendageVisibility(0x29, temp_s0); + func_8033A45C(1, dummy_kazooieVisible); + func_8033A45C(9, dummy_kazooieVisible); + func_8033A45C(0xC, dummy_kazooieVisible); + func_8033A45C(0xF, dummy_kazooieVisible); + func_8033A45C(2, dummy_modelWink); + func_8033A45C(0xA, dummy_modelWink); + func_8033A45C(0xD, dummy_modelWink); + func_8033A45C(0x10, dummy_modelWink); + func_8033A45C(8, dummy_modelSquint); + func_8033A45C(0xB, dummy_modelSquint); + func_8033A45C(0xE, dummy_modelSquint); + func_8033A45C(0x11, dummy_modelSquint); + temp_s0 = dummy_modelMouth1 + 1; + func_8033A45C(0x12, temp_s0); + func_8033A45C(0x14, temp_s0); + func_8033A45C(0x16, temp_s0); + func_8033A45C(0x18, temp_s0); + func_8033A45C(0x13, temp_s0); + func_8033A45C(0x15, temp_s0); + func_8033A45C(0x17, temp_s0); + func_8033A45C(0x19, temp_s0); + temp_s0 = dummy_modelMouth2 + 1; + func_8033A45C(0x22, temp_s0); + func_8033A45C(0x24, temp_s0); + func_8033A45C(0x26, temp_s0); + func_8033A45C(0x28, temp_s0); + func_8033A45C(0x23, temp_s0); + func_8033A45C(0x25, temp_s0); + func_8033A45C(0x27, temp_s0); + func_8033A45C(0x29, temp_s0); break; case ASSET_359_MODEL_BANJO_WALRUS: - modelRender_setAppendageVisibility(3, dummy_D_8037D23A); + func_8033A45C(3, dummy_D_8037D23A); break; case ASSET_374_MODEL_BANJO_CROC: - temp_s0 = dummy_kazooieTurbos + 1; - modelRender_setAppendageVisibility(4, temp_s0); - modelRender_setAppendageVisibility(5, temp_s0); - modelRender_setAppendageVisibility(6, temp_s0); - modelRender_setAppendageVisibility(7, temp_s0); + temp_s0 = dummy_modelMouth1 + 1; + func_8033A45C(4, temp_s0); + func_8033A45C(5, temp_s0); + func_8033A45C(6, temp_s0); + func_8033A45C(7, temp_s0); break; } dummy_func_8029DBF0(); @@ -189,18 +179,13 @@ void DummyPlayer::Draw(Gfx** gfx, Mtx** mtx, Vtx** vtx) { sp38[2] += dummyDisplacement[2]; if (dummyBin) { - // anctrl_drawSetup re-runs anim_update, which invokes the bonus-mask callback. - sActiveDummyBottlesBonus = dummyBottlesBonus; anctrl_drawSetup(dummyAnimCtrl, dummyPosition, 1); - sActiveDummyBottlesBonus = 0; - modelAppendages_loadAppendage(); + func_8029DD6C(); modelRender_setEnvColor(env_color[0], env_color[1], env_color[2], dummyEnvAlpha); modelRender_func_8033A280(2.0f); // modelRender_preDraw((GenFunction_1)_dummy_preDraw, 0); modelRender_setRefPoints(dummy_D_80363780); modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL); - // Each dummy draws the shared model bin through its own recolored palettes. - PlayerColors_applyForDraw(dummyOwnerId, dummy_getModelId(), dummyBin, &dummyColors); if (dummy_D_8037C150.unk0) { dummy_D_8037C150.unk0 = 0; modelRender_draw(gfx, mtx, dummy_D_8037C150.unk4, rotation, dummyScale, sp38, dummyBin); @@ -242,7 +227,9 @@ void DummyPlayer::dummy_updateModel(void) { } void DummyPlayer::dummy_reset(void) { - dummy_despawnActor(); // skips if already detached + // Clear stale actor reference — the game engine owns actor lifetime and may have + // already freed it (e.g. after a map transition). Don't dereference the old pointer. + // dummyActor = NULL; if (dummyAnimCtrl) { dummyAnim_free(); dummyAnimCtrl = NULL; @@ -279,31 +266,23 @@ void DummyPlayer::dummy_reset(void) { dummyAnim_reset(); } -// Forget the stand-in without despawning it. void DummyPlayer::dummy_detachActor(void) { - dummyMarker = nullptr; -} - -void DummyPlayer::dummy_despawnActor(void) { - if (dummyMarker == nullptr) { - return; - } - Actor* actor = marker_getActor(dummyMarker); - if (actor != nullptr && actor->unk104 != nullptr) { - ActorMarker* shadowMarker = actor->unk104; - Actor* shadow = marker_getActor(shadowMarker); - if (shadow != nullptr) { - shadow->unk104 = nullptr; - } - actor->unk104 = nullptr; - marker_despawn(shadowMarker); - } - marker_despawn(dummyMarker); - dummyMarker = nullptr; + // dummyActor = nullptr; } void DummyPlayer::dummy_free(void) { - dummy_despawnActor(); + /*if (dummyActor) { + if (dummyActor->unk104) { + Actor *shadow = marker_getActor(dummyActor->unk104); + shadow->unk104 = NULL; + shadow->despawn_flag = true; + dummyActor->unk104 = NULL; + } + if (dummyActor->marker) { + marker_despawn(dummyActor->marker); + } + dummyActor = NULL; + }*/ if (dummyBin) { assetcache_release(dummyBin); dummyBin = NULL; @@ -322,41 +301,25 @@ void DummyPlayer::dummy_free(void) { void DummyPlayer::dummyAnim_reset() { dummy_D_8037D230 = 0; dummy_D_8037D234 = 0; - dummy_kazooieUpper = 0; - dummy_kazooieFeet = 0; - dummy_kazooieLower = 0; - dummy_banjoLeftEye = 0.0f; - dummy_banjoRightEye = 0.0f; - dummy_kazooieTurbos = 0; - dummy_kazooieBoots = 0; + dummy_kazooieVisible = 0; + dummy_modelWink = 0; + dummy_modelSquint = 0; + dummy_modelEyeBlendUpper = 0.0f; + dummy_modelEyeBlendLower = 0.0f; + dummy_modelMouth1 = 0; + dummy_modelMouth2 = 0; dummy_D_8037D23A = 0; } -// func_802D7124 (core2/fx/enemy_shadow.c): distance-gated drop-shadow attach + keep-alive. -extern "C" void func_802D7124(Actor* actor, f32 scale); - void DummyPlayer::dummy_update(void) { dummyAnim_update(); - if (dummyMarker == nullptr) { - Actor* spawned = actor_spawnWithYaw_f32(ACTOR_3CC_DUMMY_PLAYER_ANCHOR, dummyPosition, (s32)dummyYaw); - if (spawned == nullptr) { - return; - } - dummyMarker = spawned->marker; - } - - Actor* actor = marker_getActor(dummyMarker); - if (actor == nullptr || actor->despawn_flag) { - return; - } - actor->position[0] = dummyPosition[0]; - actor->position[1] = dummyPosition[1]; - actor->position[2] = dummyPosition[2]; - actor->yaw = dummyYaw; - if (dummyIsVisible) { - func_802D7124(actor, 1.0f); - } + // if (dummyActor && !dummyActor->despawn_flag) { + // dummyActor->position[0] = dummyPosition[0]; + // dummyActor->position[1] = dummyPosition[1]; + // dummyActor->position[2] = dummyPosition[2]; + // func_802D729C(dummyActor, 1.0f); + // } } BKModelBin* DummyPlayer::dummy_getModelBin(void) { @@ -496,7 +459,8 @@ void DummyPlayer::dummyAnim_init(void) { dummyAnimCtrl = anctrl_new(1); func_80287784(dummyAnimCtrl, 0); anctrl_setSmoothTransition(dummyAnimCtrl, false); - func_8028746C(dummyAnimCtrl, dummy_applyBottlesBonus); + // func_8028746C(dummyAnimCtrl, __baanim_applyBottlesBonus); + // AnimModifyFunction = NULL; anctrl_drawSetup(dummyAnimCtrl, dummyPosition, 1); dummyAnimUpdateType = BAANIM_UPDATE_0_NONE; //__baanim_setUpdateType(BAANIM_UPDATE_1_NORMAL); @@ -539,20 +503,18 @@ void DummyPlayer::dummyAnim_update(void) { default: break; } - sActiveDummyBottlesBonus = dummyBottlesBonus; anctrl_update(dummyAnimCtrl); - sActiveDummyBottlesBonus = 0; } void DummyPlayer::setModelSubStates(bool kazooie, bool squint, bool wink, bool mouth1, bool mouth2, f32 eyeBlendUpper, f32 eyeBlendLower) { - dummy_kazooieUpper = kazooie; - dummy_kazooieLower = squint; - dummy_kazooieFeet = wink; - dummy_kazooieTurbos = mouth1; - dummy_kazooieBoots = mouth2; - dummy_banjoLeftEye = eyeBlendUpper; - dummy_banjoRightEye = eyeBlendLower; + dummy_kazooieVisible = kazooie; + dummy_modelSquint = squint; + dummy_modelWink = wink; + dummy_modelMouth1 = mouth1; + dummy_modelMouth2 = mouth2; + dummy_modelEyeBlendUpper = eyeBlendUpper; + dummy_modelEyeBlendLower = eyeBlendLower; } void DummyPlayer::dummyAnim_setUpdateType(s32 state) { diff --git a/src/port/Network/Anchor/DummyPlayer.h b/src/port/Network/Anchor/DummyPlayer.h index c472559f6..9eb364c84 100644 --- a/src/port/Network/Anchor/DummyPlayer.h +++ b/src/port/Network/Anchor/DummyPlayer.h @@ -1,8 +1,9 @@ #pragma once +extern "C" { #include "functions.h" #include "core2/ba/model.h" #include "variables.h" -#include "port/Enhancements/Cosmetics/PlayerColors.h" +} class DummyPlayer { public: @@ -48,15 +49,13 @@ class DummyPlayer { void dummy_setScale(f32 scale); void dummy_setTransformation(Transformation transform); Transformation dummy_getTransformation(); - // Bottles-bonus effect mask (D_803635EC bitfield). - void dummy_setBottlesBonus(s32 mask); void dummy_setVisible(s32 arg0); void dummy_setYDisplacement(f32 arg0); void dummy_setYaw(f32 yaw); void dummy_update(void); void dummy_updateModel(void); // void func_80254008(void); - void modelAppendages_loadAppendage(void); + void func_8029DD6C(void); // void modelRender_func_8033A280(f32); // anim void dummyAnim_init(void); @@ -78,17 +77,7 @@ class DummyPlayer { // eye/mouth void dummy_setEyeState(bool squint, bool wink, bool isHat); AnimCtrl* dummy_getAnimCtrl(); - ActorMarker* dummy_getMarker() const { - return dummyMarker; - } - void dummy_despawnActor(void); - // Cosmetics: which Anchor client this stand-in belongs to, and the model colors they chose. - void dummy_setOwner(uint32_t clientId) { - dummyOwnerId = clientId; - } - void dummy_setColors(const BKPlayerColorSet& colors) { - dummyColors = colors; - } + // Actor* getDummyActor() const { return dummyActor; } private: uint32_t PlayerID; @@ -123,7 +112,8 @@ class DummyPlayer { } dummyAnimScale; AnimCtrl* dummyAnimCtrl = nullptr; f32 dummyVelocity[3]; - ActorMarker* dummyMarker = nullptr; + ActorMarker* dummyMarker; + Actor* dummyActor = nullptr; f32 dummy_D_8037C100[3]; f32 dummy_D_8037C110[3]; f32 dummyDisplacement[3]; @@ -136,16 +126,13 @@ class DummyPlayer { f32 dummy_D_8037D230; u8 dummy_D_8037D234; - u8 dummy_kazooieLower; - u8 dummy_kazooieFeet; - u8 dummy_kazooieTurbos; - u8 dummy_kazooieUpper; - u8 dummy_kazooieBoots; + u8 dummy_modelSquint; + u8 dummy_modelWink; + u8 dummy_modelMouth1; + u8 dummy_kazooieVisible; + u8 dummy_modelMouth2; u8 dummy_D_8037D23A; - f32 dummy_banjoLeftEye; - f32 dummy_banjoRightEye; + f32 dummy_modelEyeBlendUpper; + f32 dummy_modelEyeBlendLower; Transformation dummy_transformation; - s32 dummyBottlesBonus = 0; - uint32_t dummyOwnerId = 0; - BKPlayerColorSet dummyColors = {}; }; \ No newline at end of file diff --git a/src/port/Network/Anchor/FightSync.c b/src/port/Network/Anchor/FightSync.c deleted file mode 100644 index d53fd8551..000000000 --- a/src/port/Network/Anchor/FightSync.c +++ /dev/null @@ -1,554 +0,0 @@ -#include "FightSync.h" -#include "port/Network/Anchor/Authority.h" - -#include -#include "functions.h" -#include "variables.h" -#include "prop.h" -#include "fight/fight.h" - -// chfinalboss.c globals. D_803927xx = spell-spawn scratch vectors. -extern f32 D_80392758[3]; -extern f32 D_80392768[3]; -extern f32 D_80392778[3]; -extern f32 __chFinalBossFireballFlightTime; -extern ActorMarker* __chFinalBossFlightPadMarker; -extern u8 __chFinalBossSpellBarrierActive; -extern ActorArray* suBaddieActorArray; -extern u8 sFinalBossJinjoStatueActivated; -// Collision radius for the jinjo-into-Grunty test. -extern f32 func_8033229C(ActorMarker* marker); - -// Set once the ending script takes over (chfinalboss_setBossDefeated). -static u8 sFightNetCinematic = 0; -static u8 sFightNetWasFollower = 0; -// Bit per jinjo statue id (1-4): its jinjo already slammed Grunty. -static u8 sFightNetJinjoSlammed = 0; -static FightWorldSnapshot sFightNetSnap; -static u8 sFightNetCatchupActive = 0; -static u8 sFightNetCatchupSpawned[6]; // statue spawn already queued, indexed by statue id -static u8 sFightNetCatchupPadDone = 0; -static u8 sFightNetCatchupBarrierDone = 0; - -static bool FightSync_IsFollower(void) { - return NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS) && !NetAuthority_IsSelf(NET_ACTIVITY_FINAL_BOSS); -} - -static bool FightSync_IsLiveAuthority(void) { - return NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS) && NetAuthority_IsSelf(NET_ACTIVITY_FINAL_BOSS); -} - -static Actor* FightSync_FindBoss(void) { - Actor* boss = actorArray_findActorFromActorId(ACTOR_38B_GRUNTILDA_FINAL_BOSS); - - if (boss == NULL || !boss->volatile_initialized || boss->despawn_flag) { - return NULL; - } - return boss; -} - -// The jinjo statue bases share one actor id, so find by their statue id (1-4). -static Actor* FightSync_FindStatueBase(s32 statue_id) { - s32 i; - - if (suBaddieActorArray == NULL) { - return NULL; - } - for (i = 0; i < suBaddieActorArray->cnt; i++) { - Actor* actor = &suBaddieActorArray->data[i]; - if (actor->marker == NULL || actor->marker->id != MARKER_27A_JINJO_STATUE_BASE) { - continue; - } - if (actor->actorTypeSpecificField != statue_id || actor->despawn_flag) { - continue; - } - return actor; - } - return NULL; -} - -// Apply a networked egg via getHitByEgg(other == NULL), the counting path. -static void FightSync_ApplyJinjoStatueEgg(s32 statue_id) { - Actor* base = FightSync_FindStatueBase(statue_id); - - if (base != NULL) { - chBossJinjoBase_getHitByEgg(base->marker, NULL); - } -} - -static void FightSync_ReleaseFirstStatueCutscene(void) { - if (sFinalBossJinjoStatueActivated) { - sFinalBossJinjoStatueActivated = 0; - timed_exitStaticCamera(1.0f); - func_80324E38(1.0f, 0); - } -} - -// --- boss lifecycle hooks (called from chfinalboss.c) ----------------------------------------- - -void FightSync_OnBossSpawned(void) { - s32 i; - sFightNetCinematic = 0; - sFightNetWasFollower = 0; - sFightNetJinjoSlammed = 0; - sFightNetCatchupActive = 0; - // Cleared on a fresh boss spawn, not in ApplyWorld, so a repeat snapshot can't re-run catch-up. - sFightNetCatchupPadDone = 0; - sFightNetCatchupBarrierDone = 0; - for (i = 0; i < 6; i++) { - sFightNetCatchupSpawned[i] = 0; - } -} - -void FightSync_OnBossDefeated(void) { - sFightNetCinematic = 1; -} - -// --- authority replication hooks ------------------------------------------------------------- - -void FightSync_OnSpellSpawned(s32 kind) { - if (FightSync_IsLiveAuthority()) { - // Kind 0 (ballistic fireball) carries lead time; each follower re-aims at its own player. - s32 leadMs = (kind == 0) ? (s32)(__chFinalBossFireballFlightTime * 1000.0f) : 0; - FightSync_SendEvent(FIGHT_EV_SPELL, kind, leadMs, D_80392758, D_80392768, D_80392778); - } -} - -void FightSync_OnFlightPadSpawned(void) { - if (FightSync_IsLiveAuthority()) { - FightSync_SendEvent(FIGHT_EV_PAD_SPAWN, 0, 0, NULL, NULL, NULL); - } -} - -void FightSync_OnFlightPadDespawned(void) { - if (FightSync_IsLiveAuthority()) { - FightSync_SendEvent(FIGHT_EV_PAD_DESPAWN, 0, 0, NULL, NULL, NULL); - } -} - -void FightSync_OnBarrierSpawned(void) { - if (FightSync_IsLiveAuthority()) { - FightSync_SendEvent(FIGHT_EV_BARRIER, 0, 0, NULL, NULL, NULL); - } -} - -void FightSync_OnStatueSpawned(s32 statue_id) { - if (FightSync_IsLiveAuthority()) { - FightSync_SendEvent(FIGHT_EV_STATUE_SPAWN, statue_id, 0, NULL, NULL, NULL); - } -} - -void FightSync_OnJinjoSlam(s32 statue_id) { - sFightNetJinjoSlammed |= 1 << statue_id; - if (FightSync_IsLiveAuthority()) { - FightSync_SendEvent(FIGHT_EV_JINJO_ATTACK, statue_id, 0, NULL, NULL, NULL); - } -} - -void FightSync_ReplicateEgg(s32 statue_id, s32 pad_index) { - if (FightSync_IsLiveAuthority()) { - FightSync_SendEvent(FIGHT_EV_EGG_FED, statue_id, pad_index, NULL, NULL, NULL); - } -} - -// --- follower input forwarding ---------------------------------------------------------------- - -bool FightSync_ForwardBossHit(s32 phase) { - if (!FightSync_IsFollower()) { - return false; - } - FightSync_SendEvent(FIGHT_EV_BOSS_HIT, phase, 0, NULL, NULL, NULL); - return true; -} - -bool FightSync_ForwardEgg(s32 statue_id, s32 pad_index) { - if (!FightSync_IsFollower()) { - return false; - } - FightSync_SendEvent(FIGHT_EV_EGG, statue_id, pad_index, NULL, NULL, NULL); - return true; -} - -// --- stream: gather (authority) / apply (follower) --------------------------------------------- - -bool FightSync_GatherUpdate(f32 pos[3], f32* yaw, s32* state, s32* phase, s32* mirror, s32* vuln) { - Actor* boss; - ActorLocal_FinalBoss* local; - - if (sFightNetCinematic) { - return false; - } - boss = FightSync_FindBoss(); - if (boss == NULL) { - return false; - } - local = (ActorLocal_FinalBoss*)&boss->local; - pos[0] = boss->position[0]; - pos[1] = boss->position[1]; - pos[2] = boss->position[2]; - *yaw = boss->yaw; - *state = boss->state; - *phase = local->phase; - *mirror = local->mirror_phase5; - // Phase-2 vulnerability toggle (unkA). - *vuln = local->unkA; - return true; -} - -static void FightSync_ApplyBossState(Actor* this, s32 phase, s32 state) { - ActorLocal_FinalBoss* local = (ActorLocal_FinalBoss*)&this->local; - - // unk44_31 = broomstick motor sfx source. - if (this->unk44_31 != 0 && phase != FINALBOSS_PHASE_1_BROOMSTICK) { - sfxsource_freeSfxsourceByIndex(this->unk44_31); - this->unk44_31 = 0; - } - local->phase = phase; - subaddie_set_state_with_direction(this, state, 0.0001f, 1); - if (state == 9 || state == 0x21 || state == 0x22 || state == 0x2B) { - actor_playAnimationOnce(this); - } else { - actor_loopAnimation(this); - } - chfinalboss_func_80386600(this->marker, (state == 6 || state == 7 || state == 8) ? 1 : 0); - if (phase == FINALBOSS_PHASE_5_JINJONATOR || state == 0x21 || state == 0x22) { - chfinalboss_func_80386628(this->marker, 0); - } else { - chfinalboss_func_80386628(this->marker, 1); - } - if (state == 0x21) { - // State 0x21 = broom shatters (end of phase 4); replay the burst. - chfinalboss_createBroomstickParticles(this->position, ASSET_552_MODEL_BROOMSTICK_PIECE_HEAD, 1); - chfinalboss_createBroomstickParticles(this->position, ASSET_553_MODEL_BROOMSTICK_PIECE_SHORT, 12); - chfinalboss_createBroomstickParticles(this->position, ASSET_554_MODEL_BROOMSTICK_PIECE_LONG, 20); - chfinalboss_createBroomstickParticles(this->position, ASSET_555_MODEL_BROOMSTICK_PIECE_EYE, 2); - } -} - -void FightSync_ApplyUpdate(const f32 pos[3], f32 yaw, s32 state, s32 phase, s32 mirror, s32 vuln) { - Actor* boss; - ActorLocal_FinalBoss* local; - - if (!FightSync_IsFollower() || sFightNetCinematic) { - return; - } - boss = FightSync_FindBoss(); - if (boss == NULL) { - return; - } - sFightNetWasFollower = 1; - local = (ActorLocal_FinalBoss*)&boss->local; - boss->position[0] = pos[0]; - boss->position[1] = pos[1]; - boss->position[2] = pos[2]; - boss->yaw = yaw; - boss->yaw_ideal = yaw; - local->mirror_phase5 = mirror; - // Applied every frame, not just on state change (see FightSync_GatherUpdate). - local->unkA = (u8)vuln; - if (local->phase != (u8)phase || boss->state != state) { - FightSync_ApplyBossState(boss, phase, state); - } -} - -// --- latecomer world snapshot ------------------------------------------------------------------- - -bool FightSync_GatherWorld(FightWorldSnapshot* snap) { - Actor* base; - s32 i; - - if (sFightNetCinematic || !FightSync_IsLiveAuthority() || FightSync_FindBoss() == NULL) { - return false; - } - snap->pad = (__chFinalBossFlightPadMarker != NULL) ? 1 : 0; - snap->barrier = __chFinalBossSpellBarrierActive ? 1 : 0; - for (i = 0; i < 4; i++) { - base = FightSync_FindStatueBase(i + 1); - if (base == NULL) { - snap->statue[i] = 0xFF; - snap->jinjoGone[i] = 0; - } else if (base->state == CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { - snap->statue[i] = 3; - snap->jinjoGone[i] = (sFightNetJinjoSlammed & (1 << (i + 1))) ? 1 : 0; - } else { - snap->statue[i] = base->unk38_31; - snap->jinjoGone[i] = 0; - } - } - snap->jbase = chjinjonatorbase_netGetPads(snap->jpads) ? 1 : 0; - return true; -} - -void FightSync_ApplyWorld(const FightWorldSnapshot* snap) { - s32 i; - - if (!FightSync_IsFollower() || sFightNetCinematic) { - return; - } - sFightNetSnap = *snap; - sFightNetCatchupActive = 1; - // Seed the slammed set from the snapshot so a jinjo that reaches Grunty before catch-up - // rebuilds its statue is removed by the phase-4 guard rather than replaying the attack. - for (i = 0; i < 4; i++) { - if (snap->jinjoGone[i]) { - sFightNetJinjoSlammed |= 1 << (i + 1); - } - } -} - -static void FightSync_CatchupTick(Actor* boss) { - Actor* base; - Actor* jinjo; - u8 pads[4]; - s32 i; - s32 done = 1; - - if (!sFightNetCatchupActive) { - return; - } - - if (sFightNetSnap.pad && !sFightNetCatchupPadDone) { - sFightNetCatchupPadDone = 1; - __spawnQueue_add_1((GenFunction_1)chfinalboss_spawnFlightPad, 0); - } - if (sFightNetSnap.barrier && !sFightNetCatchupBarrierDone) { - sFightNetCatchupBarrierDone = 1; - chfinalboss_spawnSpellBarrier(boss->marker); - } - - for (i = 0; i < 4; i++) { - if (sFightNetSnap.statue[i] == 0xFF) { - continue; - } - base = FightSync_FindStatueBase(i + 1); - if (base == NULL) { - if (!sFightNetCatchupSpawned[i + 1]) { - sFightNetCatchupSpawned[i + 1] = 1; - chfinalboss_spawnStatue(i + 1); - } - done = 0; - continue; - } - if (base->state != CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO && base->unk38_31 < sFightNetSnap.statue[i]) { - chBossJinjoBase_getHitByEgg(base->marker, NULL); - done = 0; - continue; - } - if (sFightNetSnap.jinjoGone[i]) { - jinjo = actorArray_findActorFromActorId(ACTOR_3A4_BOSS_JINJO_BASE_IDX + i + 1); - if (jinjo != NULL) { - sFightNetJinjoSlammed |= 1 << (i + 1); - marker_despawn(jinjo->marker); - sFightNetSnap.jinjoGone[i] = 0; - } else if (base->state == CHBOSSJINJOBASE_STATE_3_SPAWNED_BOSS_JINJO) { - done = 0; - } - } - } - - if (sFightNetSnap.jbase) { - if (!chjinjonatorbase_netGetPads(pads)) { - if (!sFightNetCatchupSpawned[5]) { - sFightNetCatchupSpawned[5] = 1; - chfinalboss_spawnStatue(BOSSJINJO_5_JINJONATOR); - } - done = 0; - } else { - for (i = 0; i < 4; i++) { - if (pads[i] > sFightNetSnap.jpads[i]) { - chjinjonatorbase_netApplyEgg(i); - done = 0; - break; - } - } - } - } - - if (done) { - sFightNetCatchupActive = 0; - } -} - -bool FightSync_BossFollowerTick(void* bossPtr) { - Actor* boss = (Actor*)bossPtr; - - if (!FightSync_IsFollower() || sFightNetCinematic) { - return false; - } - FightSync_CatchupTick(boss); - - // Detect a jinjo-into-Grunty collision locally (display-only) ahead of the authority's slam event. - if (((ActorLocal_FinalBoss*)&boss->local)->phase == FINALBOSS_PHASE_4_JINJOS) { - ActorMarker* jinjoMarker = chfinalboss_findCollidingJinjo(boss, func_8033229C(boss->marker)); - if (jinjoMarker != NULL) { - Actor* jinjo = marker_getActor(jinjoMarker); - s32 sid = (jinjo != NULL) ? jinjo->actorTypeSpecificField : 0; - if (sid >= BOSSJINJO_1_ORANGE && sid <= BOSSJINJO_4_YELLOW && (sFightNetJinjoSlammed & (1 << sid))) { - marker_despawn(jinjoMarker); - } else { - if (sid >= BOSSJINJO_1_ORANGE && sid <= BOSSJINJO_4_YELLOW) { - sFightNetJinjoSlammed |= 1 << sid; - } - chbossjinjo_attack(jinjoMarker); - FightSync_ReleaseFirstStatueCutscene(); - } - } - } - - switch (boss->state) { - case 2: - case 3: - case 4: - case 6: - case 7: - case 8: - case 14: - case 21: - case 28: - chfinalboss_spawnBroomstickGlowParticles(boss); - break; - } - return true; -} - -// --- one-shot event dispatch -------------------------------------------------------------------- - -void FightSync_ApplyEvent(s32 ev, s32 a, s32 b, const f32 v0[3], const f32 v1[3], const f32 v2[3]) { - Actor* boss = FightSync_FindBoss(); - s32 i; - - switch (ev) { - case FIGHT_EV_SPELL: - if (!FightSync_IsFollower() || v0 == NULL) { - return; - } - // Kind 0 (ballistic fireball) is re-aimed at this client's own player. - if (a == 0) { - if (boss != NULL) { - f32 src[3]; - f32 leadTime = (b > 0) ? (b / 1000.0f) : 1.3f; - src[0] = boss->position[0]; - src[1] = boss->position[1]; - src[2] = boss->position[2]; - chfinalboss_throwObject(boss->marker, src, leadTime, 0); - } - break; - } - // Spawn helpers read these globals; set them before queueing. - for (i = 0; i < 3; i++) { - D_80392758[i] = v0[i]; - D_80392768[i] = v1[i]; - D_80392778[i] = v2[i]; - } - if (a == 2) { - __spawnQueue_add_1((GenFunction_1)chfinalboss_func_80386EC0, 0); - } else if (a == 1) { - __spawnQueue_add_1((GenFunction_1)chfinalboss_func_80387074, 0); - } - break; - - case FIGHT_EV_PAD_SPAWN: - if (!FightSync_IsFollower()) { - return; - } - __spawnQueue_add_1((GenFunction_1)chfinalboss_spawnFlightPad, 0); - break; - - case FIGHT_EV_PAD_DESPAWN: - if (!FightSync_IsFollower()) { - return; - } - chfinalboss_despawnFlightPad(); - break; - - case FIGHT_EV_BARRIER: - if (!FightSync_IsFollower() || boss == NULL) { - return; - } - chfinalboss_spawnSpellBarrier(boss->marker); - break; - - case FIGHT_EV_STATUE_SPAWN: - if (!FightSync_IsFollower() || a < BOSSJINJO_1_ORANGE || a > BOSSJINJO_5_JINJONATOR) { - return; - } - chfinalboss_spawnStatue(a); - break; - - case FIGHT_EV_EGG_FED: - if (!FightSync_IsFollower()) { - return; - } - if (a == BOSSJINJO_5_JINJONATOR) { - chjinjonatorbase_netApplyEgg(b); - } else { - FightSync_ApplyJinjoStatueEgg(a); - } - break; - - case FIGHT_EV_JINJO_ATTACK: { - Actor* jinjo; - if (!FightSync_IsFollower() || a < BOSSJINJO_1_ORANGE || a > BOSSJINJO_4_YELLOW) { - return; - } - sFightNetJinjoSlammed |= 1 << a; - jinjo = actorArray_findActorFromActorId(ACTOR_3A4_BOSS_JINJO_BASE_IDX + a); - if (jinjo != NULL) { - chbossjinjo_attack(jinjo->marker); - } - FightSync_ReleaseFirstStatueCutscene(); - break; - } - - case FIGHT_EV_BOSS_HIT: - if (!FightSync_IsLiveAuthority() || boss == NULL) { - return; - } - if (getGameMode() == GAME_MODE_4_PAUSED) { - return; - } - if (((ActorLocal_FinalBoss*)&boss->local)->phase != (u8)a) { - return; - } - chfinalboss_collisionPassive(boss->marker, NULL); - break; - - case FIGHT_EV_EGG: - if (!FightSync_IsLiveAuthority()) { - return; - } - if (getGameMode() == GAME_MODE_4_PAUSED) { - return; - } - if (a == BOSSJINJO_5_JINJONATOR) { - chjinjonatorbase_netApplyEgg(b); - } else { - if (sFinalBossJinjoStatueActivated != 0) { - return; - } - FightSync_ApplyJinjoStatueEgg(a); - } - break; - } -} - -void FightSync_OnAuthorityChanged(void) { - Actor* boss; - ActorLocal_FinalBoss* local; - - FightSyncSeq_Reset(); - if (sFightNetCinematic) { - return; - } - boss = FightSync_FindBoss(); - if (boss == NULL) { - return; - } - if (sFightNetWasFollower && FightSync_IsLiveAuthority()) { - sFightNetWasFollower = 0; - local = (ActorLocal_FinalBoss*)&boss->local; - if (local->phase != FINALBOSS_PHASE_0_INTRO) { - chfinalboss_setPhase(boss->marker, local->phase); - } - } -} diff --git a/src/port/Network/Anchor/FightSync.h b/src/port/Network/Anchor/FightSync.h deleted file mode 100644 index 2c6127966..000000000 --- a/src/port/Network/Anchor/FightSync.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include -#include - -// Final Grunty fight sync (Anchor). -// -// First client in the fight map with the boss spawned claims NET_ACTIVITY_FINAL_BOSS and runs -// the fight; everyone else mirrors it. -// -// FIGHT_UPDATE: authority -> map, per-frame transform/state stream, sequence-guarded. -// FIGHT_STATE: authority -> joining client, world catch-up snapshot. -// FIGHT_EVENT: one-shot; authority -> map for spells/pads/barrier/statues/eggs/jinjo -// attacks, follower -> authority for boss hits and statue eggs. - -// FIGHT_EVENT ids ('ev' field). -enum FightSyncEvent { - // authority -> followers - FIGHT_EV_SPELL = 0, // a = kind (0 fireball, 1 final fireball, 2 green blast); p/v/w = spawn vectors - FIGHT_EV_PAD_SPAWN, // flight pad appears (end of phase 2) - FIGHT_EV_PAD_DESPAWN, // flight pad removed (during phase 3 barrier cast) - FIGHT_EV_BARRIER, // spell barrier spawns on Grunty - FIGHT_EV_STATUE_SPAWN, // a = ch_bossjinjo_e statue id (1-4 jinjos, 5 jinjonator) - FIGHT_EV_EGG_FED, // a = statue id (1-4 jinjos, 5 jinjonator), b = jinjonator pad index - FIGHT_EV_JINJO_ATTACK, // a = jinjo statue id whose jinjo just slammed Grunty - // followers -> authority - FIGHT_EV_BOSS_HIT, // a = the phase the hitting client believed Grunty was in - FIGHT_EV_EGG, // a = statue id, b = jinjonator pad index -}; - -// FIGHT_STATE catch-up snapshot for a client joining mid-fight. -typedef struct FightWorldSnapshot { - uint8_t pad; // flight pad present - uint8_t barrier; // spell barrier up on Grunty - uint8_t statue[4]; // jinjo statue bases (ids 1-4): 0xFF absent, else eggs fed (3 = broken) - uint8_t jinjoGone[4]; // statue broken and its jinjo has already slammed into Grunty - uint8_t jbase; // jinjonator pedestal present - uint8_t jpads[4]; // remaining eggs per jinjonator pedestal pad -} FightWorldSnapshot; - -#ifdef __cplusplus -extern "C" { -#endif - -// --- hooks called by the FINALE actors (implemented in FightSync.c) -------------------- - -// Boss lifecycle: spawn resets sync state; defeat drops every client to local simulation. -void FightSync_OnBossSpawned(void); -void FightSync_OnBossDefeated(void); - -// True = a remote authority drives this boss; chfinalboss_update should skip its brain. -bool FightSync_BossFollowerTick(void* boss /* Actor* */); - -// Forward follower input to the authority; true = handled remotely, skip local apply. -bool FightSync_ForwardBossHit(int32_t phase); -bool FightSync_ForwardEgg(int32_t statue_id, int32_t pad_index); - -// Authority world replication (acts only as the live authority). -void FightSync_ReplicateEgg(int32_t statue_id, int32_t pad_index); -void FightSync_OnSpellSpawned(int32_t kind); -void FightSync_OnFlightPadSpawned(void); -void FightSync_OnFlightPadDespawned(void); -void FightSync_OnBarrierSpawned(void); -void FightSync_OnStatueSpawned(int32_t statue_id); -void FightSync_OnJinjoSlam(int32_t statue_id); - -// --- FINALE entry points used by FightSync.c (implemented in the decomp actors) -------- - -void chjinjonatorbase_netApplyEgg(int32_t pad_index); -bool chjinjonatorbase_netGetPads(uint8_t pads[4]); - -// --- C -> network (bridges implemented in the packet .cpp files) ----------------------- - -void FightSync_SendUpdate(const float pos[3], float yaw, int32_t state, int32_t phase, int32_t mirror, int32_t vuln); -// v0/v1/v2 may be NULL for events that carry no vectors. -void FightSync_SendEvent(int32_t ev, int32_t a, int32_t b, const float v0[3], const float v1[3], const float v2[3]); -void FightSync_SendSnapshot(uint32_t clientId); - -uint32_t FightSyncSeq_Next(void); -bool FightSyncSeq_Accept(uint32_t seq); -void FightSyncSeq_Reset(void); - -// --- network -> sync layer (implemented in FightSync.c) -------------------------------- - -void FightSync_OnAuthorityChanged(void); - -// Fill the stream fields from the live boss; false if there's no boss to stream. -bool FightSync_GatherUpdate(float pos[3], float* yaw, int32_t* state, int32_t* phase, int32_t* mirror, int32_t* vuln); - -void FightSync_ApplyUpdate(const float pos[3], float yaw, int32_t state, int32_t phase, int32_t mirror, int32_t vuln); -void FightSync_ApplyEvent(int32_t ev, int32_t a, int32_t b, const float v0[3], const float v1[3], const float v2[3]); - -// Gather on the authority (false = nothing to send) / apply on a joining follower. -bool FightSync_GatherWorld(FightWorldSnapshot* snap); -void FightSync_ApplyWorld(const FightWorldSnapshot* snap); - -#ifdef __cplusplus -} -#endif diff --git a/src/port/Network/Anchor/HookHandlers.cpp b/src/port/Network/Anchor/HookHandlers.cpp index 6963775f7..884a69486 100644 --- a/src/port/Network/Anchor/HookHandlers.cpp +++ b/src/port/Network/Anchor/HookHandlers.cpp @@ -1,37 +1,17 @@ #include "Anchor.h" #include "Authority.h" #include "VileSync.h" -#include "FightSync.h" #include //#include "soh/frame_interpolation.h" #include "port/Engine.h" -#include "port/UI/Notification.h" -#include "port/Patches/Patches.h" -#include -#include "functions.h" extern "C" { #include "variables.h" +#include "functions.h" float OTRGetDimensionFromLeftEdge(float v); float OTRGetDimensionFromRightEdge(float v); -s32 chMrVile_netGetAnimMode(Actor* actor); -void port_jiggySpawn_remove(int32_t jiggyId); -int32_t port_mapFlag_wasSetRemotely(int32_t index); -bool __chSmBottles_isAnySpiralMountainAbilityLearned(void); -} - -extern "C" void port_fpTwinkly_release(void) { - NetAuthority_Release(NET_ACTIVITY_FP_TWINKLY); -} - -s32 Anchor_LevelOfMap(s32 map); - -// Every listener below that alters vanilla behaviour is wrapped in this. Presence-only rooms -// (the global room, or sync turned off) must play exactly like single player. -static bool Anchor_WorldSyncActive() { - Anchor* anchor = Anchor::GetInstance(); - return anchor != nullptr && anchor->IsWorldSyncActive(); +s32 chvile_netGetAnimMode(Actor* actor); } // True when a remote client owns the Mr. Vile minigame (our local logic must follow). @@ -41,7 +21,8 @@ static bool Anchor_IsVileFollower() { // True when we are the live, connected authority for the Mr. Vile minigame. static bool Anchor_IsVileAuthority() { - return NetAuthority_IsClaimed(NET_ACTIVITY_VILE_MINIGAME) && NetAuthority_IsSelf(NET_ACTIVITY_VILE_MINIGAME); + return Anchor::GetInstance()->isConnected && NetAuthority_IsClaimed(NET_ACTIVITY_VILE_MINIGAME) && + NetAuthority_IsSelf(NET_ACTIVITY_VILE_MINIGAME); } // Authority-side per-frame work: stream Mr. Vile's transform and broadcast the periodic @@ -56,7 +37,7 @@ static void Anchor_UpdateVileSync() { Actor* vile = actorArray_findClosestActorFromActorId(origin, ACTOR_13A_MR_VILE, -1, &dist); if (vile != nullptr) { Anchor::GetInstance()->SendPacket_VileUpdate(vile->position, vile->pitch, vile->yaw, vile->roll, - (u8)chMrVile_netGetAnimMode(vile)); + (u8)chvile_netGetAnimMode(vile)); } static u32 sSnapshotTimer = 0; @@ -66,103 +47,6 @@ static void Anchor_UpdateVileSync() { } } -static void Anchor_UpdateFightSync() { - auto* anchor = Anchor::GetInstance(); - if (!Anchor_WorldSyncActive() || !anchor->IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { - return; - } - - f32 pos[3]; - f32 yaw; - s32 state, phase, mirror, vuln; - if (!FightSync_GatherUpdate(pos, &yaw, &state, &phase, &mirror, &vuln)) { - return; - } - - if (!NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS)) { - NetAuthority_Claim(NET_ACTIVITY_FINAL_BOSS); - } - if (NetAuthority_IsClaimed(NET_ACTIVITY_FINAL_BOSS) && NetAuthority_IsSelf(NET_ACTIVITY_FINAL_BOSS)) { - anchor->SendPacket_FightUpdate(pos, yaw, state, phase, mirror, vuln); - } -} - -static bool Anchor_ShouldBroadcastVolatileFlag(s32 index) { - static const std::unordered_set syncList = { - VOLATILE_FLAG_B6_WITCH_SWITCH_PRESSED_MM, VOLATILE_FLAG_B7_WITCH_SWITCH_PRESSED_MMM, - VOLATILE_FLAG_B8_WITCH_SWITCH_PRESSED_TTC, VOLATILE_FLAG_B9_WITCH_SWITCH_PRESSED_RBB, - VOLATILE_FLAG_BA_WITCH_SWITCH_PRESSED_CCW, VOLATILE_FLAG_BB_WITCH_SWITCH_PRESSED_FP, - VOLATILE_FLAG_BC_WITCH_SWITCH_PRESSED_CC, VOLATILE_FLAG_BD_WITCH_SWITCH_PRESSED_BGS, - VOLATILE_FLAG_BE_WITCH_SWITCH_PRESSED_GV, - }; - return syncList.contains(index); -} - -bool Anchor_ScopedFlagExcluded(s32 space, s32 index) { - static const std::unordered_set excluded = { - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_5_TTC_UNKNOWN, // TTC sandcastle drain - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE, // FP xmas-tree ice shatter - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_30_RBB_UNKNOWN, // RBB anchor/Snorkel chain cutscene - // GV water-pyramid rise: reapplied live from JIGGY_42 in water_pyramidrot.c. - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_6_GV_UNKNOWN, - (ANCHOR_FLAGSPACE_MAP_SPECIFIC << 16) | MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1C_MM_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1D_TTC_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1E_CC_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_1F_BGS_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_20_FP_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_21_GV_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_22_MMM_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_23_RBB_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_24_CCW_OPEN, - (ANCHOR_FLAGSPACE_LEVEL_SPECIFIC << 16) | LEVEL_FLAG_3F_LAIR_GRUNTY_DOOR_OPEN, - }; - if (excluded.contains((space << 16) | index)) { - return true; - } - // BGS jiggy-switch timers (walkway=3, maze=0xC): kept local. - if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_D_BGS_BUBBLEGLOOP_SWAMP && - (index == 3 || index == 0xC)) { - return true; - } - if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_7_TTC_TREASURE_TROVE_COVE && - index <= TTC_SPECIFIC_FLAG_3_BLUBBER_SHOW_JIGGY_SPAWNED_TEXT_FLAG) { - return true; - } - // FP xmas tree star minigame (flags 2/3): per-player, kept local; result syncs via ANCHOR_PUZZLE_FP_TREE_ICE. - if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_27_FP_FREEZEEZY_PEAK && - (index == 2 || index == 3)) { - return true; - } - // FP bear cubs' presents-received flags: kept local; ANCHOR_PUZZLE_FP_PRESENTS syncs the result. - if (space == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC && - (s32)map_getLevel(gsworld_getMap()) == (s32)LEVEL_5_FREEZEEZY_PEAK && - (index == LEVEL_FLAG_11_FP_UNKNOWN || index == LEVEL_FLAG_12_FP_UNKNOWN || index == LEVEL_FLAG_13_FP_UNKNOWN)) { - return true; - } - // SM map flags are entirely Bottles-tutorial choreography; - // syncing any of them runs someone else's state machine. - if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC && gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN) { - return true; - } - return false; -} - -static bool Anchor_ShouldSyncItemCount(s32 item, const RoomState& room) { - switch (item) { - // Progress counters, not consumables; the caller already gates on syncItemsAndFlags. - case ITEM_1C_MUMBO_TOKEN: - case ITEM_26_JIGGY_TOTAL: - return true; - case ITEM_D_EGGS: - case ITEM_F_RED_FEATHER: - case ITEM_10_GOLD_FEATHER: - return room.shareConsumables != 0; - default: - return false; - } -} - void Anchor::RegisterHooks() { // #region Hooks that are required for basic Anchor functionality @@ -184,88 +68,25 @@ void Anchor::RegisterHooks() { Anchor::GetInstance()->ClearDummies(); Anchor::GetInstance()->PopulateDummies((GameMap)ev->nextMap); Authority_OnSelfMapChanged(ev->nextMap); - s32 prevLevel = Anchor_LevelOfMap((s32)ev->prevMap); - if (prevLevel == 0 || prevLevel != Anchor_LevelOfMap((s32)ev->nextMap)) { - Anchor::GetInstance()->SweepUnoccupiedLevelState((GameMap)ev->nextMap); - } Anchor::GetInstance()->SendPacket_MapLoad((GameMap)ev->nextMap, ev->exit); // Anchor::GetInstance()->SendPacket_PlayerUpdate(true); - - auto* anchor = Anchor::GetInstance(); - if (Anchor_WorldSyncActive() && ev->nextMap != MAP_91_FILE_SELECT && ev->nextMap != MAP_1E_CS_START_NINTENDO && - ev->nextMap != MAP_1F_CS_START_RAREWARE) { - anchor->SendPacket_RequestScopedState((GameMap)ev->nextMap); - - s32 enteredFlag = -1; - switch (ev->nextMap) { - case MAP_2_MM_MUMBOS_MOUNTAIN: - enteredFlag = FILEPROG_B0_HAS_ENTERED_MM; - break; - case MAP_7_TTC_TREASURE_TROVE_COVE: - enteredFlag = FILEPROG_B2_HAS_ENTERED_TTC; - break; - case MAP_B_CC_CLANKERS_CAVERN: - enteredFlag = FILEPROG_B8_HAS_ENTERED_CC; - break; - case MAP_D_BGS_BUBBLEGLOOP_SWAMP: - enteredFlag = FILEPROG_B1_HAS_ENTERED_BGS; - break; - case MAP_12_GV_GOBIS_VALLEY: - enteredFlag = FILEPROG_B3_HAS_ENTERED_GV; - break; - case MAP_1B_MMM_MAD_MONSTER_MANSION: - enteredFlag = FILEPROG_B7_HAS_ENTERED_MMM; - break; - case MAP_27_FP_FREEZEEZY_PEAK: - enteredFlag = FILEPROG_B6_HAS_ENTERED_FP; - break; - case MAP_31_RBB_RUSTY_BUCKET_BAY: - enteredFlag = FILEPROG_B4_HAS_ENTERED_RBB; - break; - case MAP_40_CCW_HUB: - enteredFlag = FILEPROG_B5_HAS_ENTERED_CCW; - break; - default: - break; - } - if (enteredFlag >= 0 && fileProgressFlag_get((enum file_progress_e)enteredFlag)) { - anchor->SendPacket_SetFlag((u8)ANCHOR_FLAGSPACE_FILE_PROGRESS, (s16)enteredFlag); - } - } }); COND_HOOK(OnReset, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { Anchor::GetInstance()->SendPacket_MapLoad((GameMap)getDefaultBootMap(), gsworld_getExit()); }); - COND_HOOK(OnGameLoad, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - anchor->hasCheckedRandoCompat = false; - anchor->reloadMapOnTeamState = false; - anchor->SendPacket_RequestTeamState(true); - }); - COND_HOOK(OnPlayerDraw, EVENT_PRIORITY_HIGH, true, [](IEvent* event) { auto drawEv = reinterpret_cast(event); Anchor::GetInstance()->DrawDummies(reinterpret_cast(drawEv)); }); COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_HIGH, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - anchor->SendPacket_PlayerUpdate(); - anchor->ProcessIncomingPacketQueue(); - anchor->RefreshClientActors(); - anchor->UpdateDummies(); + Anchor::GetInstance()->SendPacket_PlayerUpdate(); + Anchor::GetInstance()->ProcessIncomingPacketQueue(); + Anchor::GetInstance()->RefreshClientActors(); + Anchor::GetInstance()->UpdateDummies(); Anchor_UpdateVileSync(); - Anchor_UpdateFightSync(); - - if (Anchor_WorldSyncActive() && anchor->IsSaveLoaded()) { - anchor->FlushPendingJiggySpawns(); - if (!anchor->hasCheckedRandoCompat) { - anchor->CheckRandoRoomCompatibility(); - anchor->hasCheckedRandoCompat = true; - } - } }); COND_HOOK(OnPlayerTransformChange, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { @@ -279,12 +100,14 @@ void Anchor::RegisterHooks() { // returning to idle (or the player declining) releases it. COND_HOOK(OnVileGameStateChange, EVENT_PRIORITY_NORMAL, true, [](IEvent* event) { auto ev = reinterpret_cast(event); - if (!Anchor_WorldSyncActive() || gsworld_getMap() != MAP_10_BGS_MR_VILE) { + if (!Anchor::GetInstance()->isConnected || gsworld_getMap() != MAP_10_BGS_MR_VILE) { return; } if (ev->state >= 2) { NetAuthority_Claim(NET_ACTIVITY_VILE_MINIGAME); - // Push round start/end immediately rather than waiting for the periodic snapshot. + // Push the transition immediately (round start, round end with its result + // jingle) instead of waiting for the next periodic snapshot. Gather rejects + // the non-broadcast states, so this is a no-op for dialog transitions. if (Anchor_IsVileAuthority()) { Anchor::GetInstance()->SendPacket_VileGameState(); } @@ -310,78 +133,6 @@ void Anchor::RegisterHooks() { }); // Followers: suppress local random logic; network state drives these instead. - COND_VB_SHOULD(VB_CCW_FLOWER_REMOTE_GROW, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - s32 stageFlag = va_arg(args, s32); - *should = fileProgressFlag_get((enum file_progress_e)stageFlag) != 0; - } - }); - - COND_VB_SHOULD(VB_CC_RINGS_SNAP_WATER, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - *should = false; - } - }); - - // Vanilla despawns the CCW podium until its switch is pressed, and only rebuilds it when the cube - // re-streams. Keep the actor alive (hidden) instead, so a teammate's press reveals it in place. - COND_VB_SHOULD(VB_CCW_PODIUM_DESPAWN, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - *should = false; - } - }); - - COND_VB_SHOULD(VB_JIGSAW_PICTURE_RESYNC, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - *should = true; - } - }); - - // Lair door remote-open: Door of Grunty's open flag (0xE2) is already set on arrival; key off - // visual state (fully open == 0x1B) instead. Other lair doors stay flag-based. - COND_VB_SHOULD(VB_LEVELDOOR_REMOTE_OPEN_DONE, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - s32 doorActorId = va_arg(args, s32); - s32 doorState = va_arg(args, s32); - if (doorActorId == ACTOR_2E5_LARGE_DOOR_TO_FINAL_BATTLE) { - *should = (doorState == 0x1B); - } - } - }); - - COND_VB_SHOULD(VB_FP_TWINKLY_START, EVENT_PRIORITY_NORMAL, isConnected, { - if (NetAuthority_IsClaimed(NET_ACTIVITY_FP_TWINKLY) && !NetAuthority_IsSelf(NET_ACTIVITY_FP_TWINKLY)) { - *should = false; - } else { - NetAuthority_Claim(NET_ACTIVITY_FP_TWINKLY); - } - }); - - COND_VB_SHOULD(VB_DOOR_OPEN_CAMERA, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - s32 doorId = va_arg(args, s32); - switch (doorId) { - case GV_DOOR_CAM_SUN: - *should = !port_mapFlag_wasSetRemotely(3); - break; - case GV_DOOR_CAM_STAR: - *should = !port_mapFlag_wasSetRemotely(5); - break; - case GV_DOOR_CAM_KAZOOIE: - *should = !port_mapFlag_wasSetRemotely(6); - break; - case GV_DOOR_CAM_JINXY: - *should = !(port_mapFlag_wasSetRemotely(0) && port_mapFlag_wasSetRemotely(1)); - break; - case MMM_DOOR_CAM_CHURCH: - *should = !port_mapFlag_wasSetRemotely(0); // MMM_SPECIFIC_FLAG_0_UNKNOWN - break; - default: - break; - } - } - }); - COND_VB_SHOULD(VB_VILE_YUMBLIE_EMERGE, EVENT_PRIORITY_NORMAL, true, { if (Anchor_IsVileFollower()) { *should = false; @@ -437,139 +188,29 @@ void Anchor::RegisterHooks() { Anchor::GetInstance()->OnActorDestroyed(ev->actor); }); - // #region Flag sync - - COND_HOOK(OnGameFlagSet, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { - return; - } - auto ev = reinterpret_cast(event); - for (s32 i = 0; i < ev->length; i++) { - s32 index = ev->index + i; - if (ev->flagSpace == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC) { - if (Anchor_ScopedFlagExcluded(ev->flagSpace, index)) { - continue; - } - anchor->SendPacket_ScopedFlag((u8)ev->flagSpace, (s16)index, - (u8)(levelSpecificFlags_get(index) ? 1 : 0)); - continue; - } - if (ev->flagSpace == ANCHOR_FLAGSPACE_MAP_SPECIFIC) { - if (Anchor_ScopedFlagExcluded(ev->flagSpace, index)) { - continue; - } - anchor->SendPacket_ScopedFlag((u8)ev->flagSpace, (s16)index, (u8)(mapSpecificFlags_get(index) ? 1 : 0)); - continue; - } - s32 bit; - if (ev->flagSpace == ANCHOR_FLAGSPACE_VOLATILE) { - if (!Anchor_ShouldBroadcastVolatileFlag(index)) { - continue; - } - bit = volatileFlag_get((enum volatile_flags_e)index); - } else { - bit = fileProgressFlag_get((enum file_progress_e)index); - } - if (bit) { - anchor->SendPacket_SetFlag((u8)ev->flagSpace, (s16)index); - } else { - anchor->SendPacket_UnsetFlag((u8)ev->flagSpace, (s16)index); - } - } - }); - - COND_HOOK(OnItemCountChanged, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { - return; - } - auto ev = reinterpret_cast(event); - if (Anchor_ShouldSyncItemCount(ev->item, anchor->roomState)) { - anchor->SendPacket_SetItemCount((s16)ev->item, ev->count); - } - }); - - COND_HOOK(OnAbilityLearned, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { - return; - } - auto ev = reinterpret_cast(event); - anchor->SendPacket_SetAbility((s16)ev->move, (u8)ev->value); - }); - - COND_HOOK(OnCollectibleCollected, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { - return; - } - auto ev = reinterpret_cast(event); - anchor->SendPacket_CollectItem((u8)ev->kind, (s32)ev->id); - }); - - COND_HOOK(OnRandoCheckObtained, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { - return; - } - auto ev = reinterpret_cast(event); - anchor->SendPacket_SetCheckStatus((s32)ev->randoCheckId, (s32)ev->map); - }); - - COND_HOOK(OnJiggySpawned, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto* anchor = Anchor::GetInstance(); - if (!anchor->IsSaveLoaded() || !anchor->roomState.syncItemsAndFlags) { - return; - } - auto ev = reinterpret_cast(event); - anchor->SendPacket_SpawnJiggy((s16)ev->jiggyId, ev->x, ev->y, ev->z); - }); - - COND_HOOK(OnHoneycombDropSpawn, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - auto ev = reinterpret_cast(event); - Anchor::GetInstance()->SendPacket_SpawnHoneycomb((s16)ev->honeycombId, ev->bundleId, ev->x, ev->y, ev->z); - }); - - // SM intro Bottles: the tutorial offer is first-answer-wins for the team. - COND_VB_SHOULD(VB_SM_TUTORIAL_CHOICE_OPEN, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive()) { - // By level, not map: a romhack's Spiral Mountain may be a different map id. - if (__chSmBottles_isAnySpiralMountainAbilityLearned() || - (port_puzzleStep_getForLevel(LEVEL_B_SPIRAL_MOUNTAIN, ANCHOR_PUZZLE_SM_TUTORIAL) & 1)) { - *should = false; - } else if (NetAuthority_IsClaimed(NET_ACTIVITY_SM_TUTORIAL) && - !NetAuthority_IsSelf(NET_ACTIVITY_SM_TUTORIAL)) { - *should = false; - } else { - NetAuthority_Claim(NET_ACTIVITY_SM_TUTORIAL); - } - } - }); - - // Ability molehills wake up only after the tutorial choice exists: the offer was - // answered (synced bit) or a move is already known (covers skip-tutorial saves). - COND_VB_SHOULD(VB_SM_MOLEHILL_ACTIVE, EVENT_PRIORITY_NORMAL, isConnected, { - if (Anchor_WorldSyncActive() && !__chSmBottles_isAnySpiralMountainAbilityLearned() && - !(port_puzzleStep_getForLevel(LEVEL_B_SPIRAL_MOUNTAIN, ANCHOR_PUZZLE_SM_TUTORIAL) & 1)) { - *should = false; - } - }); - - COND_HOOK(OnTimedJiggyExpired, EVENT_PRIORITY_NORMAL, isConnected, [](IEvent* event) { - if (!Anchor_WorldSyncActive()) { - return; - } - auto ev = reinterpret_cast(event); - port_jiggySpawn_remove(ev->jiggyId); - }); - - COND_HOOK(OnSaveFileSave, EVENT_PRIORITY_NORMAL, isConnected, - [](IEvent* event) { Anchor::GetInstance()->SendPacket_UpdateTeamState(); }); - - // #endregion - // COND_HOOK(OnPlayerSfx, isConnected, [&](u16 sfxId) { SendPacket_PlayerSfx(sfxId); }); + // COND_HOOK(OnOcarinaNote, isConnected, + // [&](uint8_t note, float modulator, int8_t bend) { SendPacket_OcarinaSfx(note, modulator, bend); }); + // + // COND_HOOK(OnLoadGame, isConnected, [&](s16 fileNum) { justLoadedSave = true; }); + // + // COND_HOOK(OnSaveFile, isConnected, [&](s16 fileNum, int sectionID) { + // if (sectionID == 0) { + // SendPacket_UpdateTeamState(); + // } + // }); + // + // COND_HOOK(OnFlagSet, isConnected, + // [&](s16 flagType, s16 flag) { SendPacket_SetFlag(SCENE_ID_MAX, flagType, flag); }); + // + // COND_HOOK(OnFlagUnset, isConnected, + // [&](s16 flagType, s16 flag) { SendPacket_UnsetFlag(SCENE_ID_MAX, flagType, flag); }); + // + // COND_HOOK(OnSceneFlagSet, isConnected, + // [&](s16 sceneNum, s16 flagType, s16 flag) { SendPacket_SetFlag(sceneNum, flagType, flag); }); + // + // COND_HOOK(OnSceneFlagUnset, isConnected, + // [&](s16 sceneNum, s16 flagType, s16 flag) { SendPacket_UnsetFlag(sceneNum, flagType, flag); }); // // COND_HOOK(OnRandoSetCheckStatus, isConnected, [&](RandomizerCheck rc, RandomizerCheckStatus status) { // if (!isHandlingUpdateTeamState) { diff --git a/src/port/Network/Anchor/JigsawPedestal.cpp b/src/port/Network/Anchor/JigsawPedestal.cpp deleted file mode 100644 index 7341efcbb..000000000 --- a/src/port/Network/Anchor/JigsawPedestal.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "port/Network/Anchor/JigsawPedestal.h" -#include "port/Network/Anchor/Anchor.h" -#include "functions.h" -#include -#include - -static std::unordered_map sPedestalOwner; - -static bool JigsawPedestal_SyncActive() { - Anchor* anchor = Anchor::GetInstance(); - return anchor != nullptr && anchor->IsWorldSyncActive(); -} - -int32_t port_jigsawPedestal_tryClaim(int32_t id) { - Anchor* anchor = Anchor::GetInstance(); - if (!JigsawPedestal_SyncActive()) { - return 1; - } - auto it = sPedestalOwner.find(id); - if (it != sPedestalOwner.end() && it->second != anchor->ownClientId) { - return 0; - } - sPedestalOwner[id] = anchor->ownClientId; - anchor->SendPacket_PedestalOwner(id, true); - return 1; -} - -int32_t port_jigsawPedestal_isSelf(int32_t id) { - Anchor* anchor = Anchor::GetInstance(); - if (!JigsawPedestal_SyncActive()) { - return 1; - } - auto it = sPedestalOwner.find(id); - return (it == sPedestalOwner.end() || it->second == anchor->ownClientId) ? 1 : 0; -} - -void port_jigsawPedestal_release(int32_t id) { - Anchor* anchor = Anchor::GetInstance(); - if (!JigsawPedestal_SyncActive()) { - return; - } - // Keep a finished picture's claim until we leave the map: vanilla already refuses to let anyone - // step back on it, and holding covers a teammate whose completion bits are still in flight. - if (jigsawPicture_isJigsawPictureComplete(id)) { - return; - } - auto it = sPedestalOwner.find(id); - if (it != sPedestalOwner.end() && it->second == anchor->ownClientId) { - sPedestalOwner.erase(it); - anchor->SendPacket_PedestalOwner(id, false); - } -} - -void JigsawPedestal_ApplyRemote(int32_t id, uint32_t clientId, bool claimed) { - auto it = sPedestalOwner.find(id); - if (claimed) { - // Simultaneous-claim tie-break: lowest clientId wins. - if (it == sPedestalOwner.end() || clientId < it->second) { - sPedestalOwner[id] = clientId; - } - } else if (it != sPedestalOwner.end() && it->second == clientId) { - sPedestalOwner.erase(it); - } -} - -void JigsawPedestal_ClearClient(uint32_t clientId) { - for (auto it = sPedestalOwner.begin(); it != sPedestalOwner.end();) { - it = (it->second == clientId) ? sPedestalOwner.erase(it) : std::next(it); - } -} - -void JigsawPedestal_ReleaseAllSelf() { - Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr) { - return; - } - std::vector mine; - for (auto& [id, owner] : sPedestalOwner) { - if (owner == anchor->ownClientId) { - mine.push_back(id); - } - } - for (int32_t id : mine) { - sPedestalOwner.erase(id); - if (anchor->isConnected) { - anchor->SendPacket_PedestalOwner(id, false); - } - } -} - -void JigsawPedestal_Reset() { - sPedestalOwner.clear(); -} diff --git a/src/port/Network/Anchor/JigsawPedestal.h b/src/port/Network/Anchor/JigsawPedestal.h deleted file mode 100644 index dbf37379e..000000000 --- a/src/port/Network/Anchor/JigsawPedestal.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include - -// Per-pedestal interaction lock for the Lair jigsaw podiums (keyed by actorTypeSpecificField). - -#ifdef __cplusplus -extern "C" { -#endif - -int32_t port_jigsawPedestal_tryClaim(int32_t id); -// 1 if we may drive this podium (unowned/self/offline), 0 if another owns it. -int32_t port_jigsawPedestal_isSelf(int32_t id); -void port_jigsawPedestal_release(int32_t id); - -#ifdef __cplusplus -} - -// Network-internal entry points (Anchor packet handlers / lifecycle). -void JigsawPedestal_ApplyRemote(int32_t id, uint32_t clientId, bool claimed); -void JigsawPedestal_ClearClient(uint32_t clientId); -void JigsawPedestal_ReleaseAllSelf(); -void JigsawPedestal_Reset(); -#endif diff --git a/src/port/Network/Anchor/JsonConversions.hpp b/src/port/Network/Anchor/JsonConversions.hpp index b9d250b77..243b8b25e 100644 --- a/src/port/Network/Anchor/JsonConversions.hpp +++ b/src/port/Network/Anchor/JsonConversions.hpp @@ -22,42 +22,9 @@ inline void to_json(json& j, const Color_RGB8& color) { j = json{ { "r", color.r }, { "g", color.g }, { "b", color.b } }; } -// Model colors travel as a fixed-length array, one entry per BKColorChannel. Clients that -// predate the feature simply omit the key and everyone renders them with vanilla colors. -inline void from_json(const json& j, BKPlayerColorSet& colors) { - colors = BKPlayerColorSet{}; - if (!j.is_array()) { - return; - } - for (size_t i = 0; i < j.size() && i < (size_t)BK_COLOR_CHANNEL_COUNT; i++) { - const json& entry = j[i]; - if (!entry.is_object()) { - continue; - } - colors.channel[i].enabled = entry.value("on", false) ? 1 : 0; - colors.channel[i].r = entry.value("r", (u8)0); - colors.channel[i].g = entry.value("g", (u8)0); - colors.channel[i].b = entry.value("b", (u8)0); - } -} - -inline void to_json(json& j, const BKPlayerColorSet& colors) { - j = json::array(); - for (int i = 0; i < BK_COLOR_CHANNEL_COUNT; i++) { - j.push_back(json{ { "on", colors.channel[i].enabled != 0 }, - { "r", colors.channel[i].r }, - { "g", colors.channel[i].g }, - { "b", colors.channel[i].b } }); - } -} - inline void from_json(const json& j, AnchorClient& client) { client.clientId = j.value("clientId", (u32)0); client.name = j.value("name", "???"); - client.colors = BKPlayerColorSet{}; - if (j.contains("colors")) { - from_json(j.at("colors"), client.colors); - } client.clientVersion = j.value("clientVersion", "???"); client.teamId = j.value("teamId", "default"); client.online = j.value("online", false); @@ -67,7 +34,6 @@ inline void from_json(const json& j, AnchorClient& client) { client.map = j.value("map", MAP_0_UNKNOWN); client.exit = j.value("exit", (s32)0); client.self = j.value("self", false); - client.cutsceneReturnMap = 0; } #endif // __cplusplus diff --git a/src/port/Network/Anchor/Menu.cpp b/src/port/Network/Anchor/Menu.cpp index f9080c128..afff951ed 100644 --- a/src/port/Network/Anchor/Menu.cpp +++ b/src/port/Network/Anchor/Menu.cpp @@ -1,12 +1,8 @@ #include "Anchor.h" -#include #include #include "port/UI/LighthouseGui.hpp" #include "port/UI/LighthouseMenu.h" #include "port/ShipUtils.h" -#include "port/Romhack/RomhackConfig.h" -#include "port/Romhack/RomhackCompat.h" -#include "port/Rando/Rando.h" namespace LighthouseGui { extern std::shared_ptr mLighthouseMenu; @@ -17,68 +13,6 @@ static const char* pvpModes[3] = { "Off", "On", "On + Friendly Fire" }; static std::vector teleportModes = { "None", "Team Only", "All" }; static std::vector showLocationsModes = { "None", "Team Only", "All" }; -static const char* playerColorLabels[BK_COLOR_CHANNEL_COUNT] = { - "Banjo's fur", "Banjo's shorts", "Kazooie's feathers", "Kazooie's beak & legs", "Banjo's backpack", "Banjo's skin", -}; - -// Channel order is the wire order; this is the order the rows are listed in. -static const int playerColorOrder[BK_COLOR_CHANNEL_COUNT] = { - BK_COLOR_BANJO_FUR, BK_COLOR_BANJO_SKIN, BK_COLOR_BANJO_SHORTS, - BK_COLOR_BANJO_BACKPACK, BK_COLOR_KAZOOIE_FEATHERS, BK_COLOR_KAZOOIE_BEAK, -}; - -// Per-part recoloring of the player model. Any mix of channels can be enabled; each one -// re-tints only the palette entries and vertex colors belonging to that part, so shading -// is preserved. The selection is part of client state, so everyone in the room sees it. -static void AnchorPlayerColorSection(Anchor* anchor) { - UIWidgets::PushStyleHeader(THEME_COLOR); - if (!ImGui::CollapsingHeader("Player Colors")) { - UIWidgets::PopStyleHeader(); - return; - } - - ImGui::TextWrapped("Tick a part and pick a color to recolor Banjo & Kazooie. Other players in your " - "room see your choices. Transformations keep their own colors."); - ImGui::Spacing(); - - for (int row = 0; row < BK_COLOR_CHANNEL_COUNT; row++) { - const int i = playerColorOrder[row]; - const char* baseCVar = PlayerColors_getChannelCVar(i); - if (baseCVar == nullptr) { - continue; - } - u8 r, g, b; - PlayerColors_getVanilla(i, &r, &g, &b); - const Color_RGBA8 vanilla = { r, g, b, 255 }; - const std::string enabledCVar = std::string(baseCVar) + ".Enabled"; - const std::string pickerLabel = std::string("##") + baseCVar; - - ImGui::PushID(i); - UIWidgets::CVarColorPicker(pickerLabel.c_str(), baseCVar, vanilla, false, - UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRandomButton, THEME_COLOR); - ImGui::SameLine(); - UIWidgets::CVarCheckbox(playerColorLabels[i], enabledCVar.c_str(), - UIWidgets::CheckboxOptions().DefaultValue(false).Color(THEME_COLOR)); - ImGui::PopID(); - } - - // Compare the resulting set rather than the widgets' return values: Reset and Random - // write the CVar without reporting a change. - static BKPlayerColorSet lastSent = {}; - static bool haveLastSent = false; - BKPlayerColorSet current; - PlayerColors_getLocal(¤t); - if (!haveLastSent || std::memcmp(¤t, &lastSent, sizeof(current)) != 0) { - lastSent = current; - haveLastSent = true; - if (anchor->isEnabled) { - anchor->SendPacket_UpdateClientState(); - } - } - - UIWidgets::PopStyleHeader(); -} - void AnchorMainMenu(WidgetInfo& info) { auto anchor = Anchor::GetInstance(); @@ -111,7 +45,10 @@ void AnchorMainMenu(WidgetInfo& info) { } UIWidgets::PopStyleInput(); - ImGui::Text("Name"); + ImGui::Text("Name & Color"); + static Color_RGBA8 defaultColor = { 100, 255, 100, 255 }; + UIWidgets::CVarColorPicker("##Color", CVAR_REMOTE_ANCHOR("Color"), defaultColor); + ImGui::SameLine(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (UIWidgets::InputString("##Name", &anchorName, UIWidgets::InputOptions().Color(THEME_COLOR))) { CVarSetString(CVAR_REMOTE_ANCHOR("Name"), anchorName.c_str()); @@ -147,13 +84,12 @@ void AnchorMainMenu(WidgetInfo& info) { if (UIWidgets::Button("Global Room", UIWidgets::ButtonOptions() .Color(UIWidgets::Colors::Blue) - .Tooltip("Always-online public room so you don't have to explore alone. " - "You'll see other players' characters, but nothing is synced - " - "no items, flags, PvP, or teleporting."))) { + .Tooltip("Always-online public room so you don't have to experience " + "Hyrule alone. PVP and syncing are disabled."))) { CVarSetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org"); CVarSetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383); CVarSetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), "lh-global"); + CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), "soh-global"); Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); } @@ -180,42 +116,6 @@ void AnchorMainMenu(WidgetInfo& info) { ImGui::EndDisabled(); ImGui::Spacing(); - AnchorPlayerColorSection(anchor); - - ImGui::Spacing(); - - UIWidgets::CVarCheckbox("Show Player Nametags", CVAR_REMOTE_ANCHOR("Nametags"), - UIWidgets::CheckboxOptions() - .DefaultValue(true) - .Color(THEME_COLOR) - .Tooltip("Draw each other player's name above their character.")); - - if (CVarGetInteger(CVAR_REMOTE_ANCHOR("Nametags"), 1)) { - UIWidgets::CVarSliderFloat("Nametag Distance", CVAR_REMOTE_ANCHOR("NametagScale"), - UIWidgets::FloatSliderOptions() - .Min(0.5f) - .Max(6.0f) - .Step(0.5f) - .DefaultValue(1.0f) - .ShowButtons(true) - .Format("%.1fx") - .Color(THEME_COLOR) - .Tooltip("Multiplies how far away another player's nametag stays visible.")); - } - - ImGui::Spacing(); - - UIWidgets::CVarCheckbox( - "Show Teammate Notifications", CVAR_REMOTE_ANCHOR("Notifications"), - UIWidgets::CheckboxOptions() - .DefaultValue(true) - .Color(THEME_COLOR) - .Tooltip("Show a notification when a teammate collects a jiggy, opens a level, or (in a " - "randomizer) obtains a shuffled check. Randomizer check notifications also require " - "\"Send Collection Notifications\" to be enabled in the Randomizer settings.")); - - ImGui::Spacing(); - if (!anchor->isEnabled) { return; } @@ -228,32 +128,45 @@ void AnchorMainMenu(WidgetInfo& info) { ImGui::SeparatorText("Current Room"); ImGui::Text("%s Connected", ICON_FA_CHECK); - if (!anchor->IsGlobalRoom()) { - UIWidgets::PushStyleButton(THEME_COLOR); - if (ImGui::Button("Request Team State")) { - anchor->SendPacket_RequestTeamState(); - anchor->reloadMapOnTeamState = true; - } - UIWidgets::Tooltip("Try this if you are missing items or flags that your team members have collected"); - UIWidgets::PopStyleButton(); - - ImGui::SameLine(); + UIWidgets::PushStyleButton(THEME_COLOR); + if (ImGui::Button("Request Team State")) { + anchor->SendPacket_RequestTeamState(); } + UIWidgets::Tooltip("Try this if you are missing items or flags that your team members have collected"); + UIWidgets::PopStyleButton(); + + ImGui::SameLine(); - UIWidgets::WindowButton("Toggle Anchor Room Window", CVAR_WINDOW("AnchorRoom"), LighthouseGui::mAnchorRoomWindow); + // UIWidgets::WindowButton("Toggle Anchor Room Window", CVAR_WINDOW("AnchorRoom"), SohGui::mAnchorRoomWindow); ImGui::Spacing(); - if (!LighthouseGui::mAnchorRoomWindow->IsVisible()) { - LighthouseGui::mAnchorRoomWindow->DrawElement(); - } + bool hideLocations = Anchor::GetInstance()->roomState.showLocationsMode == 0; + ImGui::BeginDisabled(hideLocations); + UIWidgets::CVarCheckbox( + "Show Other Players on Minimap", CVAR_REMOTE_ANCHOR("ShowOtherPlayersOnMinimap"), + UIWidgets::CheckboxOptions() + .Color(THEME_COLOR) + .DefaultValue(true) + .Tooltip(!hideLocations + ? "Other players will appear on the minimap in areas where you have the compass. " + "Visibility is restricted according to the Show Locations mode for the room." + : "Cannot show other players because the room's Show Locations mode is set to None.")); + ImGui::EndDisabled(); + + ImGui::Spacing(); + + /*if (!SohGui::mAnchorRoomWindow->IsVisible()) { + SohGui::mAnchorRoomWindow->DrawElement(); + }*/ } void AnchorAdminMenu(WidgetInfo& info) { auto anchor = Anchor::GetInstance(); + bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); if (!anchor->isEnabled || !anchor->isConnected || anchor->roomState.ownerClientId != anchor->ownClientId || - anchor->IsGlobalRoom()) { + isGlobalRoom) { return; } @@ -268,23 +181,16 @@ void AnchorAdminMenu(WidgetInfo& info) { for (auto& team : teams) { anchor->SendPacket_ClearTeamState(team); } - anchor->roomState.isRomhack = port_isRomhack(); - anchor->roomState.romhackName = Lighthouse::CurrentRomhackLabel(); - anchor->roomState.isRando = IS_RANDO; - anchor->roomState.seed = IS_RANDO ? (int32_t)RANDO_SEED : 0; - anchor->lastWarnedRomhackLabel.clear(); - anchor->lastWarnedRandoState.clear(); - anchor->SendPacket_UpdateRoomState(); } UIWidgets::PopStyleButton(); - // if (UIWidgets::CVarCombobox("PvP Mode:", CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), pvpModes, - // UIWidgets::ComboboxOptions() - // .DefaultIndex(1) - // .LabelPosition(UIWidgets::LabelPositions::Above) - // .Color(THEME_COLOR))) { - // anchor->SendPacket_UpdateRoomState(); - // } + if (UIWidgets::CVarCombobox("PvP Mode:", CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), pvpModes, + UIWidgets::ComboboxOptions() + .DefaultIndex(1) + .LabelPosition(UIWidgets::LabelPositions::Above) + .Color(THEME_COLOR))) { + anchor->SendPacket_UpdateRoomState(); + } if (UIWidgets::CVarCombobox("Show Locations For:", CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), showLocationsModes, UIWidgets::ComboboxOptions() @@ -304,11 +210,6 @@ void AnchorAdminMenu(WidgetInfo& info) { UIWidgets::CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { anchor->SendPacket_UpdateRoomState(); } - if (UIWidgets::CVarCheckbox("Share Consumables (Eggs/Feathers)", - CVAR_REMOTE_ANCHOR("RoomSettings.ShareConsumables"), - UIWidgets::CheckboxOptions().DefaultValue(false).Color(THEME_COLOR))) { - anchor->SendPacket_UpdateRoomState(); - } } void AnchorInstructionsMenu(WidgetInfo& info) { @@ -321,13 +222,16 @@ void AnchorInstructionsMenu(WidgetInfo& info) { ImGui::TextWrapped("2. Come up with a unique Room ID (this is basically your password) and enter it, along with " "your desired player name and team ID and click Enable"); - ImGui::TextWrapped("3. For Rando: The host should configure the randomizer settings and generate a seed, then get " - "in game to create a save file to share."); + ImGui::TextWrapped("3. The host should configure the randomizer settings and generate a seed, then share the newly " + "generated JSON spoiler file with other players."); + + ImGui::TextWrapped("4. All players should load the same JSON spoiler file (drag it into SoH window), make sure " + "seed icons match, then create a new file."); - ImGui::TextWrapped("4. All players should now load into their game. IMPORTANT! If using an existing save/seed " + ImGui::TextWrapped("5. All players should now load into their game. IMPORTANT! If using an existing save/seed " "ensure the player with the most progress loads the file first."); - ImGui::TextWrapped("5. After everyone has loaded in, verify on the network tab that it doesn't warn about anyone " + ImGui::TextWrapped("6. After everyone has loaded in, verify on the network tab that it doesn't warn about anyone " "being on a wrong version or seed."); ImGui::Spacing(); diff --git a/src/port/Network/Anchor/Packets/AllClientState.cpp b/src/port/Network/Anchor/Packets/AllClientState.cpp index 59d6ee01a..0def295e9 100644 --- a/src/port/Network/Anchor/Packets/AllClientState.cpp +++ b/src/port/Network/Anchor/Packets/AllClientState.cpp @@ -6,7 +6,9 @@ #include "port/Engine.h" #include "port/UI/Notification.h" +extern "C" { #include "functions.h" +} /** * ALL_CLIENT_STATE @@ -18,13 +20,11 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { std::vector newClients = payload["state"].get>(); - bool isGlobalRoom = IsGlobalRoom(); + bool isGlobalRoom = (std::string("lh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); std::vector clientsToRemove; - uint32_t joinOrder = 0; // add new clients for (auto& client : newClients) { - client.joinOrder = client.online ? ++joinOrder : 0; if (!client.online && clients.contains(client.clientId)) { clientsToRemove.push_back(client.clientId); } @@ -64,9 +64,6 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { clients[client.clientId].isGameComplete = client.isGameComplete; clients[client.clientId].map = client.map; clients[client.clientId].exit = client.exit; - clients[client.clientId].joinOrder = client.joinOrder; - clients[client.clientId].colors = client.colors; - ApplyClientCosmetics(client.clientId); Authority_OnClientStateChanged(client.clientId, client.online, client.map); } @@ -83,7 +80,6 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { if (dummies.contains(clientId)) { dummies.erase(clientId); } - PlayerColors_forgetOwner(clientId); if (clients.at(clientId).dummy != nullptr) { clients.at(clientId).dummy->dummy_free(); free(clients.at(clientId).dummy); @@ -92,6 +88,5 @@ void Anchor::HandlePacket_AllClientState(nlohmann::json& payload) { } PopulateDummies((GameMap)gsworld_getMap()); - SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); SendPacket_PlayerUpdate(true); } diff --git a/src/port/Network/Anchor/Packets/BreakObject.cpp b/src/port/Network/Anchor/Packets/BreakObject.cpp deleted file mode 100644 index ae42e9d20..000000000 --- a/src/port/Network/Anchor/Packets/BreakObject.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include -#include - -#include "functions.h" - -#include "port/Patches/Patches.h" - -/** - * BREAK_OBJECT - */ - -std::set> sBrokenObjects; - -extern "C" int32_t port_breakable_isBroken(int32_t map, int32_t markerId, int32_t x, int32_t y, int32_t z) { - return sBrokenObjects.count({ map, markerId, x, y, z }) != 0 ? 1 : 0; -} - -std::vector port_breakable_snapshotBroken() { - std::vector flat; - flat.reserve(sBrokenObjects.size() * 5); - for (const auto& e : sBrokenObjects) { - flat.insert(flat.end(), e.begin(), e.end()); - } - return flat; -} - -void port_breakable_restoreBroken(const std::vector& flat) { - sBrokenObjects.clear(); - for (size_t i = 0; i + 5 <= flat.size(); i += 5) { - sBrokenObjects.insert({ flat[i], flat[i + 1], flat[i + 2], flat[i + 3], flat[i + 4] }); - } -} - -void port_breakable_clearForLevel(int32_t levelId) { - std::erase_if(sBrokenObjects, [levelId](const std::array& e) { - return (int32_t)map_getLevel((enum map_e)e[0]) == levelId; - }); -} - -void Anchor::SendPacket_BreakObject(s16 markerId, s32 x, s32 y, s32 z, s32 map, bool replay) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = BREAK_OBJECT; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["marker"] = markerId; - payload["x"] = x; - payload["y"] = y; - payload["z"] = z; - payload["map"] = map; - payload["replay"] = replay; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_BreakObject(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s16 markerId = payload.at("marker").get(); - s32 x = payload.at("x").get(); - s32 y = payload.at("y").get(); - s32 z = payload.at("z").get(); - s32 map = payload.at("map").get(); - bool replay = payload.contains("replay") ? payload.at("replay").get() : true; - - sBrokenObjects.insert({ map, markerId, x, y, z }); - if (replay && (s32)gsworld_getMap() == map) { - port_breakable_remoteBreakAt(markerId, x, y, z); - } -} - -extern "C" void port_breakable_broadcastBreak(int32_t markerId, int32_t x, int32_t y, int32_t z) { - s32 map = (s32)gsworld_getMap(); - if (sBrokenObjects.count({ map, markerId, x, y, z }) != 0) { - return; - } - sBrokenObjects.insert({ map, markerId, x, y, z }); - Anchor::GetInstance()->SendPacket_BreakObject((s16)markerId, x, y, z, map); -} - -extern "C" void port_breakable_recordBreak(int32_t markerId, int32_t x, int32_t y, int32_t z) { - s32 map = (s32)gsworld_getMap(); - if (sBrokenObjects.count({ map, markerId, x, y, z }) != 0) { - return; - } - sBrokenObjects.insert({ map, markerId, x, y, z }); - Anchor::GetInstance()->SendPacket_BreakObject((s16)markerId, x, y, z, map, false); -} - -extern "C" void port_breakable_despawnBrokenRestores(s32 map); - -void RegisterBreakObject_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sBrokenObjects.clear(); }); - - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnMapLoad* ev = (OnMapLoad*)event; - port_breakable_despawnBrokenRestores((s32)ev->nextMap); - }); -} - -static RegisterShipInitFunc initBreakObject(RegisterBreakObject_Init, {}); diff --git a/src/port/Network/Anchor/Packets/CarryThrow.cpp b/src/port/Network/Anchor/Packets/CarryThrow.cpp deleted file mode 100644 index a74d22195..000000000 --- a/src/port/Network/Anchor/Packets/CarryThrow.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/Patches/Patches.h" - -#include "functions.h" - -/** - * CARRY_THROW - */ - -void Anchor::SendPacket_CarryThrow(s32 markerId, f32 start[3], f32 target[3]) { - if (!IsSaveLoaded()) { - return; - } - - nlohmann::json payload; - payload["type"] = CARRY_THROW; - payload["marker"] = markerId; - payload["start"] = { start[0], start[1], start[2] }; - payload["target"] = { target[0], target[1], target[2] }; - - SendToCurrentMapPlayers(payload); -} - -void Anchor::HandlePacket_CarryThrow(nlohmann::json& payload) { - if (!IsSaveLoaded()) { - return; - } - - uint32_t clientId = payload.value("clientId", 0u); - s32 markerId = payload.value("marker", 0); - std::vector start = payload["start"].get>(); - std::vector target = payload["target"].get>(); - if (start.size() < 3 || target.size() < 3) { - return; - } - - port_remoteCarry_throw(clientId, markerId, start.data(), target.data()); -} - -extern "C" void port_anchor_onCarryThrow(s32 markerId, f32 start[3], f32 target[3]) { - Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected) { - return; - } - anchor->SendPacket_CarryThrow(markerId, start, target); -} - -extern "C" s32 port_anchor_getDummyTransform(u32 clientId, f32 pos[3], f32* yaw) { - Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected) { - return 0; - } - auto it = anchor->clients.find(clientId); - if (it == anchor->clients.end() || !it->second.online || it->second.dummy == nullptr || - (s32)it->second.map != (s32)gsworld_getMap()) { - return 0; - } - it->second.dummy->dummy_getPosition(pos); - *yaw = it->second.dummy->dummy_getYaw(); - return 1; -} diff --git a/src/port/Network/Anchor/Packets/CollectItem.cpp b/src/port/Network/Anchor/Packets/CollectItem.cpp deleted file mode 100644 index 0c02282e9..000000000 --- a/src/port/Network/Anchor/Packets/CollectItem.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include -#include "port/Enhancements/Retention/Retention.h" -#include "port/Rando/Rando.h" -#include "port/UI/Notification.h" - -#include "functions.h" - -static const char* const kJiggyLevelNames[10] = { - "Mumbo's Mountain", "Treasure Trove Cove", "Clanker's Cavern", "Bubblegloop Swamp", "Freezeezy Peak", - "Gruntilda's Lair", "Gobi's Valley", "Click Clock Wood", "Rusty Bucket Bay", "Mad Monster Mansion", -}; - -/** - * COLLECT_ITEM - */ - -void Anchor::SendPacket_CollectItem(u8 kind, s32 id) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = COLLECT_ITEM; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["kind"] = kind; - payload["id"] = id; - payload["map"] = (s32)gsworld_getMap(); - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_CollectItem(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - u8 kind = payload.at("kind").get(); - s32 id = payload.at("id").get(); - s32 map = payload.at("map").get(); - bool sameMap = (s32)gsworld_getMap() == map; - - switch (kind) { - case ANCHOR_COLLECTIBLE_JIGGY: - if (!jiggyscore_isCollected((enum jiggy_e)id)) { - jiggyscore_setCollected(id, true); - func_8034798C(); // recompute the current-level jiggy HUD count - if ((s32)map_getLevel((enum map_e)map) == (s32)level_get()) { - code_73640_printItemCount(ITEM_E_JIGGY); - } else { - code_73640_printItemCount(ITEM_26_JIGGY_TOTAL); - } - if (!IS_RANDO && ShouldShowNotifications()) { - size_t levelIdx = (size_t)(id - 1) / 10; - const char* where = levelIdx < (sizeof(kJiggyLevelNames) / sizeof(kJiggyLevelNames[0])) - ? kJiggyLevelNames[levelIdx] - : "an unknown level"; - Notification::Emit({ - .prefix = GetClientName(payload.value("clientId", 0u)), - .message = "collected Jiggy #" + std::to_string(((id - 1) % 10) + 1) + " in " + where, - }); - } - } - if (sameMap) { - ActorMarker* m = func_8032B16C((enum jiggy_e)id); - if (m != nullptr) { - marker_despawn(m); - } - if (id == JIGGY_20_BGS_ELEVATED_WALKWAY || id == JIGGY_25_BGS_MAZE) { - func_802D6924(); - } - } - break; - case ANCHOR_COLLECTIBLE_HONEYCOMB: - if (!honeycombscore_get((enum honeycomb_e)id)) { - honeycombscore_set((enum honeycomb_e)id, 1); - item_inc(ITEM_13_EMPTY_HONEYCOMB); - if (!(item_getCount(ITEM_13_EMPTY_HONEYCOMB) < 6)) { - gcpausemenu_80314AC8(0); - } - } - if (sameMap) { - ActorMarker* m = actorArray_findHoneycombMarkerById((enum honeycomb_e)id); - if (m != nullptr) { - marker_despawn(m); - } - } - break; - case ANCHOR_COLLECTIBLE_MUMBO: - if (!mumboscore_get((enum mumbotoken_e)id)) { - mumboscore_set((enum mumbotoken_e)id, true); - } - if (sameMap) { - ActorMarker* m = actorArray_findMumboTokenMarkerById((enum mumbotoken_e)id); - if (m != nullptr) { - marker_despawn(m); - } - } - break; - case ANCHOR_COLLECTIBLE_NOTE: - port_noteRetention_applyRemoteCollect(map, id, sameMap ? 1 : 0); - break; - case ANCHOR_COLLECTIBLE_JINJO: - port_jinjoRetention_applyRemoteCollect(map, id, sameMap ? 1 : 0); - break; - case ANCHOR_COLLECTIBLE_WORM: - case ANCHOR_COLLECTIBLE_ACORN: - case ANCHOR_COLLECTIBLE_PRESENT_BLUE: - case ANCHOR_COLLECTIBLE_PRESENT_GREEN: - case ANCHOR_COLLECTIBLE_PRESENT_RED: - case ANCHOR_COLLECTIBLE_GOLD: - case ANCHOR_COLLECTIBLE_ORANGE: { - enum item_e item; - switch (kind) { - case ANCHOR_COLLECTIBLE_WORM: - item = ITEM_22_CATERPILLAR; - break; - case ANCHOR_COLLECTIBLE_ACORN: - item = ITEM_23_ACORNS; - break; - case ANCHOR_COLLECTIBLE_PRESENT_BLUE: - item = ITEM_20_BLUE_PRESENT; - break; - case ANCHOR_COLLECTIBLE_PRESENT_GREEN: - item = ITEM_1F_GREEN_PRESENT; - break; - case ANCHOR_COLLECTIBLE_PRESENT_RED: - item = ITEM_21_RED_PRESENT; - break; - case ANCHOR_COLLECTIBLE_ORANGE: - item = ITEM_19_ORANGE; - break; - default: - item = ITEM_18_GOLD_BULLIONS; - break; - } - bool noHud = (kind == ANCHOR_COLLECTIBLE_ORANGE) && !sameMap; - s32 delta = (id < 0) ? -1 : 1; - if (noHud) { - item_adjustByDiffWithoutHud(item, delta); - } else { - item_adjustByDiffWithHud(item, delta); - } - if (id >= 0) { - port_carriedSync_applyRemoteCollect(kind, map, id, sameMap ? 1 : 0); - } - break; - } - } -} diff --git a/src/port/Network/Anchor/Packets/DamagePlayer.cpp b/src/port/Network/Anchor/Packets/DamagePlayer.cpp index adb708b7a..09322c944 100644 --- a/src/port/Network/Anchor/Packets/DamagePlayer.cpp +++ b/src/port/Network/Anchor/Packets/DamagePlayer.cpp @@ -1,9 +1,14 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +extern "C" { #include "macros.h" #include "functions.h" +// extern PlayState* gPlayState; +// void func_80838280(Player* player); +} /** * DAMAGE_PLAYER @@ -24,8 +29,37 @@ void Anchor::SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage) { } void Anchor::HandlePacket_DamagePlayer(nlohmann::json& payload) { - return; // unimplemented uint32_t clientId = payload.at("clientId").get(); + // if (!clients.contains(clientId) || clients[clientId].player == nullptr) { + // return; + // } AnchorClient& anchorClient = clients[clientId]; + // Player* otherPlayer = anchorClient.player; + // Player* self = GET_PLAYER(gPlayState); + + //// Prevent incoming damage during cutscenes or item get sequences + // if (Player_InBlockingCsMode(gPlayState, self) || self->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || + // self->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) { + // return; + // } + + // u8 damageEffect = payload.at("damageEffect").get(); + // u8 damage = payload.at("damage").get(); + + // self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune + + // if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_FIRE) { + // for (int i = 0; i < ARRAY_COUNT(self->bodyFlameTimers); i++) { + // self->bodyFlameTimers[i] = Rand_S16Offset(0, 200); + // } + // self->bodyIsBurning = true; + // } else if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_STUN) { + // self->actor.freezeTimer = 20; + // Actor_SetColorFilter(&self->actor, 0, 0xFF, 0, 24); + // return; + // } + + // func_80837C0C(gPlayState, self, damageEffect, 4.0f, 5.0f, + // Actor_WorldYawTowardActor(&otherPlayer->actor, &self->actor), 20); } diff --git a/src/port/Network/Anchor/Packets/DisableAnchor.cpp b/src/port/Network/Anchor/Packets/DisableAnchor.cpp index 9a4a322e6..ec047c3b5 100644 --- a/src/port/Network/Anchor/Packets/DisableAnchor.cpp +++ b/src/port/Network/Anchor/Packets/DisableAnchor.cpp @@ -1,6 +1,7 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" /** * DISABLE_ANCHOR diff --git a/src/port/Network/Anchor/Packets/EggToll.cpp b/src/port/Network/Anchor/Packets/EggToll.cpp deleted file mode 100644 index 584372f93..000000000 --- a/src/port/Network/Anchor/Packets/EggToll.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include -#include -#include - -#include "functions.h" - -#include "port/Patches/Patches.h" - -/** - * EGG_TOLL - */ - -std::map, int32_t> sStages; - -void recordStage(int32_t map, int32_t secondaryId, int32_t stage) { - std::array key = { map, secondaryId }; - auto it = sStages.find(key); - if (it == sStages.end() || stage > it->second) { - sStages[key] = stage; - } -} - -extern "C" int32_t port_eggToll_getStage(int32_t map, int32_t secondaryId) { - auto it = sStages.find({ map, secondaryId }); - return it != sStages.end() ? it->second : 0; -} - -extern "C" void port_eggToll_onAdvance(int32_t map, int32_t secondaryId, int32_t stage) { - recordStage(map, secondaryId, stage); - Anchor::GetInstance()->SendPacket_EggToll((s16)secondaryId, stage, map); -} - -void Anchor::SendPacket_EggToll(s16 secondaryId, s32 stage, s32 map) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = EGG_TOLL; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["sec"] = secondaryId; - payload["stage"] = stage; - payload["map"] = map; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_EggToll(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s16 secondaryId = payload.at("sec").get(); - s32 stage = payload.at("stage").get(); - s32 map = payload.at("map").get(); - - recordStage(map, secondaryId, stage); - if ((s32)gsworld_getMap() == map) { - port_eggToll_remoteApply(map, secondaryId, stage); - } -} - -std::vector port_eggToll_snapshot() { - std::vector flat; - flat.reserve(sStages.size() * 3); - for (const auto& [key, stage] : sStages) { - flat.push_back(key[0]); - flat.push_back(key[1]); - flat.push_back(stage); - } - return flat; -} - -void port_eggToll_restore(const std::vector& flat) { - sStages.clear(); - for (size_t i = 0; i + 3 <= flat.size(); i += 3) { - sStages[{ flat[i], flat[i + 1] }] = flat[i + 2]; - } -} - -void port_eggToll_clearForLevel(int32_t levelId) { - std::erase_if(sStages, - [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); -} - -void RegisterEggToll_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sStages.clear(); }); - - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnMapLoad* ev = (OnMapLoad*)event; - for (const auto& [key, stage] : sStages) { - if (key[0] == (int32_t)ev->nextMap) { - port_eggToll_remoteApply(key[0], key[1], stage); - } - } - }); -} - -static RegisterShipInitFunc initEggToll(RegisterEggToll_Init, {}); diff --git a/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp b/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp index fd4017e11..ab6192cdb 100644 --- a/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp +++ b/src/port/Network/Anchor/Packets/EntranceDiscovered.cpp @@ -1,11 +1,12 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +//#include "soh/Enhancements/randomizer/randomizer_entrance.h" +//#include "soh/OTRGlobals.h" /** * ENTRANCE_DISCOVERED - * - * currently unimplemented */ void Anchor::SendPacket_EntranceDiscovered(u16 entranceIndex) { @@ -28,4 +29,5 @@ void Anchor::HandlePacket_EntranceDiscovered(nlohmann::json& payload) { } u16 entranceIndex = payload.at("entranceIndex").get(); + // Entrance_SetEntranceDiscovered(entranceIndex, 1); } diff --git a/src/port/Network/Anchor/Packets/FightEvent.cpp b/src/port/Network/Anchor/Packets/FightEvent.cpp deleted file mode 100644 index 75babb01c..000000000 --- a/src/port/Network/Anchor/Packets/FightEvent.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include "port/Network/Anchor/Authority.h" -#include "port/Network/Anchor/FightSync.h" -#include -#include - -#include "functions.h" -extern "C" { -#include "variables.h" -} - -/** - * FIGHT_EVENT - */ - -void Anchor::SendPacket_FightEvent(s32 ev, s32 a, s32 b, const f32 v0[3], const f32 v1[3], const f32 v2[3]) { - if (!IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS || GetCurrentMapPlayers() == 0) { - return; - } - - nlohmann::json payload; - payload["type"] = FIGHT_EVENT; - payload["ev"] = ev; - payload["a"] = a; - payload["b"] = b; - if (v0 != nullptr && v1 != nullptr && v2 != nullptr) { - payload["p"] = { v0[0], v0[1], v0[2] }; - payload["v"] = { v1[0], v1[1], v1[2] }; - payload["w"] = { v2[0], v2[1], v2[2] }; - } - - SendToCurrentMapPlayers(payload); -} - -extern "C" void FightSync_SendEvent(int32_t ev, int32_t a, int32_t b, const float v0[3], const float v1[3], - const float v2[3]) { - Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected) { - return; - } - anchor->SendPacket_FightEvent(ev, a, b, v0, v1, v2); -} - -void Anchor::HandlePacket_FightEvent(nlohmann::json& payload) { - if (gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { - return; - } - - s32 ev = payload.value("ev", (s32)-1); - s32 a = payload.value("a", (s32)0); - s32 b = payload.value("b", (s32)0); - f32 p[3] = { 0.0f, 0.0f, 0.0f }; - f32 v[3] = { 0.0f, 0.0f, 0.0f }; - f32 w[3] = { 0.0f, 0.0f, 0.0f }; - bool hasVectors = payload.contains("p"); - - if (hasVectors) { - std::vector pv = payload["p"].get>(); - std::vector vv = payload["v"].get>(); - std::vector wv = payload["w"].get>(); - if (pv.size() < 3 || vv.size() < 3 || wv.size() < 3) { - return; - } - for (s32 i = 0; i < 3; i++) { - p[i] = pv[i]; - v[i] = vv[i]; - w[i] = wv[i]; - } - } - - FightSync_ApplyEvent(ev, a, b, hasVectors ? p : nullptr, hasVectors ? v : nullptr, hasVectors ? w : nullptr); -} diff --git a/src/port/Network/Anchor/Packets/FightState.cpp b/src/port/Network/Anchor/Packets/FightState.cpp deleted file mode 100644 index 97fb84e25..000000000 --- a/src/port/Network/Anchor/Packets/FightState.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include "port/Network/Anchor/Authority.h" -#include "port/Network/Anchor/FightSync.h" -#include -#include - -#include "functions.h" -extern "C" { -#include "variables.h" -} - -/** - * FIGHT_STATE - */ - -void Anchor::SendPacket_FightState(u32 targetClientId) { - if (!IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { - return; - } - - FightWorldSnapshot snap; - if (!FightSync_GatherWorld(&snap)) { - return; - } - - nlohmann::json payload; - payload["type"] = FIGHT_STATE; - payload["targetClientId"] = targetClientId; - payload["pad"] = snap.pad; - payload["bar"] = snap.barrier; - payload["st"] = { snap.statue[0], snap.statue[1], snap.statue[2], snap.statue[3] }; - payload["jg"] = { snap.jinjoGone[0], snap.jinjoGone[1], snap.jinjoGone[2], snap.jinjoGone[3] }; - payload["jb"] = snap.jbase; - payload["jp"] = { snap.jpads[0], snap.jpads[1], snap.jpads[2], snap.jpads[3] }; - - SendJsonToRemote(payload); -} - -extern "C" void FightSync_SendSnapshot(uint32_t clientId) { - Anchor* anchor = Anchor::GetInstance(); - if (anchor == nullptr || !anchor->isConnected) { - return; - } - anchor->SendPacket_FightState(clientId); -} - -void Anchor::HandlePacket_FightState(nlohmann::json& payload) { - if (gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { - return; - } - - FightWorldSnapshot snap; - std::vector st = payload["st"].get>(); - std::vector jg = payload["jg"].get>(); - std::vector jp = payload["jp"].get>(); - if (st.size() < 4 || jg.size() < 4 || jp.size() < 4) { - return; - } - - snap.pad = payload.value("pad", (u8)0); - snap.barrier = payload.value("bar", (u8)0); - snap.jbase = payload.value("jb", (u8)0); - for (s32 i = 0; i < 4; i++) { - snap.statue[i] = st[i]; - snap.jinjoGone[i] = jg[i]; - snap.jpads[i] = jp[i]; - } - - FightSync_ApplyWorld(&snap); -} diff --git a/src/port/Network/Anchor/Packets/FightUpdate.cpp b/src/port/Network/Anchor/Packets/FightUpdate.cpp deleted file mode 100644 index bf3ff9887..000000000 --- a/src/port/Network/Anchor/Packets/FightUpdate.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include "port/Network/Anchor/Authority.h" -#include "port/Network/Anchor/FightSync.h" -#include -#include - -#include "functions.h" -extern "C" { -#include "variables.h" -} - -/** - * FIGHT_UPDATE - */ - -static uint32_t sOutgoingSeq = 0; -static uint32_t sLastAcceptedSeq = 0; - -extern "C" uint32_t FightSyncSeq_Next(void) { - return ++sOutgoingSeq; -} - -extern "C" bool FightSyncSeq_Accept(uint32_t seq) { - if (seq <= sLastAcceptedSeq) { - return false; - } - sLastAcceptedSeq = seq; - return true; -} - -extern "C" void FightSyncSeq_Reset(void) { - sOutgoingSeq = 0; - sLastAcceptedSeq = 0; -} - -void Anchor::SendPacket_FightUpdate(const f32 pos[3], f32 yaw, s32 state, s32 phase, s32 mirror, s32 vuln) { - if (!IsSaveLoaded() || gsworld_getMap() != MAP_90_GL_BATTLEMENTS || GetCurrentMapPlayers() == 0) { - return; - } - - nlohmann::json payload; - payload["type"] = FIGHT_UPDATE; - payload["seq"] = FightSyncSeq_Next(); - payload["pos"] = { pos[0], pos[1], pos[2] }; - payload["yaw"] = yaw; - payload["st"] = state; - payload["ph"] = phase; - payload["mir"] = mirror; - payload["vuln"] = vuln; - payload["quiet"] = true; - - SendToCurrentMapPlayers(payload); -} - -extern "C" void FightSync_SendUpdate(const float pos[3], float yaw, int32_t state, int32_t phase, int32_t mirror, - int32_t vuln) { - Anchor::GetInstance()->SendPacket_FightUpdate(pos, yaw, state, phase, mirror, vuln); -} - -void Anchor::HandlePacket_FightUpdate(nlohmann::json& payload) { - if (gsworld_getMap() != MAP_90_GL_BATTLEMENTS) { - return; - } - if (!FightSyncSeq_Accept(payload.value("seq", (u32)0))) { - return; - } - - std::vector pos = payload["pos"].get>(); - if (pos.size() < 3) { - return; - } - - FightSync_ApplyUpdate(pos.data(), payload.value("yaw", 0.0f), payload.value("st", (s32)1), - payload.value("ph", (s32)0), payload.value("mir", (s32)0), payload.value("vuln", (s32)0)); -} diff --git a/src/port/Network/Anchor/Packets/GameComplete.cpp b/src/port/Network/Anchor/Packets/GameComplete.cpp index b502d8f31..44f314762 100644 --- a/src/port/Network/Anchor/Packets/GameComplete.cpp +++ b/src/port/Network/Anchor/Packets/GameComplete.cpp @@ -1,7 +1,9 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "port/UI/Notification.h" +//#include "soh/ShipUtils.h" const std::string gameCompleteMessages[] = { "killed Ganon", "saved Zelda", "proved their Courage", @@ -10,8 +12,6 @@ const std::string gameCompleteMessages[] = { /** * GAME_COMPLETE - * - * unimplemented */ void Anchor::SendPacket_GameComplete() { @@ -33,9 +33,10 @@ void Anchor::HandlePacket_GameComplete(nlohmann::json& payload) { AnchorClient& anchorClient = clients[clientId]; anchorClient.isGameComplete = true; + bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); // Notification::Emit({ - // .prefix = IsGlobalRoom() ? "Someone" : anchorClient.name, + // .prefix = isGlobalRoom ? "Someone" : anchorClient.name, // .message = ShipUtils::RandomElement(gameCompleteMessages), // }); } diff --git a/src/port/Network/Anchor/Packets/GiveItem.cpp b/src/port/Network/Anchor/Packets/GiveItem.cpp index 8d7f3801e..3c4828fb1 100644 --- a/src/port/Network/Anchor/Packets/GiveItem.cpp +++ b/src/port/Network/Anchor/Packets/GiveItem.cpp @@ -1,15 +1,20 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "port/UI/Notification.h" +//#include "soh/Enhancements/randomizer/randomizer.h" +//#include "soh/SohGui/ImGuiUtils.h" +//#include "soh/Enhancements/item-tables/ItemTableManager.h" +//#include "soh/OTRGlobals.h" +extern "C" { #include "functions.h" // extern PlayState* gPlayState; +} /** * GIVE_ITEM - * - * unimplemented */ uint8_t incomingIceTrapsFromAnchor = 0; diff --git a/src/port/Network/Anchor/Packets/Handshake.cpp b/src/port/Network/Anchor/Packets/Handshake.cpp index ce7d6dd78..0c80b0393 100644 --- a/src/port/Network/Anchor/Packets/Handshake.cpp +++ b/src/port/Network/Anchor/Packets/Handshake.cpp @@ -1,6 +1,8 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +//#include "soh/OTRGlobals.h" /** * HANDSHAKE diff --git a/src/port/Network/Anchor/Packets/HutSmash.cpp b/src/port/Network/Anchor/Packets/HutSmash.cpp deleted file mode 100644 index 4ba1718b7..000000000 --- a/src/port/Network/Anchor/Packets/HutSmash.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include -#include -#include - -#include "functions.h" - -/** - * HUT_SMASH - */ - -std::map, int32_t> sHuts; - -extern "C" int32_t port_hutSmash_get(int32_t x, int32_t y, int32_t z) { - auto it = sHuts.find({ (int32_t)gsworld_getMap(), x, y, z }); - return it != sHuts.end() ? it->second : -1; -} - -extern "C" int32_t port_hutSmash_countForCurrentLevel(void) { - int32_t level = (int32_t)map_getLevel(gsworld_getMap()); - int32_t count = 0; - for (const auto& [key, loot] : sHuts) { - if ((int32_t)map_getLevel((enum map_e)key[0]) == level) { - count++; - } - } - return count; -} - -extern "C" void port_hutSmash_record(int32_t x, int32_t y, int32_t z, int32_t loot) { - int32_t map = (int32_t)gsworld_getMap(); - std::array key = { map, x, y, z }; - if (sHuts.find(key) != sHuts.end()) { - return; - } - sHuts[key] = loot; - Anchor::GetInstance()->SendPacket_HutSmash(x, y, z, loot, map); -} - -void Anchor::SendPacket_HutSmash(s32 x, s32 y, s32 z, s32 loot, s32 map) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = HUT_SMASH; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["x"] = x; - payload["y"] = y; - payload["z"] = z; - payload["loot"] = loot; - payload["map"] = map; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_HutSmash(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s32 x = payload.at("x").get(); - s32 y = payload.at("y").get(); - s32 z = payload.at("z").get(); - s32 loot = payload.at("loot").get(); - s32 map = payload.at("map").get(); - - sHuts.emplace(std::array{ map, x, y, z }, loot); -} - -std::vector port_hutSmash_snapshot() { - std::vector flat; - flat.reserve(sHuts.size() * 5); - for (const auto& [key, loot] : sHuts) { - flat.push_back(key[0]); - flat.push_back(key[1]); - flat.push_back(key[2]); - flat.push_back(key[3]); - flat.push_back(loot); - } - return flat; -} - -void port_hutSmash_restore(const std::vector& flat) { - sHuts.clear(); - for (size_t i = 0; i + 5 <= flat.size(); i += 5) { - sHuts[{ flat[i], flat[i + 1], flat[i + 2], flat[i + 3] }] = flat[i + 4]; - } -} - -void port_hutSmash_clearForLevel(int32_t levelId) { - std::erase_if(sHuts, - [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); -} - -void RegisterHutSmash_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sHuts.clear(); }); -} - -static RegisterShipInitFunc initHutSmash(RegisterHutSmash_Init, {}); diff --git a/src/port/Network/Anchor/Packets/JiggyCrane.cpp b/src/port/Network/Anchor/Packets/JiggyCrane.cpp deleted file mode 100644 index 863a4b6d1..000000000 --- a/src/port/Network/Anchor/Packets/JiggyCrane.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "functions.h" - -#include "port/Patches/Patches.h" - -/** - * JIGGY_CRANE - */ - -void Anchor::SendPacket_JiggyCrane(s32 stage) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags || GetCurrentMapPlayers() == 0) { - return; - } - - nlohmann::json payload; - payload["type"] = JIGGY_CRANE; - payload["stage"] = stage; - - SendToCurrentMapPlayers(payload); -} - -void Anchor::HandlePacket_JiggyCrane(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - port_jiggyCrane_remoteApply(payload.at("stage").get()); -} - -extern "C" void port_jiggyCrane_broadcast(int32_t stage) { - Anchor::GetInstance()->SendPacket_JiggyCrane(stage); -} diff --git a/src/port/Network/Anchor/Packets/MapLoad.cpp b/src/port/Network/Anchor/Packets/MapLoad.cpp index f22fc1167..6765b0aa1 100644 --- a/src/port/Network/Anchor/Packets/MapLoad.cpp +++ b/src/port/Network/Anchor/Packets/MapLoad.cpp @@ -3,9 +3,10 @@ #include #include +extern "C" { #include "variables.h" #include "functions.h" -#include "port/Patches/Patches.h" +} /** * MAP_LOAD @@ -19,7 +20,6 @@ void Anchor::SendPacket_MapLoad(GameMap map, s32 exit) { payload["type"] = MAP_LOAD; payload["map"] = map; payload["exit"] = exit; - payload["returnMap"] = port_cutsceneWarp_getReturnMap(); SendJsonToRemote(payload); } @@ -30,13 +30,11 @@ void Anchor::HandlePacket_MapLoad(nlohmann::json& payload) { clients[clientId].map = payload.at("map").get(); clients[clientId].exit = payload.at("exit").get(); - clients[clientId].cutsceneReturnMap = payload.value("returnMap", (s32)0); clients[clientId].isSaveLoaded = clients[clientId].map != MAP_1E_CS_START_NINTENDO && clients[clientId].map != MAP_1F_CS_START_RAREWARE && clients[clientId].map != MAP_91_FILE_SELECT; EvaluateDummyForClient(clientId); Authority_OnPeerMapLoad(clientId, clients[clientId].map); - SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); // Handle instances where map-specific updates aren't captured by other clients, causing transformations // and animation states to be desynced until updated again while the client is in the map. diff --git a/src/port/Network/Anchor/Packets/PedestalOwner.cpp b/src/port/Network/Anchor/Packets/PedestalOwner.cpp deleted file mode 100644 index cd3ceca92..000000000 --- a/src/port/Network/Anchor/Packets/PedestalOwner.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include "port/Network/Anchor/JigsawPedestal.h" -#include -#include - -/** - * PEDESTAL_OWNER - * - * Claim/release of a jigsaw podium lock; conflicts resolve by lowest clientId. - */ - -void Anchor::SendPacket_PedestalOwner(s32 id, bool claimed) { - nlohmann::json payload; - payload["type"] = PEDESTAL_OWNER; - payload["id"] = id; - payload["claimed"] = claimed; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_PedestalOwner(nlohmann::json& payload) { - uint32_t clientId = payload.at("clientId").get(); - s32 id = payload.at("id").get(); - bool claimed = payload.value("claimed", false); - - JigsawPedestal_ApplyRemote(id, clientId, claimed); -} diff --git a/src/port/Network/Anchor/Packets/PlayerSfx.cpp b/src/port/Network/Anchor/Packets/PlayerSfx.cpp index bafc83537..a3c2bdf5e 100644 --- a/src/port/Network/Anchor/Packets/PlayerSfx.cpp +++ b/src/port/Network/Anchor/Packets/PlayerSfx.cpp @@ -3,9 +3,12 @@ #include #include +extern "C" { #include "macros.h" #include "functions.h" #include "variables.h" +// extern PlayState* gPlayState; +} /** * PLAYER_SFX @@ -23,7 +26,22 @@ void Anchor::SendPacket_PlayerSfx(u16 sfxId) { payload["type"] = PLAYER_SFX; payload["sfxId"] = sfxId; payload["quiet"] = true; + + // for (auto& [clientId, client] : clients) { + // if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded && !client.self) { + // payload["targetClientId"] = clientId; + // SendJsonToRemote(payload); + // } + // } } void Anchor::HandlePacket_PlayerSfx(nlohmann::json& payload) { + // uint32_t clientId = payload.at("clientId").get(); + // u16 sfxId = payload.at("sfxId").get(); + + // if (!clients.contains(clientId) || !clients[clientId].player) { + // return; + // } + + // Player_PlaySfx((Actor*)clients[clientId].player, sfxId); } diff --git a/src/port/Network/Anchor/Packets/PlayerUpdate.cpp b/src/port/Network/Anchor/Packets/PlayerUpdate.cpp index 71987a608..861451017 100644 --- a/src/port/Network/Anchor/Packets/PlayerUpdate.cpp +++ b/src/port/Network/Anchor/Packets/PlayerUpdate.cpp @@ -3,13 +3,11 @@ #include #include +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" - -extern "C" ActorMarker* bacarry_getMarker(void); - -#include "port/Patches/Patches.h" +} /** * PLAYER_UPDATE @@ -30,16 +28,6 @@ void Anchor::SendToCurrentMapPlayers(nlohmann::json& payload) { } } -void Anchor::SendToCurrentLevelPlayers(nlohmann::json& payload) { - enum level_e myLevel = map_getLevel(gsworld_getMap()); - for (auto& [clientId, client] : clients) { - if (client.online && client.isSaveLoaded && !client.self && map_getLevel((enum map_e)client.map) == myLevel) { - payload["targetClientId"] = clientId; - SendJsonToRemote(payload); - } - } -} - void Anchor::SendPacket_PlayerSubRangeChange(f32 duration, f32 end) { if (!IsSaveLoaded() || GetCurrentMapPlayers() == 0) { return; @@ -173,36 +161,19 @@ void Anchor::SendPacket_PlayerUpdate(bool full, uint32_t targetClientId) { anctrl_getSubRange(baanim_getAnimCtrlPtr(), &sub_start, &sub_end); payload["subrange_end"] = sub_end; } - payload["kazooieUpper"] = modelAppendages_showKazooiesUpperHalf(); - payload["kazooieLower"] = modelAppendages_showKazooiesAss(); - payload["kazooieFeet"] = modelAppendages_showKazooiesFeetAndShoes(); - payload["kazooieTurbos"] = modelAppendages_hideTurboTrainers(); - payload["kazooieBoots"] = modelAppendages_hideWadingBoots(); - payload["banjoLeftEye"] = modelAppendages_showBanjosLeftEye(); - payload["banjoRightEye"] = modelAppendages_showBanjosRightEye(); - payload["bottlesBonus"] = baanim_getActiveBottlesBonusMask(); - { - // Carried-collectible marker id (0 = none); skipped once thrown (unk138_21 = in flight). - s32 carryId = 0; - ActorMarker* carryMarker = bacarry_getMarker(); - if (carryMarker != nullptr) { - Actor* carried = marker_getActor(carryMarker); - if (carried != nullptr && !carried->unk138_21) { - carryId = carryMarker->id; - payload["carryOff"] = { carried->position[0] - pos[0], carried->position[1] - pos[1], - carried->position[2] - pos[2] }; - payload["carryYaw"] = mlNormalizeAngle(carried->yaw - player_getYaw()); - } - } - payload["carry"] = carryId; - } + payload["kazooieVisible"] = func_8029DFBC(); // Kazooie visibility (Kazooie popped out) + payload["modelSquint"] = func_8029DFA4(); // squint + payload["modelWink"] = func_8029DFB0(); // wink + payload["modelMouth1"] = func_8029DFE0(); // mouth + payload["modelMouth2"] = func_8029DFEC(); // mouth 2 + payload["modelEyeBlendUpper"] = func_8029DFC8(); // eye blend upper + payload["modelEyeBlendLower"] = func_8029DFD4(); // eye blend lower if (full) { payload["anim_id"] = anctrl_getIndex(baanim_getAnimCtrlPtr()); payload["anim_control"] = anctrl_getPlaybackType(baanim_getAnimCtrlPtr()); } payload["type"] = full ? PLAYER_UPDATE_FULL : PLAYER_UPDATE; - payload["quiet"] = true; if (targetClientId != 0) { payload["targetClientId"] = targetClientId; @@ -263,24 +234,9 @@ void Anchor::HandlePacket_PlayerUpdate(nlohmann::json& payload) { (AnimControl)payload.value("anim_control", (int)ANIMCTRL_LOOP), 0.0f, payload.value("subrange_end", 1.0f), false); } - client.dummy->setModelSubStates(payload.value("kazooieUpper", false), payload.value("kazooieLower", false), - payload.value("kazooieFeet", false), payload.value("kazooieTurbos", false), - payload.value("kazooieBoots", false), payload.value("banjoLeftEye", 0.0f), - payload.value("banjoRightEye", 0.0f)); - client.dummy->dummy_setBottlesBonus(payload.value("bottlesBonus", 0)); - { - f32 carryOff[3] = { 0.0f, 0.0f, 0.0f }; - f32 carryYaw = 0.0f; - if (payload.contains("carryOff")) { - std::vector off = payload["carryOff"].get>(); - if (off.size() >= 3) { - carryOff[0] = off[0]; - carryOff[1] = off[1]; - carryOff[2] = off[2]; - } - carryYaw = payload.value("carryYaw", 0.0f); - } - port_remoteCarry_setCarried(clientId, payload.value("carry", 0), carryOff, carryYaw); - } + client.dummy->setModelSubStates(payload.value("kazooieVisible", false), payload.value("modelSquint", false), + payload.value("modelWink", false), payload.value("modelMouth1", false), + payload.value("modelMouth2", false), payload.value("modelEyeBlendUpper", 0.0f), + payload.value("modelEyeBlendLower", 0.0f)); } } diff --git a/src/port/Network/Anchor/Packets/PuzzleStep.cpp b/src/port/Network/Anchor/Packets/PuzzleStep.cpp deleted file mode 100644 index 638f20dd9..000000000 --- a/src/port/Network/Anchor/Packets/PuzzleStep.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include -#include -#include -#include - -#include "functions.h" -extern "C" { -void chTreasurehunt_netTick(void); -} - -#include "port/Patches/Patches.h" - -/** - * PUZZLE_STEP - * - * Syncs multi-step world puzzles with no flag of their own (Tanktup's legs, croctus feed, pink - * eggs). Progress is an OR-merged bitmask keyed by (map, puzzleId); never saved. - */ - -std::map, int32_t> sPuzzleBits; -std::map, int32_t> sPuzzleCounts; -// PUZZLE_POS: (map, puzzleId) -> set of spawn-position hashes for positional puzzles (see below). -std::map, std::set> sPuzzlePos; - -static int32_t puzzlePosHash(int32_t x, int32_t y, int32_t z) { - uint32_t h = (uint32_t)x * 73856093u ^ (uint32_t)y * 19349663u ^ (uint32_t)z * 83492791u; - return (int32_t)((h & 0x7FFFFFFFu) | 1u); // never 0 (the "no positional hash" sentinel) -} - -/** - * Every bitmask entry is written by one vanilla actor that lives in one known map, and - * some entries are derived from -- or applied back to -- raw map/level flag indices whose - * meaning is map-relative. A romhack that relocates such an actor makes it read one map's - * flag and republish it as another's. To avoid complications, each puzzle id is scoped to - * its actor's home: outside it every leg is inert. - * - * Vanilla is unaffected, and a romhack keeps live sync for every puzzle it didn't relocate. - */ -struct PuzzleHome { - std::set maps; - int32_t level = -1; // home is a whole level (romhacks may remap a level's maps) -}; - -static const std::map& puzzleHomes() { - static const std::map homes = { - { ANCHOR_PUZZLE_BGS_TANKTUP, { { MAP_D_BGS_BUBBLEGLOOP_SWAMP } } }, - { ANCHOR_PUZZLE_BGS_CROCTUS, { { MAP_D_BGS_BUBBLEGLOOP_SWAMP } } }, - // The egg chain's map isn't pinned down in the decomp; its readback only drives - // actor state, so the whole level is safe. - { ANCHOR_PUZZLE_BGS_PINKEGG, { {}, LEVEL_4_BUBBLEGLOOP_SWAMP } }, - { ANCHOR_PUZZLE_CC_CLANKER_TEETH, { { MAP_B_CC_CLANKERS_CAVERN } } }, - { ANCHOR_PUZZLE_GV_JINXY_DOOR, { { MAP_12_GV_GOBIS_VALLEY } } }, - { ANCHOR_PUZZLE_MM_JUJU, { { MAP_2_MM_MUMBOS_MOUNTAIN } } }, - { ANCHOR_PUZZLE_TTC_NIPPER, { { MAP_7_TTC_TREASURE_TROVE_COVE } } }, - { ANCHOR_PUZZLE_TTC_BLUBBER, { { MAP_7_TTC_TREASURE_TROVE_COVE } } }, - { ANCHOR_PUZZLE_TTC_XHUNT, { { MAP_7_TTC_TREASURE_TROVE_COVE } } }, - { ANCHOR_PUZZLE_FP_TREE_ICE, { { MAP_53_FP_CHRISTMAS_TREE } } }, - { ANCHOR_PUZZLE_FP_PRESENTS, { { MAP_27_FP_FREEZEEZY_PEAK } } }, - { ANCHOR_PUZZLE_FP_SNOWBUTTONS, { { MAP_27_FP_FREEZEEZY_PEAK } } }, - { ANCHOR_PUZZLE_FP_SLUSHES, { { MAP_27_FP_FREEZEEZY_PEAK } } }, - { ANCHOR_PUZZLE_RBB_ENGINE_FANS, { { MAP_34_RBB_ENGINE_ROOM } } }, - // Tutorial choreography follows the level, not the map. - { ANCHOR_PUZZLE_SM_TUTORIAL, { {}, LEVEL_B_SPIRAL_MOUNTAIN } }, - }; - return homes; -} - -static bool mirrorAllowedFor(int32_t puzzleId, int32_t map) { - auto it = puzzleHomes().find(puzzleId); - if (it == puzzleHomes().end()) { - return false; // unknown id: fail inert - } - if (it->second.maps.count(map)) { - return true; - } - return it->second.level >= 0 && (int32_t)map_getLevel((enum map_e)map) == it->second.level; -} - -static bool mirrorLive(int32_t puzzleId) { - return mirrorAllowedFor(puzzleId, (int32_t)gsworld_getMap()); -} - -extern "C" int32_t port_puzzleStep_get(int32_t puzzleId) { - if (!mirrorLive(puzzleId)) { - return 0; - } - auto it = sPuzzleBits.find({ (int32_t)gsworld_getMap(), puzzleId }); - return it != sPuzzleBits.end() ? it->second : 0; -} - -extern "C" int32_t port_puzzleStep_getForMap(int32_t map, int32_t puzzleId) { - if (!mirrorAllowedFor(puzzleId, map)) { - return 0; - } - auto it = sPuzzleBits.find({ map, puzzleId }); - return it != sPuzzleBits.end() ? it->second : 0; -} - -// For level-homed puzzles: a relocated actor writes under the romhack's map -// key, which a map-keyed read can't know. ORs the puzzle's bits across the level. -extern "C" int32_t port_puzzleStep_getForLevel(int32_t levelId, int32_t puzzleId) { - int32_t bits = 0; - for (const auto& [key, val] : sPuzzleBits) { - if (key[1] == puzzleId && mirrorAllowedFor(puzzleId, key[0]) && - (int32_t)map_getLevel((enum map_e)key[0]) == levelId) { - bits |= val; - } - } - return bits; -} - -extern "C" void port_puzzleStep_orBits(int32_t puzzleId, int32_t bits) { - if (!mirrorLive(puzzleId)) { - return; - } - int32_t map = (int32_t)gsworld_getMap(); - std::array key = { map, puzzleId }; - int32_t before = sPuzzleBits.count(key) ? sPuzzleBits[key] : 0; - int32_t after = before | bits; - if (after == before) { - return; - } - sPuzzleBits[key] = after; - Anchor::GetInstance()->SendPacket_PuzzleStep(puzzleId, after, map); -} - -void Anchor::SendPacket_PuzzleStep(s32 puzzleId, s32 bits, s32 map, s32 phash) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = PUZZLE_STEP; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["puzzle"] = puzzleId; - payload["bits"] = bits; - payload["map"] = map; - // A positional puzzle ships its member's hash instead of a bit; 0 = an ordinary bitmask step. - if (phash != 0) { - payload["phash"] = phash; - } - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_PuzzleStep(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s32 puzzleId = payload.at("puzzle").get(); - s32 map = payload.at("map").get(); - if (!mirrorAllowedFor(puzzleId, map)) { - return; - } - s32 phash = payload.value("phash", (s32)0); - if (phash != 0) { - sPuzzlePos[{ map, puzzleId }].insert(phash); - return; - } - sPuzzleBits[{ map, puzzleId }] |= payload.at("bits").get(); -} - -std::vector port_puzzleStep_snapshot() { - std::vector flat; - flat.reserve(sPuzzleBits.size() * 3); - for (const auto& [key, bits] : sPuzzleBits) { - flat.push_back(key[0]); - flat.push_back(key[1]); - flat.push_back(bits); - } - return flat; -} - -void port_puzzleStep_restore(const std::vector& flat) { - sPuzzleBits.clear(); - for (size_t i = 0; i + 3 <= flat.size(); i += 3) { - if (!mirrorAllowedFor(flat[i + 1], flat[i])) { - continue; - } - sPuzzleBits[{ flat[i], flat[i + 1] }] = flat[i + 2]; - } -} - -void port_puzzleStep_clearForLevel(int32_t levelId) { - std::erase_if(sPuzzleBits, - [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); - std::erase_if(sPuzzleCounts, - [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); - std::erase_if(sPuzzlePos, - [levelId](const auto& kv) { return (int32_t)map_getLevel((enum map_e)kv.first[0]) == levelId; }); -} - -/** - * PUZZLE_POS - * - * Positional companion to PUZZLE_STEP for steps keyed by spawn position instead of a bit index - * (FP's Sir Slushes). Rides the same PUZZLE_STEP packet via the phash field. - */ - -extern "C" int32_t port_puzzlePos_isMarked(int32_t puzzleId, int32_t x, int32_t y, int32_t z) { - if (!mirrorLive(puzzleId)) { - return 0; - } - auto it = sPuzzlePos.find({ (int32_t)gsworld_getMap(), puzzleId }); - return (it != sPuzzlePos.end() && it->second.count(puzzlePosHash(x, y, z))) ? 1 : 0; -} - -extern "C" void port_puzzlePos_mark(int32_t puzzleId, int32_t x, int32_t y, int32_t z) { - if (!mirrorLive(puzzleId)) { - return; - } - int32_t map = (int32_t)gsworld_getMap(); - int32_t hash = puzzlePosHash(x, y, z); - auto& set = sPuzzlePos[{ map, puzzleId }]; - if (!set.insert(hash).second) { - return; - } - Anchor::GetInstance()->SendPacket_PuzzleStep(puzzleId, 0, map, hash); -} - -// Flat [map, puzzleId, count, hashes...] runs. -std::vector port_puzzlePos_snapshot() { - std::vector flat; - for (const auto& [key, set] : sPuzzlePos) { - flat.push_back(key[0]); - flat.push_back(key[1]); - flat.push_back((int32_t)set.size()); - for (int32_t h : set) { - flat.push_back(h); - } - } - return flat; -} - -void port_puzzlePos_restore(const std::vector& flat) { - sPuzzlePos.clear(); - size_t i = 0; - while (i + 3 <= flat.size()) { - int32_t map = flat[i], puzzleId = flat[i + 1], count = flat[i + 2]; - i += 3; - // Still consume the run's hashes when filtered so the stream stays aligned. - const bool allowed = mirrorAllowedFor(puzzleId, map); - for (int32_t j = 0; j < count && i < flat.size(); j++, i++) { - if (allowed) { - sPuzzlePos[{ map, puzzleId }].insert(flat[i]); - } - } - } -} - -/** - * PUZZLE_COUNT - * - * Companion to PUZZLE_STEP for count-based progress (Eyrie's fed worms, Nabnut's acorns). - * Not home-scoped: counters never touch flag indices (keyed by the real map, applied only - * to actor state), and scoping them would brick a relocated Eyrie/Nabnut. - */ - -extern "C" int32_t port_puzzleCount_get(int32_t counterId) { - auto it = sPuzzleCounts.find({ (int32_t)gsworld_getMap(), counterId }); - return it != sPuzzleCounts.end() ? it->second : 0; -} - -extern "C" void port_puzzleCount_add(int32_t counterId, int32_t delta) { - int32_t map = (int32_t)gsworld_getMap(); - sPuzzleCounts[{ map, counterId }] += delta; - Anchor::GetInstance()->SendPacket_PuzzleCount(counterId, delta, map); -} - -void Anchor::SendPacket_PuzzleCount(s32 counterId, s32 delta, s32 map) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = PUZZLE_COUNT; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["counter"] = counterId; - payload["delta"] = delta; - payload["map"] = map; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_PuzzleCount(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s32 counterId = payload.at("counter").get(); - s32 delta = payload.at("delta").get(); - s32 map = payload.at("map").get(); - - sPuzzleCounts[{ map, counterId }] += delta; -} - -std::vector port_puzzleCount_snapshot() { - std::vector flat; - flat.reserve(sPuzzleCounts.size() * 3); - for (const auto& [key, count] : sPuzzleCounts) { - flat.push_back(key[0]); - flat.push_back(key[1]); - flat.push_back(count); - } - return flat; -} - -void port_puzzleCount_restore(const std::vector& flat) { - sPuzzleCounts.clear(); - for (size_t i = 0; i + 3 <= flat.size(); i += 3) { - sPuzzleCounts[{ flat[i], flat[i + 1] }] = flat[i + 2]; - } -} - -void RegisterPuzzleStep_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - sPuzzleBits.clear(); - sPuzzleCounts.clear(); - sPuzzlePos.clear(); - }); - // Treasure hunt has no actor to poll until the first X is busted. - REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - if (gsworld_getMap() == MAP_7_TTC_TREASURE_TROVE_COVE) { - chTreasurehunt_netTick(); - } - }); -} - -static RegisterShipInitFunc initPuzzleStep(RegisterPuzzleStep_Init, {}); diff --git a/src/port/Network/Anchor/Packets/RequestTeamState.cpp b/src/port/Network/Anchor/Packets/RequestTeamState.cpp index 7ebbfe2b0..220a16f80 100644 --- a/src/port/Network/Anchor/Packets/RequestTeamState.cpp +++ b/src/port/Network/Anchor/Packets/RequestTeamState.cpp @@ -1,6 +1,7 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/OTRGlobals.h" /** * REQUEST_TEAM_STATE @@ -15,10 +16,8 @@ * state */ -void Anchor::SendPacket_RequestTeamState(bool force) { - // `force` bypasses the IsSaveLoaded check: OnGameLoad fires from gameFile_load while the map is - // still FILE_SELECT, so the save is loading but IsSaveLoaded() is still false. - if ((!force && !IsSaveLoaded()) || !roomState.syncItemsAndFlags) { +void Anchor::SendPacket_RequestTeamState() { + if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } diff --git a/src/port/Network/Anchor/Packets/RequestTeleport.cpp b/src/port/Network/Anchor/Packets/RequestTeleport.cpp index 17a0e8926..ab02cedea 100644 --- a/src/port/Network/Anchor/Packets/RequestTeleport.cpp +++ b/src/port/Network/Anchor/Packets/RequestTeleport.cpp @@ -1,11 +1,13 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" /** * REQUEST_TELEPORT * - * Asks a client for their location; they reply with TELEPORT_TO (map, position, yaw). + * Because we don't have all the necessary information to directly teleport to a player, we emit a request, + * in which they will respond with a TELEPORT_TO packet, with the necessary information. */ void Anchor::SendPacket_RequestTeleport(uint32_t clientId) { @@ -29,33 +31,61 @@ void Anchor::HandlePacket_RequestTeleport(nlohmann::json& payload) { SendPacket_TeleportTo(clientId); } +// Reusable function to check if teleporting to a client is allowed bool Anchor::CanTeleportTo(uint32_t clientId) { + // Teleporting is disabled if (roomState.teleportMode == 0) { return false; } + // You're not loaded into a save if (!IsSaveLoaded()) { return false; } + // The client doesn't exist if (clients.find(clientId) == clients.end()) { return false; } AnchorClient& client = clients[clientId]; + // The client is yourself if (client.self) { return false; } + // The client isn't online or loaded into a save if (!client.online || !client.isSaveLoaded) { return false; } + // Teleporting to team only, but the client is not on your team std::string ownTeamId = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); if (roomState.teleportMode == 1 && client.teamId != ownTeamId) { return false; } + //// Problematic scenes for teleporting + // if (client.sceneNum == SCENE_ID_MAX || client.sceneNum == SCENE_GROTTOS || client.sceneNum == SCENE_MARKET_DAY || + // client.sceneNum == SCENE_MARKET_NIGHT || client.sceneNum == SCENE_MARKET_RUINS || + // client.sceneNum == SCENE_MARKET_ENTRANCE_DAY || client.sceneNum == SCENE_MARKET_ENTRANCE_NIGHT || + // client.sceneNum == SCENE_MARKET_ENTRANCE_RUINS || client.sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY || + // client.sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT || + // client.sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS || client.sceneNum == SCENE_BACK_ALLEY_DAY || + // client.sceneNum == SCENE_BACK_ALLEY_NIGHT) { + // return false; + // } + + //// Child can't teleport to Ganon's Castle exterior + // if (client.sceneNum == SCENE_OUTSIDE_GANONS_CASTLE && gSaveContext.linkAge == LINK_AGE_CHILD) { + // return false; + // } + + //// Adult can't teleport to Hyrule Castle exterior + // if (client.sceneNum == SCENE_HYRULE_CASTLE && gSaveContext.linkAge == LINK_AGE_ADULT) { + // return false; + // } + return true; } diff --git a/src/port/Network/Anchor/Packets/ScopedFlag.cpp b/src/port/Network/Anchor/Packets/ScopedFlag.cpp deleted file mode 100644 index b6b6e938a..000000000 --- a/src/port/Network/Anchor/Packets/ScopedFlag.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include "functions.h" - -static uint32_t sMapFlagSetRemotely = 0; - -extern "C" int32_t port_mapFlag_wasSetRemotely(int32_t index) { - return (index >= 0 && index < 32 && (sMapFlagSetRemotely & (1u << index))) ? 1 : 0; -} - -/** - * SCOPED_FLAG - * - * Realtime sync of a transient level-/map flag; ctx = sender's level/map id. - */ - -void Anchor::SendPacket_ScopedFlag(u8 space, s16 index, u8 value) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = SCOPED_FLAG; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["space"] = space; - payload["index"] = index; - payload["value"] = value; - - if (space == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC) { - payload["ctx"] = (s32)map_getLevel(gsworld_getMap()); - SendToCurrentLevelPlayers(payload); - } else { - payload["ctx"] = (s32)gsworld_getMap(); - SendToCurrentMapPlayers(payload); - } -} - -void Anchor::HandlePacket_ScopedFlag(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - u8 space = payload.at("space").get(); - s16 index = payload.at("index").get(); - u8 value = payload.at("value").get(); - s32 ctx = payload.at("ctx").get(); - - if (space == ANCHOR_FLAGSPACE_LEVEL_SPECIFIC) { - if ((s32)map_getLevel(gsworld_getMap()) == ctx) { - levelSpecificFlags_setEx(index, value, 0); - } - } else if (space == ANCHOR_FLAGSPACE_MAP_SPECIFIC) { - if ((s32)gsworld_getMap() == ctx) { - mapSpecificFlags_setEx(index, value, 0); - if (value && index >= 0 && index < 32) { - sMapFlagSetRemotely |= (1u << index); - } - RevealSwitchHoneycomb(); - } - } -} - -void RegisterScopedFlag_Init() { - REGISTER_LISTENER(OnGameFlagSet, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - auto ev = reinterpret_cast(event); - if (ev->flagSpace == ANCHOR_FLAGSPACE_MAP_SPECIFIC && ev->index >= 0 && ev->index < 32) { - sMapFlagSetRemotely &= ~(1u << ev->index); - } - }); - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sMapFlagSetRemotely = 0; }); -} - -static RegisterShipInitFunc initScopedFlag(RegisterScopedFlag_Init, {}); diff --git a/src/port/Network/Anchor/Packets/ScopedState.cpp b/src/port/Network/Anchor/Packets/ScopedState.cpp deleted file mode 100644 index ee0f7c1fb..000000000 --- a/src/port/Network/Anchor/Packets/ScopedState.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include -#include -#include - -#include "functions.h" - -/** - * REQUEST_SCOPED_STATE / SCOPED_STATE - * - * On map load, a client asks the team for current level/map flag state; same-scope teammates reply. - */ - -void Anchor::SendPacket_RequestScopedState(GameMap map) { - nlohmann::json payload; - payload["type"] = REQUEST_SCOPED_STATE; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["level"] = (s32)map_getLevel((enum map_e)map); - payload["map"] = (s32)map; - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_RequestScopedState(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s32 reqLevel = payload.at("level").get(); - s32 reqMap = payload.at("map").get(); - - nlohmann::json response; - response["type"] = SCOPED_STATE; - response["targetClientId"] = payload.at("clientId").get(); - bool any = false; - - if ((s32)map_getLevel(gsworld_getMap()) == reqLevel) { - s32 size; - u8* addr; - levelSpecificFlags_getSizeAndPtr(&size, &addr); - std::vector levelFlags(addr, addr + size); - for (s32 idx = 0; idx < size * 8; idx++) { - if (Anchor_ScopedFlagExcluded(ANCHOR_FLAGSPACE_LEVEL_SPECIFIC, idx)) { - levelFlags[idx >> 3] &= ~(1 << (idx & 7)); - } - } - response["level"] = reqLevel; - response["levelFlags"] = levelFlags; - any = true; - } - if ((s32)gsworld_getMap() == reqMap) { - u32 mapFlags = (u32)mapSpecificFlags_getAll(); - for (s32 idx = 0; idx < 32; idx++) { - if (Anchor_ScopedFlagExcluded(ANCHOR_FLAGSPACE_MAP_SPECIFIC, idx)) { - mapFlags &= ~(1u << idx); - } - } - response["map"] = reqMap; - response["mapFlags"] = mapFlags; - any = true; - } - - if (any) { - SendJsonToRemote(response); - } -} - -void Anchor::HandlePacket_ScopedState(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - if (payload.contains("levelFlags") && (s32)map_getLevel(gsworld_getMap()) == payload.at("level").get()) { - auto bytes = payload["levelFlags"].get>(); - s32 size; - u8* addr; - levelSpecificFlags_getSizeAndPtr(&size, &addr); - s32 count = std::min(size, (s32)bytes.size()); - for (s32 i = 0; i < count; i++) { - addr[i] |= bytes[i]; - } - } - if (payload.contains("mapFlags") && (s32)gsworld_getMap() == payload.at("map").get()) { - u32 mapFlags = payload["mapFlags"].get(); - mapSpecificFlags_setAll(mapSpecificFlags_getAll() | mapFlags); - RevealSwitchHoneycomb(); - } -} diff --git a/src/port/Network/Anchor/Packets/ServerMessage.cpp b/src/port/Network/Anchor/Packets/ServerMessage.cpp index ed1dab04d..dfa3ece6b 100644 --- a/src/port/Network/Anchor/Packets/ServerMessage.cpp +++ b/src/port/Network/Anchor/Packets/ServerMessage.cpp @@ -1,6 +1,7 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "port/UI/Notification.h" /** diff --git a/src/port/Network/Anchor/Packets/SetAbility.cpp b/src/port/Network/Anchor/Packets/SetAbility.cpp deleted file mode 100644 index 903ba8c40..000000000 --- a/src/port/Network/Anchor/Packets/SetAbility.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "functions.h" -extern "C" { -void chSmBottles_netApplyTutorialComplete(void); -} - -/** - * SET_ABILITY - * - * Realtime sync of a learned move. Not queued. - */ - -void Anchor::SendPacket_SetAbility(s16 move, u8 value) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = SET_ABILITY; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["quiet"] = true; - payload["move"] = move; - payload["value"] = value; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_SetAbility(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s16 move = payload.at("move").get(); - u8 value = payload.at("value").get(); - - ability_setLearnedEx(move, value, 0); - if (value) { - ability_setHasUsed((enum ability_e)move); - } - - // A remote unlock just completed the SM tutorial set while we're standing in Spiral - // Mountain with a pre-completion world. Apply the completion state live. - if (value && (s32)gsworld_getMap() == MAP_1_SM_SPIRAL_MOUNTAIN && - !mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED) && - chmole_learnedAllSpiralMountainAbilities()) { - chSmBottles_netApplyTutorialComplete(); - } -} diff --git a/src/port/Network/Anchor/Packets/SetCheckStatus.cpp b/src/port/Network/Anchor/Packets/SetCheckStatus.cpp index 74e9a4698..a0a4334fc 100644 --- a/src/port/Network/Anchor/Packets/SetCheckStatus.cpp +++ b/src/port/Network/Anchor/Packets/SetCheckStatus.cpp @@ -1,80 +1,57 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +//#include "soh/OTRGlobals.h" -#include "port/UI/cvar_prefixes.h" -#include "port/Rando/Rando.h" -#include "port/Rando/CustomObject/CustomObject.h" -#include "port/Rando/StaticData/StaticData.h" - -#include "functions.h" -extern "C" { -void marker_despawn(ActorMarker* marker); -} - -Actor* FindActorByRandoCheckId(RandoCheckId randoCheckId); +static bool isResultOfHandling = false; /** * SET_CHECK_STATUS * - * Fired when a shuffled rando check is first obtained; teammates mark it obtained and - * despawn their copy if in the same map. + * Fired when a check status is updated or skipped */ -void Anchor::SendPacket_SetCheckStatus(s32 rc, s32 map) { - if (!IS_RANDO || !IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = SET_CHECK_STATUS; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["rc"] = rc; - payload["map"] = map; - - SendJsonToRemote(payload); -} - -// Adopt a check a teammate obtained: despawn our copy, mark obtained silently (no item grant, -// notification, or re-broadcast). -void Anchor::AdoptRemoteCheck(s32 rcRaw) { - RandoCheckId rc = (RandoCheckId)rcRaw; - if (rc <= RC_UNKNOWN || rc >= RC_MAX || RANDO_SAVE_CHECKS[rc].eligible) { - return; - } - if (CustomObject::CheckSpawnedIdList(rc)) { - Actor* actor = FindActorByRandoCheckId(rc); - if (actor != NULL && actor->marker != NULL) { - marker_despawn(actor->marker); - } - } - CustomObject::CheckObtainedEX(rc, true); +void Anchor::SendPacket_SetCheckStatus(/*RandomizerCheck rc*/) { + // if (!IsSaveLoaded() || isResultOfHandling) { + // return; + // } + // + // auto randoContext = Rando::Context::GetRawInstance(); + // + // nlohmann::json payload; + // payload["type"] = SET_CHECK_STATUS; + // payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + // payload["addToQueue"] = true; + // payload["rc"] = rc; + // payload["status"] = randoContext->GetItemLocation(rc)->GetCheckStatus(); + // payload["skipped"] = randoContext->GetItemLocation(rc)->GetIsSkipped(); + // payload["quiet"] = true; + // + // SendJsonToRemote(payload); } void Anchor::HandlePacket_SetCheckStatus(nlohmann::json& payload) { - if (!IS_RANDO || !IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - RandoCheckId rc = (RandoCheckId)payload.at("rc").get(); - s32 map = payload.at("map").get(); - - if (rc <= RC_UNKNOWN || rc >= RC_MAX) { - return; - } - if (RANDO_SAVE_CHECKS[rc].eligible) { - return; - } - - // BGS timed-switch checks cleanup - if ((s32)gsworld_getMap() == map && (rc == RC_BGS_JIGGY_ELEVATED_WALKWAY || rc == RC_BGS_JIGGY_MAZE)) { - func_802D6924(); - } - - AdoptRemoteCheck(rc); - - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RandoNotifications"), 0) && ShouldShowNotifications()) { - Rando::StaticData::SendRemoteCheckNotification(rc, GetClientName(payload.value("clientId", 0u))); - } + // if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { + // return; + // } + // + // auto randoContext = Rando::Context::GetRawInstance(); + // + // RandomizerCheck rc = payload.at("rc").get(); + // RandomizerCheckStatus status = payload.at("status").get(); + // bool skipped = payload.at("skipped").get(); + // + // isResultOfHandling = true; + // + // if (randoContext->GetItemLocation(rc)->GetCheckStatus() != status) { + // randoContext->GetItemLocation(rc)->SetCheckStatus(status); + // } + // if (randoContext->GetItemLocation(rc)->GetIsSkipped() != skipped) { + // randoContext->GetItemLocation(rc)->SetIsSkipped(skipped); + // } + // + // CheckTracker::RecalculateAllAreaTotals(); + // CheckTracker::RecalculateAvailableChecks(); + // isResultOfHandling = false; } diff --git a/src/port/Network/Anchor/Packets/SetFlag.cpp b/src/port/Network/Anchor/Packets/SetFlag.cpp index 91a57eb06..88e754f0f 100644 --- a/src/port/Network/Anchor/Packets/SetFlag.cpp +++ b/src/port/Network/Anchor/Packets/SetFlag.cpp @@ -1,47 +1,22 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +//#include "soh/OTRGlobals.h" +extern "C" { #include "functions.h" -#include "port/Patches/Patches.h" -#include "port/Rando/Rando.h" -#include "port/UI/Notification.h" +// extern PlayState* gPlayState; +} /** * SET_FLAG * - * Fired when a flag bit is set (raised) in either flag space. + * Fired when a flag is set in the save context */ -static const char* LevelOpenSeenFlagName(s16 flag) { - switch (flag) { - case 0x28: - return "Mumbo's Mountain"; - case 0x29: - return "Treasure Trove Cove"; - case 0x2A: - return "Clanker's Cavern"; - case 0x2B: - return "Bubblegloop Swamp"; - case 0x2C: - return "Freezeezy Peak"; - case 0x2D: - return "Gobi's Valley"; - case 0x2E: - return "Mad Monster Mansion"; - case 0x2F: - return "Rusty Bucket Bay"; - case 0x30: - return "Click Clock Wood"; - case FILEPROG_E2_DOOR_OF_GRUNTY_OPEN: - return "the door to Gruntilda"; - default: - return nullptr; - } -} - -void Anchor::SendPacket_SetFlag(u8 flagSpace, s16 flag) { +void Anchor::SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag) { if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } @@ -50,7 +25,8 @@ void Anchor::SendPacket_SetFlag(u8 flagSpace, s16 flag) { payload["type"] = SET_FLAG; payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); payload["addToQueue"] = true; - payload["flagSpace"] = flagSpace; + payload["sceneNum"] = sceneNum; + payload["flagType"] = flagType; payload["flag"] = flag; SendJsonToRemote(payload); @@ -61,28 +37,37 @@ void Anchor::HandlePacket_SetFlag(nlohmann::json& payload) { return; } - u8 flagSpace = payload.at("flagSpace").get(); + s16 sceneNum = payload.at("sceneNum").get(); + s16 flagType = payload.at("flagType").get(); s16 flag = payload.at("flag").get(); - if (flagSpace == ANCHOR_FLAGSPACE_RANDO_INF) { - // Non-derived rando flag; set directly. - if (IS_RANDO && flag > RANDO_INF_UNKNOWN && flag < RANDO_INF_MAX) { - RANDO_SAVE_FLAGS[flag].flagState = 1; - } - } else if (flagSpace == ANCHOR_FLAGSPACE_VOLATILE) { - volatileFlag_setEx((enum volatile_flags_e)flag, 1, 0); - } else { - bool wasSet = fileProgressFlag_get((enum file_progress_e)flag) != 0; - fileProgressFlag_setEx((enum file_progress_e)flag, 1, 0); - port_progressFlag_remoteCue(flag); - // Vanilla only; rando reports world access via SET_CHECK_STATUS instead. - if (!wasSet && !IS_RANDO && ShouldShowNotifications()) { - if (const char* opened = LevelOpenSeenFlagName(flag)) { - Notification::Emit({ - .prefix = GetClientName(payload.value("clientId", 0u)), - .message = std::string("opened ") + opened, - }); - } - } - } + // if (sceneNum == SCENE_ID_MAX) { + // auto effect = new GameInteractionEffect::SetFlag(); + // effect->parameters[0] = flagType; + // effect->parameters[1] = flag; + // effect->Apply(); + + // // Special case: If King Zora moved, and the player has Ruto's Letter, convert it to an empty bottle + // if (flagType == FLAG_EVENT_CHECK_INF && flag == EVENTCHKINF_KING_ZORA_MOVED && + // Inventory_HasSpecificBottle(ITEM_LETTER_RUTO)) { + // Inventory_ReplaceItem(gPlayState, ITEM_LETTER_RUTO, ITEM_BOTTLE); + // } + //} else { + // // Special case: Ignore water temple water level flags, stored at 0x1C, 0x1D, 0x1E. + // if (sceneNum == SCENE_WATER_TEMPLE && flagType == FLAG_SCENE_SWITCH && + // (flag == 0x1C || flag == 0x1D || flag == 0x1E)) { + // return; + // } + + // // Special case: Ignore forest temple elevator flag, stored at 0x1B. + // if (sceneNum == SCENE_FOREST_TEMPLE && flagType == FLAG_SCENE_SWITCH && flag == 0x1B) { + // return; + // } + + // auto effect = new GameInteractionEffect::SetSceneFlag(); + // effect->parameters[0] = sceneNum; + // effect->parameters[1] = flagType; + // effect->parameters[2] = flag; + // effect->Apply(); + //} } diff --git a/src/port/Network/Anchor/Packets/SetItemCount.cpp b/src/port/Network/Anchor/Packets/SetItemCount.cpp deleted file mode 100644 index 0ae95b34c..000000000 --- a/src/port/Network/Anchor/Packets/SetItemCount.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "functions.h" -extern "C" { -s32 item_adjustByDiff(enum item_e item, s32 diff, s32 no_hud, s32 triggerEvent); -} - -/** - * ITEM_COUNT - * - * Realtime sync of a spendable item count (absolute value). Not queued. - */ - -void Anchor::SendPacket_SetItemCount(s16 item, s32 count) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = ITEM_COUNT; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["quiet"] = true; - payload["item"] = item; - payload["count"] = count; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_SetItemCount(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s16 item = payload.at("item").get(); - s32 count = payload.at("count").get(); - - // Jiggy-total increase is a teammate's collect: apply silently (paired COLLECT_ITEM pops the - // HUD counter). Decreases (pedestal spends) keep the vanilla total pop. - if (item == ITEM_26_JIGGY_TOTAL && count > item_getCount(ITEM_26_JIGGY_TOTAL)) { - item_adjustByDiff((enum item_e)item, count - item_getCount(ITEM_26_JIGGY_TOTAL), 1, 0); - return; - } - - item_setEx(item, count, 0); -} diff --git a/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp b/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp deleted file mode 100644 index 5441ecf81..000000000 --- a/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "functions.h" -extern "C" { -void chHoneycomb_netSpawnDropAt(s32 uid, s32 bundleId, f32 x, f32 y, f32 z); -} - -void Anchor::SendPacket_SpawnHoneycomb(s16 honeycombId, s32 bundleId, f32 x, f32 y, f32 z) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - nlohmann::json payload; - payload["type"] = HONEYCOMB_SPAWN; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["honeycombId"] = honeycombId; - payload["bundle"] = bundleId; - payload["x"] = x; - payload["y"] = y; - payload["z"] = z; - payload["ctx"] = (s32)gsworld_getMap(); - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_SpawnHoneycomb(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s16 honeycombId = payload.at("honeycombId").get(); - if ((s32)gsworld_getMap() != payload.at("ctx").get()) { - return; - } - if (honeycombscore_get((enum honeycomb_e)honeycombId)) { - return; - } - // Already present locally, nothing to add. - if (actorArray_findHoneycombMarkerById((enum honeycomb_e)honeycombId) != nullptr) { - return; - } - - chHoneycomb_netSpawnDropAt(honeycombId, payload.at("bundle").get(), payload.at("x").get(), - payload.at("y").get(), payload.at("z").get()); -} diff --git a/src/port/Network/Anchor/Packets/SpawnJiggy.cpp b/src/port/Network/Anchor/Packets/SpawnJiggy.cpp deleted file mode 100644 index 54827734f..000000000 --- a/src/port/Network/Anchor/Packets/SpawnJiggy.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include -#include - -#include "functions.h" - -/** - * JIGGY_SPAWN - * - * Sync of dynamically spawned jiggies (witch-switch puzzle, minigame reward, jinjo fifth, etc). - * Team-wide record (map -> jiggyId -> position) re-applied every map visit. - */ - -struct SpawnedJiggy { - int16_t jiggyId; - float x; - float y; - float z; - bool inFlight = false; -}; -std::map> sSpawnedJiggies; - -SpawnedJiggy& recordJiggySpawn(int32_t map, int16_t jiggyId, float x, float y, float z) { - auto& list = sSpawnedJiggies[map]; - for (auto& pj : list) { - if (pj.jiggyId == jiggyId) { - pj.x = x; - pj.y = y; - pj.z = z; - return pj; - } - } - list.push_back({ jiggyId, x, y, z }); - return list.back(); -} - -void trySpawnRecordedJiggy(SpawnedJiggy& pj) { - if (jiggyscore_isCollected((enum jiggy_e)pj.jiggyId)) { - return; - } - if (jiggylist_hasSpawnedObject((enum jiggy_e)pj.jiggyId)) { - pj.inFlight = false; - return; - } - if (pj.inFlight) { - return; - } - f32 pos[3] = { pj.x, pj.y, pj.z }; - codeABC00_spawnJiggyAtLocationEx((enum jiggy_e)pj.jiggyId, pos, 0); // silent, no re-broadcast - pj.inFlight = true; -} - -void Anchor::SendPacket_SpawnJiggy(s16 jiggyId, f32 x, f32 y, f32 z) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s32 map = (s32)gsworld_getMap(); - recordJiggySpawn(map, jiggyId, x, y, z); - - nlohmann::json payload; - payload["type"] = JIGGY_SPAWN; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["addToQueue"] = true; - payload["jiggyId"] = jiggyId; - payload["x"] = x; - payload["y"] = y; - payload["z"] = z; - payload["map"] = map; - - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_SpawnJiggy(nlohmann::json& payload) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - - s16 jiggyId = payload.at("jiggyId").get(); - s32 map = payload.at("map").get(); - f32 x = payload.at("x").get(); - f32 y = payload.at("y").get(); - f32 z = payload.at("z").get(); - - SpawnedJiggy& pj = recordJiggySpawn(map, jiggyId, x, y, z); - - if ((s32)gsworld_getMap() == map) { - trySpawnRecordedJiggy(pj); - } -} - -void Anchor::FlushPendingJiggySpawns() { - auto it = sSpawnedJiggies.find((s32)gsworld_getMap()); - if (it == sSpawnedJiggies.end()) { - return; - } - auto& list = it->second; - for (size_t i = 0; i < list.size();) { - auto& pj = list[i]; - if (jiggyscore_isCollected((enum jiggy_e)pj.jiggyId)) { - list.erase(list.begin() + i); - continue; - } - trySpawnRecordedJiggy(pj); - i++; - } -} - -// Team-state snapshot/restore (UpdateTeamState.cpp). Flat [map, jiggyId, x, y, z] tuples. -std::vector port_jiggySpawn_snapshot() { - std::vector flat; - for (const auto& [map, list] : sSpawnedJiggies) { - for (const auto& pj : list) { - flat.push_back(map); - flat.push_back(pj.jiggyId); - flat.push_back((int32_t)pj.x); - flat.push_back((int32_t)pj.y); - flat.push_back((int32_t)pj.z); - } - } - return flat; -} - -void port_jiggySpawn_restore(const std::vector& flat) { - sSpawnedJiggies.clear(); - for (size_t i = 0; i + 5 <= flat.size(); i += 5) { - sSpawnedJiggies[flat[i]].push_back( - { (int16_t)flat[i + 1], (float)flat[i + 2], (float)flat[i + 3], (float)flat[i + 4] }); - } -} - -extern "C" void port_jiggySpawn_remove(int32_t jiggyId) { - for (auto& [map, list] : sSpawnedJiggies) { - std::erase_if(list, [jiggyId](const SpawnedJiggy& pj) { return pj.jiggyId == jiggyId; }); - } -} - -extern "C" int32_t port_jiggySpawn_isRecorded(int32_t jiggyId) { - if (jiggyscore_isCollected((enum jiggy_e)jiggyId)) { - return 0; - } - for (const auto& [map, list] : sSpawnedJiggies) { - for (const auto& pj : list) { - if (pj.jiggyId == jiggyId) { - return 1; - } - } - } - return 0; -} - -void RegisterSpawnJiggy_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sSpawnedJiggies.clear(); }); - - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - for (auto& [map, list] : sSpawnedJiggies) { - for (auto& pj : list) { - pj.inFlight = false; - } - } - }); -} - -static RegisterShipInitFunc initSpawnJiggy(RegisterSpawnJiggy_Init, {}); diff --git a/src/port/Network/Anchor/Packets/TeleportTo.cpp b/src/port/Network/Anchor/Packets/TeleportTo.cpp index ba66addf4..31140ff70 100644 --- a/src/port/Network/Anchor/Packets/TeleportTo.cpp +++ b/src/port/Network/Anchor/Packets/TeleportTo.cpp @@ -1,16 +1,18 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "port/Network/Anchor/JsonConversions.hpp" -#include "functions.h" - -// Exit id the game reserves for "spawn at an explicit position" (see func_8028E4B0). -#define EXIT_WARP_DESTINATION 0x63 +extern "C" { +#include "macros.h" +// extern PlayState* gPlayState; +} /** * TELEPORT_TO * - * See REQUEST_TELEPORT; carries the sender's live map/position/yaw. + * See REQUEST_TELEPORT for more information, this is the second part of the process. */ void Anchor::SendPacket_TeleportTo(uint32_t clientId) { @@ -18,18 +20,16 @@ void Anchor::SendPacket_TeleportTo(uint32_t clientId) { return; } - f32 pos[3]; - player_getPosition(pos); + /*Player* player = GET_PLAYER(gPlayState); nlohmann::json payload; payload["type"] = TELEPORT_TO; payload["targetClientId"] = clientId; - payload["map"] = gsworld_getMap(); - payload["exit"] = gsworld_getExit(); - payload["pos"] = pos; - payload["yaw"] = player_getYaw(); + payload["entranceIndex"] = gSaveContext.entranceIndex; + payload["roomIndex"] = gPlayState->roomCtx.curRoom.num; + payload["posRot"] = player->actor.world; - SendJsonToRemote(payload); + SendJsonToRemote(payload);*/ } void Anchor::HandlePacket_TeleportTo(nlohmann::json& payload) { @@ -37,18 +37,23 @@ void Anchor::HandlePacket_TeleportTo(nlohmann::json& payload) { return; } - GameMap map = payload.at("map").get(); - std::vector pos = payload.at("pos").get>(); - f32 yaw = payload.at("yaw").get(); - - if (map == (GameMap)gsworld_getMap()) { - yaw_set(yaw); - yaw_setIdeal(yaw); - yaw_applyIdeal(); - func_8028F85C(pos.data()); - return; - } - - player_setWarpDestination(pos.data(), yaw, payload.value("exit", 0)); - func_8031D04C(map, EXIT_WARP_DESTINATION); + // s32 entranceIndex = payload.at("entranceIndex").get(); + // s8 roomIndex = payload.at("roomIndex").get(); + // PosRot posRot = payload.at("posRot").get(); + + // gPlayState->nextEntranceIndex = entranceIndex; + // gPlayState->transitionTrigger = TRANS_TRIGGER_START; + // gPlayState->transitionType = TRANS_TYPE_INSTANT; + // gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = entranceIndex; + // gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = roomIndex; + // gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = posRot.pos; + // gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = posRot.rot.y; + // gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0xDFF; + // gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST; + // gSaveContext.respawnFlag = 1; + // static HOOK_ID hookId = 0; + // hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, { + // *should = false; + // GameInteractor::Instance->UnregisterGameHookForID(hookId); + // }); } diff --git a/src/port/Network/Anchor/Packets/UnsetFlag.cpp b/src/port/Network/Anchor/Packets/UnsetFlag.cpp index 745e60f51..e1b88908c 100644 --- a/src/port/Network/Anchor/Packets/UnsetFlag.cpp +++ b/src/port/Network/Anchor/Packets/UnsetFlag.cpp @@ -1,16 +1,22 @@ #include "port/Network/Anchor/Anchor.h" #include #include +//#include "soh/Enhancements/game-interactor/GameInteractor.h" +//#include "soh/OTRGlobals.h" +extern "C" { #include "functions.h" +//#include "soh/Enhancements/randomizer/ShuffleTradeItems.h" +// extern PlayState* gPlayState; +} /** * UNSET_FLAG * - * Fired when a flag bit is cleared (lowered) in either flag space. + * Fired when a flag is unset in the save context */ -void Anchor::SendPacket_UnsetFlag(u8 flagSpace, s16 flag) { +void Anchor::SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag) { if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } @@ -19,7 +25,8 @@ void Anchor::SendPacket_UnsetFlag(u8 flagSpace, s16 flag) { payload["type"] = UNSET_FLAG; payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); payload["addToQueue"] = true; - payload["flagSpace"] = flagSpace; + payload["sceneNum"] = sceneNum; + payload["flagType"] = flagType; payload["flag"] = flag; SendJsonToRemote(payload); @@ -30,12 +37,73 @@ void Anchor::HandlePacket_UnsetFlag(nlohmann::json& payload) { return; } - u8 flagSpace = payload.at("flagSpace").get(); + s16 sceneNum = payload.at("sceneNum").get(); + s16 flagType = payload.at("flagType").get(); s16 flag = payload.at("flag").get(); - if (flagSpace == ANCHOR_FLAGSPACE_VOLATILE) { - volatileFlag_setEx((enum volatile_flags_e)flag, 0, 0); - } else { - fileProgressFlag_setEx((enum file_progress_e)flag, 0, 0); - } + // if (sceneNum == SCENE_ID_MAX) { + // auto effect = new GameInteractionEffect::UnsetFlag(); + // effect->parameters[0] = flagType; + // effect->parameters[1] = flag; + // effect->Apply(); + + // // Special case: If an adult trade item flag is unset, replace the item if the player has it equipped + // if (flagType == FLAG_RANDOMIZER_INF && + // (flag >= RAND_INF_ADULT_TRADES_HAS_POCKET_EGG && flag <= RAND_INF_ADULT_TRADES_HAS_CLAIM_CHECK)) { + // u16 itemToReplace = ITEM_POCKET_EGG; + // switch (flag) { + // case RAND_INF_ADULT_TRADES_HAS_POCKET_EGG: + // itemToReplace = ITEM_POCKET_EGG; + // break; + // case RAND_INF_ADULT_TRADES_HAS_POCKET_CUCCO: + // itemToReplace = ITEM_POCKET_CUCCO; + // break; + // case RAND_INF_ADULT_TRADES_HAS_COJIRO: + // itemToReplace = ITEM_COJIRO; + // break; + // case RAND_INF_ADULT_TRADES_HAS_ODD_MUSHROOM: + // itemToReplace = ITEM_ODD_MUSHROOM; + // break; + // case RAND_INF_ADULT_TRADES_HAS_ODD_POTION: + // itemToReplace = ITEM_ODD_POTION; + // break; + // case RAND_INF_ADULT_TRADES_HAS_SAW: + // itemToReplace = ITEM_SAW; + // break; + // case RAND_INF_ADULT_TRADES_HAS_SWORD_BROKEN: + // itemToReplace = ITEM_SWORD_BROKEN; + // break; + // case RAND_INF_ADULT_TRADES_HAS_PRESCRIPTION: + // itemToReplace = ITEM_PRESCRIPTION; + // break; + // case RAND_INF_ADULT_TRADES_HAS_FROG: + // itemToReplace = ITEM_FROG; + // break; + // case RAND_INF_ADULT_TRADES_HAS_EYEDROPS: + // itemToReplace = ITEM_EYEDROPS; + // break; + // case RAND_INF_ADULT_TRADES_HAS_CLAIM_CHECK: + // itemToReplace = ITEM_CLAIM_CHECK; + // break; + // } + // Inventory_ReplaceItem(gPlayState, itemToReplace, Randomizer_GetNextAdultTradeItem()); + // } + //} else { + // // Special case: Ignore water temple water level flags, stored at 0x1C, 0x1D, 0x1E. + // if (sceneNum == SCENE_WATER_TEMPLE && flagType == FLAG_SCENE_SWITCH && + // (flag == 0x1C || flag == 0x1D || flag == 0x1E)) { + // return; + // } + + // // Special case: Ignore forest temple elevator flag, stored at 0x1B. + // if (sceneNum == SCENE_FOREST_TEMPLE && flagType == FLAG_SCENE_SWITCH && flag == 0x1B) { + // return; + // } + + // auto effect = new GameInteractionEffect::UnsetSceneFlag(); + // effect->parameters[0] = sceneNum; + // effect->parameters[1] = flagType; + // effect->parameters[2] = flag; + // effect->Apply(); + //} } diff --git a/src/port/Network/Anchor/Packets/UpdateClientState.cpp b/src/port/Network/Anchor/Packets/UpdateClientState.cpp index 12ef0a91b..9482d448f 100644 --- a/src/port/Network/Anchor/Packets/UpdateClientState.cpp +++ b/src/port/Network/Anchor/Packets/UpdateClientState.cpp @@ -3,10 +3,12 @@ #include "port/Network/Anchor/JsonConversions.hpp" #include #include +//#include "soh/OTRGlobals.h" -#include "port/Rando/Rando.h" - +extern "C" { #include "variables.h" +// extern PlayState* gPlayState; +} /** * UPDATE_CLIENT_STATE @@ -26,12 +28,8 @@ nlohmann::json Anchor::PrepClientState() { payload["teamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); payload["online"] = true; - BKPlayerColorSet colors; - PlayerColors_getLocal(&colors); - to_json(payload["colors"], colors); - if (IsSaveLoaded()) { - payload["seed"] = (uint32_t)(IS_RANDO ? RANDO_SEED : 0); + payload["seed"] = /*IS_RANDO ? Rando::Context::GetRawInstance()->GetSeed() : */ 0; payload["isSaveLoaded"] = true; payload["isGameComplete"] = false; payload["map"] = gsworld_getMap(); @@ -62,6 +60,7 @@ void Anchor::HandlePacket_UpdateClientState(nlohmann::json& payload) { AnchorClient client = payload["state"].get(); clients[clientId].clientId = clientId; clients[clientId].name = client.name; + // clients[clientId].color = client.color; clients[clientId].clientVersion = client.clientVersion; clients[clientId].teamId = client.teamId; clients[clientId].online = client.online; @@ -70,11 +69,8 @@ void Anchor::HandlePacket_UpdateClientState(nlohmann::json& payload) { clients[clientId].isGameComplete = client.isGameComplete; clients[clientId].map = client.map; clients[clientId].exit = client.exit; - clients[clientId].colors = client.colors; - ApplyClientCosmetics(clientId); EvaluateDummyForClient(clientId); Authority_OnClientStateChanged(clientId, client.online, client.map); - SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); if (client.online) { // Covers clients (re)connecting while already in an activity's map: rebroadcast // any claim of ours so they don't briefly act as their own authority. diff --git a/src/port/Network/Anchor/Packets/UpdateRoomState.cpp b/src/port/Network/Anchor/Packets/UpdateRoomState.cpp index e8e98a539..de1263a67 100644 --- a/src/port/Network/Anchor/Packets/UpdateRoomState.cpp +++ b/src/port/Network/Anchor/Packets/UpdateRoomState.cpp @@ -4,11 +4,14 @@ #include #include "port/Romhack/RomhackConfig.h" #include "port/Romhack/RomhackCompat.h" -#include "port/Rando/Rando.h" #include "port/UI/LighthouseGui.hpp" #include "port/UI/LighthouseModals.h" +//#include "soh/OTRGlobals.h" +extern "C" { #include "variables.h" +// extern PlayState* gPlayState; +} /** * UPDATE_ROOM_STATE @@ -17,29 +20,22 @@ nlohmann::json Anchor::PrepRoomState() { nlohmann::json payload; payload["ownerClientId"] = ownClientId; - - if (IsGlobalRoom()) { - payload["pvpMode"] = 0; - payload["showLocationsMode"] = 0; - payload["teleportMode"] = 0; - payload["syncItemsAndFlags"] = 0; - payload["shareConsumables"] = 0; - payload["isRomHack"] = false; - payload["romhackName"] = ""; - payload["isRando"] = false; - payload["seed"] = 0; - return payload; - } - + bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "")); + + // if (isGlobalRoom) { + // // Global room uses hardcoded settings + // payload["pvpMode"] = 0; + // payload["showLocationsMode"] = 0; + // payload["teleportMode"] = 0; + // payload["syncItemsAndFlags"] = 0; + // } else { payload["pvpMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), 1); payload["showLocationsMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), 1); payload["teleportMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.TeleportMode"), 1); payload["syncItemsAndFlags"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.SyncItemsAndFlags"), 1); - payload["shareConsumables"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.ShareConsumables"), 0); payload["isRomHack"] = port_isRomhack(); payload["romhackName"] = Lighthouse::CurrentRomhackLabel(); - payload["isRando"] = (bool)IS_RANDO; - payload["seed"] = (int32_t)(IS_RANDO ? RANDO_SEED : 0); + //} return payload; } @@ -56,35 +52,17 @@ void Anchor::HandlePacket_UpdateRoomState(nlohmann::json& payload) { if (!payload.contains("state")) { return; } - - if (IsGlobalRoom()) { - roomState.ownerClientId = payload["state"].value("ownerClientId", (uint32_t)0); - roomState.pvpMode = 0; - roomState.showLocationsMode = 0; - roomState.teleportMode = 0; - roomState.syncItemsAndFlags = 0; - roomState.shareConsumables = 0; - roomState.isRomhack = false; - roomState.romhackName.clear(); - return; - } - roomState.isRomhack = payload["state"]["isRomHack"].get(); roomState.romhackName = payload["state"]["romhackName"].get(); const std::string localLabel = Lighthouse::CurrentRomhackLabel(); if (roomState.romhackName != localLabel) { - if (roomState.romhackName != lastWarnedRomhackLabel) { - lastWarnedRomhackLabel = roomState.romhackName; - std::string msg = "There's a romhack mismatch between your client and the server:\n\n"; - msg += Lighthouse::DescribeRomhackMismatch(port_isRomhack(), localLabel, roomState.isRomhack, - roomState.romhackName); - msg += "\n\nYou can still play together, but items, flags, and custom content\n" - "may not sync correctly. To avoid desyncs, enable or disable the\n" - "appropriate mod(s) in the Mod Menu so both sides match, then reconnect."; - LighthouseGui::RegisterPopup("Romhack Mismatch Warning", msg); - } - } else { - lastWarnedRomhackLabel.clear(); + Disable(); + std::string msg = "There's a romhack mismatch between your client and the server:\n\n"; + msg += Lighthouse::DescribeRomhackMismatch(port_isRomhack(), localLabel, roomState.isRomhack, + roomState.romhackName); + msg += "\n\nAnchor has been disabled. Please enable or disable the appropriate\n" + "mod(s) in the Mod Menu and reconnect, or enter a new room name."; + LighthouseGui::RegisterPopup("Incompatible Romhack State", msg); } roomState.ownerClientId = payload["state"]["ownerClientId"].get(); @@ -92,49 +70,4 @@ void Anchor::HandlePacket_UpdateRoomState(nlohmann::json& payload) { roomState.showLocationsMode = payload["state"]["showLocationsMode"].get(); roomState.teleportMode = payload["state"]["teleportMode"].get(); roomState.syncItemsAndFlags = payload["state"]["syncItemsAndFlags"].get(); - roomState.shareConsumables = payload["state"].value("shareConsumables", (u8)0); - roomState.isRando = payload["state"].value("isRando", false); - roomState.seed = payload["state"].value("seed", (int32_t)0); - - CheckRandoRoomCompatibility(); -} - -void Anchor::CheckRandoRoomCompatibility() { - if (IsGlobalRoom() || !isConnected || !IsSaveLoaded()) { - return; - } - - const bool localRando = IS_RANDO; - const int32_t localSeed = localRando ? (int32_t)RANDO_SEED : 0; - - std::string msg; - if (roomState.isRando && !localRando) { - msg = "This is a randomizer room, but the save you loaded is not a randomizer file.\n\n" - "Items, flags, and checks will not line up - you'll receive progress you can't use\n" - "and may corrupt the shared session. Load the matching randomizer file, or\n" - "disconnect before continuing."; - } else if (!roomState.isRando && localRando) { - msg = "You loaded a randomizer file, but this room is running a vanilla game.\n\n" - "Shuffled checks won't match what teammates send, so progress will desync.\n" - "Reconnect to a randomizer room, or load a vanilla file to match this one."; - } else if (roomState.isRando && localRando && roomState.seed != localSeed) { - msg = "Seed mismatch: your randomizer seed differs from the room's.\n\n" - "Checks are shuffled differently per seed, so syncing will scatter items to the\n" - "wrong locations. Everyone on a team must generate/load from the same seed.\n"; - msg += "\n Your seed: " + std::to_string(localSeed); - msg += "\n Room seed: " + std::to_string(roomState.seed); - } - - if (msg.empty()) { - lastWarnedRandoState.clear(); - return; - } - - std::string sig = std::to_string(roomState.isRando) + ":" + std::to_string(roomState.seed) + "|" + - std::to_string(localRando) + ":" + std::to_string(localSeed); - if (sig == lastWarnedRandoState) { - return; - } - lastWarnedRandoState = sig; - LighthouseGui::RegisterPopup("Randomizer Mismatch Warning", msg); } diff --git a/src/port/Network/Anchor/Packets/UpdateTeamState.cpp b/src/port/Network/Anchor/Packets/UpdateTeamState.cpp index 380097a40..a51b0046d 100644 --- a/src/port/Network/Anchor/Packets/UpdateTeamState.cpp +++ b/src/port/Network/Anchor/Packets/UpdateTeamState.cpp @@ -2,97 +2,110 @@ #include "port/Network/Anchor/JsonConversions.hpp" #include #include +//#include "soh/OTRGlobals.h" #include "port/UI/Notification.h" -#include "port/Enhancements/Retention/Retention.h" -#include "port/Rando/Rando.h" -#include -#include +extern "C" { #include "variables.h" -#include "functions.h" - -// In-memory session sets that aren't part of the save but still ride team state. Flat int -// tuples; defined in the respective port modules. -extern std::vector port_breakable_snapshotBroken(); -extern void port_breakable_restoreBroken(const std::vector& flat); -extern std::vector port_carriedSync_snapshotCollected(); -extern void port_carriedSync_restoreCollected(const std::vector& flat); -extern std::vector port_eggToll_snapshot(); -extern void port_eggToll_restore(const std::vector& flat); -extern std::vector port_puzzleStep_snapshot(); -extern void port_puzzleStep_restore(const std::vector& flat); -extern std::vector port_puzzleCount_snapshot(); -extern void port_puzzleCount_restore(const std::vector& flat); -extern std::vector port_puzzlePos_snapshot(); -extern void port_puzzlePos_restore(const std::vector& flat); -extern std::vector port_jiggySpawn_snapshot(); -extern void port_jiggySpawn_restore(const std::vector& flat); -extern std::vector port_hutSmash_snapshot(); -extern void port_hutSmash_restore(const std::vector& flat); +// extern PlayState* gPlayState; +} /** * UPDATE_TEAM_STATE * - * Pushes our full flag state to teammates on REQUEST_TEAM_STATE or on save. Sending clears - * the team queue (assumed drained); receiving replays any queued packets after applying state. + * Pushes the current save state to the server for other teammates to use. + * + * Fires when the server passes on a REQUEST_TEAM_STATE packet, or when this client saves the game + * + * When sending this packet we will assume that the team queue has been emptied for this client, so the queue + * stored in the server will be cleared. + * + * When receiving this packet, if there is items in the team queue, we will play them back in order. */ -// Snapshot a decomp byte-array score/flag section into a JSON byte array. -static std::vector ScoreBytes(void (*getSizeAndPtr)(s32*, u8**)) { - s32 size; - u8* addr; - getSizeAndPtr(&size, &addr); - return std::vector(addr, addr + size); -} - void Anchor::SendPacket_UpdateTeamState() { if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { return; } - json payload; - payload["type"] = UPDATE_TEAM_STATE; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["queue"] = json::array(); - payload["state"]["fileProgressFlags"] = ScoreBytes(fileProgressFlag_getSizeAndPtr); - payload["state"]["jiggies"] = ScoreBytes(jiggyscore_getSizeAndPtr); - payload["state"]["honeycombs"] = ScoreBytes(honeycombscore_getSizeAndPtr); - payload["state"]["mumboTokens"] = ScoreBytes(mumboscore_getSizeAndPtr); - payload["state"]["noteScores"] = ScoreBytes(itemscore_noteScores_getSizeAndPtr); - payload["state"]["savedItems"] = ScoreBytes(saveditem_getSizeAndPtr); - payload["state"]["abilities"] = ScoreBytes(ability_getSizeAndPtr); - // Time scores use a (s32*, void**) accessor, so packed inline. - s32 tsSize; - void* tsAddr; - timeScores_getSizeAndPtr(&tsSize, &tsAddr); - payload["state"]["timeScores"] = std::vector((u8*)tsAddr, (u8*)tsAddr + tsSize); - payload["state"]["volatileFlags"] = ScoreBytes(volatileFlag_getSizeAndPtr); - // In-memory session sets (never saved). - payload["state"]["brokenObjects"] = port_breakable_snapshotBroken(); - payload["state"]["carriedCollected"] = port_carriedSync_snapshotCollected(); - payload["state"]["eggTolls"] = port_eggToll_snapshot(); - payload["state"]["puzzleSteps"] = port_puzzleStep_snapshot(); - payload["state"]["puzzleCounts"] = port_puzzleCount_snapshot(); - payload["state"]["puzzlePos"] = port_puzzlePos_snapshot(); - payload["state"]["spawnedJiggies"] = port_jiggySpawn_snapshot(); - payload["state"]["huts"] = port_hutSmash_snapshot(); - - // Randomizer progress lives outside the vanilla score sections: obtained checks + RANDO_INF flags. - if (IS_RANDO) { - std::vector checks(RC_MAX, 0); - for (s32 rc = RC_UNKNOWN + 1; rc < RC_MAX; rc++) { - checks[rc] = RANDO_SAVE_CHECKS[rc].eligible ? 1 : 0; - } - payload["state"]["randoChecks"] = checks; - - std::vector randoFlags(RANDO_INF_MAX, 0); - for (s32 i = RANDO_INF_UNKNOWN + 1; i < RANDO_INF_MAX; i++) { - randoFlags[i] = RANDO_SAVE_FLAGS[i].flagState; - } - payload["state"]["randoFlags"] = randoFlags; - } + // json payload; + // payload["type"] = UPDATE_TEAM_STATE; + // payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - SendJsonToRemote(payload); + //// Assume the team queue has been emptied, so clear it + // payload["queue"] = json::array(); + + // payload["state"] = gSaveContext; + //// manually update current scene flags + // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4] = gPlayState->actorCtx.flags.chest; + // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 1] = gPlayState->actorCtx.flags.swch; + // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 2] = gPlayState->actorCtx.flags.clear; + // payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 3] = gPlayState->actorCtx.flags.collect; + + //// The commented out code below is an attempt at sending the entire randomizer seed over, in hopes that a player + //// doesn't have to generate the seed themselves Currently it doesn't work :) + // if (IS_RANDO) { + // auto randoContext = Rando::Context::GetRawInstance(); + + // payload["state"]["rando"] = json::object(); + // payload["state"]["rando"]["itemLocations"] = json::array(); + // for (int i = 0; i < RC_MAX; i++) { + // payload["state"]["rando"]["itemLocations"][i] = json::array(); + // // payload["state"]["rando"]["itemLocations"][i]["rgID"] = + // // randoContext->GetItemLocation(i)->GetPlacedRandomizerGet(); + // payload["state"]["rando"]["itemLocations"][i][0] = randoContext->GetItemLocation(i)->GetCheckStatus(); + // payload["state"]["rando"]["itemLocations"][i][1] = (u8)randoContext->GetItemLocation(i)->GetIsSkipped(); + + // if (randoContext->GetItemLocation(i)->GetPlacedRandomizerGet() == RG_ICE_TRAP) { + // payload["state"]["rando"]["itemLocations"][i]["fakeRgID"] = + // randoContext->GetItemOverride(i).LooksLike(); + // payload["state"]["rando"]["itemLocations"][i]["trickName"] = json::object(); + // payload["state"]["rando"]["itemLocations"][i]["trickName"]["english"] = + // randoContext->GetItemOverride(i).GetTrickName().GetEnglish(); + // payload["state"]["rando"]["itemLocations"][i]["trickName"]["french"] = + // randoContext->GetItemOverride(i).GetTrickName().GetFrench(); + // } + // if (randoContext->GetItemLocation(i)->HasCustomPrice()) { + // payload["state"]["rando"]["itemLocations"][i]["price"] = + // randoContext->GetItemLocation(i)->GetPrice(); + // } + //} + + // auto entranceCtx = randoContext->GetEntranceShuffler(); + // for (int i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { + // payload["state"]["rando"]["entrances"][i] = json::object(); + // payload["state"]["rando"]["entrances"][i]["type"] = entranceCtx->entranceOverrides[i].type; + // payload["state"]["rando"]["entrances"][i]["index"] = entranceCtx->entranceOverrides[i].index; + // payload["state"]["rando"]["entrances"][i]["destination"] = entranceCtx->entranceOverrides[i].destination; + // payload["state"]["rando"]["entrances"][i]["override"] = entranceCtx->entranceOverrides[i].override; + // payload["state"]["rando"]["entrances"][i]["overrideDestination"] = + // entranceCtx->entranceOverrides[i].overrideDestination; + // } + + // payload["state"]["rando"]["seed"] = json::array(); + // for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) { + // payload["state"]["rando"]["seed"][i] = randoContext->hashIconIndexes[i]; + // } + // payload["state"]["rando"]["inputSeed"] = randoContext->GetSeedString(); + // payload["state"]["rando"]["finalSeed"] = randoContext->GetSeed(); + + // payload["state"]["rando"]["randoSettings"] = json::array(); + // for (int i = 0; i < RSK_MAX; i++) { + // payload["state"]["rando"]["randoSettings"][i] = + // randoContext->GetOption((RandomizerSettingKey(i))).GetSelectedOptionIndex(); + // } + + // payload["state"]["rando"]["masterQuestDungeonCount"] = randoContext->GetDungeons()->CountMQ(); + // payload["state"]["rando"]["masterQuestDungeons"] = json::array(); + // for (int i = 0; i < randoContext->GetDungeons()->GetDungeonListSize(); i++) { + // payload["state"]["rando"]["masterQuestDungeons"][i] = randoContext->GetDungeon(i)->IsMQ(); + // } + // for (int i = 0; i < randoContext->GetTrials()->GetTrialListSize(); i++) { + // payload["state"]["rando"]["requiredTrials"][i] = randoContext->GetTrial(i)->IsRequired(); + // } + /*} + + SendJsonToRemote(payload);*/ } void Anchor::SendPacket_ClearTeamState(std::string teamId) { @@ -104,167 +117,188 @@ void Anchor::SendPacket_ClearTeamState(std::string teamId) { SendJsonToRemote(payload); } -// Overwrites a local byte section with the authoritative team-state array (no additive merge). -static void ApplyTeamBytes(nlohmann::json& bytes, void (*getSizeAndPtr)(s32*, u8**)) { - s32 size; - u8* addr; - getSizeAndPtr(&size, &addr); - s32 count = std::min(size, (s32)bytes.size()); - for (s32 i = 0; i < count; i++) { - addr[i] = bytes[i].get(); - } -} - void Anchor::HandlePacket_UpdateTeamState(nlohmann::json& payload) { if (!roomState.syncItemsAndFlags) { return; } isHandlingUpdateTeamState = true; + // This can happen in between file select and the game starting, so we can't use this check, but we need to ensure + // we be careful to wrap PlayState usage in this check + // + // if (!IsSaveLoaded()) { + // return; + // } - if (payload.contains("state")) { - auto& state = payload["state"]; - // Direct byte copy bypasses the setters; no OnGameFlagSet / collectible events fire. - if (state.contains("fileProgressFlags")) { - ApplyTeamBytes(state["fileProgressFlags"], fileProgressFlag_getSizeAndPtr); - } - if (state.contains("volatileFlags")) { - ApplyTeamBytes(state["volatileFlags"], volatileFlag_getSizeAndPtr); - } - if (state.contains("jiggies")) { - ApplyTeamBytes(state["jiggies"], jiggyscore_getSizeAndPtr); - } - if (state.contains("honeycombs")) { - ApplyTeamBytes(state["honeycombs"], honeycombscore_getSizeAndPtr); - } - if (state.contains("mumboTokens")) { - ApplyTeamBytes(state["mumboTokens"], mumboscore_getSizeAndPtr); - } - if (state.contains("noteScores")) { - ApplyTeamBytes(state["noteScores"], itemscore_noteScores_getSizeAndPtr); - } - // Per-level retention sets; takes effect on next map load. - if (state.contains("noteRetention")) { - ApplyTeamBytes(state["noteRetention"], port_noteRetention_getSizeAndPtr); - } - if (state.contains("jinjoRetention")) { - ApplyTeamBytes(state["jinjoRetention"], port_jinjoRetention_getSizeAndPtr); - } - if (state.contains("abilities")) { - ApplyTeamBytes(state["abilities"], ability_getSizeAndPtr); - } - // In-memory session sets; takes effect on next map load. - if (state.contains("brokenObjects")) { - port_breakable_restoreBroken(state["brokenObjects"].get>()); - } - if (state.contains("carriedCollected")) { - port_carriedSync_restoreCollected(state["carriedCollected"].get>()); - } - if (state.contains("eggTolls")) { - port_eggToll_restore(state["eggTolls"].get>()); - } - if (state.contains("puzzleSteps")) { - port_puzzleStep_restore(state["puzzleSteps"].get>()); - } - if (state.contains("puzzlePos")) { - port_puzzlePos_restore(state["puzzlePos"].get>()); - } - if (state.contains("puzzleCounts")) { - port_puzzleCount_restore(state["puzzleCounts"].get>()); - } - if (state.contains("spawnedJiggies")) { - port_jiggySpawn_restore(state["spawnedJiggies"].get>()); - } - if (state.contains("huts")) { - port_hutSmash_restore(state["huts"].get>()); - } - - // Recompute cached HUD counts the overwrites above bypassed. - if (IsSaveLoaded()) { - if (state.contains("jiggies")) { - func_8034798C(); - } - if (state.contains("honeycombs")) { - func_80347958(); - } - if (state.contains("mumboTokens")) { - func_80347984(); - } - - // Saved item counts: mumbo tokens [0] and jiggy total [4] always sync; feathers - // [1-3] only when the room shares consumables. - if (state.contains("savedItems")) { - auto& incoming = state["savedItems"]; - s32 size; - u8* addr; - saveditem_getSizeAndPtr(&size, &addr); // rebuilds the array from live counts - u8 buf[5]; - for (s32 i = 0; i < 5; i++) { - buf[i] = (i < size) ? addr[i] : 0; - } - if (incoming.size() >= 5) { - buf[0] = incoming[0].get(); - buf[4] = incoming[4].get(); - if (roomState.shareConsumables) { - buf[1] = incoming[1].get(); - buf[2] = incoming[2].get(); - buf[3] = incoming[3].get(); - } - func_803479C0(buf); - } - } - - // Per-level best times (truncated u16 each). - if (state.contains("timeScores")) { - auto incoming = state["timeScores"].get>(); - u16 ts[0xB] = { 0 }; - size_t n = std::min(incoming.size(), sizeof(ts)); - for (size_t i = 0; i < n; i++) { - ((u8*)ts)[i] = incoming[i]; - } - itemscore_timeScores_fromSaveData(ts); - } - } - - // Randomizer catch-up: reconcile check records (obtain without re-granting, see - // AdoptRemoteCheck) and take RANDO_INF flags authoritatively. - if (IS_RANDO && IsSaveLoaded()) { - if (state.contains("randoChecks")) { - auto checks = state["randoChecks"].get>(); - s32 n = std::min((s32)checks.size(), (s32)RC_MAX); - for (s32 rc = RC_UNKNOWN + 1; rc < n; rc++) { - if (checks[rc]) { - AdoptRemoteCheck(rc); - } - } - } - if (state.contains("randoFlags")) { - auto flags = state["randoFlags"].get>(); - s32 n = std::min((s32)flags.size(), (s32)RANDO_INF_MAX); - for (s32 i = RANDO_INF_UNKNOWN + 1; i < n; i++) { - RANDO_SAVE_FLAGS[i].flagState = flags[i]; - } - } - } - - SweepUnoccupiedLevelState((GameMap)gsworld_getMap()); - - Notification::Emit({ - .message = "Save updated from team", - }); - - if (reloadMapOnTeamState && IsSaveLoaded()) { - reloadMapOnTeamState = false; - transitionToMap(gsworld_getMap(), gsworld_getExit(), 1); - } - } + // if (payload.contains("state")) { + // SaveContext loadedData = payload["state"].get(); - if (payload.contains("queue")) { - std::lock_guard lock(incomingPacketQueueMutex); - for (auto& item : payload["queue"]) { - incomingPacketQueue.push(nlohmann::json::parse(item.get())); - } - } + // gSaveContext.healthCapacity = loadedData.healthCapacity; + // gSaveContext.magicLevel = loadedData.magicLevel; + // gSaveContext.magicCapacity = gSaveContext.magic = loadedData.magicCapacity; + // gSaveContext.isMagicAcquired = loadedData.isMagicAcquired; + // gSaveContext.isDoubleMagicAcquired = loadedData.isDoubleMagicAcquired; + // gSaveContext.isDoubleDefenseAcquired = loadedData.isDoubleDefenseAcquired; + // gSaveContext.bgsFlag = loadedData.bgsFlag; + // gSaveContext.swordHealth = loadedData.swordHealth; + // gSaveContext.ship.quest = loadedData.ship.quest; + + // for (int i = 0; i < 124; i++) { + // if (i == SCENE_WATER_TEMPLE) { + // // Keep water temple water level flags + // u32 mask = (1 << 0x1C) | (1 << 0x1D) | (1 << 0x1E); + // loadedData.sceneFlags[i].swch = + // (loadedData.sceneFlags[i].swch & ~mask) | (gSaveContext.sceneFlags[i].swch & mask); + // } + + // if (i == SCENE_FOREST_TEMPLE) { + // // Keep forest temple elevator flag + // u32 mask = (1 << 0x1B); + // loadedData.sceneFlags[i].swch = + // (loadedData.sceneFlags[i].swch & ~mask) | (gSaveContext.sceneFlags[i].swch & mask); + // } + + // gSaveContext.sceneFlags[i] = loadedData.sceneFlags[i]; + // if (IsSaveLoaded() && gPlayState->sceneNum == i) { + // gPlayState->actorCtx.flags.chest = loadedData.sceneFlags[i].chest; + // gPlayState->actorCtx.flags.swch = loadedData.sceneFlags[i].swch; + // gPlayState->actorCtx.flags.clear = loadedData.sceneFlags[i].clear; + // gPlayState->actorCtx.flags.collect = loadedData.sceneFlags[i].collect; + // } + // } + + // for (int i = 0; i < 14; i++) { + // gSaveContext.eventChkInf[i] = loadedData.eventChkInf[i]; + // } + + // for (int i = 0; i < 4; i++) { + // gSaveContext.itemGetInf[i] = loadedData.itemGetInf[i]; + // } + + // // Skip last row of infTable, don't want to sync swordless flag + // for (int i = 0; i < 29; i++) { + // gSaveContext.infTable[i] = loadedData.infTable[i]; + // } + + // for (int i = 0; i < ceil((RAND_INF_MAX + 15) / 16); i++) { + // gSaveContext.ship.randomizerInf[i] = loadedData.ship.randomizerInf[i]; + // } + + // for (int i = 0; i < 6; i++) { + // gSaveContext.gsFlags[i] = loadedData.gsFlags[i]; + // } + + // gSaveContext.ship.stats.firstInput = loadedData.ship.stats.firstInput; + // gSaveContext.ship.stats.fileCreatedAt = loadedData.ship.stats.fileCreatedAt; + + // // Restore master sword state + // // Disabling this for now, not really sure I understand why I did this in the past + // // u8 hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, 1); + // // if (hasMasterSword) { + // // loadedData.inventory.equipment |= 0x2; + // // } else { + // // loadedData.inventory.equipment &= ~0x2; + // // } + + // // Restore bottle contents (unless it's ruto's letter) + // for (int i = 0; i < 4; i++) { + // if (gSaveContext.inventory.items[SLOT_BOTTLE_1 + i] != ITEM_NONE && + // gSaveContext.inventory.items[SLOT_BOTTLE_1 + i] != ITEM_LETTER_RUTO) { + // loadedData.inventory.items[SLOT_BOTTLE_1 + i] = gSaveContext.inventory.items[SLOT_BOTTLE_1 + i]; + // } + // } + + // // Restore ammo if it's non-zero, unless it's beans + // for (int i = 0; i < ARRAY_COUNT(gSaveContext.inventory.ammo); i++) { + // if (gSaveContext.inventory.ammo[i] != 0 && i != SLOT(ITEM_BEAN) && i != SLOT(ITEM_BEAN + 1)) { + // loadedData.inventory.ammo[i] = gSaveContext.inventory.ammo[i]; + // } + // } + + // gSaveContext.inventory = loadedData.inventory; + + // // The commented out code below is an attempt at sending the entire randomizer seed over, in hopes that a + // player + // // doesn't have to generate the seed themselves Currently it doesn't work :) + // if (IS_RANDO && payload["state"].contains("rando")) { + // auto randoContext = Rando::Context::GetRawInstance(); + + // for (int i = 0; i < RC_MAX; i++) { + // auto itemLocation = payload["state"]["rando"].at("itemLocations").at(i); + // // randoContext->GetItemLocation(i)->RefPlacedItem() = + // // itemLocation.at("rgID").get(); + // OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetCheckStatus( + // itemLocation.at(0).get()); + // OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped(itemLocation.at(1).get()); + + // // if (itemLocation.contains("fakeRgID")) { + // // randoContext->overrides.emplace(static_cast(i), + // // Rando::ItemOverride(static_cast(i), + // // itemLocation.at("fakeRgID").get())); + // // randoContext->GetItemOverride(i).GetTrickName().english = + // // itemLocation.at("trickName").at("english").get(); + // // randoContext->GetItemOverride(i).GetTrickName().french = + // // itemLocation.at("trickName").at("french").get(); + // // } + // // if (itemLocation.contains("price")) { + // // u16 price = itemLocation.at("price"].get(); + // // if (price > 0) { + // // randoContext->GetItemLocation(i)->SetCustomPrice(price); + // // } + // // } + // } + + // // auto entranceCtx = randoContext->GetEntranceShuffler(); + // // for (int i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { + // // entranceCtx->entranceOverrides[i].type = + // // payload["state"]["rando"]["entrances"][i]["type"].get(); + // entranceCtx->entranceOverrides[i].index + // // = payload["state"]["rando"]["entrances"][i]["index"].get(); + // // entranceCtx->entranceOverrides[i].destination = + // // payload["state"]["rando"]["entrances"][i]["destination"].get(); + // // entranceCtx->entranceOverrides[i].override = + // // payload["state"]["rando"]["entrances"][i]["override"].get(); + // // entranceCtx->entranceOverrides[i].overrideDestination = + // // payload["state"]["rando"]["entrances"][i]["overrideDestination"].get(); + // // } + + // // for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) { + // // randoContext->hashIconIndexes[i] = payload["state"]["rando"]["seed"][i].get(); + // // } + // // randoContext->GetSettings()->SetSeedString(payload["state"]["rando"]["inputSeed"].get()); + // // randoContext->GetSettings()->SetSeed(payload["state"]["rando"]["finalSeed"].get()); + + // // for (int i = 0; i < RSK_MAX; i++) { + // // + // randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(payload["state"]["rando"]["randoSettings"][i].get()); + // // } + + // // randoContext->GetDungeons()->ClearAllMQ(); + // // for (int i = 0; i < randoContext->GetDungeons()->GetDungeonListSize(); i++) { + // // if (payload["state"]["rando"]["masterQuestDungeons"][i].get()) { + // // randoContext->GetDungeon(i)->SetMQ(); + // // } + // // } + + // // randoContext->GetTrials()->SkipAll(); + // // for (int i = 0; i < randoContext->GetTrials()->GetTrialListSize(); i++) { + // // if (payload["state"]["rando"]["requiredTrials"][i].get()) { + // // randoContext->GetTrial(i)->SetAsRequired(); + // // } + // // } + // } + + // Notification::Emit({ + // .message = "Save updated from team", + // }); + //} - isHandlingUpdateTeamState = false; + // if (payload.contains("queue")) { + // std::lock_guard lock(incomingPacketQueueMutex); + // for (auto& item : payload["queue"]) { + // nlohmann::json itemPayload = nlohmann::json::parse(item.get()); + // incomingPacketQueue.push(itemPayload); + // } + // } + // isHandlingUpdateTeamState = false; } diff --git a/src/port/Network/Anchor/Packets/VileEatRequest.cpp b/src/port/Network/Anchor/Packets/VileEatRequest.cpp index 7576365e7..536b061f1 100644 --- a/src/port/Network/Anchor/Packets/VileEatRequest.cpp +++ b/src/port/Network/Anchor/Packets/VileEatRequest.cpp @@ -3,8 +3,10 @@ #include #include +extern "C" { #include "functions.h" #include "variables.h" +} /** * VILE_EAT_REQUEST @@ -12,6 +14,9 @@ * Sent by a non-authority client when its local player chomps a piece. The minigame * authority validates the request against the live piece list and, on success, consumes * the piece and broadcasts the result as a VILE_HOLE_STATE (eaten) packet. + * + * No sequence number: this is a request toward the authority, not part of the + * authority's ordered state stream. */ void Anchor::SendPacket_VileEatRequest(u8 holeId) { @@ -36,10 +41,14 @@ void Anchor::HandlePacket_VileEatRequest(nlohmann::json& payload) { return; } + // Only the authority acts on eat requests; VileSync_HandleEatRequest returns false + // (touching nothing) on non-authority clients. uint32_t eaterClientId = payload.at("clientId").get(); s32 pieceType = 0; s32 correctType = 0; if (VileSync_HandleEatRequest(holeId, eaterClientId, &pieceType, &correctType)) { + // Confirm the successful eat back to the requester so it replays its croc's eat + // feedback (the piece removal already rides the eaten VILE_HOLE_STATE broadcast). SendPacket_VileEatResult(eaterClientId, (u8)pieceType, (u8)correctType); } } diff --git a/src/port/Network/Anchor/Packets/VileEatResult.cpp b/src/port/Network/Anchor/Packets/VileEatResult.cpp index 21d8b8142..214943b6f 100644 --- a/src/port/Network/Anchor/Packets/VileEatResult.cpp +++ b/src/port/Network/Anchor/Packets/VileEatResult.cpp @@ -3,14 +3,22 @@ #include #include +extern "C" { #include "functions.h" #include "variables.h" +} /** * VILE_EAT_RESULT * - * Sent by the minigame authority to confirm a successful VILE_EAT_REQUEST. - * Catches up on animations and sounds as necessary + * Sent by the minigame authority to confirm a successful VILE_EAT_REQUEST. The + * requester suppressed its local consume (so its croc never played the chomp), so on + * receipt it replays the eat feedback: the chomp animation/SFX, plus the wrong-type + * reaction when the eaten piece didn't match the required type. Score and piece removal + * are authority-driven and arrive via the snapshot / eaten VILE_HOLE_STATE separately. + * + * Broadcast to the chamber with the eater's id; only the eater acts on it. No sequence + * number: this is one-shot cosmetic feedback, not part of the ordered state stream. */ void Anchor::SendPacket_VileEatResult(u32 eaterClientId, u8 pieceType, u8 correctType) { diff --git a/src/port/Network/Anchor/Packets/VileGameState.cpp b/src/port/Network/Anchor/Packets/VileGameState.cpp index c4f2da03e..fba3bc9cb 100644 --- a/src/port/Network/Anchor/Packets/VileGameState.cpp +++ b/src/port/Network/Anchor/Packets/VileGameState.cpp @@ -3,14 +3,21 @@ #include #include +extern "C" { #include "functions.h" #include "variables.h" +} /** * VILE_GAME_STATE * * Periodic full snapshot of the Mr. Vile minigame, broadcast by the authority to other - * clients in the chamber every second or two while the game is running. + * clients in the chamber every second or two while the game is running. Application is + * idempotent: it corrects any drift from lost packets and brings late joiners fully up + * to date (a late joiner is just a client whose drift is 100%). + * + * Events (VILE_HOLE_STATE / VILE_UPDATE) make the game feel synced; this packet makes + * it provably synced. */ void Anchor::SendPacket_VileGameState() { diff --git a/src/port/Network/Anchor/Packets/VileHoleState.cpp b/src/port/Network/Anchor/Packets/VileHoleState.cpp index f0078cd05..379e1094c 100644 --- a/src/port/Network/Anchor/Packets/VileHoleState.cpp +++ b/src/port/Network/Anchor/Packets/VileHoleState.cpp @@ -3,8 +3,10 @@ #include #include +extern "C" { #include "functions.h" #include "variables.h" +} /** * VILE_HOLE_STATE diff --git a/src/port/Network/Anchor/Packets/VileUpdate.cpp b/src/port/Network/Anchor/Packets/VileUpdate.cpp index 642375c9b..9d0c37d53 100644 --- a/src/port/Network/Anchor/Packets/VileUpdate.cpp +++ b/src/port/Network/Anchor/Packets/VileUpdate.cpp @@ -3,8 +3,10 @@ #include #include +extern "C" { #include "functions.h" #include "variables.h" +} /** * VILE_UPDATE @@ -13,7 +15,7 @@ * in the chamber at the player-update cadence. Remote clients skip Mr. Vile's AI and * apply this instead. * - * animMode is the chMrVile_setAction mode (101 idle / 102 walk / 103 munch / 104 burp). + * animMode is the BGS_func_8038BBA0 mode (101 idle / 102 walk / 103 munch / 104 burp). * * Note: sent every frame while the minigame runs, so keep this payload lean. */ diff --git a/src/port/Network/Anchor/Packets/WaterRise.cpp b/src/port/Network/Anchor/Packets/WaterRise.cpp deleted file mode 100644 index 63ff97663..000000000 --- a/src/port/Network/Anchor/Packets/WaterRise.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "port/Network/Anchor/Anchor.h" -#include -#include - -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/PortEnhancements.h" -#include "port/Enhancements/Events/Hooks/Events.h" - -#include - -#include "functions.h" -extern "C" { -#include "variables.h" -// func_8034C5AC: xform-3 water group. func_8034E78C: animate its dy. -} - -/** - * WATER_RISE - * - * A rising water level animates only on the client that triggered it (lair: switch cutscene in - * func_802D5628/func_802D5260; CC rings: func_8034E78C). Remotes otherwise only get the trailing - * fileprog flag / JIGGY_1C spawn at the end, snapping the water. This packet signals the rise start. - * - * kind 0 (lair): RBB-lobby water subaddie, driven every frame by func_802D5260. p1 = target level - * (1-3), stashed by a remote as a "pending level" until the real flag catches up. - * kind 1 (CC): rings water (xform-3 dy), no per-frame holder; remote replays func_8034E78C. - * p1 = mesh id, p2 = target dy, dur = seconds. - */ - -enum { WATERRISE_KIND_LAIR = 0, WATERRISE_KIND_CC = 1 }; - -// map -> pending target level for the lair water (remote only; cleared once the flag reaches it). -static std::map sLairPendingLevel; - -static int32_t lairLevelForFlag(int32_t levelFlag) { - switch (levelFlag) { - case FILEPROG_23_LAIR_WATER_LEVEL_1: - return 1; - case FILEPROG_25_LAIR_WATER_LEVEL_2: - return 2; - case FILEPROG_27_LAIR_WATER_LEVEL_3: - return 3; - default: - return 0; - } -} - -// Called from func_802D6264 (the lair switch/cutscene trigger). If the flag the cutscene will set is -// a water-level flag, broadcast the rise now. -extern "C" void port_lairWater_onRiseTrigger(int32_t waterMap, int32_t levelFlag) { - int32_t level = lairLevelForFlag(levelFlag); - if (level == 0) { - return; // not a water switch (doors, witch switches, etc. use this same trigger) - } - Anchor::GetInstance()->SendPacket_WaterRise(waterMap, WATERRISE_KIND_LAIR, level, 0, 0.0f); -} - -// func_802D5260 asks for the effective target level: max(flag-derived level, pending level from a -// teammate's in-flight rise). Clears the pending once the real flag catches up. -extern "C" int32_t port_lairWater_targetLevel(int32_t map, int32_t flagLevel) { - auto it = sLairPendingLevel.find(map); - if (it == sLairPendingLevel.end()) { - return flagLevel; - } - if (flagLevel >= it->second) { - sLairPendingLevel.erase(it); - return flagLevel; - } - return it->second; -} - -extern "C" void port_ccWater_broadcastRise(int32_t map, int32_t waterId, int32_t targetDy, f32 duration) { - Anchor::GetInstance()->SendPacket_WaterRise(map, WATERRISE_KIND_CC, waterId, targetDy, duration); -} - -void Anchor::SendPacket_WaterRise(s32 map, s32 kind, s32 p1, s32 p2, f32 duration) { - if (!IsSaveLoaded() || !roomState.syncItemsAndFlags) { - return; - } - nlohmann::json payload; - payload["type"] = WATER_RISE; - payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); - payload["map"] = map; - payload["kind"] = kind; - payload["p1"] = p1; - payload["p2"] = p2; - payload["dur"] = duration; - SendJsonToRemote(payload); -} - -void Anchor::HandlePacket_WaterRise(nlohmann::json& payload) { - if (!roomState.syncItemsAndFlags) { - return; - } - s32 map = payload.at("map").get(); - s32 kind = payload.at("kind").get(); - s32 p1 = payload.at("p1").get(); - s32 p2 = payload.value("p2", (s32)0); - f32 dur = payload.value("dur", 0.0f); - - if (kind == WATERRISE_KIND_LAIR) { - int32_t cur = sLairPendingLevel.count(map) ? sLairPendingLevel[map] : 0; - if (p1 > cur) { - sLairPendingLevel[map] = p1; - } - } else if (kind == WATERRISE_KIND_CC) { - // Only replay while in the water's map; on later entry func_80388104 snaps it on its own. - if ((s32)gsworld_getMap() == map) { - Struct70s* water = func_8034C5AC(p1); - if (water != nullptr) { - func_8034E78C((Struct73s*)water, p2, dur); - } - } - } -} - -void RegisterWaterRise_Init() { - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { sLairPendingLevel.clear(); }); -} - -static RegisterShipInitFunc initWaterRise(RegisterWaterRise_Init, {}); diff --git a/src/port/Network/Anchor/VileSync.c b/src/port/Network/Anchor/VileSync.c index 096f768b9..25f8d4264 100644 --- a/src/port/Network/Anchor/VileSync.c +++ b/src/port/Network/Anchor/VileSync.c @@ -9,8 +9,8 @@ // Implemented in src/BGS (see [port] Anchor sync entry points there). extern void chyumblie_netApplyState(Actor* actor, s32 state, s32 piece_type); extern s32 chyumblie_netGetState(Actor* actor, s32* piece_type); -extern void chMrVile_netApplyUpdate(Actor* actor, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode); -extern s32 chMrVile_netGetAnimMode(Actor* actor); +extern void chvile_netApplyUpdate(Actor* actor, const f32 position[3], f32 pitch, f32 yaw, f32 roll, u8 anim_mode); +extern s32 chvile_netGetAnimMode(Actor* actor); extern bool chvilegame_netGather(Actor* actor, VileGameSnapshot* dst); extern void chvilegame_netApply(Actor* actor, const VileGameSnapshot* src); extern bool chvilegame_netConsumeRemote(Actor* actor, f32 position[3], s32* out_piece_type, s32* out_correct_type); @@ -98,7 +98,7 @@ bool VileSync_HandleEatRequest(int32_t holeId, uint32_t eaterClientId, int32_t* return false; } pos[0] = holePos[0]; - pos[1] = 0.0f; // piece positions are stored with y = 0 (see chMrVileMinigame_newPiece) + pos[1] = 0.0f; // piece positions are stored with y = 0 (see chvilegame_new_piece) pos[2] = holePos[1]; // A successful consume broadcasts the eaten hole state itself (the state change // fires OnVileHoleStateChange on this authority client); the piece type / correctness @@ -117,7 +117,7 @@ void VileSync_ApplyVileUpdate(const float position[3], float pitch, float yaw, f Actor* vile = VileSync_FindActor(ACTOR_13A_MR_VILE); if (vile != NULL) { - chMrVile_netApplyUpdate(vile, position, pitch, yaw, roll, animMode); + chvile_netApplyUpdate(vile, position, pitch, yaw, roll, animMode); } } diff --git a/src/port/Network/Anchor/VileSync.h b/src/port/Network/Anchor/VileSync.h index c6e6a83b0..68c21e9fb 100644 --- a/src/port/Network/Anchor/VileSync.h +++ b/src/port/Network/Anchor/VileSync.h @@ -69,7 +69,7 @@ bool VileSync_HandleEatRequest(int32_t holeId, uint32_t eaterClientId, int32_t* // plus the wrong-type reaction) once the authority confirms the eat succeeded. void VileSync_PlayLocalEatFeedback(int32_t pieceType, int32_t correctType); -// Apply a streamed Mr. Vile transform + anim mode (chMrVile_setAction modes 101-104). +// Apply a streamed Mr. Vile transform + anim mode (BGS_func_8038BBA0 modes 101-104). void VileSync_ApplyVileUpdate(const float position[3], float pitch, float yaw, float roll, uint8_t animMode); // Fill dst from the live minigame controller. Returns false if there is nothing to diff --git a/src/port/OS/OS.h b/src/port/OS/OS.h deleted file mode 100644 index 0321ca20c..000000000 --- a/src/port/OS/OS.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef PORT_OS_H -#define PORT_OS_H - -// N64 OS SDK -// -// libultraship already implements most of the libultra surface, and where its -// version is correct for a PC port we use it as-is. This layer exists only for -// the calls libultraship cannot serve, so that the decomp's own threading code -// can run instead of being replaced by port stand-ins. - -#ifdef __cplusplus -extern "C" { -#endif - -#include "libultraship/libultra/message.h" -#include "libultraship/libultra/thread.h" -#include "libultraship/libultra/pfs.h" -#include "libultraship/libultra/sptask.h" -#include "libultraship/libultra/time.h" - -void OS_CreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p); -void OS_StartThread(OSThread* thread); -void OS_StopThread(OSThread* thread); -void OS_DestroyThread(OSThread* thread); -void OS_SetThreadPri(OSThread* thread, OSPri p); - -// Allowlist one decomp thread entry point. Until its entry is passed here, an -// osCreateThread/osStartThread pair is recorded but never launched, so threads -// are revived deliberately, one consumer at a time. -void OS_EnableThreadEntry(void* entry); - -// OS_MESG_BLOCK only blocks on queues opted in here. -void OS_SetQueueBlocking(OSMesgQueue* mq, int enabled); - -// Cooperative exit for threads. -void OS_RequestThreadExit(void); -int OS_ThreadShouldExit(void); -void OS_JoinDecompThreads(void); - -// Stop every queue blocking and wake all waiters, so the tick can unwind and be -// joined. Call once the window has closed and before joining it. -void OS_BeginShutdown(void); - -// Watchdog diagnostics: threads currently parked inside a blocking -// osSendMesg/osRecvMesg, so a stall dump can say where each one waits. -typedef struct OS_BlockedWait { - unsigned long tid; // SDL thread id - OSMesgQueue* mq; - int isSend; // 0 = recv, 1 = send/jam -} OS_BlockedWait; -int OS_MesgSnapshotBlockedWaits(OS_BlockedWait* out, int max); - -// Raise a registered hardware event (VI retrace, SI done, RDP done). -void OS_SendEventMesg(OSEvent event); - -// Raise an event ahead of whatever the recipient already has queued, the way -// an interrupt preempts. Used for completions that must not be reordered -// behind pending messages. -void OS_JamEventMesg(OSEvent event); - -// The VI ticker starts with osCreateViManager; this stops it at shutdown. -void OS_StopViTicker(void); - -// Complete one pending controller read: poll the pads and raise OS_EVENT_SI. -// Called by the thread that owns SDL input. -int OS_SiService(void); - -// Whether that thread has begun servicing SI at all. -int OS_SiPumpLive(void); - -// Cancel a pending timer. Both halves of the pair are ours (OS_Timer.cpp), but -// only osSetTimer has a prototype in LUS to be found through, so a decomp caller -// needs this one declared here. -int osStopTimer(OSTimer* t); - -// The timer worker starts with the first osSetTimer; this stops it at shutdown. -void OS_StopTimerWorker(void); - -s32 osPfsInit(OSMesgQueue* mq, OSPfs* pfs, s32 channel); - -// Whether osViBlack has the display blanked. The renderer blacks the presented -// frame while the world keeps rendering underneath. -int OS_ViBlackActive(void); - -// Take the task osSpTaskStartGo handed over, or NULL if none is pending. -OSTask* OS_SpTakePendingTask(void); - -// Same, but without consuming it; the watchdog reports what is in flight. -OSTask* OS_SpPeekPendingTask(void); - -#ifdef __cplusplus -} -#endif - -#endif // PORT_OS_H diff --git a/src/port/OS/OS_AI.cpp b/src/port/OS/OS_AI.cpp deleted file mode 100644 index ac072f54e..000000000 --- a/src/port/OS/OS_AI.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// This file should eventually go to LUS as the AI api. -// -// The audio interface, backed by the libultraship audio player. The decomp's -// audio manager runs its original path and this is the DAC at the end of it. - -#include "OS.h" - -#include - -#include "port/UI/cvar_prefixes.h" - -extern "C" { -#include "libultraship/libultra/types.h" -#include "libultraship/libultra/os.h" -int32_t AudioPlayerBuffered(void); -int32_t AudioPlayerGetDesiredBuffered(void); -void AudioPlayerPlayFrame(const uint8_t* buf, size_t len); -} - -#include -#include - -extern "C" u32 osAiGetLength(void) { - int32_t excess = AudioPlayerBuffered() - AudioPlayerGetDesiredBuffered(); - return excess > 0 ? (u32)excess * 4 : 0; -} - -// How many extra synth frames the audio pump should queue this cycle to -// rebuild the playback cushion. -extern "C" int32_t port_audioCatchupFrames(void) { - constexpr int32_t kFrameSamples = 736; - constexpr int32_t kMaxCatchup = 3; - int32_t deficit = AudioPlayerGetDesiredBuffered() - AudioPlayerBuffered(); - if (deficit < kFrameSamples) { - return 0; - } - int32_t frames = deficit / kFrameSamples; - return frames > kMaxCatchup ? kMaxCatchup : frames; -} - -extern "C" s32 osAiSetNextBuffer(void* buff, size_t len) { - static bool sPrimed = false; - if (!sPrimed) { - sPrimed = true; - std::vector silence((size_t)AudioPlayerGetDesiredBuffered() * 4, 0); - AudioPlayerPlayFrame(silence.data(), silence.size()); - } - - float masterVol = CVarGetInteger(CVAR_SETTING("Volume.Master"), 40) / 100.0f; - if (masterVol >= 1.0f) { - AudioPlayerPlayFrame((const uint8_t*)buff, len); - return 0; - } - std::vector scaled(len / 2); - const int16_t* src = (const int16_t*)buff; - for (size_t i = 0; i < scaled.size(); i++) { - scaled[i] = (int16_t)(src[i] * masterVol); - } - AudioPlayerPlayFrame((const uint8_t*)scaled.data(), len); - return 0; -} diff --git a/src/port/OS/OS_Cont.cpp b/src/port/OS/OS_Cont.cpp deleted file mode 100644 index b7369c77d..000000000 --- a/src/port/OS/OS_Cont.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// This file should eventually go to LUS as the SI api. The controller init and -// motor pieces are unchanged from libultra/os.cpp and only live here because -// taking osSetTimer port-side meant taking that whole object with it. - -#include "OS.h" - -#include - -#include -#include -#include - -extern "C" { - -uint8_t __osMaxControllers = MAXCONTROLLERS; - -int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) { - *controllerBits = 0; - status->status |= 1; - - // The SDL game-controller subsystem and mappings are brought up earlier, in - // Context::InitControlDeck, so controllers work in pre-game UI. ControlDeck::Init - // stays here as it needs the game's controllerBits. - Ship::Context::GetRawInstance()->GetControlDeck()->Init(controllerBits); - - return 0; -} - -// The SI, as a request and a completion rather than an inline poll. -// -// LUS's StartReadData does nothing and GetReadData polls the control deck on -// whichever thread asked, which cannot work once the tick is off the window -// thread: SDL input belongs to the thread pumping its events. A read is -// posted here, completed by that thread in OS_SiService, and answered with -// OS_EVENT_SI, which is what pfsManager_init already registered for and what -// its thread has been waiting on all along. -namespace { -std::atomic sReadPending{ false }; -std::mutex sLatchMutex; -OSContPad sLatch[MAXCONTROLLERS]; -std::atomic sLatchValid{ false }; -std::atomic sPumpLive{ false }; -} // namespace - -int32_t osContStartReadData(OSMesgQueue* mesg) { - (void)mesg; // completion goes to whoever registered for OS_EVENT_SI - sReadPending.store(true, std::memory_order_release); - return 0; -} - -extern "C" int OS_SiPumpLive(void) { - return sPumpLive.load(std::memory_order_acquire) ? 1 : 0; -} - -extern "C" int OS_SiService(void) { - sPumpLive.store(true, std::memory_order_release); - if (!sReadPending.exchange(false, std::memory_order_acq_rel)) { - return 0; - } - { - std::lock_guard lock(sLatchMutex); - memset(sLatch, 0, sizeof(sLatch)); - Ship::Context::GetRawInstance()->GetControlDeck()->WriteToPad(sLatch); - } - sLatchValid.store(true, std::memory_order_release); - OS_SendEventMesg(OS_EVENT_SI); - return 1; -} - -void osContGetReadData(OSContPad* pad) { - if (sLatchValid.load(std::memory_order_acquire)) { - std::lock_guard lock(sLatchMutex); - memcpy(pad, sLatch, sizeof(sLatch)); - return; - } - memset(pad, 0, sizeof(OSContPad) * __osMaxControllers); -} - -int32_t __osMotorAccess(OSPfs* pfs, uint32_t vibrate) { - auto io = Ship::Context::GetRawInstance()->GetControlDeck()->GetControllerByPort(pfs->channel)->GetRumble(); - if (vibrate) { - io->StartRumble(); - } else { - io->StopRumble(); - } - - return 0; -} - -int32_t osMotorInit(OSMesgQueue* ctrlrqueue, OSPfs* pfs, int32_t channel) { - pfs->channel = channel; - return 0; -} - -// Controller Pak gets probed first, the return kickstarts rumble -int32_t osPfsInit(OSMesgQueue* mq, OSPfs* pfs, int32_t channel) { - (void)mq; - (void)pfs; - (void)channel; - return PFS_ERR_DEVICE; -} - -} // extern "C" diff --git a/src/port/OS/OS_Mesg.cpp b/src/port/OS/OS_Mesg.cpp deleted file mode 100644 index d0e2885a5..000000000 --- a/src/port/OS/OS_Mesg.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// This file should eventually replace libultraship's os_mesg.cpp - -#include -#include -#include -#include - -#include - -#include "OS.h" - -extern "C" { -#include "libultraship/libultra/message.h" -#include "libultraship/libultra/internal.h" - -// Event -> (queue, message) routing table. -// Override from lus os_vi.cpp. -__OSEventState __osEventStateTab[OS_NUM_EVENTS] = { 0 }; -} - -// Message queues that can actually block. -// -// LUS's queues never do: osRecvMesg on an empty queue just returns -1. Every -// decomp thread is a loop parked on a queue, so they'd spin instead of sleeping -// and nobody would ever get woken. -// -// The queue fields themselves stay as they were, since decomp code reads them -// directly (pfsmanager watches validCount); only the waiting is ours, a -// condvar pair per queue where libultra used priority-ordered thread lists. -// Blocking is opt-in per queue. - -namespace { - -struct QueueSync { - std::condition_variable notEmpty; - std::condition_variable notFull; - bool blockingEnabled = false; -}; - -std::mutex sMesgMutex; -std::map sQueueSync; - -QueueSync& SyncFor(OSMesgQueue* mq) { - return sQueueSync[mq]; -} - -// Blocked-wait registry for the watchdog. Slots are atomics so a stall dump -// can read them without taking sMesgMutex (which a deadlocked thread may -// implicate); marking and clearing happen under sMesgMutex on the wait path. -constexpr int kMaxBlockedWaits = 16; -struct BlockedWaitSlot { - std::atomic tid{ 0 }; - std::atomic mq{ nullptr }; - std::atomic isSend{ 0 }; -}; -BlockedWaitSlot sBlockedWaits[kMaxBlockedWaits]; - -int MarkBlockedWait(OSMesgQueue* mq, int isSend) { - unsigned long tid = (unsigned long)SDL_ThreadID(); - for (int i = 0; i < kMaxBlockedWaits; i++) { - unsigned long expected = 0; - if (sBlockedWaits[i].tid.compare_exchange_strong(expected, tid, std::memory_order_acq_rel)) { - sBlockedWaits[i].mq.store(mq, std::memory_order_release); - sBlockedWaits[i].isSend.store(isSend, std::memory_order_release); - return i; - } - } - return -1; -} - -void ClearBlockedWait(int slot) { - if (slot >= 0) { - sBlockedWaits[slot].mq.store(nullptr, std::memory_order_release); - sBlockedWaits[slot].tid.store(0, std::memory_order_release); - } -} - -} // namespace - -extern "C" { - -void osCreateMesgQueue(OSMesgQueue* mq, OSMesg* msgBuf, int32_t count) { - std::lock_guard lock(sMesgMutex); - mq->mtqueue = nullptr; - mq->fullqueue = nullptr; - mq->validCount = 0; - mq->first = 0; - mq->msgCount = count; - mq->msg = msgBuf; - sQueueSync[mq]; -} - -int32_t osSendMesg(OSMesgQueue* mq, OSMesg msg, int32_t flag) { - std::unique_lock lock(sMesgMutex); - QueueSync& sync = SyncFor(mq); - int waitSlot = -1; - while (mq->validCount >= mq->msgCount) { - if (flag != OS_MESG_BLOCK || !sync.blockingEnabled) { - ClearBlockedWait(waitSlot); - return -1; - } - if (waitSlot < 0) { - waitSlot = MarkBlockedWait(mq, 1); - } - sync.notFull.wait(lock); - } - ClearBlockedWait(waitSlot); - s32 last = (mq->first + mq->validCount) % mq->msgCount; - mq->msg[last] = msg; - mq->validCount++; - sync.notEmpty.notify_one(); - return 0; -} - -// LUS bails when the queue is empty, which has it backwards. -// A jam should fail when there's no room, same as a send. -int32_t osJamMesg(OSMesgQueue* mq, OSMesg msg, int32_t flag) { - std::unique_lock lock(sMesgMutex); - QueueSync& sync = SyncFor(mq); - int waitSlot = -1; - while (mq->validCount >= mq->msgCount) { - if (flag != OS_MESG_BLOCK || !sync.blockingEnabled) { - ClearBlockedWait(waitSlot); - return -1; - } - if (waitSlot < 0) { - waitSlot = MarkBlockedWait(mq, 1); - } - sync.notFull.wait(lock); - } - ClearBlockedWait(waitSlot); - mq->first = (mq->first + mq->msgCount - 1) % mq->msgCount; - mq->msg[mq->first] = msg; - mq->validCount++; - sync.notEmpty.notify_one(); - return 0; -} - -int32_t osRecvMesg(OSMesgQueue* mq, OSMesg* msg, int32_t flag) { - std::unique_lock lock(sMesgMutex); - QueueSync& sync = SyncFor(mq); - int waitSlot = -1; - while (mq->validCount == 0) { - if (flag != OS_MESG_BLOCK || !sync.blockingEnabled) { - ClearBlockedWait(waitSlot); - return -1; - } - if (waitSlot < 0) { - waitSlot = MarkBlockedWait(mq, 0); - } - sync.notEmpty.wait(lock); - } - ClearBlockedWait(waitSlot); - if (msg != nullptr) { - *msg = mq->msg[mq->first]; - } - mq->first = (mq->first + 1) % mq->msgCount; - mq->validCount--; - sync.notFull.notify_one(); - return 0; -} - -void osSetEventMesg(OSEvent event, OSMesgQueue* mq, OSMesg msg) { - std::lock_guard lock(sMesgMutex); - if (event < OS_NUM_EVENTS) { - __osEventStateTab[event].queue = mq; - __osEventStateTab[event].msg = msg; - } -} - -void OS_SetQueueBlocking(OSMesgQueue* mq, int enabled) { - std::lock_guard lock(sMesgMutex); - SyncFor(mq).blockingEnabled = (enabled != 0); -} - -// Called once the window closes, before the tick is joined. -void OS_BeginShutdown(void) { - std::lock_guard lock(sMesgMutex); - for (auto& [mq, sync] : sQueueSync) { - (void)mq; - sync.blockingEnabled = false; - sync.notEmpty.notify_all(); - sync.notFull.notify_all(); - } -} - -// Lock-free on purpose: the caller is a watchdog inspecting a possible -// deadlock, so it must not touch sMesgMutex. Entries can be mid-update; -// they are diagnostics, not decisions. -int OS_MesgSnapshotBlockedWaits(OS_BlockedWait* out, int max) { - int n = 0; - for (int i = 0; i < kMaxBlockedWaits && n < max; i++) { - unsigned long tid = sBlockedWaits[i].tid.load(std::memory_order_acquire); - OSMesgQueue* mq = sBlockedWaits[i].mq.load(std::memory_order_acquire); - if (tid == 0 || mq == nullptr) { - continue; - } - out[n].tid = tid; - out[n].mq = mq; - out[n].isSend = sBlockedWaits[i].isSend.load(std::memory_order_acquire); - n++; - } - return n; -} - -// Raise a hardware event. Nothing interrupts on PC, so whoever stands in for a -// piece of hardware calls this when the real one would have fired. -void OS_SendEventMesg(OSEvent event) { - OSMesgQueue* mq = nullptr; - OSMesg msg = {}; - { - std::lock_guard lock(sMesgMutex); - if (event >= OS_NUM_EVENTS || __osEventStateTab[event].queue == nullptr) { - return; - } - mq = __osEventStateTab[event].queue; - msg = __osEventStateTab[event].msg; - } - osSendMesg(mq, msg, OS_MESG_NOBLOCK); -} - -// Same, but the message goes to the front of the queue. An interrupt landed -// ahead of whatever the recipient had queued; a hardware stand-in whose event -// must be seen before pending messages jams instead of sending. -void OS_JamEventMesg(OSEvent event) { - OSMesgQueue* mq = nullptr; - OSMesg msg = {}; - { - std::lock_guard lock(sMesgMutex); - if (event >= OS_NUM_EVENTS || __osEventStateTab[event].queue == nullptr) { - return; - } - mq = __osEventStateTab[event].queue; - msg = __osEventStateTab[event].msg; - } - osJamMesg(mq, msg, OS_MESG_NOBLOCK); -} - -} // extern "C" diff --git a/src/port/OS/OS_RCP.cpp b/src/port/OS/OS_RCP.cpp deleted file mode 100644 index 8a1c06e12..000000000 --- a/src/port/OS/OS_RCP.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// This file should eventually go to LUS as the RCP api - -#include "OS.h" - -#include - -extern "C" { -#include -#include "libultraship/libultra/types.h" -#include "libultraship/libultra/sptask.h" -} - -// The RDP command unit's status register. -// -// Nothing on PC obeys FREEZE, since there is no RDP to stall, but thread5 runs -// its pipeline off that bit: it freezes after handing a frame over and clears -// it on the next retrace, which is what keeps one frame in flight. Holding the -// bit as real state lets that code run as written instead of being replaced. - -namespace { -std::atomic sStatus{ 0 }; -} - -extern "C" u32 osDpGetStatus(void) { - return sStatus.load(std::memory_order_acquire); -} - -// Writes are set/clear command pairs, mirrored into the bits reads return. -extern "C" void osDpSetStatus(u32 data) { - uint32_t set = 0; - uint32_t clr = 0; - if (data & DPC_SET_FREEZE) { - set |= DPC_STATUS_FREEZE; - } - if (data & DPC_CLR_FREEZE) { - clr |= DPC_STATUS_FREEZE; - } - if (data & DPC_SET_FLUSH) { - set |= DPC_STATUS_FLUSH; - } - if (data & DPC_CLR_FLUSH) { - clr |= DPC_STATUS_FLUSH; - } - if (set != 0) { - sStatus.fetch_or(set, std::memory_order_acq_rel); - } - if (clr != 0) { - sStatus.fetch_and(~clr, std::memory_order_acq_rel); - } -} - -// Task submission. -// -// There is no RSP, so this only hands the task over; whoever drains it decides -// what running one means. For the graphics task that has to be the window -// thread, since it ends up in the renderer. -// -// One slot is enough: the decomp starts a task and waits for its SP event -// before starting the next, so a second can never be pending. -namespace { -std::atomic sPendingTask{ nullptr }; -std::atomic sYieldPending{ false }; // yield requested, not yet observed -std::atomic sResumePending{ false }; // next gfx StartGo is the resume -} // namespace - -extern "C" void osSpTaskYield(void) { - sYieldPending.store(true, std::memory_order_release); - OS_JamEventMesg(OS_EVENT_SP); -} - -extern "C" OSYieldResult osSpTaskYielded(OSTask* task) { - (void)task; - if (sYieldPending.exchange(false, std::memory_order_acq_rel)) { - sResumePending.store(true, std::memory_order_release); - return 1; - } - return 0; -} - -extern "C" void osSpTaskLoad(OSTask* task) { - (void)task; // no DMEM to load; StartGo carries the pointer -} - -extern "C" void osSpTaskStartGo(OSTask* task) { - if (task->t.type == M_AUDTASK) { - OS_JamEventMesg(OS_EVENT_SP); - return; - } - - if (sResumePending.exchange(false, std::memory_order_acq_rel)) { - return; - } - sPendingTask.store(task, std::memory_order_release); -} - -extern "C" OSTask* OS_SpTakePendingTask(void) { - return sPendingTask.exchange(nullptr, std::memory_order_acq_rel); -} - -extern "C" OSTask* OS_SpPeekPendingTask(void) { - return sPendingTask.load(std::memory_order_acquire); -} diff --git a/src/port/OS/OS_Threads.cpp b/src/port/OS/OS_Threads.cpp deleted file mode 100644 index 250514944..000000000 --- a/src/port/OS/OS_Threads.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// This file should eventually go to LUS as the threading api - -#include "OS.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - -struct OsThreadState { - void (*entry)(void*) = nullptr; - void* arg = nullptr; - OSPri pri = 0; - OSId id = 0; - std::thread worker; - bool started = false; -}; - -std::mutex sTableMutex; -std::map sThreads; -std::set sEnabledEntries; - -bool ThreadEnabled(void* entry) { - return sEnabledEntries.count(entry) != 0; -} - -std::atomic sExitRequested{ false }; - -// Counted rather than joined blind: a thread stuck somewhere other than its queue -// wait would never see the request, and join() cannot time out. Waiting on the -// count lets us give up on a straggler instead of hanging the process on it. -std::mutex sExitMutex; -std::condition_variable sExitCv; -int sLiveThreads = 0; - -} // namespace - -extern "C" void OS_RequestThreadExit(void) { - sExitRequested.store(true, std::memory_order_release); -} - -extern "C" int OS_ThreadShouldExit(void) { - return sExitRequested.load(std::memory_order_acquire) ? 1 : 0; -} - -extern "C" void OS_JoinDecompThreads(void) { - bool allReturned; - { - std::unique_lock lock(sExitMutex); - allReturned = sExitCv.wait_for(lock, std::chrono::seconds(2), [] { return sLiveThreads == 0; }); - } - - std::lock_guard lock(sTableMutex); - for (auto& [thread, st] : sThreads) { - (void)thread; - if (!st.worker.joinable()) { - continue; - } - if (allReturned) { - st.worker.join(); - } else { - // Nothing safe left to do: it is still inside game code, so it cannot be - // joined without hanging and cannot be killed without leaving locks held. - // Detaching restores the pre-existing behaviour for that one thread. - st.worker.detach(); - } - } - if (!allReturned) { - SPDLOG_WARN("{} decomp thread(s) did not reach their exit check; detaching", sLiveThreads); - } -} - -extern "C" void OS_EnableThreadEntry(void* entry) { - std::lock_guard lock(sTableMutex); - sEnabledEntries.insert(entry); -} - -extern "C" void OS_CreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p) { - (void)sp; // N64 stack pointers are meaningless here - std::lock_guard lock(sTableMutex); - OsThreadState& st = sThreads[thread]; - st.entry = (void (*)(void*))entry; - st.arg = arg; - st.pri = p; - st.id = id; - st.started = false; -} - -extern "C" void OS_StartThread(OSThread* thread) { - std::lock_guard lock(sTableMutex); - auto it = sThreads.find(thread); - if (it == sThreads.end() || it->second.started || it->second.entry == nullptr) { - return; - } - if (!ThreadEnabled((void*)it->second.entry)) { - return; - } - it->second.started = true; - void (*entry)(void*) = it->second.entry; - void* arg = it->second.arg; - { - std::lock_guard exitLock(sExitMutex); - sLiveThreads++; - } - // Kept joinable: shutdown waits for these to leave their loops before the - // engine they draw and play audio through is destroyed. - it->second.worker = std::thread([entry, arg]() { - entry(arg); - { - std::lock_guard exitLock(sExitMutex); - sLiveThreads--; - } - sExitCv.notify_all(); - }); -} - -extern "C" void OS_StopThread(OSThread* thread) { - // N64 semantics are preemptive suspension, which std::thread cannot do. - // Revived consumers must exit cooperatively; Stop just joins if running. - OS_DestroyThread(thread); -} - -extern "C" void OS_DestroyThread(OSThread* thread) { - std::thread worker; - { - std::lock_guard lock(sTableMutex); - auto it = sThreads.find(thread); - if (it == sThreads.end()) { - return; - } - worker = std::move(it->second.worker); - sThreads.erase(it); - } - if (worker.joinable()) { - worker.join(); - } -} - -// Priority is recorded but not applied: the N64 scheduler was cooperative and -// priority-ordered, while these are preemptive OS threads. What the game needs -// from priority is queue ordering and blocking behavior, which the queues -// provide; mapping it onto OS thread priorities would only add scheduler noise. -extern "C" void OS_SetThreadPri(OSThread* thread, OSPri p) { - std::lock_guard lock(sTableMutex); - auto it = sThreads.find(thread); - if (it != sThreads.end()) { - it->second.pri = p; - } -} diff --git a/src/port/OS/OS_Time.cpp b/src/port/OS/OS_Time.cpp deleted file mode 100644 index b068836d7..000000000 --- a/src/port/OS/OS_Time.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// This file should eventually go back to LUS; it is unchanged from its -// libultra/os.cpp original, and only lives here because taking osSetTimer -// port-side means taking that whole object with it. - -#include -#include - -extern "C" { -#include "libultraship/libultra/types.h" -#include "libultraship/libultra/os.h" -} - -// A chrono duration matching the N64's 46.875MHz clock rate. -typedef std::ratio<3000, 64> n64ClockRatio; -typedef std::ratio_divide n64CycleRate; -typedef std::chrono::duration n64CycleRateDuration; - -extern "C" { - -uint64_t __osCurrentTime = 0; - -void osSetTime(OSTime time) { - __osCurrentTime = - std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count() + - time; -} - -uint64_t osGetTime() { - return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) - .count() - - __osCurrentTime; -} - -uint32_t osGetCount() { - return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) - .count(); -} - -} // extern "C" diff --git a/src/port/OS/OS_Timer.cpp b/src/port/OS/OS_Timer.cpp deleted file mode 100644 index 4a1c74361..000000000 --- a/src/port/OS/OS_Timer.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// This file should eventually go to LUS as the timer api - -#include "OS.h" - -#include -#include -#include -#include -#include - -extern "C" { -#include "libultraship/libultra/time.h" -} - -// Deadline timers. LUS's osSetTimer returns 0 without arming anything and it -// has no osStopTimer at all, so a decomp timer never fired. Thread5 uses one -// to pace controller reads. -// -// Countdowns are in 46.875MHz ticks; 1e9/46875000 is exactly 64/3, so -// nanoseconds are ticks * 64 / 3 with no rounding. -namespace { - -struct Armed { - std::chrono::steady_clock::time_point deadline; - std::chrono::nanoseconds interval; - OSMesgQueue* mq = nullptr; - OSMesg msg = {}; -}; - -std::mutex sMutex; -std::map sTimers; -std::condition_variable sCv; -std::thread sWorker; -bool sWorkerStarted = false; -bool sStop = false; - -// One worker serves every timer, waking for whichever is due first and -// recomputing whenever the set changes under it. -void Worker() { - std::unique_lock lock(sMutex); - for (;;) { - if (sStop) { - return; - } - OSTimer* key = nullptr; - std::chrono::steady_clock::time_point deadline{}; - for (auto& [t, armed] : sTimers) { - if (key == nullptr || armed.deadline < deadline) { - key = t; - deadline = armed.deadline; - } - } - if (key == nullptr) { - sCv.wait(lock); - continue; - } - if (sCv.wait_until(lock, deadline) != std::cv_status::timeout) { - continue; // re-armed or stopped while waiting - } - if (sStop) { - return; - } - auto it = sTimers.find(key); - if (it == sTimers.end() || it->second.deadline != deadline) { - continue; // this one changed under the wait - } - OSMesgQueue* mq = it->second.mq; - OSMesg msg = it->second.msg; - if (it->second.interval.count() > 0) { - it->second.deadline += it->second.interval; - } else { - sTimers.erase(it); - } - lock.unlock(); - osSendMesg(mq, msg, OS_MESG_NOBLOCK); - lock.lock(); - } -} - -} // namespace - -extern "C" int osSetTimer(OSTimer* t, OSTime countdown, OSTime interval, OSMesgQueue* mq, OSMesg msg) { - std::lock_guard lock(sMutex); - if (sStop) { - return 0; - } - if (!sWorkerStarted) { - sWorkerStarted = true; - sWorker = std::thread(Worker); - } - Armed armed; - armed.deadline = std::chrono::steady_clock::now() + std::chrono::nanoseconds(countdown * 64 / 3); - armed.interval = std::chrono::nanoseconds(interval * 64 / 3); - armed.mq = mq; - armed.msg = msg; - sTimers[t] = armed; - sCv.notify_all(); - return 0; -} - -extern "C" int osStopTimer(OSTimer* t) { - std::lock_guard lock(sMutex); - sTimers.erase(t); - sCv.notify_all(); - return 0; -} - -extern "C" void OS_StopTimerWorker(void) { - { - std::lock_guard lock(sMutex); - if (!sWorkerStarted || sStop) { - return; - } - sStop = true; - sTimers.clear(); - } - sCv.notify_all(); - if (sWorker.joinable()) { - sWorker.join(); - } -} diff --git a/src/port/OS/OS_VI.cpp b/src/port/OS/OS_VI.cpp deleted file mode 100644 index 744eb1cf3..000000000 --- a/src/port/OS/OS_VI.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// This file should eventually replace libultraship's os_vi.cpp - -#include "OS.h" - -#include -#include -#include - -#include "port/DevTools/ThreadWatchdog.h" - -extern "C" { -#include "libultraship/libultra/types.h" -#include "libultraship/libultra/vi.h" -} - -// The VI: retrace source and framebuffer registers. -// -// LUS drives retraces off an SDL timer at 16ms, which is 62.5Hz rather than 60, -// and only if SDL_INIT_TIMER were up. It never is, so retraces never fire at -// all. Game speed is meant to come off this cadence, so it needs to be a real -// 60Hz on an absolute schedule instead of an interval that drifts. -// -// The framebuffer registers are no-ops in LUS: swap does nothing and the -// getters return null. The decomp waits for a swap to latch and compares the -// current buffer against what it last saw, so they have to hold real values. - -namespace { - -std::thread sTicker; -std::atomic sTickerRun{ false }; - -std::atomic sNextFramebuffer{ nullptr }; -std::atomic sCurrentFramebuffer{ nullptr }; -std::atomic sBlack{ false }; - -} // namespace - -extern "C" void osCreateViManager(OSPri pri) { - (void)pri; - if (sTickerRun.exchange(true)) { - return; - } - sTicker = std::thread([] { - constexpr std::chrono::nanoseconds kVi(16666667); // NTSC 60Hz - auto next = std::chrono::steady_clock::now() + kVi; - while (sTickerRun.load(std::memory_order_relaxed)) { - std::this_thread::sleep_until(next); - next += kVi; - // If the process was suspended (debugger, sleep), resync rather - // than firing a burst of catch-up retraces. - auto now = std::chrono::steady_clock::now(); - if (now - next > std::chrono::milliseconds(100)) { - next = now + kVi; - } - // A retrace latches whatever swap armed, then raises VI. - sCurrentFramebuffer.store(sNextFramebuffer.load(std::memory_order_acquire), std::memory_order_release); - ThreadWatchdog_Beat(WATCHDOG_VI_TICKER); - OS_SendEventMesg(OS_EVENT_VI); - } - }); -} - -extern "C" void OS_StopViTicker(void) { - if (!sTickerRun.exchange(false)) { - return; - } - if (sTicker.joinable()) { - sTicker.join(); - } -} - -extern "C" void osViSetEvent(OSMesgQueue* queue, OSMesg mesg, u32 retraceCount) { - (void)retraceCount; - osSetEventMesg(OS_EVENT_VI, queue, mesg); -} - -extern "C" void osViSwapBuffer(void* framebuffer) { - sNextFramebuffer.store(framebuffer, std::memory_order_release); -} - -extern "C" void* osViGetNextFramebuffer(void) { - return sNextFramebuffer.load(std::memory_order_acquire); -} - -extern "C" void* osViGetCurrentFramebuffer(void) { - return sCurrentFramebuffer.load(std::memory_order_acquire); -} - -extern "C" void osViSetMode(OSViMode* mode) { - (void)mode; -} - -extern "C" void osViSetSpecialFeatures(u32 features) { - (void)features; -} - -extern "C" void osViBlack(u8 active) { - sBlack.store(active != 0, std::memory_order_release); -} - -extern "C" int OS_ViBlackActive(void) { - return sBlack.load(std::memory_order_acquire) ? 1 : 0; -} - -extern "C" void osViSetXScale(f32 scale) { - (void)scale; -} - -extern "C" void osViSetYScale(f32 scale) { - (void)scale; -} diff --git a/src/port/Patches/AnimVertexPatches.cpp b/src/port/Patches/AnimVertexPatches.cpp deleted file mode 100644 index 87595b545..000000000 --- a/src/port/Patches/AnimVertexPatches.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -extern "C" { -#include -#include "functions.h" -#include "libultraship/libultra/gbi.h" -#include "port/Patches/Patches.h" -} - -#include "port/Interpolation/FrameInterpolation.h" - -namespace { - -// A single anim-vertex model runs 500-750 vertices. This covers roughly 20-25 -// of them on screen at once; past that a draw falls back to the shared buffer, -// which is exactly the behaviour that existed before this file. -constexpr size_t kVerticesPerSlot = 16384; -constexpr int kSlots = 2; - -Vtx* gArena[kSlots] = {}; -size_t gUsed = 0; -int gSlot = 0; -bool gWarnedExhausted = false; - -} // namespace - -extern "C" void port_animVtx_beginTick(void) { - gSlot = (gSlot + 1) % kSlots; - gUsed = 0; - if (gArena[gSlot] == nullptr) { - gArena[gSlot] = new (std::nothrow) Vtx[kVerticesPerSlot]; - } -} - -extern "C" void port_modelRender_snapshotAnimVertices(Gfx** gfx, void* vertices, int32_t count) { - if (gfx == nullptr || vertices == nullptr || count <= 0) { - return; - } - Vtx* arena = gArena[gSlot]; - if (arena == nullptr || gUsed + (size_t)count > kVerticesPerSlot) { - return; - } - - Vtx* copy = arena + gUsed; - gUsed += (size_t)count; - std::memcpy(copy, vertices, (size_t)count * sizeof(Vtx)); - - // Hand the pose to interpolation. It owns the blend from here: this buffer - // is private to this draw, so replay can rewrite it per sub-frame. - FrameInterpolation_RecordAnimVertices(copy, vertices, count); - gSPSegment((*gfx)++, 0x01, osVirtualToPhysical(copy)); -} diff --git a/src/port/Patches/CameraPatches.cpp b/src/port/Patches/CameraPatches.cpp index 6770a57f3..733372f18 100644 --- a/src/port/Patches/CameraPatches.cpp +++ b/src/port/Patches/CameraPatches.cpp @@ -13,9 +13,13 @@ #include "port/ShipInit.hpp" #include "port/ShipUtils.h" +extern "C" { #include "enums.h" #include "functions.h" #include "variables.h" +enum level_e map_getLevel(enum map_e map); +enum map_e gsworld_getMap(void); +} #include @@ -92,7 +96,6 @@ static void updateCutsceneAspect(int32_t mapId) { // Widescreen yaw fix — per-frame yaw adjustment for certain static cameras in widescreen mode #define CVAR_WS_CAMERA_FIX CVAR_ENHANCEMENT("Fix.WidescreenCamera") -#define CVAR_NO_SCREEN_SHAKE CVAR_SETTING("A11yDisableScreenShake") struct WsYawFix { int32_t map; @@ -173,11 +176,5 @@ void RegisterCameraPatches_Init() { }); } -void RegisterScreenShake_Init() { - COND_VB_SHOULD(VB_CAMERA_APPLY_SHAKE, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_SCREEN_SHAKE, 0), - { *should = false; }); -} - static RegisterShipInitFunc cutsceneAspectInitFunc(RegisterCutsceneAspect, { CVAR_CUTSCENE_ASPECT }); static RegisterShipInitFunc staticCamInitFunc(RegisterCameraPatches_Init); -static RegisterShipInitFunc screenShakeInitFunc(RegisterScreenShake_Init, { CVAR_NO_SCREEN_SHAKE }); diff --git a/src/port/Patches/FramePacingPatches.cpp b/src/port/Patches/FramePacingPatches.cpp index 4c7081372..5ff05d6ee 100644 --- a/src/port/Patches/FramePacingPatches.cpp +++ b/src/port/Patches/FramePacingPatches.cpp @@ -20,27 +20,33 @@ enum map_e gsworld_getMap(void); // Demo Display Pacing static int sDemoViCount = 0; -static constexpr int kMaxDemoViCount = 0xF; int port_getDemoViCount(void) { return sDemoViCount; } void port_setDemoViCount(int viCount) { - sDemoViCount = (viCount > kMaxDemoViCount) ? kMaxDemoViCount : viCount; + sDemoViCount = viCount; } int port_getDemoDisplayViCount(int rawViCount) { - if (getGameMode() == GAME_MODE_A_SNS_PICTURE) { + int displayViCount = rawViCount; + int game_mode = getGameMode(); + + if (game_mode == GAME_MODE_8_BOTTLES_BONUS) { + displayViCount = 3; + } else if (game_mode == GAME_MODE_A_SNS_PICTURE) { switch (gsworld_getMap()) { case MAP_7F_FP_WOZZAS_CAVE: case MAP_92_GV_SNS_CHAMBER: - return 3; + displayViCount = 3; + break; default: break; } } - return rawViCount; + + return displayViCount; } // Cutscene Stutter Compensation @@ -56,7 +62,6 @@ static int sLairDingpotDurations[] = { 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, static int sCutsceneCounter = 0; static int sCutsceneNextStutter = 0; static int sCutsceneLagIndex = 0; -static int sCutsceneExtraVis = 0; static bool shouldLagCutscene(int* startFrames, int* durations, int count) { if (sCutsceneNextStutter == -1) { @@ -88,40 +93,47 @@ static void resetCutsceneTimings(void) { sCutsceneCounter = 0; sCutsceneNextStutter = 0; sCutsceneLagIndex = 0; - sCutsceneExtraVis = 0; } -// Advances the stutter tables by one cutscene frame. Called from func_802E4384, -// the single point where a tick commits its time delta, so every consumer of -// port_getCutsceneExtraVis() sees the same answer for that tick. -void port_tickCutsceneStutter(void) { - sCutsceneExtraVis = 0; - +int port_getCutsceneExtraVis(void) { if (!CVarGetInteger(CVAR_CUTSCENE_SYNC, 1)) - return; + return 0; + + int extra = 0; switch (gsworld_getMap()) { case MAP_1E_CS_START_NINTENDO: if (shouldLagCutscene(sConcertStartFrames, sConcertDurations, (int)(sizeof(sConcertStartFrames) / sizeof(sConcertStartFrames[0])))) { - sCutsceneExtraVis = 1; + extra = 1; } sCutsceneCounter++; break; case MAP_7B_CS_INTRO_GL_DINGPOT_1: if (shouldLagCutscene(sLairDingpotStartFrames, sLairDingpotDurations, (int)(sizeof(sLairDingpotStartFrames) / sizeof(sLairDingpotStartFrames[0])))) { - sCutsceneExtraVis = 1; + extra = 1; } sCutsceneCounter++; break; default: break; } + + return extra; } -int port_getCutsceneExtraVis(void) { - return sCutsceneExtraVis; +int port_getInterpolationFpsCap(void) { + if (!CVarGetInteger(CVAR_CUTSCENE_SYNC, 1)) + return 0; + + switch (gsworld_getMap()) { + // [port] Cap concert to 30 fps + case MAP_1E_CS_START_NINTENDO: + return 30; + default: + return 0; + } } } // extern "C" diff --git a/src/port/Patches/FramebufferPatches.cpp b/src/port/Patches/FramebufferPatches.cpp index 15549e843..06d71ab31 100644 --- a/src/port/Patches/FramebufferPatches.cpp +++ b/src/port/Patches/FramebufferPatches.cpp @@ -5,22 +5,17 @@ #include -#include "port/Engine.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" - -// From Patches.h; declared here because this file's definitions use concrete -// Gfx/model types where the header declares void*. -extern "C" void port_runOnRenderThread(void (*fn)(void*), void* arg); - extern "C" { #include "core1/core1.h" #include "model.h" +int gfx_create_framebuffer(unsigned int width, unsigned int height, unsigned int native_width, + unsigned int native_height, unsigned char resize, unsigned char force_fixed_aspect); void gfx_register_fb_texture(const void* cpuAddr, int fbId); BKGfxList* modelbin_getGfxList(BKModelBin* arg0); -s32 getGameMode(void); +unsigned int OTRGetGameRenderWidth(void); +unsigned int OTRGetGameRenderHeight(void); // During FADE_IN, the game disables scene drawing one frame before // capturing gFramebuffers. Without freezing, the readback would overwrite @@ -70,17 +65,10 @@ static void currentRenderSize(int* w, int* h) { } } -// Framebuffer creation talks to the renderer, so under thread5 mode it has to -// happen on the render thread rather than the game tick. -static void createPauseFb(void* arg) { - (void)arg; - s_pauseFbId = gfx_create_framebuffer(s_pauseFbW, s_pauseFbH, s_pauseFbW, s_pauseFbH, 0, 0); -} - int port_getPauseFramebufferId(void) { if (s_pauseFbId < 0) { currentRenderSize(&s_pauseFbW, &s_pauseFbH); - port_runOnRenderThread(createPauseFb, NULL); + s_pauseFbId = gfx_create_framebuffer(s_pauseFbW, s_pauseFbH, s_pauseFbW, s_pauseFbH, 0, 0); } return s_pauseFbId; } @@ -96,7 +84,7 @@ int port_capturePauseFramebuffer(void) { if (s_pauseFbId < 0 || w != s_pauseFbW || h != s_pauseFbH) { s_pauseFbW = w; s_pauseFbH = h; - port_runOnRenderThread(createPauseFb, NULL); + s_pauseFbId = gfx_create_framebuffer(w, h, w, h, 0, 0); } return s_pauseFbId; } @@ -191,63 +179,28 @@ static void patchModelDL(BKModelBin* model_bin, uintptr_t seg_start, uintptr_t s #define IMAGE_WIDTH (TILE_SIZE * 5) #define IMAGE_HEIGHT (TILE_SIZE * 4) -// Aux picture FB (Bottles Bonus / SNS pictures) - -// Scale the framebuffer from 160x128 based on the application width - -static u16 sAuxFbDummy[1]; - -#define AUX_FB_SCALE_MAX 2 -#define AUX_FB_SCALE_STEP_WIDTH 640 - -static s32 sAuxGpuFbId = -1; -static int s_auxFbRenderW = 0; -static int s_auxFbRenderH = 0; +// Aux picture FB readback (Bottles Bonus / SNS pictures) -static int auxFbScale(void) { - int scale = s_auxFbRenderW / AUX_FB_SCALE_STEP_WIDTH; +extern s16* D_80382450; // aux picture CPU buffer (picturebuffer.c) +extern s32 sAuxGpuFbId; // aux picture GPU FB id (picturebuffer.c) - if (scale > AUX_FB_SCALE_MAX) { - scale = AUX_FB_SCALE_MAX; - } - if (scale < 1) { - scale = 1; - } - return scale; -} - -static void createAuxFb(void* arg) { - (void)arg; - int scale = auxFbScale(); - int nativeW = s_auxFbRenderW / scale; - int nativeH = s_auxFbRenderH / scale; - - if (nativeW < 1) { - nativeW = 1; - } - if (nativeH < 1) { - nativeH = 1; - } - sAuxGpuFbId = gfx_create_framebuffer(IMAGE_WIDTH, IMAGE_HEIGHT, nativeW, nativeH, 1, true); - if (sAuxGpuFbId >= 0) { - gfx_register_fb_texture(sAuxFbDummy, sAuxGpuFbId); - } +s32 port_getAuxGpuFbId(void) { + return sAuxGpuFbId; } -static s32 auxGpuFbId(void) { - int w; - int h; - currentRenderSize(&w, &h); - if (sAuxGpuFbId < 0 || w != s_auxFbRenderW || h != s_auxFbRenderH) { - s_auxFbRenderW = w; - s_auxFbRenderH = h; - port_runOnRenderThread(createAuxFb, NULL); +void port_readAuxFbToCpu(Gfx** gfx) { + if (sAuxGpuFbId >= 0 && D_80382450 != NULL) { + gDPReadFB((*gfx)++, sAuxGpuFbId, (u16*)D_80382450, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1); + __gSPInvalidateTexCache((*gfx)++, 0); } - return sAuxGpuFbId; } // Picture model patching (Bottles Bonus / SNS pictures) +#define TILE_SIZE 32 +#define IMAGE_WIDTH (TILE_SIZE * 5) +#define IMAGE_HEIGHT (TILE_SIZE * 4) +#define SEG4_TAGGED ((uintptr_t)0x04000000 | 1) #define FROM_XZ 0 #define FROM_YZ 1 @@ -277,8 +230,8 @@ void port_patchPictureModel(BKModelBin* model_bin, s32 min_xy, s32 max_xy, s32 m sPicMaxXY = max_xy; sPicMinZ = min_z; sPicMaxZ = max_z; - patchModelDL(model_bin, 0x04000000, 0x04100000, sAuxFbDummy, IMAGE_WIDTH, IMAGE_HEIGHT, setPictureVertexTexcoord, - G_TF_BILERP, 1); + patchModelDL(model_bin, 0x04000000, 0x04100000, (const void*)SEG4_TAGGED, IMAGE_WIDTH, IMAGE_HEIGHT, + setPictureVertexTexcoord, G_TF_BILERP, 1); } // Transition model patching (falling jiggy pieces) @@ -288,16 +241,11 @@ void port_patchPictureModel(BKModelBin* model_bin, s32 min_xy, s32 max_xy, s32 m static u16 sTransitionFbDummy[1]; static s32 sTransitionGpuFbId = -1; -static void createTransitionFb(void* arg) { - (void)arg; - sTransitionGpuFbId = gfx_create_framebuffer(DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, - DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, 1, 0); - gfx_register_fb_texture(sTransitionFbDummy, sTransitionGpuFbId); -} - s32 port_getTransitionGpuFbId(void) { if (sTransitionGpuFbId < 0) { - port_runOnRenderThread(createTransitionFb, NULL); + sTransitionGpuFbId = gfx_create_framebuffer(DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, + DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT, 1, 0); + gfx_register_fb_texture(sTransitionFbDummy, sTransitionGpuFbId); } return sTransitionGpuFbId; } @@ -333,36 +281,3 @@ void port_patchTransitionModel(BKModelBin* model_bin) { } } // extern "C" - -// Submitted picture-mode frames since the last map load. The first few frames a -// reloaded map composes are structurally normal DLs that draw nothing visible. -static s32 sPicFramesSinceMapLoad = 0; -static constexpr s32 kPicWarmupFrames = 3; - -void RegisterFramebufferPatches_Init() { - REGISTER_VB_SHOULD(VB_PICTUREBOX_TARGET_FB, EVENT_PRIORITY_NORMAL, { - Gfx** gdl = va_arg(args, Gfx**); - s32 auxFb = auxGpuFbId(); - if (gdl != nullptr && auxFb >= 0) { - gsSPSetFB((*gdl)++, auxFb); - } - (void)should; - }); - - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { sPicFramesSinceMapLoad = 0; }); - - REGISTER_VB_SHOULD(VB_PICTUREBOX_SUBMIT_FRAME, EVENT_PRIORITY_NORMAL, { - s32 gfxCount = va_arg(args, s32); - s32 mode = getGameMode(); - if (mode == GAME_MODE_8_BOTTLES_BONUS || mode == GAME_MODE_A_SNS_PICTURE) { - sPicFramesSinceMapLoad++; - if (sPicFramesSinceMapLoad <= kPicWarmupFrames || gfxCount < 100) { - SPDLOG_INFO("[pictureDiag] dropped frame (sinceLoad={}, gfxCount={})", sPicFramesSinceMapLoad, - gfxCount); - *should = false; - } - } - }); -} - -static RegisterShipInitFunc initFramebufferPatches(RegisterFramebufferPatches_Init); diff --git a/src/port/Patches/GeoCull.cpp b/src/port/Patches/GeoCull.cpp index 099e91a8c..52d9e2f06 100644 --- a/src/port/Patches/GeoCull.cpp +++ b/src/port/Patches/GeoCull.cpp @@ -2,10 +2,6 @@ #include "port/Enhancements/Events/Hooks/Events.h" -extern "C" { -#include "model.h" -} - static int sConsumerMask = 0; extern "C" void GeoCull_SetConsumer(int consumerBit, int active) { @@ -25,13 +21,7 @@ extern "C" int port_geoCullDraw(int type, const void* cmd, const void* modelBin, return drawnVanilla; } - // Key commands by their offset within the geo command list. - const auto* bin = static_cast(modelBin); - const unsigned char* geoBase = (const unsigned char*)modelBin; - if (bin != nullptr) { - geoBase += bin->geo_list_offset; - } - int offset = (int)((const unsigned char*)cmd - geoBase); + int offset = (int)((const unsigned char*)cmd - (const unsigned char*)modelBin); bool forceDraw = false; CALL_EVENT(OnGeoCull, type, offset, modelBin, areaIds, areaCount, detail0, detail1, drawnVanilla, &forceDraw); return (drawnVanilla || forceDraw) ? 1 : 0; diff --git a/src/port/Patches/GeoCull.h b/src/port/Patches/GeoCull.h index f43303833..93daa8cfb 100644 --- a/src/port/Patches/GeoCull.h +++ b/src/port/Patches/GeoCull.h @@ -22,6 +22,10 @@ extern "C" { #define GEOCULL_CONSUMER_DEBUG 1 #define GEOCULL_CONSUMER_ENHANCEMENT 2 +// Called from each conditional cull command in render.c. `cmd`/`modelBin` give the command's +// stable byte offset; `drawnVanilla` is the unmodified recurse decision. areaIds/areaCount +// apply to CAMERA only (NULL/0 otherwise); detail0/detail1 are kind-specific extras (CAMERA: +// flags; LOD: min,max). Returns the final draw decision (1 = draw). int port_geoCullDraw(int type, const void* cmd, const void* modelBin, int drawnVanilla, const unsigned char* areaIds, int areaCount, int detail0, int detail1); diff --git a/src/port/Patches/GraphicsPatches.cpp b/src/port/Patches/GraphicsPatches.cpp index d8082b1f4..bf3d81e9f 100644 --- a/src/port/Patches/GraphicsPatches.cpp +++ b/src/port/Patches/GraphicsPatches.cpp @@ -1,10 +1,5 @@ -#include -#include -#include - #include #include "port/UI/cvar_prefixes.h" -#include "port/Engine.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" #include "port/ShipUtils.h" @@ -12,60 +7,47 @@ #define CVAR_DRAW_DISTANCE CVAR_ENHANCEMENT("Graphics.DrawDistance") #define CVAR_DISABLE_LOD CVAR_ENHANCEMENT("Graphics.DisableLOD") -#define CVAR_FP_LOBBY_DOOR_TILE CVAR_ENHANCEMENT("Fixes.FPLobbyDoorTile") static const int kMaxDrawDistanceMul = 6; static int sDrawDistanceCubeWidth(int mul) { return 4 * mul; } -static int sDrawDistanceLevel = 1; +static int sDrawDistanceLevel = 0; static int sDisableLOD = 0; extern "C" { -#include #include "enums.h" #include "functions.h" -#include "libultraship/libultra/gbi.h" -#include "port/Romhack/RomhackConfig.h" extern s32 gFramebufferWidth; extern s32 gFramebufferHeight; - -// Romhack model display lists can leave a palette (TLUT) mode enabled and leak it -// into the next model's draw. -void port_modelRenderResetTLUT(Gfx** gfx) { - if (!port_isRomhack()) { - return; - } - gDPSetTextureLUT((*gfx)++, G_TT_NONE); -} +float GameEngine_GetAspectRatio(void); // Widescreen HUD edge anchoring (centered-ortho HUD geometry). - -static const float kHudCenterBand = 32.0f; - float port_hudOrthoShift(float refX) { float halfW = (f32)gFramebufferWidth * 0.5f; float extraHalf = (f32)gFramebufferHeight * 0.5f * GameEngine_GetAspectRatio() - halfW; if (extraHalf < 0.0f) { extraHalf = 0.0f; // narrower than 4:3 (e.g. pillarboxed): never pull inward } - if (refX < halfW - kHudCenterBand) { + if (refX < halfW) { return -extraHalf; // left-anchored } - if (refX > halfW + kHudCenterBand) { + if (refX > halfW) { return extraHalf; // right-anchored } return 0.0f; // centered } -int port_getDrawDistanceSetting(void) { - return sDrawDistanceLevel; -} - int port_getDrawDistanceLevel(void) { - int mul = port_getDrawDistanceSetting(); + int mul = CVarGetInteger(CVAR_ENHANCEMENT("Graphics.DrawDistance"), 1); + if (mul < 1) { + mul = 1; + } + if (mul > kMaxDrawDistanceMul) { + mul = kMaxDrawDistanceMul; + } if (IsDemoMode() && getGameMode() != GAME_MODE_4_PAUSED) { mul = 1; } @@ -114,9 +96,7 @@ static void OnGeoCull_LevelOcclusion(IEvent* event) { if (ev->type != OCCLUSION_CMD_CAMERA) { return; } - // Offset into the opaque map model's geo command list (the "outside areas {1,2}" CAMERA - // command). Read it off the Occlusion Debugger, which reports the same geo-relative key. - if (gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN && ev->offset == 0x2C98 && + if (gsworld_getMap() == MAP_2_MM_MUMBOS_MOUNTAIN && ev->offset == 0x2CD0 && ev->modelBin == (const void*)mapModel_getModelBin(0)) { *ev->forceDraw = true; } @@ -149,155 +129,8 @@ static void RegisterDrawDistanceGraphics_Init() { static RegisterShipInitFunc drawDistanceGraphicsInit(RegisterDrawDistanceGraphics_Init, { CVAR_DRAW_DISTANCE }); static void RefreshDrawDistanceCVars() { - int mul = CVarGetInteger(CVAR_DRAW_DISTANCE, 1); - if (mul < 1) { - mul = 1; - } - if (mul > kMaxDrawDistanceMul) { - mul = kMaxDrawDistanceMul; - } - sDrawDistanceLevel = mul; + sDrawDistanceLevel = CVarGetInteger(CVAR_DRAW_DISTANCE, 1); sDisableLOD = CVarGetInteger(CVAR_DISABLE_LOD, 0); } static RegisterShipInitFunc drawDistanceCVarCache(RefreshDrawDistanceCVars, { CVAR_DRAW_DISTANCE, CVAR_DISABLE_LOD }); - -// ============================================================================ -// STALE TILE DESCRIPTOR — Freezeezy Peak lobby door trim -// ============================================================================ - -// F3DEX opcodes as used by BK64. -static const uint8_t kOpVtx = 0x04; -static const uint8_t kOpTri2 = 0xB1; -static const uint8_t kOpTri1 = 0xBF; -static const uint8_t kOpSetTileSize = 0xF2; -static const uint8_t kOpSetTile = 0xF5; -static const uint8_t kOpSetTImg = 0xFD; - -static const uint32_t kTxClampBit = 0x2; // G_TX_CLAMP -static const uint8_t kRenderTile = 0; // G_TX_RENDERTILE - -// Torch tags a G_SETTIMG that references an extracted texture by putting 0xFF in -// the top byte of w1 and the texture index in the low 24 bits. -static const uint32_t kTexMarker = 0xFF; - -static const char kFPLobbySuffix[] = "GL_FP_LOBBY_OPA"; - -static bool sPathEndsWith(const char* path, const char* suffix) { - if (path == NULL) { - return false; - } - size_t plen = strlen(path); - size_t slen = strlen(suffix); - return plen >= slen && strcmp(path + plen - slen, suffix) == 0; -} - -static void OnModelDisplayListLoad_StaleTile(IEvent* event) { - auto* ev = reinterpret_cast(event); - if (ev->dlWords == NULL || ev->texSizes == NULL || !sPathEndsWith(ev->path, kFPLobbySuffix)) { - return; - } - - // Walk the list tracking live render-tile state, flagging any G_SETTILE whose - // clamp causes a larger texture to be drawn through a smaller tile. - std::vector toPatch; - int curTex = -1; - uint32_t liveTile = UINT32_MAX; - uint32_t tileW = 0, tileH = 0; - - for (uint32_t i = 0; i + 1 < ev->dlWordCount; i += 2) { - uint32_t w0 = ev->dlWords[i]; - uint32_t w1 = ev->dlWords[i + 1]; - uint8_t op = (uint8_t)(w0 >> 24); - - if (op == kOpSetTImg) { - if (((w1 >> 24) & 0xFF) == kTexMarker) { - curTex = (int)(w1 & 0x00FFFFFF); - } - } else if (op == kOpSetTile) { - if (((w1 >> 24) & 0x7) == kRenderTile) { - liveTile = i; - } - } else if (op == kOpSetTileSize) { - if (((w1 >> 24) & 0x7) == kRenderTile) { - uint32_t uls = (w0 >> 12) & 0xFFF; - uint32_t ult = w0 & 0xFFF; - uint32_t lrs = (w1 >> 12) & 0xFFF; - uint32_t lrt = w1 & 0xFFF; - tileW = ((lrs - uls) / 4) + 1; - tileH = ((lrt - ult) / 4) + 1; - } - } else if (op == kOpVtx || op == kOpTri1 || op == kOpTri2) { - if (curTex < 0 || liveTile == UINT32_MAX || tileW == 0 || tileH == 0) { - continue; - } - if ((uint32_t)curTex >= ev->texCount) { - continue; - } - uint32_t declW = ev->texSizes[curTex].width; - uint32_t declH = ev->texSizes[curTex].height; - if (declW <= tileW && declH <= tileH) { - continue; - } - uint32_t tileWord = ev->dlWords[liveTile + 1]; - uint32_t cms = (tileWord >> 8) & 0x3; - uint32_t cmt = (tileWord >> 18) & 0x3; - if (((cms & kTxClampBit) == 0) && ((cmt & kTxClampBit) == 0)) { - continue; - } - // Only safe to swap clamp for wrap when the mask makes the wrap period - // exactly the texture size. - uint32_t masks = (tileWord >> 4) & 0xF; - uint32_t maskt = (tileWord >> 14) & 0xF; - if (masks == 0 || maskt == 0 || (1u << masks) != declW || (1u << maskt) != declH) { - continue; - } - if (std::find(toPatch.begin(), toPatch.end(), liveTile) == toPatch.end()) { - toPatch.push_back(liveTile); - } - } - } - - for (size_t n = 0; n < toPatch.size(); n++) { - ev->dlWords[toPatch[n] + 1] &= ~((kTxClampBit << 18) | (kTxClampBit << 8)); - } -} - -static void RegisterStaleTileFix_Init() { - COND_HOOK(OnModelDisplayListLoad, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FP_LOBBY_DOOR_TILE, 0), - OnModelDisplayListLoad_StaleTile); -} - -static RegisterShipInitFunc staleTileFixInit(RegisterStaleTileFix_Init, { CVAR_FP_LOBBY_DOOR_TILE }); - -// ============================ -// INHERITED RENDER STATE -// ============================ - -static void ApplySnowRenderState(Gfx** gfx) { - gSPClearGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | - G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH); - gSPSetGeometryMode((*gfx)++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH); - gDPSetAlphaCompare((*gfx)++, G_AC_NONE); - gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF); - gDPSetEnvColor((*gfx)++, 0xFF, 0xFF, 0xFF, 0xFF); - gDPSetBlendColor((*gfx)++, 0x00, 0x00, 0x00, 0x80); -} - -static void RegisterSnowRenderState_Init() { - COND_VB_SHOULD(VB_SNOW_RENDER_STATE, EVENT_PRIORITY_NORMAL, true, { - ApplySnowRenderState(va_arg(args, Gfx**)); - *should = false; - }); -} - -static RegisterShipInitFunc sSnowRenderStateInit(RegisterSnowRenderState_Init); - -static void RegisterModelDrawDistFadeAlpha_Init() { - COND_VB_SHOULD(VB_MODEL_DRAWDIST_FADE_ALPHA, EVENT_PRIORITY_NORMAL, true, { - s32* alpha = va_arg(args, s32*); - *alpha = std::clamp(*alpha, 0, 0xFF); - }); -} - -static RegisterShipInitFunc sModelDrawDistFadeAlphaInit(RegisterModelDrawDistFadeAlpha_Init); diff --git a/src/port/Patches/MirrorPatches.cpp b/src/port/Patches/MirrorPatches.cpp index eb8264a25..9455105df 100644 --- a/src/port/Patches/MirrorPatches.cpp +++ b/src/port/Patches/MirrorPatches.cpp @@ -5,10 +5,10 @@ #include #include -#include "functions.h" extern "C" { #include "model.h" #include "prop.h" +#include "functions.h" } static bool sMirrorSceneActive = false; @@ -25,12 +25,12 @@ static ActorDrawFunc sOrig_actor_draw = nullptr; extern "C" { // ActorInfo externs for text-bearing models (must be inside extern "C" for correct linkage) -extern ActorInfo D_80393354; // level entry signs (model 0x563) -extern ActorInfo chMumboSign5; // 5 mumbo token sign (0x301) -extern ActorInfo chMumboSign10; // 10 mumbo token sign (0x302) -extern ActorInfo chMumboSign15; // 15 mumbo token sign (0x303) -extern ActorInfo chMumboSign20; // 20 mumbo token sign (0x304) -extern ActorInfo chMumboSign25; // 25 mumbo token sign (0x305) +extern ActorInfo D_80393354; // level entry signs (model 0x563) +extern ActorInfo D_80367530; // 5 mumbo token sign (0x301) +extern ActorInfo D_80367554; // 10 mumbo token sign (0x302) +extern ActorInfo D_80367578; // 15 mumbo token sign (0x303) +extern ActorInfo D_8036759C; // 20 mumbo token sign (0x304) +extern ActorInfo D_803675C0; // 25 mumbo token sign (0x305) // Custom draw functions used by text-bearing actors (not in functions.h) extern Actor* lair_func_80387560(ActorMarker*, Gfx**, Mtx**, Vtx**); @@ -142,11 +142,11 @@ void port_mirror_patchTextActors(void) { // Mumbo token signs (5 variants: 5, 10, 15, 20, 25 tokens) sOrig_actor_draw = (ActorDrawFunc)actor_draw; - chMumboSign5.draw_func = mirror_excluded_actor_draw; - chMumboSign10.draw_func = mirror_excluded_actor_draw; - chMumboSign15.draw_func = mirror_excluded_actor_draw; - chMumboSign20.draw_func = mirror_excluded_actor_draw; - chMumboSign25.draw_func = mirror_excluded_actor_draw; + D_80367530.draw_func = mirror_excluded_actor_draw; + D_80367554.draw_func = mirror_excluded_actor_draw; + D_80367578.draw_func = mirror_excluded_actor_draw; + D_8036759C.draw_func = mirror_excluded_actor_draw; + D_803675C0.draw_func = mirror_excluded_actor_draw; } } // extern "C" diff --git a/src/port/Patches/Patches.h b/src/port/Patches/Patches.h index bb77404c1..cf1c8a564 100644 --- a/src/port/Patches/Patches.h +++ b/src/port/Patches/Patches.h @@ -7,22 +7,13 @@ extern "C" { #endif -// Threaded rendering (Game.cpp) - -// Carries the interpolation pair with a submitted display list. -void port_thread5_onSubmit(void* taskData); -// Runs fn on the window thread when the tick is on its own thread. -void port_runOnRenderThread(void (*fn)(void*), void* arg); -// Waits for in-flight display lists before freeing or reading what they use. -void port_pipelineSyncPoint(void); - // Frame Pacing (FramePacingPatches.cpp) int port_getDemoViCount(void); void port_setDemoViCount(int viCount); int port_getDemoDisplayViCount(int rawViCount); -void port_tickCutsceneStutter(void); int port_getCutsceneExtraVis(void); +int port_getInterpolationFpsCap(void); // Localization (Localization.cpp) @@ -30,13 +21,10 @@ int port_pauseMenuNeedsRefresh(void); // language or Return-to-Lair CVar changed void port_pauseMenuRebuild(void); // free + recreate + replay the main menu open void port_setPrintScale(float scale); -// Dialog font (AltDialogFont.cpp, SpritePatches.cpp) - -void port_dialogFontHd_rebuild(void); // rebuild the HD glyph textures for the current base -void port_refreshDialogFontGlyphCount(void); // re-read the reachable glyph count from the active font - // Framebuffer (FramebufferPatches.cpp) +void port_setViBlack(int active); +int port_isViBlack(void); void port_freezeReadback(int freeze); void port_requestReadback(void); int port_consumeReadbackRequest(void); @@ -46,6 +34,8 @@ void port_getPauseFramebufferSize(int* w, int* h); int port_pauseConsumeRecaptureRequest(void); int port_shouldCaptureTransition(void); +int32_t port_getAuxGpuFbId(void); +void port_readAuxFbToCpu(void* gfx_ptr); void port_patchPictureModel(void* model_bin, int32_t min_xy, int32_t max_xy, int32_t min_z, int32_t max_z, uint32_t from); int32_t port_getTransitionGpuFbId(void); @@ -74,22 +64,12 @@ int port_scalePlayerDamage(int damage); // Graphics (GraphicsPatches.cpp) -int port_getDrawDistanceSetting(void); // configured multiplier; safe during map load -int port_getDrawDistanceLevel(void); // render-time multiplier; clamped to 1x outside normal gameplay +int port_getDrawDistanceLevel(void); int port_shouldDisableLOD(void); float port_drawDistanceMul(void); void port_applyModelDrawDistanceCull(int* fadeFlag, float* cullMult, float* cullDist); int port_spriteSizeCulled(float depth, float size, float baseThreshold, int disableFlag); float port_hudOrthoShift(float refX); -void port_modelRenderResetTLUT(Gfx** gfx); - -// Vertex-animated models (AnimVertexPatches.cpp) - -// Recycles the per-draw vertex arena; once per tick, before the display list is built. -void port_animVtx_beginTick(void); -// Copies the just-posed vertices somewhere only this draw points at, and repoints -// segment 0x01 at the copy. -void port_modelRender_snapshotAnimVertices(Gfx** gfx, void* vertices, int32_t count); // Mirror (MirrorPatches.cpp) @@ -118,105 +98,9 @@ void port_unlockAudio(void); void port_audioIntMaskEnter(void); void port_audioIntMaskExit(void); -// Romhacks - -void* port_getRomhackResumeWarpFunc(void); -void romhack_RewriteActorSpawn(void* actorInfo, u32* flags); - // Attract-demo audio hold void port_beginDemoAudioHold(void); -void port_tickDemoAudioHold(void); -int port_audioHeld(void); -void port_noteMainLoopAlive(void); -int port_audioStallHold(void); -int32_t port_audioCatchupFrames(void); - -// One-shot cues when a teammate's file-progress flag arrives -void port_progressFlag_remoteCue(int32_t progressFlag); -void port_notedoor_remoteOpen(int32_t progressFlag); -void port_leveldoor_remoteOpen(int32_t progressFlag); - -void port_breakable_remoteBreak(int32_t progressFlag); - -void port_breakable_broadcastBreak(int32_t markerId, int32_t x, int32_t y, int32_t z); -void port_breakable_remoteBreakAt(int32_t markerId, int32_t x, int32_t y, int32_t z); - -void port_breakable_recordBreak(int32_t markerId, int32_t x, int32_t y, int32_t z); - -int32_t port_breakable_isBroken(int32_t map, int32_t markerId, int32_t x, int32_t y, int32_t z); - -int32_t port_cutsceneWarp_getReturnMap(void); - -void port_eggToll_onAdvance(int32_t map, int32_t secondaryId, int32_t stage); -int32_t port_eggToll_getStage(int32_t map, int32_t secondaryId); -void port_eggToll_remoteApply(int32_t map, int32_t secondaryId, int32_t stage); - -#define ANCHOR_PUZZLE_BGS_TANKTUP 1 -#define ANCHOR_PUZZLE_BGS_CROCTUS 2 -#define ANCHOR_PUZZLE_BGS_PINKEGG 3 -// CC clanker teeth: bits 0-2 = token tooth egg count, bits 3-5 = jiggy tooth. -#define ANCHOR_PUZZLE_CC_CLANKER_TEETH 4 -#define ANCHOR_PUZZLE_GV_JINXY_DOOR 5 -// MM Juju totem: bits 0-3, count of the 4 segments knocked off. -#define ANCHOR_PUZZLE_MM_JUJU 6 -// TTC Nipper: bits 0-2, count of hits taken (all 3 = dead, shell open). -#define ANCHOR_PUZZLE_TTC_NIPPER 7 -// TTC Blubber: bit 0 = first bullion delivered, bit 1 = second (jiggy spawned, Blubber leaves). -#define ANCHOR_PUZZLE_TTC_BLUBBER 8 -// TTC treasure hunt: bits 0-5, count of beak-busted X steps (bit 5 = treasure dug up). -#define ANCHOR_PUZZLE_TTC_XHUNT 9 -// FP xmas tree ice: 1 bit, set when the tree-top ice shatters. Recorded in the tree-interior -// map; the FP hub tree reads it via getForMap. -#define ANCHOR_PUZZLE_FP_TREE_ICE 10 -// FP bear cubs' presents: bit 0 = blue, bit 1 = green, bit 2 = red delivered. -#define ANCHOR_PUZZLE_FP_PRESENTS 11 -// FP snowman buttons: bit per button; all three spawns JIGGY_2D. -#define ANCHOR_PUZZLE_FP_SNOWBUTTONS 12 -#define ANCHOR_PUZZLE_FP_SLUSHES 13 -// RBB engine-room fans: 1 bit. Transient map flag 0 (enginefan.c reads it to slow the fans); persisted across reloads. -#define ANCHOR_PUZZLE_RBB_ENGINE_FANS 14 -// SM intro Bottles: bit 0 = the tutorial choice has been made. -#define ANCHOR_PUZZLE_SM_TUTORIAL 15 - -void port_remoteCarry_setCarried(uint32_t clientId, int32_t markerId, float offset[3], float yawOffset); -void port_remoteCarry_throw(uint32_t clientId, int32_t markerId, float start[3], float target[3]); -void port_remoteCarry_reset(void); -void port_anchorDummies_onActorsFreed(void); - -// Connected, in a real room, syncing world state. -int32_t port_anchor_isWorldSyncActive(void); - -// The puzzle mirrors below are home-scoped. -void port_puzzleStep_orBits(int32_t puzzleId, int32_t bits); -int32_t port_puzzleStep_get(int32_t puzzleId); -int32_t port_puzzleStep_getForMap(int32_t map, int32_t puzzleId); -int32_t port_puzzleStep_getForLevel(int32_t levelId, int32_t puzzleId); - -void port_puzzlePos_mark(int32_t puzzleId, int32_t x, int32_t y, int32_t z); -int32_t port_puzzlePos_isMarked(int32_t puzzleId, int32_t x, int32_t y, int32_t z); - -void port_fpTwinkly_release(void); - -int32_t port_mapFlag_wasSetRemotely(int32_t index); - -#define ANCHOR_COUNT_CCW_EYRIE_FED 0 -#define ANCHOR_COUNT_CCW_NABNUT_ACORNS 1 -void port_puzzleCount_add(int32_t counterId, int32_t delta); -int32_t port_puzzleCount_get(int32_t counterId); - -void port_hutSmash_record(int32_t x, int32_t y, int32_t z, int32_t loot); -int32_t port_hutSmash_get(int32_t x, int32_t y, int32_t z); -int32_t port_hutSmash_countForCurrentLevel(void); - -void port_jiggyCrane_broadcast(int32_t stage); -void port_jiggyCrane_remoteApply(int32_t stage); - -// Rate-limited: a marker reached cube_removeProp with a propPtr outside its cube. -void port_warnPropNotInCube(int32_t index, int32_t propCnt); - -// Rate-limited: a cube's node-prop split index passed 31, where the old :5 field wrapped. -void port_warnNodePropSplit(int32_t splitIndex, int32_t nodeCnt); #ifdef __cplusplus } diff --git a/src/port/Patches/PerfPatches.cpp b/src/port/Patches/PerfPatches.cpp deleted file mode 100644 index 037a48567..000000000 --- a/src/port/Patches/PerfPatches.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include -#include -#include - -#include - -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Patches/Patches.h" -#include "port/ShipInit.hpp" - -extern "C" { -#include -#include "functions.h" -#include "core2/lighting.h" - -extern s32 D_80383450[CUBE_SORT_SCRATCH_SIZE]; - -// core1 helpers not exposed through functions.h. -extern void func_80256E24(f32 dst[3], f32 theta, f32 phi, f32 x, f32 y, f32 z); -extern void ml_vec3f_normalize(f32 vec[3]); -extern void viewport_getPosition_vec3f(f32 dst[3]); -extern void viewport_getRotation_vec3f(f32 dst[3]); -} - -static const f32 kFrustumZX = 45.168514251708984f; // must match viewport.c -static const f32 kFrustumZY = 34.20201110839844f; -static constexpr float kDrawDistCullPadDeg = 25.0f; -static f32 sPadFrustumX = 89.21774f; -static f32 sPadFrustumY = 93.9692611694336f; -static f32 sPadPlanes[4][4]; -static bool sPadPlanesDirty = true; - -// TODO: Find better place for these two warn functions -// Capped so a bad frame can't flood the log; one print is enough to investigate. -extern "C" void port_warnPropNotInCube(int32_t index, int32_t propCnt) { - static int32_t sReported = 0; - if (sReported < 20) { - sReported++; - SPDLOG_WARN("cube_removeProp: prop not in cube (index {}, cnt {})", index, propCnt); - } -} - -// Fires only for a cube the old :5 unk0_4 would have silently corrupted, so if this -// never prints, no shipped map reaches the limit and the widening is forward-looking. -extern "C" void port_warnNodePropSplit(int32_t splitIndex, int32_t nodeCnt) { - static int32_t sReported = 0; - if (sReported < 20) { - sReported++; - SPDLOG_WARN("cube node-prop split {} of {} exceeds the old 31 limit", splitIndex, nodeCnt); - } -} - -// __cube_sort re-sorts every visible cube's props each tick, but only the camera -// moves, so the order rarely changes. A stable insertion sort skims an already -// sorted array in one pass and produces the same ordering as the vanilla sort. -static void RegisterCubeSort_Init() { - COND_VB_SHOULD(VB_CUBE_PROP_SORT, EVENT_PRIORITY_NORMAL, true, { - Cube* cube = va_arg(args, Cube*); - s32 n = cube->prop2Cnt; - for (s32 i = 1; i < n; i++) { - if (D_80383450[i] <= D_80383450[i - 1]) { - continue; - } - s32 key = D_80383450[i]; - Prop tmp; - std::memcpy(&tmp, &cube->prop2Ptr[i], sizeof(Prop)); - s32 j = i - 1; - while (j >= 0 && D_80383450[j] < key) { - D_80383450[j + 1] = D_80383450[j]; - std::memcpy(&cube->prop2Ptr[j + 1], &cube->prop2Ptr[j], sizeof(Prop)); - j--; - } - D_80383450[j + 1] = key; - std::memcpy(&cube->prop2Ptr[j + 1], &tmp, sizeof(Prop)); - } - *should = false; - }); -} - -// Same vertex recolor loop as gclights_recolor_vertices, but out-of-range lights -// are rejected with squared distances so only vertices inside a fade band pay a sqrt. -static void RegisterGcLights_Init() { - COND_VB_SHOULD(VB_GCLIGHTS_RECOLOR, EVENT_PRIORITY_NORMAL, true, { - Vtx* vtx = va_arg(args, Vtx*); - Vtx* vtxEnd = va_arg(args, Vtx*); - Vtx* refVtx = va_arg(args, Vtx*); - Lighting** lightsBegin = va_arg(args, Lighting**); - Lighting** lightsEnd = va_arg(args, Lighting**); - - // Active-light list caps at 16 entries (NUM_LIGHTING_ELEM). - f32 minSq[16]; - f32 maxSq[16]; - s32 nLights = (s32)(lightsEnd - lightsBegin); - for (s32 li = 0; li < nLights; li++) { - minSq[li] = lightsBegin[li]->fade_radius_min * lightsBegin[li]->fade_radius_min; - maxSq[li] = lightsBegin[li]->fade_radius_max * lightsBegin[li]->fade_radius_max; - } - - for (; vtx < vtxEnd; vtx++, refVtx++) { - f32 mod[3]; - mod[0] = mod[1] = mod[2] = 0.0f; - for (s32 li = 0; li < nLights; li++) { - const Lighting* light = lightsBegin[li]; - f32 dx = light->positionCopy[0] - (f32)refVtx->v.ob[0]; - f32 dy = light->positionCopy[1] - (f32)refVtx->v.ob[1]; - f32 dz = light->positionCopy[2] - (f32)refVtx->v.ob[2]; - f32 distSq = dx * dx + dy * dy + dz * dz; - if (maxSq[li] <= distSq) { - continue; - } - if (distSq <= minSq[li]) { - mod[0] += light->red; - mod[1] += light->green; - mod[2] += light->blue; - } else { - f32 dist = sqrtf(distSq); - f32 fade = - 1.0f - ((dist - light->fade_radius_min) / (light->fade_radius_max - light->fade_radius_min)); - mod[0] += fade * light->red; - mod[1] += fade * light->green; - mod[2] += fade * light->blue; - } - } - vtx->v.cn[0] = (s8)((refVtx->v.cn[0] * mod[0]) / 256.0) & 0xFF; - vtx->v.cn[1] = (s8)((refVtx->v.cn[1] * mod[1]) / 256.0) & 0xFF; - vtx->v.cn[2] = (s8)((refVtx->v.cn[2] * mod[2]) / 256.0) & 0xFF; - } - *should = false; - }); -} - -// Same rotations as mlMtx_rotate_yaw_deg/mlMtx_rotate_pitch_deg, but every -// snowflake shares one camera rotation, so cache the sin/cos instead of -// recomputing four of them per flake. -static void ApplySnowCameraRotation(const f32 camRot[3]) { - constexpr double kBadDtor = 3.141592654 / 180.0; - static f32 sYawDeg; - static f32 sPitchDeg; - static f32 sSinYaw, sCosYaw; - static f32 sSinPitch, sCosPitch; - static bool sHaveTrig = false; - - f32 pitchDeg = camRot[0]; - f32 yawDeg = camRot[1]; - if (!sHaveTrig || yawDeg != sYawDeg || pitchDeg != sPitchDeg) { - f32 yawRad = (f32)(yawDeg * kBadDtor); - f32 pitchRad = (f32)(pitchDeg * kBadDtor); - sSinYaw = sinf(yawRad); - sCosYaw = cosf(yawRad); - sSinPitch = sinf(pitchRad); - sCosPitch = cosf(pitchRad); - sYawDeg = yawDeg; - sPitchDeg = pitchDeg; - sHaveTrig = true; - } - - MtxF* m = mlMtx_get_stack_pointer(); - if (yawDeg != 0.0f) { - for (s32 i = 0; i < 3; i++) { - f32 r0 = m->mf[0][i]; - f32 r2 = m->mf[2][i]; - m->mf[0][i] = r0 * sCosYaw - r2 * sSinYaw; - m->mf[2][i] = r0 * sSinYaw + r2 * sCosYaw; - } - } - if (pitchDeg != 0.0f) { - for (s32 i = 0; i < 3; i++) { - f32 r1 = m->mf[1][i]; - f32 r2 = m->mf[2][i]; - m->mf[1][i] = r1 * sCosPitch + r2 * sSinPitch; - m->mf[2][i] = r1 * -sSinPitch + r2 * sCosPitch; - } - } -} - -static void RegisterSnowTrig_Init() { - COND_VB_SHOULD(VB_SNOW_CAMERA_ROTATION, EVENT_PRIORITY_NORMAL, true, { - ApplySnowCameraRotation(va_arg(args, f32*)); - *should = false; - }); -} - -static void RebuildPaddedPlanes() { - f32 rot[3]; - f32 pos[3]; - viewport_getRotation_vec3f(rot); - viewport_getPosition_vec3f(pos); - - // Components are cotangent-form (component/Z = cot(half angle)), so - // widening the frustum means shrinking the lateral component. - const f32 kDegToRad = 3.14159265f / 180.0f; - const f32 kMaxHalfAngle = 88.0f * kDegToRad; - f32 halfX = atanf(kFrustumZX / sPadFrustumX) + kDrawDistCullPadDeg * kDegToRad; - f32 halfY = atanf(kFrustumZY / sPadFrustumY) + kDrawDistCullPadDeg * kDegToRad; - halfX = std::min(halfX, kMaxHalfAngle); - halfY = std::min(halfY, kMaxHalfAngle); - f32 px = kFrustumZX / tanf(halfX); - f32 py = kFrustumZY / tanf(halfY); - - func_80256E24(sPadPlanes[0], rot[0], rot[1], -px, 0.0f, kFrustumZX); - func_80256E24(sPadPlanes[1], rot[0], rot[1], px, 0.0f, kFrustumZX); - func_80256E24(sPadPlanes[2], rot[0], rot[1], 0.0f, py, kFrustumZY); - func_80256E24(sPadPlanes[3], rot[0], rot[1], 0.0f, -py, kFrustumZY); - for (int i = 0; i < 4; i++) { - ml_vec3f_normalize(sPadPlanes[i]); - sPadPlanes[i][3] = -(pos[0] * sPadPlanes[i][0] + pos[1] * sPadPlanes[i][1] + pos[2] * sPadPlanes[i][2]); - } - sPadPlanesDirty = false; -} - -// Culled when all 8 corners are outside one plane. -static bool PaddedBoxCulled(const f32 boxMin[3], const f32 boxMax[3]) { - for (int p = 0; p < 4; p++) { - bool allOutside = true; - for (int c = 0; c < 8 && allOutside; c++) { - f32 x = (c & 1) ? boxMax[0] : boxMin[0]; - f32 y = (c & 2) ? boxMax[1] : boxMin[1]; - f32 z = (c & 4) ? boxMax[2] : boxMin[2]; - if (sPadPlanes[p][0] * x + sPadPlanes[p][1] * y + sPadPlanes[p][2] * z + sPadPlanes[p][3] < 0.0f) { - allOutside = false; - } - } - if (allOutside) { - return true; - } - } - return false; -} - -static void RegisterDrawDistCull_Init() { - COND_HOOK(ViewportFrustumUpdate, EVENT_PRIORITY_LOW, true, [](IEvent* event) { - auto* ev = (ViewportFrustumUpdate*)event; - sPadFrustumX = *ev->frustumX; - sPadFrustumY = *ev->frustumY; - sPadPlanesDirty = true; - }); - COND_VB_SHOULD(VB_DRAWDIST_BOX_CULL, EVENT_PRIORITY_NORMAL, true, { - f32* boxMin = va_arg(args, f32*); - f32* boxMax = va_arg(args, f32*); - if (sPadPlanesDirty) { - RebuildPaddedPlanes(); - } - if (PaddedBoxCulled(boxMin, boxMax)) { - *should = false; - } - }); -} - -static RegisterShipInitFunc sCubeSortInit(RegisterCubeSort_Init); -static RegisterShipInitFunc sGcLightsInit(RegisterGcLights_Init); -static RegisterShipInitFunc sSnowTrigInit(RegisterSnowTrig_Init); -static RegisterShipInitFunc sDrawDistCullInit(RegisterDrawDistCull_Init); \ No newline at end of file diff --git a/src/port/Patches/SpritePatches.cpp b/src/port/Patches/SpritePatches.cpp index 5f225d5d2..496e231d9 100644 --- a/src/port/Patches/SpritePatches.cpp +++ b/src/port/Patches/SpritePatches.cpp @@ -4,10 +4,6 @@ #include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Patches/Patches.h" -#include "port/ShipInit.hpp" - extern "C" { #include "structs.h" @@ -23,12 +19,13 @@ void assetcache_release(void* asset); enum asset_e print_getCurrentMapBoldFontTexture(void); char* ResourceMgr_ReloadByAssetId(uint32_t assetId); +int ResourceMgr_IsJapanese(void); enum level_e level_get(void); s32 gcpausemenu_levelToMenuPage(enum level_e level); extern s32 gFramebufferWidth; -extern BKSprite* print_sFontSpriteAssets[]; // font alphamask sprites ([0] = dialog font) -extern s32 print_sDialogFontGlyphCount; // reachable glyph count: byte range 0x21 .. 0x21+count-1 +extern BKSprite* D_80380AB8[]; // font alphamask sprites ([0] = dialog font) +extern s32 print_sDialogFontGlyphCount; // reachable glyph count: byte range 0x21 .. 0x21+count-1 #define SPRITE_DISPLAY_CACHE_SIZE 256 @@ -48,8 +45,8 @@ void port_spriteDisplayCache_clear(void) { // sets this once from the base font, but a language pack can swap in an extended dialog font // (more glyphs than the base 62) at runtime. void port_refreshDialogFontGlyphCount(void) { - if (print_sFontSpriteAssets[0] != NULL) { - print_sDialogFontGlyphCount = sprite_getFramePtr(print_sFontSpriteAssets[0], 0)->chunkCnt; + if (D_80380AB8[0] != NULL) { + print_sDialogFontGlyphCount = sprite_getFramePtr(D_80380AB8[0], 0)->chunkCnt; } } @@ -135,11 +132,9 @@ BKSprite* port_loadFilledBanner(s32 bannerAssetId, s32 fillId) { u8* maskPx = px + (x + y * cw) * 4; const s32 intensity = maskPx[2]; // mask byte[2] = intensity const u8 alpha = maskPx[3]; // mask byte[3] = alpha - // 5-bit channel * 8-bit intensity / 31 expands to 8-bit exactly (31 * 255 / 31 == 255). - // Dividing first truncates to 0..8, blacking out any intensity below 0x1F. - r5 = (r5 * intensity) / 0x1F; - g5 = (g5 * intensity) / 0x1F; - b5 = (b5 * intensity) / 0x1F; + r5 *= (intensity / 0x1F); + g5 *= (intensity / 0x1F); + b5 *= (intensity / 0x1F); maskPx[0] = (u8)r5; maskPx[1] = (u8)g5; maskPx[2] = (u8)b5; @@ -224,9 +219,3 @@ void port_pauseBannerFree(void) { } } // extern "C" - -static void RegisterSpriteRestoreAlphaCompare_Init() { - COND_VB_SHOULD(VB_SPRITE_RESTORE_ALPHA_COMPARE, EVENT_PRIORITY_NORMAL, true, { *should = true; }); -} - -static RegisterShipInitFunc sSpriteRestoreAlphaCompareInit(RegisterSpriteRestoreAlphaCompare_Init); diff --git a/src/port/Patches/TransitionPatches.cpp b/src/port/Patches/TransitionPatches.cpp index 041e9e44e..7b4b82afe 100644 --- a/src/port/Patches/TransitionPatches.cpp +++ b/src/port/Patches/TransitionPatches.cpp @@ -8,7 +8,9 @@ #include "port/ShipInit.hpp" #include "port/Patches/Patches.h" +extern "C" { #include "enums.h" +} // Falling-pieces transition uids. #define TRANSITION_FALLING_PIECES_IN 0x10 @@ -19,6 +21,20 @@ static int32_t sTransitionModelId = 0; static int32_t sTransitionUid = 0; static int32_t sTransitionSubstate = 0; +// Emulate N64's osViBlack on PC. On N64, osViBlack(1) blanked the TV output but +// the RDP still rendered to framebuffers. On PC we render normally (so the capture +// sees the world), then Engine.cpp clears the backbuffer to black before present +// while this flag is set. +static bool s_viBlack = false; + +extern "C" void port_setViBlack(int active) { + s_viBlack = (active != 0); +} + +extern "C" int port_isViBlack(void) { + return s_viBlack ? 1 : 0; +} + extern "C" int port_shouldCaptureTransition(void) { if (sTransitionModelId != ASSET_467_MODEL_TRANSITION_FALLING_JIGGIES) { return 0; @@ -38,6 +54,7 @@ void RegisterTransitionPatches_Init() { sTransitionModelId = ev->modelId; sTransitionUid = ev->uid; sTransitionSubstate = ev->substate; + port_setViBlack(ev->uid == TRANSITION_FALLING_PIECES_IN && ev->substate <= 4 ? 1 : 0); }); // Widescreen transition scaling. For the falling jiggy pieces, X-scale the diff --git a/src/port/Rando/CheckTracker/CheckTracker.cpp b/src/port/Rando/CheckTracker/CheckTracker.cpp index e650188ca..1e231cc64 100644 --- a/src/port/Rando/CheckTracker/CheckTracker.cpp +++ b/src/port/Rando/CheckTracker/CheckTracker.cpp @@ -103,7 +103,7 @@ std::string GetTotalCheckCount() { uint32_t collected = 0; uint32_t totalShuffled = 0; for (auto& entry : Rando::Logic::shuffledPool) { - if (entry.eligible || entry.skipped) { + if (entry.obtained || entry.skipped) { collected++; } if (entry.isShuffled) { @@ -131,7 +131,7 @@ void UpdateWorldCheckCount(level_e world) { if (Rando::StaticData::Checks[entry.randoCheckId].worldId != world) { continue; } - if (entry.eligible || entry.skipped) { + if (entry.obtained || entry.skipped) { worldCollected++; } if (entry.isShuffled) { @@ -219,7 +219,7 @@ void DrawCheckTrackerList() { continue; } - if (CVAR_HIDE_COLLECTED && entry.eligible) { + if (CVAR_HIDE_COLLECTED && entry.obtained) { continue; } @@ -227,16 +227,16 @@ void DrawCheckTrackerList() { continue; } - ImVec4 checkTextColor = entry.eligible ? VecFromRGBA8(CVAR_COLLECTED_COLOR) + ImVec4 checkTextColor = entry.obtained ? VecFromRGBA8(CVAR_COLLECTED_COLOR) : UIWidgets::ColorValues.at(UIWidgets::Colors::White); - ImVec4 itemTextColor = entry.eligible ? VecFromRGBA8(CVAR_ITEM_COLOR) + ImVec4 itemTextColor = entry.obtained ? VecFromRGBA8(CVAR_ITEM_COLOR) : UIWidgets::ColorValues.at(UIWidgets::Colors::Indigo); if (entry.skipped) { checkTextColor = itemTextColor = VecFromRGBA8(CVAR_SKIPPED_COLOR); } - if (!entry.eligible && CVAR_SHOW_LOGIC) { + if (!entry.obtained && CVAR_SHOW_LOGIC) { checkTextColor = Rando::Logic::CanAccessCheck(entry.randoCheckId) ? UIWidgets::ColorValues.at(UIWidgets::Colors::White) : VecFromRGBA8(CVAR_LOGIC_COLOR); @@ -244,7 +244,7 @@ void DrawCheckTrackerList() { ImGui::BeginGroup(); ImGui::TextColored(checkTextColor, checkNames.at(entry.randoCheckId).c_str()); - if (entry.eligible) { + if (entry.obtained) { ImGui::SameLine(); RandoItemId randoItemId = Rando::Logic::GetShuffledObject(entry.randoCheckId).randoItemId; const std::string& randoItemName = diff --git a/src/port/Rando/CustomCollectible/CustomCollectible.cpp b/src/port/Rando/CustomCollectible/CustomCollectible.cpp deleted file mode 100644 index 5178333cc..000000000 --- a/src/port/Rando/CustomCollectible/CustomCollectible.cpp +++ /dev/null @@ -1,243 +0,0 @@ -#include "CustomCollectible.h" -#include "CustomCollectibleDrawCustom.h" -#include - -#include -#include "port/ShipInit.hpp" -#include - -extern "C" { -#include "functions.h" -#include "actor.h" -void __chJinjo_802CDC9C(Actor* thisx, s16 arg1); -Actor* func_802D94B4(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); -Actor* chSnsEgg_draw(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); -} - -static std::queue propQueue; - -std::unordered_map customCollectibleDrawInfo = { - { ACTOR_52_BLUE_EGG, { ASSET_36D_SPRITE_BLUE_EGG, CCT_GENERIC_SPRITE } }, - { ACTOR_47_EMPTY_HONEYCOMB, { ASSET_361_MODEL_EMPTY_HONEYCOMB, CCT_GENERIC_MODEL } }, - { ACTOR_49_EXTRA_LIFE, { ASSET_36E_MODEL_EXTRA_LIFE, CCT_GENERIC_SPRITE } }, - { ACTOR_50_HONEYCOMB, { ASSET_363_MODEL_HONEYCOMB, CCT_GENERIC_MODEL } }, - { ACTOR_46_JIGGY, { ASSET_35F_MODEL_JIGGY, CCT_GENERIC_MODEL } }, - { ACTOR_60_JINJO_BLUE, { ASSET_3C0_MODEL_JINJO_BLUE, CCT_JINJO } }, - { ACTOR_62_JINJO_GREEN, { ASSET_3C2_MODEL_JINJO_GREEN, CCT_JINJO } }, - { ACTOR_5F_JINJO_ORANGE, { ASSET_3BC_MODEL_JINJO_ORANGE, CCT_JINJO } }, - { ACTOR_61_JINJO_PINK, { ASSET_3C1_MODEL_JINJO_PINK, CCT_JINJO } }, - { ACTOR_5E_JINJO_YELLOW, { ASSET_3BB_MODEL_JINJO_YELLOW, CCT_JINJO } }, - { ACTOR_12C_MOLEHILL, { ASSET_387_MODEL_BOTTLES, CCT_MOLEHILL } }, - { ACTOR_2D_MUMBO_TOKEN, { ASSET_41A_SPRITE_MUMBO_TOKEN, CCT_GENERIC_SPRITE } }, - { ACTOR_51_MUSIC_NOTE, { ASSET_6D6_SPRITE_MUSIC_NOTE, CCT_GENERIC_SPRITE } }, - { ACTOR_25E_SNS_EGG, { ASSET_50D_MODEL_SNS_EGG, CCT_VANILLA_SNS_EGG } }, - { ACTOR_25D_ICE_KEY, { ASSET_50C_MODEL_ICE_KEY, CCT_GENERIC_MODEL } }, - { ACTOR_3CD_CUSTOM_COLLECTIBLE, { ASSET_35F_MODEL_JIGGY, CCT_CUSTOM_MODEL } }, -}; - -ActorAnimationInfo moleAnimation[] = { - { ASSET_13B_ANIM_BOTTLES_IDLE, 7.0f }, -}; - -ActorAnimationInfo chJinjoAnimation[] = { - { ASSET_2F_ANIM_JINJO_HELP, 1.5f }, -}; - -ActorInfo customActorInfo = { MARKER_300_CUSTOM_COLLECTIBLE, - ACTOR_3CD_CUSTOM_COLLECTIBLE, - ASSET_0_NONE, - 0, - NULL, - CustomCollectible_Update, - NULL, - NULL, - 0, - 0, - 0.8f, - 0 }; - -void CustomCollectible_Update(Actor* actor) { - ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&actor->local; - - if (!actor->initialized) { - actor->initialized = true; - actor->marker->collidable = true; - - actor->scale = CustomCollectible::GetScale(customLocal->itemType); - } - - if (customLocal->itemType == RITYPE_MOLEHILL || customLocal->itemType == RITYPE_JINJO) { - CustomCollectible::FacePlayer(actor); - } else { - actor->yaw += 5.0f; - } - - // Sparkles - if (customCollectibleDrawInfo[customLocal->actorId].drawType != CCT_GENERIC_SPRITE) { - for (int i = 0; i < 4; i++) { - if (randf() < 0.03) { - commonParticle_add(actor->marker, i + 5, func_80329904); - commonParticle_new((common_particle_e)8, actor->marker->unk14_21); - } - } - } - - // Allows shadows - if (customLocal->itemType == RITYPE_AP_ITEM) { - actor->unk124_6 = 1; - actor->marker->unk14_21 = 1; - } -} - -f32 CustomCollectible::GetScale(RandoItemType itemType) { - switch (itemType) { - case RITYPE_MUSIC_NOTE: - case RITYPE_SNS_EGG: - return 0.42857143f; - case RITYPE_EMPTY_HONEYCOMB: - case RITYPE_MOLEHILL: - return 0.8f; - default: - return 1.0f; - } -} - -void CustomCollectible::FacePlayer(Actor* actor) { - // Copied from source code inside jinjo.c - f32 sp7C[3]; - f32 sp6C; - f32* sp30 = actor->position; - func_8028E964(sp7C); - func_80257F18(sp30, sp7C, &sp6C); - s16 sp64 = (actor->yaw * 182.04444); - s16 sp66 = (s32)(sp6C * 182.04444); - sp66 = sp64 - sp66; - s32 sp60 = func_8028AED4(sp30, 55.0f); - __chJinjo_802CDC9C(actor, sp66); -} - -Actor* CustomCollectible::AttachCustomVariables(RandoCheckId randoCheckId, Actor* customCollectible) { - ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&customCollectible->local; - - RandoItemId randoItemId = RANDO_SAVE_CHECKS[randoCheckId].randoItemId; - - customLocal->randoCheckId = randoCheckId; - customLocal->randoItemId = randoItemId; - customLocal->actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; - customLocal->itemType = Rando::StaticData::Items[randoItemId].randoItemType; - - return customCollectible; -} - -Actor* CustomCollectible::Spawn(int32_t position[3], RandoCheckId randoCheckId) { - int32_t spawnPosition[3] = { position[0], position[1], position[2] }; - - int32_t flags = ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21; - - RandoItemId randoItemId = RANDO_SAVE_CHECKS[randoCheckId].randoItemId; - RandoItemType itemType = Rando::StaticData::Items[randoItemId].randoItemType; - - // actor_new stores the ActorInfo* permanently, so it must outlive Spawn() - static std::unordered_map sActorInfoCache; - ActorInfo& collectibleInfo = sActorInfoCache[randoItemId]; - collectibleInfo = CustomCollectible::GetActorAndDrawInfo(randoItemId); - - // Spawn actor - Actor* customCollectible = actor_new(spawnPosition, 0, &collectibleInfo, flags); - if (itemType == RITYPE_SNS_EGG) { - customCollectible->actorTypeSpecificField = CustomCollectible::GetSNSEggColor(randoItemId); - } - customCollectible->marker->collisionFunc = CustomCollectible::OnCollect; - customCollectible = CustomCollectible::AttachCustomVariables(randoCheckId, customCollectible); - - return customCollectible; -} - -uint32_t CustomCollectible::GetSNSEggColor(RandoItemId randoItemId) { - switch (randoItemId) { - case RI_STOP_N_SWOP_EGG_BLUE: - return (uint32_t)SNS_ITEM_EGG_BLUE; - case RI_STOP_N_SWOP_EGG_CYAN: - return (uint32_t)SNS_ITEM_EGG_CYAN; - case RI_STOP_N_SWOP_EGG_GREEN: - return (uint32_t)SNS_ITEM_EGG_GREEN; - case RI_STOP_N_SWOP_EGG_PINK: - return (uint32_t)SNS_ITEM_EGG_PINK; - case RI_STOP_N_SWOP_EGG_RED: - return (uint32_t)SNS_ITEM_EGG_RED; - case RI_STOP_N_SWOP_EGG_YELLOW: - return (uint32_t)SNS_ITEM_EGG_YELLOW; - default: - return (uint32_t)SNS_ITEM_EGG_CYAN; - } -} - -ActorInfo CustomCollectible::GetActorAndDrawInfo(RandoItemId randoItemId) { - ActorInfo collectibleInfo = customActorInfo; - - actor_e actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; - auto drawInfo = customCollectibleDrawInfo[actorId]; - - collectibleInfo.modelId = drawInfo.drawModel; - - switch (drawInfo.drawType) { - case CCT_GENERIC_MODEL: - collectibleInfo.draw_func = actor_draw; - break; - case CCT_GENERIC_SPRITE: - collectibleInfo.draw_func = fxTouchSparkle_draw; - collectibleInfo.shadow_scale = 0.0f; - break; - case CCT_JINJO: - collectibleInfo.draw_func = actor_draw; - collectibleInfo.animations = chJinjoAnimation; - break; - case CCT_MOLEHILL: - collectibleInfo.draw_func = func_802D94B4; - collectibleInfo.animations = moleAnimation; - break; - case CCT_VANILLA_SNS_EGG: - collectibleInfo.draw_func = chSnsEgg_draw; - break; - case CCT_CUSTOM_MODEL: - collectibleInfo.draw_func = CustomCollectible_DrawCustomModel; - break; - default: - break; - } - return collectibleInfo; -} - -void CustomCollectible::OnCollect(struct actorMarker_s* self, struct actorMarker_s* other) { - Actor* actor = marker_getActor(self); - ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&actor->local; - fxSparkle_honeycomb(&self->propPtr->x); - ItemQueue::AddCheck(customLocal->randoCheckId); - marker_despawn(self); -} - -// When regular props are spawned in BK, the game isn't fully set up yet to spawn -// actors. So we delay prop spawns until the game's ready to spawn actors. -void CustomCollectible::QueueProp(int32_t position[3], RandoCheckId randoCheckId) { - QueuedProp queuedProp; - queuedProp.position[0] = position[0]; - queuedProp.position[1] = position[1]; - queuedProp.position[2] = position[2]; - queuedProp.randoCheckId = randoCheckId; - propQueue.push(queuedProp); -} - -void CustomCollectible::ProcessPropQueue() { - while (propQueue.size() > 0) { - QueuedProp prop = propQueue.front(); - Actor* actor = CustomCollectible::Spawn(prop.position, prop.randoCheckId); - propQueue.pop(); - } -} - -void RegisterCustomCollectible() { - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO, - [](IEvent* event) { CustomCollectible::ProcessPropQueue(); }); -} - -static RegisterShipInitFunc initFunc(RegisterCustomCollectible, { "IS_RANDO" }); diff --git a/src/port/Rando/CustomCollectible/CustomCollectible.h b/src/port/Rando/CustomCollectible/CustomCollectible.h deleted file mode 100644 index 8b2f06bdb..000000000 --- a/src/port/Rando/CustomCollectible/CustomCollectible.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include "port/Rando/ItemQueue.h" -#include "prop.h" - -typedef struct { - RandoCheckId randoCheckId; - RandoItemId randoItemId; - actor_e actorId; - RandoItemType itemType; -} ActorLocal_CustomCollectible; - -enum CustomCollectibleDrawTypes { - CCT_GENERIC_MODEL, - CCT_GENERIC_SPRITE, - CCT_JINJO, - CCT_MOLEHILL, - CCT_VANILLA_SNS_EGG, - CCT_CUSTOM_MODEL, -}; - -typedef struct { - asset_e drawModel; - CustomCollectibleDrawTypes drawType; -} CustomCollectibleDrawInfo; - -typedef struct { - s32 position[3]; - RandoCheckId randoCheckId; -} QueuedProp; - -void CustomCollectible_Update(Actor* actor); - -class CustomCollectible { -private: - static Actor* AttachCustomVariables(RandoCheckId randoItemId, Actor* customCollectible); - static void OnCollect(struct actorMarker_s* self, struct actorMarker_s* other); - static ActorInfo GetActorAndDrawInfo(RandoItemId randoItemId); - static uint32_t GetSNSEggColor(RandoItemId randoItemId); - -public: - static Actor* Spawn(int32_t position[3], RandoCheckId randoCheckId); - static f32 GetScale(RandoItemType itemType); - static void FacePlayer(Actor* actor); - static void QueueProp(int32_t position[3], RandoCheckId randoCheckId); - static void ProcessPropQueue(); -}; diff --git a/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp b/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp deleted file mode 100644 index 80ae1ed27..000000000 --- a/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Custom item model rendering. -// -// The models live in lighthouse.o2r as XML libultraship resources under -// objects/object_X_item. -// They are untextured prim-color geometry, so they draw with a single matrix -// push and no material setup beyond what the display lists carry. - -// Include order matters here. -// 1. ResourceHelpers.h (via ship/Context.h -> spdlog) parses the Windows headers, -// which must happen before any decomp header: Events.h drags in prop.h -> -// structs.h -> bool.h, whose function-like BOOL(x) macro corrupts the -// `typedef BOOL (CALLBACK* ...)` declarations in the Windows SDK. -// 2. bridge.h/Events.h bring in the events bridge/json templates, which must be -// seen with C++ linkage before functions.h re-includes them inside the -// extern "C" block below. -#include -#include "port/ResourceHelpers.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Interpolation/FrameInterpolation.h" - -#include "CustomCollectibleDrawCustom.h" -#include "CustomCollectible.h" - -extern "C" { -#include -#include "macros.h" -#include "prop.h" -#include "functions.h" -#include "variables.h" -#include "core1/viewport.h" -#include "core1/mlmtx.h" -} - -static const char* sCustomModelPaths[] = { - "objects/object_archipelago_item/gArchipelagoItemDL", - "objects/object_archipelago_item/gArchipelagoJunkDL", - "objects/object_archipelago_item/gArchipelagoProgressiveDL", -}; - -// The models are authored at OoT world scale, which is roughly 10x too large -// for BK. Baked into every draw so callers treat scale 1.0 as "natural size". -static const f32 sCustomModelBaseScale = 0.04f; - -// BK never uploads RSP lights (its models bake shading into vertex colors), but -// these materials enable G_LIGHTING, so without our own light setup the shade -// input is garbage and the model renders black. Neutral white key light from -// the upper-front-right plus a mid ambient. -static Lights1 sCustomModelLights = gdSPDefLights1(110, 110, 110, 255, 255, 255, 40, 40, 40); - -// Pin the resources so the cached Gfx pointers stay valid across frames. -static std::shared_ptr sModelResources[ARRAY_COUNT(sCustomModelPaths)]; -static Gfx* sModelDLs[ARRAY_COUNT(sCustomModelPaths)]; - -static Gfx* CustomCollectible_GetDL(CustomItemModel model) { - if (model < 0 || model >= (s32)ARRAY_COUNT(sCustomModelPaths)) { - return nullptr; - } - if (sModelDLs[model] == nullptr) { - sModelResources[model] = GetResourceByName(sCustomModelPaths[model]); - if (sModelResources[model] == nullptr) { - return nullptr; - } - sModelDLs[model] = ResourceMgr_LoadGfxByName(sCustomModelPaths[model]); - } - return sModelDLs[model]; -} - -Actor* CustomCollectible_DrawCustomModel(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) { - Actor* actor = marker_getActor(marker); - ActorLocal_CustomCollectible* customLocal = (ActorLocal_CustomCollectible*)&actor->local; - CustomItemModel model; - - switch (customLocal->randoItemId) { - case RI_AP_ITEM_PROGRESSION: - model = ARCHIPELAGO_MODEL_PROGRESSIVE; - break; - default: - break; - } - - Gfx* dl = CustomCollectible_GetDL(model); - if (dl == nullptr) { - return actor; - } - - f32 camera_position[3]; - viewport_getPosition_vec3f(camera_position); - - // The mlMtx calls below are recorded for frame interpolation; the scope key - // pairs this draw's matrix across ticks. Keyed by model, so two instances - // of the same model drawn in the same frame would need instance-keyed - // scopes instead. - FrameInterpolation_RecordOpenChild("custom_item", (uintptr_t)model); - f32 rotation[3] = { actor->pitch, actor->yaw, actor->roll }; - f32 position[3] = { actor->position[0], actor->position[1] + 50, actor->position[2] }; - // The modelview translation is camera-relative, matching modelRender_draw. - mlMtxIdent(); - func_80252AF0(camera_position, position, rotation, actor->scale * sCustomModelBaseScale, NULL); - mlMtxApply(*mtx); - gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPSetLights1((*gfx)++, sCustomModelLights); - gSPDisplayList((*gfx)++, dl); - gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW); - - FrameInterpolation_RecordCloseChild(); - - return actor; -} diff --git a/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h b/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h deleted file mode 100644 index ce87b41bf..000000000 --- a/src/port/Rando/CustomCollectible/CustomCollectibleDrawCustom.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef PORT_ARCHIPELAGO_ITEM_H -#define PORT_ARCHIPELAGO_ITEM_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Forward declarations (tag structs from prop.h) so this header stays free of -// the decomp includes including prop.h here would drag in bool.h, whose -// function-like BOOL() macro corrupts the Windows SDK headers in C++ TUs. -struct actorMarker_s; -struct actor_s; - -typedef enum CustomItemModel { - ARCHIPELAGO_MODEL_NONE = -1, // resolver sentinel: keep the vanilla model - ARCHIPELAGO_MODEL_ITEM, - ARCHIPELAGO_MODEL_JUNK, - ARCHIPELAGO_MODEL_PROGRESSIVE, -} CustomItemModel; - -// Draws an Archipelago item model at a world position. Must be called from a -// draw context that owns the display list and matrix pools (an actor draw -// callback, a world/player draw event hook, cutscene draw code, etc.). -// rotation is pitch/yaw/roll in degrees and may be NULL; scale is a relative -// multiplier where 1.0 = natural in-world size (the OoT-scale source models are -// shrunk to BK proportions internally). -Actor* CustomCollectible_DrawCustomModel(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/port/Rando/CustomObject/CustomObject.cpp b/src/port/Rando/CustomObject/CustomObject.cpp index beeaa989a..aa30f92d3 100644 --- a/src/port/Rando/CustomObject/CustomObject.cpp +++ b/src/port/Rando/CustomObject/CustomObject.cpp @@ -2,7 +2,6 @@ #include #include "port/UI/cvar_prefixes.h" #include "port/Rando/Logic/Logic.h" -#include "port/Rando/ObjectBehavior/ObjectBehavior.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "actor.h" @@ -35,6 +34,7 @@ void ml_vec3f_to_vec3h(s16 dst[3], f32 src[3]); void gcparade_beginFinalParade(void); void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume); +Actor* marker_getActor(ActorMarker* thisx); void marker_despawn(ActorMarker* marker); Actor* actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags); extern ActorInfo chJinjoBlue; @@ -43,18 +43,18 @@ extern ActorInfo chJinjoYellow; extern ActorInfo chJinjoPink; extern ActorInfo chJinjoOrange; extern ActorInfo chJiggy; -extern ActorInfo chEmptyHoneycomb; -extern ActorInfo chMumboToken; +extern ActorInfo D_80366C80; +extern ActorInfo D_803685A0; extern ActorInfo sumusicNote; extern ActorInfo chExtraLife; -extern ActorInfo chHoneycomb; -extern ActorInfo chBlueEgg; -extern ActorInfo chRedFeather; -extern ActorInfo chGoldFeather; +extern ActorInfo D_80366CA4; +extern ActorInfo D_80367D00; +extern ActorInfo D_80367D24; +extern ActorInfo D_80367D48; -extern ActorInfo chSnsEgg; -extern ActorInfo chIceKey; +extern ActorInfo D_80367814; +extern ActorInfo D_803677A8; } typedef struct { @@ -69,9 +69,9 @@ bool shouldRemoveEX = false; // clang-format off std::map> actorInfoMap = { - { ACTOR_2D_MUMBO_TOKEN, { chMumboToken, ACTOR_FLAG_UNKNOWN_6 } }, + { ACTOR_2D_MUMBO_TOKEN, { D_803685A0, ACTOR_FLAG_UNKNOWN_6 } }, { ACTOR_46_JIGGY, { chJiggy, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_7 | ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_47_EMPTY_HONEYCOMB, { chEmptyHoneycomb, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_47_EMPTY_HONEYCOMB, { D_80366C80, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_49_EXTRA_LIFE, { chExtraLife, ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_51_MUSIC_NOTE, { sumusicNote, ACTOR_FLAG_UNKNOWN_21 } }, { ACTOR_5E_JINJO_YELLOW, { chJinjoYellow, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, @@ -79,15 +79,16 @@ std::map> actorInfoMap = { { ACTOR_60_JINJO_BLUE, { chJinjoBlue, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, { ACTOR_61_JINJO_PINK, { chJinjoPink, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, { ACTOR_62_JINJO_GREEN, { chJinjoGreen, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8 } }, - { ACTOR_50_HONEYCOMB, { chHoneycomb, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_52_BLUE_EGG, { chBlueEgg, ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_129_RED_FEATHER, { chRedFeather, ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_370_GOLD_FEATHER, { chGoldFeather, ACTOR_FLAG_UNKNOWN_21 } }, - { ACTOR_25E_SNS_EGG, { chSnsEgg, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, - { ACTOR_25D_ICE_KEY, { chIceKey, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, + { ACTOR_50_HONEYCOMB, { D_80366CA4, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_52_BLUE_EGG, { D_80367D00, ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_129_RED_FEATHER, { D_80367D24, ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_370_GOLD_FEATHER, { D_80367D48, ACTOR_FLAG_UNKNOWN_21 } }, + { ACTOR_25E_SNS_EGG, { D_80367814, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, + { ACTOR_25D_ICE_KEY, { D_803677A8, ACTOR_FLAG_UNKNOWN_9 | ACTOR_FLAG_UNKNOWN_10 | ACTOR_FLAG_UNKNOWN_15 } }, }; // clang-format on +extern int32_t GetJinjoActorMarkerId(actor_e actorId); int32_t currentMap = -1; void CustomObject::ResetRandoSpawnQueue() { @@ -171,10 +172,6 @@ Actor* CustomObject::SpawnCustomActorEX(RandoCheckId randoCheckId, int32_t posit Actor* customActor = actor_new(position, 0, actorInfo, flags); if (customActor != NULL) { - // Music notes don't cast shadows, custom or otherwise. - if (actorInfo->actorId == ACTOR_51_MUSIC_NOTE) { - customActor->unk124_6 = 0; - } customActor = SetCustomActorParametersEX(randoCheckId, customActor); randoSpawnedCheckIds.push_back(randoCheckId); } @@ -207,7 +204,7 @@ void CustomObject::FlushRandoSpawnQueue() { } actor_e randoActorId = Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId); - if (randoSaveCheck.eligible) { + if (randoSaveCheck.obtained) { randoActorId = GetRandomJunkActorId(randoSaveCheck); } @@ -220,8 +217,7 @@ void CustomObject::FlushRandoSpawnQueue() { &actorInfoMap.at(randoActorId).first, actorInfoMap.at(randoActorId).second); - if (customActor != NULL && randoSaveCheck.eligible && - RANDO_SAVE_OPTIONS[RO_SPAWN_JUNK].optionValue == RO_GENERIC_ON) { + if (randoSaveCheck.obtained && RANDO_SAVE_OPTIONS[RO_SPAWN_JUNK].optionValue == RO_GENERIC_ON) { customActor->marker->unk14_21 = true; customActor->scale = 1.0f; } @@ -254,7 +250,7 @@ Actor* CustomObject::ShouldCreateCustomActorEX(RandoCheckId randoCheckId, int32_ return NULL; } - if (randoSaveCheck.eligible) { + if (randoSaveCheck.obtained) { if (refActor != nullptr) { randoActorId = (actor_e)refActor->modelCacheIndex; } else { @@ -339,22 +335,16 @@ void CustomObject::ResolveCustomActorCollisionEX(RandoCheckId randoCheckId) { void CustomObject::CheckObtainedEX(RandoCheckId randoCheckId, bool isInit) { for (auto& pool : Rando::Logic::shuffledPool) { - if (pool.randoCheckId == randoCheckId && !pool.eligible) { - pool.eligible = true; + if (pool.randoCheckId == randoCheckId && !pool.obtained) { + pool.obtained = true; shouldRemoveEX = true; - RANDO_SAVE_CHECKS[pool.randoCheckId].eligible = true; + RANDO_SAVE_CHECKS[pool.randoCheckId].obtained = true; CustomObject::RemoveSpawnedIdFromList(randoCheckId); - if (isInit) { - CustomObject::ResolveCustomActorCollisionEX(randoCheckId); - } else { + if (!isInit) { Rando::StaticData::SendCollisionNotification(pool.randoCheckId); } Rando::StaticData::ModifyRandoInfFlagState(randoCheckId); Rando::Logic::RefreshReachableRegions(); - // Broadcast real collects only (not save-load/remote apply, both isInit). - if (!isInit) { - CALL_EVENT(OnRandoCheckObtained, (int32_t)randoCheckId, (int32_t)gsworld_getMap()); - } break; } } diff --git a/src/port/Rando/ItemQueue.cpp b/src/port/Rando/ItemQueue.cpp deleted file mode 100644 index 8b2571fe7..000000000 --- a/src/port/Rando/ItemQueue.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include "ItemQueue.h" - -#include -#include -#include - -#include "port/UI/Notification.h" -#include "port/UI/UIWidgets.hpp" -#include -#include "port/ShipInit.hpp" -#include "port/Rando/Logic/Logic.h" -#include "actor.h" -#include "port/Enhancements/Retention/Retention.h" - -extern "C" { -#include "functions.h" -extern u8 sHoneycombScore[3]; -extern struct { - u8 D_803832C0[0xD]; - u8 D_803832CD[0xD]; -} jiggyscore; -#define MUMBO_TOKEN_COUNT 126 -#define MUMBOSCORE_SIZE (((MUMBO_TOKEN_COUNT - 1 + 7) & ~7) / 8) -extern u8 sMumboTokenScore[MUMBOSCORE_SIZE]; -extern u8 D_80385FF0[0xE]; - -extern ActorInfo chJinjoBlue; -extern ActorInfo chJinjoGreen; -extern ActorInfo chJinjoYellow; -extern ActorInfo chJinjoPink; -extern ActorInfo chJinjoOrange; -extern void spawnOrbit(); -} - -constexpr u8 kAllJinjos = 0x1F; // all five color bits collected - -#define CVAR_NAME_SHOW_COLLISION_NOTIFICATIONS "gRandoSettings.RandoNotifications" -#define CVAR_SHOW_COLLISION_NOTIFICATIONS CVarGetInteger(CVAR_NAME_SHOW_COLLISION_NOTIFICATIONS, 0) - -#define JIGGY_ID_MULTIPLIER(levelId) (1 + (10 * (levelId - 1))) -#define HONEYCOMB_ID_MULTIPLIER(levelId) (1 + (2 * (levelId - 1))) - -static std::queue itemQueue; - -std::unordered_map itemColors = { - { ACTOR_1_UNKNOWN, UIWidgets::Colors::Brown }, { ACTOR_52_BLUE_EGG, UIWidgets::Colors::Cyan }, - { ACTOR_47_EMPTY_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_49_EXTRA_LIFE, UIWidgets::Colors::Yellow }, - { ACTOR_50_HONEYCOMB, UIWidgets::Colors::Yellow }, { ACTOR_46_JIGGY, UIWidgets::Colors::Yellow }, - { ACTOR_60_JINJO_BLUE, UIWidgets::Colors::SkyBlue }, { ACTOR_62_JINJO_GREEN, UIWidgets::Colors::Green }, - { ACTOR_5F_JINJO_ORANGE, UIWidgets::Colors::Orange }, { ACTOR_61_JINJO_PINK, UIWidgets::Colors::Pink }, - { ACTOR_5E_JINJO_YELLOW, UIWidgets::Colors::Yellow }, { ACTOR_12C_MOLEHILL, UIWidgets::Colors::Cyan }, - { ACTOR_2D_MUMBO_TOKEN, UIWidgets::Colors::Gray }, { ACTOR_51_MUSIC_NOTE, UIWidgets::Colors::Yellow }, - { ACTOR_25E_SNS_EGG, UIWidgets::Colors::Pink }, { ACTOR_25D_ICE_KEY, UIWidgets::Colors::White }, -}; - -std::unordered_map snsColors = { - { RI_STOP_N_SWOP_EGG_YELLOW, UIWidgets::Colors::Yellow }, { RI_STOP_N_SWOP_EGG_RED, UIWidgets::Colors::Red }, - { RI_STOP_N_SWOP_EGG_GREEN, UIWidgets::Colors::Green }, { RI_STOP_N_SWOP_EGG_BLUE, UIWidgets::Colors::Blue }, - { RI_STOP_N_SWOP_EGG_PINK, UIWidgets::Colors::Pink }, { RI_STOP_N_SWOP_EGG_CYAN, UIWidgets::Colors::Cyan }, - { RI_STOP_N_SWOP_ICE_KEY, UIWidgets::Colors::White }, -}; - -std::unordered_map jinjoJiggyChecks = { - { LEVEL_1_MUMBOS_MOUNTAIN, RC_MM_JIGGY_JINJO }, { LEVEL_2_TREASURE_TROVE_COVE, RC_TTC_JIGGY_JINJO }, - { LEVEL_3_CLANKERS_CAVERN, RC_CC_JIGGY_JINJO }, { LEVEL_4_BUBBLEGLOOP_SWAMP, RC_BGS_JIGGY_JINJO }, - { LEVEL_5_FREEZEEZY_PEAK, RC_FP_JIGGY_JINJO }, { LEVEL_7_GOBIS_VALLEY, RC_GV_JIGGY_JINJO }, - { LEVEL_8_CLICK_CLOCK_WOOD, RC_CCW_JIGGY_JINJO }, { LEVEL_9_RUSTY_BUCKET_BAY, RC_RBB_JIGGY_JINJO }, - { LEVEL_A_MAD_MONSTER_MANSION, RC_MMM_JIGGY_JINJO }, -}; - -void ItemQueue::Process() { - if (itemQueue.size() < 1) { - return; - } - - RandoCheckId randoCheckId = itemQueue.front(); - - // Grant item - RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; - if (!randoSaveCheck.received) { - ItemQueue::GiveItem(randoSaveCheck.randoItemId); - ItemQueue::SendNotification(randoSaveCheck.randoItemId); - Rando::StaticData::ModifyRandoInfFlagState(randoCheckId); - // RANDO_SAVE_CHECKS[randoCheckId].received = true; - } - - itemQueue.pop(); -} - -void ItemQueue::GiveItem(RandoItemId randoItemId) { - RandoItemType itemType = Rando::StaticData::Items[randoItemId].randoItemType; - actor_e actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; - int16_t worldId = Rando::StaticData::Items[randoItemId].worldId; - uint16_t combId; - uint16_t maxHoneycombs; - uint32_t jiggyId; - ActorInfo* actorInfo; - int32_t playerPosition[3]; - Actor* customActor; - uint8_t collectedJinjos; - - switch (itemType) { - case RITYPE_BLUE_EGG: - coMusicPlayer_playMusic(COMUSIC_C_EGG_COLLECTED, 32000); - item_inc(ITEM_D_EGGS); - break; - case RITYPE_EMPTY_HONEYCOMB: - combId = HONEYCOMB_ID_MULTIPLIER(worldId); - maxHoneycombs = worldId == LEVEL_B_SPIRAL_MOUNTAIN ? 6 : 2; - if (worldId > LEVEL_6_LAIR) { - combId = HONEYCOMB_ID_MULTIPLIER(worldId - 1); - } - for (int i = 0; i < (maxHoneycombs); i++) { - if ((sHoneycombScore[((combId + i) - 1) / 8] & (1 << ((combId + i) & 7))) == 0) { - honeycombscore_set((honeycomb_e)(combId + i), 1); - break; - } - } - coMusicPlayer_playMusic(COMUSIC_17_EMPTY_HONEYCOMB_COLLECTED, 28000); - item_inc(ITEM_13_EMPTY_HONEYCOMB); - if (!(item_getCount(ITEM_13_EMPTY_HONEYCOMB) < 6)) { - gcpausemenu_80314AC8(0); - } - break; - case RITYPE_EXTRA_LIFE: - coMusicPlayer_playMusic(COMUSIC_15_EXTRA_LIFE_COLLECTED, 0x7FFF); - item_inc(ITEM_16_LIFE); - break; - case RITYPE_HONEYCOMB: - coMusicPlayer_playMusic(COMUSIC_16_HONEYCOMB_COLLECTED, 28000); - item_inc(ITEM_14_HEALTH); - break; - case RITYPE_JIGGY: - jiggyId = JIGGY_ID_MULTIPLIER(worldId); - for (int32_t i = jiggyId; i <= (jiggyId + 9); i++) { - if ((jiggyscore.D_803832C0[(i - 1) / 8] & (1 << (i & 7))) == 0) { - jiggyscore_setCollected(i, 1); - break; - } - } - coMusicPlayer_playMusic(COMUSIC_D_JINGLE_JIGGY_COLLECTED, -1); - item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, 1); - item_inc(ITEM_E_JIGGY); - spawnOrbit(); - break; - case RITYPE_JINJO: - if (worldId == map_getLevel(gsworld_getMap())) { - item_adjustByDiffWithHud(ITEM_12_JINJOS, jinjoBitFromActor(actorId)); - } - collectedJinjos = collectedBits(worldId); - collectedJinjos |= jinjoBitFromActor(actorId); - if (collectedJinjos == kAllJinjos) { - ItemQueue::AddCheck(jinjoJiggyChecks[worldId]); - } - setCollectedBits(worldId, collectedJinjos); - // Spawn vanilla jinjo on top of the player because the animation is too complex to handle without doing - // this. Collection behaviour is canceled in Jinjo.cpp so that part can all be handled here in the - // ItemQueue. - switch (actorId) { - case ACTOR_5E_JINJO_YELLOW: - actorInfo = &chJinjoYellow; - break; - case ACTOR_5F_JINJO_ORANGE: - actorInfo = &chJinjoOrange; - break; - case ACTOR_60_JINJO_BLUE: - actorInfo = &chJinjoBlue; - break; - case ACTOR_61_JINJO_PINK: - actorInfo = &chJinjoPink; - break; - case ACTOR_62_JINJO_GREEN: - actorInfo = &chJinjoGreen; - break; - } - player_getPosition_s32(playerPosition); - customActor = actor_new(playerPosition, 0, actorInfo, ACTOR_FLAG_UNKNOWN_6 | ACTOR_FLAG_UNKNOWN_8); - break; - case RITYPE_MOLEHILL: - coMusicPlayer_playMusic(COMUSIC_D_JINGLE_JIGGY_COLLECTED, -1); - switch (randoItemId) { - case RI_MOLEHILL_BARGE: - ability_unlock(ABILITY_0_BARGE); - break; - case RI_MOLEHILL_BEAK_BOMB: - ability_unlock(ABILITY_1_BEAK_BOMB); - break; - case RI_MOLEHILL_BEAK_BUSTER: - ability_unlock(ABILITY_2_BEAK_BUSTER); - break; - case RI_MOLEHILL_CAMERA_CONTROL: - ability_unlock(ABILITY_3_CAMERA_CONTROL); - break; - case RI_MOLEHILL_CLAW_SWIPE: - ability_unlock(ABILITY_4_CLAW_SWIPE); - ability_unlock(ABILITY_C_ROLL); - ability_unlock(ABILITY_B_RATATAT_RAP); - break; - case RI_MOLEHILL_CLIMB: - ability_unlock(ABILITY_5_CLIMB); - break; - case RI_MOLEHILL_DIVE: - ability_unlock(ABILITY_F_DIVE); - break; - case RI_MOLEHILL_EGGS: - ability_unlock(ABILITY_6_EGGS); - item_adjustByDiffWithHud(ITEM_D_EGGS, 50); - break; - case RI_MOLEHILL_FLAP_FLIP: - ability_unlock(ABILITY_A_HOLD_A_JUMP_HIGHER); - ability_unlock(ABILITY_7_FEATHERY_FLAP); - ability_unlock(ABILITY_8_FLAP_FLIP); - break; - case RI_MOLEHILL_FLIGHT: - ability_unlock(ABILITY_9_FLIGHT); - item_adjustByDiffWithHud(ITEM_F_RED_FEATHER, 25); - break; - case RI_MOLEHILL_SHOCK_JUMP: - ability_unlock(ABILITY_D_SHOCK_JUMP); - break; - case RI_MOLEHILL_TALON_TROT: - ability_unlock(ABILITY_10_TALON_TROT); - break; - case RI_MOLEHILL_TURBO_TALON: - ability_unlock(ABILITY_11_TURBO_TALON); - break; - case RI_MOLEHILL_WADING_BOOTS: - ability_unlock(ABILITY_E_WADING_BOOTS); - break; - case RI_MOLEHILL_WONDERWING: - ability_unlock(ABILITY_12_WONDERWING); - item_adjustByDiffWithHud(ITEM_10_GOLD_FEATHER, 5); - break; - default: - break; - } - break; - case RITYPE_MUMBO_TOKEN: - func_8030E760((sfx_e)0x401, 1.0f, 0x7fff); - for (uint32_t i = MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA; - i <= MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL; i++) { - if ((sMumboTokenScore[(i - 1) / 8] & (1 << (i & 7))) == 0) { - mumboscore_set((mumbotoken_e)i, true); - break; - } - } - item_inc(ITEM_1C_MUMBO_TOKEN); - break; - case RITYPE_MUSIC_NOTE: - coMusicPlayer_playMusic(COMUSIC_9_NOTE_COLLECTED, 16000); - D_80385FF0[worldId]++; - if (worldId == map_getLevel(gsworld_getMap())) { - item_set(ITEM_C_NOTE, D_80385FF0[map_getLevel(gsworld_getMap())]); - } - break; - case RITYPE_SNS_EGG: - comusic_playTrack(COMUSIC_88_BIG_SNS_FANFARE); - FUNC_8030E624(SFX_114_BRICKWALL_BREAKING, 0.8f, 15000); - switch (randoItemId) { - case RI_STOP_N_SWOP_EGG_BLUE: - sns_set_item_and_update_payload(SNS_ITEM_EGG_BLUE, 0, 1); - break; - case RI_STOP_N_SWOP_EGG_CYAN: - sns_set_item_and_update_payload(SNS_ITEM_EGG_CYAN, 0, 1); - break; - case RI_STOP_N_SWOP_EGG_GREEN: - sns_set_item_and_update_payload(SNS_ITEM_EGG_GREEN, 0, 1); - break; - case RI_STOP_N_SWOP_EGG_PINK: - sns_set_item_and_update_payload(SNS_ITEM_EGG_PINK, 0, 1); - break; - case RI_STOP_N_SWOP_EGG_RED: - sns_set_item_and_update_payload(SNS_ITEM_EGG_RED, 0, 1); - break; - case RI_STOP_N_SWOP_EGG_YELLOW: - sns_set_item_and_update_payload(SNS_ITEM_EGG_YELLOW, 0, 1); - break; - } - break; - case RITYPE_SNS_KEY: - sns_set_item_and_update_payload(SNS_ITEM_ICE_KEY, 0, 1); - comusic_playTrack(COMUSIC_88_BIG_SNS_FANFARE); - break; - case RITYPE_AP_ITEM: - break; - default: - break; - } -} - -void ItemQueue::SendNotification(RandoItemId randoItemId) { - if (CVAR_SHOW_COLLISION_NOTIFICATIONS) { - RandoItemType itemType = Rando::StaticData::Items[randoItemId].randoItemType; - actor_e actorId = (actor_e)Rando::StaticData::Items[randoItemId].actorId; - std::string prefix = ""; - std::string message = Rando::StaticData::Items[randoItemId].name; - std::string suffix = ""; - ImVec4 itemColor = UIWidgets::ColorValues.at(itemColors[actorId]); - - if (itemType == RITYPE_MOLEHILL) { - prefix = "You learned"; - } else if (itemType == RITYPE_SNS_EGG || itemType == RITYPE_SNS_KEY) { - int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); - prefix = "You collected "; - prefix += Rando::StaticData::Items[randoItemId].article; - suffix = "("; - suffix += std::to_string(totalsnsItems); - suffix += " / 7)"; - - itemColor = UIWidgets::ColorValues.at(snsColors[randoItemId]); - } else { - prefix = "You collected "; - prefix += Rando::StaticData::Items[randoItemId].article; - } - - Notification::Emit({ - .prefix = prefix, - .prefixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), - .message = message, - .messageColor = itemColor, - .suffix = suffix, - .suffixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), - }); - } -} - -void ItemQueue::Clear() { - while (!itemQueue.empty()) { - itemQueue.pop(); - } -} - -void ItemQueue::AddCheck(RandoCheckId randoCheckId) { - RANDO_SAVE_CHECKS[randoCheckId].eligible = true; - itemQueue.push(randoCheckId); -} - -void RegisterItemQueue() { - COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { ItemQueue::Process(); }); - - COND_HOOK(OnSaveFileLoad, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { ItemQueue::Clear(); }); -} - -static RegisterShipInitFunc initFunc(RegisterItemQueue, { "IS_RANDO" }); diff --git a/src/port/Rando/ItemQueue.h b/src/port/Rando/ItemQueue.h deleted file mode 100644 index 0e526b04d..000000000 --- a/src/port/Rando/ItemQueue.h +++ /dev/null @@ -1,10 +0,0 @@ -#include "port/Rando/Rando.h" - -class ItemQueue { -public: - static void Process(); - static void Clear(); - static void GiveItem(RandoItemId randoItemId); - static void SendNotification(RandoItemId randoItemId); - static void AddCheck(RandoCheckId randoCheckId); -}; diff --git a/src/port/Rando/LighthouseMenuRando.cpp b/src/port/Rando/LighthouseMenuRando.cpp index 8c654a44d..0a5a8117a 100644 --- a/src/port/Rando/LighthouseMenuRando.cpp +++ b/src/port/Rando/LighthouseMenuRando.cpp @@ -7,11 +7,12 @@ #include "port/Rando/CustomObject/CustomObject.h" #include "port/Rando/Logic/Logic.h" -#include "port/Rando/Spoiler/Spoiler.h" #include +extern "C" { #include "variables.h" +} const char* logicModes[2] = { "Glitchless", @@ -60,38 +61,6 @@ void LighthouseMenu::AddMenuRando() { } UIWidgets::PopStyleCombobox(); }); - AddWidget(path, "Load Existing Spoiler Log", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_RANDOMIZER_SETTING("UseExistingLog")) - .RaceDisable(false) - .Options(CheckboxOptions().Tooltip("Uses a Spoiler Log in the randomizer folder.")); - AddWidget(path, "Available Spoiler Logs", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { - std::vector spoilerLogPtrs; - spoilerLogPtrs.reserve(Rando::Spoiler::spoilerLogs.size()); - for (const auto& log : Rando::Spoiler::spoilerLogs) { - spoilerLogPtrs.push_back(log.c_str()); - } - - ImGui::BeginDisabled(!CVarGetInteger(CVAR_RANDOMIZER_SETTING("UseExistingLog"), 0)); - if (UIWidgets::CVarCombobox("Seed", CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), spoilerLogPtrs, - { .labelPosition = UIWidgets::LabelPositions::None, .color = WIDGET_COLOR })) { - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), 0) == 0) { - CVarSetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), ""); - } else { - std::string spoilerName = - Rando::Spoiler::spoilerLogs[CVarGetInteger(CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), 0)]; - CVarSetString("gRandoSettings.SpoilerFile", spoilerName.c_str()); - } - } - ImGui::SameLine(); - if (UIWidgets::Button(ICON_FA_REFRESH, UIWidgets::ButtonOptions() - .Color(WIDGET_COLOR) - .Size(ImVec2(32.0f, 32.0f)) - .Tooltip("Refreshes the list of Spoiler Logs."))) { - Rando::Spoiler::RefreshSpoilerLogs(); - } - ImGui::EndDisabled(); - }); - AddWidget(path, "Send Collection Notifications", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_RANDOMIZER_SETTING("RandoNotifications")) .Options(CheckboxOptions().Tooltip("Sends notifications when you collect a Rando Item.")); @@ -268,6 +237,36 @@ void LighthouseMenu::AddMenuRando() { } }); + // Rando - Junk Options + AddSidebarEntry("Rando", "Junk Options", 1); + path = { "Rando", "Junk Options", SECTION_COLUMN_1 }; + + AddWidget(path, "Enable Junk", WIDGET_SEPARATOR_TEXT); + + AddWidget(path, "Spawn Junk For Obtained Checks", WIDGET_CVAR_CHECKBOX) + .CVar(Rando::StaticData::Options[RO_SPAWN_JUNK].cvar) + .Options(CheckboxOptions().Tooltip("Spawns a junk item in place of an object that has already been collected.")) + .Callback([](WidgetInfo& info) { UpdateJunkList(); }); + + AddWidget(path, "Junk Selection", WIDGET_SEPARATOR_TEXT); + + AddWidget(path, "Honeycomb Refills", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_RANDOMIZER_SETTING("Junk.HealthRefill")) + .Options(CheckboxOptions().Tooltip("Adds Health Refills to the Junk List.")) + .Callback([](WidgetInfo& info) { UpdateJunkList(); }); + AddWidget(path, "Blue Eggs", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_RANDOMIZER_SETTING("Junk.BlueEggs")) + .Options(CheckboxOptions().Tooltip("Adds Blue Eggs to the Junk List.")) + .Callback([](WidgetInfo& info) { UpdateJunkList(); }); + AddWidget(path, "Red Feathers", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_RANDOMIZER_SETTING("Junk.RedFeathers")) + .Options(CheckboxOptions().Tooltip("Adds Red Feathers to the Junk List.")) + .Callback([](WidgetInfo& info) { UpdateJunkList(); }); + AddWidget(path, "Gold Feathers", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_RANDOMIZER_SETTING("Junk.GoldFeathers")) + .Options(CheckboxOptions().Tooltip("Adds Gold Feathers to the Junk List.")) + .Callback([](WidgetInfo& info) { UpdateJunkList(); }); + // Rando - Check Tracker path.sidebarName = "Check Tracker"; AddSidebarEntry("Rando", path.sidebarName, 1); diff --git a/src/port/Rando/Logic/GeneratePools.cpp b/src/port/Rando/Logic/GeneratePools.cpp index f6eace65e..64aca987e 100644 --- a/src/port/Rando/Logic/GeneratePools.cpp +++ b/src/port/Rando/Logic/GeneratePools.cpp @@ -130,7 +130,7 @@ void GenerateShufflePool(SaveData* saveData) { .randoItemId = Rando::StaticData::Checks[std::get<2>(itemPool[i])].randoItemId, .randoCollectionId = std::get<1>(itemPool[i]), .isShuffled = checkPool[i] == RC_UNKNOWN ? false : true, - .eligible = false, + .obtained = false, .skipped = false, }; @@ -146,7 +146,7 @@ void GenerateShufflePool(SaveData* saveData) { .randoItemId = Rando::StaticData::Checks[std::get<2>(abilityItemPool[a])].randoItemId, .randoCollectionId = std::get<1>(abilityItemPool[a]), .isShuffled = true, - .eligible = false, + .obtained = false, .skipped = false, }; @@ -177,8 +177,7 @@ void GeneratePoolFromSaveData(SaveData* saveData) { .randoItemId = randoSaveCheck.randoItemId, .randoCollectionId = randoSaveCheck.randoCollectionId, .isShuffled = randoSaveCheck.isShuffled, - .eligible = randoSaveCheck.eligible, - .received = randoSaveCheck.received, + .obtained = randoSaveCheck.obtained, .skipped = randoSaveCheck.skipped, }; diff --git a/src/port/Rando/Logic/GenerateSaveData.cpp b/src/port/Rando/Logic/GenerateSaveData.cpp index 2106f2302..3361ce00a 100644 --- a/src/port/Rando/Logic/GenerateSaveData.cpp +++ b/src/port/Rando/Logic/GenerateSaveData.cpp @@ -8,9 +8,11 @@ #include "port/Save/Types.h" extern "C" { +void ability_setLearned(s32 move, s32 val); void ability_setHasUsed(enum ability_e move); void item_setMaxCount(s32 item); +void fileProgressFlag_set(enum file_progress_e index, s32 set); } // clang-format off @@ -126,7 +128,7 @@ void Rando::Logic::InitializeSaveData(SaveData* saveData) { // .randoItemId = Rando::StaticData::GetRandoItemByActorId((actor_e)randoStaticCheck.actorId), .randoCollectionId = randoStaticCheck.collectionId, .isShuffled = false, - .eligible = false, + .obtained = false, .skipped = false, }; @@ -148,7 +150,7 @@ void Rando::Logic::InitializeSaveData(SaveData* saveData) { } void Rando::Logic::GenerateSaveData(SaveData* saveData) { - for (auto& object : RANDO_SAVE_CHECKS) { + for (auto& object : Rando::Logic::shuffledPool) { saveData->shipSaveData.randoSaveData.randoSaveCheck[object.randoCheckId] = object; } @@ -170,30 +172,21 @@ void Rando::Logic::GrantStartingLoadout() { item_setMaxCount(item); } } -} -void Rando::Logic::GrantFileProgressFlags() { + // Set progress flag for tutorial dialogue, skipping them for (auto& fileprog : progressLoadout) { fileProgressFlag_set(fileprog, 1); } -} -void Rando::Logic::GrantSpiralMountainChecks() { - if (!CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.SkipSMTutorial"), 0)) { - return; - } + if (CVarGetInteger(CVAR_ENHANCEMENT("Gameplay.SkipSMTutorial"), 0)) { + for (auto& smCheckId : smRandoCheckIdList) { + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[smCheckId]; - for (auto& smCheckId : smRandoCheckIdList) { - RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[smCheckId]; - - if (!randoSaveCheck.isShuffled) { - continue; - } + if (!randoSaveCheck.isShuffled) { + continue; + } - CustomObject::CheckObtainedEX(smCheckId, true); - if (Rando::StaticData::Items[randoSaveCheck.randoItemId].randoItemType == RITYPE_MOLEHILL) { - ability_setLearned((ability_e)randoSaveCheck.randoCollectionId, true); - ability_setHasUsed((ability_e)randoSaveCheck.randoCollectionId); + CustomObject::CheckObtainedEX(smCheckId, true); } } } \ No newline at end of file diff --git a/src/port/Rando/Logic/GlitchlessLogic.cpp b/src/port/Rando/Logic/GlitchlessLogic.cpp index 75390a401..495a9df96 100644 --- a/src/port/Rando/Logic/GlitchlessLogic.cpp +++ b/src/port/Rando/Logic/GlitchlessLogic.cpp @@ -241,9 +241,7 @@ void PopulateJinjoCheckIds() { } void ResetSaveData() { - // [port] `data` is the 112-byte vanilla payload, not the whole SaveData, which is - // ~43 KB once shipSaveData (rando checks, note/jinjo retention) is counted. - for (size_t s = 0; s < sizeof(gameFile_saveData[selectedFileNum].data); s++) { + for (int s = 0; s < sizeof(SaveData); s++) { gameFile_saveData[selectedFileNum].data[s] = 0; } @@ -383,6 +381,13 @@ void GenerateGlitchlessLogicPool(std::vector& checkPool, PlacedItemCounts placedItems = { .noteCount = 0, .jiggyCount = 0, .mumboTokenCount = 0 }; PlacedCheckObject placedCheckItems[RC_MAX] = {}; + for (auto& shuffledCheck : checkPool) { + reachableChecks[shuffledCheck].isShuffled = true; + } + for (auto& shuffledAbiity : abilityCheckPool) { + reachableChecks[shuffledAbiity].isShuffled = true; + } + if (CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_JINJOS].cvar, 0) == RO_GENERIC_ON) { PopulateJinjoCheckIds(); } @@ -398,46 +403,23 @@ void GenerateGlitchlessLogicPool(std::vector& checkPool, reachableChecks[checkId].name = checkData.name; reachableChecks[checkId].canAccess = false; reachableChecks[checkId].isFilled = false; - reachableChecks[checkId].isShuffled = false; - } - - for (auto& shuffledCheck : checkPool) { - reachableChecks[shuffledCheck].isShuffled = true; - } - for (auto& shuffledAbiity : abilityCheckPool) { - reachableChecks[shuffledAbiity].isShuffled = true; } // Starting Initialization reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess = true; Rando::Logic::GrantStartingLoadout(); for (auto& [ability, abilityInfo] : abilityLoadoutMap) { - if (!CVarGetInteger(abilityInfo.second, 0)) { - continue; - } - - RandoCheckId abilityCheck = Rando::StaticData::GetCheckByAbilityId(ability); - - auto it = std::find(abilityCheckPool.begin(), abilityCheckPool.end(), abilityCheck); - if (it == abilityCheckPool.end()) { - continue; - } - - abilityCheckPool.erase(it); - - // The molehill left the pool, so it has to stop being a valid placement target as well. - reachableChecks[abilityCheck].isShuffled = false; - - // The player already owns this ability, so its item leaves the pool alongside the molehill. - auto item = std::find_if(abilityItemPool.begin(), abilityItemPool.end(), - [&](const std::tuple& abilityItem) { - return std::get<1>(abilityItem) == (int32_t)ability; - }); - if (item != abilityItemPool.end()) { - abilityItemPool.erase(item); + if (CVarGetInteger(abilityInfo.second, 0)) { + RandoCheckId abilityCheck = Rando::StaticData::GetCheckByAbilityId(ability); + + auto it = std::find(abilityCheckPool.begin(), abilityCheckPool.end(), abilityCheck); + if (it != abilityCheckPool.end()) { + abilityCheckPool.erase(it); + UpdateAccessibility(RR_SPIRAL_MOUNTAIN_ENTRANCE, + reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess); + continue; + } } - - UpdateAccessibility(RR_SPIRAL_MOUNTAIN_ENTRANCE, reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess); } UpdateAccessibility(RR_SPIRAL_MOUNTAIN_ENTRANCE, reachableRegions[RR_SPIRAL_MOUNTAIN_ENTRANCE].canAccess); diff --git a/src/port/Rando/Logic/Logic.h b/src/port/Rando/Logic/Logic.h index bed9f239a..964235b66 100644 --- a/src/port/Rando/Logic/Logic.h +++ b/src/port/Rando/Logic/Logic.h @@ -6,21 +6,32 @@ #include -#include "functions.h" extern "C" { -// Decomp functions that functions.h does not declare (defined in smbottles.c, -// mumbo_transforms.c and jigsawpicture.c respectively). +void item_set(s32 item, s32 val); +void item_adjustByDiffWithoutHud(enum item_e item, s32 diff); +s32 item_getCount(enum item_e item); +void itemscore_noteScores_clear(void); + +void ability_unlock(enum ability_e); +int ability_isUnlocked(enum ability_e uid); +void ability_setLearned(s32 move, s32 val); void __chSmBottles_skipIntroTutorial(void); + +void fileProgressFlag_set(enum file_progress_e index, s32 set); +bool fileProgressFlag_get(enum file_progress_e index); s32 __transformation_getCost(enum transformation_e trans_id); s32 _puzzleCost(s32 index); + +u32 player_getTransformation(void); + +enum level_e map_getLevel(enum map_e map); +enum map_e gsworld_getMap(void); } extern int32_t randoFinalSeed; extern std::map> abilityLoadoutMap; extern std::map> itemLoadoutMap; -extern std::vector progressLoadout; -extern std::vector smRandoCheckIdList; extern Rando::StaticData::RandoLogicData reachableRegions[RR_MAX]; extern Rando::StaticData::RandoLogicData reachableEvents[RA_MAX]; @@ -56,17 +67,20 @@ void GeneratePoolFromSaveData(SaveData* saveData); void InitializeSaveData(SaveData* saveData); void GenerateSaveData(SaveData* saveData); void GrantStartingLoadout(); -void GrantFileProgressFlags(); -void GrantSpiralMountainChecks(); void RefreshReachableRegions(); inline bool IsCheckShuffled(RandoCheckId randoCheckId) { - return RANDO_SAVE_CHECKS[randoCheckId].isShuffled; -} + bool isShuffled = false; -inline bool IsCheckObtained(RandoCheckId randoCheckId) { - return RANDO_SAVE_CHECKS[randoCheckId].eligible; + for (auto& object : shuffledPool) { + if (object.randoCheckId == randoCheckId) { + isShuffled = object.isShuffled; + break; + } + } + + return isShuffled; } inline RandoSaveCheck GetShuffledObject(RandoCheckId randoCheckId) { @@ -87,12 +101,25 @@ inline RandoSaveCheck GetShuffledObject(RandoCheckId randoCheckId) { return shuffledObject; } +inline bool IsCheckObtained(RandoCheckId randoCheckId) { + bool isObtained = false; + + for (auto& object : shuffledPool) { + if (object.randoCheckId == randoCheckId) { + isObtained = object.obtained; + break; + } + } + + return isObtained; +} + inline bool ShouldSpawnJinjoJiggy(int16_t levelId) { bool shouldSpawn = false; int16_t jinjoCount = 0; for (auto& location : Rando::Logic::shuffledPool) { - if (!location.eligible) { + if (!location.obtained) { continue; } @@ -118,7 +145,7 @@ inline int32_t GetTotalSnsItemsCollected() { int32_t snsCount = 0; for (auto& location : Rando::Logic::shuffledPool) { - if (!location.eligible) { + if (!location.obtained) { continue; } @@ -224,9 +251,7 @@ inline bool CanOpenWorld(level_e levelId) { return true; } - // [port] index 9 is the Door of Grunty picture; 25 is only its vanilla cost, and a - // romhack can change it like any other. - int32_t puzzleCost = levelId == LEVEL_6_LAIR ? _puzzleCost(9) : _puzzleCost(levelNum - 1); + int32_t puzzleCost = levelId == LEVEL_6_LAIR ? 25 : _puzzleCost(levelNum - 1); int32_t jiggyCount = item_getCount(ITEM_E_JIGGY); if (jiggyCount >= puzzleCost) { @@ -339,8 +364,6 @@ inline bool CanKillEnemy(actor_e enemyType) { canKillEnemy = true; } break; - default: - break; } return canKillEnemy; diff --git a/src/port/Rando/MiscBehavior/OnFileLoad.cpp b/src/port/Rando/MiscBehavior/OnFileLoad.cpp index 12100a6d0..e8d8161f9 100644 --- a/src/port/Rando/MiscBehavior/OnFileLoad.cpp +++ b/src/port/Rando/MiscBehavior/OnFileLoad.cpp @@ -1,7 +1,5 @@ #include "MiscBehavior.h" #include -#include "src/port/ShipInit.hpp" -#include "ship/Context.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/UI/Notification.h" @@ -9,8 +7,8 @@ #include "port/UI/cvar_prefixes.h" #include "port/Rando/Logic/Logic.h" -#include "port/Rando/Spoiler/Spoiler.h" #include "port/Rando/CheckTracker/CheckTracker.h" +// #include "port/Rando/Spoiler/Spoiler.h" extern "C" { enum map_e gsworld_getMap(void); @@ -23,8 +21,6 @@ void Rando::MiscBehavior::OnFileLoad() { Rando::Logic::shuffledPool.clear(); }); - REGISTER_LISTENER(OnGameStart, EVENT_PRIORITY_NORMAL, [](IEvent* event) { ShipInit::Init("IS_RANDO"); }); - REGISTER_LISTENER(OnSaveLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnSaveLoad* ev = (OnSaveLoad*)event; SaveData* saveData = (SaveData*)ev->saveData; @@ -34,34 +30,21 @@ void Rando::MiscBehavior::OnFileLoad() { if (saveData->magic != 0) { if (saveData->shipSaveData.fileType == FILE_TYPE_SAVE_RANDO) { Rando::Logic::GeneratePoolFromSaveData(saveData); + CALL_EVENT(InitRandoEvents); } return; } if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Enable"), 0)) { Rando::Logic::InitializeSaveData(saveData); - std::string spoilerPath = CVarGetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), ""); - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("UseExistingLog"), 0) && !spoilerPath.empty()) { - // std::string spoilerPath = CVarGetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), ""); - Rando::Spoiler::GenerateFromSpoiler(Rando::Spoiler::LoadFromFile(spoilerPath.c_str())); - } else { - Rando::Logic::GenerateShufflePool(saveData); - Rando::Logic::GrantStartingLoadout(); - Rando::Logic::GrantFileProgressFlags(); - Rando::Logic::GrantSpiralMountainChecks(); - std::string spoilerName = std::to_string(saveData->shipSaveData.randoSaveData.seedId).c_str(); - std::erase(spoilerName, '-'); - spoilerName += ".json"; - Rando::Spoiler::SaveToFile(spoilerName, Rando::Spoiler::GenerateFromPoolGeneration()); - } - + Rando::Logic::GenerateShufflePool(saveData); + Rando::Logic::GrantStartingLoadout(); saveData->shipSaveData.fileType = FILE_TYPE_SAVE_RANDO; saveData->shipSaveData.fileCreatedAt = GetUnixTimestamp(); + CALL_EVENT(InitRandoEvents); } }); - REGISTER_LISTENER(OnGameStart, EVENT_PRIORITY_NORMAL, [](IEvent* event) { CALL_EVENT(InitRandoEvents); }); - REGISTER_LISTENER(OnLoadFileSelect, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnLoadFileSelect* ev = (OnLoadFileSelect*)event; diff --git a/src/port/Rando/MiscBehavior/WorldState.cpp b/src/port/Rando/MiscBehavior/WorldState.cpp index e42d8c144..ab26bea2a 100644 --- a/src/port/Rando/MiscBehavior/WorldState.cpp +++ b/src/port/Rando/MiscBehavior/WorldState.cpp @@ -5,7 +5,17 @@ #include "spdlog/spdlog.h" #include "enums.h" -#include "functions.h" +extern "C" { +s32 getGameMode(void); +void mapSpecificFlags_set(s32 i, s32 val); +s32 mapSpecificFlags_get(s32 i); + +enum map_e gsworld_getMap(void); +enum level_e map_getLevel(enum map_e map); + +Struct70s* func_8034C5AC(s32 arg0); +void func_8034E71C(Struct73s* arg0, s32 arg1, f32 arg2); +} // These read per-file save data, so they must not be evaluated before a file is selected. #define EMPTY_HONEYCOMB_OPTION_ENABLED \ @@ -31,8 +41,8 @@ void Rando::StaticData::ModifyRandoInfFlagState(RandoCheckId randoCheckId) { break; case RC_GV_JIGGY_WATER_PYRAMID: case RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_WATER_PYRAMID].eligible && - RANDO_SAVE_CHECKS[RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID].eligible) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_WATER_PYRAMID].obtained && + RANDO_SAVE_CHECKS[RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID].obtained) { randoInfFlag = RANDO_INF_WATER_PYRAMID_DRAINED; } break; @@ -96,18 +106,18 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { switch (currentLevel) { case LEVEL_1_MUMBOS_MOUNTAIN: - if (RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible) { + if (RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained) { if (ev->actorId == ACTOR_F_CHIMPY) { event->Cancelled = true; ev->result = NULL; } } mapSpecificFlags_set(MM_SPECIFIC_FLAG_0_CHIMPY_STUMP_RAISED, - RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible); + RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained); mapSpecificFlags_set(MM_SPECIFIC_FLAG_2_ORANGE_HAS_BEEN_RETURNED, - RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible); + RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained); mapSpecificFlags_set(MM_SPECIFIC_FLAG_3_CHIMPY_HAS_LEFT, - RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].eligible); + RANDO_SAVE_CHECKS[RC_MM_JIGGY_CHIMPY].obtained); break; case LEVEL_3_CLANKERS_CAVERN: if (currentMap == MAP_22_CC_INSIDE_CLANKER && @@ -117,11 +127,11 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { break; case LEVEL_9_RUSTY_BUCKET_BAY: if (ev->actorId == 0x18F) { - mapSpecificFlags_set(0, RANDO_SAVE_CHECKS[RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE].eligible); + mapSpecificFlags_set(0, RANDO_SAVE_CHECKS[RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE].obtained); } break; case LEVEL_A_MAD_MONSTER_MANSION: - if (ev->actorId == ACTOR_39_NAPPER && RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].eligible) { + if (ev->actorId == ACTOR_39_NAPPER && RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].obtained) { event->Cancelled = true; ev->result = NULL; } @@ -155,7 +165,7 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (currentMap == MAP_26_MMM_NAPPERS_ROOM && randoSaveCheck.randoCheckId != RC_MMM_JIGGY_MANSION_TABLE) { event->Cancelled = true; - ev->result = RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].eligible; + ev->result = RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].obtained; break; } } @@ -169,20 +179,13 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (ev->jiggyId == JIGGY_2E_FP_PRESENTS) { if (currenLevel == LEVEL_5_FREEZEEZY_PEAK) { event->Cancelled = true; - ev->result = RANDO_SAVE_CHECKS[RC_FP_JIGGY_IGLOO].eligible; - break; - } - } - if (ev->jiggyId == JIGGY_37_LAIR_BGS_WITCH_SWITCH) { - if (currenLevel == LEVEL_6_LAIR) { - event->Cancelled = true; - ev->result = RANDO_SAVE_CHECKS[RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP].eligible; + ev->result = RANDO_SAVE_CHECKS[RC_FP_JIGGY_IGLOO].obtained; break; } } event->Cancelled = true; - ev->result = randoSaveCheck.eligible; + ev->result = randoSaveCheck.obtained; break; } } @@ -202,29 +205,13 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (randoCheckId == RC_MMM_JIGGY_TUMBLARS_PUZZLE) { ev->result = mapSpecificFlags_get(MMM_SPECIFIC_FLAG_TUMBLAR_BROKEN); } else if (randoCheckId == RC_CC_JIGGY_CLANKER_RAISED) { - // Clanker's height and his rings' water level are both recalled from - // this query, so it has to answer for the world event and not just - // for a reward still sitting in the level. - ev->result = RANDO_SAVE_FLAGS[RANDO_INF_CLANKER_RAISED].flagState || - CustomObject::CheckSpawnedIdList(randoCheckId); - } else if (randoCheckId == RC_CC_JIGGY_RINGS) { - ev->result = RANDO_SAVE_FLAGS[RANDO_INF_MINIGAME_RINGS_COMPLETED].flagState || - CustomObject::CheckSpawnedIdList(randoCheckId); + ev->result = RANDO_SAVE_FLAGS[RANDO_INF_CLANKER_RAISED].flagState; } else { - ev->result = CustomObject::CheckSpawnedIdList(randoCheckId) || RANDO_SAVE_CHECKS[randoCheckId].eligible; + ev->result = CustomObject::CheckSpawnedIdList(randoCheckId); } } }) - // Drop the id-keyed requirement for the MMM floorboard honeycomb (marker.c) - COND_VB_SHOULD(VB_HONEYCOMB_PUMPKIN_REQUIREMENT, EVENT_PRIORITY_NORMAL, true, { - (void)args; - if (!IS_RANDO || !EMPTY_HONEYCOMB_OPTION_ENABLED) { - return; - } - *should = false; - }) - REGISTER_LISTENER(OnIsHoneycombScoreCollected, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnIsHoneycombScoreCollected* ev = (OnIsHoneycombScoreCollected*)event; @@ -249,7 +236,7 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (ev->honeycombId == HONEYCOMB_17_SM_COLLIWOBBLE) { ev->result = false; } else { - ev->result = saveCheck.eligible; + ev->result = saveCheck.obtained; } break; @@ -277,7 +264,7 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { if (saveCheck.randoCollectionId == ev->tokenId) { event->Cancelled = true; - ev->result = saveCheck.eligible; + ev->result = saveCheck.obtained; break; } } diff --git a/src/port/Rando/ObjectBehavior/BlueEgg.cpp b/src/port/Rando/ObjectBehavior/BlueEgg.cpp deleted file mode 100644 index 7d55692d7..000000000 --- a/src/port/Rando/ObjectBehavior/BlueEgg.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_BLUE_EGGS].optionValue - -bool OverrideBlueEggSpawn(s16 spawnPosition[3], int32_t propAsset) { - if (propAsset != ASSET_6D7_SPRITE_BLUE_EGGS) { - return false; - } - - s32 position[3] = { spawnPosition[0], spawnPosition[1], spawnPosition[2] }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); - - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } - - // Let vanilla blue eggs spawn after check has been obtained. - if (Rando::Logic::IsCheckObtained(randoCheckId)) { - return false; - } - - CustomCollectible::QueueProp(position, randoCheckId); - return true; -} - -void RegisterRandoBlueEggs() { - COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { - s16* spawnPosition = va_arg(args, s16*); - int32_t propAsset = va_arg(args, int32_t); - bool replaceEgg = OverrideBlueEggSpawn(spawnPosition, propAsset); - if (replaceEgg) { - *should = true; - } - }); -} - -static RegisterShipInitFunc initFunc(RegisterRandoBlueEggs, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Boggy.cpp b/src/port/Rando/ObjectBehavior/Boggy.cpp index 613d96c15..8634b420b 100644 --- a/src/port/Rando/ObjectBehavior/Boggy.cpp +++ b/src/port/Rando/ObjectBehavior/Boggy.cpp @@ -20,7 +20,7 @@ void Rando::ObjectBehavior::ModifyBoggyBehavior(void* boggyActor) { switch (actor->actor_info->actorId) { case ACTOR_160_BOGGY_1: case ACTOR_181_SCARF_SLED: - if (RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].eligible) { + if (RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].obtained) { marker_despawn(actor->marker); if (actor->actor_info->actorId == ACTOR_160_BOGGY_1) { func_80387760(actor->marker); @@ -28,12 +28,12 @@ void Rando::ObjectBehavior::ModifyBoggyBehavior(void* boggyActor) { } break; case ACTOR_C8_BOGGY_2: - if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].eligible) { + if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_SLED_TO_BOGGY].obtained) { marker_despawn(actor->marker); } break; case 0x33D: - if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_BOGGY_RACE_2].eligible) { + if (!RANDO_SAVE_CHECKS[RC_FP_JIGGY_BOGGY_RACE_2].obtained) { marker_despawn(actor->marker); } break; diff --git a/src/port/Rando/ObjectBehavior/Bundle.cpp b/src/port/Rando/ObjectBehavior/Bundle.cpp index 739359c51..6f7806343 100644 --- a/src/port/Rando/ObjectBehavior/Bundle.cpp +++ b/src/port/Rando/ObjectBehavior/Bundle.cpp @@ -1,551 +1,572 @@ #include "ObjectBehavior.h" #include "port/Rando/Logic/Logic.h" #include "port/Rando/CustomObject/CustomObject.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/ShipInit.hpp" -#include "port/Rando/CustomCollectible/CustomCollectible.h" +#include +#include "port/UI/cvar_prefixes.h" +#include +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "spdlog/spdlog.h" extern "C" { extern f32 gBundle_yaw; + bool fileProgressFlag_get(enum file_progress_e index); +void marker_despawn(ActorMarker* marker); } -typedef struct { - RandoCheckId randoCheckId; - bool customPhysics; -} RandoBundleInfo; - +bool applyCustomPhysics = false; +std::vector bundleDespawnQueue; int32_t vileCount = 0; -RandoBundleInfo IdentifyBundle(bundle_e bundleId, BundleInfo* bundleInfo, s32 bundleCount, f32 spawnPosition[3]) { - map_e currentMap = gsworld_getMap(); - level_e currentLevel = map_getLevel(currentMap); - s32 position[3] = { (int32_t)spawnPosition[0], (int32_t)spawnPosition[1], (int32_t)spawnPosition[2] }; - RandoBundleInfo randoBundleInfo; - randoBundleInfo.randoCheckId = RC_UNKNOWN; - randoBundleInfo.customPhysics = false; - - switch (currentLevel) { - case LEVEL_1_MUMBOS_MOUNTAIN: - switch (bundleId) { - case BUNDLE_0_MM_HUT_MUSIC_NOTE: - randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_MM_NOTE_HUT_BUNDLE_1 + bundleCount); - randoBundleInfo.customPhysics = true; - break; - case BUNDLE_1_MM_HUT_BLUE_EGG: - randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_MM_BLUE_EGG_HUT_BUNDLE_1 + bundleCount); - randoBundleInfo.customPhysics = true; - break; - case BUNDLE_3_MM_HUT_JINJO_GREEN: - randoBundleInfo.randoCheckId = RC_MM_JINJO_GREEN; - randoBundleInfo.customPhysics = true; - break; - case BUNDLE_4_MM_HUT_JIGGY: - if (position[1] < 2000) { - randoBundleInfo.randoCheckId = RC_MM_JIGGY_ORANGE_PADS; - } else { - randoBundleInfo.randoCheckId = RC_MM_JIGGY_HUTS; - randoBundleInfo.customPhysics = true; - } - break; - case BUNDLE_6_MM_HUT_EXTRA_LIFE: - randoBundleInfo.randoCheckId = RC_MM_EXTRA_LIFE_HUT; - randoBundleInfo.customPhysics = true; - break; - case BUNDLE_7__JIGGY: - randoBundleInfo.randoCheckId = RC_MM_JIGGY_CHIMPY; - break; - case BUNDLE_10__JIGGY: - randoBundleInfo.randoCheckId = RC_MM_JIGGY_JUJU; - break; - case BUNDLE_15__JIGGY: - randoBundleInfo.randoCheckId = RC_MM_JIGGY_CONGA; - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 400) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1 + bundleCount); - } else { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_2_TREASURE_TROVE_COVE: - switch (bundleId) { - case BUNDLE_4_MM_HUT_JIGGY: - randoBundleInfo.randoCheckId = RC_TTC_JIGGY_RED_X; - break; - case BUNDLE_7__JIGGY: - randoBundleInfo.randoCheckId = RC_TTC_JIGGY_BLUBBER; - break; - default: - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 900 && position[1] > 890) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1 + bundleCount); - } else if (position[1] < 1770 && position[1] > 1765) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1 + bundleCount); - } else if (position[1] < 1910 && position[1] > 1905) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1 + bundleCount); - } else if (position[1] < 875 && position[1] > 870) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1 + bundleCount); - } - break; - } - break; - case LEVEL_3_CLANKERS_CAVERN: - switch (bundleId) { - case BUNDLE_10__JIGGY: - switch (position[1]) { - case 1536: - randoBundleInfo.randoCheckId = RC_CC_JIGGY_TOOTH; - break; - default: - randoBundleInfo.randoCheckId = RC_CC_JIGGY_RINGS; - break; - } - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 1405 && position[1] > 1395) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1 + bundleCount); - } else if (position[1] < 5495 && position[1] > 5490) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1 + bundleCount); - } else if (position[1] < 3820 && position[1] > 3810) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_4_BUBBLEGLOOP_SWAMP: - switch (bundleId) { - case BUNDLE_6_MM_HUT_EXTRA_LIFE: - randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_BGS_EXTRA_LIFE_MR_VILE_1 + vileCount); - vileCount++; - randoBundleInfo.customPhysics = true; - if (vileCount >= 3) { - vileCount = 0; - } - break; - case BUNDLE_7__JIGGY: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_CROCTUS; - break; - case BUNDLE_8__JIGGY: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_MR_VILE; - break; - case BUNDLE_9__JIGGY: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_TANKTUP; - break; - case BUNDLE_B_BGS_HUT_MUSIC_NOTE: - randoBundleInfo.randoCheckId = (RandoCheckId)((int32_t)RC_BGS_NOTE_HUT_BUNDLE_1 + bundleCount); - break; - case BUNDLE_C_BGS_HUT_JIGGY: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_HUTS; - break; - case BUNDLE_10__JIGGY: - switch (position[2]) { - case 49: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_ELEVATED_WALKWAY; - break; - case -1386: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_FLIBBITS; - break; - case 2799: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_PINKEGG; - break; - case -1020: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_TIPTUP; - break; - case -6148: - randoBundleInfo.randoCheckId = RC_BGS_JIGGY_MAZE; - break; - default: - break; - } - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 1260 && position[1] > 1250) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1 + bundleCount); - } else if (position[1] < 1160 && position[1] > 1150) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1 + bundleCount); - } else if (position[0] < 4390 && position[0] > 4385) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1 + bundleCount); - } else if (position[0] < 2565 && position[0] > 2560) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_5_FREEZEEZY_PEAK: - switch (bundleId) { - case BUNDLE_9__JIGGY: - randoBundleInfo.randoCheckId = RC_FP_JIGGY_SLED_TO_BOGGY; - break; - case BUNDLE_10__JIGGY: - if (position[1] > 1900) { - randoBundleInfo.randoCheckId = RC_FP_JIGGY_BOGGY_RACE_1; - } else if (position[1] < 850) { - randoBundleInfo.randoCheckId = RC_FP_JIGGY_WOZZA; - } - break; - case BUNDLE_7__JIGGY: - randoBundleInfo.randoCheckId = RC_FP_JIGGY_BOGGY_RACE_2; - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 820 && position[1] > 810) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1 + bundleCount); - } else if (position[1] < 590 && position[1] > 580) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1 + bundleCount); - } else if (position[1] < 1755 && position[1] > 1745) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1 + bundleCount); - } else if (position[1] < 5760 && position[1] > 5750) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_6_LAIR: - switch (bundleId) { - case BUNDLE_C_BGS_HUT_JIGGY: - if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN].posY) { - randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN; - break; - } - if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY].posY) { - randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY; - break; - } - if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD].posY) { - randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD; - break; - } - if (position[1] == Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN].posY) { - randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN; - break; - } - break; - case BUNDLE_10__JIGGY: - if (fileProgressFlag_get(FILEPROG_1A_TTC_WITCH_SWITCH_JIGGY_PRESSED) && - gsworld_getMap() == MAP_6D_GL_TTC_LOBBY) { - randoBundleInfo.randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE; - auto spawnTuple = Rando::StaticData::multiSpawnCheckMap.at(randoBundleInfo.randoCheckId); - position[0] = std::get<0>(spawnTuple); - position[1] = std::get<1>(spawnTuple); - position[2] = std::get<2>(spawnTuple); - } else { - randoBundleInfo.customPhysics = true; - randoBundleInfo.randoCheckId = - Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); - } - break; - case BUNDLE_18__HONEYCOMB: - switch (currentMap) { - case MAP_69_GL_MM_LOBBY: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1 + bundleCount); - break; - case MAP_6D_GL_TTC_LOBBY: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1 + bundleCount); - break; - case MAP_6F_GL_FP_LOBBY: - if (position[1] < 295 && position[1] > 285) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1 + - bundleCount); - } else if (position[1] < 255 && position[1] > 245) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1 + - bundleCount); - } - break; - case MAP_70_GL_CC_LOBBY: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1 + bundleCount); - break; - case MAP_71_GL_STATUE_ROOM: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1 + - bundleCount); - break; - case MAP_72_GL_BGS_LOBBY: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1 + bundleCount); - break; - case MAP_75_GL_MMM_LOBBY: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1 + bundleCount); - break; - case MAP_78_GL_RBB_AND_MMM_PUZZLE: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1 + bundleCount); - break; - case MAP_79_GL_CCW_LOBBY: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1 + bundleCount); - break; - } - break; - default: - break; - } - break; - case LEVEL_7_GOBIS_VALLEY: - switch (bundleId) { - case BUNDLE_10__JIGGY: - randoBundleInfo.randoCheckId = - Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); - break; - case BUNDLE_D__EMPTY_HONEYCOMB: - randoBundleInfo.randoCheckId = RC_GV_EMPTY_HONEYCOMB_GOBI; - break; - case BUNDLE_18__HONEYCOMB: - if (position[1] < 2990 && position[1] > 2980) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1 + bundleCount); - } else if (position[1] < 1990 && position[1] > 1980) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1 + bundleCount); - } else if (position[1] < 610 && position[1] > 600) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); - } - break; - default: - break; - } - break; - case LEVEL_8_CLICK_CLOCK_WOOD: - switch (bundleId) { - case BUNDLE_18__HONEYCOMB: - switch (currentMap) { - case MAP_40_CCW_HUB: - if (position[1] < 150 && position[1] > 140) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1 + - bundleCount); - } else if (position[1] < 160 && position[1] > 150) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1 + - bundleCount); - } - break; - case MAP_43_CCW_SPRING: - if (position[0] < 5 && position[0] > -5) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1 + - bundleCount); - } else if (position[0] < -1545 && position[0] > -1555) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1 + - bundleCount); - } else if (position[0] < 4345 && position[0] > 4340) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1 + - bundleCount); - } - break; - case MAP_44_CCW_SUMMER: - if (position[1] < -440 && position[1] > -450) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1 + - bundleCount); - } else if (position[1] < 160 && position[1] > 150) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1 + - bundleCount); - } else if (position[1] < 4580 && position[1] > 4570) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1 + - bundleCount); - } - break; - case MAP_45_CCW_AUTUMN: - if (position[1] < 1435 && position[1] > 1425) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1 + - bundleCount); - } else if (position[1] < 160 && position[1] > 150) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1 + - bundleCount); - } else if (position[1] < 4405 && position[1] > 4395) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1 + - bundleCount); - } - break; - case MAP_46_CCW_WINTER: - if (position[1] < 1060 && position[1] > 1050) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1 + - bundleCount); - } else if (position[1] < 4405 && position[1] > 4395) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1 + - bundleCount); - } - break; - case MAP_4D_CCW_WINTER_MUMBOS_SKULL: - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1 + - bundleCount); - break; - } - default: - break; - } - break; - case LEVEL_9_RUSTY_BUCKET_BAY: - switch (bundleId) { - case BUNDLE_6_MM_HUT_EXTRA_LIFE: - randoBundleInfo.randoCheckId = RC_RBB_EXTRA_LIFE_BOOM_BOXES; - randoBundleInfo.customPhysics = true; - break; - case BUNDLE_18__HONEYCOMB: - if (position[0] == 0 && position[1] == 156 && position[2] == 4800) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1 + bundleCount); - } else if (position[0] == 0 && position[1] == 156 && position[2] == -178) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1 + bundleCount); - } else if (position[0] == 7850 && position[1] == -1019 && position[2] == 3550) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1 + bundleCount); - } - break; - default: - break; - } - case LEVEL_A_MAD_MONSTER_MANSION: - switch (bundleId) { - case BUNDLE_18__HONEYCOMB: - switch (currentMap) { - case MAP_1C_MMM_CHURCH: - if (position[0] < 1880 && position[0] > 1870) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1 + - bundleCount); - } else if (position[0] < -1870 && position[0] > -1880) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1 + bundleCount); - } - break; - case MAP_1B_MMM_MAD_MONSTER_MANSION: - if (position[1] < 160 && position[1] > 150) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1 + bundleCount); - } else if (position[1] < 335 && position[1] > 325) { - randoBundleInfo.randoCheckId = - (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1 + bundleCount); - } - break; - default: - break; - } - break; - default: - break; - } - break; - case LEVEL_B_SPIRAL_MOUNTAIN: - switch (bundleId) { - case BUNDLE_1F_SM_EMPTY_HONEYCOMB: - if (position[1] >= 500 && position[1] <= 800) { - randoBundleInfo.randoCheckId = RC_SM_EMPTY_HONEYCOMB_COLLIWOBBLE; - } else { - randoBundleInfo.randoCheckId = RC_SM_EMPTY_HONEYCOMB_QUARRIES; - } - break; - case BUNDLE_18__HONEYCOMB: - break; - default: - break; - } - break; - default: - return randoBundleInfo; - } - - return randoBundleInfo; -} - -bool OverrideBundleSpawn(bundle_e bundleId, BundleInfo* bundleInfo, s32 bundleCount, f32 spawnPosition[3]) { - - s32 position[3] = { (int32_t)spawnPosition[0], (int32_t)spawnPosition[1], (int32_t)spawnPosition[2] }; - - if (bundleId == BUNDLE_16__HONEYCOMB && - (gsworld_getMap() == MAP_43_CCW_SPRING || gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN)) { - if (CheckEnemyOverlapPosition(position)) { - return false; - } - } - - RandoBundleInfo randoBundleInfo = IdentifyBundle(bundleId, bundleInfo, bundleCount, spawnPosition); - - if (randoBundleInfo.randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoBundleInfo.randoCheckId)) { - return false; +void Rando::ObjectBehavior::DespawnCollectedBundles() { + if (bundleDespawnQueue.empty()) { + return; } - if (Rando::Logic::IsCheckObtained(randoBundleInfo.randoCheckId)) { - bool isConsumable = bundleInfo->actor_id == ACTOR_52_BLUE_EGG || bundleInfo->actor_id == ACTOR_50_HONEYCOMB; - return !isConsumable; + for (auto& bundle : bundleDespawnQueue) { + marker_despawn(bundle); } - Actor* actor = CustomCollectible::Spawn(position, randoBundleInfo.randoCheckId); - if (randoBundleInfo.customPhysics) { - ApplyCustomActorPhysics(randoBundleInfo.randoCheckId, actor, false); - } else { - ApplyBundleActorPhysics(actor, bundleId, (BundleInfo*)bundleInfo, gBundle_yaw); - } - - return true; + bundleDespawnQueue.clear(); } -void RegisterRandoBundles() { +void Rando::ObjectBehavior::InitBundleBehavior() { + COND_HOOK(ClearBundleDespawnQueue, EVENT_PRIORITY_NORMAL, IS_RANDO, + [](IEvent* event) { bundleDespawnQueue.clear(); }) + COND_VB_SHOULD(VB_BUNDLE_SPAWN_SET_ACTOR_DATA, EVENT_PRIORITY_NORMAL, IS_RANDO, { Actor* refActor = va_arg(args, Actor*); + if (refActor == NULL) { *should = true; } - }); + }) COND_VB_SHOULD(VB_OVERRIDE_BUNDLE_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO, { bundle_e bundleId = (bundle_e)va_arg(args, int); BundleInfo* bundleInfo = va_arg(args, BundleInfo*); s32 bundleCount = va_arg(args, s32); f32* position = va_arg(args, f32*); + Actor** actor = va_arg(args, Actor**); - bool replaceBundle = OverrideBundleSpawn(bundleId, bundleInfo, bundleCount, position); - if (replaceBundle) { - *should = true; + map_e currentMap = gsworld_getMap(); + level_e currentLevel = map_getLevel(currentMap); + + int32_t spawnPosition[3]; + spawnPosition[0] = (int32_t)position[0]; + spawnPosition[1] = (int32_t)position[1]; + spawnPosition[2] = (int32_t)position[2]; + + SPDLOG_INFO("Bundle ID: {} :: {}, {}, {}", (int32_t)bundleId, spawnPosition[0], spawnPosition[1], spawnPosition[2]); + + if (bundleId == BUNDLE_16__HONEYCOMB && + (currentMap == MAP_43_CCW_SPRING || currentMap == MAP_B_CC_CLANKERS_CAVERN)) { + if (CheckEnemyOverlapPosition(spawnPosition)) { + *should = false; + return; + } } - }); -} -static RegisterShipInitFunc initFunc(RegisterRandoBundles, { "IS_RANDO" }); + RandoCheckId randoCheckId = RC_UNKNOWN; + applyCustomPhysics = false; + + switch (currentLevel) { + case LEVEL_1_MUMBOS_MOUNTAIN: + switch (bundleId) { + case BUNDLE_0_MM_HUT_MUSIC_NOTE: + randoCheckId = (RandoCheckId)((int32_t)RC_MM_NOTE_HUT_BUNDLE_1 + bundleCount); + applyCustomPhysics = true; + break; + case BUNDLE_1_MM_HUT_BLUE_EGG: + randoCheckId = (RandoCheckId)((int32_t)RC_MM_BLUE_EGG_HUT_BUNDLE_1 + bundleCount); + applyCustomPhysics = true; + break; + case BUNDLE_3_MM_HUT_JINJO_GREEN: + randoCheckId = RC_MM_JINJO_GREEN; + applyCustomPhysics = true; + break; + case BUNDLE_4_MM_HUT_JIGGY: + if (spawnPosition[1] < 2000) { + randoCheckId = RC_MM_JIGGY_ORANGE_PADS; + } else { + randoCheckId = RC_MM_JIGGY_HUTS; + applyCustomPhysics = true; + } + break; + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoCheckId = RC_MM_EXTRA_LIFE_HUT; + applyCustomPhysics = true; + break; + case BUNDLE_7__JIGGY: + randoCheckId = RC_MM_JIGGY_CHIMPY; + break; + case BUNDLE_10__JIGGY: + randoCheckId = RC_MM_JIGGY_JUJU; + break; + case BUNDLE_15__JIGGY: + randoCheckId = RC_MM_JIGGY_CONGA; + break; + case BUNDLE_18__HONEYCOMB: + if (spawnPosition[1] < 400) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1 + bundleCount); + } else { + randoCheckId = + (RandoCheckId)((int32_t)RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_2_TREASURE_TROVE_COVE: + switch (bundleId) { + case BUNDLE_4_MM_HUT_JIGGY: + randoCheckId = RC_TTC_JIGGY_RED_X; + break; + case BUNDLE_7__JIGGY: + randoCheckId = RC_TTC_JIGGY_BLUBBER; + break; + default: + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 900 && position[1] > 890) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1 + bundleCount); + } else if (position[1] < 1770 && position[1] > 1765) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1 + bundleCount); + } else if (position[1] < 1910 && position[1] > 1905) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1 + bundleCount); + } else if (position[1] < 875 && position[1] > 870) { + randoCheckId = + (RandoCheckId)((int32_t)RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1 + bundleCount); + } + break; + } + break; + case LEVEL_3_CLANKERS_CAVERN: + switch (bundleId) { + case BUNDLE_10__JIGGY: + switch (spawnPosition[1]) { + case 1536: + randoCheckId = RC_CC_JIGGY_TOOTH; + break; + default: + randoCheckId = RC_CC_JIGGY_RINGS; + break; + } + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 1405 && position[1] > 1395) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1 + bundleCount); + } else if (position[1] < 5495 && position[1] > 5490) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1 + bundleCount); + } else if (position[1] < 3820 && position[1] > 3810) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_4_BUBBLEGLOOP_SWAMP: + switch (bundleId) { + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoCheckId = (RandoCheckId)((int32_t)RC_BGS_EXTRA_LIFE_MR_VILE_1 + vileCount); + vileCount++; + applyCustomPhysics = true; + if (vileCount >= 3) { + vileCount = 0; + } + break; + case BUNDLE_7__JIGGY: + randoCheckId = RC_BGS_JIGGY_CROCTUS; + break; + case BUNDLE_8__JIGGY: + randoCheckId = RC_BGS_JIGGY_MR_VILE; + break; + case BUNDLE_9__JIGGY: + randoCheckId = RC_BGS_JIGGY_TANKTUP; + break; + case BUNDLE_B_BGS_HUT_MUSIC_NOTE: + randoCheckId = (RandoCheckId)((int32_t)RC_BGS_NOTE_HUT_BUNDLE_1 + bundleCount); + break; + case BUNDLE_C_BGS_HUT_JIGGY: + randoCheckId = RC_BGS_JIGGY_HUTS; + break; + case BUNDLE_10__JIGGY: + switch (spawnPosition[2]) { + case 49: + randoCheckId = RC_BGS_JIGGY_ELEVATED_WALKWAY; + break; + case -1386: + randoCheckId = RC_BGS_JIGGY_FLIBBITS; + break; + case 2799: + randoCheckId = RC_BGS_JIGGY_PINKEGG; + break; + case -1020: + randoCheckId = RC_BGS_JIGGY_TIPTUP; + break; + case -6148: + randoCheckId = RC_BGS_JIGGY_MAZE; + break; + default: + break; + } + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 1260 && position[1] > 1250) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1 + bundleCount); + } else if (position[1] < 1160 && position[1] > 1150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1 + bundleCount); + } else if (position[0] < 4390 && position[0] > 4385) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1 + bundleCount); + } else if (position[0] < 2565 && position[0] > 2560) { + randoCheckId = + (RandoCheckId)((int32_t)RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_5_FREEZEEZY_PEAK: + switch (bundleId) { + case BUNDLE_9__JIGGY: + randoCheckId = RC_FP_JIGGY_SLED_TO_BOGGY; + break; + case BUNDLE_10__JIGGY: + if (spawnPosition[1] > 1900) { + randoCheckId = RC_FP_JIGGY_BOGGY_RACE_1; + } else if (spawnPosition[1] < 850) { + randoCheckId = RC_FP_JIGGY_WOZZA; + } + break; + case BUNDLE_7__JIGGY: + randoCheckId = RC_FP_JIGGY_BOGGY_RACE_2; + break; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 820 && position[1] > 810) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1 + bundleCount); + } else if (position[1] < 590 && position[1] > 580) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1 + bundleCount); + } else if (position[1] < 1755 && position[1] > 1745) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1 + bundleCount); + } else if (position[1] < 5760 && position[1] > 5750) { + randoCheckId = + (RandoCheckId)((int32_t)RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1 + bundleCount); + } + break; + } + break; + case LEVEL_6_LAIR: + switch (bundleId) { + case BUNDLE_C_BGS_HUT_JIGGY: + if (spawnPosition[1] == + Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN].posY) { + randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN; + break; + } + if (spawnPosition[1] == + Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY].posY) { + randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY; + break; + } + if (spawnPosition[1] == + Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD].posY) { + randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLICK_CLOCK_WOOD; + break; + } + if (spawnPosition[1] == + Rando::StaticData::Checks[RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN].posY) { + randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN; + break; + } + break; + case BUNDLE_10__JIGGY: + if (fileProgressFlag_get(FILEPROG_1A_TTC_WITCH_SWITCH_JIGGY_PRESSED) && + gsworld_getMap() == MAP_6D_GL_TTC_LOBBY) { + randoCheckId = RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE; + auto spawnTuple = Rando::StaticData::multiSpawnCheckMap.at(randoCheckId); + spawnPosition[0] = std::get<0>(spawnTuple); + spawnPosition[1] = std::get<1>(spawnTuple); + spawnPosition[2] = std::get<2>(spawnTuple); + } else { + applyCustomPhysics = true; + randoCheckId = Rando::StaticData::GetCheckByPosition(spawnPosition[0], spawnPosition[1], + spawnPosition[2]); + } + break; + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_69_GL_MM_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1 + bundleCount); + break; + case MAP_6D_GL_TTC_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1 + bundleCount); + break; + case MAP_6F_GL_FP_LOBBY: + if (position[1] < 295 && position[1] > 285) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1 + bundleCount); + } else if (position[1] < 255 && position[1] > 245) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1 + bundleCount); + } + break; + case MAP_70_GL_CC_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1 + bundleCount); + break; + case MAP_71_GL_STATUE_ROOM: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1 + bundleCount); + break; + case MAP_72_GL_BGS_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1 + bundleCount); + break; + case MAP_75_GL_MMM_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1 + bundleCount); + break; + case MAP_78_GL_RBB_AND_MMM_PUZZLE: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1 + bundleCount); + break; + case MAP_79_GL_CCW_LOBBY: + randoCheckId = + (RandoCheckId)((int32_t)RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1 + bundleCount); + break; + } + break; + default: + break; + } + break; + case LEVEL_7_GOBIS_VALLEY: + switch (bundleId) { + case BUNDLE_10__JIGGY: + randoCheckId = + Rando::StaticData::GetCheckByPosition(spawnPosition[0], spawnPosition[1], spawnPosition[2]); + break; + case BUNDLE_D__EMPTY_HONEYCOMB: + randoCheckId = RC_GV_EMPTY_HONEYCOMB_GOBI; + case BUNDLE_18__HONEYCOMB: + if (position[1] < 2990 && position[1] > 2980) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1 + bundleCount); + } else if (position[1] < 1990 && position[1] > 1980) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1 + bundleCount); + } else if (position[1] < 610 && position[1] > 600) { + randoCheckId = + (RandoCheckId)((int32_t)RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1 + bundleCount); + } + break; + default: + break; + } + break; + case LEVEL_8_CLICK_CLOCK_WOOD: + switch (bundleId) { + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_40_CCW_HUB: + if (position[1] < 150 && position[1] > 140) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1 + + bundleCount); + } + break; + case MAP_43_CCW_SPRING: + if (position[0] < 5 && position[0] > -5) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1 + + bundleCount); + } else if (position[0] < -1545 && position[0] > -1555) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[0] < 4345 && position[0] > 4340) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_44_CCW_SUMMER: + if (position[1] < -440 && position[1] > -450) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[1] < 4580 && position[1] > 4570) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1 + + bundleCount); + } + break; + case MAP_45_CCW_AUTUMN: + if (position[1] < 1435 && position[1] > 1425) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1 + + bundleCount); + } else if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1 + + bundleCount); + } else if (position[1] < 4405 && position[1] > 4395) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_46_CCW_WINTER: + if (position[1] < 1060 && position[1] > 1050) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1 + + bundleCount); + } else if (position[1] < 4405 && position[1] > 4395) { + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1 + + bundleCount); + } + break; + case MAP_4D_CCW_WINTER_MUMBOS_SKULL: + randoCheckId = + (RandoCheckId)((int32_t)RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1 + + bundleCount); + break; + } + default: + break; + } + break; + case LEVEL_9_RUSTY_BUCKET_BAY: + switch (bundleId) { + case BUNDLE_6_MM_HUT_EXTRA_LIFE: + randoCheckId = RC_RBB_EXTRA_LIFE_BOOM_BOXES; + applyCustomPhysics = true; + break; + case BUNDLE_18__HONEYCOMB: + if (position[0] == 0 && position[1] == 156 && position[2] == 4800) { + randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1 + bundleCount); + } else if (position[0] == 0 && position[1] == 156 && position[2] == -178) { + randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1 + bundleCount); + } else if (position[0] == 7850 && position[1] == -1019 && position[2] == 3550) { + randoCheckId = + (RandoCheckId)((int32_t)RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1 + bundleCount); + } + break; + default: + break; + } + case LEVEL_A_MAD_MONSTER_MANSION: + switch (bundleId) { + case BUNDLE_18__HONEYCOMB: + switch (currentMap) { + case MAP_1C_MMM_CHURCH: + if (position[0] < 1880 && position[0] > 1870) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1 + bundleCount); + } else if (position[0] < -1870 && position[0] > -1880) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1 + bundleCount); + } + break; + case MAP_1B_MMM_MAD_MONSTER_MANSION: + if (position[1] < 160 && position[1] > 150) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1 + bundleCount); + } else if (position[1] < 335 && position[1] > 325) { + randoCheckId = + (RandoCheckId)((int32_t)RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1 + + bundleCount); + } + break; + default: + break; + } + break; + default: + break; + } + break; + case LEVEL_B_SPIRAL_MOUNTAIN: + switch (bundleId) { + case BUNDLE_1F_SM_EMPTY_HONEYCOMB: + if (spawnPosition[1] >= 500 && spawnPosition[1] <= 800) { + randoCheckId = RC_SM_EMPTY_HONEYCOMB_COLLIWOBBLE; + } else { + randoCheckId = RC_SM_EMPTY_HONEYCOMB_QUARRIES; + } + break; + case BUNDLE_18__HONEYCOMB: + break; + default: + break; + } + break; + default: + return; + } + + if (randoCheckId == RC_UNKNOWN) { + return; + } + + if (!Rando::Logic::IsCheckShuffled(randoCheckId)) { + return; + } + + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; + if (randoSaveCheck.obtained) { + actor_e actorId = (actor_e)Rando::StaticData::Items[randoSaveCheck.randoItemId].actorId; + *actor = + CustomObject::SpawnCustomActorEX(randoCheckId, spawnPosition, &actorInfoMap.at((actor_e)actorId).first, + actorInfoMap.at((actor_e)actorId).second); + + bundleDespawnQueue.push_back((*actor)->marker); + } else { + *actor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, spawnPosition, false); + + if (*actor == NULL) { + *should = true; + return; + } + + if (applyCustomPhysics) { + ApplyCustomActorPhysics(randoCheckId, *actor, false); + } else { + ApplyBundleActorPhysics(*actor, bundleId, (BundleInfo*)bundleInfo, gBundle_yaw); + } + } + + *should = true; + }) +} diff --git a/src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp b/src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp deleted file mode 100644 index 90a744a80..000000000 --- a/src/port/Rando/ObjectBehavior/EmptyHoneyComb.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_EMPTY_HONEYCOMBS].optionValue - -bool OverrideEmptyHoneyCombSpawn(OnActorSpawn* ev) { - if (ev->actorId != ACTOR_47_EMPTY_HONEYCOMB) { - return false; - } - - int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); - - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } - - if (!Rando::Logic::IsCheckObtained(randoCheckId)) { - CustomCollectible::Spawn(spawnPosition, randoCheckId); - } - - return true; -} - -void RegisterRandoEmptyHoneyCombs() { - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - - bool replaceEmptyHoneyComb = OverrideEmptyHoneyCombSpawn(ev); - if (replaceEmptyHoneyComb) { - event->Cancelled = true; - } - }); -} - -static RegisterShipInitFunc initFunc(RegisterRandoEmptyHoneyCombs, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/ExtraLife.cpp b/src/port/Rando/ObjectBehavior/ExtraLife.cpp deleted file mode 100644 index 875e68355..000000000 --- a/src/port/Rando/ObjectBehavior/ExtraLife.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUMBO_TOKENS].optionValue - -bool OverrideExtraLifeSpawn(OnActorSpawn* ev) { - if (ev->actorId != ACTOR_49_EXTRA_LIFE) { - return false; - } - - int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); - - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } - - if (!Rando::Logic::IsCheckObtained(randoCheckId)) { - CustomCollectible::Spawn(spawnPosition, randoCheckId); - } - - return true; -} - -void RegisterRandoExtraLifes() { - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - - bool replaceExtraLife = OverrideExtraLifeSpawn(ev); - if (replaceExtraLife) { - event->Cancelled = true; - } - }); -} - -static RegisterShipInitFunc initFunc(RegisterRandoExtraLifes, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Gobi.cpp b/src/port/Rando/ObjectBehavior/Gobi.cpp index 1ac60ec89..abf0f6ef1 100644 --- a/src/port/Rando/ObjectBehavior/Gobi.cpp +++ b/src/port/Rando/ObjectBehavior/Gobi.cpp @@ -22,12 +22,12 @@ void Rando::ObjectBehavior::ModifyGobiBehavior(void* gobiActor) { case ACTOR_12E_GOBI_1: case ACTOR_12F_GOBI_ROPE: case ACTOR_130_GOBI_ROCK: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].eligible) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].obtained) { marker_despawn(actor->marker); } break; case ACTOR_131_GOBI_2: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].eligible && !RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].eligible) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_1].obtained && !RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].obtained) { if (actor->state == 1) { chGobi2_setState(actor, 2); actor->marker->collidable = true; @@ -41,7 +41,7 @@ void Rando::ObjectBehavior::ModifyGobiBehavior(void* gobiActor) { } break; case ACTOR_135_GOBI_3: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].eligible) { + if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].obtained) { if (actor->state == 0) { chGobi3_setState(actor, 2); actor->marker->collidable = true; diff --git a/src/port/Rando/ObjectBehavior/Jiggy.cpp b/src/port/Rando/ObjectBehavior/Jiggy.cpp index f473113af..cc4fc67f8 100644 --- a/src/port/Rando/ObjectBehavior/Jiggy.cpp +++ b/src/port/Rando/ObjectBehavior/Jiggy.cpp @@ -1,81 +1,56 @@ #include "ObjectBehavior.h" -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" #include "port/Rando/Logic/Logic.h" #include "port/Rando/CustomObject/CustomObject.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue - -bool OverrideJiggySpawn(f32 position[3], jiggy_e jiggyId) { - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByJiggyId(jiggyId); - - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } +#include "port/Enhancements/Events/Hooks/Events.h" - int32_t spawnPosition[3] = { (int32_t)position[0], (int32_t)position[1], (int32_t)position[2] }; +#include "spdlog/spdlog.h" - if (jiggyId == JIGGY_26_BGS_TANKTUP) { - spawnPosition[0] -= 300; - spawnPosition[1] += 100; - spawnPosition[2] -= 300; - } +#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue - Actor* actor = CustomCollectible::Spawn(spawnPosition, randoCheckId); - if (jiggyId != JIGGY_17_CC_CLANKER_RAISED && jiggyId != JIGGY_1B_CC_TOOTH) { - ApplyCustomActorPhysics(randoCheckId, actor, false); - } - return true; -} +void Rando::ObjectBehavior::InitJiggyBehavior() { + COND_VB_SHOULD(VB_NAPPER_SET_JIGGY_POSITION, EVENT_PRIORITY_NORMAL, true, { + if (!IS_RANDO && !OPTION_ENABLED) { + return; + } -bool OverrideJiggyActorSpawn(OnActorSpawn* ev) { - if (ev->actorId != ACTOR_46_JIGGY) { - return false; - } + if (RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].obtained) { + *should = false; + } + }) - int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); + COND_VB_SHOULD(VB_OVERRIDE_JIGGY_SPAWN, EVENT_PRIORITY_NORMAL, true, { + jiggy_e jiggyId = (jiggy_e)va_arg(args, int); + f32* position = va_arg(args, f32*); - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } + if (!IS_RANDO && !OPTION_ENABLED) { + return; + } - if (Rando::Logic::IsCheckObtained(randoCheckId)) { - return true; - } + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByJiggyId(jiggyId); - CustomCollectible::Spawn(spawnPosition, randoCheckId); - return true; -} + if (randoCheckId == RC_UNKNOWN) { + return; + } -void RegisterRandoJiggies() { - COND_VB_SHOULD(VB_NAPPER_SET_JIGGY_POSITION, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { - if (RANDO_SAVE_CHECKS[RC_MMM_JIGGY_MANSION_TABLE].eligible) { - *should = false; + if (!Rando::Logic::IsCheckShuffled(randoCheckId)) { + return; } - }); - // Jiggies can be spawned through 2 separate code paths, that's why there's 2 hooks with slight - // variations on how it identifies the jiggy. - COND_VB_SHOULD(VB_OVERRIDE_JIGGY_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { - jiggy_e jiggyId = (jiggy_e)va_arg(args, int); - f32* position = va_arg(args, f32*); + int32_t spawnPosition[3]; + spawnPosition[0] = (int32_t)position[0]; + spawnPosition[1] = (int32_t)position[1]; + spawnPosition[2] = (int32_t)position[2]; - bool replaceJiggy = OverrideJiggySpawn(position, jiggyId); - if (replaceJiggy) { - *should = true; + if (jiggyId == JIGGY_26_BGS_TANKTUP) { + spawnPosition[0] -= 300; + spawnPosition[1] += 100; + spawnPosition[2] -= 300; } - }); - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - - bool replaceJiggy = OverrideJiggyActorSpawn(ev); - if (replaceJiggy) { - event->Cancelled = true; + Actor* randoCustomActor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, spawnPosition, false); + if (jiggyId != JIGGY_17_CC_CLANKER_RAISED && jiggyId != JIGGY_1B_CC_TOOTH) { + ApplyCustomActorPhysics(randoCheckId, randoCustomActor, false); } - }); + *should = true; + }) } - -static RegisterShipInitFunc initFunc(RegisterRandoJiggies, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Jinjo.cpp b/src/port/Rando/ObjectBehavior/Jinjo.cpp index 3df071888..61764a6bd 100644 --- a/src/port/Rando/ObjectBehavior/Jinjo.cpp +++ b/src/port/Rando/ObjectBehavior/Jinjo.cpp @@ -1,8 +1,12 @@ -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" +#include "ObjectBehavior.h" #include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" -#include "port/Enhancements/Retention/Retention.h" +#include "port/Rando/CustomObject/CustomObject.h" + +#include +#include "port/UI/cvar_prefixes.h" +#include +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" extern "C" { s32 item_adjustByDiffWithHud(enum item_e item, s32 diff); @@ -10,48 +14,29 @@ s32 item_adjustByDiffWithHud(enum item_e item, s32 diff); #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JINJOS].optionValue -bool OverrideJinjoSpawn(OnActorSpawn* ev) { - if (ev->actorId != ACTOR_5E_JINJO_YELLOW && ev->actorId != ACTOR_5F_JINJO_ORANGE && - ev->actorId != ACTOR_60_JINJO_BLUE && ev->actorId != ACTOR_61_JINJO_PINK && - ev->actorId != ACTOR_62_JINJO_GREEN) { - return false; - } +void Rando::ObjectBehavior::InitJinjoBehavior() { + COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + OnSetJiggyList* ev = (OnSetJiggyList*)event; - int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); + for (auto& location : Rando::Logic::shuffledPool) { + if (!location.obtained) { + continue; + } - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; - if (!Rando::Logic::IsCheckObtained(randoCheckId)) { - CustomCollectible::Spawn(spawnPosition, randoCheckId); - } + if (randoItem.worldId != ev->levelId) { + continue; + } - return true; -} + if (randoItem.randoItemType == RITYPE_JINJO) { + int32_t jinjoMarkerId = GetJinjoActorMarkerId((actor_e)randoItem.actorId); + item_adjustByDiffWithHud(ITEM_12_JINJOS, (1 << ((jinjoMarkerId + 6) & 0x1F))); + } + } + }) -void RegisterRandoJinjos() { COND_VB_SHOULD(VB_UPDATE_JINJO_HUD, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { *should = true; }) COND_VB_SHOULD(VB_SET_JINJO_COUNT, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { *should = true; }) - - COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnSetJiggyList* ev = (OnSetJiggyList*)event; - u8 bits = collectedBits(ev->levelId); - if (bits != 0) { - item_adjustByDiffWithoutHud(ITEM_12_JINJOS, bits - item_getCount(ITEM_12_JINJOS)); - } - }); - - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - - bool replaceJinjo = OverrideJinjoSpawn(ev); - if (replaceJinjo) { - event->Cancelled = true; - } - }); } - -static RegisterShipInitFunc initFunc(RegisterRandoJinjos, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/Molehill.cpp b/src/port/Rando/ObjectBehavior/Molehill.cpp index cdcea42f4..e7e640f73 100644 --- a/src/port/Rando/ObjectBehavior/Molehill.cpp +++ b/src/port/Rando/ObjectBehavior/Molehill.cpp @@ -1,17 +1,53 @@ +#include "ObjectBehavior.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomObject/CustomObject.h" + #include -#include "port/ShipInit.hpp" +#include "port/UI/cvar_prefixes.h" +#include +#include "port/Enhancements/Events/PortEnhancements.h" #include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" +#define MOLETABLE_SIZE 16 #define BRIDGE_REQUIREMENT 6 +typedef struct { + s16 teach_text_id; + s16 refresher_text_id; + s8 camera_node; + s8 ability; +} ChMoleDescription; + extern "C" { +void func_80347A14(s32 arg0); +s32 item_adjustByDiffWithHud(enum item_e item, s32 diff); +void ability_unlock(enum ability_e); s32 mapSpecificFlags_get(s32 i); void mapSpecificFlags_set(s32 i, s32 val); } // clang-format off +ChMoleDescription moleDialogTable[MOLETABLE_SIZE] = { + //{ ASSET_DF3_DIALOG_BOTTLES_INTRODUCTION, ASSET_E08_DIALOG_BOTTLES_FIND_ANOTHER_MOLEHILL, 0x1, -1 }, + { ASSET_DF4_DIALOG_BOTTLES_CAMERA_CONTROL_LEARN, ASSET_DF5_DIALOG_BOTTLES_CAMERA_CONTROL_REFRESHER, 0x3, ABILITY_3_CAMERA_CONTROL }, + { ASSET_DFB_DIALOG_BOTTLES_DIVE_LEARN, ASSET_DFE_DIALOG_BOTTLES_DIVE_REFRESHER, 0x5, ABILITY_F_DIVE }, + { -1, ASSET_E00_DIALOG_BOTTLES_ATTACK_REFRESHER, 0x6, ABILITY_4_CLAW_SWIPE }, + { ASSET_E04_DIALOG_BOTTLES_BEAK_BARGE_LEARN, ASSET_E06_DIALOG_BOTTLES_BEAK_BARGE_REFRESHER, 0x8, ABILITY_0_BARGE }, + { -1, ASSET_DFA_DIALOG_BOTTLES_JUMP_REFRESHER, 0x4, ABILITY_8_FLAP_FLIP }, + { ASSET_E01_DIALOG_BOTTLES_CLIMB_LEARN, ASSET_E03_DIALOG_BOTTLES_CLIMB_REFRESHER, 0x7, ABILITY_5_CLIMB }, + //{ ASSET_E10_DIALOG_BOTTLES_BRIDGE_BROKEN, ASSET_E11_DIALOG_BOTTLES_BRIDGE_STILL_BROKEN, 0x11, -1 }, + { ASSET_C23_DIALOG_BEAKBOMB_LEARN, ASSET_C24_DIALOG_BEAKBOMB_REFRESHER, 0x0F, ABILITY_1_BEAK_BOMB }, + { ASSET_B47_DIALOG_EGGS_LEARN, ASSET_B4B_DIALOG_EGGS_REFRESHER, 0x16, ABILITY_6_EGGS }, + { ASSET_B48_DIALOG_BEAKBUSTER_LEARN, ASSET_B4C_DIALOG_BEAKBUSTER_REFRESHER, 0x17, ABILITY_2_BEAK_BUSTER }, + { ASSET_B49_DIALOG_TALON_TROT_LEARN, ASSET_B4A_DIALOG_TALON_TROT_REFRESHER, 0x18, ABILITY_10_TALON_TROT }, + { ASSET_A1F_DIALOG_SHOCKJUMP_LEARN, ASSET_A23_DIALOG_SHOCKJUMP_REFRESHER, 0x0C, ABILITY_D_SHOCK_JUMP }, + { ASSET_A20_DIALOG_FLY_LEARN, ASSET_A22_DIALOG_FLY_REFRESHER, 0x0D, ABILITY_9_FLIGHT }, + { ASSET_D35_DIALOG_WONDERWING_LEARN, ASSET_D36_DIALOG_WONDERWING_REFRESHER, 0x01, ABILITY_12_WONDERWING }, + { ASSET_C88_DIALOG_WADING_BOOTS_LEARN, ASSET_C89_DIALOG_WADING_BOOTS_REFRESHER, 0x10, ABILITY_E_WADING_BOOTS }, + { ASSET_A84_DIALOG_TURBOTRAINERS_LEARN, ASSET_A85_DIALOG_TURBOTRAINERS_REFRESHER, 0x19, ABILITY_11_TURBO_TALON }, + { ASSET_F64_DIALOG_NOTEDOORS_LEARN, ASSET_F65_DIALOG_NOTEDOORS_REFRESHER, 0x0E, ABILITY_13_1ST_NOTEDOOR }, +}; + std::vector spiralMountainBridge = { RC_SM_MOLEHILL_JUMP, RC_SM_MOLEHILL_CAMERA_CONTROL, @@ -22,13 +58,27 @@ std::vector spiralMountainBridge = { }; // clang-format on +ChMoleDescription result; + #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MOLEHILLS].optionValue +ChMoleDescription GetMoleDescriptionByAbility(int16_t abilityId) { + result.ability = -1; + for (int i = 0; i < MOLETABLE_SIZE; i++) { + if (moleDialogTable[i].ability == abilityId) { + result = moleDialogTable[i]; + break; + } + } + + return result; +} + bool CheckBridgeState() { int32_t smBridgeCheck = 0; if (!mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED)) { for (auto& check : spiralMountainBridge) { - if (RANDO_SAVE_CHECKS[check].eligible) { + if (Rando::Logic::GetShuffledObject(check).obtained) { smBridgeCheck++; } } @@ -37,49 +87,117 @@ bool CheckBridgeState() { return smBridgeCheck == BRIDGE_REQUIREMENT ? true : false; } -bool OverrideMoleSpawn(OnActorSpawn* ev) { - if (ev->actorId != ACTOR_12B_TUTORIAL_BOTTLES && ev->actorId != ACTOR_37A_BOTTLES) { - return false; - } +void SetSpiralMountainFlags() { + mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); +} - int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); +static void MarkBridgeRepairedDialogComplete() { + CALL_EVENT(SetRandoInfFlag, RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, true); +} - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } +void Rando::ObjectBehavior::InitMolehillBehavior() { + COND_VB_SHOULD(VB_OVERRIDE_MOLEHILL_ABILITY, EVENT_PRIORITY_NORMAL, true, { + Actor* molehillActor = va_arg(args, Actor*); + s32* textId = va_arg(args, s32*); + s32* isLearned = va_arg(args, s32*); - if (Rando::Logic::IsCheckObtained(randoCheckId)) { - return true; - } + if (!IS_RANDO && !OPTION_ENABLED) { + return; + } - CustomCollectible::Spawn(spawnPosition, randoCheckId); - return true; -} + if (molehillActor->actorTypeSpecificField == 8) { + return; + } + + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition( + molehillActor->position_x, molehillActor->position_y, molehillActor->position_z); -void RegisterRandoMolehills() { - COND_HOOK(OnCheckSpiralMountainAbilities, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { + if (randoCheckId == RC_UNKNOWN) { + return; + } + + RandoSaveCheck shuffledMolehill = Rando::Logic::GetShuffledObject(randoCheckId); + ChMoleDescription moleInfo = GetMoleDescriptionByAbility(shuffledMolehill.randoCollectionId); + + if (moleInfo.ability >= ABILITY_0_BARGE) { + *should = true; + + func_80347A14(0); + molehillActor->has_met_before = true; + + switch (moleInfo.ability) { + case ABILITY_4_CLAW_SWIPE: + *textId = (s32)moleInfo.refresher_text_id; + ability_unlock(ABILITY_4_CLAW_SWIPE); + ability_unlock(ABILITY_C_ROLL); + ability_unlock(ABILITY_B_RATATAT_RAP); + break; + case ABILITY_6_EGGS: + *textId = (s32)moleInfo.refresher_text_id; + ability_unlock((ability_e)moleInfo.ability); + item_adjustByDiffWithHud(ITEM_D_EGGS, 50); + break; + case ABILITY_8_FLAP_FLIP: + *textId = (s32)moleInfo.refresher_text_id; + ability_unlock(ABILITY_A_HOLD_A_JUMP_HIGHER); + ability_unlock(ABILITY_7_FEATHERY_FLAP); + ability_unlock(ABILITY_8_FLAP_FLIP); + break; + case ABILITY_9_FLIGHT: + *textId = (s32)moleInfo.refresher_text_id; + ability_unlock((ability_e)moleInfo.ability); + item_adjustByDiffWithHud(ITEM_F_RED_FEATHER, 25); + break; + case ABILITY_12_WONDERWING: + *textId = (s32)moleInfo.refresher_text_id; + ability_unlock((ability_e)moleInfo.ability); + item_adjustByDiffWithHud(ITEM_10_GOLD_FEATHER, 5); + break; + default: + *textId = (s32)moleInfo.refresher_text_id; + ability_unlock((ability_e)moleInfo.ability); + break; + } + + CustomObject::CheckObtainedEX(shuffledMolehill.randoCheckId); + + if (map_getLevel(gsworld_getMap()) == LEVEL_B_SPIRAL_MOUNTAIN) { + if (CheckBridgeState()) { + SetSpiralMountainFlags(); + } + } + } + }) + + COND_VB_SHOULD(VB_OVERRIDE_BOTTLES_TEXT_CALLBACK, EVENT_PRIORITY_NORMAL, true, { + Actor* molehillActor = va_arg(args, Actor*); + + if (!IS_RANDO && !OPTION_ENABLED) { + return; + } + + if (CheckBridgeState() && !RANDO_SAVE_FLAGS[RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE].flagState) { + *should = true; + } + }) + + COND_HOOK(OnCheckSpiralMountainAbilities, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { OnCheckSpiralMountainAbilities* ev = (OnCheckSpiralMountainAbilities*)event; + if (!IS_RANDO && !OPTION_ENABLED) { + return; + } + if (mapSpecificFlags_get(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED)) { mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, false); } if (CheckBridgeState()) { mapSpecificFlags_set(SM_SPECIFIC_FLAG_3_ALL_SM_ABILITIES_LEARNED, true); - mapSpecificFlags_set(SM_SPECIFIC_FLAG_1_TALKED_TO_BOTTLES, true); + if (!RANDO_SAVE_FLAGS[RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE].flagState) { + MarkBridgeRepairedDialogComplete(); + } event->Cancelled = true; ev->result = true; } - }); - - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - - bool replaceMole = OverrideMoleSpawn(ev); - if (replaceMole) { - event->Cancelled = true; - } - }); + }) } - -static RegisterShipInitFunc initFunc(RegisterRandoMolehills, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/MumboToken.cpp b/src/port/Rando/ObjectBehavior/MumboToken.cpp deleted file mode 100644 index 1ecbc7a12..000000000 --- a/src/port/Rando/ObjectBehavior/MumboToken.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUMBO_TOKENS].optionValue - -bool OverrideMumboTokenSpawn(OnActorSpawn* ev) { - if (ev->actorId != ACTOR_2D_MUMBO_TOKEN) { - return false; - } - - int32_t spawnPosition[3] = { ev->posX, ev->posY, ev->posZ }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(ev->posX, ev->posY, ev->posZ); - - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } - - if (!Rando::Logic::IsCheckObtained(randoCheckId)) { - CustomCollectible::Spawn(spawnPosition, randoCheckId); - } - - return true; -} - -void RegisterRandoMumboTokens() { - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { - OnActorSpawn* ev = (OnActorSpawn*)event; - - bool replaceMumboToken = OverrideMumboTokenSpawn(ev); - if (replaceMumboToken) { - event->Cancelled = true; - } - }); -} - -static RegisterShipInitFunc initFunc(RegisterRandoMumboTokens, { "IS_RANDO" }); diff --git a/src/port/Rando/ObjectBehavior/MusicNote.cpp b/src/port/Rando/ObjectBehavior/MusicNote.cpp index ec2ec0595..24d32b6ee 100644 --- a/src/port/Rando/ObjectBehavior/MusicNote.cpp +++ b/src/port/Rando/ObjectBehavior/MusicNote.cpp @@ -1,49 +1,38 @@ -#include "port/ShipInit.hpp" -#include "port/Enhancements/Events/Hooks/Events.h" +#include "ObjectBehavior.h" #include "port/Rando/Logic/Logic.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" +#include "port/Rando/CustomObject/CustomObject.h" + +#include +#include "port/UI/cvar_prefixes.h" +#include +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" extern "C" { void item_inc(enum item_e item); -extern u8 D_80385FF0[0xE]; } #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue -bool OverrideMusicNoteSpawn(s16 spawnPosition[3], int32_t propAsset) { - if (propAsset != ASSET_6D6_SPRITE_MUSIC_NOTE) { - return false; - } - - s32 position[3] = { spawnPosition[0], spawnPosition[1], spawnPosition[2] }; - RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); - - if (randoCheckId == RC_UNKNOWN || !Rando::Logic::IsCheckShuffled(randoCheckId)) { - return false; - } - - if (!Rando::Logic::IsCheckObtained(randoCheckId)) { - CustomCollectible::QueueProp(position, randoCheckId); - } - - return true; -} - -void RegisterRandoMusicNotes() { +void Rando::ObjectBehavior::InitMusicNoteBehavior() { COND_HOOK(OnSetJiggyList, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, [](IEvent* event) { OnSetJiggyList* ev = (OnSetJiggyList*)event; + int32_t currentNotes = 0; - item_set(ITEM_C_NOTE, D_80385FF0[ev->levelId]); - }); + for (auto& location : Rando::Logic::shuffledPool) { + Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[location.randoItemId]; - COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { - s16* spawnPosition = va_arg(args, s16*); - int32_t propAsset = va_arg(args, int32_t); - bool replaceNote = OverrideMusicNoteSpawn(spawnPosition, propAsset); - if (replaceNote) { - *should = true; + if (randoItem.worldId != ev->levelId) { + continue; + } + + if (randoItem.randoItemType == RITYPE_MUSIC_NOTE) { + if (location.obtained) { + currentNotes++; + } + } } - }); -} -static RegisterShipInitFunc initFunc(RegisterRandoMusicNotes, { "IS_RANDO" }); + item_set(ITEM_C_NOTE, currentNotes); + }) +} diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index 2fbb1d0d7..68f158eaf 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -13,16 +13,33 @@ #define CVAR_SHOW_COLLISION_NOTIFICATIONS CVarGetInteger(CVAR_NAME_SHOW_COLLISION_NOTIFICATIONS, 0) extern "C" { +void player_getPosition(f32 dst[3]); +Actor* marker_getActor(ActorMarker* thisx); +bool func_802C9C14(Actor* actor); + +s32 mapSpecificFlags_get(s32 i); + +void coMusicPlayer_playMusic(enum comusic_e track_id, s32 volume); extern ActorArray* suBaddieActorArray; } +bool isSaveState = false; std::map> randoSaveState; // clang-format off std::vector actorSpawnWhitelist = { + ACTOR_2D_MUMBO_TOKEN, + ACTOR_46_JIGGY, ACTOR_47_EMPTY_HONEYCOMB, ACTOR_49_EXTRA_LIFE, ACTOR_50_HONEYCOMB, + ACTOR_51_MUSIC_NOTE, + ACTOR_52_BLUE_EGG, + ACTOR_5E_JINJO_YELLOW, + ACTOR_5F_JINJO_ORANGE, + ACTOR_60_JINJO_BLUE, + ACTOR_61_JINJO_PINK, + ACTOR_62_JINJO_GREEN, ACTOR_25E_SNS_EGG, ACTOR_25D_ICE_KEY, //ACTOR_12C_MOLEHILL, @@ -79,19 +96,21 @@ std::vector enemyKillOverlapList = { bool nextActorSaveState = false; bool IsActorWhitelisted(int32_t actorId) { - /*for (auto& entry : actorSpawnWhitelist) { + for (auto& entry : actorSpawnWhitelist) { if (entry == actorId) { return true; } } - if (CVarGetInteger(Rando::StaticData::Options[RO_SPAWN_JUNK].cvar, 0) == RO_GENERIC_ON) { - for (auto& junk : junkItemList) { - if (junk == actorId) { - return true; + if (!isSaveState) { + if (CVarGetInteger(Rando::StaticData::Options[RO_SPAWN_JUNK].cvar, 0) == RO_GENERIC_ON) { + for (auto& junk : junkItemList) { + if (junk == actorId) { + return true; + } } } - }*/ + } return false; } @@ -149,63 +168,46 @@ Actor* FindActorByRandoCheckId(RandoCheckId randoCheckId) { return NULL; } -// subject is "You" or a teammate's name for Anchor remote collects. -static void EmitCheckNotification(RandoCheckId randoCheckId, const std::string& subject) { - RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; - std::string prefix; - std::string message; - std::string suffix = ""; - ImVec4 itemColor = - WIDGET_TEXT_COLOR(randoItemColors.at((actor_e)Rando::StaticData::Items[randoSaveCheck.randoItemId].actorId)); - RandoItemType itemType = Rando::StaticData::Items[randoSaveCheck.randoItemId].randoItemType; - - if (itemType == RITYPE_MOLEHILL) { - prefix = subject + " learned"; - message = abilityNameList[randoSaveCheck.randoCollectionId].c_str(); - } else if (itemType == RITYPE_SNS_EGG || itemType == RITYPE_SNS_KEY) { - int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); - prefix = subject + " collected "; - prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; - - message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; - suffix = "("; - suffix += std::to_string(totalsnsItems); - suffix += " / 7)"; - - itemColor = WIDGET_TEXT_COLOR(snsItemColors.at(randoSaveCheck.randoCollectionId)); - } else { - prefix = subject + " collected "; - prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; - message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; - } - - Notification::Emit({ - .prefix = prefix, - .prefixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), - .message = message, - .messageColor = itemColor, - .suffix = suffix, - .suffixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), - }); -} - void Rando::StaticData::SendCollisionNotification(RandoCheckId randoCheckId) { if (CVAR_SHOW_COLLISION_NOTIFICATIONS) { - EmitCheckNotification(randoCheckId, "You"); - } -}; - -void Rando::StaticData::SendRemoteCheckNotification(RandoCheckId randoCheckId, const std::string& collectorName) { - EmitCheckNotification(randoCheckId, collectorName); -}; + RandoSaveCheck randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId]; + actor_e actorId = Rando::StaticData::GetActorIdByRandoItemId(randoSaveCheck.randoItemId); + std::string prefix; + std::string message; + std::string suffix = ""; + ImVec4 itemColor = WIDGET_TEXT_COLOR(randoItemColors.at(actorId)); + + if (actorId == ACTOR_12C_MOLEHILL) { + prefix = "You learned"; + message = abilityNameList[randoSaveCheck.randoCollectionId].c_str(); + } else if (randoSaveCheck.randoItemId >= RI_STOP_N_SWOP_EGG_BLUE && + randoSaveCheck.randoItemId <= RI_STOP_N_SWOP_ICE_KEY) { + int32_t totalsnsItems = Rando::Logic::GetTotalSnsItemsCollected(); + prefix = "You collected "; + prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; + + message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; + suffix = "("; + suffix += std::to_string(totalsnsItems); + suffix += " / 7)"; + + itemColor = WIDGET_TEXT_COLOR(snsItemColors.at(randoSaveCheck.randoCollectionId)); + } else { + prefix = "You collected "; + prefix += Rando::StaticData::Items[randoSaveCheck.randoItemId].article; + message = Rando::StaticData::Items[randoSaveCheck.randoItemId].name; + } -bool ShouldOverrideSpawn(RandoCheckId randoCheckId) { - if (Rando::Logic::IsCheckShuffled(randoCheckId)) { - return true; + Notification::Emit({ + .prefix = prefix, + .prefixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), + .message = message, + .messageColor = itemColor, + .suffix = suffix, + .suffixColor = WIDGET_TEXT_COLOR(UIWidgets::Colors::White), + }); } - - return false; -} +}; bool CheckEnemyOverlapPosition(int32_t pos[3]) { level_e levelId = map_getLevel(gsworld_getMap()); @@ -241,6 +243,12 @@ static void FireClearBundleDespawnQueue() { // Entry point for the module, run once on game boot void Rando::ObjectBehavior::Init() { + InitBundleBehavior(); + InitJiggyBehavior(); + InitJinjoBehavior(); + InitMolehillBehavior(); + InitMusicNoteBehavior(); + InitPropBehavior(); InitStopNSwopBehavior(); UpdateJunkList(); @@ -250,6 +258,7 @@ void Rando::ObjectBehavior::Init() { map_e currentMap = gsworld_getMap(); CustomObject::FlushRandoSpawnQueue(); + DespawnCollectedBundles(); if (ev->actorId == ACTOR_12_BEEHIVE) { SPDLOG_INFO("Actor ID: {} {}, {}, {}", ev->actorId, ev->posX, ev->posY, ev->posZ); @@ -257,7 +266,7 @@ void Rando::ObjectBehavior::Init() { if (currentMap == MAP_12_GV_GOBIS_VALLEY) { if (ev->actorId == ACTOR_118_GRABBA) { - event->Cancelled = RANDO_SAVE_CHECKS[RC_GV_JIGGY_GRABBA].eligible; + event->Cancelled = RANDO_SAVE_CHECKS[RC_GV_JIGGY_GRABBA].obtained; ev->result = NULL; } } @@ -307,12 +316,12 @@ void Rando::ObjectBehavior::Init() { COND_HOOK(OnLoadActorSaveState, EVENT_PRIORITY_NORMAL, IS_RANDO, [](IEvent* event) { OnLoadActorSaveState* ev = (OnLoadActorSaveState*)event; - // Decide up front whether this restore is ours: anything we don't manage falls - // through to the vanilla restore untouched. The predicate has to be the same one - // the save side recorded under, junk included. + isSaveState = true; if (!IsActorWhitelisted((actor_e)ev->actor->modelCacheIndex)) { + event->Cancelled = true; return; } + isSaveState = false; if (randoSaveState.empty()) { return; @@ -336,16 +345,12 @@ void Rando::ObjectBehavior::Init() { return; } - // The check already has a live actor. Restoring would stack a second one on - // top of it, so drop the restore entirely. if (CustomObject::CheckSpawnedIdList(randoCheckId)) { event->Cancelled = true; return; } - // refActor keeps an obtained check restoring the junk actor it was saved as - // instead of rolling a fresh one. - CustomObject::ShouldCreateCustomActorEX(randoCheckId, position, false, ev->actor); + Actor* randoCustomActor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, position, false, ev->actor); randoSaveState.erase(randoCheckId); event->Cancelled = true; }) diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.h b/src/port/Rando/ObjectBehavior/ObjectBehavior.h index c620a504c..25221fd9e 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.h +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.h @@ -13,6 +13,12 @@ namespace Rando { namespace ObjectBehavior { void Init(); +void InitBundleBehavior(); +void InitJiggyBehavior(); +void InitJinjoBehavior(); +void InitMolehillBehavior(); +void InitMusicNoteBehavior(); +void InitPropBehavior(); void InitStopNSwopBehavior(); void ModifySwitchBehavior(int32_t switchActorId); @@ -20,6 +26,7 @@ void ModifyGobiBehavior(void* gobiActor); void ModifyBoggyBehavior(void* boggyActor); void ModifyPresentBehavior(void* presentActor); void ModifyStopNSwopWorldBehavior(void* snsActor); +void DespawnCollectedBundles(); } // namespace ObjectBehavior diff --git a/src/port/Rando/ObjectBehavior/Present.cpp b/src/port/Rando/ObjectBehavior/Present.cpp index da91e939c..d8be0600e 100644 --- a/src/port/Rando/ObjectBehavior/Present.cpp +++ b/src/port/Rando/ObjectBehavior/Present.cpp @@ -10,25 +10,12 @@ s32 levelSpecificFlags_get(s32 i); #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue -std::map presentLevelFlagMap = { - { ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE, LEVEL_FLAG_11_FP_UNKNOWN }, - { ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE, LEVEL_FLAG_12_FP_UNKNOWN }, - { ACTOR_1F1_RED_PRESENT_COLLECTIBLE, LEVEL_FLAG_13_FP_UNKNOWN }, -}; - -void GetPresentLevelFlag(Actor* actor, level_flags_e levelFlag) { - if (levelSpecificFlags_get(levelFlag)) { - marker_despawn(actor->marker); - } -} - void Rando::ObjectBehavior::ModifyPresentBehavior(void* presentActor) { if (!IS_RANDO && !OPTION_ENABLED) { return; } Actor* actor = (Actor*)presentActor; - int32_t actorAdjustment = 0; int32_t levelFlag = 0; switch (actor->actor_info->actorId) { @@ -43,7 +30,10 @@ void Rando::ObjectBehavior::ModifyPresentBehavior(void* presentActor) { case ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE: case ACTOR_1EF_GREEN_PRESENT_COLLECTIBLE: case ACTOR_1F1_RED_PRESENT_COLLECTIBLE: - GetPresentLevelFlag(actor, presentLevelFlagMap.at((actor_e)actor->actor_info->actorId)); + levelFlag = (LEVEL_FLAG_11_FP_UNKNOWN + (actor->actor_info->actorId - ACTOR_1ED_BLUE_PRESENT_COLLECTIBLE)); + if (levelSpecificFlags_get(levelFlag)) { + marker_despawn(actor->marker); + } break; default: break; diff --git a/src/port/Rando/ObjectBehavior/Prop.cpp b/src/port/Rando/ObjectBehavior/Prop.cpp new file mode 100644 index 000000000..db6b416b9 --- /dev/null +++ b/src/port/Rando/ObjectBehavior/Prop.cpp @@ -0,0 +1,52 @@ +#include "ObjectBehavior.h" +#include "port/Rando/Logic/Logic.h" +#include "port/Rando/CustomObject/CustomObject.h" + +#include +#include "port/UI/cvar_prefixes.h" +#include +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include "spdlog/spdlog.h" + +#define BLUE_EGG_OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_BLUE_EGGS].optionValue +#define MUSIC_NOTE_OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_MUSIC_NOTES].optionValue + +void Rando::ObjectBehavior::InitPropBehavior() { + COND_VB_SHOULD(VB_OVERRIDE_PROP_SPAWN, EVENT_PRIORITY_NORMAL, true, { + s16* spawnPosition = va_arg(args, s16*); + int32_t propAsset = va_arg(args, int32_t); + + if (!IS_RANDO) { + return; + } + + if (!BLUE_EGG_OPTION_ENABLED && propAsset == ASSET_6D7_SPRITE_BLUE_EGGS) { + return; + } + + if (!MUSIC_NOTE_OPTION_ENABLED && propAsset == ASSET_6D6_SPRITE_MUSIC_NOTE) { + return; + } + + int32_t position[3]; + position[0] = spawnPosition[0]; + position[1] = spawnPosition[1]; + position[2] = spawnPosition[2]; + + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByPosition(position[0], position[1], position[2]); + if (randoCheckId == RC_UNKNOWN) { + *should = false; + return; + } + + if (!Rando::Logic::IsCheckShuffled(randoCheckId)) { + *should = false; + return; + } + + Actor* randoCustomActor = CustomObject::ShouldCreateCustomActorEX(randoCheckId, position, true); + *should = true; + }) +} diff --git a/src/port/Rando/ObjectBehavior/StopNSwop.cpp b/src/port/Rando/ObjectBehavior/StopNSwop.cpp index 335f5cdec..df6b232d4 100644 --- a/src/port/Rando/ObjectBehavior/StopNSwop.cpp +++ b/src/port/Rando/ObjectBehavior/StopNSwop.cpp @@ -40,7 +40,7 @@ void Rando::ObjectBehavior::ModifyStopNSwopWorldBehavior(void* snsActor) { void Rando::ObjectBehavior::InitStopNSwopBehavior() { COND_VB_SHOULD(VB_OVERRIDE_SNS_MAP_CHECK, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { *should = true; }) COND_VB_SHOULD(VB_OVERRIDE_TIMED_DIALOGUE, EVENT_PRIORITY_NORMAL, IS_RANDO && OPTION_ENABLED, { - asset_e textId = (asset_e)va_arg(args, int); + asset_e textId = va_arg(args, asset_e); if (textId == ASSET_DB3_DIALOG_SNS_EGG_1_TEXT || textId == ASSET_DB5_DIALOG_ICE_KEY_TEXT || textId == ASSET_DB2_DIALOG_MUMBO_MISTAKE_2) { diff --git a/src/port/Rando/ObjectBehavior/Switch.cpp b/src/port/Rando/ObjectBehavior/Switch.cpp index c26be158c..619f4979b 100644 --- a/src/port/Rando/ObjectBehavior/Switch.cpp +++ b/src/port/Rando/ObjectBehavior/Switch.cpp @@ -6,7 +6,13 @@ #include "spdlog/spdlog.h" extern "C" { +Actor* actorArray_findActorFromActorId(enum actor_e actor_id); void destroyJiggy(Actor* thisx, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, enum volatile_flags_e arg6); + +s32 mapSpecificFlags_get(s32 i); +void mapSpecificFlags_set(s32 i, s32 val); + +void actor_collisionOff(Actor*); } #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue diff --git a/src/port/Rando/Rando.cpp b/src/port/Rando/Rando.cpp index 6dd76de7a..cee6eb6b4 100644 --- a/src/port/Rando/Rando.cpp +++ b/src/port/Rando/Rando.cpp @@ -5,7 +5,7 @@ #include "MiscBehavior/MiscBehavior.h" #include "port/Rando/CheckTracker/CheckTracker.h" // #include "port/Rando/EntranceTracker/EntranceTracker.h" -#include "port/Rando/Spoiler/Spoiler.h" +// #include "port/Rando/Spoiler/Spoiler.h" #include "port/ShipInit.hpp" #include "spdlog/spdlog.h" @@ -23,7 +23,7 @@ void Rando::Init() { fs::create_directory(randomizerFolderPath); } - Rando::Spoiler::RefreshSpoilerLogs(); + // Rando::Spoiler::RefreshSpoilerLogs(); Rando::MiscBehavior::Init(); // Rando::EntranceTracker::Init(); // Ship::Context::GetInstance()->GetFileDropMgr()->RegisterDropHandler(Rando::Spoiler::HandleFileDropped); diff --git a/src/port/Rando/Rando.h b/src/port/Rando/Rando.h index 7d5f7ecb4..f2897cc38 100644 --- a/src/port/Rando/Rando.h +++ b/src/port/Rando/Rando.h @@ -22,10 +22,6 @@ extern int16_t selectedFileNum; #define RANDO_SAVE_OPTIONS gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.randoSaveOption #define RANDO_SAVE_FLAGS gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.randoSaveFlag -// Loaded rando file's seed id, or 0 if none. -#define RANDO_SEED \ - (selectedFileNum == DEFAULT_FILE_NUM ? 0 : gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.seedId) - // #define RANDO_SAVE_ENTRANCES(fileNum) gSaveBuffer.files[fileNum]->shipSaveData.randoSaveData.randoSaveEntrances // #define RANDO_EVENTS gSaveContext.save.shipSaveInfo.rando.randoEvents // #define RANDO_STARTING_ITEMS gSaveContext.save.shipSaveInfo.rando.randoStartingItems diff --git a/src/port/Rando/Spoiler/File.cpp b/src/port/Rando/Spoiler/File.cpp deleted file mode 100644 index 67bf5f119..000000000 --- a/src/port/Rando/Spoiler/File.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "Spoiler.h" -#include "port/UI/Notification.h" -#include "ship/Context.h" -#include - -extern std::string CollapsedJSONArray(const nlohmann::ordered_json& jsonFile); - -namespace fs = std::filesystem; - -namespace Rando { - -namespace Spoiler { - -void SaveToFile(const std::string& fileName, nlohmann::ordered_json spoiler) { - std::string testDirectory = Ship::Context::GetPathRelativeToAppDirectory("randomizer/", "bk64"); - std::string filePath = Ship::Context::GetPathRelativeToAppDirectory("randomizer/" + fileName, "bk64"); - - if (!fs::exists(testDirectory)) { - fs::create_directories(testDirectory); - } - - std::ofstream fileStream(filePath); - if (!fileStream.is_open()) { - Notification::Emit( - { .message = "Error: Failed to open spoiler file.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); - return; - } - - std::string collapsedString = CollapsedJSONArray(spoiler); - if (fileStream.is_open()) { - fileStream << collapsedString; - fileStream.close(); - } else { - Notification::Emit( - { .message = "Error: Failed to open save file.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); - } - - fileStream << spoiler.dump(4); - RefreshSpoilerLogs(); -} - -nlohmann::json LoadFromFile(const std::string& fileName) { - nlohmann::json spoiler; - std::string spoilerFilePath = Ship::Context::GetPathRelativeToAppDirectory("randomizer/" + fileName, "bk64"); - std::ifstream fileStream(spoilerFilePath); - - if (!fs::exists(spoilerFilePath)) { - return spoiler; - } - - if (!fileStream.is_open()) { - Notification::Emit( - { .message = "Error: Failed to open spoiler file.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); - return spoiler; - } - - try { - fileStream >> spoiler; - } catch (nlohmann::json::exception& e) { - throw std::runtime_error("Failed to parse spoiler file: " + std::string(e.what())); - } - - if (!spoiler.contains("type") || spoiler["type"] != "LIGHTHOUSE_RANDO_SPOILER") { - throw std::runtime_error("Spoiler file is not a valid spoiler file"); - } - - return spoiler; -} - -} // namespace Spoiler - -} // namespace Rando diff --git a/src/port/Rando/Spoiler/Generate.cpp b/src/port/Rando/Spoiler/Generate.cpp deleted file mode 100644 index c98ce18a8..000000000 --- a/src/port/Rando/Spoiler/Generate.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "Spoiler.h" -#include -#include "port/Rando/Logic/Logic.h" -#include "port/UI/Notification.h" - -extern void RandoSaveCheck_to_json(nlohmann::json& j, const RandoSaveCheck& randoSaveCheck); -extern RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& randoSaveCheck); - -namespace Rando { - -namespace Spoiler { -nlohmann::ordered_json GenerateFromPoolGeneration() { - nlohmann::ordered_json orderedSpoiler = nlohmann::ordered_json::object(); - - orderedSpoiler["type"] = "LIGHTHOUSE_RANDO_SPOILER"; - orderedSpoiler["seed"] = randoFinalSeed; // TODO: Add once Manual Seed Input is finished. - - orderedSpoiler["options"] = nlohmann::json::object(); - for (auto& optionEntry : RANDO_SAVE_OPTIONS) { - orderedSpoiler["options"][optionEntry.name] = optionEntry.optionValue; - } - - orderedSpoiler["checks"] = nlohmann::json::object(); - - for (auto& checkEntry : RANDO_SAVE_CHECKS) { - nlohmann::json check = nlohmann::json::object(); - RandoSaveCheck_to_json(check, checkEntry); - - if (checkEntry.randoCheckId == RC_UNKNOWN) { - checkEntry.name = "RC_UNKNOWN"; - } - - orderedSpoiler["checks"][checkEntry.name] = check; - } - - orderedSpoiler["loadout"] = nlohmann::json::object(); - - orderedSpoiler["loadout"]["abilities"] = nlohmann::json::array(); - orderedSpoiler["loadout"]["abilities"].push_back(ABILITY_A_HOLD_A_JUMP_HIGHER); - orderedSpoiler["loadout"]["abilities"].push_back(ABILITY_13_1ST_NOTEDOOR); - for (auto& [abilityId, abilityInfo] : abilityLoadoutMap) { - if (CVarGetInteger(abilityInfo.second, 0)) { - orderedSpoiler["loadout"]["abilities"].push_back(abilityId); - } - } - - orderedSpoiler["loadout"]["items"] = nlohmann::json::array(); - for (auto& [item, itemInfo] : itemLoadoutMap) { - if (CVarGetInteger(itemInfo.second, 0)) { - orderedSpoiler["loadout"]["items"].push_back(item); - } - } - - return orderedSpoiler; -} - -void GenerateFromSpoiler(nlohmann::json spoiler) { - Rando::Logic::shuffledPool.clear(); - - if (!spoiler.contains("type") || spoiler["type"] != "LIGHTHOUSE_RANDO_SPOILER") { - Notification::Emit({ .message = "Error: Invalid Spoiler Log.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) }); - return; - } - - gameFile_saveData[selectedFileNum].shipSaveData.randoSaveData.seedId = spoiler["seed"]; - - if (spoiler.contains("checks") && !spoiler["checks"].empty()) { - for (auto& data : spoiler["checks"].items()) { - RandoSaveCheck checkEntry = RandoSaveCheck_from_json(data.value(), checkEntry); - checkEntry.name = Rando::StaticData::Checks[checkEntry.randoCheckId].name; - RANDO_SAVE_CHECKS[checkEntry.randoCheckId] = checkEntry; - - Rando::Logic::shuffledPool.push_back(checkEntry); - } - } - - if (spoiler.contains("options") && !spoiler["options"].empty()) { - for (auto& data : spoiler["options"].items()) { - for (auto& [optionId, staticOption] : Rando::StaticData::Options) { - if (staticOption.name == data.key()) { - RANDO_SAVE_OPTIONS[optionId].optionValue = data.value().get(); - break; - } - } - } - } - - if (spoiler.contains("loadout") && !spoiler["loadout"].empty()) { - if (spoiler["loadout"].contains("abilities") && !spoiler["loadout"]["abilities"].empty()) { - for (auto& data : spoiler["loadout"]["abilities"].items()) { - ability_setLearned(data.value(), true); - ability_setHasUsed(data.value()); - } - } - - if (spoiler["loadout"].contains("items") && !spoiler["loadout"]["items"].empty()) { - for (auto& data : spoiler["loadout"]["items"].items()) { - item_setMaxCount(data.value()); - } - } - } - - Rando::Logic::GrantFileProgressFlags(); - Rando::Logic::GrantSpiralMountainChecks(); - - Notification::Emit({ .message = "Loaded from Spoiler Log.", .messageColor = ImVec4(0, 0.85f, 0, 1) }); -} - -} // namespace Spoiler - -} // namespace Rando diff --git a/src/port/Rando/Spoiler/RefreshOptions.cpp b/src/port/Rando/Spoiler/RefreshOptions.cpp deleted file mode 100644 index 6568f9ed0..000000000 --- a/src/port/Rando/Spoiler/RefreshOptions.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "Spoiler.h" -#include -#include "ship/Context.h" -#include - -#include - -std::vector Rando::Spoiler::spoilerLogs; -const std::filesystem::path randomizerFolderPath(Ship::Context::GetPathRelativeToAppDirectory("randomizer", "bk64")); - -void Rando::Spoiler::RefreshSpoilerLogs() { - Rando::Spoiler::spoilerLogs.clear(); - - Rando::Spoiler::spoilerLogs.push_back("Generate New Seed"); - s32 spoilerFileIndex = -1; - - if (!std::filesystem::exists(randomizerFolderPath)) { - std::filesystem::create_directory(randomizerFolderPath); - } - - for (const auto& entry : std::filesystem::directory_iterator(randomizerFolderPath)) { - if (entry.is_regular_file()) { - std::string fileName = entry.path().filename().string(); - - Rando::Spoiler::spoilerLogs.push_back(fileName); - - // Check if the current file is the one set in the cvar - if (fileName == CVarGetString("gRandoSettings.SpoilerFile", "")) { - spoilerFileIndex = Rando::Spoiler::spoilerLogs.size() - 1; - } - } - } - - if (spoilerFileIndex == -1) { - CVarSetInteger("gRandoSettings.SpoilerFileIndex", 0); - CVarSetString("gRandoSettings.SpoilerFile", ""); - } else { - CVarSetInteger("gRandoSettings.SpoilerFileIndex", spoilerFileIndex); - } -} \ No newline at end of file diff --git a/src/port/Rando/Spoiler/Spoiler.h b/src/port/Rando/Spoiler/Spoiler.h deleted file mode 100644 index 272e70f6a..000000000 --- a/src/port/Rando/Spoiler/Spoiler.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RANDO_SPOILER_H -#define RANDO_SPOILER_H - -#include -#include -#include "port/Rando/Logic/Logic.h" -#include - -namespace Rando { - -namespace Spoiler { -extern std::vector spoilerLogs; - -nlohmann::ordered_json GenerateFromPoolGeneration(); - -void GenerateFromSpoiler(nlohmann::json spoiler); -void SaveToFile(const std::string& fileName, nlohmann::ordered_json spoiler); -nlohmann::json LoadFromFile(const std::string& filePath); - -void RefreshSpoilerLogs(); - -} // namespace Spoiler - -} // namespace Rando - -#endif \ No newline at end of file diff --git a/src/port/Rando/StaticData/Checks.cpp b/src/port/Rando/StaticData/Checks.cpp index 9ac508693..8a23c19b4 100644 --- a/src/port/Rando/StaticData/Checks.cpp +++ b/src/port/Rando/StaticData/Checks.cpp @@ -4,6 +4,11 @@ #include "prop.h" #include "include/core1/sns.h" +extern "C" { +enum map_e gsworld_getMap(void); +enum level_e map_getLevel(enum map_e map); +} + namespace Rando { namespace StaticData { @@ -19,75 +24,75 @@ std::array CheckNames = std::array(); // clang-format off std::map Checks = { RC(RC_UNKNOWN, RCTYPE_UNKNOWN, LEVEL_D_CUTSCENE, RI_UNKNOWN, NULL, 0, 0, 0), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4309, 100, 6025), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4368, 100, 6106), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4428, 100, 6198), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4484, 100, 6296), - RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4541, 100, 6389), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4133, 1400, -1304), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4208, 1400, -1422), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4343, 1400, -1422), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4412, 1400, -1304), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4342, 1400, -1184), - RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4207, 1400, -1184), - RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1185, 0, 0), - RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -1189, 0, 0), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 300, 0, -1830), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 150, 0, -1829), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -150, 0, -1832), - RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -300, 0, -1831), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7873, 1000, -6525), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7591, 1000, -6568), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7309, 1000, -6610), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -7017, 1000, -6552), - RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -6729, 1000, -6507), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3920, 1250, -7549), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3920, 1350, -7549), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3920, 1450, -7549), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 839, 1250, 2740), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 839, 1350, 2740), - RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 839, 1450, 2740), - RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3209, 150, -253), - RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -3403, 150, -761), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5917, 0, 2497), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5705, 0, 2672), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5283, 0, 3047), - RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 5087, 0, 3251), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1813, 0, -2967), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1857, 0, -3096), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1889, 0, -3228), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -404, 0, -1715), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -518, 0, -1728), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -628, 0, -1744), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1497, 0, -3242), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1501, 0, -3121), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 1506, 0, -3005), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -635, 0, -1361), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -528, 0, -1380), - RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, -427, 0, -1398), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4592, 0, -3489), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4586, 0, -3710), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4809, 0, -3711), - RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG, NULL, 4814, 0, -3490), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4309, 100, 6025), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4368, 100, 6106), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4428, 100, 6198), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4484, 100, 6296), + RC(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4541, 100, 6389), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4133, 1400, -1304), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4208, 1400, -1422), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4343, 1400, -1422), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4412, 1400, -1304), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4342, 1400, -1184), + RC(RC_BGS_BLUE_EGG_ELEVATED_WALKWAY_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4207, 1400, -1184), + RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1185, 0, 0), + RC(RC_BGS_BLUE_EGG_INSIDE_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -1189, 0, 0), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 300, 0, -1830), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 150, 0, -1829), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -150, 0, -1832), + RC(RC_BGS_BLUE_EGG_INSIDE_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -300, 0, -1831), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7873, 1000, -6525), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7591, 1000, -6568), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7309, 1000, -6610), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -7017, 1000, -6552), + RC(RC_BGS_BLUE_EGG_MAZE_WALKWAY_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -6729, 1000, -6507), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1250, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1350, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_BLUE_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3920, 1450, -7549), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1250, 2740), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1350, 2740), + RC(RC_BGS_BLUE_EGG_POLE_NEAR_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 839, 1450, 2740), + RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3209, 150, -253), + RC(RC_BGS_BLUE_EGG_STUMP_NEAR_BIG_EGG_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -3403, 150, -761), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5917, 0, 2497), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5705, 0, 2672), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5283, 0, 3047), + RC(RC_BGS_BLUE_EGG_SWAMP_BEHIND_TANKTUP_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 5087, 0, 3251), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1813, 0, -2967), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1857, 0, -3096), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1889, 0, -3228), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -404, 0, -1715), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -518, 0, -1728), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -628, 0, -1744), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1497, 0, -3242), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_5, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1501, 0, -3121), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_MR_VILES_6, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 1506, 0, -3005), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -635, 0, -1361), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -528, 0, -1380), + RC(RC_BGS_BLUE_EGG_SWAMP_NEAR_SWITCH_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, -427, 0, -1398), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_1, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4592, 0, -3489), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_2, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4586, 0, -3710), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_3, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4809, 0, -3711), + RC(RC_BGS_BLUE_EGG_SWAMP_UNDER_HUTS_4, RCTYPE_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, NULL, 4814, 0, -3490), RC(RC_BGS_EMPTY_HONEYCOMB_MUMBOS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_7_BGS_MUMBOS, 0, 600, 0), RC(RC_BGS_EMPTY_HONEYCOMB_TANKTUP, RCTYPE_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, HONEYCOMB_8_BGS_TANKTUP, 0, 537, -1157), - RC(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, -4382, 985, 2799), - RC(RC_BGS_EXTRA_LIFE_MR_VILE_1, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 0, 0, 0), - RC(RC_BGS_EXTRA_LIFE_MR_VILE_2, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 0, 0, 0), - RC(RC_BGS_EXTRA_LIFE_MR_VILE_3, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 0, 0, 0), - RC(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE, NULL, 7149, 0, -4353), - RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_ABOVE_THE_EGG, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, -4382, 985, 2799), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_1, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_2, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_MR_VILE_3, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_EXTRA_LIFE_SWAMP_BY_THE_HUTS, RCTYPE_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, NULL, 7149, 0, -4353), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_ELEVATED_WALKWAY_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_MAZE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_TANKTUP_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), + RC(RC_BGS_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, NULL, 0, 0, 0), RC(RC_BGS_JIGGY_CROCTUS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_22_CROCTUS, 0, 0, 0), RC(RC_BGS_JIGGY_ELEVATED_WALKWAY, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_20_BGS_ELEVATED_WALKWAY, 0, 0, 0), RC(RC_BGS_JIGGY_FLIBBITS, RCTYPE_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JIGGY_BUBBLEGLOOP_SWAMP, JIGGY_24_BGS_FLIBBITS, 0, 0, 0), @@ -104,16 +109,16 @@ std::map Checks = { RC(RC_BGS_JINJO_PINK, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_PINK_BUBBLEGLOOP_SWAMP, NULL, 5670, 0, -4158), RC(RC_BGS_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_JINJO_YELLOW_BUBBLEGLOOP_SWAMP, NULL, -1606, 500, 2797), RC(RC_BGS_MOLEHILL_WADING_BOOTS, RCTYPE_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MOLEHILL_WADING_BOOTS, ABILITY_E_WADING_BOOTS, 4297, 100, 6286), - RC(RC_BGS_MUMBO_TOKEN_ALCOVE_ABOVE_YELLOW_FLIBBITS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1B_BGS_ALCOVE_ABOVE_YELLOW_FLIBBITS, 4278, 1400, -1302), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1A_BGS_BEHIND_MUMBOS_SKULL, -6940, 1000, -5838), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1C_BGS_BEHIND_TIPTUP, 0, 0, -1829), - RC(RC_BGS_MUMBO_TOKEN_BEHIND_YELLOW_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_18_BGS_BEHIND_YELLOW_JINJO, -1855, 0, 2835), - RC(RC_BGS_MUMBO_TOKEN_FLOATING_BETWEEN_HUT_AND_CROCTUS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_19_BGS_FLOATING_BETWEEN_HUT_AND_CROCTUS, 6546, 2992, -4697), - RC(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1D_BGS_INSIDE_MR_VILES, 0, 300, -1754), - RC(RC_BGS_MUMBO_TOKEN_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_1E_BGS_INSIDE_MUMBOS_SKULL, 0, 0, -450), - RC(RC_BGS_MUMBO_TOKEN_TOP_OF_POLE_NEXT_TO_BIG_EGG, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_17_BGS_TOP_OF_POLE_NEXT_TO_BIG_EGG, -3993, 1055, 1295), - RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_1, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_15_BGS_UNDER_HUT_1, 5049, 0, -5142), - RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_2, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN, MUMBOTOKEN_16_BGS_UNDER_HUT_2, 5347, 0, -5055), + RC(RC_BGS_MUMBO_TOKEN_ALCOVE_ABOVE_YELLOW_FLIBBITS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1B_BGS_ALCOVE_ABOVE_YELLOW_FLIBBITS, 4278, 1400, -1302), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1A_BGS_BEHIND_MUMBOS_SKULL, -6940, 1000, -5838), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_TIPTUP, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1C_BGS_BEHIND_TIPTUP, 0, 0, -1829), + RC(RC_BGS_MUMBO_TOKEN_BEHIND_YELLOW_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_18_BGS_BEHIND_YELLOW_JINJO, -1855, 0, 2835), + RC(RC_BGS_MUMBO_TOKEN_FLOATING_BETWEEN_HUT_AND_CROCTUS, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_19_BGS_FLOATING_BETWEEN_HUT_AND_CROCTUS, 6546, 2992, -4697), + RC(RC_BGS_MUMBO_TOKEN_INSIDE_MR_VILES, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1D_BGS_INSIDE_MR_VILES, 0, 300, -1754), + RC(RC_BGS_MUMBO_TOKEN_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_1E_BGS_INSIDE_MUMBOS_SKULL, 0, 0, -450), + RC(RC_BGS_MUMBO_TOKEN_TOP_OF_POLE_NEXT_TO_BIG_EGG, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_17_BGS_TOP_OF_POLE_NEXT_TO_BIG_EGG, -3993, 1055, 1295), + RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_1, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_15_BGS_UNDER_HUT_1, 5049, 0, -5142), + RC(RC_BGS_MUMBO_TOKEN_UNDER_HUT_2, RCTYPE_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, MUMBOTOKEN_16_BGS_UNDER_HUT_2, 5347, 0, -5055), RC(RC_BGS_NOTE_ABOVE_MR_VILES_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -912, 347, -3385), RC(RC_BGS_NOTE_ABOVE_MR_VILES_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1073, 318, -3495), RC(RC_BGS_NOTE_ABOVE_MR_VILES_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, -1247, 405, -3608), @@ -214,64 +219,64 @@ std::map Checks = { RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_1, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 2921, 93, -513), RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_2, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3020, 93, -304), RC(RC_BGS_NOTE_THIRD_SHORT_SWAMP_LOG_3, RCTYPE_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, NULL, 3114, 93, -86), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6379, 5087, 2586), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6582, 5047, 2536), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6785, 4876, 2454), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 6989, 4703, 2388), - RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 7194, 4526, 2321), - RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2588, 5456, 2596), - RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2494, 5456, 2556), - RC(RC_CC_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -5274, 3269, -270), - RC(RC_CC_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4937, 3221, -597), - RC(RC_CC_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4492, 3113, -449), - RC(RC_CC_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4392, 3051, -27), - RC(RC_CC_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -4722, 3104, 299), - RC(RC_CC_BLUE_EGG_ENTRANCE_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -5159, 3232, 178), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2293, 3662, 2354), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2360, 3662, 2231), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2329, 3662, 2107), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2216, 3662, 2018), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 2094, 3662, 1968), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 1970, 3662, 1998), - RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 1895, 3662, 2117), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -390, -116, 1316), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -476, -192, 480), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -433, -214, -453), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, -390, -160, -1300), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 391, -160, -1300), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 434, -214, -453), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 476, -192, 480), - RC(RC_CC_BLUE_EGG_NEAR_RINGS_8, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 389, -116, 1316), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 15075, 3648, -20), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14862, 3649, -17), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14651, 3649, -20), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14437, 3649, -20), - RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 14225, 3649, -20), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2392, 5200), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2293, 5276), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2197, 5350), - RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 0, 2099, 5425), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3854, 1202, -532), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3692, 1202, -356), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3529, 1202, -182), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3369, 1207, -10), - RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3206, 1202, 165), - RC(RC_CC_BLUE_EGG_YELLOW_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 4271, 5261, -2936), - RC(RC_CC_BLUE_EGG_YELLOW_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG, NULL, 3247, 5262, -2842), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6379, 5087, 2586), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6582, 5047, 2536), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6785, 4876, 2454), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 6989, 4703, 2388), + RC(RC_CC_BLUE_EGG_ABOVEWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 7194, 4526, 2321), + RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2588, 5456, 2596), + RC(RC_CC_BLUE_EGG_ALCOVE_WITH_OPEN_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2494, 5456, 2556), + RC(RC_CC_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -5274, 3269, -270), + RC(RC_CC_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4937, 3221, -597), + RC(RC_CC_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4492, 3113, -449), + RC(RC_CC_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4392, 3051, -27), + RC(RC_CC_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -4722, 3104, 299), + RC(RC_CC_BLUE_EGG_ENTRANCE_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -5159, 3232, 178), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2293, 3662, 2354), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2360, 3662, 2231), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2329, 3662, 2107), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2216, 3662, 2018), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 2094, 3662, 1968), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 1970, 3662, 1998), + RC(RC_CC_BLUE_EGG_LEDGE_NEAR_CHOMPA_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 1895, 3662, 2117), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -390, -116, 1316), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -476, -192, 480), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -433, -214, -453), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, -390, -160, -1300), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 391, -160, -1300), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_6, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 434, -214, -453), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_7, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 476, -192, 480), + RC(RC_CC_BLUE_EGG_NEAR_RINGS_8, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 389, -116, 1316), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 15075, 3648, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14862, 3649, -17), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14651, 3649, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14437, 3649, -20), + RC(RC_CC_BLUE_EGG_NEAR_SNIPPETS_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 14225, 3649, -20), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2392, 5200), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2293, 5276), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2197, 5350), + RC(RC_CC_BLUE_EGG_SLOW_SAWBLADES_EXIT_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 0, 2099, 5425), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3854, 1202, -532), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3692, 1202, -356), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_3, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3529, 1202, -182), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_4, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3369, 1207, -10), + RC(RC_CC_BLUE_EGG_UNDERWATER_PIPE_5, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3206, 1202, 165), + RC(RC_CC_BLUE_EGG_YELLOW_GRATE_1, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 4271, 5261, -2936), + RC(RC_CC_BLUE_EGG_YELLOW_GRATE_2, RCTYPE_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN, RI_BLUE_EGG_CLANKERS_CAVERN, NULL, 3247, 5262, -2842), RC(RC_CC_EMPTY_HONEYCOMB_ABOVEWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_6_CC_ABOVE_WATER, 7886, 4272, 1969), RC(RC_CC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, HONEYCOMB_5_CC_UNDERWATER, 3718, 3311, 2519), - RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE, NULL, 4570, 3727, 2783), - RC(RC_CC_EXTRA_LIFE_JINJO_PIPE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE, NULL, 7309, 4267, 2286), - RC(RC_CC_EXTRA_LIFE_YELLOW_GRATE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE, NULL, 1752, 5270, -2214), - RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CC_EXTRA_LIFE_CLANKERS_LEFT_FIN, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 4570, 3727, 2783), + RC(RC_CC_EXTRA_LIFE_JINJO_PIPE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 7309, 4267, 2286), + RC(RC_CC_EXTRA_LIFE_YELLOW_GRATE, RCTYPE_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN, RI_EXTRA_LIFE_CLANKERS_CAVERN, NULL, 1752, 5270, -2214), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_INSIDE_CLANKER_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_1, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_2, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), + RC(RC_CC_HONEYCOMB_BEEHIVE_NEAR_THE_YELLOW_GRATES_3, RCTYPE_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN, RI_HONEYCOMB_CLANKERS_CAVERN, NULL, 0, 0, 0), RC(RC_CC_JIGGY_BOLT, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_18_CC_BOLT, 90, 5962, -12), RC(RC_CC_JIGGY_CLANKER_RAISED, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_17_CC_CLANKER_RAISED, 0, 0, 0), RC(RC_CC_JIGGY_FAST_SAWBLADES, RCTYPE_JIGGY, LEVEL_3_CLANKERS_CAVERN, RI_JIGGY_CLANKERS_CAVERN, JIGGY_1E_CC_FAST_SAWBLADES, 0, -340, -1604), @@ -288,11 +293,11 @@ std::map Checks = { RC(RC_CC_JINJO_PINK, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_PINK_CLANKERS_CAVERN, NULL, 3644, -474, 48), RC(RC_CC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_3_CLANKERS_CAVERN, RI_JINJO_YELLOW_CLANKERS_CAVERN, NULL, -4726, 5337, -110), RC(RC_CC_MOLEHILL_WONDERWING, RCTYPE_MOLEHILL, LEVEL_3_CLANKERS_CAVERN, RI_MOLEHILL_WONDERWING, ABILITY_12_WONDERWING, -259, -500, 1413), - RC(RC_CC_MUMBO_TOKEN_CHOMPA_BEHIND_CLANKERS_TAIL, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_10_CC_CHOMPA_BEHIND_CLANKERS_TAIL, 9823, 4225, -19), - RC(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE, -9694, 5272, 1607), - RC(RC_CC_MUMBO_TOKEN_TUNNEL_RIGHT_OF_CLANKER, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, 870, 2146, -3148), - RC(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_13_CC_ALCOVE_WITH_OPEN_GRATE, 2028, 5456, 2344), - RC(RC_CC_MUMBO_TOKEN_CLANKERS_LEFT_TOOTH, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN, MUMBOTOKEN_14_CC_CLANKERS_LEFT_TOOTH, 532, 1424, 6632), + RC(RC_CC_MUMBO_TOKEN_CHOMPA_BEHIND_CLANKERS_TAIL, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_10_CC_CHOMPA_BEHIND_CLANKERS_TAIL, 9823, 4225, -19), + RC(RC_CC_MUMBO_TOKEN_ABOVE_LEVEL_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE, -9694, 5272, 1607), + RC(RC_CC_MUMBO_TOKEN_TUNNEL_RIGHT_OF_CLANKER, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, 870, 2146, -3148), + RC(RC_CC_MUMBO_TOKEN_ALCOVE_WITH_OPEN_GRATE, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_13_CC_ALCOVE_WITH_OPEN_GRATE, 2028, 5456, 2344), + RC(RC_CC_MUMBO_TOKEN_CLANKERS_LEFT_TOOTH, RCTYPE_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN, RI_MUMBO_TOKEN_CLANKERS_CAVERN, MUMBOTOKEN_14_CC_CLANKERS_LEFT_TOOTH, 532, 1424, 6632), RC(RC_CC_NOTE_ABOVE_BOLT_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2036, 5693, -15), RC(RC_CC_NOTE_ABOVE_BOLT_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1533, 5693, 381), RC(RC_CC_NOTE_ABOVE_BOLT_3, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 1043, 5693, 377), @@ -393,164 +398,164 @@ std::map Checks = { RC(RC_CC_NOTE_UNDERWATER_PIPE_7, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 6804, 1184, 2361), RC(RC_CC_NOTE_YELLOW_GRATE_1, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 2240, 5262, -2473), RC(RC_CC_NOTE_YELLOW_GRATE_2, RCTYPE_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLANKERS_CAVERN, NULL, 5270, 5261, -2937), - RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 825, 758, 531), - RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 682, 758, 583), - RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 536, 758, 628), - RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -113, 304, 3001), - RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 115, 605, 3001), - RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -170, 0, -700), - RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 0, -20, -630), - RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 170, 0, -699), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1362, 4419, 2014), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1860, 4469, 1580), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2181, 4519, 1118), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5700, 40, -1000), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5500, 40, -500), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5350, 40, 0), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3513, 4102, -541), - RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3595, 4104, 478), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3615, 2773, 1411), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4356, 2821, 356), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4920, 2778, 1222), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3735, 2828, -787), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4431, 2830, -882), - RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5370, 2882, -787), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3270, 103, -815), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3483, 109, -341), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3483, 99, 342), - RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3270, 121, 815), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3930, 4900, 316), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4378, 4900, 764), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5018, 4900, 773), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5468, 4900, 314), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5468, 4900, -315), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -5018, 4900, -773), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4378, 4900, -764), - RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -3930, 4900, -315), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 510, 387, 0), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 0, 398, 520), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 0, 398, -520), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 472, 413, -237), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 383, 413, -295), - RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 287, 413, -357), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 975, 900, 2573), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2566, 900, 968), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2568, 900, -968), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 1950, 900, -1949), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 975, 900, -2574), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -50, 1050, -2750), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -975, 900, -2575), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2579, 1100, -980), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2579, 900, 980), - RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -977, 900, 2573), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2140, 2938, -1157), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1696, 3050, -1731), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1072, 3157, -2180), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 790, 3300, -2345), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 1427, 3300, -1995), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 1873, 3899, -1580), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2267, 3963, -1018), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 2450, 4019, -394), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4366, -599, -311), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 5404, -593, -734), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 5831, -589, 301), - RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4769, -600, 726), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4302, 3719, 583), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 4214, 3719, 1076), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3653, 3719, 1587), - RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 3080, 3719, 2063), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -633, 5, -4826), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -727, 5, -5426), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -635, 5, -6006), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 9, 5, -6099), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 634, 5, -6008), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 726, 5, -5426), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 636, 5, -4834), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 9, 5, -4734), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4815, 125, 200), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4930, 125, 0), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4815, 125, -201), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4585, 125, -200), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4470, 125, 0), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -4585, 125, 200), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1153, 4019, 4293), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1284, 4019, 4611), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1599, 4019, 4747), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -2047, 4019, 4303), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1920, 4019, 3996), - RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -1603, 4019, 3851), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -285, 513, -354), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -395, 513, -280), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -504, 513, -205), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -577, 513, -110), - RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -646, 513, -5), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 253, -500, -621), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 617, -499, -263), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 621, -499, 254), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 258, -500, 624), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -254, -500, 621), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -622, -499, 259), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -624, -499, -254), - RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -262, -500, -619), - RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 244, 150, -509), - RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, 88, 250, 682), - RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG, NULL, -531, 450, -430), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 825, 758, 531), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 682, 758, 583), + RC(RC_CCW_BLUE_EGG_AUTUMN_GNAWTYS_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 536, 758, 628), + RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -113, 304, 3001), + RC(RC_CCW_BLUE_EGG_AUTUMN_LEAF_NEAR_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 115, 605, 3001), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -170, 0, -700), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, -20, -630), + RC(RC_CCW_BLUE_EGG_AUTUMN_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 170, 0, -699), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1362, 4419, 2014), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1860, 4469, 1580), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2181, 4519, 1118), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5700, 40, -1000), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5500, 40, -500), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5350, 40, 0), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3513, 4102, -541), + RC(RC_CCW_BLUE_EGG_AUTUMN_NEAR_TREEHOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3595, 4104, 478), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3615, 2773, 1411), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4356, 2821, 356), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4920, 2778, 1222), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3735, 2828, -787), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4431, 2830, -882), + RC(RC_CCW_BLUE_EGG_AUTUMN_TOP_OF_BRANCH_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5370, 2882, -787), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3270, 103, -815), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3483, 109, -341), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3483, 99, 342), + RC(RC_CCW_BLUE_EGG_ENTRANCE_HUB_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3270, 121, 815), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3930, 4900, 316), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4378, 4900, 764), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5018, 4900, 773), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5468, 4900, 314), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5468, 4900, -315), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -5018, 4900, -773), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4378, 4900, -764), + RC(RC_CCW_BLUE_EGG_SPRING_EYRIES_NEST_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -3930, 4900, -315), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 510, 387, 0), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, 398, 520), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 0, 398, -520), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 472, 413, -237), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 383, 413, -295), + RC(RC_CCW_BLUE_EGG_SPRING_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 287, 413, -357), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 975, 900, 2573), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2566, 900, 968), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2568, 900, -968), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1950, 900, -1949), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 975, 900, -2574), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -50, 1050, -2750), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -975, 900, -2575), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2579, 1100, -980), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_9, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2579, 900, 980), + RC(RC_CCW_BLUE_EGG_SPRING_LOWER_TREE_LEDGE_10, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -977, 900, 2573), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2140, 2938, -1157), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1696, 3050, -1731), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1072, 3157, -2180), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 790, 3300, -2345), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1427, 3300, -1995), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 1873, 3899, -1580), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2267, 3963, -1018), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_BEEHIVE_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 2450, 4019, -394), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4366, -599, -311), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 5404, -593, -734), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 5831, -589, 301), + RC(RC_CCW_BLUE_EGG_SPRING_NEAR_GNAWTYS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4769, -600, 726), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4302, 3719, 583), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 4214, 3719, 1076), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3653, 3719, 1587), + RC(RC_CCW_BLUE_EGG_SPRING_UNFINISHED_BRIDGE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 3080, 3719, 2063), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -633, 5, -4826), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -727, 5, -5426), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -635, 5, -6006), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 9, 5, -6099), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 634, 5, -6008), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 726, 5, -5426), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 636, 5, -4834), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_BIG_FLOWER_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 9, 5, -4734), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4815, 125, 200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4930, 125, 0), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4815, 125, -201), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4585, 125, -200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4470, 125, 0), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -4585, 125, 200), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1153, 4019, 4293), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1284, 4019, 4611), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1599, 4019, 4747), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -2047, 4019, 4303), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1920, 4019, 3996), + RC(RC_CCW_BLUE_EGG_SUMMER_NEAR_NABNUTS_HOUSE_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -1603, 4019, 3851), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -285, 513, -354), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -395, 513, -280), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -504, 513, -205), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -577, 513, -110), + RC(RC_CCW_BLUE_EGG_WINTER_INSIDE_NABNUTS_HOUSE_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -646, 513, -5), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 253, -500, -621), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 617, -499, -263), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 621, -499, 254), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 258, -500, 624), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -254, -500, 621), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -622, -499, 259), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -624, -499, -254), + RC(RC_CCW_BLUE_EGG_WINTER_NABNUTS_WINDOW_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -262, -500, -619), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_1, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 244, 150, -509), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_2, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, 88, 250, 682), + RC(RC_CCW_BLUE_EGG_WINTER_WINDOW_ABOVE_NABNUT_3, RCTYPE_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD, RI_BLUE_EGG_CLICK_CLOCK_WOOD, NULL, -531, 450, -430), RC(RC_CCW_EMPTY_HONEYCOMB_GNAWTYS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_D_CCW_GNAWTYS, 694, 998, 632), RC(RC_CCW_EMPTY_HONEYCOMB_NABNUTS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, HONEYCOMB_E_CCW_NABNUTS, 640, 513, -202), - RC(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -225, 640, 506), - RC(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 4050, 4284, 1010), - RC(RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -310, 730, -856), - RC(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -4993, 2896, -944), - RC(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 5100, 425, 0), - RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -693, 2, 528), - RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -310, 730, -855), - RC(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 3604, 22, -4012), - RC(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 5848, 4244, 612), - RC(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 833, 441, 133), - RC(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, -3157, 300, -3149), - RC(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE, NULL, 3078, -338, 3076), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_BEHIND_GNAWTYS_FIRE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -225, 640, 506), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_SNAREBEAR_NEAR_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 4050, 4284, 1010), + RC(RC_CCW_EXTRA_LIFE_AUTUMN_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -310, 730, -856), + RC(RC_CCW_EXTRA_LIFE_SPRING_BRANCHES_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -4993, 2896, -944), + RC(RC_CCW_EXTRA_LIFE_SPRING_SNAREBEAR_IN_THE_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 5100, 425, 0), + RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_BY_THE_JIGGY, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -693, 2, 528), + RC(RC_CCW_EXTRA_LIFE_SPRING_TOP_ROOM_IN_THE_BRANCHES, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -310, 730, -855), + RC(RC_CCW_EXTRA_LIFE_SUMMER_NEAR_THE_BIG_FLOWER, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3604, 22, -4012), + RC(RC_CCW_EXTRA_LIFE_SUMMER_TREEHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 5848, 4244, 612), + RC(RC_CCW_EXTRA_LIFE_SUMMER_TOP_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 833, 441, 133), + RC(RC_CCW_EXTRA_LIFE_WINTER_BENEATH_SIR_SLUSH, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, -3157, 300, -3149), + RC(RC_CCW_EXTRA_LIFE_WINTER_UNDER_THE_ICY_LAKE, RCTYPE_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD, RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, NULL, 3078, -338, 3076), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_ABOVE_THE_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_AUTUMN_IN_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_LEFT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_ENTRANCE_RIGHT_OF_SUMMER_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_BY_THE_BIG_FLOWER_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SPRING_UNDER_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_DRIED_UP_LAKE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_GRASS_NEAR_THE_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_SUMMER_OUTSIDE_NABNUTS_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_AROUND_THE_TREE_BASE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_INSIDE_MUMBOS_SKULL_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_1, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_2, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), + RC(RC_CCW_HONEYCOMB_BEEHIVE_WINTER_OUTSIDE_THE_TREEHOUSE_3, RCTYPE_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD, RI_HONEYCOMB_CLICK_CLOCK_WOOD, NULL, 0, 0, 0), RC(RC_CCW_JIGGY_EYRIE, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_49_CCW_EYRIE, 0, 0, 0), RC(RC_CCW_JIGGY_FLOWER, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4D_CCW_FLOWER, 0, 0, 0), RC(RC_CCW_JIGGY_GNAWTY, RCTYPE_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD, RI_JIGGY_CLICK_CLOCK_WOOD, JIGGY_4B_CCW_GNAWTY, 240, 600, 75), @@ -566,31 +571,31 @@ std::map Checks = { RC(RC_CCW_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_ORANGE_CLICK_CLOCK_WOOD, NULL, -1592, 900, -6073), RC(RC_CCW_JINJO_PINK, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_PINK_CLICK_CLOCK_WOOD, NULL, -225, 1039, -1100), RC(RC_CCW_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_8_CLICK_CLOCK_WOOD, RI_JINJO_YELLOW_CLICK_CLOCK_WOOD, NULL, -3602, 0, 4266), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6A_CCW_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, 153, 1857, 2677), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6D_CCW_AUTUMN_LEAF_NEAR_TREEHOUSE, 3405, 4107, 1003), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6B_CCW_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, 500, 166, 5125), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6C_CCW_AUTUMN_SNAREBEAR_TOP_OF_TREE, 0, 5830, -3325), - RC(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6E_CCW_AUTUMN_TOP_OF_BRANCH, -5929, 2586, 61), - RC(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5D_CCW_SPRING_FRONT_OF_EYRIE, -2750, 4586, -513), - RC(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_62_CCW_SPRING_NABNUTS_HOUSE, -575, 300, -139), - RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5F_CCW_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, 1904, 105, -2706), - RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_60_CCW_SPRING_SNAREBEAR_NEAR_ENTRANCE, 1000, 105, 5300), - RC(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5E_CCW_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, -2649, 0, -395), - RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_61_CCW_SPRING_TOP_OF_BEEHIVE, 0, 3513, -5240), - RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5C_CCW_SPRING_TOP_OF_BRANCH, -4053, 2894, 587), - RC(RC_CCW_MUMBO_TOKEN_SPRING_UNFINISHED_WOOD_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_5B_CCW_SPRING_UNFINISHED_WOOD_TREEHOUSE, 6134, 4244, 306), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_64_CCW_SUMMER_BIG_FLOWER_FIELD, -3578, 40, -4259), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_67_CCW_SUMMER_ENTRANCE_GNAWTYS_HOUSE, 2700, -600, 0), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_68_CCW_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, 2043, 3534, 1799), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_69_CCW_SUMMER_INSIDE_MUMBOS_SKULL, 0, 416, 500), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_63_CCW_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, -1861, 4469, 1583), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_65_CCW_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, -3855, 1428, 3840), - RC(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_66_CCW_SUMMER_TOP_OF_BRANCH, -4661, 2800, -1248), - RC(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_6F_CCW_WINTER_BIG_FLOWER, 0, 105, -5400), - RC(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_71_CCW_WINTER_BROKEN_BEEHIVE, 0, 3138, -3696), - RC(RC_CCW_MUMBO_TOKEN_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_70_CCW_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, 5950, -46, 0), - RC(RC_CCW_MUMBO_TOKEN_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, -3157, 300, -3149), - RC(RC_CCW_MUMBO_TOKEN_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN, MUMBOTOKEN_72_CCW_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, 40, 3969, 5000), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6A_CCW_AUTUMN_FLOATING_ABOVE_BIG_CLUCKER, 153, 1857, 2677), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_LEAF_NEAR_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6D_CCW_AUTUMN_LEAF_NEAR_TREEHOUSE, 3405, 4107, 1003), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6B_CCW_AUTUMN_SNAREBEAR_NEAR_ENTRANCE, 500, 166, 5125), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_SNAREBEAR_TOP_OF_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6C_CCW_AUTUMN_SNAREBEAR_TOP_OF_TREE, 0, 5830, -3325), + RC(RC_CCW_MUMBO_TOKEN_AUTUMN_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6E_CCW_AUTUMN_TOP_OF_BRANCH, -5929, 2586, 61), + RC(RC_CCW_MUMBO_TOKEN_SPRING_FRONT_OF_EYRIE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5D_CCW_SPRING_FRONT_OF_EYRIE, -2750, 4586, -513), + RC(RC_CCW_MUMBO_TOKEN_SPRING_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_62_CCW_SPRING_NABNUTS_HOUSE, -575, 300, -139), + RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5F_CCW_SPRING_SNAREBEAR_NEAR_BIG_FLOWER, 1904, 105, -2706), + RC(RC_CCW_MUMBO_TOKEN_SPRING_SNAREBEAR_NEAR_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_60_CCW_SPRING_SNAREBEAR_NEAR_ENTRANCE, 1000, 105, 5300), + RC(RC_CCW_MUMBO_TOKEN_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5E_CCW_SPRING_THORN_FIELD_FRONT_OF_MUMBOS_SKULL, -2649, 0, -395), + RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_61_CCW_SPRING_TOP_OF_BEEHIVE, 0, 3513, -5240), + RC(RC_CCW_MUMBO_TOKEN_SPRING_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5C_CCW_SPRING_TOP_OF_BRANCH, -4053, 2894, 587), + RC(RC_CCW_MUMBO_TOKEN_SPRING_UNFINISHED_WOOD_TREEHOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_5B_CCW_SPRING_UNFINISHED_WOOD_TREEHOUSE, 6134, 4244, 306), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_BIG_FLOWER_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_64_CCW_SUMMER_BIG_FLOWER_FIELD, -3578, 40, -4259), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_ENTRANCE_GNAWTYS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_67_CCW_SUMMER_ENTRANCE_GNAWTYS_HOUSE, 2700, -600, 0), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_68_CCW_SUMMER_FLOATING_ABOVE_BIG_CLUCKER, 2043, 3534, 1799), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_INSIDE_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_69_CCW_SUMMER_INSIDE_MUMBOS_SKULL, 0, 416, 500), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_63_CCW_SUMMER_PLATFORMS_BEFORE_EYRIES_NEST, -1861, 4469, 1583), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_65_CCW_SUMMER_SNAREBEAR_NEAR_THORN_FIELD, -3855, 1428, 3840), + RC(RC_CCW_MUMBO_TOKEN_SUMMER_TOP_OF_BRANCH, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_66_CCW_SUMMER_TOP_OF_BRANCH, -4661, 2800, -1248), + RC(RC_CCW_MUMBO_TOKEN_WINTER_BIG_FLOWER, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_6F_CCW_WINTER_BIG_FLOWER, 0, 105, -5400), + RC(RC_CCW_MUMBO_TOKEN_WINTER_BROKEN_BEEHIVE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_71_CCW_WINTER_BROKEN_BEEHIVE, 0, 3138, -3696), + RC(RC_CCW_MUMBO_TOKEN_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_70_CCW_WINTER_FROZEN_RIVER_NEAR_FLIGHT_PAD, 5950, -46, 0), + RC(RC_CCW_MUMBO_TOKEN_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_73_CCW_WINTER_SIR_SLUSH_BETWEEN_BIG_FLOWER_AND_MUMBOS_SKULL, -3157, 300, -3149), + RC(RC_CCW_MUMBO_TOKEN_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, RCTYPE_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, MUMBOTOKEN_72_CCW_WINTER_WALKWAY_FRONT_OF_NABNUTS_HOUSE, 40, 3969, 5000), RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_1, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -674, -1, 925), RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_2, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -674, 0, -900), RC(RC_CCW_NOTE_AUTUMN_BEEHIVE_INTERIOR_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, 675, -2, 925), @@ -692,73 +697,73 @@ std::map Checks = { RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_3, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -1691, 5210, -2199), RC(RC_CCW_NOTE_WINTER_TREETOP_PLATFORMS_4, RCTYPE_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, NULL, -764, 5590, -2634), RC(RC_CCW_SNS_YELLOW_EGG, RCTYPE_STOP_N_SWOP, LEVEL_8_CLICK_CLOCK_WOOD, RI_STOP_N_SWOP_EGG_YELLOW, SNS_ITEM_EGG_YELLOW, 556, 150, 47), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1536, 3505, 9857), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1606, 3505, 9635), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1674, 3505, 9422), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1610, 3505, 9197), - RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1545, 3505, 8981), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 404, 18, -2625), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 654, 18, -3169), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1410, 17, -2859), - RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 1185, 18, -2295), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -344, 2110, -200), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -195, 2110, -343), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1, 2110, -399), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 199, 2110, -346), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 345, 2110, -199), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 395, 2110, 1), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 341, 2110, 196), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 199, 2110, 340), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 0, 2110, 393), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -198, 2110, 347), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -344, 2110, 198), - RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -396, 2110, 0), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1465, 7354, 1066), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1961, 7227, 248), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1734, 7166, -667), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -948, 7201, -1175), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -33, 7313, -984), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 496, 7442, -179), - RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, 278, 7505, 757), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -3128, -168, -4645), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2939, -168, -4791), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2759, -168, -4928), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2552, -168, -5061), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2367, -168, -5166), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -2165, -168, -5146), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1979, -168, -5120), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1897, -168, -4931), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1824, -168, -4732), - RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -1758, -168, -4514), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -4112, -168, 5604), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -3753, -168, 6126), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -3887, -168, 6767), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -4440, -168, 7130), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -5069, -168, 6990), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -5424, -168, 6438), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -5280, -168, 5810), - RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -4753, -168, 5455), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -6559, 0, -291), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -7119, 0, -113), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -7166, 0, 926), - RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG, NULL, -6599, 0, 1184), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1536, 3505, 9857), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1606, 3505, 9635), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1674, 3505, 9422), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1610, 3505, 9197), + RC(RC_FP_BLUE_EGG_BEHIND_IGLOO_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1545, 3505, 8981), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 404, 18, -2625), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 654, 18, -3169), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1410, 17, -2859), + RC(RC_FP_BLUE_EGG_NEAR_GREEN_PRESENT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 1185, 18, -2295), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -344, 2110, -200), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -195, 2110, -343), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1, 2110, -399), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 199, 2110, -346), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 345, 2110, -199), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 395, 2110, 1), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 341, 2110, 196), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 199, 2110, 340), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 0, 2110, 393), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -198, 2110, 347), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -344, 2110, 198), + RC(RC_FP_BLUE_EGG_POTTED_TREE_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -396, 2110, 0), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1465, 7354, 1066), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1961, 7227, 248), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1734, 7166, -667), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -948, 7201, -1175), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -33, 7313, -984), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 496, 7442, -179), + RC(RC_FP_BLUE_EGG_SNOWMANS_HAT_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, 278, 7505, 757), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3128, -168, -4645), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2939, -168, -4791), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2759, -168, -4928), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2552, -168, -5061), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2367, -168, -5166), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -2165, -168, -5146), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1979, -168, -5120), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1897, -168, -4931), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_9, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1824, -168, -4732), + RC(RC_FP_BLUE_EGG_WATER_BEHIND_SNOWMAN_10, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -1758, -168, -4514), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4112, -168, 5604), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3753, -168, 6126), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -3887, -168, 6767), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4440, -168, 7130), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_5, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5069, -168, 6990), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_6, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5424, -168, 6438), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_7, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -5280, -168, 5810), + RC(RC_FP_BLUE_EGG_WATER_POTTED_TREE_8, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -4753, -168, 5455), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_1, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -6559, 0, -291), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_2, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -7119, 0, -113), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_3, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -7166, 0, 926), + RC(RC_FP_BLUE_EGG_WOZZAS_CAVE_4, RCTYPE_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK, RI_BLUE_EGG_FREEZEEZY_PEAK, NULL, -6599, 0, 1184), RC(RC_FP_EMPTY_HONEYCOMB_UNDER_SIR_SLUSH, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_A_FP_SIR_SLUSH, 4295, 441, 1268), RC(RC_FP_EMPTY_HONEYCOMB_WOZZAS_CAVE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, HONEYCOMB_9_FP_WOZZAS_CAVE, -6531, 135, 422), - RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE, NULL, 6992, 1390, -3159), - RC(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE, NULL, -4450, 1591, -7407), - RC(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE, NULL, -7322, 0, 391), - RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_FP_EXTRA_LIFE_ABOVE_MUMBOS_SKULL, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, 6992, 1390, -3159), + RC(RC_FP_EXTRA_LIFE_RACE_FINISH_LINE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -4450, 1591, -7407), + RC(RC_FP_EXTRA_LIFE_WOZZAS_CAVE, RCTYPE_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK, RI_EXTRA_LIFE_FREEZEEZY_PEAK, NULL, -7322, 0, 391), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_NEAR_RACE_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_PRESENT_STACK_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_START_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_1, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_2, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), + RC(RC_FP_HONEYCOMB_BEEHIVE_SCARF_END_3, RCTYPE_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK, RI_HONEYCOMB_FREEZEEZY_PEAK, NULL, 0, 0, 0), RC(RC_FP_JIGGY_BEAT_ALL_SIR_SLUSH, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_31_FP_SIR_SLUSH, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_1, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_30_FP_BOGGY_2, 0, 0 ,0), RC(RC_FP_JIGGY_BOGGY_RACE_2, RCTYPE_JIGGY, LEVEL_5_FREEZEEZY_PEAK, RI_JIGGY_FREEZEEZY_PEAK, JIGGY_2C_FP_BOGGY_3, 0, 0 ,0), @@ -775,16 +780,16 @@ std::map Checks = { RC(RC_FP_JINJO_PINK, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_PINK_FREEZEEZY_PEAK, NULL, -6851, 1193, 930), RC(RC_FP_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_5_FREEZEEZY_PEAK, RI_JINJO_YELLOW_FREEZEEZY_PEAK, NULL, 0, 406, -511), RC(RC_FP_MOLEHILL_BEAK_BOMB, RCTYPE_MOLEHILL, LEVEL_5_FREEZEEZY_PEAK, RI_MOLEHILL_BEAK_BOMB, ABILITY_1_BEAK_BOMB, -7462, 250, 1324), - RC(RC_FP_MUMBO_TOKEN_INSIDE_BOGGYS_IGLOO, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_28_FP_INSIDE_BOGGYS_IGLOO, 0, 10, -215), - RC(RC_FP_MUMBO_TOKEN_PRESENT_STACK, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_21_FP_BEHIND_PILE_PRESENT_BOXES, -5904, 260, 794), - RC(RC_FP_MUMBO_TOKEN_POTTED_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_25_FP_CHRISTMAS_TREE_POT, -4590, 350, 6344), - RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_START, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_23_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_LEFT_FOOT, 1413, 18, 2802), - RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_FINISH, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_24_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_RIGHT_FOOT, -4527, 211, -803), - RC(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_26_FP_TIP_OF_SCARF, -793, 3020, 4389), - RC(RC_FP_MUMBO_TOKEN_SNOWMAN_LEFT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_1F_FP_SNOWMAN_LEFT_FOOT, -1815, 4, -1019), - RC(RC_FP_MUMBO_TOKEN_SNOWMAN_RIGHT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_20_FP_SNOWMAN_RIGHT_FOOT, 634, 5, 769), - RC(RC_FP_MUMBO_TOKEN_VILLAGE_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_22_FP_ABOVE_CHIMNEY_FLIGHT_PAD, 5296, 2013, 2729), - RC(RC_FP_MUMBO_TOKEN_WATER_BEHIND_SNOWMAN, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN, MUMBOTOKEN_27_FP_WATER_BEHIND_SNOWMAN, -2424, -168, -4235), + RC(RC_FP_MUMBO_TOKEN_INSIDE_BOGGYS_IGLOO, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_28_FP_INSIDE_BOGGYS_IGLOO, 0, 10, -215), + RC(RC_FP_MUMBO_TOKEN_PRESENT_STACK, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_21_FP_BEHIND_PILE_PRESENT_BOXES, -5904, 260, 794), + RC(RC_FP_MUMBO_TOKEN_POTTED_TREE, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_25_FP_CHRISTMAS_TREE_POT, -4590, 350, 6344), + RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_START, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_23_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_LEFT_FOOT, 1413, 18, 2802), + RC(RC_FP_MUMBO_TOKEN_SIR_SLUSH_NEAR_RACE_FINISH, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_24_FP_INSIDE_SIR_SLUSH_NEAR_SNOWMANS_RIGHT_FOOT, -4527, 211, -803), + RC(RC_FP_MUMBO_TOKEN_SLED_TO_BOGGY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_26_FP_TIP_OF_SCARF, -793, 3020, 4389), + RC(RC_FP_MUMBO_TOKEN_SNOWMAN_LEFT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_1F_FP_SNOWMAN_LEFT_FOOT, -1815, 4, -1019), + RC(RC_FP_MUMBO_TOKEN_SNOWMAN_RIGHT_FOOT, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_20_FP_SNOWMAN_RIGHT_FOOT, 634, 5, 769), + RC(RC_FP_MUMBO_TOKEN_VILLAGE_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_22_FP_ABOVE_CHIMNEY_FLIGHT_PAD, 5296, 2013, 2729), + RC(RC_FP_MUMBO_TOKEN_WATER_BEHIND_SNOWMAN, RCTYPE_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK, RI_MUMBO_TOKEN_FREEZEEZY_PEAK, MUMBOTOKEN_27_FP_WATER_BEHIND_SNOWMAN, -2424, -168, -4235), RC(RC_FP_NOTE_FIRST_SLOPE_1, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -790, 3505, 8345), RC(RC_FP_NOTE_FIRST_SLOPE_2, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -820, 3149, 7926), RC(RC_FP_NOTE_FIRST_SLOPE_3, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -843, 2725, 7475), @@ -886,109 +891,109 @@ std::map Checks = { RC(RC_FP_NOTE_SNOWMAN_SCARF_18, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, -941, 5605, 844), RC(RC_FP_NOTE_SNOWMAN_SCARF_19, RCTYPE_MUSIC_NOTE, LEVEL_5_FREEZEEZY_PEAK, RI_MUSIC_NOTE_FREEZEEZY_PEAK, NULL, 17, 5605, 266), RC(RC_FP_SNS_ICE_KEY, RCTYPE_STOP_N_SWOP, LEVEL_5_FREEZEEZY_PEAK, RI_STOP_N_SWOP_ICE_KEY, SNS_ITEM_ICE_KEY, 1567, 583, 2416), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, -1065), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, -605), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, -145), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, 315), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, 775), - RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 50, 2009, 1235), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2799, 0, -2071), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2911, 0, -1907), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3016, 0, -1764), - RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3120, 0, -1616), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -9, -1395, 1178), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 382, -1395, 1090), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 820, -1395, 1183), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 820, -1395, 1692), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 445, -1395, 1832), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 27, -1395, 1781), - RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -185, -1395, 1477), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 3600), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 4001), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 4400), - RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 0, 800, 4800), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6392, 122, 744), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6732, 277, 765), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7018, 426, 641), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7264, 495, 389), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7264, 496, -1392), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -7018, 426, -1640), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6732, 277, -1767), - RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -6392, 122, -1749), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2726, -176, -6393), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 2986, -176, -6339), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3277, -176, -6332), - RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 3552, -176, -6394), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1004, -800, 6827), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 888, -802, 6826), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -300, -792, 6800), - RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -458, -768, 6764), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1335, -1482, 1349), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1835, -1486, 485), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1832, -1486, -499), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1344, -1492, -1346), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -499, -1492, -1836), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 491, -1490, -1832), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1342, -1486, -1349), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1833, -1492, -491), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1846, -1492, 503), - RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 1341, -1492, 1361), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -885, -749, 3037), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -98, -749, 3041), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 418, -750, 3577), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 422, -750, 4333), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -114, -750, 4871), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -864, -750, 4881), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1412, -750, 4335), - RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1410, -749, 3551), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1499, 0, 310), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1630, 0, 310), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1630, 0, 180), - RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -1499, 0, 180), - RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 7900, 1750, -1445), - RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 7900, 1750, -1358), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -898, 0, -630), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -126, 0, -637), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 671, 0, -637), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, 671, 0, 631), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -112, 0, 630), - RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG, NULL, -899, 0, 630), - RC(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, 0, 1600, -3700), - RC(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, -1992, 878, -3052), - RC(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, 2954, 1247, 100), - RC(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, -8689, -1781, -3192), - RC(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, 3599, -478, 2424), - RC(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE, NULL, -838, 1950, 835), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -1065), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -605), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, -145), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 315), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 775), + RC(RC_GL_BLUE_EGG_ABOVE_350_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 50, 2009, 1235), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2799, 0, -2071), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2911, 0, -1907), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3016, 0, -1764), + RC(RC_GL_BLUE_EGG_BEFORE_GOBIS_VALLEY_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3120, 0, -1616), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -9, -1395, 1178), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 382, -1395, 1090), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 820, -1395, 1183), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 820, -1395, 1692), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 445, -1395, 1832), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 27, -1395, 1781), + RC(RC_GL_BLUE_EGG_BEFORE_SECOND_NOTE_DOOR_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -185, -1395, 1477), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 3600), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4001), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4400), + RC(RC_GL_BLUE_EGG_CCW_ENTRANCE_UPPER_TUNNEL_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 0, 800, 4800), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6392, 122, 744), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6732, 277, 765), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7018, 426, 641), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7264, 495, 389), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7264, 496, -1392), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -7018, 426, -1640), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6732, 277, -1767), + RC(RC_GL_BLUE_EGG_BGS_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -6392, 122, -1749), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2726, -176, -6393), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 2986, -176, -6339), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3277, -176, -6332), + RC(RC_GL_BLUE_EGG_FP_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 3552, -176, -6394), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1004, -800, 6827), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 888, -802, 6826), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -300, -792, 6800), + RC(RC_GL_BLUE_EGG_MMM_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -458, -768, 6764), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1335, -1482, 1349), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1835, -1486, 485), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1832, -1486, -499), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1344, -1492, -1346), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -499, -1492, -1836), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 491, -1490, -1832), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1342, -1486, -1349), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1833, -1492, -491), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_9, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1846, -1492, 503), + RC(RC_GL_BLUE_EGG_MMM_PUZZLE_BOARD_10, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 1341, -1492, 1361), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -885, -749, 3037), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -98, -749, 3041), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 418, -750, 3577), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 422, -750, 4333), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -114, -750, 4871), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -864, -750, 4881), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_7, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1412, -750, 4335), + RC(RC_GL_BLUE_EGG_NEAR_PURPLE_CAULDRON_8, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1410, -749, 3551), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1499, 0, 310), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1630, 0, 310), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1630, 0, 180), + RC(RC_GL_BLUE_EGG_RBB_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -1499, 0, 180), + RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 7900, 1750, -1445), + RC(RC_GL_BLUE_EGG_RBB_PUZZLE_BOARD_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 7900, 1750, -1358), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -898, 0, -630), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -126, 0, -637), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 671, 0, -637), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, 671, 0, 631), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -112, 0, 630), + RC(RC_GL_BLUE_EGG_WATER_SWITCH_1_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_6_LAIR, RI_BLUE_EGG_GRUNTILDAS_LAIR, NULL, -899, 0, 630), + RC(RC_GL_EXTRA_LIFE_ABOVE_CLICK_CLOCK_WOODS_ENTRANCE, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 0, 1600, -3700), + RC(RC_GL_EXTRA_LIFE_ABOVE_THE_LOG_NEAR_BUBBLEGLOOP, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -1992, 878, -3052), + RC(RC_GL_EXTRA_LIFE_BACK_OF_GRUNTY_STATUES_HAT, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 2954, 1247, 100), + RC(RC_GL_EXTRA_LIFE_BEHIND_MUMBOS_SHACK, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -8689, -1781, -3192), + RC(RC_GL_EXTRA_LIFE_CLICK_CLOCK_WOODS_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, 3599, -478, 2424), + RC(RC_GL_EXTRA_LIFE_MAD_MONSTER_MANSION_PUZZLE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_6_LAIR, RI_EXTRA_LIFE_GRUNTILDAS_LAIR, NULL, -838, 1950, 835), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_BGS_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BEHIND_MMM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_BIG_GRUNTY_STATUE_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_50_NOTE_DOOR_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CCW_PUZZLE_SWITCH_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_FIRST_GRUNTY_STATUE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_CC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_TTC_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_1, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_2, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), + RC(RC_GL_HONEYCOMB_BEEHIVE_NEAR_RBB_PUZZLE_3, RCTYPE_HONEYCOMB, LEVEL_6_LAIR, RI_HONEYCOMB_GRUNTILDAS_LAIR, NULL, 0, 0, 0), RC(RC_GL_JIGGY_LOBBY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_33_LAIR_1ST_JIGGY, -1505, 600, 123), RC(RC_GL_JIGGY_WITCH_SWITCH_BUBBLEGLOOP_SWAMP, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_37_LAIR_BGS_WITCH_SWITCH, 0, 0, -20), RC(RC_GL_JIGGY_WITCH_SWITCH_CLANKERS_CAVERN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_35_LAIR_CC_WITCH_SWITCH, 0, 75, 156), @@ -999,85 +1004,85 @@ std::map Checks = { RC(RC_GL_JIGGY_WITCH_SWITCH_MUMBOS_MOUNTAIN, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_34_LAIR_MM_WITCH_SWITCH, 4165, 1000, -2363), RC(RC_GL_JIGGY_WITCH_SWITCH_RUSTY_BUCKET_BAY, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_3B_LAIR_RBB_WITCH_SWITCH, 0, 1200, 1650), RC(RC_GL_JIGGY_WITCH_SWITCH_TREASURE_TROVE_COVE, RCTYPE_JIGGY, LEVEL_6_LAIR, RI_JIGGY_GRUNTILDAS_LAIR, JIGGY_36_LAIR_TTC_WITCH_SWITCH, 998, 783, 368), - RC(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_51_LAIR_BEHIND_PURPLE_CAULDRON, 162, -750, 4611), - RC(RC_GL_MUMBO_TOKEN_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_53_LAIR_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, -180, 351, -750), - RC(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_54_LAIR_ABOVE_CC_ENTRANCE, 0, 850, -2450), - RC(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_52_LAIR_CCW_JIGGY_PODIUM, 4936, -478, 286), - RC(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_55_LAIR_BEHIND_SARCOPHAGUS, -1486, 0, -922), - RC(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_56_LAIR_ADVENT_TOP_WINDOW, 4155, 1485, 6270), - RC(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_59_LAIR_UNDERWATER_RBB_ENTRANCE_AREA, 1764, -1400, -1136), - RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), - RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), - RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), - RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 387, 2730, -6645), - RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 17, 2730, -6645), - RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -342, 2730, -6645), - RC(RC_GV_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1325, -59, 9447), - RC(RC_GV_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 845, -55, 9275), - RC(RC_GV_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 781, -51, 8805), - RC(RC_GV_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1214, -51, 8493), - RC(RC_GV_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1647, -56, 8820), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 712, 20, -1636), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 612, 20, -1636), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 511, 20, -1636), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 517, 22, -1502), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 612, 22, -1502), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 712, 22, -1502), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -856, 25, -1243), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -775, 25, -1243), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -775, 25, -1140), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -855, 25, -1140), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1139, 25, 880), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1139, 25, 961), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1240, 25, 964), - RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1240, 24, 884), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -985, 2432, 994), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1056, 2432, 466), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1137, 2432, -58), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -814, 2431, -394), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -472, 2432, -752), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 129, 2432, -740), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 740, 2432, -729), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 945, 2432, -392), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1151, 2431, -43), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1099, 2432, 473), - RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 1039, 2432, 970), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2251, 0, -50), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2347, 0, 159), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2550, 0, 251), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2757, 0, 137), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2850, 0, -50), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2756, 0, -272), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2550, 0, -349), - RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -2359, 0, -293), - RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4379, 1623, 6824), - RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4674, 1659, 6885), - RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4530, 1665, 6538), - RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4402, 1618, 5076), - RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4551, 1663, 5336), - RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -4689, 1662, 5017), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -671, 13, -369), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -390, 13, 655), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 354, 13, -645), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 645, 13, 384), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, -1168, 3325, -5619), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 861, 3821, -5292), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 526, 4316, -3580), - RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG, NULL, 523, 4316, -4952), + RC(RC_GL_MUMBO_TOKEN_BEHIND_PURPLE_CAULDRON, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_51_LAIR_BEHIND_PURPLE_CAULDRON, 162, -750, 4611), + RC(RC_GL_MUMBO_TOKEN_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_53_LAIR_TOP_OF_PIPE_IN_ORANGE_CAULDRON_ROOM, -180, 351, -750), + RC(RC_GL_MUMBO_TOKEN_ABOVE_CC_ENTRANCE, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_54_LAIR_ABOVE_CC_ENTRANCE, 0, 850, -2450), + RC(RC_GL_MUMBO_TOKEN_CCW_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_52_LAIR_CCW_JIGGY_PODIUM, 4936, -478, 286), + RC(RC_GL_MUMBO_TOKEN_BEHIND_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_55_LAIR_BEHIND_SARCOPHAGUS, -1486, 0, -922), + RC(RC_GL_MUMBO_TOKEN_ADVENT_TOP_WINDOW, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_56_LAIR_ADVENT_TOP_WINDOW, 4155, 1485, 6270), + RC(RC_GL_MUMBO_TOKEN_UNDERWATER_RBB_ENTRANCE_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_59_LAIR_UNDERWATER_RBB_ENTRANCE_AREA, 1764, -1400, -1136), + RC(RC_GL_MUMBO_TOKEN_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_5A_LAIR_WHIPCRACK_NEAR_MMM_JIGGY_PODIUM, -1140, 707, 1973), + RC(RC_GL_MUMBO_TOKEN_BEHIND_MUMBO_IN_CRYPT, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_57_LAIR_BEHIND_MUMBO_IN_CRYPT, 1488, 249, 0), + RC(RC_GL_MUMBO_TOKEN_ABOVE_NOTE_DOOR_WATER_AREA, RCTYPE_MUMBO_TOKEN, LEVEL_6_LAIR, RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, MUMBOTOKEN_58_LAIR_ABOVE_NOTE_DOOR_WATER_AREA, 1256, 2582, 0), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 387, 2730, -6645), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 17, 2730, -6645), + RC(RC_GV_BLUE_EGG_BEHIND_WATER_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -342, 2730, -6645), + RC(RC_GV_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1325, -59, 9447), + RC(RC_GV_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 845, -55, 9275), + RC(RC_GV_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 781, -51, 8805), + RC(RC_GV_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1214, -51, 8493), + RC(RC_GV_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1647, -56, 8820), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 712, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 612, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 511, 20, -1636), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 517, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 612, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 712, 22, -1502), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -856, 25, -1243), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -775, 25, -1243), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -775, 25, -1140), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -855, 25, -1140), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1139, 25, 880), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_12, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1139, 25, 961), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_13, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1240, 25, 964), + RC(RC_GV_BLUE_EGG_MAZE_PYRAMID_INTERIOR_14, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1240, 24, 884), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -985, 2432, 994), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1056, 2432, 466), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1137, 2432, -58), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -814, 2431, -394), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -472, 2432, -752), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 129, 2432, -740), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 740, 2432, -729), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 945, 2432, -392), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_9, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1151, 2431, -43), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_10, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1099, 2432, 473), + RC(RC_GV_BLUE_EGG_NEAR_MAZE_PYRAMID_11, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 1039, 2432, 970), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2251, 0, -50), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2347, 0, 159), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2550, 0, 251), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2757, 0, 137), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2850, 0, -50), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_6, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2756, 0, -272), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_7, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2550, 0, -349), + RC(RC_GV_BLUE_EGG_SPHYNX_INTERIOR_8, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -2359, 0, -293), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4379, 1623, 6824), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4674, 1659, 6885), + RC(RC_GV_BLUE_EGG_SPHYNX_LEFT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4530, 1665, 6538), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4402, 1618, 5076), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4551, 1663, 5336), + RC(RC_GV_BLUE_EGG_SPHYNX_RIGHT_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -4689, 1662, 5017), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -671, 13, -369), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -390, 13, 655), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 354, 13, -645), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 645, 13, 384), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_1, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, -1168, 3325, -5619), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_2, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 861, 3821, -5292), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_3, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 526, 4316, -3580), + RC(RC_GV_BLUE_EGG_WATER_PYRAMID_TOP_4, RCTYPE_BLUE_EGG, LEVEL_7_GOBIS_VALLEY, RI_BLUE_EGG_GOBIS_VALLEY, NULL, 523, 4316, -4952), RC(RC_GV_EMPTY_HONEYCOMB_CACTUS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_B_GV_CACTUS, 2911, 3292, -3307), RC(RC_GV_EMPTY_HONEYCOMB_GOBI, RCTYPE_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, HONEYCOMB_C_GV_GOBI_3, -6885, 2383, 1335), - RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE, NULL, -8948, 1332, 5500), - RC(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE, NULL, 1282, 18, 1971), - RC(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE, NULL, -230, 4820, -4421), - RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_GV_EXTRA_LIFE_BEHIND_JINXY, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -8948, 1332, 5500), + RC(RC_GV_EXTRA_LIFE_INSIDE_SANDYBUTTS_TOMB, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, 1282, 18, 1971), + RC(RC_GV_EXTRA_LIFE_ON_TOP_OF_WATER_PYRAMID, RCTYPE_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY, RI_EXTRA_LIFE_GOBIS_VALLEY, NULL, -230, 4820, -4421), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_BEHIND_WATER_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_PUZZLE_PYRAMID_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_1, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_2, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), + RC(RC_GV_HONEYCOMB_BEEHIVE_NEAR_WARP_PAD_3, RCTYPE_HONEYCOMB, LEVEL_7_GOBIS_VALLEY, RI_HONEYCOMB_GOBIS_VALLEY, NULL, 0, 0, 0), RC(RC_GV_JIGGY_ANCIENT_ONES, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_46_GV_ANCIENT_ONES, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_1, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_44_GV_GOBI_1, 0, 0, 0), RC(RC_GV_JIGGY_GOBI_2, RCTYPE_JIGGY, LEVEL_7_GOBIS_VALLEY, RI_JIGGY_GOBIS_VALLEY, JIGGY_45_GV_GOBI_2, 0, 0, 0), @@ -1094,16 +1099,16 @@ std::map Checks = { RC(RC_GV_JINJO_PINK, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_PINK_GOBIS_VALLEY, NULL, -4964, 0, 700), RC(RC_GV_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_7_GOBIS_VALLEY, RI_JINJO_YELLOW_GOBIS_VALLEY, NULL, 3067, 447, 10270), RC(RC_GV_MOLEHILL_TURBO_TALON, RCTYPE_MOLEHILL, LEVEL_7_GOBIS_VALLEY, RI_MOLEHILL_TURBO_TALON, ABILITY_11_TURBO_TALON, -6445, 2831, -822), - RC(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2F_GV_BEHIND_SANDYBUTTS_SARCOPHAGUS, -5514, 0, 138), - RC(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2B_GV_BOTTOM_OF_MOAT, 91, 535, -860), - RC(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2D_GV_FRONT_OF_STAR_DOOR, -230, 2843, -3091), - RC(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_32_GV_INSIDE_JINXY, -2550, 0, -51), - RC(RC_GV_MUMBO_TOKEN_INSIDE_MEMORY_GAME_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2E_GV_INSIDE_MEMORY_GAME_ROOM, 715, 248, 0), - RC(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_30_GV_INSIDE_WATER_PYRAMID, -300, 1439, -1194), - RC(RC_GV_MUMBO_TOKEN_NEXT_TO_RUBEE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_31_GV_NEXT_TO_RUBEE, 0, 107, -602), - RC(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2A_GV_SAND_RIGHT_OF_JINXY, -5386, 1420, 10034), - RC(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_29_GV_TOP_OF_JINXYS_NOSE, -2149, 3340, 5867), - RC(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN, MUMBOTOKEN_2C_GV_TOP_OF_WATER_PYRAMID, 64, 3484, 400), + RC(RC_GV_MUMBO_TOKEN_BEHIND_SANDYBUTTS_SARCOPHAGUS, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2F_GV_BEHIND_SANDYBUTTS_SARCOPHAGUS, -5514, 0, 138), + RC(RC_GV_MUMBO_TOKEN_BOTTOM_OF_MOAT, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2B_GV_BOTTOM_OF_MOAT, 91, 535, -860), + RC(RC_GV_MUMBO_TOKEN_FRONT_OF_STAR_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2D_GV_FRONT_OF_STAR_DOOR, -230, 2843, -3091), + RC(RC_GV_MUMBO_TOKEN_INSIDE_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_32_GV_INSIDE_JINXY, -2550, 0, -51), + RC(RC_GV_MUMBO_TOKEN_INSIDE_MEMORY_GAME_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2E_GV_INSIDE_MEMORY_GAME_ROOM, 715, 248, 0), + RC(RC_GV_MUMBO_TOKEN_INSIDE_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_30_GV_INSIDE_WATER_PYRAMID, -300, 1439, -1194), + RC(RC_GV_MUMBO_TOKEN_NEXT_TO_RUBEE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_31_GV_NEXT_TO_RUBEE, 0, 107, -602), + RC(RC_GV_MUMBO_TOKEN_SAND_RIGHT_OF_JINXY, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2A_GV_SAND_RIGHT_OF_JINXY, -5386, 1420, 10034), + RC(RC_GV_MUMBO_TOKEN_TOP_OF_JINXYS_NOSE, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_29_GV_TOP_OF_JINXYS_NOSE, -2149, 3340, 5867), + RC(RC_GV_MUMBO_TOKEN_TOP_OF_WATER_PYRAMID, RCTYPE_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY, RI_MUMBO_TOKEN_GOBIS_VALLEY, MUMBOTOKEN_2C_GV_TOP_OF_WATER_PYRAMID, 64, 3484, 400), RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_1, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7178, 2372, 1754), RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_2, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7148, 2371, 1568), RC(RC_GV_NOTE_DESERT_DOOR_ALCOVE_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -7123, 2371, 1404), @@ -1205,56 +1210,56 @@ std::map Checks = { RC(RC_GV_NOTE_WATER_PYRAMID_TOP_3, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -828, 3821, -3580), RC(RC_GV_NOTE_WATER_PYRAMID_TOP_4, RCTYPE_MUSIC_NOTE, LEVEL_7_GOBIS_VALLEY, RI_MUSIC_NOTE_GOBIS_VALLEY, NULL, -489, 4316, -4946), RC(RC_GV_SNS_BLUE_EGG, RCTYPE_STOP_N_SWOP, LEVEL_7_GOBIS_VALLEY, RI_STOP_N_SWOP_EGG_BLUE, SNS_ITEM_EGG_BLUE, 8, 470, -4141), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_HUT_BUNDLE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 0, 0, 0), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -131, 398, -496), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -362, 378, -362), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -487, 398, -146), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -493, 398, 101), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -352, 398, 371), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -131, 398, 496), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 136, 398, -499), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 361, 379, -363), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 498, 394, -129), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 495, 398, 133), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 359, 398, 362), - RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 134, 379, 497), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -10, 1507, -125), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -80, 1503, -71), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -74, 1521, 19), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -3, 1510, 52), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 60, 1510, -87), - RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, 67, 1510, 0), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5548, 200, 5984), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5706, 200, 5962), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5835, 201, 5896), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5911, 200, 5764), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5967, 200, 5615), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5927, 200, 5471), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5858, 200, 5343), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5732, 200, 5272), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -5061, 298, 6090), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -4881, 299, 6135), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -3958, 600, 6084), - RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -3827, 600, 5997), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2840, 2355, -2408), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2811, 2355, -2445), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2776, 2355, -2494), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2743, 2355, -2538), - RC(RC_MM_BLUE_EGG_UNDER_RUINS_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG, NULL, -2713, 2355, -2576), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_HUT_BUNDLE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -131, 398, -496), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -362, 378, -362), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -487, 398, -146), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -493, 398, 101), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -352, 398, 371), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -131, 398, 496), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 136, 398, -499), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 361, 379, -363), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_9, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 498, 394, -129), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_10, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 495, 398, 133), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_11, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 359, 398, 362), + RC(RC_MM_BLUE_EGG_INSIDE_MUMBOS_SKULL_12, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 134, 379, 497), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -10, 1507, -125), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -80, 1503, -71), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -74, 1521, 19), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3, 1510, 52), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 60, 1510, -87), + RC(RC_MM_BLUE_EGG_INSIDE_TICKERS_TOWER_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, 67, 1510, 0), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5548, 200, 5984), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5706, 200, 5962), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5835, 201, 5896), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5911, 200, 5764), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5967, 200, 5615), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5927, 200, 5471), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5858, 200, 5343), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_LOWER_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5732, 200, 5272), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -5061, 298, 6090), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_MIDDLE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -4881, 299, 6135), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3958, 600, 6084), + RC(RC_MM_BLUE_EGG_NEAR_CONGA_UPPER_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -3827, 600, 5997), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_1, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2840, 2355, -2408), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_2, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2811, 2355, -2445), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_3, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2776, 2355, -2494), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_4, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2743, 2355, -2538), + RC(RC_MM_BLUE_EGG_UNDER_RUINS_5, RCTYPE_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN, RI_BLUE_EGG_MUMBOS_MOUNTAIN, NULL, -2713, 2355, -2576), RC(RC_MM_EMPTY_HONEYCOMB_HILL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_1_MM_HILL, 985, 484, 1681), RC(RC_MM_EMPTY_HONEYCOMB_JUJU, RCTYPE_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, HONEYCOMB_2_MM_JUJU, 4302, 2900, -1490), - RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE, NULL, 0, 0, 0), - RC(RC_MM_EXTRA_LIFE_TICKERS_TOWER, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE, NULL, 223, 3563, -382), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MM_EXTRA_LIFE_HUT, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_EXTRA_LIFE_TICKERS_TOWER, RCTYPE_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN, RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, NULL, 223, 3563, -382), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_BIG_BUTT_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_1, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_2, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), + RC(RC_MM_HONEYCOMB_BEEHIVE_BY_THE_HUTS_3, RCTYPE_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN, RI_HONEYCOMB_MUMBOS_MOUNTAIN, NULL, 0, 0, 0), RC(RC_MM_JIGGY_CHIMPY, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_9_MM_CHIMPY, 0, 0, 0), RC(RC_MM_JIGGY_CONGA, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_A_MM_CONGA, 0, 0, 0), RC(RC_MM_JIGGY_HILL, RCTYPE_JIGGY, LEVEL_1_MUMBOS_MOUNTAIN, RI_JIGGY_MUMBOS_MOUNTAIN, JIGGY_07_MM_HILL, 4335, 1485, 794), @@ -1273,11 +1278,11 @@ std::map Checks = { RC(RC_MM_MOLEHILL_BEAK_BUSTER, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_BEAK_BUSTER, ABILITY_2_BEAK_BUSTER, 3943, 2155, -3422), RC(RC_MM_MOLEHILL_TALON_TROT, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_TALON_TROT, ABILITY_10_TALON_TROT, -2550, 2255, -1217), RC(RC_MM_MOLEHILL_USE_EGGS, RCTYPE_MOLEHILL, LEVEL_1_MUMBOS_MOUNTAIN, RI_MOLEHILL_EGGS, ABILITY_6_EGGS, -5926, 200, 6213), - RC(RC_MM_MUMBO_TOKEN_BEHIND_PINK_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_04_MM_BEHIND_PINK_JINJO, 5855, 0, 2169), - RC(RC_MM_MUMBO_TOKEN_BEHIND_RUINS, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_02_MM_BEHIND_RUINS, -4869, 2255, -2506), - RC(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_05_MM_INSIDE_TICKERS_TOWER, -343, 345, -518), - RC(RC_MM_MUMBO_TOKEN_STUMP_NEAR_CONGA, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA, -4431, 475, 6183), - RC(RC_MM_MUMBO_TOKEN_UNDER_RAMP_TO_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN, MUMBOTOKEN_03_MM_UNDER_RAMP_TO_MUMBOS_SKULL, 5150, 2168, -2447), + RC(RC_MM_MUMBO_TOKEN_BEHIND_PINK_JINJO, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_04_MM_BEHIND_PINK_JINJO, 5855, 0, 2169), + RC(RC_MM_MUMBO_TOKEN_BEHIND_RUINS, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_02_MM_BEHIND_RUINS, -4869, 2255, -2506), + RC(RC_MM_MUMBO_TOKEN_INSIDE_TICKERS_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_05_MM_INSIDE_TICKERS_TOWER, -343, 345, -518), + RC(RC_MM_MUMBO_TOKEN_STUMP_NEAR_CONGA, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA, -4431, 475, 6183), + RC(RC_MM_MUMBO_TOKEN_UNDER_RAMP_TO_MUMBOS_SKULL, RCTYPE_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, MUMBOTOKEN_03_MM_UNDER_RAMP_TO_MUMBOS_SKULL, 5150, 2168, -2447), RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_1, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4867, 297, 1766), RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_2, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4782, 298, 1892), RC(RC_MM_NOTE_SOUTH_SLOPE_FIRST_PLATFORM_3, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 4971, 299, 1887), @@ -1378,100 +1383,100 @@ std::map Checks = { RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_4, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, 60, 817, -87), RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_5, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -10, 817, -125), RC(RC_MM_NOTE_INSIDE_TICKERS_TOWER_6, RCTYPE_MUSIC_NOTE, LEVEL_1_MUMBOS_MOUNTAIN, RI_MUSIC_NOTE_MUMBOS_MOUNTAIN, NULL, -80, 817, -71), - RC(RC_MMM_BLUE_EGG_BEDROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -650, 175, 450), - RC(RC_MMM_BLUE_EGG_BEDROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -650, 175, 300), - RC(RC_MMM_BLUE_EGG_BEDROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -650, 175, 150), - RC(RC_MMM_BLUE_EGG_CELLAR_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -464, 40, -473), - RC(RC_MMM_BLUE_EGG_CELLAR_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -495, 40, -474), - RC(RC_MMM_BLUE_EGG_CELLAR_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -524, 40, -473), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 950, 588, 819), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2300, 588, 819), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2299, 588, 820), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -949, 588, 820), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2300, 588, 2369), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 950, 588, 2369), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -949, 588, 2370), - RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2299, 588, 2370), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4885, -2065), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2069, 4885, -1765), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2069, 4885, -1464), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4839, -2065), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4838, -1764), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4839, -1465), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4813, 2730), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4813, 2430), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2100, 4813, 2129), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4768, 2720), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4768, 2420), - RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 2070, 4768, 2119), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, -480), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, -280), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -701, 0, -80), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, 121), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, 320), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -700, 0, 520), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -600, 0, 619), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -400, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -199, 0, 621), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 200, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 401, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 600, 0, 620), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, 519), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, 320), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, 120), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, -78), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, -279), - RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 700, 0, -481), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -350, 550, -2499), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -176, 550, -2499), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 0, 550, -2500), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 174, 550, -2500), - RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 349, 550, -2500), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 446, 135, -339), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 450, 0, -35), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 450, 0, 36), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 35, 0, 351), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -36, 0, 350), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -442, 160, 331), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -437, 150, -336), - RC(RC_MMM_BLUE_EGG_EGG_ROOM_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -302, 150, -336), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 225, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 61, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -103, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -268, -135, -390), - RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -442, -135, -390), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 50, 1100, -760), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 50, 1100, 1255), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 1942, 1100, 1255), - RC(RC_MMM_BLUE_EGG_MANSION_AWNING_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 1950, 1099, -758), - RC(RC_MMM_BLUE_EGG_MAZE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -1750, 0, 2410), - RC(RC_MMM_BLUE_EGG_MAZE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -1951, 0, 2655), - RC(RC_MMM_BLUE_EGG_MAZE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, -2446, 0, 760), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7173, -175, -103), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7173, -175, 452), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7173, -175, 1008), - RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7174, -175, 1564), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 4200, -275, -2324), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 4200, -275, -2474), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7150, -273, -2383), - RC(RC_MMM_BLUE_EGG_NEAR_WELL_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG, NULL, 7149, -273, -2233), + RC(RC_MMM_BLUE_EGG_BEDROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 450), + RC(RC_MMM_BLUE_EGG_BEDROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 300), + RC(RC_MMM_BLUE_EGG_BEDROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -650, 175, 150), + RC(RC_MMM_BLUE_EGG_CELLAR_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -464, 40, -473), + RC(RC_MMM_BLUE_EGG_CELLAR_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -495, 40, -474), + RC(RC_MMM_BLUE_EGG_CELLAR_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -524, 40, -473), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 950, 588, 819), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2300, 588, 819), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2299, 588, 820), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_NORTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -949, 588, 820), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2300, 588, 2369), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHEAST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 950, 588, 2369), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -949, 588, 2370), + RC(RC_MMM_BLUE_EGG_CHURCH_PEW_SOUTHWEST_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2299, 588, 2370), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4885, -2065), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2069, 4885, -1765), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2069, 4885, -1464), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4839, -2065), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4838, -1764), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4839, -1465), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2730), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2430), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2100, 4813, 2129), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2720), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2420), + RC(RC_MMM_BLUE_EGG_CHURCH_RAFTERS_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 2070, 4768, 2119), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, -480), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, -280), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -701, 0, -80), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 121), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 320), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -700, 0, 520), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -600, 0, 619), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -400, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_9, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -199, 0, 621), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_10, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 200, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_11, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 401, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_12, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 600, 0, 620), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_13, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 519), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_14, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 320), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_15, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, 120), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_16, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -78), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_17, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -279), + RC(RC_MMM_BLUE_EGG_CHURCH_WINDOW_18, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 700, 0, -481), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -350, 550, -2499), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -176, 550, -2499), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 0, 550, -2500), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 174, 550, -2500), + RC(RC_MMM_BLUE_EGG_DINING_ROOM_MANTLE_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 349, 550, -2500), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 446, 135, -339), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 450, 0, -35), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 450, 0, 36), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 35, 0, 351), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -36, 0, 350), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_6, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -442, 160, 331), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_7, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -437, 150, -336), + RC(RC_MMM_BLUE_EGG_EGG_ROOM_8, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -302, 150, -336), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 225, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 61, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -103, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -268, -135, -390), + RC(RC_MMM_BLUE_EGG_HONEYCOMB_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -442, -135, -390), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 50, 1100, -760), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 50, 1100, 1255), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 1942, 1100, 1255), + RC(RC_MMM_BLUE_EGG_MANSION_AWNING_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 1950, 1099, -758), + RC(RC_MMM_BLUE_EGG_MAZE_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -1750, 0, 2410), + RC(RC_MMM_BLUE_EGG_MAZE_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -1951, 0, 2655), + RC(RC_MMM_BLUE_EGG_MAZE_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, -2446, 0, 760), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, -103), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, 452), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7173, -175, 1008), + RC(RC_MMM_BLUE_EGG_NEAR_FOUNTAIN_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7174, -175, 1564), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_1, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 4200, -275, -2324), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_2, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 4200, -275, -2474), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_3, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7150, -273, -2383), + RC(RC_MMM_BLUE_EGG_NEAR_WELL_4, RCTYPE_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION, RI_BLUE_EGG_MAD_MONSTER_MANSION, NULL, 7149, -273, -2233), RC(RC_MMM_EMPTY_HONEYCOMB_BENEATH_THE_FLOORBOARDS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_12_MMM_FLOORBOARD, -51, -135, 52), RC(RC_MMM_EMPTY_HONEYCOMB_CHURCH_RAFTERS, RCTYPE_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, HONEYCOMB_11_MMM_CHURCH_RAFTERS, 0, 5163, 2400), - RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE, NULL, -1, 2263, -3465), - RC(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE, NULL, 0, 13, 6), - RC(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE, NULL, 0, 1326, 145), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_MMM_EXTRA_LIFE_CHURCH_PIPES, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, -1, 2263, -3465), + RC(RC_MMM_EXTRA_LIFE_CHURCH_WINDOW, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 13, 6), + RC(RC_MMM_EXTRA_LIFE_DINING_ROOM_CHANDELIER, RCTYPE_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION, RI_EXTRA_LIFE_MAD_MONSTER_MANSION, NULL, 0, 1326, 145), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_LEFT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_CHURCH_ORGAN_RIGHT_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_MAZE_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_1, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_2, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), + RC(RC_MMM_HONEYCOMB_BEEHIVE_IN_THE_TALL_GRASS_3, RCTYPE_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION, RI_HONEYCOMB_MAD_MONSTER_MANSION, NULL, 0, 0, 0), RC(RC_MMM_JIGGY_BARREL_INTERIOR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_61_MMM_RAIN_BARREL, 2, 288, -4), RC(RC_MMM_JIGGY_CELLAR, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_5E_MMM_CELLAR, -516, 30, 477), RC(RC_MMM_JIGGY_CEMETARY_POTS, RCTYPE_JIGGY, LEVEL_A_MAD_MONSTER_MANSION, RI_JIGGY_MAD_MONSTER_MANSION, JIGGY_63_MMM_FLOWER_POTS, 0, 0, 0), @@ -1487,22 +1492,22 @@ std::map Checks = { RC(RC_MMM_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_ORANGE_MAD_MONSTER_MANSION, NULL, -4265, 0, 2668), RC(RC_MMM_JINJO_PINK, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_PINK_MAD_MONSTER_MANSION, NULL, 511, 38, 203), RC(RC_MMM_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_A_MAD_MONSTER_MANSION, RI_JINJO_YELLOW_MAD_MONSTER_MANSION, NULL, -250, 540, 300), - RC(RC_MMM_MUMBO_TOKEN_ALCOVE_CLOCK_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_35_MMM_ALCOVE_CLOCK_TOWER, -2800, 1475, -1363), - RC(RC_MMM_MUMBO_TOKEN_BEHIND_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_38_MMM_BEHIND_CHURCH, -4700, 175, -5149), - RC(RC_MMM_MUMBO_TOKEN_HIDDEN_NEAR_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_33_MMM_HIDDEN_NEAR_FOUNTAIN, 3950, -175, 325), - RC(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3E_MMM_IN_CHIMNEY_INSIDE_DINNING_ROOM, -160, 190, -2599), - RC(RC_MMM_MUMBO_TOKEN_IN_THE_MAZE, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_37_MMM_IN_THE_MAZE, -4250, 0, 352), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_40_MMM_INSIDE_BEDROOM, 696, 0, -397), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_LOGGO, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, RP_MUMBO_TOKEN_INSIDE_LOGGO, 424, 170, 304), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3D_MMM_INSIDE_LOGGO_AND_INSIDE_BARREL_IN_CELLAR, -507, 30, 199), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_WELL, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3F_MMM_INSIDE_WELL, -732, 0, -109), - RC(RC_MMM_MUMBO_TOKEN_INSIDE_WHIPCRACK_IN_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_39_MMM_INSIDE_WHIPCRACK_IN_FOUNTAIN, 5900, -275, 798), - RC(RC_MMM_MUMBO_TOKEN_NEAR_FRONT_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_34_MMM_NEAR_FRONT_TUMBLARS_SHED, 173, 350, -3610), - RC(RC_MMM_MUMBO_TOKEN_NEXT_TO_MAZE_HEDGE_RAMP, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_36_MMM_NEXT_TO_MAZE_HEDGE_RAMP, -1643, 25, -1026), - RC(RC_MMM_MUMBO_TOKEN_IN_LOGGOS_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_41_MMM_SINK_IN_LOGGOS_ROOM, 52, 104, 512), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3A_MMM_TOP_OF_RAFTER_INSIDE_CHURCH, 0, 4806, 341), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3B_MMM_TOP_OF_STOOL_INSIDE_CHURCH, 0, 583, -1300), - RC(RC_MMM_MUMBO_TOKEN_TOP_OF_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN, MUMBOTOKEN_3C_MMM_TOP_OF_TUMBLARS_SHED, 1796, 857, -4243), + RC(RC_MMM_MUMBO_TOKEN_ALCOVE_CLOCK_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_35_MMM_ALCOVE_CLOCK_TOWER, -2800, 1475, -1363), + RC(RC_MMM_MUMBO_TOKEN_BEHIND_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_38_MMM_BEHIND_CHURCH, -4700, 175, -5149), + RC(RC_MMM_MUMBO_TOKEN_HIDDEN_NEAR_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_33_MMM_HIDDEN_NEAR_FOUNTAIN, 3950, -175, 325), + RC(RC_MMM_MUMBO_TOKEN_IN_CHIMNEY_INSIDE_DINING_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3E_MMM_IN_CHIMNEY_INSIDE_DINNING_ROOM, -160, 190, -2599), + RC(RC_MMM_MUMBO_TOKEN_IN_THE_MAZE, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_37_MMM_IN_THE_MAZE, -4250, 0, 352), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_BEDROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_40_MMM_INSIDE_BEDROOM, 696, 0, -397), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_LOGGO, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, RP_MUMBO_TOKEN_INSIDE_LOGGO, 424, 170, 304), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_BARREL_IN_CELLAR, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3D_MMM_INSIDE_LOGGO_AND_INSIDE_BARREL_IN_CELLAR, -507, 30, 199), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_WELL, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3F_MMM_INSIDE_WELL, -732, 0, -109), + RC(RC_MMM_MUMBO_TOKEN_INSIDE_WHIPCRACK_IN_FOUNTAIN, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_39_MMM_INSIDE_WHIPCRACK_IN_FOUNTAIN, 5900, -275, 798), + RC(RC_MMM_MUMBO_TOKEN_NEAR_FRONT_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_34_MMM_NEAR_FRONT_TUMBLARS_SHED, 173, 350, -3610), + RC(RC_MMM_MUMBO_TOKEN_NEXT_TO_MAZE_HEDGE_RAMP, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_36_MMM_NEXT_TO_MAZE_HEDGE_RAMP, -1643, 25, -1026), + RC(RC_MMM_MUMBO_TOKEN_IN_LOGGOS_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_41_MMM_SINK_IN_LOGGOS_ROOM, 52, 104, 512), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_RAFTER_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3A_MMM_TOP_OF_RAFTER_INSIDE_CHURCH, 0, 4806, 341), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_STOOL_INSIDE_CHURCH, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3B_MMM_TOP_OF_STOOL_INSIDE_CHURCH, 0, 583, -1300), + RC(RC_MMM_MUMBO_TOKEN_TOP_OF_TUMBLARS_SHED, RCTYPE_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION, RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, MUMBOTOKEN_3C_MMM_TOP_OF_TUMBLARS_SHED, 1796, 857, -4243), RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 7150, -275, -3474), RC(RC_MMM_NOTE_AROUND_THE_WELL_WEST_1, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 7150, -275, -3325), RC(RC_MMM_NOTE_AROUND_THE_WELL_EAST_2, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 4200, -275, -3325), @@ -1605,79 +1610,79 @@ std::map Checks = { RC(RC_MMM_NOTE_WELL_INTERIOR_7, RCTYPE_MUSIC_NOTE, LEVEL_A_MAD_MONSTER_MANSION, RI_MUSIC_NOTE_MAD_MONSTER_MANSION, NULL, 681, 0, 182), RC(RC_MMM_SNS_CYAN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_CYAN, SNS_ITEM_EGG_CYAN, 1995, 100, -476), RC(RC_MMM_SNS_GREEN_EGG, RCTYPE_STOP_N_SWOP, LEVEL_A_MAD_MONSTER_MANSION, RI_STOP_N_SWOP_EGG_GREEN, SNS_ITEM_EGG_GREEN, 517, 350, -241), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -450, 0, -750), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 450, 0, -751), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 450, 0, 750), - RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -450, 0, 750), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -750, -800, -3651), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -750, -800, -3726), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -50, -800, -3651), - RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -49, -800, -3726), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -3001), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -2300), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -2475), - RC(RC_RBB_BLUE_EGG_ENGING_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -2550, 1059, -2825), - RC(RC_RRB_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -550, -650, 3549), - RC(RC_RRB_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -1200, -450, 3899), - RC(RC_RRB_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -1750, -650, 3300), - RC(RC_RRB_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 1549, -500, 3250), - RC(RC_RRB_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 1900, -200, 3800), - RC(RC_RBB_BLUE_EGG_KITCHEN_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 702, 213, -596), - RC(RC_RBB_BLUE_EGG_KITCHEN_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 758, 213, -600), - RC(RC_RBB_BLUE_EGG_KITCHEN_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 647, 213, -601), - RC(RC_RBB_BLUE_EGG_KITCHEN_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 645, 213, -501), - RC(RC_RBB_BLUE_EGG_KITCHEN_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 705, 213, -503), - RC(RC_RBB_BLUE_EGG_KITCHEN_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 758, 213, -503), - RC(RC_RBB_BLUE_EGG_KITCHEN_7, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 760, 213, -408), - RC(RC_RBB_BLUE_EGG_KITCHEN_8, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 700, 213, -407), - RC(RC_RBB_BLUE_EGG_KITCHEN_9, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 646, 213, -404), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 590), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 409), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 230), - RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -740, 340, 50), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 8726, -2613, 3075), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 8726, -2613, 3550), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 8726, -2613, 4025), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 6976, -2613, 3075), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 6976, -2613, 3550), - RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 6975, -2613, 4025), - RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -3721, -185, -1677), - RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -3953, -185, -1677), - RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -4185, -185, -1678), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -651, 140, -959), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -651, 140, -1064), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -520, 140, -1064), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -390, 140, -1064), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -389, 140, -959), - RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -520, 140, -959), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, 450), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, 324), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, 199), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -399, 400, 74), - RC(RC_RBB_BLUE_EGG_TNT_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -400, 400, -49), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 4500, -250, -1150), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 5050, 50, -1050), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 4100, -250, 1150), - RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 4650, 150, 1050), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -726, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -537, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -350, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, -163, 575, 125), - RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG, NULL, 25, 575, 124), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -450, 0, -750), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 450, 0, -751), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 450, 0, 750), + RC(RC_RBB_BLUE_EGG_ANCHOR_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -450, 0, 750), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -750, -800, -3651), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -750, -800, -3726), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -50, -800, -3651), + RC(RC_RBB_BLUE_EGG_BETWEEN_SHIPPING_CONTAINERS_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -49, -800, -3726), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -3001), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2300), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2475), + RC(RC_RBB_BLUE_EGG_ENGING_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -2550, 1059, -2825), + RC(RC_RRB_BLUE_EGG_ENTRANCE_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -550, -650, 3549), + RC(RC_RRB_BLUE_EGG_ENTRANCE_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -1200, -450, 3899), + RC(RC_RRB_BLUE_EGG_ENTRANCE_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -1750, -650, 3300), + RC(RC_RRB_BLUE_EGG_ENTRANCE_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 1549, -500, 3250), + RC(RC_RRB_BLUE_EGG_ENTRANCE_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 1900, -200, 3800), + RC(RC_RBB_BLUE_EGG_KITCHEN_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 702, 213, -596), + RC(RC_RBB_BLUE_EGG_KITCHEN_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 758, 213, -600), + RC(RC_RBB_BLUE_EGG_KITCHEN_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 647, 213, -601), + RC(RC_RBB_BLUE_EGG_KITCHEN_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 645, 213, -501), + RC(RC_RBB_BLUE_EGG_KITCHEN_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 705, 213, -503), + RC(RC_RBB_BLUE_EGG_KITCHEN_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 758, 213, -503), + RC(RC_RBB_BLUE_EGG_KITCHEN_7, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 760, 213, -408), + RC(RC_RBB_BLUE_EGG_KITCHEN_8, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 700, 213, -407), + RC(RC_RBB_BLUE_EGG_KITCHEN_9, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 646, 213, -404), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 590), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 409), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 230), + RC(RC_RBB_BLUE_EGG_NAVIGATION_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -740, 340, 50), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 3075), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 3550), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 8726, -2613, 4025), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6976, -2613, 3075), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6976, -2613, 3550), + RC(RC_RBB_BLUE_EGG_NEAR_PINK_JINJO_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 6975, -2613, 4025), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -3721, -185, -1677), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -3953, -185, -1677), + RC(RC_RBB_BLUE_EGG_ON_LIFE_BOAT_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -4185, -185, -1678), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -651, 140, -959), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -651, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -520, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -390, 140, -1064), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -389, 140, -959), + RC(RC_RBB_BLUE_EGG_SHIPPING_CONTAINER_INTERIOR_THIRD_6, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -520, 140, -959), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 450), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 324), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, 199), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -399, 400, 74), + RC(RC_RBB_BLUE_EGG_TNT_ROOM_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -400, 400, -49), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4500, -250, -1150), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 5050, 50, -1050), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4100, -250, 1150), + RC(RC_RBB_BLUE_EGG_TOP_OF_SHIP_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 4650, 150, 1050), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_1, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -726, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_2, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -537, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_3, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -350, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_4, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, -163, 575, 125), + RC(RC_RBB_BLUE_EGG_WAREHOUSE_INTERIOR_5, RCTYPE_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY, RI_BLUE_EGG_RUSTY_BUCKET_BAY, NULL, 25, 575, 124), RC(RC_RBB_EMPTY_HONEYCOMB_BOAT_HOUSE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_F_RBB_BOAT_HOUSE, 0, 1000, 0), RC(RC_RBB_EMPTY_HONEYCOMB_ENGINE_ROOM, RCTYPE_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, HONEYCOMB_10_RBB_ENGINE_ROOM, 0, 360, 3541), - RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE, NULL, -626, 140, -351), - RC(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE, NULL, -2551, 1065, -2650), - RC(RC_RBB_EXTRA_LIFE_WAREHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE, NULL, -950, 1045, -50), - RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_RBB_EXTRA_LIFE_BOOM_BOXES, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -626, 140, -351), + RC(RC_RBB_EXTRA_LIFE_ENGINE_ROOM, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -2551, 1065, -2650), + RC(RC_RBB_EXTRA_LIFE_WAREHOUSE, RCTYPE_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY, RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, NULL, -950, 1045, -50), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_ENGINE_ROOM_ENTRANCE_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_FIRST_SHIPPING_CONTAINER_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_1, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_2, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), + RC(RC_RBB_HONEYCOMB_BEEHIVE_GRATE_ABOVE_PINK_JINJO_3, RCTYPE_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY, RI_HONEYCOMB_RUSTY_BUCKET_BAY, NULL, 0, 0, 0), RC(RC_RBB_JIGGY_BOSS_BOOM_BOX, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_56_RBB_BOSS_BOOM_BOX, 0, 0, 0), RC(RC_RBB_JIGGY_CAPTAINS_CABIN, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_58_RBB_CAPTAINS_CABIN, -997, 273, 355), RC(RC_RBB_JIGGY_CRANE_CAGE, RCTYPE_JIGGY, LEVEL_9_RUSTY_BUCKET_BAY, RI_JIGGY_RUSTY_BUCKET_BAY, JIGGY_59_RBB_CRANE_CAGE, -4900, 0, 0), @@ -1693,21 +1698,21 @@ std::map Checks = { RC(RC_RBB_JINJO_ORANGE, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_ORANGE_RUSTY_BUCKET_BAY, NULL, -193, 0, -979), RC(RC_RBB_JINJO_PINK, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_PINK_RUSTY_BUCKET_BAY, NULL, 7850, -2613, 4026), RC(RC_RBB_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_9_RUSTY_BUCKET_BAY, RI_JINJO_YELLOW_RUSTY_BUCKET_BAY, NULL, -8615, -1000, -3555), - RC(RC_RBB_MUMBO_TOKEN_TOXIC_WASTE_POND, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_46_RBB_TOXIC_WASTE_POND, -7401, -1000, -3425), - RC(RC_RBB_MUMBO_TOKEN_ON_LIFE_BOAT, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_44_RBB_ON_LIFE_BOAT, 7053, -985, -1672), - RC(RC_RBB_MUMBO_TOKEN_SHIPS_PROW, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_43_RBB_SHIPS_PROW, -6200, 150, 0), - RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_47_RBB_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, 6200, 400, 0), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_SHIPS_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_42_RBB_TOP_OF_SHIPS_CHIMNEY, 1000, 2750, 0), - RC(RC_RBB_MUMBO_TOKEN_FRONT_OF_CHOMPA_LEFT_OF_SHIP, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_45_RBB_FRONT_OF_CHOMPA_LEFT_OF_SHIP, -3299, -457, 3800), - RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_48_RBB_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, -650, 562, -35), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_49_RBB_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, -278, 710, -557), - RC(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4C_RBB_INSIDE_KITCHEN, -771, 238, -293), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BUNK_IN_CABIN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4A_RBB_TOP_OF_BUNK_IN_CABIN, 583, 323, -70), - RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_50_RBB_TOP_OF_BOX_INSIDE_TNT_ROOM, -435, 300, -435), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4D_RBB_ENGINE_ROOM_LEFT_PIPE, -2450, 1100, -400), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4E_RBB_ENGINE_ROOM_RIGHT_PIPE, 2450, 1100, -400), - RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_SPINNING_PLATFORM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4F_RBB_ENGINE_ROOM_SPINNING_PLATFORM, -319, 12, 1899), - RC(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN, MUMBOTOKEN_4B_RBB_INSIDE_NAVIGATION_ROOM, -656, 0, -222), + RC(RC_RBB_MUMBO_TOKEN_TOXIC_WASTE_POND, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_46_RBB_TOXIC_WASTE_POND, -7401, -1000, -3425), + RC(RC_RBB_MUMBO_TOKEN_ON_LIFE_BOAT, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_44_RBB_ON_LIFE_BOAT, 7053, -985, -1672), + RC(RC_RBB_MUMBO_TOKEN_SHIPS_PROW, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_43_RBB_SHIPS_PROW, -6200, 150, 0), + RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_47_RBB_UNDER_CHOMPA_IN_WITCH_SWITCH_TOWER, 6200, 400, 0), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_SHIPS_CHIMNEY, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_42_RBB_TOP_OF_SHIPS_CHIMNEY, 1000, 2750, 0), + RC(RC_RBB_MUMBO_TOKEN_FRONT_OF_CHOMPA_LEFT_OF_SHIP, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_45_RBB_FRONT_OF_CHOMPA_LEFT_OF_SHIP, -3299, -457, 3800), + RC(RC_RBB_MUMBO_TOKEN_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_48_RBB_UNDER_CHOMPA_INSIDE_FIRST_BLUE_CONTAINER, -650, 562, -35), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_49_RBB_TOP_OF_BOX_INSIDE_SECOND_BLUE_CONTAINER, -278, 710, -557), + RC(RC_RBB_MUMBO_TOKEN_INSIDE_KITCHEN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4C_RBB_INSIDE_KITCHEN, -771, 238, -293), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BUNK_IN_CABIN, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4A_RBB_TOP_OF_BUNK_IN_CABIN, 583, 323, -70), + RC(RC_RBB_MUMBO_TOKEN_TOP_OF_BOX_INSIDE_TNT_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_50_RBB_TOP_OF_BOX_INSIDE_TNT_ROOM, -435, 300, -435), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_LEFT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4D_RBB_ENGINE_ROOM_LEFT_PIPE, -2450, 1100, -400), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_RIGHT_PIPE, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4E_RBB_ENGINE_ROOM_RIGHT_PIPE, 2450, 1100, -400), + RC(RC_RBB_MUMBO_TOKEN_ENGINE_ROOM_SPINNING_PLATFORM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4F_RBB_ENGINE_ROOM_SPINNING_PLATFORM, -319, 12, 1899), + RC(RC_RBB_MUMBO_TOKEN_INSIDE_NAVIGATION_ROOM, RCTYPE_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, MUMBOTOKEN_4B_RBB_INSIDE_NAVIGATION_ROOM, -656, 0, -222), RC(RC_RBB_NOTE_ANCHOR_ROOM_1, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3500, 449, -501), RC(RC_RBB_NOTE_ANCHOR_ROOM_2, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 3499, 449, 499), RC(RC_RBB_NOTE_ANCHOR_ROOM_3, RCTYPE_MUSIC_NOTE, LEVEL_9_RUSTY_BUCKET_BAY, RI_MUSIC_NOTE_RUSTY_BUCKET_BAY, NULL, 4499, 449, -500), @@ -1815,81 +1820,81 @@ std::map Checks = { RC(RC_SM_EMPTY_HONEYCOMB_TREE, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_16_SM_TREE, -2752, 1299, 37), RC(RC_SM_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_15_SM_UNDERWATER, -264, -442, -651), RC(RC_SM_EMPTY_HONEYCOMB_WATERFALL, RCTYPE_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, HONEYCOMB_14_SM_WATERFALL, -6725, 1300, -1803), - RC(RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE, NULL, 3656, 339, 6552), - RC(RC_SM_EXTRA_LIFE_WATERFALL, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE, NULL, -7108, 1200, -3079), + RC(RC_SM_EXTRA_LIFE_ABOVE_BANJOS_HOUSE, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, NULL, 3656, 339, 6552), + RC(RC_SM_EXTRA_LIFE_WATERFALL, RCTYPE_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN, RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, NULL, -7108, 1200, -3079), RC(RC_SM_MOLEHILL_ATTACK, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLAW_SWIPE, ABILITY_4_CLAW_SWIPE, 4675, 400, 511), RC(RC_SM_MOLEHILL_BEAK_BARGE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_BARGE, ABILITY_0_BARGE, 3271, -110, -2673), RC(RC_SM_MOLEHILL_CAMERA_CONTROL, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CAMERA_CONTROL, ABILITY_3_CAMERA_CONTROL, 2250, -34, 2774 ), RC(RC_SM_MOLEHILL_CLIMB, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_CLIMB, ABILITY_5_CLIMB, -1999, 342, -2545), RC(RC_SM_MOLEHILL_DIVE, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_DIVE, ABILITY_F_DIVE, -2336, 302, 973), RC(RC_SM_MOLEHILL_JUMP, RCTYPE_MOLEHILL, LEVEL_B_SPIRAL_MOUNTAIN, RI_MOLEHILL_FLAP_FLIP, ABILITY_8_FLAP_FLIP, -164, -190, 3313), - RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 4539, 1667, 1639), - RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 4539, 1792, 1639), - RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 4539, 1917, 1639), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -2906, 1012, -6249), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -2941, 1011, -6045), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3580, 1062, -5526), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3808, 1062, -5389), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3978, 1312, -5163), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3995, 1312, -4990), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4215, 1411, -4547), - RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4413, 1412, -4482), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -106, -23, 186), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -142, -23, 315), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -267, -23, 318), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -306, -23, 212), - RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -215, -23, 117), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 1012, 5782, -2017), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 864, 5826, -1874), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 648, 5857, -1874), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 743, 6580, -3494), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 944, 6625, -3436), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 1077, 6667, -3226), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2475, 5793, -2303), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2357, 5791, -2182), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2351, 5822, -2417), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 2241, 5819, -2305), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 720, 5819, -4297), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 869, 5820, -4332), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 750, 5791, -4131), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 918, 5793, -4172), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1269, 5795, -2811), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1147, 5822, -2700), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1145, 5792, -2928), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -1037, 5818, -2802), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 687, 5822, -1177), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 843, 5819, -1172), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 857, 5793, -1336), - RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, 689, 5794, -1347), - RC(RC_TTC_BLUE_EGG_LOCKUP_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3966, 1190, 1747), - RC(RC_TTC_BLUE_EGG_LOCKUP_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4051, 1190, 1793), - RC(RC_TTC_BLUE_EGG_LOCKUP_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4051, 1190, 1706), - RC(RC_TTC_BLUE_EGG_LOCKUP_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3882, 1190, 1795), - RC(RC_TTC_BLUE_EGG_LOCKUP_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3882, 1190, 1707), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -5319, 2470, -2929), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -5154, 2470, -3256), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4975, 2470, -3543), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4749, 2470, -3780), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4410, 2470, -3814), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -4092, 2470, -3826), - RC(RC_TTC_BLUE_EGG_UPPER_POOL_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG, NULL, -3957, 2470, -3586), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1667, 1639), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1792, 1639), + RC(RC_TTC_BLUE_EGG_ABOVE_SHOCK_PAD_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 4539, 1917, 1639), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -2906, 1012, -6249), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -2941, 1011, -6045), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3580, 1062, -5526), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3808, 1062, -5389), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3978, 1312, -5163), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3995, 1312, -4990), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4215, 1411, -4547), + RC(RC_TTC_BLUE_EGG_ALCOVE_LEDGE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4413, 1412, -4482), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -106, -23, 186), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -142, -23, 315), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -267, -23, 318), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -306, -23, 212), + RC(RC_TTC_BLUE_EGG_INSIDE_NIPPER_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -215, -23, 117), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 1012, 5782, -2017), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 864, 5826, -1874), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 648, 5857, -1874), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 743, 6580, -3494), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 944, 6625, -3436), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_LEDGE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 1077, 6667, -3226), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2475, 5793, -2303), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2357, 5791, -2182), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2351, 5822, -2417), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 2241, 5819, -2305), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 720, 5819, -4297), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 869, 5820, -4332), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 750, 5791, -4131), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_8, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 918, 5793, -4172), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_9, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1269, 5795, -2811), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_10, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1147, 5822, -2700), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_11, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1145, 5792, -2928), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_12, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -1037, 5818, -2802), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_13, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 687, 5822, -1177), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_14, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 843, 5819, -1172), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_15, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 857, 5793, -1336), + RC(RC_TTC_BLUE_EGG_LIGHTHOUSE_TREE_16, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, 689, 5794, -1347), + RC(RC_TTC_BLUE_EGG_LOCKUP_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3966, 1190, 1747), + RC(RC_TTC_BLUE_EGG_LOCKUP_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4051, 1190, 1793), + RC(RC_TTC_BLUE_EGG_LOCKUP_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4051, 1190, 1706), + RC(RC_TTC_BLUE_EGG_LOCKUP_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3882, 1190, 1795), + RC(RC_TTC_BLUE_EGG_LOCKUP_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3882, 1190, 1707), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_1, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -5319, 2470, -2929), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_2, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -5154, 2470, -3256), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_3, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4975, 2470, -3543), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_4, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4749, 2470, -3780), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_5, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4410, 2470, -3814), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_6, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -4092, 2470, -3826), + RC(RC_TTC_BLUE_EGG_UPPER_POOL_7, RCTYPE_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE, RI_BLUE_EGG_TREASURE_TROVE_COVE, NULL, -3957, 2470, -3586), RC(RC_TTC_EMPTY_HONEYCOMB_FLOATING_BOX, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_4_TTC_FLOATING_BOX, 8473, 844, -2684), RC(RC_TTC_EMPTY_HONEYCOMB_UNDERWATER, RCTYPE_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, HONEYCOMB_3_TTC_UNDERWATER, -4303, 46, 115), - RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE, NULL, -2442, 3158, -1706), - RC(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE, NULL, 5864, 677, 7898), - RC(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE, NULL, 4710, 323, -6007), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), - RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB, NULL, 0, 0, 0), + RC(RC_TTC_EXTRA_LIFE_CLIFFSIDE_POOL, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, -2442, 3158, -1706), + RC(RC_TTC_EXTRA_LIFE_SHARKFOOD_ISLAND_SIGN, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 5864, 677, 7898), + RC(RC_TTC_EXTRA_LIFE_SPIRAL_PATH, RCTYPE_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE, RI_EXTRA_LIFE_TREASURE_TROVE_COVE, NULL, 4710, 323, -6007), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_BLUBBERS_SHIP_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_NEAR_THE_BACK_STAIRS_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_IN_THE_CLIFFSIDE_POOL_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_1, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_2, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), + RC(RC_TTC_HONEYCOMB_BEEHIVE_ON_THE_BEACH_3, RCTYPE_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE, RI_HONEYCOMB_TREASURE_TROVE_COVE, NULL, 0, 0, 0), RC(RC_TTC_JIGGY_ALCOVE1, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0D_TTC_ALCOVE_1, 2832, 2152, -1797), RC(RC_TTC_JIGGY_ALCOVE2, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_0E_TTC_ALCOVE_2, -5116, 1417, -3915), RC(RC_TTC_JIGGY_BLUBBER, RCTYPE_JIGGY, LEVEL_2_TREASURE_TROVE_COVE, RI_JIGGY_TREASURE_TROVE_COVE, JIGGY_14_TTC_BLUBBER, 0, 0, 0), @@ -1907,16 +1912,16 @@ std::map Checks = { RC(RC_TTC_JINJO_YELLOW, RCTYPE_JINJO, LEVEL_2_TREASURE_TROVE_COVE, RI_JINJO_YELLOW_TREASURE_TROVE_COVE, NULL, -968, 5358, -776), RC(RC_TTC_MOLEHILL_FLIGHT, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, RI_MOLEHILL_FLIGHT, ABILITY_9_FLIGHT, -288, 2161, 1314), RC(RC_TTC_MOLEHILL_SHOCK_JUMP, RCTYPE_MOLEHILL, LEVEL_2_TREASURE_TROVE_COVE, RI_MOLEHILL_SHOCK_JUMP, ABILITY_D_SHOCK_JUMP, 2698, 1517, 3338), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_PILLAR_UNDERWATER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0C_TTC_BEHIND_PILLAR_UNDERWATER, 6480, 597, -258), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0A_TTC_BEHIND_LIGHTHOUSE_DOOR, 565, 6917, -2776), - RC(RC_TTC_MUMBO_TOKEN_BEHIND_NIPPER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0F_TTC_BEHIND_NIPPER, -6620, 510, 4621), - RC(RC_TTC_MUMBO_TOKEN_FLOATING_ABOVE_SHOCKJUMP_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0E_TTC_FLOATING_ABOVE_SHOCKJUMP_PAD, 2462, 2217, 2957), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_1, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_07_TTC_INSIDE_LOCKUP_1, -2660, 2447, -6079), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_2, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_08_TTC_INSIDE_LOCKUP_2, -2646, 2447, -6223), - RC(RC_TTC_MUMBO_TOKEN_INSIDE_SALTY_HIPPO, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_06_TTC_INSIDE_SALTY_HIPPO, 610, -412, 31), - RC(RC_TTC_MUMBO_TOKEN_ON_FLOATING_BOX, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0B_TTC_ON_FLOATING_BOX, -783, 745, -3872), - RC(RC_TTC_MUMBO_TOKEN_POND_BOTTOM, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_0D_TTC_POND_BOTTOM, -4932, 1122, -1063), - RC(RC_TTC_MUMBO_TOKEN_SALTY_HIPPO_MAST, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN, MUMBOTOKEN_09_TTC_SALTY_HIPPO_MAST, -221, 2029, 929), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_PILLAR_UNDERWATER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0C_TTC_BEHIND_PILLAR_UNDERWATER, 6480, 597, -258), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_LIGHTHOUSE_DOOR, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0A_TTC_BEHIND_LIGHTHOUSE_DOOR, 565, 6917, -2776), + RC(RC_TTC_MUMBO_TOKEN_BEHIND_NIPPER, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0F_TTC_BEHIND_NIPPER, -6620, 510, 4621), + RC(RC_TTC_MUMBO_TOKEN_FLOATING_ABOVE_SHOCKJUMP_PAD, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0E_TTC_FLOATING_ABOVE_SHOCKJUMP_PAD, 2462, 2217, 2957), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_1, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_07_TTC_INSIDE_LOCKUP_1, -2660, 2447, -6079), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_LOCKUP_2, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_08_TTC_INSIDE_LOCKUP_2, -2646, 2447, -6223), + RC(RC_TTC_MUMBO_TOKEN_INSIDE_SALTY_HIPPO, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_06_TTC_INSIDE_SALTY_HIPPO, 610, -412, 31), + RC(RC_TTC_MUMBO_TOKEN_ON_FLOATING_BOX, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0B_TTC_ON_FLOATING_BOX, -783, 745, -3872), + RC(RC_TTC_MUMBO_TOKEN_POND_BOTTOM, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_0D_TTC_POND_BOTTOM, -4932, 1122, -1063), + RC(RC_TTC_MUMBO_TOKEN_SALTY_HIPPO_MAST, RCTYPE_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE, RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, MUMBOTOKEN_09_TTC_SALTY_HIPPO_MAST, -221, 2029, 929), RC(RC_TTC_NOTE_BEACH_LOCKUP_1, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4802, 737, -2351), RC(RC_TTC_NOTE_BEACH_LOCKUP_2, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4730, 737, -2420), RC(RC_TTC_NOTE_BEACH_LOCKUP_3, RCTYPE_MUSIC_NOTE, LEVEL_2_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_TREASURE_TROVE_COVE, NULL, 4803, 736, -2444), diff --git a/src/port/Rando/StaticData/Flags.cpp b/src/port/Rando/StaticData/Flags.cpp index 0fad9ae3d..4f807dd28 100644 --- a/src/port/Rando/StaticData/Flags.cpp +++ b/src/port/Rando/StaticData/Flags.cpp @@ -17,6 +17,7 @@ namespace StaticData { std::map Flags = { RF(RANDO_INF_UNKNOWN, RO_GENERIC_OFF), RF(RANDO_INF_ANCHOR_RAISED, RO_GENERIC_OFF), + RF(RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, RO_GENERIC_OFF), RF(RANDO_INF_CLANKER_RAISED, RO_GENERIC_OFF), RF(RANDO_INF_MINIGAME_RINGS_COMPLETED, RO_GENERIC_OFF), RF(RANDO_INF_WATER_PYRAMID_DRAINED, RO_GENERIC_OFF), diff --git a/src/port/Rando/StaticData/Items.cpp b/src/port/Rando/StaticData/Items.cpp index 65591bdeb..415740927 100644 --- a/src/port/Rando/StaticData/Items.cpp +++ b/src/port/Rando/StaticData/Items.cpp @@ -10,29 +10,59 @@ namespace Rando { namespace StaticData { -#define RI(id, article, name, type, actorId, worldId) \ - { \ - id, { \ - id, #id, article, name, type, actorId, worldId \ - } \ +#define RI(id, article, name, type, actorId) \ + { \ + id, { \ + id, #id, article, name, type, actorId \ + } \ } // clang-format off std::map Items = { RI(RI_UNKNOWN, "", "Unknown", RITYPE_UNKNOWN, ACTOR_1_UNKNOWN, LEVEL_D_CUTSCENE), - RI(RI_BLUE_EGG, "a", "Blue Egg", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_D_CUTSCENE), + RI(RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, "a", "Blue Egg - BGS", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_BLUE_EGG_CLANKERS_CAVERN, "a", "Blue Egg - CC", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_3_CLANKERS_CAVERN), + RI(RI_BLUE_EGG_CLICK_CLOCK_WOOD, "a", "Blue Egg - CCW", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_BLUE_EGG_FREEZEEZY_PEAK, "a", "Blue Egg - FP", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_BLUE_EGG_GOBIS_VALLEY, "a", "Blue Egg - GV", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_7_GOBIS_VALLEY), + RI(RI_BLUE_EGG_GRUNTILDAS_LAIR, "a", "Blue Egg - Gl", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_6_LAIR), + RI(RI_BLUE_EGG_MAD_MONSTER_MANSION, "a", "Blue Egg - MMM", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_BLUE_EGG_MUMBOS_MOUNTAIN, "a", "Blue Egg - MM", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_BLUE_EGG_RUSTY_BUCKET_BAY, "a", "Blue Egg - RBB", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_BLUE_EGG_TREASURE_TROVE_COVE, "a", "Blue Egg - TTC", RITYPE_BLUE_EGG, ACTOR_52_BLUE_EGG, LEVEL_2_TREASURE_TROVE_COVE), RI(RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Empty Honeycomb - BGS", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, "a", "Empty Honeycomb - CC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), RI(RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Empty Honeycomb - CCW", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), RI(RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, "a", "Empty Honeycomb - FP", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), RI(RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, "a", "Empty Honeycomb - GV", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), + RI(RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Empty Honeycomb - GL", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_6_LAIR), RI(RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Empty Honeycomb - MMM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), RI(RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Empty Honeycomb - MM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), RI(RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Empty Honeycomb - RBB", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), RI(RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Empty Honeycomb - SM", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN), RI(RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Empty Honeycomb - TTC", RITYPE_EMPTY_HONEYCOMB, ACTOR_47_EMPTY_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), - RI(RI_EXTRA_LIFE, "an", "Extra Life", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_D_CUTSCENE), - RI(RI_HONEYCOMB, "a", "Honeycomb", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_D_CUTSCENE), + RI(RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, "an", "Extra Life - BGS", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_EXTRA_LIFE_CLANKERS_CAVERN, "an", "Extra Life - CC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_3_CLANKERS_CAVERN), + RI(RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, "an", "Extra Life - CCW", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_EXTRA_LIFE_FREEZEEZY_PEAK, "an", "Extra Life - FP", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_EXTRA_LIFE_GOBIS_VALLEY, "an", "Extra Life - GV", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_7_GOBIS_VALLEY), + RI(RI_EXTRA_LIFE_GRUNTILDAS_LAIR, "an", "Extra Life - GL", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_6_LAIR), + RI(RI_EXTRA_LIFE_MAD_MONSTER_MANSION, "an", "Extra Life - MMM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, "an", "Extra Life - MM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, "an", "Extra Life - RBB", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, "an", "Extra Life - SM", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_EXTRA_LIFE_TREASURE_TROVE_COVE, "an", "Extra Life - TTC", RITYPE_EXTRA_LIFE, ACTOR_49_EXTRA_LIFE, LEVEL_2_TREASURE_TROVE_COVE), + RI(RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, "a", "Honeycomb - BGS", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_HONEYCOMB_CLANKERS_CAVERN, "a", "Honeycomb - CC", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_3_CLANKERS_CAVERN), + RI(RI_HONEYCOMB_CLICK_CLOCK_WOOD, "a", "Honeycomb - CCW", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_HONEYCOMB_FREEZEEZY_PEAK, "a", "Honeycomb - FP", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_HONEYCOMB_GOBIS_VALLEY, "a", "Honeycomb - GV", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_7_GOBIS_VALLEY), + RI(RI_HONEYCOMB_GRUNTILDAS_LAIR, "a", "Honeycomb - GL", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_6_LAIR), + RI(RI_HONEYCOMB_MAD_MONSTER_MANSION, "a", "Honeycomb - MMM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_HONEYCOMB_MUMBOS_MOUNTAIN, "a", "Honeycomb - MM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_HONEYCOMB_RUSTY_BUCKET_BAY, "a", "Honeycomb - RBB", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_HONEYCOMB_SPIRAL_MOUNTAIN, "a", "Honeycomb - SM", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_B_SPIRAL_MOUNTAIN), + RI(RI_HONEYCOMB_TREASURE_TROVE_COVE, "a", "Honeycomb - TTC", RITYPE_HONEYCOMB, ACTOR_50_HONEYCOMB, LEVEL_2_TREASURE_TROVE_COVE), RI(RI_JIGGY_BUBBLEGLOOP_SWAMP, "a", "Jiggy - BGS", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_JIGGY_CLANKERS_CAVERN, "a", "Jiggy - CC", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_3_CLANKERS_CAVERN), RI(RI_JIGGY_CLICK_CLOCK_WOOD, "a", "Jiggy - CCW", RITYPE_JIGGY, ACTOR_46_JIGGY, LEVEL_8_CLICK_CLOCK_WOOD), @@ -103,7 +133,16 @@ std::map Items = { RI(RI_MOLEHILL_TURBO_TALON, "", "Turbo Talon", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_7_GOBIS_VALLEY), RI(RI_MOLEHILL_WADING_BOOTS, "", "Wading Boots", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_MOLEHILL_WONDERWING, "", "Wonderwing", RITYPE_MOLEHILL, ACTOR_12C_MOLEHILL, LEVEL_3_CLANKERS_CAVERN), - RI(RI_MUMBO_TOKEN, "a", "Mumbo Token", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_D_CUTSCENE), + RI(RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, "a", "Mumbo Token - BGS", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_4_BUBBLEGLOOP_SWAMP), + RI(RI_MUMBO_TOKEN_CLANKERS_CAVERN, "a", "Mumbo Token - CC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_3_CLANKERS_CAVERN), + RI(RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, "a", "Mumbo Token - CCW", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_8_CLICK_CLOCK_WOOD), + RI(RI_MUMBO_TOKEN_FREEZEEZY_PEAK, "a", "Mumbo Token - FP", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_5_FREEZEEZY_PEAK), + RI(RI_MUMBO_TOKEN_GOBIS_VALLEY, "a", "Mumbo Token - GV", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_7_GOBIS_VALLEY), + RI(RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, "a", "Mumbo Token - GL", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_6_LAIR), + RI(RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, "a", "Mumbo Token - MMM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_A_MAD_MONSTER_MANSION), + RI(RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, "a", "Mumbo Token - MM", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_1_MUMBOS_MOUNTAIN), + RI(RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, "a", "Mumbo Token - RBB", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_9_RUSTY_BUCKET_BAY), + RI(RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, "a", "Mumbo Token - TTC", RITYPE_MUMBO_TOKEN, ACTOR_2D_MUMBO_TOKEN, LEVEL_2_TREASURE_TROVE_COVE), RI(RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, "a", "Note - BGS", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_4_BUBBLEGLOOP_SWAMP), RI(RI_MUSIC_NOTE_CLANKERS_CAVERN, "a", "Note - CC", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_3_CLANKERS_CAVERN), RI(RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, "a", "Note - CCW", RITYPE_MUSIC_NOTE, ACTOR_51_MUSIC_NOTE, LEVEL_8_CLICK_CLOCK_WOOD), @@ -120,7 +159,6 @@ std::map Items = { RI(RI_STOP_N_SWOP_EGG_RED, "a", "Red Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_9_RUSTY_BUCKET_BAY), RI(RI_STOP_N_SWOP_EGG_YELLOW, "a", "Yellow Egg", RITYPE_SNS_EGG, ACTOR_25E_SNS_EGG, LEVEL_8_CLICK_CLOCK_WOOD), RI(RI_STOP_N_SWOP_ICE_KEY, "an", "Ice Key", RITYPE_SNS_KEY, ACTOR_25D_ICE_KEY, LEVEL_5_FREEZEEZY_PEAK), - RI(RI_AP_ITEM_PROGRESSION, "a", "AP Progression Item", RITYPE_AP_ITEM, ACTOR_3CD_CUSTOM_COLLECTIBLE, LEVEL_D_CUTSCENE), }; // clang-format on diff --git a/src/port/Rando/StaticData/StaticData.h b/src/port/Rando/StaticData/StaticData.h index 030f55954..bfb3cb9ff 100644 --- a/src/port/Rando/StaticData/StaticData.h +++ b/src/port/Rando/StaticData/StaticData.h @@ -13,7 +13,6 @@ namespace Rando { namespace StaticData { void SendCollisionNotification(RandoCheckId randoCheckId); -void SendRemoteCheckNotification(RandoCheckId randoCheckId, const std::string& collectorName); struct RandoLogicData { const char* name; diff --git a/src/port/Rando/Types.h b/src/port/Rando/Types.h index 146d7c8cc..ba6b63e3f 100644 --- a/src/port/Rando/Types.h +++ b/src/port/Rando/Types.h @@ -2040,25 +2040,54 @@ typedef enum { RITYPE_MUSIC_NOTE, RITYPE_SNS_EGG, RITYPE_SNS_KEY, - RITYPE_AP_ITEM, RITYPE_MAX, } RandoItemType; typedef enum { RI_UNKNOWN, - RI_BLUE_EGG, + RI_BLUE_EGG_BUBBLEGLOOP_SWAMP, + RI_BLUE_EGG_CLANKERS_CAVERN, + RI_BLUE_EGG_CLICK_CLOCK_WOOD, + RI_BLUE_EGG_FREEZEEZY_PEAK, + RI_BLUE_EGG_GOBIS_VALLEY, + RI_BLUE_EGG_GRUNTILDAS_LAIR, + RI_BLUE_EGG_MAD_MONSTER_MANSION, + RI_BLUE_EGG_MUMBOS_MOUNTAIN, + RI_BLUE_EGG_RUSTY_BUCKET_BAY, + RI_BLUE_EGG_TREASURE_TROVE_COVE, RI_EMPTY_HONEYCOMB_BUBBLEGLOOP_SWAMP, RI_EMPTY_HONEYCOMB_CLANKERS_CAVERN, RI_EMPTY_HONEYCOMB_CLICK_CLOCK_WOOD, RI_EMPTY_HONEYCOMB_FREEZEEZY_PEAK, RI_EMPTY_HONEYCOMB_GOBIS_VALLEY, + RI_EMPTY_HONEYCOMB_GRUNTILDAS_LAIR, RI_EMPTY_HONEYCOMB_MAD_MONSTER_MANSION, RI_EMPTY_HONEYCOMB_MUMBOS_MOUNTAIN, RI_EMPTY_HONEYCOMB_RUSTY_BUCKET_BAY, RI_EMPTY_HONEYCOMB_SPIRAL_MOUNTAIN, RI_EMPTY_HONEYCOMB_TREASURE_TROVE_COVE, - RI_EXTRA_LIFE, - RI_HONEYCOMB, + RI_EXTRA_LIFE_BUBBLEGLOOP_SWAMP, + RI_EXTRA_LIFE_CLANKERS_CAVERN, + RI_EXTRA_LIFE_CLICK_CLOCK_WOOD, + RI_EXTRA_LIFE_FREEZEEZY_PEAK, + RI_EXTRA_LIFE_GOBIS_VALLEY, + RI_EXTRA_LIFE_GRUNTILDAS_LAIR, + RI_EXTRA_LIFE_MAD_MONSTER_MANSION, + RI_EXTRA_LIFE_MUMBOS_MOUNTAIN, + RI_EXTRA_LIFE_RUSTY_BUCKET_BAY, + RI_EXTRA_LIFE_SPIRAL_MOUNTAIN, + RI_EXTRA_LIFE_TREASURE_TROVE_COVE, + RI_HONEYCOMB_BUBBLEGLOOP_SWAMP, + RI_HONEYCOMB_CLANKERS_CAVERN, + RI_HONEYCOMB_CLICK_CLOCK_WOOD, + RI_HONEYCOMB_FREEZEEZY_PEAK, + RI_HONEYCOMB_GOBIS_VALLEY, + RI_HONEYCOMB_GRUNTILDAS_LAIR, + RI_HONEYCOMB_MAD_MONSTER_MANSION, + RI_HONEYCOMB_MUMBOS_MOUNTAIN, + RI_HONEYCOMB_RUSTY_BUCKET_BAY, + RI_HONEYCOMB_SPIRAL_MOUNTAIN, + RI_HONEYCOMB_TREASURE_TROVE_COVE, RI_JIGGY_BUBBLEGLOOP_SWAMP, RI_JIGGY_CLANKERS_CAVERN, RI_JIGGY_CLICK_CLOCK_WOOD, @@ -2129,7 +2158,16 @@ typedef enum { RI_MOLEHILL_TURBO_TALON, RI_MOLEHILL_WADING_BOOTS, RI_MOLEHILL_WONDERWING, - RI_MUMBO_TOKEN, + RI_MUMBO_TOKEN_BUBBLEGLOOP_SWAMP, + RI_MUMBO_TOKEN_CLANKERS_CAVERN, + RI_MUMBO_TOKEN_CLICK_CLOCK_WOOD, + RI_MUMBO_TOKEN_FREEZEEZY_PEAK, + RI_MUMBO_TOKEN_GOBIS_VALLEY, + RI_MUMBO_TOKEN_GRUNTILDAS_LAIR, + RI_MUMBO_TOKEN_MAD_MONSTER_MANSION, + RI_MUMBO_TOKEN_MUMBOS_MOUNTAIN, + RI_MUMBO_TOKEN_RUSTY_BUCKET_BAY, + RI_MUMBO_TOKEN_TREASURE_TROVE_COVE, RI_MUSIC_NOTE_BUBBLEGLOOP_SWAMP, RI_MUSIC_NOTE_CLANKERS_CAVERN, RI_MUSIC_NOTE_CLICK_CLOCK_WOOD, @@ -2146,7 +2184,6 @@ typedef enum { RI_STOP_N_SWOP_EGG_RED, RI_STOP_N_SWOP_EGG_YELLOW, RI_STOP_N_SWOP_ICE_KEY, - RI_AP_ITEM_PROGRESSION, RI_MAX, } RandoItemId; @@ -2382,6 +2419,7 @@ typedef enum { typedef enum { RANDO_INF_UNKNOWN, RANDO_INF_ANCHOR_RAISED, + RANDO_INF_BRIDGE_REPAIRED_DIALOG_COMPLETE, RANDO_INF_CLANKER_RAISED, RANDO_INF_MINIGAME_RINGS_COMPLETED, RANDO_INF_WATER_PYRAMID_DRAINED, @@ -2394,8 +2432,7 @@ typedef struct RandoSaveCheck { RandoItemId randoItemId; int32_t randoCollectionId; bool isShuffled; - bool eligible; - bool received; + bool obtained; bool skipped; } RandoSaveCheck; diff --git a/src/port/Resource/Alt/AltBoldFont.cpp b/src/port/Resource/Alt/AltBoldFont.cpp index c5ec43030..df9c8524e 100644 --- a/src/port/Resource/Alt/AltBoldFont.cpp +++ b/src/port/Resource/Alt/AltBoldFont.cpp @@ -23,7 +23,6 @@ #include #include -#include "AltPathPool.h" #include "AltSprites.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" @@ -42,11 +41,7 @@ struct ChunkHeader { int16_t x, y, w, h; }; -// resolveHd hands these strings' addresses into display lists, and texture -// binds may be memoized on that address downstream: the strings must be -// immutable and immortal, so they live in the shared alt-path pool. -// reset() clears the output mapping, never the pool. -std::unordered_map sByOutput; +std::unordered_map sByOutput; std::unordered_set sBuilt; std::mutex sMutex; @@ -140,7 +135,7 @@ void buildHd(const void* output, const void* maskChunk, const void* sphereChunk) std::unique_lock lock(sMutex); if (sBuilt.count(cachePath)) { - sByOutput[output] = InternAltPath("__OTR__" + cachePath); + sByOutput[output] = "__OTR__" + cachePath; return; } @@ -148,7 +143,7 @@ void buildHd(const void* output, const void* maskChunk, const void* sphereChunk) // the identity path. Serve it directly and skip compositing. if (Ship::Context::GetRawInstance()->GetResourceManager()->GetArchiveManager()->HasFile("alt/" + cachePath)) { sBuilt.insert(cachePath); - sByOutput[output] = InternAltPath("__OTR__" + cachePath); + sByOutput[output] = "__OTR__" + cachePath; return; } lock.unlock(); @@ -216,7 +211,7 @@ void buildHd(const void* output, const void* maskChunk, const void* sphereChunk) lock.lock(); sBuilt.insert(cachePath); - sByOutput[output] = InternAltPath("__OTR__" + cachePath); + sByOutput[output] = "__OTR__" + cachePath; } void resolveHd(const void* output, const char** path) { @@ -226,7 +221,7 @@ void resolveHd(const void* output, const char** path) { std::lock_guard lock(sMutex); auto it = sByOutput.find(output); if (it != sByOutput.end()) { - *path = it->second; + *path = it->second.c_str(); } } diff --git a/src/port/Resource/Alt/AltDialogFont.cpp b/src/port/Resource/Alt/AltDialogFont.cpp deleted file mode 100644 index 76c2782c6..000000000 --- a/src/port/Resource/Alt/AltDialogFont.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// Cross-revision HD dialog font. -// -// The dialog font changed between ROM revisions: US v1.0 has 62 glyphs at native 8x12; v1.1/PAL/JP -// extended it to 75 glyphs at 8x13 (the extra 13 are the PAL accents; every glyph also grew one row). -// A LOAD_AS_RAW alt bakes its h/v scale factors against the native dims of the ROM the pack was built -// from, so a v1.0-built pack's glyph carries a scale computed for 12 rows. -// -// The pixels are fine; only the baked scale is wrong, and it is wrong purely because native dims -// differ between revisions. Calculate and re-scale port-side so hd packs don't need per-revision art. - -#include -#include -#include -#include - -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Patches/Patches.h" -#include "port/ResourceHelpers.h" -#include "port/ShipInit.hpp" - -#include -#include -#include -#include -#include -#include - -namespace { - -constexpr uint32_t kDialogFontAssetId = 0x6EB; -constexpr const char* kFontBaseFallback = "assets/sprite/ASSET_6EB_DIALOG_FONT_ALPHAMASK"; -std::unordered_set sBuiltSheets; -std::string fontSheetPath(std::string resolved) { - return resolved.empty() ? kFontBaseFallback : resolved; -} - -std::shared_ptr loadTex(const std::string& path, bool loadExact) { - return std::static_pointer_cast( - Ship::Context::GetRawInstance()->GetResourceManager()->LoadResourceProcess(path, loadExact)); -} - -// HD art for one chunk: the active sheet's own alt when the pack ships one, else the base game's -// alt for the same slot. Null when neither has art for it. -std::shared_ptr loadHdChunk(const std::string& activePath, const std::string& basePath, - const Fast::Texture* nativeCell, bool& fromBaseSheet) { - fromBaseSheet = false; - auto alt = loadTex(activePath, false); - if (alt != nullptr && alt.get() != nativeCell) { - return alt; - } - if (basePath == activePath) { - return nullptr; - } - fromBaseSheet = true; - return loadTex(Ship::IResource::gAltAssetPrefix + basePath, true); -} - -// Build a corrected alt for one chunk and cache it under "alt/". Returns false when -// there is nothing to do: no alt shipped, the dims already reconcile, or it isn't an HD raw texture. -bool correctChunk(const std::string& activePath, const std::string& basePath) { - auto base = loadTex(activePath, true); // live native cell - if (base == nullptr || base->Width <= 0 || base->Height <= 0) { - return false; - } - bool fromBaseSheet = false; - auto alt = loadHdChunk(activePath, basePath, base.get(), fromBaseSheet); - if (alt == nullptr || alt->ImageData == nullptr) { - return false; - } - if (alt->Type != Fast::TextureType::RGBA32bpp || (alt->Flags & TEX_FLAG_LOAD_AS_RAW) == 0) { - return false; - } - - const int nativeW = base->Width; - const int nativeH = base->Height; - - // Width is revision-stable (drift is height-only), so the integer scale comes cleanly off it. - // Bail if the alt isn't an integer multiple of the native width, or is degenerate. - if (nativeW <= 0 || alt->Width % nativeW != 0) { - return false; - } - const int k = alt->Width / nativeW; - if (k < 1) { - return false; - } - - const int dstW = nativeW * k; - const int dstH = nativeH * k; - // Matching heights mean no drift to correct. Art borrowed from the base sheet still has to be - // re-cached, though: nothing is reachable at the active path until we put it there. - if (dstH == (int)alt->Height && !fromBaseSheet) { - return false; - } - - // Top-align the HD rows into the k-scaled native cell; the zero-filled remainder stays transparent. - const int copyRows = (int)alt->Height < dstH ? (int)alt->Height : dstH; - const int rowBytes = dstW * 4; - - auto pixels = std::make_shared>((size_t)dstW * dstH * 4, 0); - for (int r = 0; r < copyRows; r++) { - std::memcpy(pixels->data() + (size_t)r * rowBytes, alt->ImageData + (size_t)r * rowBytes, (size_t)rowBytes); - } - - // Same HD pixels, but VPixelScale re-derived against the live native rows (native_rows * k == dstH). - // Cache under the alt path so the resource layer returns this in place of the raw archive alt. - const std::string altPath = Ship::IResource::gAltAssetPrefix + activePath; - auto initData = std::make_shared(); - initData->Path = altPath; - auto tex = std::make_shared(initData); - tex->Type = Fast::TextureType::RGBA32bpp; - tex->Width = (uint16_t)dstW; - tex->Height = (uint16_t)dstH; - tex->Flags = TEX_FLAG_LOAD_AS_RAW; - tex->HByteScale = alt->HByteScale; - tex->VPixelScale = (float)k; - tex->ImageDataSize = (uint32_t)pixels->size(); - tex->mImageBuffer = pixels; - tex->ImageData = (uint8_t*)pixels->data(); - - Ship::Context::GetRawInstance()->GetResourceManager()->CacheExternalResource(altPath, tex); - return true; -} - -} // namespace - -// Called when the dialog font is (re)loaded, boot and language switch alike. Scans every chunk of -// the sheet now in play and corrects each. -extern "C" void port_dialogFontHd_rebuild(void) { - if (!Ship::Context::GetRawInstance()->GetResourceManager()->IsAltAssetsEnabled()) { - return; - } - - const std::string activeFont = fontSheetPath(ResourceHelpers_GetActiveAssetPath(kDialogFontAssetId)); - if (sBuiltSheets.count(activeFont) != 0) { - return; - } - const std::string baseFont = fontSheetPath(ResourceHelpers_GetBaseAssetPath(kDialogFontAssetId)); - - bool built = false; - for (int frame = 0; frame < 64; frame++) { - bool anyInFrame = false; - for (int chunk = 0; chunk < 256; chunk++) { - const std::string suffix = "_" + std::to_string(frame) + "_" + std::to_string(chunk); - const std::string activePath = activeFont + suffix; - if (loadTex(activePath, true) == nullptr) { - break; - } - anyInFrame = true; - built = true; - correctChunk(activePath, baseFont + suffix); - } - if (!anyInFrame) { - break; - } - } - - if (built) { - sBuiltSheets.insert(activeFont); - } -} diff --git a/src/port/Resource/GfxBridge.c b/src/port/Resource/GfxBridge.c index cf62f287f..30c28c9a5 100644 --- a/src/port/Resource/GfxBridge.c +++ b/src/port/Resource/GfxBridge.c @@ -5,8 +5,6 @@ // __OTR__ asset paths instead of raw RAM; these wrappers detect that, swap in the // loaded resource via the ResourceManager, then forward to the real __gSP* GBI ops. -#include - #include "libultraship/libultra/gbi.h" #include "libultraship/bridge/resourcebridge.h" #include "src/port/ResourceHelpers.h" @@ -14,9 +12,12 @@ int ResourceMgr_OTRSigCheck(char* imgData) { uintptr_t i = (uintptr_t)(imgData); - // [port] Guard against small integers masquerading as pointers, which arise when - // N64 code computes an address from a NULL-based buffer. - if (i < 0x10000) + // [port] Reject N64 segmented addresses and special sentinels. + // Segmented addresses fit in 32 bits with a non-zero segment byte (bits 24-31). + // Bit 0 set = already-tagged segmented address from stub GBI functions. + if ((i & 1) == 1) + return 0; + if (i != 0 && i <= 0xFFFFFFFF && (i >> 24) != 0) return 0; // if ((i & 0xFF000000) != 0xAB000000 && (i & 0xFF000000) != 0xCD000000 && i != 0) { @@ -51,23 +52,18 @@ void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset) { __gSPDisplayList(pkt, dl + offset); } -// [port] `v` is a host pointer or an __OTR__ path. It is never a segmented address: -// callers that mean "segment N, offset off" use gSPVertexSeg. void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0) { if (ResourceMgr_OTRSigCheck((char*)v) == 1) v = (uintptr_t)ResourceMgr_LoadVtxByName((char*)v); - __gSPVertex(pkt, v, n, v0); -} - -// [port] Emit a vertex command that references segment `seg` at byte offset `off`. -// Bit 0 is the tag Fast::Interpreter::SegAddr keys on to resolve against its segment -// table; host pointers are always even, so the two can never be confused. -void gSPVertexSeg(Gfx* pkt, u32 seg, uintptr_t off, int n, int v0) { - assert(seg < 16); - assert(off <= 0x00FFFFFE); + // [port] Mark N64 segmented addresses with bit 0 so the interpreter's SegAddr resolves them. + // SEGMENT_ADDR(num, off) produces values like 0x01000000 without bit 0 set. + // Segmented addresses fit in 32 bits with a non-zero segment byte (bits 24-31). + if (v != 0 && v <= 0xFFFFFFFF && (v >> 24) != 0) { + v |= 1; + } - __gSPVertex(pkt, ((uintptr_t)(seg & 0xF) << 24) | (off & 0x00FFFFFEu) | 1u, n, v0); + __gSPVertex(pkt, v, n, v0); } void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr) { diff --git a/src/port/Resource/Importers/MapFactory.cpp b/src/port/Resource/Importers/MapFactory.cpp index d7a19d22a..68f90b4de 100644 --- a/src/port/Resource/Importers/MapFactory.cpp +++ b/src/port/Resource/Importers/MapFactory.cpp @@ -128,24 +128,19 @@ void SerializeLegacyMapData(std::vector& out, const std::vector(cube.nodeProps.size(), 0xFF); out.push_back(0x0A); - out.push_back(static_cast(nodeCnt)); + out.push_back(static_cast(std::min(cube.nodeProps.size(), 0xFF))); out.push_back(0x0B); - for (size_t n = 0; n < nodeCnt; n++) { - WriteNodeProp(out, cube.nodeProps[n]); + for (const auto& node : cube.nodeProps) { + WriteNodeProp(out, node); } } if (!cube.props.empty()) { - const size_t propCnt = std::min(cube.props.size(), 0xFF); out.push_back(0x08); - out.push_back(static_cast(propCnt)); + out.push_back(static_cast(std::min(cube.props.size(), 0xFF))); out.push_back(0x09); - for (size_t pi = 0; pi < propCnt; pi++) { - const auto& prop = cube.props[pi]; + for (const auto& prop : cube.props) { // [port] Props are raw 12-byte N64 big-endian structs from the ROM. // Layout: u32(4) + s16(2) + s16(2) + s16(2) + u16(2) = 12 bytes. // Byte-swap each multi-byte field to native (little-endian) order diff --git a/src/port/Resource/Importers/ModelFactory.cpp b/src/port/Resource/Importers/ModelFactory.cpp index 409d3ccf3..c1c4ebc41 100644 --- a/src/port/Resource/Importers/ModelFactory.cpp +++ b/src/port/Resource/Importers/ModelFactory.cpp @@ -6,12 +6,12 @@ #include #include "port/Resource/Alt/AltPathPool.h" -#include "port/Enhancements/Events/Hooks/Events.h" #include -#include +extern "C" { #include "model.h" +} namespace Factories { namespace { @@ -132,18 +132,6 @@ ResourceFactoryBinaryModelV0::ReadResource(std::shared_ptr file, tm.type, tm.width, tm.height, tm.tlutColors, tm.textureDataOffset); } - // Let enhancements patch the raw display list before it is widened. - // Command indices must be preserved; the geo layout references them by position. - if (!rawDLWords.empty() && texCount > 0) { - std::vector texSizes; - texSizes.reserve(texMetas.size()); - for (const auto& tm : texMetas) { - texSizes.push_back(ModelTexSize{ tm.width, tm.height }); - } - CALL_EVENT(OnModelDisplayListLoad, initData->Path.c_str(), rawDLWords.data(), - static_cast(rawDLWords.size()), texSizes.data(), texCount); - } - // Raw texture data blob — full contiguous pixel area from the ROM. // Preserves animated texture frames and unlisted data between textures. uint32_t rawTexDataSize = reader->ReadUInt32(); @@ -398,22 +386,29 @@ ResourceFactoryBinaryModelV0::ReadResource(std::shared_ptr file, // // Layout (each section padded to 8-byte alignment): // [ 0 ] BKModelBin header (zero-init, geo_type set) - // [ T ] BKTextureList + BKTextureInfo[] + pixel data -> texture_list_offset - // [ GL ] GeoLayout command tree -> geo_list_offset - // [ A ] BKAnimationList + BKAnimation[] -> animation_list_offset - // [ B ] BKCollisionList + ColGeo[] + ColTri[] -> collision_list_offset - // [ 14 ] BKModelUnk14List + entries -> unk14 - // [ 20 ] BKCameraAreaList + entries -> unk20 - // [ E ] effect count (s16) + effects -> mesh_list_offset - // [ 28 ] BKAnimVerticesList + entries -> unk28 - // [ AT ] AnimTexture[4] -> animated_texture_list_offset - // [ V ] BKVertexList header + Vtx[] -> vtx_list_offset - // [ G ] BKGfxList header + Gfx[] -> gfx_list_offset + // [ GL ] GeoLayout command tree → geo_list_offset + // [ T ] BKTextureList + BKTextureInfo[] + pixel data → texture_list_offset + // [ A ] BKAnimationList + BKAnimation[] → animation_list_offset + // [ B ] BKCollisionList + ColGeo[] + ColTri[] → collision_list_offset + // [ 14 ] BKModelUnk14List + entries → unk14 + // [ 20 ] BKCameraAreaList + entries → unk20 + // [ E ] effect count (s16) + effects → mesh_list_offset + // [ 28 ] BKAnimVerticesList + entries → unk28 + // [ AT ] AnimTexture[4] → animated_texture_list_offset + // [ V ] BKVertexList header + Vtx[] → vtx_list_offset + // [ G ] BKGfxList header + Gfx[] → gfx_list_offset auto out = std::vector(sizeof(BKModelBin), 0); auto hdr = [&]() -> BKModelBin* { return reinterpret_cast(out.data()); }; hdr()->geo_type = static_cast(geoType); + // GeoLayout section + if (geoBlob && !geoBlob->Data.empty()) { + PadTo8(out); + hdr()->geo_list_offset = static_cast(out.size()); + AppendBytes(out, geoBlob->Data.data(), geoBlob->Data.size()); + } + // Texture section if (texCount > 0) { PadTo8(out); @@ -446,16 +441,13 @@ ResourceFactoryBinaryModelV0::ReadResource(std::shared_ptr file, // Write pixel data area (raw blob from Torch) if (blobPtr) { AppendBytes(out, blobPtr, rawTexDataSize); + } else { + // Fallback: zero-filled if blob was missing + for (uint32_t i = 0; i < rawTexDataSize; i++) + out.push_back(0); } } - // GeoLayout section - if (geoBlob && !geoBlob->Data.empty()) { - PadTo8(out); - hdr()->geo_list_offset = static_cast(out.size()); - AppendBytes(out, geoBlob->Data.data(), geoBlob->Data.size()); - } - // Animation section if (hasAnim) { PadTo8(out); diff --git a/src/port/Resource/Type/Sprite.cpp b/src/port/Resource/Type/Sprite.cpp index 72c12daef..38c8c0e7e 100644 --- a/src/port/Resource/Type/Sprite.cpp +++ b/src/port/Resource/Type/Sprite.cpp @@ -125,6 +125,27 @@ void Sprite::BuildSpriteStructure() { // SPDLOG_DEBUG(" Frame buffer size: {} bytes, pointer: {}", // frameSizes[frameIdx], static_cast(sprite->frames[frameIdx])); } + + // SPDLOG_INFO("=== Sprite structure complete (total {} bytes) ===", totalSize); + + // Verify + // SPDLOG_INFO("Verification: frameCnt={}, type=0x{:X}", sprite->frameCnt, sprite->type); + if (frameCount > 0) { + BKSpriteFrame* verifyFrame = sprite->frames[0]; + // SPDLOG_INFO("Frame 0: w={}, h={}, chunkCnt={}, frame pointer={}", + // verifyFrame->w, verifyFrame->h, verifyFrame->chunkCnt, + // static_cast(verifyFrame)); + + if (verifyFrame->chunkCnt > 0) { + BKSpriteTextureBlock* verifyChunk = reinterpret_cast(verifyFrame + 1); + // SPDLOG_INFO("First chunk at frame+1: pointer={}, pos=({}, {}), size={}x{}", + // static_cast(verifyChunk), + // verifyChunk->x, verifyChunk->y, verifyChunk->w, verifyChunk->h); + // SPDLOG_INFO("Expected offset from frame: {} bytes, actual: {} bytes", + // sizeof(BKSpriteFrame), + // reinterpret_cast(verifyChunk) - reinterpret_cast(verifyFrame)); + } + } } BKSprite* Sprite::GetPointer() { diff --git a/src/port/ResourceHelpers.cpp b/src/port/ResourceHelpers.cpp index a350a0f86..933b692ac 100644 --- a/src/port/ResourceHelpers.cpp +++ b/src/port/ResourceHelpers.cpp @@ -27,19 +27,14 @@ #include "GameVersion/AssetVersionRemap.h" #include "GameVersion/BaseGameVersion.h" +extern "C" { #include "enums.h" +} +extern "C" uint16_t ResourceMgr_LoadTexWidthByName(char* texPath); +extern "C" uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); extern "C" void func_8031B5C4(int32_t lang); // decomp: set dialog language index -extern "C" { -// SNS picture demo table (core2/map/exit.c, Struct_core2_C4320_0). unk2 is both -// the demo file slot and the map exit/entry-point id used for the warp. -typedef struct { - uint8_t map, unk1, exit, unk3, unk4, unk5; -} BKSnsDemoEntry; -extern BKSnsDemoEntry D_80371F78[3]; -} - // Dialog language state — detected at boot from o2r version static int sDialogLanguageCount = 1; // 1 for US/JP, 3 for PAL (EN/FR/DE) static int sDialogLanguage = 0; // 0=English, 1=French, 2=German @@ -112,7 +107,7 @@ const std::unordered_map& GetAssetSymbolMap() { switch (Lighthouse::GetBaseVersion()) { case BK_VER_US_11: remapTable = &sV10toV11Remap; - SPDLOG_INFO("Loaded US v1.1 o2r with {} entries", symbolMap.size()); + SPDLOG_INFO("Loaded v1.1 o2r with {} entries", symbolMap.size()); break; case BK_VER_PAL: remapTable = &sV10toPALRemap; @@ -124,22 +119,10 @@ const std::unordered_map& GetAssetSymbolMap() { break; case BK_VER_US_10: default: - SPDLOG_INFO("Loaded US v1.0 o2r"); // v1.0 or a v1.0-based romhack: decomp IDs are already correct. break; } - // Non-v1.0 ROMs keep the SNS picture demos one slot lower (0x5E, matching - // the PAL VER_SELECT in the decomp) and their map setups place the demo - // entry points at that exit id too. The compiled v1.0 value (0x5F) would - // load the right demo file via the alias but warp to a nonexistent exit, - // so retarget the table; the 2508/2511/2513 aliases cover the asset side. - if (remapTable) { - for (auto& entry : D_80371F78) { - entry.exit = 0x5E; - } - } - // Relocate the JP world-name banners to their 0x1600 aliases for a JP // base (a JP pack does this re-point at language-select time instead). if (Lighthouse::GetBaseVersion() == BK_VER_JP) { @@ -188,11 +171,6 @@ extern "C" int ResourceMgr_GetDialogLanguageCount(void) { return sDialogLanguageCount; } -// PAL is the only base that carries more than one dialog language (EN/FR/DE). -extern "C" int ResourceMgr_IsPal(void) { - return sDialogLanguageCount > 1 ? 1 : 0; -} - extern "C" int ResourceMgr_IsJapanese(void) { return sIsJapanese ? 1 : 0; } @@ -242,8 +220,12 @@ extern "C" int ResourceMgr_IsAssetRepointed(uint32_t assetId) { return sDialogOverride.find(assetId) != sDialogOverride.end() ? 1 : 0; } -// The base game's own o2r path for an asset id, ignoring any active language re-point. -std::string ResourceHelpers_GetBaseAssetPath(uint32_t assetId) { +// Resolve an asset id to its o2r path: the active language override wins for +// re-pointed dialog ids, otherwise the base manifest. +static std::string ResolveAssetPath(uint32_t assetId) { + if (auto ov = sDialogOverride.find(assetId); ov != sDialogOverride.end()) { + return ov->second; + } const auto& symbolMap = GetAssetSymbolMap(); if (auto entry = symbolMap.find(assetId); entry != symbolMap.end()) { return entry->second; @@ -251,14 +233,6 @@ std::string ResourceHelpers_GetBaseAssetPath(uint32_t assetId) { return std::string(); } -// The o2r path an asset id resolves to right now. -std::string ResourceHelpers_GetActiveAssetPath(uint32_t assetId) { - if (auto ov = sDialogOverride.find(assetId); ov != sDialogOverride.end()) { - return ov->second; - } - return ResourceHelpers_GetBaseAssetPath(assetId); -} - static char* LoadAndRetainResource(const std::string& path, uint32_t assetId) { auto res = GetResourceByName(path.c_str()); if (res && res->GetRawPointer() != nullptr) { @@ -277,7 +251,7 @@ extern "C" char* ResourceMgr_ReloadByAssetId(uint32_t assetId) { sResourceRefCache.erase(it); } - std::string mappedPath = ResourceHelpers_GetActiveAssetPath(assetId); + std::string mappedPath = ResolveAssetPath(assetId); if (!mappedPath.empty()) { std::replace(mappedPath.begin(), mappedPath.end(), '\\', '/'); @@ -302,7 +276,7 @@ extern "C" char* ResourceMgr_LoadByAssetId(uint32_t assetId) { sResourceRefCache.erase(it); } - std::string mappedPath = ResourceHelpers_GetActiveAssetPath(assetId); + std::string mappedPath = ResolveAssetPath(assetId); if (mappedPath.empty()) { // A reserved-but-empty ROM slot resolves to nothing by design (the game // tolerates it, as on N64); only a genuinely-missing asset is worth tracing. @@ -329,20 +303,14 @@ extern "C" size_t ResourceMgr_GetResourceSize(uint32_t assetId) { return 0; } -// Force an asset id to resolve to a custom resource shipped at `customPath`. -extern "C" void ResourceMgr_RegisterAssetOverride(uint32_t assetId, const char* customPath) { - auto res = GetResourceByName(customPath); - if (res != nullptr && res->GetRawPointer() != nullptr) { - sResourceRefCache[assetId] = res; - } -} - -// Actors with sprite assets can be spawned as "model" props (unk8_1=1), causing collision -// code to call marker_loadModelBin which reinterprets sprite data as BKModelBin. This helper -// lets decomp code detect and skip the model path for sprite assets. +// On N64, sprites and models were raw binary blobs that could be type-punned. +// On PC, they're separate resource types from different importers. Actors with sprite +// assets can be spawned as "model" props (unk8_1=1), causing collision code to call +// marker_loadModelBin which reinterprets sprite data as BKModelBin. This helper lets +// decomp code detect and skip the model path for sprite assets. extern "C" int ResourceMgr_IsModelAsset(uint32_t assetId) { if (auto it = sResourceRefCache.find(assetId); it != sResourceRefCache.end()) { - return it->second->GetInitData()->Type == 0x424B4D4F; + return it->second->GetInitData()->Type == 0x424B4D4F; // Torch::ResourceType::BKModel } return 0; } @@ -395,12 +363,7 @@ void ResourceHelpers_ApplyLanguage(std::unordered_map dia } ++sLanguageGeneration; // invalidates re-pointed models on their next draw sIsJapanese = isJapanese; - sDialogLanguageCount = (dialogCount > 0) ? dialogCount : 1; - if (dialogIndex < 0 || dialogIndex >= sDialogLanguageCount) { - SPDLOG_WARN("[ResourceHelpers] Dialog language index {} out of range for a {}-language source; using 0", - dialogIndex, sDialogLanguageCount); - dialogIndex = 0; - } + sDialogLanguageCount = dialogCount; sDialogLanguage = dialogIndex; // keep ResourceMgr_GetDialogLanguage() in sync - func_8031B5C4(dialogIndex); + func_8031B5C4(dialogIndex); // clamps against sDialogLanguageCount } diff --git a/src/port/ResourceHelpers.h b/src/port/ResourceHelpers.h index e1223cd95..1fb9957a8 100644 --- a/src/port/ResourceHelpers.h +++ b/src/port/ResourceHelpers.h @@ -6,7 +6,6 @@ #include //#include "ResourceManager.h" #include "ship/Context.h" -#include "ship/resource/ResourceManager.h" std::shared_ptr GetResourceByName(const char* path); @@ -15,11 +14,9 @@ extern "C" { #include char* ResourceMgr_LoadByAssetId(uint32_t assetId); -void ResourceMgr_RegisterAssetOverride(uint32_t assetId, const char* customPath); size_t ResourceMgr_GetResourceSize(uint32_t assetId); int ResourceMgr_IsModelAsset(uint32_t assetId); int ResourceMgr_GetDialogLanguageCount(void); -int ResourceMgr_IsPal(void); int ResourceMgr_IsJapanese(void); int ResourceMgr_GetDialogLanguage(void); void ResourceMgr_SetDialogLanguage(int lang); @@ -38,8 +35,6 @@ Mtx* ResourceMgr_LoadMtxByName(char* path); void ResourceHelpers_ApplyLanguage(std::unordered_map dialogOverride, bool isJapanese, int dialogCount, int dialogIndex); -std::string ResourceHelpers_GetBaseAssetPath(uint32_t assetId); -std::string ResourceHelpers_GetActiveAssetPath(uint32_t assetId); #endif #endif diff --git a/src/port/Romhack/RomhackCompat.cpp b/src/port/Romhack/RomhackCompat.cpp index 904facd27..0bd322e5f 100644 --- a/src/port/Romhack/RomhackCompat.cpp +++ b/src/port/Romhack/RomhackCompat.cpp @@ -7,13 +7,7 @@ namespace Lighthouse { static constexpr const char* kVanillaLabel = "Vanilla"; std::string CurrentRomhackLabel() { - if (!port_isRomhack()) { - return kVanillaLabel; - } - if (const char* id = port_getRomhackIdentifier()) { - return id; - } - return port_getRomhackName(); + return port_isRomhack() ? port_getRomhackName() : kVanillaLabel; } std::string DescribeRomhackMismatch(bool localIsRomhack, const std::string& localLabel, bool remoteIsRomhack, diff --git a/src/port/Romhack/RomhackConfig.cpp b/src/port/Romhack/RomhackConfig.cpp index 303dd86a9..e989cca8c 100644 --- a/src/port/Romhack/RomhackConfig.cpp +++ b/src/port/Romhack/RomhackConfig.cpp @@ -62,8 +62,6 @@ static int sHideJiggiesLevel = -1; static int sHideCollectiblesLevel = -1; static int sNoteDoors[12] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; static int sJiggyCosts[11] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -static int sJiggySizes[11] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -static int sJiggyFlags[11] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; static char* sLevelNames[13] = {}; static std::unordered_map sWarpDests; static std::string sRomName; @@ -72,7 +70,6 @@ static std::string sRomName; // loaded romhack has no detectable injected MIPS code. static std::string sCustomCodeHashHex; static uint32_t sCustomCodeRamBase = 0; -static int sCustomCodeKind = -1; // ROM SHA1 — populated by the ROM_HASH section. Always emitted by Torch for // any romhack; serves as the fallback identifier when no custom-code blob is @@ -354,16 +351,12 @@ static void LoadGameConfig() { break; case 8: // JIGGY_PUZZLES - for (uint16_t e = 0; e < entryCount && pos + 6 <= size; e++) { + for (uint16_t e = 0; e < entryCount && pos + 2 <= size; e++) { int idx = data[pos]; int cost = data[pos + 1]; - int sizeBits = data[pos + 2]; - int flag = readLE16(data + pos + 4); - pos += 6; + pos += 2; if (idx >= 0 && idx < 11) { sJiggyCosts[idx] = cost; - sJiggySizes[idx] = sizeBits; - sJiggyFlags[idx] = flag; } } break; @@ -397,7 +390,7 @@ static void LoadGameConfig() { } break; - case 11: // CUSTOM_CODE + case 11: // CUSTOM_CODE — single entry: u32 ramBase + u8 hash[20] if (entryCount >= 1 && pos + 24 <= size) { sCustomCodeRamBase = readLE32(data + pos); char hex[41]; @@ -405,6 +398,17 @@ static void LoadGameConfig() { std::snprintf(hex + i * 2, 3, "%02x", data[pos + 4 + i]); } sCustomCodeHashHex.assign(hex, 40); + if (Lighthouse::LookupRomhackIdentifier(sCustomCodeHashHex.c_str()) == nullptr) { + // Hash isn't in RomhackTable.h yet — Lighthouse can detect + // this hack ships custom code but doesn't know which one. + // Log the SHA1 so a hand-port author can pick it up. + SPDLOG_WARN("[GameConfig] Custom-code SHA1 {} is not identified! This romhack's " + "scripted behavior will be absent until a hand-port is added " + "(ramBase=0x{:08X}).", + sCustomCodeHashHex, sCustomCodeRamBase); + } + // Known identifiers are surfaced in the summary log line below. + pos += 24; // Skip any additional entries (forward-compat). for (uint16_t e = 1; e < entryCount && pos + 24 <= size; e++) { @@ -416,13 +420,6 @@ static void LoadGameConfig() { } break; - case 13: // CUSTOM_CODE_INFO - if (entryCount >= 1 && pos + 4 <= size) { - sCustomCodeKind = readLE16(data + pos); - } - pos += entryCount * 4; - break; - case 12: // ROM_HASH — single entry: u8 hash[20] if (entryCount >= 1 && pos + 20 <= size) { char hex[41]; @@ -447,31 +444,48 @@ static void LoadGameConfig() { } } + int codeConstCount = 0; + for (int i = 0; i < 24; i++) { + // Check each static against its default (-1) + const int* vals[] = { &sNewGameMap, &sStartLevel1, &sStartLevel2, + &sKnowAllMoves, &sMumboCostTermite, &sMumboCostCroc, + &sMumboCostWalrus, &sMumboCostPumpkin, &sMumboCostBee, + &sEggsNormalMax, &sRedFeathersNormalMax, &sGoldFeathersNormalMax, + &sEggsCheatomax, &sRedFeathersCheatomax, &sGoldFeathersCheatomax, + &sNotesMax, &sJiggiesPerWorld, &sHoneycombsPerWorld, + &sExtraHcStart, &sWarpExitBanjosHouse, &sWarpEnterLair, + &sSpecialLevel, &sHideJiggiesLevel, &sHideCollectiblesLevel }; + if (*vals[i] != -1) { + codeConstCount++; + } + } + int levelNameCount = 0; + for (int i = 0; i < 13; i++) { + if (sLevelNames[i]) { + levelNameCount++; + } + } + int noteDoorCount = 0; + for (int i = 0; i < 12; i++) { + if (sNoteDoors[i] != -1) { + noteDoorCount++; + } + } + int jiggyCostCount = 0; + for (int i = 0; i < 11; i++) { + if (sJiggyCosts[i] != -1) { + jiggyCostCount++; + } + } if (sCustomCodeHashHex.empty()) { // Data-only romhack — BB patches only, no injected MIPS to identify. // Fall back to the o2r-derived name for visibility. SPDLOG_INFO("[GameConfig] Loaded romhack: {}", sRomName.empty() ? "" : sRomName); - } else if (const auto* entry = Lighthouse::LookupRomhackEntry(sCustomCodeHashHex.c_str())) { - SPDLOG_INFO("[GameConfig] Loaded romhack: {}", entry->identifier); - // No warning when the custom code is just the BB globalized-overlay - // framework or is already ported. Only injected, not-yet-ported code merits one. - // isPorted=false means analysis confirmed real un-ported custom code, - // regardless of how the blob is shipped (Nostalgia 64's lives inside a - // globalization-kind blob). - if (!entry->isPorted) { - SPDLOG_WARN("[GameConfig] {} ships injected custom code that is not ported yet; " - "scripted behavior driven by it will be absent.", - entry->identifier); - } - } else if (sCustomCodeKind == 1 /* BB_GLOBALIZATION */) { - const char* romId = sRomHashHex.empty() ? nullptr : Lighthouse::LookupRomhackIdentifier(sRomHashHex.c_str()); - SPDLOG_INFO("[GameConfig] Loaded romhack: {}", - romId ? romId : (sRomName.empty() ? "" : sRomName.c_str())); + } else if (const char* id = Lighthouse::LookupRomhackIdentifier(sCustomCodeHashHex.c_str())) { + SPDLOG_INFO("[GameConfig] Loaded romhack: {}", id); } else { - // Custom code present but the SHA1 is not in RomhackTable.h. - SPDLOG_WARN("[GameConfig] Custom-code SHA1 {} is not identified! This romhack's scripted " - "behavior will be absent until a port is added (ramBase=0x{:08X}).", - sCustomCodeHashHex, sCustomCodeRamBase); + // Custom code present but the SHA1 is not in RomhackTable.h. The + // separate warn earlier in this function already surfaced the hash. SPDLOG_INFO("[GameConfig] Loaded romhack: unidentified custom-code"); } } @@ -507,14 +521,6 @@ extern "C" const char* port_getRomhackName(void) { return sRomName.empty() ? "" : sRomName.c_str(); } -extern "C" int port_getRomhackCustomCodeKind(void) { - LoadGameConfig(); - if (!sIsRomhack || sCustomCodeHashHex.empty() || sCustomCodeKind < 0) { - return 0; // none - } - return sCustomCodeKind; -} - extern "C" bool port_getRomhackCustomCodeHash(char out_hex[41]) { LoadGameConfig(); if (sCustomCodeHashHex.empty()) { @@ -740,22 +746,6 @@ extern "C" int port_getRomhackJiggyPuzzleCost(int puzzle_index) { return -1; } -extern "C" int port_getRomhackJiggyPuzzleSize(int puzzle_index) { - ROMHACK_GUARD_INT; - if (puzzle_index >= 0 && puzzle_index < 11) { - return sJiggySizes[puzzle_index]; - } - return -1; -} - -extern "C" int port_getRomhackJiggyPuzzleFlag(int puzzle_index) { - ROMHACK_GUARD_INT; - if (puzzle_index >= 0 && puzzle_index < 11) { - return sJiggyFlags[puzzle_index]; - } - return -1; -} - extern "C" const char* port_getRomhackLevelName(int level_index) { ROMHACK_GUARD_NULL; if (level_index >= 0 && level_index < 13) { @@ -769,8 +759,3 @@ extern "C" int port_getRomhackWarpDest(int warp_index) { auto it = sWarpDests.find(warp_index); return (it != sWarpDests.end()) ? it->second : -1; } - -extern "C" void port_clearRomhackWarpDest(int warp_index) { - LoadGameConfig(); - sWarpDests.erase(warp_index); -} diff --git a/src/port/Romhack/RomhackConfig.h b/src/port/Romhack/RomhackConfig.h index 2dc678181..4d704ecb7 100644 --- a/src/port/Romhack/RomhackConfig.h +++ b/src/port/Romhack/RomhackConfig.h @@ -4,7 +4,10 @@ extern "C" { #endif -// Config building +// BB romhack game config — loaded from aGameConfig blob in the o2r. +// Returns -1 (or 0/NULL) for vanilla default when no override exists. +// All functions are fast after first call: vanilla ROMs hit one branch. + bool port_isRomhack(void); const char* port_getRomhackName(void); @@ -38,21 +41,12 @@ int port_getRomhackHoneycombsPerWorld(void); int port_getRomhackExtraHcStart(void); int port_getRomhackNoteDoor(int door_index); int port_getRomhackJiggyPuzzleCost(int puzzle_index); -int port_getRomhackJiggyPuzzleSize(int puzzle_index); -int port_getRomhackJiggyPuzzleFlag(int puzzle_index); const char* port_getRomhackLevelName(int level_index); int port_getRomhackWarpDest(int warp_index); -void port_clearRomhackWarpDest(int warp_index); bool port_getRomhackCustomCodeHash(char out_hex[41]); -int port_getRomhackCustomCodeKind(void); bool port_getRomhackRomHash(char out_hex[41]); const char* port_getRomhackIdentifier(void); -// Hack specific functions -int romhack_mumboTransform(int transformId); -int romhack_mumboWishwashyId(void); -int romhack_mumboRandomEventsAllowed(void); - #ifdef __cplusplus } #endif diff --git a/src/port/Romhack/RomhackQuirks.cpp b/src/port/Romhack/RomhackQuirks.cpp new file mode 100644 index 000000000..7df269857 --- /dev/null +++ b/src/port/Romhack/RomhackQuirks.cpp @@ -0,0 +1,56 @@ +// Per-romhack quirk handlers. Each block here is a port-side listener that +// adjusts engine behavior for a specific romhack identified via the +// RomhackTable.h SHA1 -> name mapping. Listeners run only when the loaded +// romhack matches the relevant identifier; vanilla and unrelated romhacks +// see no behavior change. +// +// To add a new quirk: +// 1. Make sure the romhack has an entry in RomhackTable.h. +// 2. Find the engine event the quirk should hook (or define a new one in +// src/port/enhancements/events/hooks/list/). +// 3. Add a REGISTER_LISTENER block below, gated on +// port_getRomhackIdentifier() returning the matching name. +// 4. Wire the registration into RegisterRomhackQuirks_Init(). + +#include + +#include +#include "port/Enhancements/Events/PortEnhancements.h" +#include "port/Enhancements/Events/Hooks/Events.h" +#include "port/ShipInit.hpp" +#include "port/Romhack/RomhackConfig.h" + +namespace { + +bool IsRomhack(const char* identifier) { + const char* id = port_getRomhackIdentifier(); + return id != nullptr && std::strcmp(id, identifier) == 0; +} + +// --- Banjo-Dreamie +// +// Pre-BB romhack whose BB-patched warp constants live in the relocated overlay +// copy. Dreamie's boot loader doesn't actually load that copy on N64. +// +// On every OnWarpResolveDest fire, restore the dispatcher's vanilla default, +// ignoring whatever the BKCF claims. + +void RegisterDreamiePatches() { + REGISTER_LISTENER(OnWarpResolveDest, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + if (!IsRomhack("Dreamie")) { + return; + } + auto* ev = reinterpret_cast(event); + if (ev->warpId == WARP_ID_SM_EXIT_BANJOS_HOUSE || ev->warpId == WARP_ID_LAIR_ENTER_MM_LOBBY_FROM_SM_LEVEL) { + *ev->dest = ev->defaultDest; + } + }); +} + +void RegisterRomhackQuirks_Init() { + RegisterDreamiePatches(); +} + +RegisterShipInitFunc initFunc(RegisterRomhackQuirks_Init); + +} // namespace diff --git a/src/port/Romhack/RomhackRegistration.cpp b/src/port/Romhack/RomhackRegistration.cpp deleted file mode 100644 index 0cf49a7fb..000000000 --- a/src/port/Romhack/RomhackRegistration.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Registration hub for per-romhack ports. -// -// Each supported romhack lives in its own file under Romhack/Specific/ and -// exposes a RegisterPatches() that installs its listeners. Registration -// itself is gated on the loaded romhack's RomhackTable.h identifier. -// -// To add a new port: -// 1. Add an entry in RomhackTable.h by hash. -// 2. Add Romhack/Specific/.cpp exposing RegisterPatches(). -// 3. Add one PORT() line to the list below. The identifier must match the -// RomhackTable.h identifier and the RegisterPatches() name. - -#include - -#include "port/Romhack/RomhackConfig.h" -#include "port/ShipInit.hpp" - -#define ROMHACK_PORT_LIST(PORT) \ - PORT(Dreamie) \ - PORT(JiggiesOfTime) \ - PORT(NewHorizons) \ - PORT(Nostalgia64) \ - PORT(CutThroatCoast) \ - PORT(BubblingBog) \ - PORT(Gruntch) - -#define ROMHACK_PORT_DECL(name) void Register##name##Patches(); -ROMHACK_PORT_LIST(ROMHACK_PORT_DECL) -#undef ROMHACK_PORT_DECL - -namespace { - -struct RomhackPort { - const char* identifier; - void (*install)(); -}; - -constexpr RomhackPort kRomhackPorts[] = { -#define ROMHACK_PORT_ENTRY(name) { #name, &Register##name##Patches }, - ROMHACK_PORT_LIST(ROMHACK_PORT_ENTRY) -#undef ROMHACK_PORT_ENTRY -}; - -void RegisterRomhackPatches_Init() { - const char* id = port_getRomhackIdentifier(); - if (id == nullptr) { - return; - } - for (const RomhackPort& port : kRomhackPorts) { - if (std::strcmp(id, port.identifier) == 0) { - port.install(); - return; - } - } -} - -RegisterShipInitFunc initFunc(RegisterRomhackPatches_Init, { "BOOT" }); - -} // namespace - -#undef ROMHACK_PORT_LIST diff --git a/src/port/Romhack/RomhackTable.h b/src/port/Romhack/RomhackTable.h index a12e19fc0..db90a0618 100644 --- a/src/port/Romhack/RomhackTable.h +++ b/src/port/Romhack/RomhackTable.h @@ -7,77 +7,46 @@ namespace Lighthouse { struct RomhackTableEntry { const char* sha1; const char* identifier; - bool isPorted; }; /* - This romhack table contains the sha1 hashes for detected code changes - injected into romhacks. Torch inserts these hashes into aGameConfig - per romhack generated into an o2r. Having a table of such hashes allows - Lighthouse to eventually port the code modifications that allow these - romhacks to function properly, and gate such changes behind matching - hashes per o2r. - - Known romhacks hashed against the latest at patch.wedarobi.com - as of July 2026. + This romhack table contains the sha1 hashes for custom code + blobs injected into romhacks. Torch inserts these hashes into + aGameConfig per romhack generated into an o2r. Having a table + of such hashes allows Lighthouse to eventually port custom code + that allows these romhacks to function properly, and gate custom + code paths behind matching hashes per o2r. */ static constexpr RomhackTableEntry kRomhackTable[] = { - // These hacks ship a separate code blob; the hash covers its decompressed - // payload. - // Cut-Throat Coast - { "13f4fa8a180fe5775a606486effbafeb58862d26", "CutThroatCoast", true }, + { "13f4fa8a180fe5775a606486effbafeb58862d26", "CutThroatCoast" }, - // The Gruntch, Santa's Village - { "bed22dd8ef931228fbc94f006dfc718a4d4f6f8c", "Gruntch", true }, + // How the Gruntch Stole Christmas — also shipped, byte-identical, in + // Santa's Village. Single hand-port covers both. + { "bed22dd8ef931228fbc94f006dfc718a4d4f6f8c", "Gruntch" }, - // Snow Glow Village - { "23596c2858283b847e9e0ff44785e35110002fc7", "SnowGlowVillage", false }, + // Snow Glow Village — derivative of Gruntch's blob with diverged code. + { "23596c2858283b847e9e0ff44785e35110002fc7", "SnowGlowVillage" }, // The Corrupted Jiggies - { "9e20be78496d66f2e5f7930022a0fee769753488", "CorruptedJiggies", false }, - - // Bubbling Bog Brewery Redone - { "af7c71b034b2d7af867cd0aec8751c49aca1f0bc", "BubblingBog", false }, - - // Cheatos Challenges - { "017bf33d80b22d7926a9839f09fd1c52f83d3b97", "CheatosChallenges", true }, - - // These hacks ship no blob of their own; they edit the globalized overlay - // in place, which aGameConfig has no schema for. Mostly actor table - // rebinds, though Nostalgia 64 also fills spare overlay space with its own - // functions and repoints update funcs at them. + { "9e20be78496d66f2e5f7930022a0fee769753488", "CorruptedJiggies" }, // Banjo-Dreamie - { "3972b2a3aca230dde1cbf66ffa6f052327b7d3fa", "Dreamie", true }, - - // Jiggies of Time - { "ad7ef5ba9051c6a360c1d60546d5ca8cf61f0d92", "JiggiesOfTime", true }, + { "3972b2a3aca230dde1cbf66ffa6f052327b7d3fa", "Dreamie" }, - // New Horizons - { "663dd77a9e3a1ed1f25399380665511a04b91a54", "NewHorizons", true }, - - // Nostalgia 64 - { "7a7a07c26d77530dc45caf8ab96e9056ea2877e1", "Nostalgia64", true }, - - { nullptr, nullptr, false }, // terminator + { nullptr, nullptr }, // terminator — keep last }; -inline const RomhackTableEntry* LookupRomhackEntry(const char* sha1Hex) { +inline const char* LookupRomhackIdentifier(const char* sha1Hex) { if (sha1Hex == nullptr || sha1Hex[0] == '\0') { return nullptr; } for (const auto* entry = kRomhackTable; entry->sha1 != nullptr; entry++) { if (std::strcmp(entry->sha1, sha1Hex) == 0) { - return entry; + return entry->identifier; } } return nullptr; } -inline const char* LookupRomhackIdentifier(const char* sha1Hex) { - const RomhackTableEntry* entry = LookupRomhackEntry(sha1Hex); - return entry ? entry->identifier : nullptr; -} - } // namespace Lighthouse diff --git a/src/port/Romhack/Shared/HackShared.cpp b/src/port/Romhack/Shared/HackShared.cpp deleted file mode 100644 index f431a00f3..000000000 --- a/src/port/Romhack/Shared/HackShared.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include "port/UI/cvar_prefixes.h" -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/RomhackConfig.h" -#include "port/ShipInit.hpp" -#include "HackShared.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "actor.h" -#include "core2/abilityprogress.h" - -extern ActorArray* suBaddieActorArray; - -extern s32 print_sCurrentFont; -extern s32 print_sMonospacedModeEnabled; -extern char print_sPreviousBoldLetter; -f32 print_calculateLetterXPos(u8 letter, f32* xPtr, f32* yPtr, f32 arg3); -} - -#define CVAR_NOTE_RETENTION CVAR_ENHANCEMENT("Gameplay.NoteRetention") - -namespace { - -void ApplyNoteSignHooks(); -f32 MeasureBoldNameWidth(const char* s); -void ApplyPauseNameCentering(); -void ApplyDialogSuppression(); -void ApplyForceAbilitiesUsed(); - -int sNoteSignActorId = -1; -const int* sSuppressedDialogs = nullptr; -int sSuppressedDialogCount = 0; -s32 sForcedUsedAbilities = 0; - -// Romhacks that have note signs and Bottles explainers don't need them when -// note saving is turned on. Suppress them. -void ApplyNoteSignHooks() { - const bool active = sNoteSignActorId >= 0 && CVarGetInteger(CVAR_NOTE_RETENTION, 0); - - COND_HOOK(OnActorSpawn, EVENT_PRIORITY_NORMAL, active, [](IEvent* event) { - auto* ev = reinterpret_cast(event); - if (ev->actorId == sNoteSignActorId) { - ev->result = nullptr; - event->Cancelled = true; - } - }); - - COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, active, [](IEvent*) { - if (suBaddieActorArray == nullptr) { - return; - } - Actor* start = suBaddieActorArray->data; - Actor* end = start + suBaddieActorArray->cnt; - for (Actor* actor = start; actor < end; actor++) { - if (actor->marker == nullptr || actor->marker->id != MARKER_B7_TUTORIAL_BOTTLES || - actor->actorTypeSpecificField != 8) { - continue; - } - if (actor->partnerActor != nullptr) { - marker_despawn(actor->partnerActor); - } - marker_despawn(actor->marker); - } - }); -} - -// Center bold font in pause menu -f32 MeasureBoldNameWidth(const char* s) { - const s32 savedSlot = print_sCurrentFont; - const s32 savedMono = print_sMonospacedModeEnabled; - const char savedPrev = print_sPreviousBoldLetter; - print_sCurrentFont = 1; - print_sMonospacedModeEnabled = 0; - print_sPreviousBoldLetter = 0; - f32 x = 0.0f; - f32 y = 0.0f; - for (const char* p = s; *p != '\0'; ++p) { - print_calculateLetterXPos((u8)(unsigned char)*p, &x, &y, 1.05f); - } - print_sCurrentFont = savedSlot; - print_sMonospacedModeEnabled = savedMono; - print_sPreviousBoldLetter = savedPrev; - return x; -} - -void ApplyPauseNameCentering() { - COND_VB_SHOULD(VB_PAUSEMENU_LEVEL_NAME_X, EVENT_PRIORITY_NORMAL, port_getRomhackIdentifier() != nullptr, { - s32* x = va_arg(args, s32*); - va_arg(args, s32); - const char* vanillaName = va_arg(args, const char*); - const char* romhackName = va_arg(args, const char*); - if (romhackName != nullptr && vanillaName != nullptr) { - const f32 shift = (MeasureBoldNameWidth(vanillaName) - MeasureBoldNameWidth(romhackName)) * 0.5f; - *x += (s32)(shift >= 0.0f ? shift + 0.5f : shift - 0.5f); - } - (void)should; - }); -} - -// Suppress a caller-supplied set of dialogs -void ApplyDialogSuppression() { - COND_VB_SHOULD(VB_OVERRIDE_DIALOG_SHOW, EVENT_PRIORITY_NORMAL, sSuppressedDialogCount > 0, { - const s32 textId = va_arg(args, s32); - for (int i = 0; i < sSuppressedDialogCount; i++) { - if (sSuppressedDialogs[i] == textId) { - *should = true; - break; - } - } - }); -} - -// Mark moves as already used -void ApplyForceAbilitiesUsed() { - COND_HOOK(OnSaveLoad, EVENT_PRIORITY_NORMAL, sForcedUsedAbilities != 0, [](IEvent*) { - for (int move = 0; move < 32; move++) { - if (sForcedUsedAbilities & (1 << move)) { - ability_setHasUsed(static_cast(move)); - } - } - }); -} - -RegisterShipInitFunc noteSignInitFunc(ApplyNoteSignHooks, { CVAR_NOTE_RETENTION }); -RegisterShipInitFunc pauseNameCenterInit(ApplyPauseNameCentering, { "BOOT" }); - -} // namespace - -void HackShared_EnableNoteSignSuppression(int signActorId) { - sNoteSignActorId = signActorId; - ApplyNoteSignHooks(); -} - -void HackShared_EnableDialogSuppression(const int* dialogIds, int count) { - sSuppressedDialogs = dialogIds; - sSuppressedDialogCount = count; - ApplyDialogSuppression(); -} - -void HackShared_EnableForceAbilitiesUsed(const ability_used* moves, int count) { - for (int i = 0; i < count; i++) { - sForcedUsedAbilities |= (1 << moves[i]); - } - ApplyForceAbilitiesUsed(); -} diff --git a/src/port/Romhack/Shared/HackShared.h b/src/port/Romhack/Shared/HackShared.h deleted file mode 100644 index 37d8cb578..000000000 --- a/src/port/Romhack/Shared/HackShared.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -extern "C" { -#include "core2/abilityprogress.h" -} - -constexpr ability_used kAllUsedAbilities[] = { - ABILITY_USED_JUMP, ABILITY_USED_FLAP, ABILITY_USED_FLIP, ABILITY_USED_SWIM, ABILITY_USED_CLIMB, - ABILITY_USED_BEAK_BARGE, ABILITY_USED_SLIDE, ABILITY_USED_EGG, ABILITY_USED_FLY, ABILITY_USED_SHOCK, - ABILITY_USED_PECK, ABILITY_USED_CLAW, ABILITY_USED_TWIRL, -}; - -void HackShared_EnableNoteSignSuppression(int signActorId); -void HackShared_EnableDialogSuppression(const int* dialogIds, int count); -void HackShared_EnableForceAbilitiesUsed(const ability_used* moves, int count); - -template inline void HackShared_EnableDialogSuppression(const int (&dialogIds)[N]) { - HackShared_EnableDialogSuppression(dialogIds, N); -} - -template inline void HackShared_EnableForceAbilitiesUsed(const ability_used (&moves)[N]) { - HackShared_EnableForceAbilitiesUsed(moves, N); -} diff --git a/src/port/Romhack/Shared/ProximityDialogs.cpp b/src/port/Romhack/Shared/ProximityDialogs.cpp deleted file mode 100644 index 1388630dc..000000000 --- a/src/port/Romhack/Shared/ProximityDialogs.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "ProximityDialogs.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "core1/ml.h" - -extern f32 D_8037C5B0[3]; -} - -namespace { -constexpr s32 kDialogFlagSkippable = 0x1; - -u16 sDialogShown[2] = { 0, 0 }; -const ProximityDialogMap* sWorldMaps = nullptr; -s32 sWorldMapCount = 0; -} // namespace - -void ProximityDialogs_Run(const ProximityDialogMap* maps, int count) { - if (getGameMode() != GAME_MODE_3_NORMAL || gcdialog_hasCurrentTextId()) { - return; - } - - const ProximityDialogMap* entry = nullptr; - const s32 map = gsworld_getMap(); - for (s32 i = 0; i < count; i++) { - if (maps[i].map == map) { - entry = &maps[i]; - break; - } - } - if (entry == nullptr) { - return; - } - if (entry->gate != nullptr && !entry->gate()) { - return; - } - - for (s32 i = 0; i < entry->pageCount; i++) { - const ProximityDialogPage& page = entry->pages[i]; - const bool tokenIsGuard = page.doneBit == 0; - if (tokenIsGuard ? mumboscore_get((enum mumbotoken_e)page.token) - : (sDialogShown[page.word] & page.doneBit) != 0) { - continue; - } - if (page.skipIfJiggy > 0 && jiggyscore_isCollected((enum jiggy_e)page.skipIfJiggy)) { - continue; - } - if (page.needFlag > 0 && !fileProgressFlag_get((enum file_progress_e)page.needFlag)) { - continue; - } - if (page.needFlagClear > 0 && fileProgressFlag_get((enum file_progress_e)page.needFlagClear)) { - continue; - } - f32 anchor[3] = { page.anchor[0], page.anchor[1], page.anchor[2] }; - if (!(ml_vec3f_distance(anchor, D_8037C5B0) < page.radius)) { - return; - } - gcdialog_showDialog(page.textId, page.dialogFlags | kDialogFlagSkippable, (f32*)page.dialogPos, NULL, NULL, - NULL); - sDialogShown[page.word] |= page.doneBit; - if (page.token >= 0) { - mumboscore_set((enum mumbotoken_e)page.token, true); - } - } -} - -void ProximityDialogs_Enable(const ProximityDialogMap* maps, int count) { - sWorldMaps = maps; - sWorldMapCount = count; - COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, sWorldMapCount > 0, - [](IEvent*) { ProximityDialogs_Run(sWorldMaps, sWorldMapCount); }); -} - -bool ProximityDialogs_IsShown(int word, unsigned bits) { - return (sDialogShown[word] & bits) != 0; -} - -void ProximityDialogs_ClearShown(int word, unsigned bits) { - sDialogShown[word] &= ~(u16)bits; -} diff --git a/src/port/Romhack/Shared/ProximityDialogs.h b/src/port/Romhack/Shared/ProximityDialogs.h deleted file mode 100644 index aac61acc8..000000000 --- a/src/port/Romhack/Shared/ProximityDialogs.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -struct ProximityDialogPage { - float anchor[3]; - float radius; - int textId; - int dialogFlags; - unsigned char word; // which sDialogShown word tracks this page - unsigned short doneBit; // bit within that word; 0 means "guarded by token instead" - int token; // mumbotoken to guard on / bank (-1 = none) - const float* dialogPos; - int skipIfJiggy; // skip if this jiggy is collected (>0) - int needFlag; // skip unless this FILEPROG flag is set (>0) - int needFlagClear; // skip if this FILEPROG flag is set (>0) -}; - -struct ProximityDialogMap { - int map; - const ProximityDialogPage* pages; - int pageCount; - // Optional per-map hook run before the page loop. Return false to skip this - // map's pages this frame; may also perform side effects. nullptr = always run. - bool (*gate)(); -}; - -// Run one frame of checks against a caller-owned table (used by the storybook). -void ProximityDialogs_Run(const ProximityDialogMap* maps, int count); - -// Register a GameFrameUpdate that runs the given world table every frame. -void ProximityDialogs_Enable(const ProximityDialogMap* maps, int count); - -// Deduce the count from a fixed table so callers pass just the table. -template inline void ProximityDialogs_Enable(const ProximityDialogMap (&maps)[N]) { - ProximityDialogs_Enable(maps, N); -} - -// Shown-bit access for gate() callbacks that re-arm a page. -bool ProximityDialogs_IsShown(int word, unsigned bits); -void ProximityDialogs_ClearShown(int word, unsigned bits); diff --git a/src/port/Romhack/Shared/StealthNoise.cpp b/src/port/Romhack/Shared/StealthNoise.cpp deleted file mode 100644 index 98147c193..000000000 --- a/src/port/Romhack/Shared/StealthNoise.cpp +++ /dev/null @@ -1,362 +0,0 @@ -#include -#include - -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/RomhackConfig.h" -#include "StealthNoise.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "bk_time.h" -#include "core1/core1.h" -#include "core2/timedfunc.h" -#include "core1/pfsmanager.h" - -extern f32 D_8037C5B0[3]; -extern PfsManagerControllerData D_80281138[4]; -extern Gfx D_80369238[]; -f32 randf(void); -s32 getGameMode(void); - -typedef struct { - s16 x, y, topVertexAlpha, bottomVertexAlpha; - u8 fmtString[8]; - f32 scale; - u8* string; - u8 rgba[4]; -} StealthPrintBuffer; -extern StealthPrintBuffer* print_sCurrentPtr; -} - -namespace { - -// Constants -constexpr f32 kHudLerp = 0.25f; -constexpr f32 kAlphaLerp = 0.2f; -constexpr f32 kAlphaEpsilon = 0.01f; -constexpr f32 kHudShownX = 20.0f; -constexpr f32 kHudHiddenX = -70.0f; -constexpr f32 kHudYDialog = 137.0f; -constexpr f32 kHudYPlain = 177.0f; -constexpr f32 kAlphaNear = 1.0f; -constexpr f32 kAlphaFar = 0.6f; -constexpr f32 kStickDeadzone = 0.1f; -constexpr f32 kGainScaleInner = 0.4f; -constexpr f32 kGainScaleOuter = 0.46f; -constexpr f32 kGainJitter = 0.05f; -constexpr f32 kDecay = 0.55f; -constexpr f32 kDecayFloor = 0.1f; -constexpr f32 kEggPeriodHead = 0.4f; -constexpr f32 kEggPeriodAss = 0.6f; -constexpr f32 kEggJitter = 0.07f; -constexpr f32 kLoudAirborne = 0.85f; -constexpr f32 kLoudAirJitter = 0.1f; -constexpr f32 kCatchCamDelay = 0.72f; -constexpr f32 kLabelScale = 0.75f; -constexpr s32 kAirborneForLanding = 3; -constexpr u32 kCatchSfxPacked = 0xB31FF86B; -constexpr s32 kCatchSfxA = 0x142; -constexpr s32 kCatchSfxB = 0x14B; - -// HUD geometry -constexpr s16 kLabelOffX = 8, kLabelOffY = 8; -constexpr s16 kFrameX = 0, kFrameY = 0, kFrameW = 85, kFrameH = 20; -constexpr s16 kBarX = 4, kBarY = 12, kBarW = 77, kBarH = 5; -constexpr f32 kFrameAlphaScale = 160.0f; -constexpr f32 kBarAlphaScale = 136.0f; - -// Quiet-states table -constexpr s32 kQuietStates[] = { - BS_0_NONE, - BS_1_IDLE, - BS_2_WALK_SLOW, - BS_1F_WALK_CREEP, - BS_5A_LOADZONE, - BS_7_CROUCH, - BS_7A_WALK_MUD, - BS_98_WALK_DRONE, - BS_9_EGG_HEAD, - BS_A_EGG_ASS, - BS_14_BTROT_ENTER, - BS_15_BTROT_IDLE, - BS_17_BTROT_EXIT, - BS_1A_WONDERWING_ENTER, - BS_1B_WONDERWING_IDLE, - BS_1E_WONDERWING_EXIT, -}; - -struct NoiseState { - s32 airborneFrames; - bool loudLanding; - f32 noise; - f32 gain; - f32 burstTimer; - f32 burstAmount; - f32 eggTimer; - bool hudRetracted; - f32 hudX, hudY, hudAlpha; - f32 targetX, targetY, targetAlpha; - bool hudOffscreen; -}; - -NoiseState sState{}; -const StealthNoiseConfig* sCfg = nullptr; -bool sCaughtBefore = false; -bool sSuspended = false; -bool sCatchPending = false; - -f32 Clamp01(f32 value) { - return value < 0.0f ? 0.0f : (value > 1.0f ? 1.0f : value); -} - -void Approach(f32& current, f32 target, f32 rate, f32 epsilon) { - const f32 delta = target - current; - if (fabsf(delta) > epsilon) { - current += delta * rate; - } -} - -bool IsQuiet(s32 state) { - for (s32 quietState : kQuietStates) { - if (quietState == state) { - return true; - } - } - return false; -} - -void ResetMeter() { - sState.airborneFrames = 0; - sState.loudLanding = false; - sState.noise = 0.0f; - sState.eggTimer = 0.0f; - sState.burstTimer = 0.0f; - sState.targetX = kHudHiddenX; - sState.targetY = kHudYPlain; - sState.targetAlpha = kAlphaFar; - sState.hudOffscreen = true; -} - -void RetractHud() { - sState.hudRetracted = true; -} - -void TriggerCatch() { - sState.noise = 1.0f; - func_8030E624(kCatchSfxPacked); - gcdialog_showDialog(sCfg->caughtTextId, sCaughtBefore ? 0x02 : 0x82, NULL, NULL, NULL, NULL); - func_80324E38(0.0f, 1); - timed_setStaticCameraToNode(kCatchCamDelay, 1); - timedFunc_set_0(kCatchCamDelay, RetractHud); - sCaughtBefore = true; - sCatchPending = true; -} - -void ResolveCatch() { - gcsfx_play((enum sfx_e)(sfx_randi2(0, 2) != 0 ? kCatchSfxA : kCatchSfxB)); - if (!mumboscore_get((enum mumbotoken_e)sCfg->firstCatchToken)) { - const s32 warpDestination = port_getRomhackWarpDest(sCfg->escapeWarpIndex); - if (warpDestination >= 0) { - func_8031CC8C(NULL, warpDestination); - } else if (sCfg->escapeWarpFallback != nullptr) { - sCfg->escapeWarpFallback(NULL, NULL); - } - mumboscore_set((enum mumbotoken_e)sCfg->firstCatchToken, 1); - } else { - transitionToMap((enum map_e)gsworld_getMap(), gsworld_getExit(), 1); - } - sSuspended = true; - sCatchPending = false; -} - -void Update() { - if (sCfg == nullptr || gsworld_getMap() != sCfg->map) { - return; - } - NoiseState& meter = sState; - - Approach(meter.hudX, meter.targetX, kHudLerp, 1.0f); - Approach(meter.hudY, meter.targetY, kHudLerp, 1.0f); - Approach(meter.hudAlpha, meter.targetAlpha, kAlphaLerp, kAlphaEpsilon); - meter.hudAlpha = Clamp01(meter.hudAlpha); - - if (meter.burstTimer > 0.0f) { - meter.burstTimer -= time_getDelta(); - if (meter.burstTimer < 0.0f) { - meter.burstTimer = 0.0f; - } - } else { - meter.burstAmount = 0.0f; - } - - const bool dialogUp = gcdialog_hasCurrentTextId() != 0; - if (!dialogUp && sCatchPending) { - ResolveCatch(); - } - - const f32 playerX = D_8037C5B0[0]; - const bool inRoom = playerX >= sCfg->zoneMin && playerX <= sCfg->zoneMax; - if (inRoom && !meter.hudRetracted) { - meter.hudOffscreen = false; - } else if (!inRoom) { - meter.hudOffscreen = true; - } - - print_dialog((s32)(kLabelOffX + meter.hudX), (s32)(kLabelOffY + meter.hudY), (u8*)"NOISE"); - if (print_sCurrentPtr != nullptr) { - print_sCurrentPtr->scale = kLabelScale; - if (inRoom && !meter.hudOffscreen) { - meter.targetAlpha = (playerX >= sCfg->innerMin && playerX <= sCfg->innerMax) ? kAlphaNear : kAlphaFar; - } else { - meter.targetAlpha = 0.0f; - } - print_sCurrentPtr->rgba[0] = 0xFF; - print_sCurrentPtr->rgba[1] = 0xFF; - print_sCurrentPtr->rgba[2] = 0xFF; - print_sCurrentPtr->rgba[3] = (u8)(meter.hudAlpha * 255.0f); - } - - meter.targetY = dialogUp ? kHudYDialog : kHudYPlain; - meter.targetX = meter.hudRetracted ? kHudHiddenX : kHudShownX; - meter.hudOffscreen = meter.hudRetracted; - - if (sSuspended || sCatchPending) { - return; - } - - const s32 state = bs_getState(); - const bool quiet = IsQuiet(state); - const bool stable = player_isStable() != 0; - - const bool inner = playerX >= sCfg->innerMin && playerX <= sCfg->innerMax; - if (!inRoom) { - ResetMeter(); - return; - } - - const bool muted = !stable || D_80281138[0].side_button2.button_z != 0 || state == BS_73_UNKNOWN || - state == BS_79_BTROT_LOCKED || state == BS_98_WALK_DRONE || state == BS_1E_WONDERWING_EXIT || - (state & ~0x10) == BS_7_CROUCH; - f32 gain = 0.0f; - if (!muted) { - gain = Clamp01((bastick_distance() - kStickDeadzone) / (inner ? kGainScaleInner : kGainScaleOuter)); - } - meter.gain = Clamp01(gain + randf() * kGainJitter); - - if (state == BS_9_EGG_HEAD || state == BS_A_EGG_ASS) { - meter.eggTimer += time_getDelta(); - const f32 period = (state == BS_9_EGG_HEAD) ? kEggPeriodHead : kEggPeriodAss; - meter.noise = (meter.eggTimer > period ? kStickDeadzone : 0.0f) + meter.burstAmount + randf() * kEggJitter; - } else { - meter.noise = (inner && stable) ? meter.gain : meter.noise + meter.gain; - meter.eggTimer = 0.0f; - if (!stable) { - meter.airborneFrames++; - if (!inner) { - meter.loudLanding = false; - } - } else { - if (meter.airborneFrames >= kAirborneForLanding) { - meter.loudLanding = true; - meter.noise = 1.0f; - } - if (!inner) { - meter.loudLanding = false; - const f32 decayed = meter.noise * kDecay; - if (decayed < kDecayFloor) { - meter.airborneFrames = 0; - meter.noise = 0.0f; - } else { - meter.noise = decayed; - } - meter.noise += randf() * kGainJitter; - } - } - } - - if (state != BS_73_UNKNOWN && state != BS_79_BTROT_LOCKED && !quiet) { - meter.noise = stable ? 1.0f : kLoudAirborne + randf() * kLoudAirJitter; - } - meter.noise = Clamp01(meter.noise); - - if (inner && stable && (!quiet || meter.loudLanding)) { - TriggerCatch(); - } -} - -void FillRect(Gfx** gfx, s32 left, s32 top, s32 width, s32 height, u8 red, u8 green, u8 blue, u8 alpha) { - if (width <= 0 || height <= 0 || alpha == 0) { - return; - } - gDPPipeSync((*gfx)++); - gDPSetPrimColor((*gfx)++, 0, 0, red, green, blue, alpha); - gDPSetCombineMode((*gfx)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); - gDPScisFillRectangle((*gfx)++, left, top, left + width - 1, top + height - 1); - gDPPipeSync((*gfx)++); -} - -void BarColour(s32 percent, u8* red, u8* green) { - const s32 remaining = 100 - percent; - if (percent >= 100) { - *red = 0xFF; - *green = 0x00; - } else if (remaining >= 100) { - *red = 0x00; - *green = 0xFF; - } else if (remaining < 40) { - *red = 0xFF; - *green = (u8)((255 * remaining) / 40); - } else { - *red = (u8)((255 * percent) / 60); - *green = 0xFF; - } -} - -void Draw(Gfx** gfx) { - if (sCfg == nullptr || gsworld_getMap() != sCfg->map || getGameMode() == GAME_MODE_4_PAUSED) { - return; - } - const NoiseState& meter = sState; - const u8 frameAlpha = (u8)(meter.hudAlpha * kFrameAlphaScale); - if (frameAlpha == 0) { - return; - } - - gSPDisplayList((*gfx)++, D_80369238); - FillRect(gfx, (s32)(kFrameX + meter.hudX), (s32)(kFrameY + meter.hudY), kFrameW, kFrameH, 0x00, 0x00, 0x00, - frameAlpha); - - s32 percent = (s32)(meter.noise * 100.0f); - percent = percent < 0 ? 0 : (percent > 100 ? 100 : percent); - u8 red, green; - BarColour(percent, &red, &green); - FillRect(gfx, (s32)(kBarX + meter.hudX), (s32)(kBarY + meter.hudY), (s32)(kBarW * meter.noise), kBarH, red, green, - 0x00, (u8)(meter.hudAlpha * kBarAlphaScale)); -} - -} // namespace - -void StealthNoise_AddBurst(float amount, float seconds) { - sState.burstAmount = amount; - sState.burstTimer = seconds; -} - -void StealthNoise_Enable(const StealthNoiseConfig& cfg) { - sCfg = &cfg; - ResetMeter(); - - REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent*) { Update(); }); - - REGISTER_LISTENER(OnHudDraw, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - auto* hudEvent = reinterpret_cast(event); - Draw(hudEvent->gfx); - }); - - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_NORMAL, [](IEvent*) { - sSuspended = false; - sCatchPending = false; - sState.hudRetracted = false; - ResetMeter(); - }); -} diff --git a/src/port/Romhack/Shared/StealthNoise.h b/src/port/Romhack/Shared/StealthNoise.h deleted file mode 100644 index 5d25e698c..000000000 --- a/src/port/Romhack/Shared/StealthNoise.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -extern "C" { -#include "prop.h" -} - -struct StealthNoiseConfig { - int map; - float zoneMin; - float zoneMax; - float innerMin; - float innerMax; - int caughtTextId; - int escapeWarpIndex; - void (*escapeWarpFallback)(NodeProp*, ActorMarker*); - int firstCatchToken; -}; - -void StealthNoise_Enable(const StealthNoiseConfig& cfg); -void StealthNoise_AddBurst(float amount, float seconds); diff --git a/src/port/Romhack/Shared/Storybook.cpp b/src/port/Romhack/Shared/Storybook.cpp deleted file mode 100644 index d461cb546..000000000 --- a/src/port/Romhack/Shared/Storybook.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "Storybook.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "macros.h" -#include "actor.h" -#include "core1/ml.h" - -extern OSContPad pfsManagerContPadData[4]; -extern PfsManagerControllerData D_80281138[4]; -extern Struct_core1_10A00_1 D_80281250[4]; -extern f32 D_8037C5B0[3]; -extern f32 player_position[3]; -} - -namespace { - -bool IsStorybookMap(enum map_e map); -f32 StoryStickAxis(s32 raw); -void StorybookInputCapture(); -void StorybookPageUpdate(); -void ApplyStorybookIntroHooks(); - -// Engine tuning -constexpr f32 kPageStep = 2500.0f; -constexpr f32 kStickClamp = 80.0f; -constexpr f32 kPushThreshold = 0.5f; -constexpr f32 kCenterThreshold = 0.3f; -constexpr s32 kDebounceTicks = 50; - -// Per-hack data -const ProximityDialogMap* sPages = nullptr; -s32 sPageCount = 0; -s32 sResumeDest = 0; -s32 sSeenToken = -1; - -bool sStorybookEnabled = false; -s32 sStoryTick = 0; -s32 sStoryLastStep = -kDebounceTicks - 1; -s32 sStoryStickX = 0; -s32 sStoryStickY = 0; - -bool IsStorybookMap(enum map_e map) { - for (s32 i = 0; i < sPageCount; i++) { - if ((enum map_e)sPages[i].map == map) { - return true; - } - } - return false; -} - -f32 StoryStickAxis(s32 raw) { - f32 v = (f32)raw; - if (v > kStickClamp) { - v = kStickClamp; - } else if (v < -kStickClamp) { - v = -kStickClamp; - } - return v / kStickClamp; -} - -void StorybookInputCapture() { - if (!IsStorybookMap(gsworld_getMap())) { - return; - } - sStoryStickX = pfsManagerContPadData[0].stick_x; - sStoryStickY = pfsManagerContPadData[0].stick_y; - memset(&D_80281138[0], 0, sizeof(D_80281138[0])); - memset(&D_80281250[0], 0, sizeof(D_80281250[0])); - pfsManagerContPadData[0].stick_x = 0; - pfsManagerContPadData[0].stick_y = 0; - pfsManagerContPadData[0].button = 0; -} - -void StorybookPageUpdate() { - sStoryTick++; - if (!IsStorybookMap(gsworld_getMap())) { - return; - } - D_8037C5B0[1] = 0.0f; - D_8037C5B0[2] = 0.0f; - - if (!gcdialog_hasCurrentTextId()) { - const f32 x = StoryStickAxis(sStoryStickX); - const f32 y = StoryStickAxis(sStoryStickY); - if (y > -kCenterThreshold && y < kCenterThreshold && x > kPushThreshold && - sStoryLastStep + kDebounceTicks < sStoryTick) { - sStoryLastStep = sStoryTick; - D_8037C5B0[0] += kPageStep; - } - } - player_position[0] = D_8037C5B0[0]; -} - -void ApplyStorybookIntroHooks() { - // First storybook writes a mumbo token to indicate that it's been seen - COND_VB_SHOULD(VB_GAMESELECT_START_NEW_GAME, EVENT_PRIORITY_NORMAL, sStorybookEnabled, { - (void)args; // gamenum is passed but unused - const bool seen = sSeenToken >= 0 && mumboscore_get((enum mumbotoken_e)sSeenToken); - *should = !seen; - }); - - // Storybook mode freezes all input except the left stick's right movement - COND_HOOK(OnControllerUpdate, EVENT_PRIORITY_NORMAL, sStorybookEnabled, [](IEvent*) { StorybookInputCapture(); }); - - COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, sStorybookEnabled, [](IEvent*) { - ProximityDialogs_Run(sPages, sPageCount); - StorybookPageUpdate(); - }); -} - -} // namespace - -extern "C" void Storybook_ResumeWarp(NodeProp* node, ActorMarker* marker) { - (void)marker; - func_8031CC8C(node, sResumeDest); -} - -extern "C" void* port_getRomhackResumeWarpFunc(void) { - return sStorybookEnabled ? (void*)&Storybook_ResumeWarp : nullptr; -} - -void Storybook_Enable(const StorybookConfig& cfg) { - sPages = cfg.pages; - sPageCount = cfg.pageCount; - sResumeDest = cfg.resumeDest; - sSeenToken = cfg.newGameSeenToken; - sStorybookEnabled = true; - ApplyStorybookIntroHooks(); -} diff --git a/src/port/Romhack/Shared/Storybook.h b/src/port/Romhack/Shared/Storybook.h deleted file mode 100644 index 554ec22d3..000000000 --- a/src/port/Romhack/Shared/Storybook.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "ProximityDialogs.h" - -struct StorybookConfig { - const ProximityDialogMap* pages; // book pages, one entry per book map - int pageCount; // number of book maps - int resumeDest; // MAP<<8 | ENTRY warp used when resuming a save - int newGameSeenToken; // mumbotoken the first book banks (-1 = none) -}; - -void Storybook_Enable(const StorybookConfig& cfg); diff --git a/src/port/Romhack/Specific/BubblingBog.cpp b/src/port/Romhack/Specific/BubblingBog.cpp deleted file mode 100644 index 9762bbe5d..000000000 --- a/src/port/Romhack/Specific/BubblingBog.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/Shared/HackShared.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -} - -// The Tooie jiggy animation exists in this hack -void TooieJiggyDance_ForceEnable(); - -void RegisterBubblingBogPatches() { - TooieJiggyDance_ForceEnable(); - HackShared_EnableForceAbilitiesUsed(kAllUsedAbilities); - - // Bubbling Bog Brewery's swapy water is hazardous - REGISTER_VB_SHOULD(VB_GROUND_HAZARD_ACTIVE, EVENT_PRIORITY_NORMAL, { - s32 map = va_arg(args, s32); - if (map == MAP_D_BGS_BUBBLEGLOOP_SWAMP && func_80294554()) { - *should = true; - } - }); -} diff --git a/src/port/Romhack/Specific/CutThroatCoast.cpp b/src/port/Romhack/Specific/CutThroatCoast.cpp deleted file mode 100644 index 4ef92627e..000000000 --- a/src/port/Romhack/Specific/CutThroatCoast.cpp +++ /dev/null @@ -1,284 +0,0 @@ -#include -#include -#include -#include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/RomhackConfig.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "model.h" - -extern struct1Cs_1 D_8036C58C[0xD]; - -// Acorn replaced with collectible doubloon -extern ActorInfo chCarriedAcorn; -void chCarriedAcorn_update(Actor* thisx); - -typedef struct { - u8 map_id; - u8 rgb[3]; - u8 alpha; -} CameraFogEntry; -extern CameraFogEntry D_80365D60[]; - -typedef struct { - u8 uid; - u8 state; - u8 next_state; - f32 duration; - s32 model_index; - s32 anim_index; - f32 scale; -} TransitionInfoEntry; -extern TransitionInfoEntry D_8036C150[0x16]; -} - -namespace { - -// Custom transition pair -constexpr s32 kPairMapA = MAP_2_MM_MUMBOS_MOUNTAIN; -constexpr s32 kPairMapB = MAP_31_RBB_RUSTY_BUCKET_BAY; -constexpr s32 kPairInIndex = 0xD; - -GameMap sPrevMap = (GameMap)0; -GameMap sCurMap = (GameMap)0; - -struct PauseRemap { - int src; - s16 level_id; - s16 x; -}; -constexpr PauseRemap kRemap[0xD] = { - { 0, 0, 80 }, { 1, 0, 64 }, { 3, 0, 37 }, { 4, 0, 27 }, { 5, 0, 52 }, { 6, 0, 35 }, { 7, 0, 72 }, - { 8, 0, 78 }, { 9, 0xA, 43 }, { 10, 0, 50 }, { 11, 0, 48 }, { 2, 0, 60 }, { 12, 0, 72 }, -}; - -void RebuildPauseMenuTable() { - u8* names[0xD]; - for (int i = 0; i < 0xD; i++) { - names[i] = D_8036C58C[i].string; - } - for (int page = 0; page < 0xD; page++) { - D_8036C58C[page].string = names[kRemap[page].src]; - D_8036C58C[page].level_id = kRemap[page].level_id; - D_8036C58C[page].x = kRemap[page].x; - } - D_8036C58C[8].string = (u8*)"CUT-THROAT COAST"; -} - -void ApplyDataPatches() { - D_80365D60[3] = { 0, { 0x34, 0x6E, 0xEF }, 0x5A }; - D_8036C150[3].state = 7; // TRANSITION_STATE_7_WHITE_IN - D_8036C150[3].next_state = 0; // TRANSITION_STATE_0_NONE - D_8036C150[3].duration = 0.7f; - D_8036C150[3].model_index = 0; - D_8036C150[3].anim_index = 0; - D_8036C150[12].duration = 0.4f; - D_8036C150[13].state = 3; // TRANSITION_STATE_3_BLACK_OUT - D_8036C150[13].next_state = 1; // TRANSITION_STATE_1_LOADING - D_8036C150[13].duration = 0.4f; - D_8036C150[13].model_index = 0; - D_8036C150[13].scale = 0.0f; -} - -// Lighthouse beam sweep -constexpr s32 kBeamFirstVtx = 423; -constexpr s32 kBeamLastVtx = 454; -constexpr f32 kBeamDegPerTick = 2.0f; - -struct BeamVert { - Vtx* v; - f32 dx, dz; -}; -BKModelBin* sBeamModelBin = nullptr; -std::vector sBeamVerts; -f32 sBeamAngle = 0.0f; -f32 sBeamPivotX, sBeamPivotZ; - -void UpdateLighthouseBeam() { - if (gsworld_getMap() != MAP_1B_MMM_MAD_MONSTER_MANSION) { - return; - } - BKModelBin* bin = mapModel_getModelBin(1); - if (bin == nullptr) { - sBeamModelBin = nullptr; - return; - } - if (bin != sBeamModelBin) { - sBeamModelBin = bin; - sBeamVerts.clear(); - BKVertexList* vl = modelbin_getVtxList(bin); - if (vl == nullptr) { - sBeamModelBin = nullptr; - return; - } - s32 cnt = vtxList_getVtxCount(vl); - if (cnt <= kBeamLastVtx) { - return; - } - for (s32 i = kBeamFirstVtx; i <= kBeamLastVtx; i++) { - sBeamVerts.push_back({ &vl->vertices[i], 0.0f, 0.0f }); - } - sBeamPivotX = 3563.0f; - sBeamPivotZ = 8751.0f; - for (auto& bv : sBeamVerts) { - bv.dx = bv.v->v.ob[0] - sBeamPivotX; - bv.dz = bv.v->v.ob[2] - sBeamPivotZ; - } - } - sBeamAngle = mlNormalizeAngle(sBeamAngle + kBeamDegPerTick); - f32 rad = sBeamAngle * (f32)(BAD_PI / 180.0); - f32 c = cosf(rad), s = sinf(rad); - for (auto& bv : sBeamVerts) { - bv.v->v.ob[0] = (s16)(sBeamPivotX + bv.dx * c - bv.dz * s); - bv.v->v.ob[2] = (s16)(sBeamPivotZ + bv.dx * s + bv.dz * c); - } -} - -} // namespace - -extern "C" void CutThroatCoast_DoubloonUpdate(Actor* thisx) { - thisx->yaw = mlNormalizeAngle(thisx->yaw + 12.0f); - chCarriedAcorn_update(thisx); -} - -void RegisterCutThroatCoastPatches() { - RebuildPauseMenuTable(); - ApplyDataPatches(); - chCarriedAcorn.update_func = CutThroatCoast_DoubloonUpdate; - - // Sweep the lighthouse beam - REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - (void)event; - UpdateLighthouseBeam(); - }); - - // Track map changes for the custom MM <-> RBB transition below. - REGISTER_LISTENER(OnMapLoad, EVENT_PRIORITY_HIGH, [](IEvent* event) { - auto* ev = reinterpret_cast(event); - sPrevMap = ev->prevMap; - sCurMap = ev->nextMap; - }); - - // Pause menu pins below - REGISTER_VB_SHOULD(VB_JIGGYSCORE_LEVEL_TOTAL, EVENT_PRIORITY_NORMAL, { - s32 lvl = va_arg(args, s32); - s32* result = va_arg(args, s32*); - s32 cnt = 0; - if (lvl == 0xA) { - for (s32 i = 1; i < 0x65; i++) { - if (jiggyscore_isCollected((enum jiggy_e)i)) { - cnt++; - } - } - if (cnt > 0xA) { - cnt = 0xA; - } - } - *result = cnt; - *should = false; - }); - - REGISTER_VB_SHOULD(VB_PAUSEMENU_LEVEL_TO_PAGE, EVENT_PRIORITY_NORMAL, { - va_arg(args, s32); - s32* page = va_arg(args, s32*); - *page = 8; - *should = false; - }); - - REGISTER_VB_SHOULD(VB_PAUSEMENU_SET_NEXT_PAGE, EVENT_PRIORITY_NORMAL, { - s8* page = va_arg(args, s8*); - *page = 8; - *should = false; - }); - - REGISTER_VB_SHOULD(VB_PAUSEMENU_DRAW_JOYSTICKS, EVENT_PRIORITY_NORMAL, { - (void)args; - *should = false; - }); - - REGISTER_VB_SHOULD(VB_PAUSEMENU_BOLD_FONT_TEXTURE, EVENT_PRIORITY_NORMAL, { - s32* fontId = va_arg(args, s32*); - *fontId = 0x6E4; - (void)should; - }); - - // TODO: CTC has an extra data blob separate from the asset table - // where a custom gravestone and note door (100) are. Torch should not - // need to do per-romhack extraction, so these will need to either be skipped - // or rebuilt a different way. For now, blank the digits on the note door. - REGISTER_VB_SHOULD(VB_NOTEDOOR_DRAW_NUMBER, EVENT_PRIORITY_NORMAL, { - s32 noteDoorIdx = va_arg(args, s32); - if (noteDoorIdx >= 1 && port_getRomhackNoteDoor(noteDoorIdx - 1) >= 0) { - *should = false; - } - }); - - // Exiting via the exit pad should go back to the CTC lobby map - REGISTER_VB_SHOULD(VB_MAP_CHANGE_REQUEST, EVENT_PRIORITY_NORMAL, { - s32* map = va_arg(args, s32*); - s32* exit = va_arg(args, s32*); - if (*map == MAP_75_GL_MMM_LOBBY) { - *map = MAP_1_SM_SPIRAL_MOUNTAIN; - *exit = 2; - } - (void)should; - }); - - REGISTER_VB_SHOULD(VB_VOID_OUT_RESPAWN_TRANSITION, EVENT_PRIORITY_NORMAL, { - s32 map = va_arg(args, s32); - s32 exit = va_arg(args, s32); - transitionToMap((enum map_e)map, exit, 1); - *should = false; - }); - - REGISTER_VB_SHOULD(VB_MAP_TRANSITION_IN_INDEX, EVENT_PRIORITY_NORMAL, { - s32 map = va_arg(args, s32); - s32* inIndex = va_arg(args, s32*); - s32 other = (map == sCurMap) ? sPrevMap : sCurMap; - if ((map == kPairMapA && other == kPairMapB) || (map == kPairMapB && other == kPairMapA)) { - *inIndex = kPairInIndex; - } - (void)should; - }); - - // The repurposed season switches are hidden below the ground when hit - REGISTER_VB_SHOULD(VB_CCW_SEASON_SWITCH_PRESSED_INIT, EVENT_PRIORITY_NORMAL, { - Actor* switchActor = va_arg(args, Actor*); - switchActor->position[1] = -420.0f; - subaddie_set_state(switchActor, 4); - *should = false; - }); - - // Suppress the jiggy tutorial dialog - REGISTER_VB_SHOULD(VB_JIGGY_COLLECT_TUTORIAL, EVENT_PRIORITY_NORMAL, { - (void)args; - *should = false; - }); - - // This MMM empty honeycomb doesn't require the pumpkin - REGISTER_VB_SHOULD(VB_HONEYCOMB_PUMPKIN_REQUIREMENT, EVENT_PRIORITY_NORMAL, { - (void)args; - *should = false; - }); - - // The sky timer never advances, so skybox layers hold their initial rotation - REGISTER_VB_SHOULD(VB_SKY_UPDATE, EVENT_PRIORITY_NORMAL, { - (void)args; - *should = false; - }); - - // No fullscreen clear behind the skybox when sky models are present - REGISTER_VB_SHOULD(VB_SKY_DRAW_BACKDROP_RECT, EVENT_PRIORITY_NORMAL, { - (void)args; - *should = false; - }); - - // Suppress Brentilda's heal dialog - REGISTER_VB_SHOULD(VB_BRENTILDA_HEAL_DIALOG, EVENT_PRIORITY_NORMAL, { - (void)args; - *should = false; - }); -} diff --git a/src/port/Romhack/Specific/Dreamie.cpp b/src/port/Romhack/Specific/Dreamie.cpp deleted file mode 100644 index 2a1dbae0c..000000000 --- a/src/port/Romhack/Specific/Dreamie.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Banjo-Dreamie - * - * Dreamie ships no custom code at all - it rewires the world purely through BB - * globalized-overlay data, so the BKCF carries everything. Spiral Mountain becomes - * the hub, and two of the ~86 warp edits retarget the Spiral Mountain transitions: - * - * warp_smExitBanjosHouse 0x0112 -> 0x0105 - * warp_lairEnterLairFromSMLevel 0x6912 -> 0x0112 - * - * Both resolve to map 0x01, which is also Dreamie's new-game map (START_MAP = 1, - * START_LEVEL_2 = 1, down from vanilla 0x69). Honoring them verbatim drops every hub - * transition back into the starting room instead of moving between areas. - * - * On every OnWarpResolveDest fire, restore the dispatcher's vanilla default for these - * two warps, ignoring what the BKCF claims. The other BKCF warp remaps are genuine and - * pass through untouched. - * - */ - -#include - -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/RomhackConfig.h" - -static constexpr int kWarpIdxSmExitBanjosHouse = 281; - -void RegisterDreamiePatches() { - port_clearRomhackWarpDest(kWarpIdxSmExitBanjosHouse); - - REGISTER_LISTENER(OnWarpResolveDest, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - auto* ev = reinterpret_cast(event); - if (ev->warpId == WARP_ID_SM_EXIT_BANJOS_HOUSE || ev->warpId == WARP_ID_LAIR_ENTER_LAIR_FROM_SM_LEVEL) { - *ev->dest = ev->defaultDest; - } - }); -} diff --git a/src/port/Romhack/Specific/JiggiesOfTime.cpp b/src/port/Romhack/Specific/JiggiesOfTime.cpp deleted file mode 100644 index 614288a40..000000000 --- a/src/port/Romhack/Specific/JiggiesOfTime.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Jiggies of Time Fun Facts - * - * The Collywobble actor is marker-swapped to prevent a spawn. This is rarely seen anyway, since BB enforces - * file select as the default boot. With vanilla, if you were to view the intro sequence after a game over, - * you'd see a stray Collywobble spawned during the concert when it shouldn't be there at all. - * - * An unused vanilla marker 0x54 spawns ASSET_50B_MODEL_X_BARREL_TOP, which in Jiggies of Time is model-swapped - * with a random honeycomb drop. - * - */ - -#include -#include "port/Romhack/Shared/HackShared.h" - -extern "C" { -#include "enums.h" -#include "functions.h" - -extern ActorInfo chXBarrelTop; -extern ActorInfo gChVegetablesCollywobbleB; -} - -void RegisterJiggiesOfTimePatches() { - chXBarrelTop.markerId = 0x54; - gChVegetablesCollywobbleB.markerId = MARKER_1F1_GRUNTLING_BLACK; - - // JoT's note signs are repurposed Red Question Marks. - // Source: https://github.com/Mr-Wiseguy/JiggiesOfTimeRecomp/blob/main/src/note_signs.c - HackShared_EnableNoteSignSuppression(ACTOR_54_RED_QUESTION_MARK); -} diff --git a/src/port/Romhack/Specific/NewHorizons.cpp b/src/port/Romhack/Specific/NewHorizons.cpp deleted file mode 100644 index 67d671680..000000000 --- a/src/port/Romhack/Specific/NewHorizons.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * New Horizons Fun Facts - * - * Beyond the BKCF-covered data tables, New Horizons patches two ActorInfo - * marker bindings inside its copy of the globalized-overlay blob. - * - */ - -#include -#include "port/Enhancements/Events/Hooks/Events.h" - -extern "C" { -#include "enums.h" -#include "functions.h" - -// { MARKER_235_CRACKED_SKYLIGHT, ACTOR_23F_CRACKED_SKYLIGHT, ... } -extern ActorInfo chCrackedSkylight; -// { 0x220, 0x22C, ... } -extern ActorInfo D_80392994; -} - -void RegisterNewHorizonsPatches() { - chCrackedSkylight.markerId = MARKER_60_BLUE_EGG_COLLECTIBLE; - D_80392994.markerId = MARKER_60_BLUE_EGG_COLLECTIBLE; -} diff --git a/src/port/Romhack/Specific/Nostalgia64.cpp b/src/port/Romhack/Specific/Nostalgia64.cpp deleted file mode 100644 index faf6b5de0..000000000 --- a/src/port/Romhack/Specific/Nostalgia64.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/Shared/HackShared.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "actor.h" - -extern ActorInfo D_80393378; -extern ActorInfo chGruntlingBlack; -extern ActorInfo chCellarHatch; -extern ActorInfo chMMMWideWindow; - -void chGruntling_initialize(Actor* thisx); -void func_802D3CE8(Actor* thisx); -} - -struct HitboxRow { - u16 markerId; - u16 flags; - u16 vals[11]; -}; -extern "C" HitboxRow collision_table[]; - -namespace { - -// Black Gruntling is recycled to use the Beta Vent enemy -bool sBlackGruntlingAttack = false; - -extern "C" void Nostalgia64_VentUpdate(Actor* thisx) { - Humanoid_Baddies_Actor* local = (Humanoid_Baddies_Actor*)&thisx->local; - if (!thisx->volatile_initialized) { - local->baddieSpecific = (thisx->modelCacheIndex == ACTOR_367_GRUNTLING_RED) ? 2 - : (thisx->modelCacheIndex == ACTOR_3BF_GRUNTLING_BLUE) ? 1 - : 0; - chGruntling_initialize(thisx); - } - humanoidBaddie_update(thisx); - if (thisx->state == 5) { - bool swipeFrame = actor_animationIsAt(thisx, 0.18f); - if (swipeFrame) { - sfx_playFadeShorthandDefault(SFX_2_CLAW_SWIPE, 1.0f, 28000, thisx->position, 1250, 2500); - } - sBlackGruntlingAttack = true; - if (swipeFrame) { - sfx_playFadeShorthandDefault(SFX_1F_HITTING_AN_ENEMY_3, 1.0f, 28000, thisx->position, 1250, 2500); - } - } -} - -// Banjo takes damage while the vent is open -extern "C" void Nostalgia64_VentSmokeUpdate(Actor* thisx) { - func_802D3CE8(thisx); - for (int i = 0; i < 0xBB; i++) { - if (collision_table[i].markerId == MARKER_1F1_GRUNTLING_BLACK) { - collision_table[i].vals[10] = 0x7000; - break; - } - } - if (sBlackGruntlingAttack) { - item_adjustByDiffWithHud(ITEM_14_HEALTH, -item_getCount(ITEM_14_HEALTH)); - bs_setState(BS_41_DIE); - sBlackGruntlingAttack = false; - } -} - -// The 1881 Barrel Top was swapped for a breakable door -extern "C" void Nostalgia64_BreakableDoorUpdate(Actor* thisx) { - func_802D3CE8(thisx); - for (int i = 0; i < 0xBB; i++) { - if (collision_table[i].markerId == MARKER_9A_1881_BARREL_TOP) { - collision_table[i].flags = 0x0804; - break; - } - } -} - -} // namespace - -void RegisterNostalgia64Patches() { - D_80393378.markerId = MARKER_65_SHRAPNEL; - - chGruntlingBlack.update_func = Nostalgia64_VentUpdate; - chCellarHatch.update_func = Nostalgia64_VentSmokeUpdate; - chMMMWideWindow.update_func = Nostalgia64_BreakableDoorUpdate; - - // The N64 cube stands in for the note signs - HackShared_EnableNoteSignSuppression(ACTOR_93_INTRO_N64_CUBE); -} diff --git a/src/port/Romhack/Specific/TheGruntch.cpp b/src/port/Romhack/Specific/TheGruntch.cpp deleted file mode 100644 index 497d139ab..000000000 --- a/src/port/Romhack/Specific/TheGruntch.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* - * All hack-specific code here is shared - between Gruntch and Santa's Village. - */ - -#include -#include "port/Enhancements/Events/Hooks/Events.h" -#include "port/Romhack/Shared/HackShared.h" -#include "port/Romhack/Shared/Storybook.h" -#include "port/Romhack/Shared/ProximityDialogs.h" -#include "port/Romhack/Shared/StealthNoise.h" - -extern "C" { -#include "enums.h" -#include "functions.h" -#include "macros.h" -#include "actor.h" -#include "core1/ml.h" -#include "core2/timedfunc.h" -#include "bk_time.h" - -extern f32 D_8037C5B0[3]; -extern PfsManagerControllerData D_80281138[4]; -extern f32 cameraPosition[3]; -extern f32 cameraRotation[3]; -extern f32 D_8037D948[3]; -extern f32 D_8037D9C8[3]; -extern f32 D_8037D9E0[3]; -extern f32 D_8037D9D4, D_8037D9D8, D_8037D9EC, D_8037D9F0; -extern struct { - u8 unk0; - u8 level; -} D_80383300; - -typedef struct struct_1A_s { - f32 delay; - f32 unk4; - u8* str; - s16 y; - u8 portrait; - u8 unkF; -} PauseTotalsRow; -extern PauseTotalsRow D_8036C520[4]; -extern s8 D_8036C5F4[]; -} - -void TooieJiggyDance_ForceEnable(); - -// Suppressed dialogs -constexpr int kGruntchSuppressedDialogs[] = { - ASSET_A6F_DIALOG_RUBEE_MEET, - ASSET_C8B_DIALOG_GRUNTY_LONG_SWITCH_MISS, - ASSET_CCF_DIALOG_GNAWTY_MEET_SUMMER, - ASSET_DA3_DIALOG_EXTRA_LIFE_MEET, - 0xF78, - ASSET_D9C_DIALOG_MUSIC_NOTE_MEET, - ASSET_D9D_DIALOG_MUMBO_TOKEN_MEET, - ASSET_D9E_DIALOG_BLUE_EGG_MEET, - ASSET_D9F_DIALOG_RED_FEATHER_MEET, - ASSET_DA0_DIALOG_GOLD_FEATHER_MEET, - ASSET_DA1_DIALOG_HONEYCOMB_MEET, -}; - -// ---------------------------------------------------------- Proximity dialogs -constexpr s32 kDialogFlags8A = 0x8A; -constexpr s32 kDialogFlags82 = 0x82; -constexpr s32 kDialogFlagsA = 0x0A; -constexpr f32 kDialogRadius = 300.0f; - -// Storybook page dialogs -constexpr ProximityDialogPage kPages37[] = { - { { -7500.0f, 0.0f, 0.0f }, - kDialogRadius, - 0xA1D, - kDialogFlags8A, - 0, - 0x8000, - MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER }, - { { -5000.0f, 0.0f, 0.0f }, kDialogRadius, 0xA1E, kDialogFlags8A, 0, 0x4000, -1 }, - { { -2500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA29, kDialogFlags8A, 0, 0x2000, -1 }, -}; - -constexpr ProximityDialogPage kPages38[] = { - { { -7500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA77, kDialogFlags8A, 0, 0x0040, -1 }, -}; - -constexpr ProximityDialogPage kPages3E[] = { - { { -7500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA70, kDialogFlags8A, 0, 0x1000, -1 }, - { { -5000.0f, 0.0f, 0.0f }, kDialogRadius, 0xA72, kDialogFlags8A, 0, 0x0800, -1 }, - { { -2500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA73, kDialogFlags8A, 0, 0x0400, -1 }, - { { 0.0f, 0.0f, 0.0f }, kDialogRadius, 0xA74, kDialogFlags8A, 0, 0x0200, -1 }, - { { 2500.0f, 0.0f, 0.0f }, kDialogRadius, 0xA75, kDialogFlags8A, 0, 0x0100, -1 }, - { { 5000.0f, 0.0f, 0.0f }, kDialogRadius, 0xA76, kDialogFlags8A, 0, 0x0080, -1 }, -}; - -constexpr ProximityDialogPage kPages3C[] = { - { { -140.0f, 100.0f, -30.0f }, kDialogRadius, 0xA83, kDialogFlags8A, 1, 0x0080, -1 }, -}; - -constexpr ProximityDialogPage kPages72[] = { - { { 315.0f, 95.0f, -2085.0f }, 200.0f, 0xA7C, kDialogFlags8A, 1, 0x0200, -1 }, -}; - -constexpr ProximityDialogPage kPages28[] = { - { { 280.0f, 0.0f, -230.0f }, - kDialogRadius, - 0xA12, - kDialogFlags8A, - 0, - 0x0000, - MUMBOTOKEN_11_CC_ABOVE_LEVEL_ENTRANCE }, -}; - -// Gameplay proximity dialogs -constexpr f32 kDialog15Pos[3] = { -568.0f, 128.0f, -180.0f }; -constexpr ProximityDialogPage kPages15[] = { - { { -200.0f, 130.0f, -100.0f }, 220.0f, 0xA82, kDialogFlags8A, 1, 0x0100, -1, kDialog15Pos }, -}; - -constexpr ProximityDialogPage kPages22[] = { - { { -2800.0f, 590.0f, 800.0f }, - 300.0f, - 0xA19, - kDialogFlags8A, - 1, - 0x1000, - -1, - NULL, - JIGGY_8_MM_ORANGE_PADS, - -1, - -1 }, - { { -180.0f, 235.0f, 370.0f }, 700.0f, 0xA1B, kDialogFlags82, 1, 0x0800, -1, NULL, JIGGY_5_MM_HUTS, 0, 0 }, -}; - -constexpr f32 kDialog1BPos[3] = { -15.0f, 798.0f, -360.0f }; -constexpr ProximityDialogPage kPages1B[] = { - { { 0.0f, 720.0f, -360.0f }, - 270.0f, - 0xA13, - kDialogFlagsA, - 1, - 0x8000, - -1, - kDialog1BPos, - -1, - -1, - FILEPROG_38_RBB_OPEN }, - { { 0.0f, 720.0f, -360.0f }, - 270.0f, - 0xA7D, - kDialogFlagsA, - 1, - 0x4000, - -1, - kDialog1BPos, - -1, - FILEPROG_38_RBB_OPEN, - -1 }, -}; - -constexpr ProximityDialogPage kPages29[] = { - { { 230.0f, 660.0f, 100.0f }, 200.0f, 0xA1C, kDialogFlags82, 1, 0x2000, -1, NULL }, -}; - -static bool GruntchDialogGate15() { - if (jiggyscore_isCollected(JIGGY_34_LAIR_MM_WITCH_SWITCH) || - !fileProgressFlag_get(FILEPROG_18_MM_WITCH_SWITCH_JIGGY_PRESSED)) { - return false; - } - fileProgressFlag_set(FILEPROG_88_TRIED_LOGGO_AS_BEAR, 1); - return true; -} - -static bool GruntchDialogGate1B() { - if (ProximityDialogs_IsShown(1, 0xC000) && player_isStable()) { - f32 reArm[3] = { 0.0f, 720.0f, -360.0f }; - if (ml_vec3f_distance(reArm, D_8037C5B0) < 170.0f && D_80281138[0].face_button[1] == 1) { - ProximityDialogs_ClearShown(1, 0xC000); - } - } - return true; -} - -// Storybook pages -constexpr ProximityDialogMap kGruntchStorybookPages[] = { - { MAP_37_RBB_CONTAINER_1, kPages37, ARRAY_COUNT(kPages37), nullptr }, - { MAP_38_RBB_CONTAINER_3, kPages38, ARRAY_COUNT(kPages38), nullptr }, - { MAP_3E_RBB_CONTAINER_2, kPages3E, ARRAY_COUNT(kPages3E), nullptr }, -}; - -// Map the player warps to when resuming save -constexpr StorybookConfig kGruntchStorybook = { - kGruntchStorybookPages, - ARRAY_COUNT(kGruntchStorybookPages), - 0x2802, - MUMBOTOKEN_12_CC_TUNNEL_RIGHT_OF_CLANKER, -}; - -// Gameplay dialogs -constexpr ProximityDialogMap kGruntchGameplayDialogs[] = { - { MAP_3C_RBB_KITCHEN, kPages3C, ARRAY_COUNT(kPages3C), nullptr }, - { MAP_28_MMM_EGG_ROOM, kPages28, ARRAY_COUNT(kPages28), nullptr }, - { MAP_72_GL_BGS_LOBBY, kPages72, ARRAY_COUNT(kPages72), nullptr }, - { MAP_15_GV_WATER_PYRAMID, kPages15, ARRAY_COUNT(kPages15), GruntchDialogGate15 }, - { MAP_1B_MMM_MAD_MONSTER_MANSION, kPages1B, ARRAY_COUNT(kPages1B), GruntchDialogGate1B }, - { MAP_22_CC_INSIDE_CLANKER, kPages22, ARRAY_COUNT(kPages22), nullptr }, - { MAP_29_MMM_NOTE_ROOM, kPages29, ARRAY_COUNT(kPages29), nullptr }, -}; - -// ---------------------------------------------------------- Conditional actors -static bool sConditionalActorsEnabled = false; - -extern "C" void romhack_RewriteActorSpawn(void* actorInfo, u32* flags) { - if (!sConditionalActorsEnabled || actorInfo == NULL || flags == NULL) { - return; - } - ActorInfo* info = (ActorInfo*)actorInfo; - switch (info->actorId) { - case 0x131: - *flags = (*flags & ~0x02u) | 0x40u; - break; - case 0xF: - case 0xF1: - case ACTOR_340_XMAS_TREE_ICE: - *flags |= 0x400u; - info->draw_distance = 0x8000; - break; - default: - break; - } -} - -// Draw the Giant Christmas Tree only if it's been "purchased" -static void Gruntch_EnableConditionalActors() { - sConditionalActorsEnabled = true; - COND_VB_SHOULD(VB_XMAS_TREE_ICE_UPDATE, EVENT_PRIORITY_NORMAL, sConditionalActorsEnabled, { - Actor* self = va_arg(args, Actor*); - if (gsworld_getMap() == MAP_1B_MMM_MAD_MONSTER_MANSION && self != NULL && self->marker != NULL && - self->marker->propPtr != NULL) { - bool open = fileProgressFlag_get(FILEPROG_38_RBB_OPEN) != 0; - self->marker->propPtr->unk8_3 = open; - self->unk38_31 = !open; - *should = false; - } - }); - - // Force Boggy to be visible - COND_VB_SHOULD(VB_BOGGY_HOME_VISIBLE, EVENT_PRIORITY_NORMAL, sConditionalActorsEnabled, { *should = true; }); -} - -// --------------------------------------------------------------- Mumbo reward -namespace { -constexpr f32 kJiggyDelay = 4.15f; -constexpr f32 kStateDelay = 3.85f; -constexpr f32 kStateValue = 1.1f; -constexpr f32 kCameraReleaseDelay = 0.5f; -constexpr s32 kRewardJiggy = 3; -constexpr s32 kCameraMotor = 1; -constexpr s32 kLeaveHutText = 0xA7E; -constexpr s32 kLeaveHutFlags = 0x02; - -f32 sJiggyPos[3] = { 0.0f, 500.0f, -95.0f }; -f32 sMumboState = 0.0f; -bool sMumboRewardEnabled = false; -bool sLeaveHutPending = false; - -void MumboReward_spawnJiggy() { - jiggy_spawn((enum jiggy_e)kRewardJiggy, sJiggyPos); - func_802BB3DC(kCameraMotor, 3.0f, 1.0f); - timedFunc_set_1(kCameraReleaseDelay, (GenFunction_1)func_802BB41C, kCameraMotor); -} - -void MumboReward_setState() { - sMumboState = kStateValue; -} -} // namespace - -extern "C" s32 romhack_mumboTransform(s32 transformId) { - if (!sMumboRewardEnabled || gsworld_getMap() != MAP_48_FP_MUMBOS_SKULL) { - return player_transform((enum transformation_e)transformId); - } - timedFunc_set_0(kJiggyDelay, MumboReward_spawnJiggy); - timedFunc_set_0(kStateDelay, MumboReward_setState); - sLeaveHutPending = true; - return 1; -} - -extern "C" s32 romhack_mumboWishwashyId(void) { - return sMumboRewardEnabled ? 9 : TRANSFORM_7_WISHWASHY; -} - -extern "C" s32 romhack_mumboRandomEventsAllowed(void) { - return sMumboRewardEnabled ? 0 : 1; -} - -// Mumbo's reward shows a static camera -namespace { -constexpr f32 kPanPosition[3] = { -250.0f, 194.0f, 147.0f }; -constexpr f32 kPanRotation[3] = { 35.0f, 315.0f, 0.0f }; - -bool sPanSaved = false; -f32 sPanSavedPosition[3]; -f32 sPanSavedRotation[3]; - -void MumboReward_updatePendingDialog() { - if (!sLeaveHutPending) { - return; - } - const s32 state = bs_getState(); - if (state == BS_74_UNKNOWN || state == BS_20_LANDING || state == BS_44_JIG_JIGGY) { - return; - } - gcdialog_showDialog(kLeaveHutText, kLeaveHutFlags, NULL, NULL, NULL, NULL); - sLeaveHutPending = false; -} - -void MumboReward_updateCamera() { - if (!sMumboRewardEnabled) { - return; - } - MumboReward_updatePendingDialog(); - if (sMumboState > 0.0f) { - if (!sPanSaved) { - sPanSaved = true; - for (int i = 0; i < 3; i++) { - sPanSavedPosition[i] = cameraPosition[i]; - sPanSavedRotation[i] = cameraRotation[i]; - } - } - for (int i = 0; i < 3; i++) { - cameraPosition[i] = kPanPosition[i]; - cameraRotation[i] = kPanRotation[i]; - D_8037D948[i] = kPanPosition[i]; - D_8037D9C8[i] = 0.0f; - D_8037D9E0[i] = 0.0f; - } - D_8037D9D4 = 0.0f; - D_8037D9D8 = 0.0f; - D_8037D9EC = 0.0f; - D_8037D9F0 = 0.0f; - - sMumboState -= time_getDelta(); - if (sMumboState == 0.0f) { - sMumboState = -1.0f; // sentinel: expired, restore next frame - } - } else if (sMumboState < 0.0f && sPanSaved) { - for (int i = 0; i < 3; i++) { - cameraPosition[i] = sPanSavedPosition[i]; - cameraRotation[i] = sPanSavedRotation[i]; - } - sPanSaved = false; - sMumboState = 0.0f; - } -} -} // namespace - -static void Gruntch_EnableMumboReward() { - sMumboRewardEnabled = true; - REGISTER_LISTENER(GameFrameUpdate, EVENT_PRIORITY_NORMAL, [](IEvent*) { MumboReward_updateCamera(); }); -} - -// Game-Over respawns -static void Gruntch_EnableVoidOutRespawn() { - REGISTER_VB_SHOULD(VB_VOID_OUT_RESPAWN_TRANSITION, EVENT_PRIORITY_NORMAL, { - s32 map = va_arg(args, s32); - s32 exit = va_arg(args, s32); - if (D_80383300.level == 1) { - map = MAP_28_MMM_EGG_ROOM; - exit = 2; - } else if (D_80383300.level == 0xA) { - map = MAP_6C_GL_RED_CAULDRON_ROOM; - exit = 5; - } - transitionToMap((enum map_e)map, exit, 1); - *should = false; - }); -} - -// Firing an egg spikes the stealth meter -static void Gruntch_EnableEggNoise() { - REGISTER_VB_SHOULD(VB_EGG_FIRE_SFX, EVENT_PRIORITY_NORMAL, { - s32 slot = va_arg(args, s32); - s32* rate = va_arg(args, s32*); - switch (slot) { - case 0: - StealthNoise_AddBurst(0.3f, 0.2f); - break; - case 1: - StealthNoise_AddBurst(0.65f, 0.3f); - *rate = 0x6D60; - break; - case 2: - StealthNoise_AddBurst(0.65f, 0.4f); - break; - default: - break; - } - (void)should; - }); -} - -// Lair music persists through various maps -constexpr s32 kMusicGroupLair[] = { 0x6A, 0x6C, 0x6F, 0x71, 0x6B, 0x15 }; -constexpr s32 kMusicGroupVillage[] = { 0x1B, 0x22, 0x0C }; - -static bool SameMusicGroup(const s32* group, int count, s32 a, s32 b) { - bool hasA = false, hasB = false; - for (int i = 0; i < count; i++) { - hasA = hasA || group[i] == a; - hasB = hasB || group[i] == b; - } - return hasA && hasB; -} - -// Banjo & Kazooie don't rebound when hitting windows with Rat-A-Tap Rap -static void Gruntch_EnableWindowRapNoRebound() { - REGISTER_VB_SHOULD(VB_BUMP_REBOUNDS_PLAYER, EVENT_PRIORITY_NORMAL, { - ActorMarker* marker = va_arg(args, ActorMarker*); - if (marker != NULL && marker->id == MARKER_107_ENGINE_ROOM_DOOR) { - *should = false; - } - }); -} - -static void Gruntch_EnableWarpMusic() { - REGISTER_VB_SHOULD(VB_WARP_KEEPS_MUSIC, EVENT_PRIORITY_NORMAL, { - const s32 dest = va_arg(args, s32); - const s32 cur = gsworld_getMap(); - if (SameMusicGroup(kMusicGroupVillage, ARRAY_COUNT(kMusicGroupVillage), cur, dest) || - SameMusicGroup(kMusicGroupLair, ARRAY_COUNT(kMusicGroupLair), cur, dest)) { - musicKeepsPlaying(); - } - (void)should; - }); -} - -// ------------------------------------------------------- Jiggy consolidation -constexpr s32 kJiggyToMM[] = { 0x14, 0x20, 0x2E, 0x4A }; -constexpr s32 kJiggyToMMM[] = { 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3E }; - -static bool JiggyMovedFromVanillaLevel(s32 id) { - for (s32 m : kJiggyToMM) { - if (m == id) { - return true; - } - } - for (s32 m : kJiggyToMMM) { - if (m == id) { - return true; - } - } - return false; -} - -// Pause-menu totals layout for Gruntch and Santa's Village -static void Gruntch_EnablePauseTotalsLayout() { - static const s16 kRowY[4] = { 46, 85, -100, 122 }; - static const s8 kScrollStep[4] = { 2, 2, 3, 3 }; - for (int i = 0; i < 4; i++) { - D_8036C520[i].y = kRowY[i]; - D_8036C5F4[i] = kScrollStep[i]; - } -} - -static void Gruntch_EnableJiggyTally() { - REGISTER_VB_SHOULD(VB_JIGGYSCORE_LEVEL_TOTAL, EVENT_PRIORITY_NORMAL, { - s32 lvl = va_arg(args, s32); - s32* result = va_arg(args, s32*); - s32 cnt = 0; - if (lvl >= 1 && lvl <= 0xA) { - for (s32 id = (lvl - 1) * 10 + 1; id <= lvl * 10; id++) { - if (!JiggyMovedFromVanillaLevel(id) && jiggyscore_isCollected((enum jiggy_e)id)) { - cnt++; - } - } - if (lvl == 1) { - for (s32 id : kJiggyToMM) { - if (jiggyscore_isCollected((enum jiggy_e)id)) { - cnt++; - } - } - } else if (lvl == 0xA) { - for (s32 id : kJiggyToMMM) { - if (jiggyscore_isCollected((enum jiggy_e)id)) { - cnt++; - } - } - } - } - *result = cnt; - *should = false; - }); - - // Hide Mt Grumpit's notes and jiggies - REGISTER_VB_SHOULD(VB_PAUSEMENU_ROW_VISIBLE, EVENT_PRIORITY_NORMAL, { - s32 lvl = va_arg(args, s32); - s32 row = va_arg(args, s32); - if (lvl == LEVEL_2_TREASURE_TROVE_COVE) { - *should = (row != 0 && row != 1); - } - }); -} - -// The second act stays locked until the RBB level-open flag is set -static void Gruntch_EnableActGate() { - REGISTER_VB_SHOULD(VB_WARP_DISPATCH, EVENT_PRIORITY_NORMAL, { - if (va_arg(args, int) == 0xAA && !fileProgressFlag_get(FILEPROG_38_RBB_OPEN)) { - *should = false; - } - }); -} - -// ------------------------------------------------------------ Stealth section -extern "C" void warp_rbbExitBoomBoxContainer(NodeProp*, ActorMarker*); - -constexpr s32 kWarpRbbExitBoomBoxContainer = 182; - -constexpr StealthNoiseConfig kGruntchStealth = { - MAP_3C_RBB_KITCHEN, -500.0f, 3600.0f, 0.0f, 3100.0f, 0xA7B, kWarpRbbExitBoomBoxContainer, - warp_rbbExitBoomBoxContainer, 0x13, -}; - -// ------------------------------------------------------- Patch registration -void RegisterGruntchPatches() { - TooieJiggyDance_ForceEnable(); - Storybook_Enable(kGruntchStorybook); - ProximityDialogs_Enable(kGruntchGameplayDialogs); - StealthNoise_Enable(kGruntchStealth); - Gruntch_EnableActGate(); - Gruntch_EnableConditionalActors(); - Gruntch_EnableMumboReward(); - Gruntch_EnableVoidOutRespawn(); - Gruntch_EnableEggNoise(); - Gruntch_EnableWarpMusic(); - Gruntch_EnableWindowRapNoRebound(); - Gruntch_EnablePauseTotalsLayout(); - Gruntch_EnableJiggyTally(); - HackShared_EnableDialogSuppression(kGruntchSuppressedDialogs); - HackShared_EnableForceAbilitiesUsed(kAllUsedAbilities); -} diff --git a/src/port/Save/SaveConverter.cpp b/src/port/Save/SaveConverter.cpp index 6860a878a..116ab6077 100644 --- a/src/port/Save/SaveConverter.cpp +++ b/src/port/Save/SaveConverter.cpp @@ -6,7 +6,7 @@ #include #include -#include "port/FilePicker.h" +#include "portable-file-dialogs.h" #include #include #include @@ -227,44 +227,23 @@ Result ExportToRecompBin(const std::string& dstPath, int slot) { return res; } -void PickAndImport(int slot, std::function onComplete) { - // We can't predict the file extension a save will come in, and we already validate later in the - // chain, so trust the user to pick the correct file. - Ship::FileBrowserRequest req; - req.Title = "Select a save to import"; - req.Filters = { { "All Files", { "*" } } }; - Lighthouse::PickFile(std::move(req), [slot, onComplete](std::optional path) { - if (!path) { - if (onComplete) { - onComplete({}); // cancelled - } - return; - } - Result r = ImportFromRawEeprom(path->string(), slot); - if (onComplete) { - onComplete(r); - } - }); +Result PickAndImport(int slot) { + // We can't predict the file extension a save will come in, and we already validate later in the chain + // Trust the user to pick the correct file + auto selection = pfd::open_file("Select a save to import", ".", { "All Files", "*" }).result(); + if (selection.empty()) { + return {}; + } + return ImportFromRawEeprom(selection[0], slot); } -void PickAndExport(int slot, std::function onComplete) { - Ship::FileBrowserRequest req; - req.Title = "Export save"; - req.Save = true; - req.DefaultName = "bk.n64.us.1.0.bin"; - req.Filters = { { "Save files (*.bin)", { "*.bin" } }, { "All Files", { "*" } } }; - Lighthouse::PickFile(std::move(req), [slot, onComplete](std::optional path) { - if (!path) { - if (onComplete) { - onComplete({}); // cancelled - } - return; - } - Result r = ExportToRecompBin(path->string(), slot); - if (onComplete) { - onComplete(r); - } - }); +Result PickAndExport(int slot) { + auto dest = pfd::save_file("Export save", "bk.n64.us.1.0.bin", { "Save files (*.bin)", "*.bin", "All Files", "*" }) + .result(); + if (dest.empty()) { + return {}; + } + return ExportToRecompBin(dest, slot); } } // namespace SaveConverter diff --git a/src/port/Save/SaveConverter.h b/src/port/Save/SaveConverter.h index e51b78d7e..073458320 100644 --- a/src/port/Save/SaveConverter.h +++ b/src/port/Save/SaveConverter.h @@ -1,7 +1,6 @@ #ifndef SAVE_CONVERTER_H #define SAVE_CONVERTER_H -#include #include namespace SaveConverter { @@ -16,11 +15,8 @@ struct Result { Result ImportFromRawEeprom(const std::string& srcPath, int slot = kSlotAll); Result ExportToRecompBin(const std::string& dstPath, int slot = kSlotAll); - -// Open the file picker, then import/export on the chosen path. onComplete runs when done; an empty -// Result.message means the user cancelled. -void PickAndImport(int slot, std::function onComplete); -void PickAndExport(int slot, std::function onComplete); +Result PickAndImport(int slot = kSlotAll); +Result PickAndExport(int slot = kSlotAll); } // namespace SaveConverter diff --git a/src/port/Save/SaveManager.cpp b/src/port/Save/SaveManager.cpp index 219c2cf69..9adfc1394 100644 --- a/src/port/Save/SaveManager.cpp +++ b/src/port/Save/SaveManager.cpp @@ -16,13 +16,13 @@ #include "Types.h" #include "port/Rando/Logic/Logic.h" -#include "port/Romhack/RomhackConfig.h" extern "C" { #include "core1/sns.h" extern SaveData gameFile_saveData[4]; -extern s8 gameFile_GameIdToFileIdMap[4]; +void savedata_update_crc(void* buffer, s32 size); +s32 item_getCount(enum item_e item); extern u8 gCompletedBottlesBonusGames[7]; } @@ -73,75 +73,10 @@ static void BitfieldSetNBits(uint8_t* array, int startIndex, int numBits, int va } } -struct ResolvedFlag { - int index; - int width; - int puzzle; -}; - -static int PuzzleIndexForFlag(const FlagDef& f) { - static const char* const kPuzzleFlagNames[] = { - "MM_PUZZLE_PIECES_PLACED", - "TTC_PUZZLE_PIECES_PLACED", - "CC_PUZZLE_PIECES_PLACED", - "BGS_PUZZLE_PIECES_PLACED", - "FP_PUZZLE_PIECES_PLACED", - "GV_PUZZLE_PIECES_PLACED", - "MMM_PUZZLE_PIECES_PLACED", - "RBB_PUZZLE_PIECES_PLACED", - "CCW_PUZZLE_PIECES_PLACED", - "DOG_PUZZLE_PIECES_PLACED", - "DOUBLE_HEALTH_PUZZLE_PIECES_PLACED", - }; - if (f.name != nullptr) { - for (int i = 0; i < 11; i++) { - if (strcmp(f.name, kPuzzleFlagNames[i]) == 0) { - return i; - } - } - } - return -1; -} - -static ResolvedFlag ResolveFlag(const FlagDef& f) { - const int puzzle = PuzzleIndexForFlag(f); - if (puzzle < 0) { - return { f.bitIndex, f.bitWidth, -1 }; - } - - const int index = port_getRomhackJiggyPuzzleFlag(puzzle); - const int width = port_getRomhackJiggyPuzzleSize(puzzle); - if (index < 0 || width < 0) { - return { f.bitIndex, f.bitWidth, puzzle }; // no override, vanilla placement - } - // A malformed override would put the counter on top of unrelated progress flags. - // The vanilla counters tile 0x5D-0x81 exactly, and 0x82 is the next flag along. - if (width == 0 || index < 0x5D || index + width - 1 > 0x81) { - SPDLOG_WARN("[SaveManager] {} declares an out-of-range puzzle layout (offset {:#x}, {} bits); " - "falling back to the vanilla placement", - f.name, index, width); - return { f.bitIndex, f.bitWidth, puzzle }; - } - return { index, width, puzzle }; -} - -// A picture's cost can shrink when a romhack ships a revised aGameConfig, which leaves an -// existing save reporting more pieces placed than the picture now has slots. The podium -// picks its occupied slots by rejection sampling, which never terminates once every slot -// is taken, so pin the counter to what the current table can represent on the way in. -static uint32_t ClampPuzzleCount(int puzzle, uint32_t value, const char* name) { - const int cost = _puzzleCost(puzzle); - if (cost >= 0 && value > static_cast(cost)) { - SPDLOG_WARN("[SaveManager] {} is {} but the picture only has {} slots; clamping", name, value, cost); - return static_cast(cost); - } - return value; -} - void RandoSaveCheck_to_json(nlohmann::json& j, const RandoSaveCheck& randoSaveCheck) { j = nlohmann::json::array({ randoSaveCheck.randoCheckId, randoSaveCheck.randoItemId, - randoSaveCheck.randoCollectionId, randoSaveCheck.isShuffled, randoSaveCheck.eligible, - randoSaveCheck.received, randoSaveCheck.skipped }); + randoSaveCheck.randoCollectionId, randoSaveCheck.isShuffled, randoSaveCheck.obtained, + randoSaveCheck.skipped }); } RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& randoSaveCheck) { @@ -149,9 +84,8 @@ RandoSaveCheck RandoSaveCheck_from_json(const nlohmann::json& j, RandoSaveCheck& j.at(1).get_to(randoSaveCheck.randoItemId); j.at(2).get_to(randoSaveCheck.randoCollectionId); j.at(3).get_to(randoSaveCheck.isShuffled); - j.at(4).get_to(randoSaveCheck.eligible); - j.at(5).get_to(randoSaveCheck.received); - j.at(6).get_to(randoSaveCheck.skipped); + j.at(4).get_to(randoSaveCheck.obtained); + j.at(5).get_to(randoSaveCheck.skipped); return randoSaveCheck; } @@ -227,11 +161,10 @@ ordered_json Convert_SaveDataToJSON(SaveData* saveData, int32_t fileNum) { if (f.world != nullptr) { continue; } - const ResolvedFlag r = ResolveFlag(f); - if (r.width == 1) { - general[f.name] = BitfieldGetBit(progressFlags, r.index); + if (f.bitWidth == 1) { + general[f.name] = BitfieldGetBit(progressFlags, f.bitIndex); } else { - general[f.name] = BitfieldGetNBits(progressFlags, r.index, r.width); + general[f.name] = BitfieldGetNBits(progressFlags, f.bitIndex, f.bitWidth); } } j["progress"] = general; @@ -243,11 +176,10 @@ ordered_json Convert_SaveDataToJSON(SaveData* saveData, int32_t fileNum) { if (f.world == nullptr || strcmp(f.world, "CHEATS") != 0) { continue; } - const ResolvedFlag r = ResolveFlag(f); - if (r.width == 1) { - cheats[f.name] = BitfieldGetBit(progressFlags, r.index); + if (f.bitWidth == 1) { + cheats[f.name] = BitfieldGetBit(progressFlags, f.bitIndex); } else { - cheats[f.name] = BitfieldGetNBits(progressFlags, r.index, r.width); + cheats[f.name] = BitfieldGetNBits(progressFlags, f.bitIndex, f.bitWidth); } } j["cheats"] = cheats; @@ -332,11 +264,10 @@ ordered_json Convert_SaveDataToJSON(SaveData* saveData, int32_t fileNum) { if (f.world == nullptr || strcmp(f.world, wd.name) != 0) { continue; } - const ResolvedFlag r = ResolveFlag(f); - if (r.width == 1) { - worldProgress[f.name] = BitfieldGetBit(progressFlags, r.index); + if (f.bitWidth == 1) { + worldProgress[f.name] = BitfieldGetBit(progressFlags, f.bitIndex); } else { - worldProgress[f.name] = BitfieldGetNBits(progressFlags, r.index, r.width); + worldProgress[f.name] = BitfieldGetNBits(progressFlags, f.bitIndex, f.bitWidth); } } if (!worldProgress.empty()) { @@ -487,15 +418,11 @@ SaveData* Convert_JSONToSaveData(int32_t fileNum) { if (generalProgress.contains(f.name)) { uint32_t value = generalProgress[f.name].get(); - const ResolvedFlag r = ResolveFlag(f); - if (r.puzzle >= 0) { - value = ClampPuzzleCount(r.puzzle, value, f.name); - } - if (r.width == 1) { - BitfieldSetBit(progressFlags, r.index, value != 0); + if (f.bitWidth == 1) { + BitfieldSetBit(progressFlags, f.bitIndex, value != 0); } else { - BitfieldSetNBits(progressFlags, r.index, r.width, value); + BitfieldSetNBits(progressFlags, f.bitIndex, f.bitWidth, value); } } } @@ -512,14 +439,13 @@ SaveData* Convert_JSONToSaveData(int32_t fileNum) { if (cheats.contains(f.name)) { uint32_t value = cheats[f.name].get(); - const ResolvedFlag r = ResolveFlag(f); - if (r.width == 1) { + if (f.bitWidth == 1) { // Set single bit (0 or 1) - BitfieldSetBit(progressFlags, r.index, value != 0); + BitfieldSetBit(progressFlags, f.bitIndex, value != 0); } else { // Set multiple bits for specific cheat values - BitfieldSetNBits(progressFlags, r.index, r.width, value); + BitfieldSetNBits(progressFlags, f.bitIndex, f.bitWidth, value); } } } @@ -607,14 +533,10 @@ SaveData* Convert_JSONToSaveData(int32_t fileNum) { if (f.world != nullptr && strcmp(f.world, wd.name) == 0) { if (src.contains(f.name)) { uint32_t val = src[f.name].get(); - const ResolvedFlag r = ResolveFlag(f); - if (r.puzzle >= 0) { - val = ClampPuzzleCount(r.puzzle, val, f.name); - } - if (r.width == 1) - BitfieldSetBit(progressFlags, r.index, val != 0); + if (f.bitWidth == 1) + BitfieldSetBit(progressFlags, f.bitIndex, val != 0); else - BitfieldSetNBits(progressFlags, r.index, r.width, val); + BitfieldSetNBits(progressFlags, f.bitIndex, f.bitWidth, val); } } } @@ -744,34 +666,6 @@ static void LoadGlobalData() { } } -static bool WriteFileAtomically(const std::filesystem::path& path, const std::string& contents) { - const std::filesystem::path tempPath = path.parent_path() / (path.filename().string() + ".tmp"); - std::error_code ec; - { - std::ofstream ofs(tempPath, std::ios::binary | std::ios::trunc); - if (!ofs.is_open()) { - SPDLOG_ERROR("SaveManager: failed to open \"{}\" for writing", tempPath.string()); - return false; - } - ofs << contents; - ofs.flush(); - if (!ofs.good()) { - SPDLOG_ERROR("SaveManager: failed writing \"{}\"; leaving the existing file alone", tempPath.string()); - ofs.close(); - std::filesystem::remove(tempPath, ec); - return false; - } - } - std::filesystem::rename(tempPath, path, ec); - if (ec) { - SPDLOG_ERROR("SaveManager: failed to replace \"{}\": {}", path.string(), ec.message()); - std::error_code removeEc; - std::filesystem::remove(tempPath, removeEc); - return false; - } - return true; -} - static void SaveGlobalData() { ordered_json j = ordered_json::object(); @@ -793,7 +687,13 @@ static void SaveGlobalData() { j["bottlesBonusCompleted"] = bb; std::string globalPath = SaveManager_GetSavePath("global.json"); - WriteFileAtomically(globalPath, CollapsedJSONArray(j)); + std::ofstream ofs(globalPath); + if (ofs.is_open()) { + ofs << CollapsedJSONArray(j); + ofs.close(); + } else { + SPDLOG_ERROR("SaveManager: failed to open global save file \"{}\" for writing", globalPath); + } } void SaveManager_MoveInvalidSaveFile(const std::filesystem::path& fileName, const std::string& message) { @@ -848,44 +748,26 @@ void SaveManager_Init() { REGISTER_LISTENER(OnSaveFileSave, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnSaveFileSave* ev = (OnSaveFileSave*)event; - std::string fileName = createFileName(ev->fileNum); - std::string filePath = SaveManager_GetSavePath(fileName); - - if (((SaveData*)ev->saveBuffer)->magic == 0) { - std::error_code ec; - fs::remove(filePath, ec); - if (ec) { - SPDLOG_ERROR("SaveManager: failed to remove erased save file \"{}\": {}", filePath, ec.message()); - } - SaveGlobalData(); - event->Cancelled = true; - return; - } - ordered_json saveFile = Convert_SaveDataToJSON((SaveData*)ev->saveBuffer, ev->fileNum); if (!saveFile.empty()) { - WriteFileAtomically(filePath, CollapsedJSONArray(saveFile)); + std::string collapsedString = CollapsedJSONArray(saveFile); + + std::string fileName = createFileName(ev->fileNum); + std::string filePath = SaveManager_GetSavePath(fileName); + + std::ofstream outputFile(filePath); + if (outputFile.is_open()) { + outputFile << collapsedString; + outputFile.close(); + } else { + SPDLOG_ERROR("SaveManager: failed to open save file \"{}\" for writing", filePath); + } } SaveGlobalData(); event->Cancelled = true; }); - REGISTER_LISTENER(OnGameErase, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnGameErase* ev = (OnGameErase*)event; - std::string fileName = createFileName(ev->gameNum); - std::error_code ec; - if (fs::remove(SaveManager_GetSavePath(fileName), ec)) { - SPDLOG_INFO("SaveManager: deleted erased save file \"{}\"", fileName); - } else if (ec) { - SPDLOG_ERROR("SaveManager: failed to delete erased save file \"{}\": {}", fileName, ec.message()); - } - // Drop retention data too. - if (ev->gameNum >= 0 && ev->gameNum < 4) { - gameFile_saveData[gameFile_GameIdToFileIdMap[ev->gameNum]].shipSaveData = {}; - } - }); - REGISTER_LISTENER(OnSaveClear, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnSaveClear* ev = (OnSaveClear*)event; SaveData* saveData = (SaveData*)ev->result; @@ -904,11 +786,6 @@ void SaveManager_Init() { event->Cancelled = true; }); - REGISTER_LISTENER(OnGameFileErase, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnGameFileErase* ev = (OnGameFileErase*)event; - gameFile_8033CFD4(ev->gamenum); - }); - REGISTER_LISTENER(OnGameLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnGameLoad* ev = (OnGameLoad*)event; gSelectedFileNum = ev->fileNum; diff --git a/src/port/Save/Types.h b/src/port/Save/Types.h index d5bede421..49a1aa2f9 100644 --- a/src/port/Save/Types.h +++ b/src/port/Save/Types.h @@ -417,9 +417,6 @@ static constexpr int kSnsItemCount = sizeof(kSnsUnlocked) / sizeof(kSnsUnlocked[ // so internal gamenum 0/1/2 corresponds to displayed Game 1/3/2. static int SlotToFileIndex(int gameNum) { static const int fileMap[3] = { 1, 3, 2 }; - if (gameNum < 0 || gameNum >= 3) { - return 0; - } return fileMap[gameNum]; } diff --git a/src/port/ShipUtils.cpp b/src/port/ShipUtils.cpp index 8381950f8..087f900dd 100644 --- a/src/port/ShipUtils.cpp +++ b/src/port/ShipUtils.cpp @@ -10,7 +10,6 @@ #include #include #include "UI/cvar_prefixes.h" -#include "UI/enhancementTypes.h" #include "fast/Fast3dGui.h" #ifdef _WIN32 #include @@ -62,7 +61,7 @@ extern uint32_t Ship_Hash(std::string str) { return hval; } -extern std::string port_FormatTimeDisplay(uint64_t value) { +extern std::string port_FormatTimeDisplay(uint32_t value) { uint32_t sec = value / 10; uint32_t hh = sec / 3600; uint32_t mm = (sec - hh * 3600) / 60; @@ -75,6 +74,7 @@ extern "C" { #include "enums.h" // game_mode_e // Furnace Fun active flag +s32 volatileFlag_get(s32); s32 getGameMode(void); int gPortResetPending = 0; @@ -95,6 +95,10 @@ bool Ship_IsCStringEmpty(const char* str) { return str == NULL || str[0] == '\0'; } +void port_audioStartThread(void) { + GameEngine::AudioStartThread(); +} + int port_checkHeap(const char* label) { #if defined(_DEBUG) && defined(_MSC_VER) if (!_CrtCheckMemory()) { @@ -292,8 +296,8 @@ int port_getBootSequence(void) { // Romhacks always boot to file select; their intros aren't compatible with the // vanilla cutscene/demo path. if (port_isRomhack()) - return BOOTSEQUENCE_FILESELECT; - return CVarGetInteger(CVAR_SETTING("BootSequence"), BOOTSEQUENCE_DEFAULT); + return 2; // BOOTSEQUENCE_FILESELECT + return CVarGetInteger(CVAR_SETTING("BootSequence"), 0); } float port_getRumbleScale(void) { @@ -319,8 +323,9 @@ float port_getRumbleScale(void) { } // extern "C" std::vector worldOpenFlags = { - FILEPROG_31_MM_OPEN, FILEPROG_32_TTC_OPEN, FILEPROG_33_CC_OPEN, FILEPROG_34_BGS_OPEN, FILEPROG_35_FP_OPEN, - FILEPROG_36_GV_OPEN, FILEPROG_37_MMM_OPEN, FILEPROG_38_RBB_OPEN, FILEPROG_39_CCW_OPEN, + FILEPROG_5D_MM_PUZZLE_PIECES_PLACED, FILEPROG_5E_TTC_PUZZLE_PIECES_PLACED, FILEPROG_60_CC_PUZZLE_PIECES_PLACED, + FILEPROG_63_BGS_PUZZLE_PIECES_PLACED, FILEPROG_66_FP_PUZZLE_PIECES_PLACED, FILEPROG_6A_GV_PUZZLE_PIECES_PLACED, + FILEPROG_6E_MMM_PUZZLE_PIECES_PLACED, FILEPROG_72_RBB_PUZZLE_PIECES_PLACED, FILEPROG_76_CCW_PUZZLE_PIECES_PLACED, }; std::unordered_map levelAbbreviations = { diff --git a/src/port/ShipUtils.h b/src/port/ShipUtils.h index 90766d680..f4a2f2fe3 100644 --- a/src/port/ShipUtils.h +++ b/src/port/ShipUtils.h @@ -20,7 +20,7 @@ extern std::vector abilityNameList; void TableCellCenteredText(const char* text); uint32_t Ship_Hash(std::string str); -std::string port_FormatTimeDisplay(uint64_t value); +std::string port_FormatTimeDisplay(uint32_t value); extern "C" { #endif @@ -34,6 +34,9 @@ void BK_LOG_INFO(const char* fmt, ...); void BK_LOG_WARN(const char* fmt, ...); void BK_LOG_ERROR(const char* fmt, ...); +// Start the audio processing thread (called from audioManager_startThread after soundfont patching) +void port_audioStartThread(void); + // Flag: when true, audio spin-waits should force-stop immediately. extern int gPortResetPending; diff --git a/src/port/UI/DeveloperTools/GameplayTools.cpp b/src/port/UI/DeveloperTools/GameplayTools.cpp index 427eedbb0..11f703de2 100644 --- a/src/port/UI/DeveloperTools/GameplayTools.cpp +++ b/src/port/UI/DeveloperTools/GameplayTools.cpp @@ -2,7 +2,6 @@ #include "port/Rando/Rando.h" #include "port/Rando/Logic/Logic.h" #include "port/Rando/CustomObject/CustomObject.h" -#include "port/Rando/CustomCollectible/CustomCollectible.h" #include "port/Enhancements/Events/Hooks/Events.h" #include "port/UI/UIWidgets.hpp" @@ -21,6 +20,23 @@ #include "include/core1/sns.h" extern "C" { +void sns_set_item_state(enum StopNSwop_Item item, s32 set, s32 state); +void jiggy_spawn(enum jiggy_e jiggy_id, f32 pos[3]); +void player_getPosition(f32 dst[3]); +void player_getPosition_s32(s32 arg0[3]); +enum map_e gsworld_getMap(void); +Actor* actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags); +void func_8031D04C(enum map_e arg0, s32 exit_id); + +void item_set(s32 item, s32 val); +void ability_setAllLearned(s32 val); +void ability_setAllUsed(s32 val); + +s32 mapSpecificFlags_get(s32 i); +void mapSpecificFlags_set(s32 i, s32 val); +enum map_e gsworld_getMap(void); +enum level_e map_getLevel(enum map_e map); + typedef struct { enum honeycomb_e uid; s32 unk4; @@ -53,7 +69,6 @@ int32_t selectedSnsItem = SNS_ITEM_EGG_YELLOW; int32_t selectedJiggy = JIGGY_01_MM_JINJO; int32_t selectedHoneycomb = HONEYCOMB_1_MM_HILL; int32_t selectedToken = MUMBOTOKEN_01_MM_STUMP_NEAR_CONGA; -int32_t selectedCustomCollectible = RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1; const char* mapNames[] = { "Mumbo's Mountain", "Treasure Trove Cove", "Clanker's Cavern", "Bubblegloop Swamp", "Freezeezy Peak", @@ -149,17 +164,17 @@ std::vector mapSpecificFlagList = { { TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN, "TTC_SPECIFIC_FLAG_5_CLAM_FIRST_MEET_TEXT_SHOWN", LEVEL_2_TREASURE_TROVE_COVE }, { TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN, "TTC_SPECIFIC_FLAG_7_NIPPER_FIRST_MEET_TEXT_SHOWN", LEVEL_2_TREASURE_TROVE_COVE }, { BGS_SPECIFIC_FLAG_1, "BGS_SPECIFIC_FLAG_1", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET, "BGS_SPECIFIC_FLAG_2_WALKWAY_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_3_WALKWAY_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY, "BGS_SPECIFIC_FLAG_4_WALKWAY_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_5_WALKWAY_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_RESET, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_WALKWAY_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, { BGS_SPECIFIC_FLAG_7, "BGS_SPECIFIC_FLAG_7", LEVEL_4_BUBBLEGLOOP_SWAMP }, { BGS_SPECIFIC_FLAG_8, "BGS_SPECIFIC_FLAG_8", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_9_MAZE_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_MAZE_JIGGY_SWITCH_PRESSED, "BGS_SPECIFIC_FLAG_MAZE_JIGGY_SWITCH_PRESSED", LEVEL_4_BUBBLEGLOOP_SWAMP }, { BGS_SPECIFIC_FLAG_A, "BGS_SPECIFIC_FLAG_A", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET, "BGS_SPECIFIC_FLAG_B_MAZE_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_C_MAZE_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, - { BGS_SPECIFIC_FLAG_D_MAZE_JIGGY, "BGS_SPECIFIC_FLAG_D_MAZE_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_MAZE_JIGGY_RESET, "BGS_SPECIFIC_FLAG_MAZE_JIGGY_RESET", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_MAZE_JIGGY_TIMER_RUNNING, "BGS_SPECIFIC_FLAG_MAZE_JIGGY_TIMER_RUNNING", LEVEL_4_BUBBLEGLOOP_SWAMP }, + { BGS_SPECIFIC_FLAG_MAZE_JIGGY, "BGS_SPECIFIC_FLAG_MAZE_JIGGY", LEVEL_4_BUBBLEGLOOP_SWAMP }, { FP_SPECIFIC_FLAG_0_XMAS_TREE_LIGHTS_ON, "FP_SPECIFIC_FLAG_0_XMAS_TREE_LIGHTS_ON", LEVEL_5_FREEZEEZY_PEAK }, { FP_SPECIFIC_FLAG_1_UNKNOWN, "FP_SPECIFIC_FLAG_1_UNKNOWN", LEVEL_5_FREEZEEZY_PEAK }, { FP_SPECIFIC_FLAG_2_XMAS_TREE_SWITCH, "FP_SPECIFIC_FLAG_2_XMAS_TREE_SWITCH", LEVEL_5_FREEZEEZY_PEAK }, @@ -223,7 +238,7 @@ void GameplayTools_UpdateSnsCheckboxes(StopNSwop_Item selectedSnsId) { } void GameplayTools_SpawnPosition() { - for (int i = 0; i <= 2; i++) { + for (int i = 0; i < 2; i++) { spawnPosition[i] = playerPosition[i] + spawnOffset[i]; } } @@ -405,27 +420,6 @@ void GameplayTools_ObjectSpawner() { ImGui::EndTable(); } - - ImGui::SeparatorText("Custom Collectible Testing"); - if (ImGui::BeginTable("ObjectSpawner", 2, ImGuiTableFlags_SizingStretchSame)) { - ImGui::TableNextColumn(); - if (UIWidgets::Button("Spawn Custom Collectible", { .color = THEME_COLOR })) { - Actor* newActor = CustomCollectible::Spawn(spawnPosition, (RandoCheckId)selectedCustomCollectible); - } - ImGui::TableNextColumn(); - std::string customCollectibleText = std::to_string(selectedCustomCollectible) + ": " + - Rando::StaticData::Checks[(RandoCheckId)selectedCustomCollectible].name; - - UIWidgets::SliderInt("##customCollectibleIndex", &selectedCustomCollectible, - UIWidgets::IntSliderOptions() - .Color(THEME_COLOR) - .Min(RC_UNKNOWN + 1) - .Max(RC_MAX - 1) - .DefaultValue(RC_BGS_BLUE_EGG_BEHIND_ENTRANCE_1) - .Format(customCollectibleText.c_str()) - .LabelPosition(UIWidgets::LabelPositions::None)); - ImGui::EndTable(); - } } void DrawGameplayToolsWarpList() { @@ -476,42 +470,10 @@ void DrawGrantUnlocks() { } } -// Index 0 traces every space; the rest are ANCHOR_FLAGSPACE_* ids offset by one. -static const std::unordered_map flagTraceSpaces = { - { 0, "All" }, { 1, "File Progress" }, { 2, "Volatile" }, { 3, "Level Specific" }, - { 4, "Map Specific" }, { 5, "Rando Inf" }, -}; - -void DrawFlagTracer() { - ImGui::SeparatorText("Flag Tracer"); - ImGui::TextWrapped("Logs every flag write to the console and log file, with the flag's enum name and a marker on " - "each map load."); - - UIWidgets::CVarCheckbox("Trace Flag Writes", CVAR_DEVELOPER_TOOLS("FlagTrace"), - UIWidgets::CheckboxOptions().Color(THEME_COLOR).DefaultValue(false)); - - if (!CVarGetInteger(CVAR_DEVELOPER_TOOLS("FlagTrace"), 0)) { - return; - } - - UIWidgets::CVarCombobox("Flag Space", CVAR_DEVELOPER_TOOLS("FlagTraceSpace"), flagTraceSpaces, - UIWidgets::ComboboxOptions() - .Color(THEME_COLOR) - .Tooltip("Limit tracing to a single flag space.") - .DefaultIndex(0)); - UIWidgets::CVarCheckbox("Include Call Stacks", CVAR_DEVELOPER_TOOLS("FlagTraceStacks"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .DefaultValue(false) - .Tooltip("Name the function and line that set each flag.")); -} - void DrawMonitoringTools() { level_e currentLevel = map_getLevel(gsworld_getMap()); int32_t mapIndex = 0; - DrawFlagTracer(); - ImGui::SeparatorText("Map Specific Flags"); if (ImGui::BeginChild("MapFlagChild")) { if (ImGui::BeginTable("MapFlagTable", 2, ImGuiTableFlags_SizingFixedFit)) { diff --git a/src/port/UI/DeveloperTools/SaveEditor.cpp b/src/port/UI/DeveloperTools/SaveEditor.cpp index 3b079579f..d93c46eba 100644 --- a/src/port/UI/DeveloperTools/SaveEditor.cpp +++ b/src/port/UI/DeveloperTools/SaveEditor.cpp @@ -13,8 +13,10 @@ #include "port/UI/LighthouseGui.hpp" #include "port/UI/cvar_prefixes.h" +extern "C" { #include "enums.h" #include "prop.h" +} #define DEFAULT_MAX_HEALTH 8 #define DEFAULT_MAX_EGGS 100 @@ -25,8 +27,16 @@ #define HONEYCOMB_ID_MULTIPLIER(levelId) (1 + (2 * (levelId - 1))) extern "C" { -bool ability_isUnlocked(enum ability_e uid); +bool player_is_present(void); +s32 item_getCount(enum item_e item); +void item_set(s32 item, s32 val); +bool fileProgressFlag_get(enum file_progress_e index); +void fileProgressFlag_set(enum file_progress_e index, s32 set); +int ability_isUnlocked(enum ability_e uid); +void ability_setLearned(s32 move, s32 val); +u32 jiggyscore_isCollected(enum jiggy_e jiggy_id); void jiggyscore_setCollected(s32 indx, s32 val); +bool honeycombscore_get(enum honeycomb_e indx); void honeycombscore_set(enum honeycomb_e indx, bool val); void mumboscore_set(enum mumbotoken_e indx, bool val); @@ -83,39 +93,39 @@ bool SaveEditor_IsHoneycombCollected(honeycomb_e honeycombId) { } void SaveEditor_UpdateCheckTracker(RandoSaveCheck randoSaveCheck) { - if (randoSaveCheck.eligible) { + if (randoSaveCheck.obtained) { CustomObject::CheckObtainedEX(randoSaveCheck.randoCheckId); } for (auto& pool : Rando::Logic::shuffledPool) { if (pool.randoCheckId == randoSaveCheck.randoCheckId) { pool.isShuffled = randoSaveCheck.isShuffled; - pool.eligible = randoSaveCheck.eligible; + pool.obtained = randoSaveCheck.obtained; pool.skipped = randoSaveCheck.skipped; break; } } - int32_t itemIncr = randoSaveCheck.eligible ? 1 : -1; + int32_t itemIncr = randoSaveCheck.obtained ? 1 : -1; Rando::StaticData::RandoStaticItem randoItem = Rando::StaticData::Items[randoSaveCheck.randoItemId]; switch (randoItem.randoItemType) { case RITYPE_JIGGY: - jiggyscore_setCollected(randoSaveCheck.randoCollectionId, randoSaveCheck.eligible); + jiggyscore_setCollected(randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, itemIncr); break; case RITYPE_EMPTY_HONEYCOMB: - honeycombscore_set((honeycomb_e)randoSaveCheck.randoCollectionId, randoSaveCheck.eligible); + honeycombscore_set((honeycomb_e)randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); break; case RITYPE_MOLEHILL: - if (randoSaveCheck.eligible) { + if (randoSaveCheck.obtained) { ability_unlock((ability_e)randoSaveCheck.randoCollectionId); } else { ability_setLearned((ability_e)randoSaveCheck.randoCollectionId, 0); } break; case RITYPE_MUMBO_TOKEN: - mumboscore_set((mumbotoken_e)randoSaveCheck.randoCollectionId, randoSaveCheck.eligible); + mumboscore_set((mumbotoken_e)randoSaveCheck.randoCollectionId, randoSaveCheck.obtained); item_adjustByDiffWithoutHud(ITEM_1C_MUMBO_TOKEN, itemIncr); break; default: @@ -357,10 +367,6 @@ void SaveEditor_DrawProgressTab() { void DrawRandoFlagEditor() { ImGui::SeparatorText("Rando INF Flags"); - if (selectedFileNum == DEFAULT_FILE_NUM) { - ImGui::Text("No Save File Loaded"); - return; - } if (ImGui::BeginChild("RandoFlagChild")) { for (int f = RANDO_INF_UNKNOWN; f < RANDO_INF_MAX; f++) { ImGui::PushID(f); @@ -375,7 +381,7 @@ void DrawRandoFlagEditor() { } void DrawRandoCheckEditor() { - if (selectedFileNum == DEFAULT_FILE_NUM || Rando::Logic::shuffledPool.empty()) { + if (Rando::Logic::shuffledPool.empty()) { ImGui::Text("No Rando Save Data"); } else { static ImGuiTextFilter rcFilter; @@ -388,10 +394,9 @@ void DrawRandoCheckEditor() { } if (ImGui::BeginChild("RandoToolsChild", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { - if (ImGui::BeginTable("RandoSaveEditorTable", 7)) { + if (ImGui::BeginTable("RandoSaveEditorTable", 6)) { ImGui::TableSetupColumn("shuffled", ImGuiTableColumnFlags_WidthFixed, 34.0f); - ImGui::TableSetupColumn("eligible", ImGuiTableColumnFlags_WidthFixed, 34.0f); - ImGui::TableSetupColumn("received", ImGuiTableColumnFlags_WidthFixed, 34.0f); + ImGui::TableSetupColumn("obtained", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("skipped", ImGuiTableColumnFlags_WidthFixed, 34.0f); ImGui::TableSetupColumn("checkName", ImGuiTableColumnFlags_WidthFixed, (ImGui::GetContentRegionAvail().x - 34.0f) * 0.60f); @@ -401,52 +406,33 @@ void DrawRandoCheckEditor() { ImGui::TableNextColumn(); for (auto& check : RANDO_SAVE_CHECKS) { - auto checkEntry = Rando::StaticData::Checks.find(check.randoCheckId); - if (checkEntry == Rando::StaticData::Checks.end()) { - continue; - } - const char* checkName = checkEntry->second.name; - - auto itemEntry = Rando::StaticData::Items.find(check.randoItemId); - const char* itemName = - (itemEntry != Rando::StaticData::Items.end()) ? itemEntry->second.name : nullptr; - - if (!rcFilter.PassFilter(checkName) && !rcFilter.PassFilter(itemName)) { + if (!rcFilter.PassFilter(check.name) && + !rcFilter.PassFilter(Rando::StaticData::Items[check.randoItemId].name)) { continue; } ImGui::PushID(check.randoCheckId); bool isChanged = false; bool isShuffled = check.isShuffled; - bool eligible = check.eligible; - bool received = check.received; + bool obtained = check.obtained; bool skipped = check.skipped; - std::string checkId = std::to_string((uint32_t)check.randoCheckId); - if (UIWidgets::Checkbox( - ("isShuffled##" + checkId).c_str(), &isShuffled, + "isShuffled", &isShuffled, UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { RANDO_SAVE_CHECKS[check.randoCheckId].isShuffled = !check.isShuffled; isChanged = true; } ImGui::TableNextColumn(); if (UIWidgets::Checkbox( - ("eligible##" + checkId).c_str(), &eligible, - UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { - RANDO_SAVE_CHECKS[check.randoCheckId].eligible = !check.eligible; - isChanged = true; - } - ImGui::TableNextColumn(); - if (UIWidgets::Checkbox( - ("received##" + checkId).c_str(), &received, + "obtained", &obtained, UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { - RANDO_SAVE_CHECKS[check.randoCheckId].received = !check.received; + RANDO_SAVE_CHECKS[check.randoCheckId].obtained = !check.obtained; isChanged = true; } ImGui::TableNextColumn(); if (UIWidgets::Checkbox( - ("skipped##" + checkId).c_str(), &skipped, + "skipped", &skipped, UIWidgets::CheckboxOptions().LabelPosition(UIWidgets::LabelPositions::None))) { RANDO_SAVE_CHECKS[check.randoCheckId].skipped = !check.skipped; isChanged = true; @@ -457,7 +443,8 @@ void DrawRandoCheckEditor() { } ImGui::TableNextColumn(); - ImGui::TextWrapped("%s", checkName); + std::string checkName = Rando::StaticData::Checks[check.randoCheckId].name; + ImGui::TextWrapped(checkName.c_str()); ImGui::TableNextColumn(); ImGui::TextWrapped(Rando::StaticData::Items[check.randoItemId].name); diff --git a/src/port/UI/InputViewer.cpp b/src/port/UI/InputViewer.cpp index 3920b287c..692de976c 100644 --- a/src/port/UI/InputViewer.cpp +++ b/src/port/UI/InputViewer.cpp @@ -73,335 +73,339 @@ void InputViewer::Draw() { } void InputViewer::DrawElement() { - static bool sButtonTexturesLoaded = false; - if (!sButtonTexturesLoaded) { - GetFast3dGui()->LoadTextureFromRawImage("Input-Viewer-Background", - "textures/buttons/InputViewerBackground.png"); - GetFast3dGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/StartBtn.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); - GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick", "textures/buttons/AnalogStick.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/DPadLeft.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/DPadRight.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); - GetFast3dGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); - GetFast3dGui()->LoadTextureFromRawImage("A-Btn Outline", "textures/buttons/ABtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("B-Btn Outline", "textures/buttons/BBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("L-Btn Outline", "textures/buttons/LBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("R-Btn Outline", "textures/buttons/RBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Z-Btn Outline", "textures/buttons/ZBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Start-Btn Outline", "textures/buttons/StartBtnOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Left Outline", "textures/buttons/CLeftOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Right Outline", "textures/buttons/CRightOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Up Outline", "textures/buttons/CUpOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("C-Down Outline", "textures/buttons/CDownOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right Outline", "textures/buttons/DPadRightOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up Outline", "textures/buttons/DPadUpOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-1 Outline", "textures/buttons/Mod1Outline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Modifier-2 Outline", "textures/buttons/Mod2Outline.png"); - GetFast3dGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); - sButtonTexturesLoaded = true; - } + if (CVarGetInteger(CVAR_WINDOW("InputViewer"), 0)) { + static bool sButtonTexturesLoaded = false; + if (!sButtonTexturesLoaded) { + GetFast3dGui()->LoadTextureFromRawImage("Input-Viewer-Background", + "textures/buttons/InputViewerBackground.png"); + GetFast3dGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/StartBtn.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); + GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick", "textures/buttons/AnalogStick.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/DPadLeft.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/DPadRight.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); + GetFast3dGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); + GetFast3dGui()->LoadTextureFromRawImage("A-Btn Outline", "textures/buttons/ABtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("B-Btn Outline", "textures/buttons/BBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("L-Btn Outline", "textures/buttons/LBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("R-Btn Outline", "textures/buttons/RBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Z-Btn Outline", "textures/buttons/ZBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Start-Btn Outline", "textures/buttons/StartBtnOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Left Outline", "textures/buttons/CLeftOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Right Outline", "textures/buttons/CRightOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Up Outline", "textures/buttons/CUpOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("C-Down Outline", "textures/buttons/CDownOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Right Outline", "textures/buttons/DPadRightOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Up Outline", "textures/buttons/DPadUpOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-1 Outline", "textures/buttons/Mod1Outline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Modifier-2 Outline", "textures/buttons/Mod2Outline.png"); + GetFast3dGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); + sButtonTexturesLoaded = true; + } - ImVec2 mainPos = ImGui::GetWindowPos(); - ImVec2 size = ImGui::GetMainViewport()->WorkSize; + ImVec2 mainPos = ImGui::GetWindowPos(); + ImVec2 size = ImGui::GetMainViewport()->WorkSize; #ifdef __WIIU__ - const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.0f; + const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.0f; #else - const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); + const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); #endif - const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); - const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); - const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); - - ImVec2 bgSize = GetFast3dGui()->GetTextureSize("Input-Viewer-Background"); - ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); - - ImGui::SetNextWindowSize( - ImVec2(scaledBGSize.x + 20, scaledBGSize.y + - (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * - CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + - 20)); - ImGui::SetNextWindowContentSize( - ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * - CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); - ImGui::SetNextWindowPos(ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), - ImGuiCond_FirstUseEver); - - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); - - OSContPad* pads = - std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetControlDeck())->GetPads(); - - ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | - ImGuiWindowFlags_NoFocusOnAppearing; - - if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) { - windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; - } + const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); + const int buttonOutlineMode = + CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); + const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); + + ImVec2 bgSize = GetFast3dGui()->GetTextureSize("Input-Viewer-Background"); + ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); + + ImGui::SetNextWindowSize( + ImVec2(scaledBGSize.x + 20, scaledBGSize.y + + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + + 20)); + ImGui::SetNextWindowContentSize( + ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); + ImGui::SetNextWindowPos( + ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), + ImGuiCond_FirstUseEver); + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + + OSContPad* pads = + std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetControlDeck())->GetPads(); + + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoFocusOnAppearing; + + if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) { + windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; + } - if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) { - ImGui::SetCursorPos(ImVec2(10, 10)); - const ImVec2 aPos = ImGui::GetCursorPos(); + if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) { + ImGui::SetCursorPos(ImVec2(10, 10)); + const ImVec2 aPos = ImGui::GetCursorPos(); - if (CVarGetInteger(CVAR_INPUT_VIEWER("ShowBackground"), 1)) { - ImGui::SetNextItemAllowOverlap(); - // Background - ImGui::Image(GetFast3dGui()->GetTextureByName("Input-Viewer-Background"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } + if (CVarGetInteger(CVAR_INPUT_VIEWER("ShowBackground"), 1)) { + ImGui::SetNextItemAllowOverlap(); + // Background + ImGui::Image(GetFast3dGui()->GetTextureByName("Input-Viewer-Background"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } - // A/B - if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // A/B + if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // C buttons - if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // C buttons + if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // L/R/Z - if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // L/R/Z + if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } - // Start - if (CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } + // Start + if (CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, + useGlobalOutlineMode ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), + BUTTON_OUTLINE_NOT_PRESSED)); + } - // Dpad - if (CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, - useGlobalOutlineMode - ? buttonOutlineMode - : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - } - // Lighthouse Unused - // Modifier 1 - // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { - // ImGui::SetNextItemAllowOverlap(); - // ImGui::SetCursorPos(aPos); - // RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize, - // useGlobalOutlineMode - // ? buttonOutlineMode - // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - //} - // Modifier 2 - // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { - // ImGui::SetNextItemAllowOverlap(); - // ImGui::SetCursorPos(aPos); - // RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize, - // useGlobalOutlineMode - // ? buttonOutlineMode - // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); - //} - - const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; - const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y; - - // Analog Stick - const int analogOutlineMode = - CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN); - const int32_t maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12); - if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || - (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick Outline"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } - const int analogStickMode = - CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN); - if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || - (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos( - ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, - aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); - ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } + // Dpad + if (CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + // Lighthouse Unused + // Modifier 1 + // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { + // ImGui::SetNextItemAllowOverlap(); + // ImGui::SetCursorPos(aPos); + // RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize, + // useGlobalOutlineMode + // ? buttonOutlineMode + // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + //} + // Modifier 2 + // if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { + // ImGui::SetNextItemAllowOverlap(); + // ImGui::SetCursorPos(aPos); + // RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize, + // useGlobalOutlineMode + // ? buttonOutlineMode + // : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + //} + + const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; + const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y; + + // Analog Stick + const int analogOutlineMode = + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN); + const int32_t maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12); + if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick Outline"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } + const int analogStickMode = + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN); + if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || + (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(GetFast3dGui()->GetTextureByName("Analog-Stick"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } - // Right Stick - const int32_t maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7); - const int rightOutlineMode = - CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN); - if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || - (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos(aPos); - ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick Outline"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } - const int rightStickMode = - CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN); - if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || - (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { - ImGui::SetNextItemAllowOverlap(); - ImGui::SetCursorPos( - ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, - aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); - ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick"), scaledBGSize, ImVec2(0, 0), - ImVec2(1.0f, 1.0f)); - } + // Right Stick + const int32_t maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7); + const int rightOutlineMode = + CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN); + if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick Outline"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } + const int rightStickMode = + CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN); + if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || + (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(GetFast3dGui()->GetTextureByName("Right-Stick"), scaledBGSize, ImVec2(0, 0), + ImVec2(1.0f, 1.0f)); + } - // Analog stick angle text - if (showAnalogAngles) { - ImGui::SetCursorPos( - ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, - scaledBGSize.y + aPos.y + 10)); - // Scale font with input viewer scale - float oldFontScale = ImGui::GetFont()->Scale; - ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f); - ImGui::PushFont(ImGui::GetFont()); - - // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt - const int32_t rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; - - // ESS range - const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8); - const int range1Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Max"), 27); - // Walking speed range - const int range2Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Min"), 27); - const int range2Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Max"), 62); - - // Push color based on angle ranges - if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && - (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { - ImGui::PushStyleColor(ImGuiCol_Text, - VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), - range1ColorDefault))); - } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) && - (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { - ImGui::PushStyleColor(ImGuiCol_Text, - VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), - range2ColorDefault))); - } else { - ImGui::PushStyleColor( - ImGuiCol_Text, - VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"), textColorDefault))); + // Analog stick angle text + if (showAnalogAngles) { + ImGui::SetCursorPos( + ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, + scaledBGSize.y + aPos.y + 10)); + // Scale font with input viewer scale + float oldFontScale = ImGui::GetFont()->Scale; + ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f); + ImGui::PushFont(ImGui::GetFont()); + + // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt + const int32_t rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; + + // ESS range + const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8); + const int range1Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Max"), 27); + // Walking speed range + const int range2Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Min"), 27); + const int range2Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Max"), 62); + + // Push color based on angle ranges + if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && + (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { + ImGui::PushStyleColor( + ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), + range1ColorDefault))); + } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) && + (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { + ImGui::PushStyleColor( + ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), + range2ColorDefault))); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, + VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"), + textColorDefault))); + } + + // Render text + ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y); + // Restore original color + ImGui::PopStyleColor(); + // Restore original font scale + ImGui::GetFont()->Scale = oldFontScale; + ImGui::PopFont(); } - // Render text - ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y); - // Restore original color - ImGui::PopStyleColor(); - // Restore original font scale - ImGui::GetFont()->Scale = oldFontScale; - ImGui::PopFont(); + ImGui::End(); } - ImGui::End(); + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); } - - ImGui::PopStyleVar(); - ImGui::PopStyleColor(); } InputViewerSettingsWindow::~InputViewerSettingsWindow() { diff --git a/src/port/UI/LighthouseGui.cpp b/src/port/UI/LighthouseGui.cpp index 7885ff7af..2e5d70095 100644 --- a/src/port/UI/LighthouseGui.cpp +++ b/src/port/UI/LighthouseGui.cpp @@ -23,8 +23,6 @@ #include "port/Rando/CheckTracker/CheckTracker.h" #include "Notification.h" -#include "port/Controller/Mapper.h" -#include "port/Network/Anchor/Anchor.h" #include "port/Enhancements/Backports/EggAim.h" #include "LighthouseMenu.h" #include "LighthouseInputEditorWindow.h" @@ -45,7 +43,6 @@ std::shared_ptr mConsoleWindow; std::shared_ptr mStatsWindow; std::shared_ptr mGfxDebuggerWindow; std::shared_ptr mInputEditorWindow; -std::shared_ptr mGamepadMapperWindow; std::shared_ptr mModMenuWindow; std::shared_ptr mRomhackMenuWindow; @@ -75,7 +72,6 @@ std::shared_ptr mEggAimCrosshair; std::shared_ptr mModalWindow; std::shared_ptr mEventDebuggerWindow; std::shared_ptr mOcclusionDebugWindow; -std::shared_ptr mAnchorRoomWindow; UIWidgets::Colors GetMenuThemeColor() { return mLighthouseMenu->GetMenuThemeColor(); @@ -109,19 +105,15 @@ void SetupGuiElements() { SPDLOG_ERROR("Could not find console window"); } - // mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow"); - // if (mGfxDebuggerWindow == nullptr) { - // SPDLOG_ERROR("Could not find input GfxDebuggerWindow"); - // } + mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow"); + if (mGfxDebuggerWindow == nullptr) { + SPDLOG_ERROR("Could not find input GfxDebuggerWindow"); + } mInputEditorWindow = std::make_shared(CVAR_WINDOW("ControllerConfiguration"), "Configure Controller"); gui->AddGuiWindow(mInputEditorWindow); - mGamepadMapperWindow = - std::make_shared(CVAR_WINDOW("GamepadMapper"), "Gamepad Mapper", ImVec2(1280, 820)); - gui->AddGuiWindow(mGamepadMapperWindow); - mModMenuWindow = std::make_shared(CVAR_WINDOW("ModMenu"), "Mod Menu"); gui->AddGuiWindow(mModMenuWindow); @@ -198,10 +190,10 @@ void SetupGuiElements() { "gWindows.CheckTrackerSettings", "Check Tracker Settings"); gui->AddGuiWindow(mRandoCheckTrackerSettingsWindow); - mInputViewer = std::make_shared(CVAR_WINDOW("InputViewer"), "Input Viewer"); + mInputViewer = std::make_shared("gWindows.InputViewer", "Input Viewer"); gui->AddGuiWindow(mInputViewer); - mInputViewerSettings = std::make_shared(CVAR_WINDOW("InputViewerSettings"), + mInputViewerSettings = std::make_shared("gWindows.InputViewerSettings", "Input Viewer Settings", ImVec2(500, 525)); gui->AddGuiWindow(mInputViewerSettings); @@ -210,9 +202,6 @@ void SetupGuiElements() { mOcclusionDebugWindow = std::make_shared(CVAR_WINDOW("OcclusionDebug"), "Occlusion Debugger"); gui->AddGuiWindow(mOcclusionDebugWindow); - - mAnchorRoomWindow = std::make_shared(CVAR_WINDOW("AnchorRoom"), "Anchor Room"); - gui->AddGuiWindow(mAnchorRoomWindow); } void Destroy() { @@ -225,7 +214,6 @@ void Destroy() { mConsoleWindow = nullptr; mGfxDebuggerWindow = nullptr; mInputEditorWindow = nullptr; - mGamepadMapperWindow = nullptr; // mCollisionViewerWindow = nullptr; // mEventLogWindow = nullptr; mNotificationWindow = nullptr; @@ -249,7 +237,6 @@ void Destroy() { mEggAimCrosshair = nullptr; mEventDebuggerWindow = nullptr; mOcclusionDebugWindow = nullptr; - mAnchorRoomWindow = nullptr; } void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, diff --git a/src/port/UI/LighthouseInputEditorWindow.cpp b/src/port/UI/LighthouseInputEditorWindow.cpp index e577e199f..e762f7be1 100644 --- a/src/port/UI/LighthouseInputEditorWindow.cpp +++ b/src/port/UI/LighthouseInputEditorWindow.cpp @@ -4,7 +4,6 @@ #include #include #include -#include "cvar_prefixes.h" #ifndef __WIIU__ #include #endif @@ -14,15 +13,6 @@ #define SCALE_IMGUI_SIZE(value) ((value / 13.0f) * ImGui::GetFontSize()) LighthouseInputEditorWindow::~LighthouseInputEditorWindow() { - auto ignored = Ship::Context::GetRawInstance() - ->GetControlDeck() - ->GetConnectedPhysicalDeviceManager() - ->GetIgnoredInstanceIdsForPort(0); - if (!ignored.empty()) { - Ship::Context::GetRawInstance()->GetConfig()->SetBlock("CVars.gSettings.IgnoredControllers", ignored); - } else { - Ship::Context::GetRawInstance()->GetConfig()->EraseBlock("CVars.gSettings.IgnoredControllers"); - } } void LighthouseInputEditorWindow::InitElement() { @@ -50,19 +40,6 @@ void LighthouseInputEditorWindow::InitElement() { addButtonName(BTN_DLEFT, "D-pad left"); addButtonName(BTN_DRIGHT, "D-pad right"); addButtonName(0, "None"); - if (Ship::Context::GetRawInstance()->GetConfig()->GetNestedJson()["CVars"]["gSettings"].contains( - "IgnoredControllers")) { - std::vector ignored = - Ship::Context::GetRawInstance()->GetConfig()->GetNestedJson()["CVars"]["gSettings"]["IgnoredControllers"]; - if (!ignored.empty()) { - for (int id : ignored) { - Ship::Context::GetRawInstance() - ->GetControlDeck() - ->GetConnectedPhysicalDeviceManager() - ->IgnoreInstanceIdForPort(0, id); - } - } - } } #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 diff --git a/src/port/UI/LighthouseMenu.cpp b/src/port/UI/LighthouseMenu.cpp index db16a7c99..63769245f 100644 --- a/src/port/UI/LighthouseMenu.cpp +++ b/src/port/UI/LighthouseMenu.cpp @@ -5,7 +5,6 @@ #include "port/Localization/Language.h" #include "port/Romhack/RomhackConfig.h" #include "port/Patches/Patches.h" -#include "port/Network/Anchor/Anchor.h" #include #include #include @@ -214,12 +213,6 @@ void LighthouseMenu::InitElement() { "Not available during the character parade." } }, { DISABLE_FOR_ROMHACK, { [](disabledInfo& info) -> bool { return port_isRomhack(); }, "Not available with romhacks" } }, - { FORCED_ON_FOR_ANCHOR_CONNECTED, - { [](disabledInfo& info) -> bool { - Anchor* anchor = Anchor::GetInstance(); - return anchor != nullptr && anchor->isConnected && !anchor->IsGlobalRoom(); - }, - "Forced on while connected to Anchor" } }, }; } diff --git a/src/port/UI/LighthouseMenuDevTools.cpp b/src/port/UI/LighthouseMenuDevTools.cpp index 6ce8a96f8..38a337350 100644 --- a/src/port/UI/LighthouseMenuDevTools.cpp +++ b/src/port/UI/LighthouseMenuDevTools.cpp @@ -6,11 +6,12 @@ //#include #include "port/ResourceHelpers.h" #include "port/DevTools/DevSequences.h" -#include "port/DevTools/ThreadWatchdog.h" #include "UIWidgets.hpp" #include +extern "C" { #include "variables.h" +} namespace LighthouseGui { @@ -72,14 +73,9 @@ void LighthouseMenu::AddMenuDevTools() { .Options(CheckboxOptions().Tooltip( "Enables the Gfx trace mode, which will output information about the Gfx commands being run.")); #endif - AddWidget(path, "Dump Thread State", WIDGET_BUTTON) - .Callback([](WidgetInfo&) { ThreadWatchdog_DumpNow(); }) - .Options( - ButtonOptions() - .Size(Sizes::Inline) - .Tooltip( - "Log a snapshot of the decomp thread heartbeats and pipeline queue state. The watchdog also logs " - "this automatically when a thread stops beating.")); + AddWidget(path, "Nametag Distance", WIDGET_CVAR_SLIDER_FLOAT) + .CVar(CVAR_DEVELOPER_TOOLS("NametagDist")) + .Options(FloatSliderOptions().DefaultValue(3000.0f).Min(1000.0f).Max(10000.0f).Step(10.0f)); /*AddWidget(path, "Debug Mode", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_DEVELOPER_TOOLS("DebugMode")) .Options(CheckboxOptions().Tooltip("Various debug features, including a level selector from the main menu."));*/ @@ -101,11 +97,6 @@ void LighthouseMenu::AddMenuDevTools() { AddWidget(path, "Spiral Mountain Ending Sequence", WIDGET_BUTTON) .Callback([](WidgetInfo&) { RequestSequence(SEQ_MODE9_BK); }) .Options(ButtonOptions().Size(Sizes::Inline).Tooltip("Jump to the post-parade demo.")); - AddWidget(path, "All 100 Ending Scene", WIDGET_BUTTON) - .Callback([](WidgetInfo&) { RequestSequence(SEQ_ENDING_ALL_100); }) - .Options(ButtonOptions() - .Size(Sizes::Inline) - .Tooltip("Jump to the 100-jiggy ending cutscene (normally shown after the final parade).")); AddWidget(path, "Attract Demos", WIDGET_SEPARATOR_TEXT); // Demo index = slot in the decomp attract table (D_80371F00); 4 and 9 are the @@ -150,6 +141,14 @@ void LighthouseMenu::AddMenuDevTools() { .HideInSearch(true) .Options(WindowButtonOptions().Tooltip( "Shows the stats window, with your FPS and frametimes, and the OS you're playing on.")); + AddWidget(path, "Adaptive FPS", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("AdaptiveFPS")) + .RaceDisable(false) + .Options(CheckboxOptions() + .Tooltip("Automatically lowers interpolation FPS in demanding scenes so the game logic never " + "stalls, then restores it when the scene clears. Disable to always target your " + "requested FPS, which may stutter on heavy scenes or weaker hardware.") + .DefaultValue(true)); // Console // path.sidebarName = "Console"; diff --git a/src/port/UI/LighthouseMenuEnhancements.cpp b/src/port/UI/LighthouseMenuEnhancements.cpp index ee18db3a6..a9be7a36c 100644 --- a/src/port/UI/LighthouseMenuEnhancements.cpp +++ b/src/port/UI/LighthouseMenuEnhancements.cpp @@ -1,12 +1,5 @@ #include "LighthouseMenu.h" #include "port/Enhancements/Trackers/DisplayOverlay.h" -#include "port/Network/Anchor/Anchor.h" - -#include "functions.h" -extern "C" { -#include "variables.h" -extern u8 gCompletedBottlesBonusGames[7]; -} #define CVAR_INT_SHIP_INIT(cvar, val) \ CVarSetInteger(cvar, val); \ @@ -14,54 +7,6 @@ extern u8 gCompletedBottlesBonusGames[7]; namespace LighthouseGui { -// Live toggle state for the Bottles' Bonus gags (non-cvar checkboxes). Order matches -// D_803635EC in ba_anim.c and gCompletedBottlesBonusGames. -static bool sBottlesBonusState[7] = { false }; - -static const char* kBottlesBonusNames[7] = { - "Big Head", - "Big Hands & Feet", - "Big Kazooie", - "Tall Body & Small Head", - "Tall Body, Small Head, Big Hands & Feet", - "Big Everything", - "Wishy-Washy Banjo", -}; - -static const char* kBottlesBonusTooltips[7] = { - "Bottles' Bonus: enlarges Banjo's head.", - "Bottles' Bonus: enlarges Banjo's hands and feet.", - "Bottles' Bonus: enlarges Kazooie's head and wings.", - "Bottles' Bonus: stretches Banjo's body and shrinks his head.", - "Bottles' Bonus: stretched body, shrunken head, and big hands and feet.", - "The 'Big Bottles Bonus': big head, big hands and feet, and big Kazooie.", - "Bottles' Bonus: turns Banjo into Wishy-Washy.", -}; - -static const char* kBottlesBonusLockedTooltip = - "Complete this Bottles' Bonus puzzle to unlock it. (Always available while connected to Anchor.)"; - -static bool IsBottlesBonusUnlocked(int i) { - Anchor* anchor = Anchor::GetInstance(); - if (anchor != nullptr && anchor->isConnected && !anchor->IsGlobalRoom()) { - return true; - } - return gCompletedBottlesBonusGames[i] != 0; -} - -static void ApplyBottlesBonusState() { - bool any = false; - for (int i = 0; i < 7; i++) { - volatileFlag_setEx((enum volatile_flags_e)(VOLATILE_FLAG_97_SANDCASTLE_BOTTLES_BONUS_1 + i), - sBottlesBonusState[i] ? 1 : 0, 0); - if (sBottlesBonusState[i]) { - any = true; - } - } - // Master gate read by __baanim_applyBottlesBonus / baanim_getActiveBottlesBonusMask. - volatileFlag_setEx(VOLATILE_FLAG_78_SANDCASTLE_NO_BONUS, any ? 1 : 0, 0); -} - extern std::shared_ptr mLighthouseMenu; using namespace UIWidgets; @@ -77,31 +22,16 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Allow Start to Skip Boot Logos", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cutscenes.SkipBootLogos")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Press Start to skip the Rareware and Nintendo logos on boot.")); AddWidget(path, "Allow Start to Skip Intro Cutscenes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cutscenes.StartSkipIntro")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Press Start to Skip Intro Cutscenes.")); AddWidget(path, "Allow Start to Skip Misc Cutscenes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cutscenes.SkipMiscCutscenes")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Press Start to skip the Gruntilda's Lair and Game Over cutscenes.")); AddWidget(path, "Skip Jiggy Dance", WIDGET_CVAR_CHECKBOX) @@ -115,11 +45,6 @@ void LighthouseMenu::AddMenuEnhancements() { .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Skips the cutscene that plays when first defeating a Clucker.")); - AddWidget(path, "Skip Note Door Dance", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_ENHANCEMENT("Cutscenes.SkipNoteDoorDance")) - .RaceDisable(false) - .Options(CheckboxOptions().Tooltip("Skips Banjo's dance when a note door opens, opening it immediately.")); - // Enhancements -> Graphics path = { "Enhancements", "Graphics", SECTION_COLUMN_1 }; AddSidebarEntry("Enhancements", path.sidebarName, 2); @@ -135,29 +60,10 @@ void LighthouseMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip("Forces game to show original aspect ratio during cutscenes to avoid seeing " "unfinished edges of scene geometry.")); - path.column = SECTION_COLUMN_2; - - AddWidget(path, "Bottles' Bonuses", WIDGET_SEPARATOR_TEXT); - - for (int i = 0; i < 7; i++) { - AddWidget(path, kBottlesBonusNames[i], WIDGET_CHECKBOX) - .ValuePointer(&sBottlesBonusState[i]) - .Callback([](WidgetInfo& info) { ApplyBottlesBonusState(); }) - .PreFunc([i](WidgetInfo& info) { - if (!IsBottlesBonusUnlocked(i)) { - info.options->disabled = true; - info.options->disabledTooltip = kBottlesBonusLockedTooltip; - } - }) - .Options(CheckboxOptions().Tooltip(kBottlesBonusTooltips[i])); - } - - path.column = SECTION_COLUMN_1; - - AddWidget(path, "Extended Draw Distance", WIDGET_CVAR_SLIDER_INT) + AddWidget(path, "Extended Draw Distance: %dx", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_ENHANCEMENT("Graphics.DrawDistance")) .RaceDisable(false) - .Options(IntSliderOptions().Min(1).Max(6).DefaultValue(1).ShowButtons(true).Format("%dx").Tooltip( + .Options(IntSliderOptions().Min(1).Max(6).DefaultValue(1).ShowButtons(true).Format("").Tooltip( "Multiplies the draw distance for objects.\n" "Higher values render more but cost performance.")); @@ -312,21 +218,11 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Fix CCW Gnawty Rock (Spring)", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fixes.GnawtySpringRock")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Makes Gnawty's rock indestructible in CCW Spring.")); AddWidget(path, "Fix Termite Mound Slopes", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fixes.TermiteMoundSlopes")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Makes slopes in the Mumbo's Mountain termite mound slide instantly.")); AddWidget(path, "Fix Early Claw Swipe During Slide", WIDGET_CVAR_CHECKBOX) @@ -354,13 +250,6 @@ void LighthouseMenu::AddMenuEnhancements() { .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Stops the Jinjo charge-up sound the instant it hits Grunty.")); - AddWidget(path, "Mute Chimpy Replay", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_ENHANCEMENT("Fixes.ChimpyStumpRumble")) - .RaceDisable(false) - .Options(CheckboxOptions().DefaultValue(true).Tooltip( - "Mutes Chimpy and the rumbling sound his stump makes on every return trip to " - "Mumbo's Mountain. The first rise keeps its sound.")); - AddWidget(path, "Fix Cutscene Audio Sync", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fix.CutsceneSync")) .RaceDisable(false) @@ -379,24 +268,8 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Fix Conga's Name", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Fixes.CongaText")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Corrects a spelling error when meeting Conga as a termite.")); - AddWidget(path, "Fix Freezeezy Peak Lobby", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_ENHANCEMENT("Fixes.FPLobbyDoorTile")) - .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) - .Options(CheckboxOptions().Tooltip("Fixes the smeared snow trim around the Freezeezy Peak entrance in " - "Gruntilda's Lair. Requires a map reload to take effect.")); - // Enhancements -> Restorations path = { "Enhancements", "Restorations", SECTION_COLUMN_1 }; AddSidebarEntry("Enhancements", path.sidebarName, 2); @@ -429,16 +302,6 @@ void LighthouseMenu::AddMenuEnhancements() { }) .DefaultIndex(1)); - AddWidget(path, "Permadeath", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_ENHANCEMENT("Gameplay.Permadeath")) - .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) - .Options(CheckboxOptions().Tooltip("Your save file is deleted on death. Lives are ignored.")); - AddWidget(path, "Skip Spiral Mountain Tutorial", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Gameplay.SkipSMTutorial")) .RaceDisable(false) @@ -497,8 +360,7 @@ void LighthouseMenu::AddMenuEnhancements() { info.activeDisables.push_back(DISABLE_FOR_ROMHACK); } }) - .Options(CheckboxOptions().Tooltip("Reduces Boggy's max speed during both sled races in Freezeezy Peak.\n" - "Requires a map reload to take effect.")); + .Options(CheckboxOptions().Tooltip("Reduces Boggy's max speed during both sled races in Freezeezy Peak.")); AddWidget(path, "Easier Mr Vile", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("EasierMrVile")) @@ -560,11 +422,6 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Note Collection Retention", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Gameplay.NoteRetention")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(FORCED_ON_FOR_ANCHOR_CONNECTED).active) { - info.activeDisables.push_back(FORCED_ON_FOR_ANCHOR_CONNECTED); - } - }) .Options(CheckboxOptions().Tooltip( "Notes you've already collected stay collected and don't respawn when you revisit a level. " "Collection is always tracked; this toggle controls whether collected notes are skipped on " @@ -573,11 +430,6 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Jinjo Collection Retention", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Gameplay.JinjoRetention")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(FORCED_ON_FOR_ANCHOR_CONNECTED).active) { - info.activeDisables.push_back(FORCED_ON_FOR_ANCHOR_CONNECTED); - } - }) .Options(CheckboxOptions().Tooltip( "Jinjos you've already collected stay collected across visits instead of resetting each time " "you enter a level, so you no longer need all five in one go. Collection is always tracked; " @@ -647,7 +499,7 @@ void LighthouseMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("Cheats.TalonTrotCycle")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip( - "While in Talon Trot: D-pad Right cycles forward (Normal->Boots->Sneakers), D-pad Left cycles backward.")); + "While in Talon Trot: D-pad Right cycles forward (Normal→Boots→Sneakers), D-pad Left cycles backward.")); // Transformations Section AddWidget(path, "Transformations", WIDGET_SEPARATOR_TEXT); @@ -655,32 +507,22 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Fast Transformation", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cheats.FastTransform")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip("Speeds up Mumbo transformation animation by 3x.")); AddWidget(path, "D-pad Cycle Transform", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cheats.CycleTransform")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Press D-pad Up/Down to cycle through transformation forms.\nUp: Forward " - "(Banjo->Termite->...->Bee->Banjo), Down: Backward.")); + "(Banjo→Mumbo→...→Wishy→Banjo), Down: Backward.")); AddWidget(path, "No Mumbo Untransform", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("Cheats.NoMumboUntransform")) .RaceDisable(false) - .PreFunc([](WidgetInfo& info) { - if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { - info.activeDisables.push_back(DISABLE_FOR_ROMHACK); - } - }) .Options(CheckboxOptions().Tooltip( "Disables Mumbo untransforming you when going too far and skips his warning dialog.")); path = { "Enhancements", "Trackers", SECTION_COLUMN_1 }; - AddSidebarEntry("Enhancements", path.sidebarName, 2); + AddSidebarEntry("Enhancements", path.sidebarName, 1); path.column = SECTION_COLUMN_1; AddWidget(path, "Gameplay Timer", WIDGET_SEPARATOR_TEXT); @@ -709,7 +551,7 @@ void LighthouseMenu::AddMenuEnhancements() { AddWidget(path, "Hide Window Background", WIDGET_CVAR_CHECKBOX) .CVar("gDisplayOverlay.Background") .Options(CheckboxOptions().Tooltip("Hides the background of the Display Overlay window.")); - AddWidget(path, "Timer Scale", WIDGET_CVAR_SLIDER_FLOAT) + AddWidget(path, "Scale: %.1fx", WIDGET_CVAR_SLIDER_FLOAT) .CVar("gDisplayOverlay.Scale") .Options(FloatSliderOptions() .Tooltip("Adjust the Scale for the Display Overlay window.") diff --git a/src/port/UI/LighthouseMenuNetwork.cpp b/src/port/UI/LighthouseMenuNetwork.cpp index 5759914bc..42310a6a7 100644 --- a/src/port/UI/LighthouseMenuNetwork.cpp +++ b/src/port/UI/LighthouseMenuNetwork.cpp @@ -7,7 +7,9 @@ #include "UIWidgets.hpp" #include +extern "C" { #include "variables.h" +} namespace LighthouseGui { diff --git a/src/port/UI/LighthouseMenuSettings.cpp b/src/port/UI/LighthouseMenuSettings.cpp index b463c570a..f70c67990 100644 --- a/src/port/UI/LighthouseMenuSettings.cpp +++ b/src/port/UI/LighthouseMenuSettings.cpp @@ -13,7 +13,9 @@ #include "UIWidgets.hpp" #include +extern "C" { #include "variables.h" +} namespace LighthouseGui { @@ -154,8 +156,8 @@ void LighthouseMenu::AddMenuSettings() { .ComponentAlignment(ComponentAlignments::Right) .ComboMap(bootSequenceLabels) .Tooltip("Configure what happens when starting or resetting the game.\n\n" - "Default: Replace the N64 branding with LUS branding\n" - "Authentic: Keep the authentic N64 branding\n" + "Default: LUS logo -> N64 logo\n" + "Authentic: N64 logo only\n" "File Select: Skip to file select menu")); path.column = SECTION_COLUMN_2; @@ -181,13 +183,12 @@ void LighthouseMenu::AddMenuSettings() { "Make sure you're playing the same game or romhack as the save you're importing.", "Select Save", "Cancel", [slot]() { - SaveConverter::PickAndImport(slot, [](SaveConverter::Result r) { - if (r.message.empty()) { - return; // cancelled - } - LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Import Complete" : "Save Import Failed", - r.message, "OK", "", nullptr, nullptr); - }); + SaveConverter::Result r = SaveConverter::PickAndImport(slot); + if (r.message.empty()) { + return; // cancelled + } + LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Import Complete" : "Save Import Failed", + r.message, "OK", "", nullptr, nullptr); }, nullptr); }) @@ -199,13 +200,12 @@ void LighthouseMenu::AddMenuSettings() { .RaceDisable(false) .Callback([](WidgetInfo& info) { int slot = CVarGetInteger(CVAR_SETTING("SaveConvertSlot"), SaveConverter::kSlotAll); - SaveConverter::PickAndExport(slot, [](SaveConverter::Result r) { - if (r.message.empty()) { - return; // cancelled - } - LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Export Complete" : "Save Export Failed", - r.message, "OK", "", nullptr, nullptr); - }); + SaveConverter::Result r = SaveConverter::PickAndExport(slot); + if (r.message.empty()) { + return; // cancelled + } + LighthouseGui::mModalWindow->RegisterPopup(r.ok ? "Save Export Complete" : "Save Export Failed", r.message, + "OK", "", nullptr, nullptr); }) .Options(ButtonOptions().Tooltip( "Export the save for the game you're playing to a Banjo: Recompiled file. Use the slot above " @@ -261,17 +261,21 @@ void LighthouseMenu::AddMenuSettings() { .Options(ButtonOptions() .Size(Sizes::Inline) .Tooltip("Pick a Banjo-Kazooie ROM and extract only its dialog into a slim language pack.")); - - // Accessibility Options AddWidget(path, "Accessibility", WIDGET_SEPARATOR_TEXT); - AddWidget(path, "Disable Screen Shake", WIDGET_CVAR_CHECKBOX) - .CVar(CVAR_SETTING("A11yDisableScreenShake")) +#if defined(_WIN32) || defined(__APPLE__) || defined(ESPEAK) + AddWidget(path, "Text to Speech", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("A11yTTS")) .RaceDisable(false) - .Options(CheckboxOptions().Tooltip( - "Stops the camera shaking on impacts such as Beak Buster landings, boulders and boss attacks. " - "Controller rumble is unaffected.")); - - // Experimental Options + .Options(CheckboxOptions().Tooltip("Enables text to speech for in game dialog")); +#endif + AddWidget(path, "Disable Idle Camera Re-Centering", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("A11yDisableIdleCam")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Disables the automatic re-centering of the camera when idle.")); + AddWidget(path, "Disable Screen Flash for Finishing Blow", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("A11yNoScreenFlashForFinishingBlow")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Disables the white screen flash on enemy kill.")); AddWidget(path, "EXPERIMENTAL", WIDGET_SEPARATOR_TEXT).Options(TextOptions().Color(Colors::Orange)); AddWidget(path, "ImGui Menu Scaling", WIDGET_CVAR_COMBOBOX) .CVar(CVAR_SETTING("ImGuiScale")) @@ -289,41 +293,41 @@ void LighthouseMenu::AddMenuSettings() { path.column = SECTION_COLUMN_1; AddSidebarEntry("Settings", "Audio", 3); - AddWidget(path, "Master Volume", WIDGET_CVAR_SLIDER_INT) + AddWidget(path, "Master Volume: %d %%", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_SETTING("Volume.Master")) .RaceDisable(false) - .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(40).ShowButtons(true).Format("%d%%")); - // AddWidget(path, "Main Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - // .CVar(CVAR_SETTING("Volume.MainMusic")) - // .RaceDisable(false) - // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(40).ShowButtons(true).Format("")); + AddWidget(path, "Main Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + .CVar(CVAR_SETTING("Volume.MainMusic")) + .RaceDisable(false) + .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, - // ((float)CVarGetInteger(CVAR_SETTING("Volume.MainMusic"), 100) / 100.0f)); - // }); - // AddWidget(path, "Sub Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - // .CVar(CVAR_SETTING("Volume.SubMusic")) - // .RaceDisable(false) - // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + // Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, + // ((float)CVarGetInteger(CVAR_SETTING("Volume.MainMusic"), 100) / 100.0f)); + //}); + AddWidget(path, "Sub Music Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + .CVar(CVAR_SETTING("Volume.SubMusic")) + .RaceDisable(false) + .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, - // ((float)CVarGetInteger(CVAR_SETTING("Volume.SubMusic"), 100) / 100.0f)); - // }); - // AddWidget(path, "Fanfare Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - // .CVar(CVAR_SETTING("Volume.Fanfare")) - // .RaceDisable(false) - // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + // Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, + // ((float)CVarGetInteger(CVAR_SETTING("Volume.SubMusic"), 100) / 100.0f)); + //}); + AddWidget(path, "Fanfare Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + .CVar(CVAR_SETTING("Volume.Fanfare")) + .RaceDisable(false) + .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_FANFARE, - // ((float)CVarGetInteger(CVAR_SETTING("Volume.Fanfare"), 100) / 100.0f)); - // }); - // AddWidget(path, "Sound Effects Volume: %d %%", WIDGET_CVAR_SLIDER_INT) - // .CVar(CVAR_SETTING("Volume.SFX")) - // .RaceDisable(false) - // .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); + // Audio_SetGameVolume(SEQ_PLAYER_FANFARE, + // ((float)CVarGetInteger(CVAR_SETTING("Volume.Fanfare"), 100) / 100.0f)); + //}); + AddWidget(path, "Sound Effects Volume: %d %%", WIDGET_CVAR_SLIDER_INT) + .CVar(CVAR_SETTING("Volume.SFX")) + .RaceDisable(false) + .Options(IntSliderOptions().Min(0).Max(100).DefaultValue(100).ShowButtons(true).Format("")); //.Callback([](WidgetInfo& info) { - // Audio_SetGameVolume(SEQ_PLAYER_SFX, ((float)CVarGetInteger(CVAR_SETTING("Volume.SFX"), 100) / 100.0f)); - // }); + // Audio_SetGameVolume(SEQ_PLAYER_SFX, ((float)CVarGetInteger(CVAR_SETTING("Volume.SFX"), 100) / 100.0f)); + //}); AddWidget(path, "Audio API (Needs reload)", WIDGET_AUDIO_BACKEND).RaceDisable(false); // Graphics Settings @@ -510,8 +514,7 @@ void LighthouseMenu::AddMenuSettings() { // Input Viewer path.sidebarName = "Input Viewer"; - path.column = SECTION_COLUMN_1; - AddSidebarEntry("Settings", path.sidebarName, 2); + AddSidebarEntry("Settings", path.sidebarName, 3); AddWidget(path, "Input Viewer", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Toggle Input Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("InputViewer")) diff --git a/src/port/UI/LighthouseModMenuWindow.cpp b/src/port/UI/LighthouseModMenuWindow.cpp index 49b15e3e6..90018371b 100644 --- a/src/port/UI/LighthouseModMenuWindow.cpp +++ b/src/port/UI/LighthouseModMenuWindow.cpp @@ -84,8 +84,8 @@ static std::vector sRomhackBaseMismatch; // Romhacks and universally shared mods get special folders // The lang folder is skipped in scans #define ROMHACKS_DIR "~romhacks" -#define SHARED_DIR "~shared" -#define LANG_DIR "~lang" +#define SHARED_DIR "shared" +#define LANG_DIR "lang" static std::string JoinModList(const std::vector& list) { std::string s; @@ -313,7 +313,7 @@ void UpdateModFiles(bool init, bool reset) { if (!IsValidExtension(p.path().extension().generic_string())) { continue; } - // Skip reserved folders (e.g. mods/~lang/ language packs) — they + // Skip reserved folders (e.g. mods/lang/ language packs) — they // aren't user-toggleable mods and must not appear in either menu. if (IsReservedModPath(modsPath, p.path())) { continue; @@ -466,7 +466,7 @@ static void DrawModInfo(std::string file) { using ModFilter = std::function; -static void DrawMods(bool enabled, const ModFilter& shown, bool alphabetical) { +static void DrawMods(bool enabled, const ModFilter& shown) { std::vector& selectedModFiles = GetModFiles(enabled); std::vector visible; @@ -482,10 +482,10 @@ static void DrawMods(bool enabled, const ModFilter& shown, bool alphabetical) { bool madeAnyChange = false; size_t switchFromIndex = 0; size_t switchToIndex = 0; - std::string pendingMoveFile; - for (size_t k = 0; k < visible.size(); k++) { - size_t vpos = alphabetical ? k : (visible.size() - 1 - k); + // Highest priority (largest real index) draws at the top, matching the + // "top overrides bottom" rule. + for (size_t vpos = visible.size() - 1; vpos != SIZE_MAX; vpos--) { size_t i = visible[vpos]; std::string file = selectedModFiles[i]; if (enabled) { @@ -496,10 +496,14 @@ static void DrawMods(bool enabled, const ModFilter& shown, bool alphabetical) { // (to the disabled list), disabled mods get an arrow pointing left. if (UIWidgets::StateButton((file + "_left_right").c_str(), enabled ? ICON_FA_ARROW_RIGHT : ICON_FA_ARROW_LEFT, ImVec2(25, 25), UIWidgets::ButtonOptions().Color(THEME_COLOR))) { - pendingMoveFile = file; + if (enabled) { + DisableMod(file); + } else { + EnableMod(file); + } } - if (enabled && !alphabetical) { + if (enabled) { const bool atTop = (vpos == visible.size() - 1); const bool atBottom = (vpos == 0); @@ -547,19 +551,11 @@ static void DrawMods(bool enabled, const ModFilter& shown, bool alphabetical) { std::iter_swap(selectedModFiles.begin() + switchFromIndex, selectedModFiles.begin() + switchToIndex); AfterModChange(); } - - if (!pendingMoveFile.empty()) { - if (enabled) { - DisableMod(pendingMoveFile); - } else { - EnableMod(pendingMoveFile); - } - } } static bool editing = false; -static void DrawModManager(const char* tableId, const ModFilter& shown, bool alphabetical = false) { +static void DrawModManager(const char* tableId, const ModFilter& shown) { auto editOpts = UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR); editOpts.Disabled(editing); editOpts.DisabledTooltip("Already editing..."); @@ -614,7 +610,7 @@ static void DrawModManager(const char* tableId, const ModFilter& shown, bool alp ImGui::TableNextColumn(); if (ImGui::BeginChild("Enabled Mods", ImVec2(0, -8))) { - DrawMods(true, shown, alphabetical); + DrawMods(true, shown); ImGui::EndChild(); } @@ -622,7 +618,7 @@ static void DrawModManager(const char* tableId, const ModFilter& shown, bool alp ImGui::TableNextColumn(); if (ImGui::BeginChild("Disabled Mods", ImVec2(0, -8))) { - DrawMods(false, shown, alphabetical); + DrawMods(false, shown); ImGui::EndChild(); } @@ -666,10 +662,7 @@ void LighthouseRomhackMenuWindow::DrawElement() { "Romhack overlays live in mods/~romhacks/. Changes require a restart, and only one\n" "romhack can be active at a time."); - // Romhacks are one-at-a-time, so there's no load order to preserve: list them - // alphabetically instead of by priority. - DrawModManager( - "tableRomhacks", [](const std::string& name) { return IsRomhackOverlay(name); }, true); + DrawModManager("tableRomhacks", [](const std::string& name) { return IsRomhackOverlay(name); }); } void LighthouseModMenuWindow::InitElement() { @@ -836,13 +829,19 @@ bool IsInlineModExtractionBusy() { return sInlineExtracting.load(); } -// Kick off the (detached) extraction worker for a ROM the user already picked + loaded. -static void BeginInlineExtraction(std::shared_ptr extractor, bool langPack) { +void RequestInlineModExtraction() { + if (sInlineExtracting.load()) { + return; + } + auto extractor = std::make_unique(); + if (!extractor->SelectGameFromUI()) { + return; + } sInlineFile = extractor->GetRomPath(); sInlineCount = 0; sInlineTotal = 0; sInlineResult = 0; - sInlineLangPack = langPack; + sInlineLangPack = false; sInlineExtracting = true; std::thread([ex = std::move(extractor)]() mutable { const bool ok = ex->GenerateOTR(sInlineCount, sInlineTotal, "bk"); @@ -851,51 +850,49 @@ static void BeginInlineExtraction(std::shared_ptr extractor, bool }).detach(); } -// Shared body of the two public requests: pick a ROM, load it, and start extraction. Language packs -// add a couple of region gates before the common kickoff. The extractor is a shared_ptr so it stays -// alive across the async pick (captured in the callback) and the detached extraction thread. -static void StartInlineRomExtraction(bool langPack) { +void RequestInlineLanguagePackExtraction() { if (sInlineExtracting.load()) { return; } - auto extractor = std::make_shared(); - extractor->SelectGameFromUI([extractor, langPack](bool ok) { - if (!ok) { - return; // cancelled or failed to load - } - if (langPack) { - // Refuse a pack when we already have it as bk.o2r. - const std::string region = extractor->GetRegionSlug(); - if (region.empty()) { - LighthouseGui::RegisterPopup("Unrecognized ROM", - "That file isn't a recognized Banjo-Kazooie ROM, so no\n" - "language pack could be made from it.", - "OK", "", nullptr, nullptr); - return; - } - if (region == Lighthouse::BaseRegionSlug()) { - LighthouseGui::RegisterPopup("Already Have This Language", - "Your base game data (bk.o2r) already provides this region's\n" - "dialog, so there's no need to add it as a language pack.", - "OK", "", nullptr, nullptr); - return; - } - // Re-extracting a region overwrites its existing pack (e.g. to refresh it after an - // update), so a pre-existing mods/lang/bk.o2r is fine. - std::error_code ec; - std::filesystem::create_directories(Ship::Context::GetPathRelativeToAppDirectory("mods/lang"), ec); - extractor->SetDialogPack(true); - } - BeginInlineExtraction(extractor, langPack); - }); -} + auto extractor = std::make_unique(); + if (!extractor->SelectGameFromUI()) { + return; + } -void RequestInlineModExtraction() { - StartInlineRomExtraction(false); -} + // Refuse a pack when we already have it as bk.o2r. + const std::string region = extractor->GetRegionSlug(); + if (region.empty()) { + LighthouseGui::RegisterPopup("Unrecognized ROM", + "That file isn't a recognized Banjo-Kazooie ROM, so no\n" + "language pack could be made from it.", + "OK", "", nullptr, nullptr); + return; + } + if (region == Lighthouse::BaseRegionSlug()) { + LighthouseGui::RegisterPopup("Already Have This Language", + "Your base game data (bk.o2r) already provides this region's\n" + "dialog, so there's no need to add it as a language pack.", + "OK", "", nullptr, nullptr); + return; + } + // Re-extracting a region overwrites its existing pack (e.g. to refresh it + // after an update), so a pre-existing mods/lang/bk.o2r is fine. + const std::string langDir = Ship::Context::GetPathRelativeToAppDirectory("mods/lang"); + std::error_code ec; + std::filesystem::create_directories(langDir, ec); -void RequestInlineLanguagePackExtraction() { - StartInlineRomExtraction(true); + extractor->SetDialogPack(true); + sInlineFile = extractor->GetRomPath(); + sInlineCount = 0; + sInlineTotal = 0; + sInlineResult = 0; + sInlineLangPack = true; + sInlineExtracting = true; + std::thread([ex = std::move(extractor)]() mutable { + const bool ok = ex->GenerateOTR(sInlineCount, sInlineTotal, "bk"); + sInlineResult = ok ? 1 : 2; + sInlineExtracting = false; + }).detach(); } void DrawInlineModExtraction() { @@ -927,7 +924,7 @@ void DrawInlineModExtraction() { const std::string packPath = GameExtractor::sLastOutputPath; if (!packPath.empty() && GetArchiveManager()->AddArchive(packPath) == nullptr) { // Shouldn't happen for an o2r we just wrote; if it does, the pack is - // still in mods/~lang and loads on the next launch. + // still in mods/lang and loads on the next launch. SPDLOG_WARN("[Lang] Pack '{}' didn't register live; it will load on the next launch.", packPath); } Lighthouse::RescanLanguages(); diff --git a/src/port/UI/LighthouseModals.cpp b/src/port/UI/LighthouseModals.cpp index d3db2586b..05696e112 100644 --- a/src/port/UI/LighthouseModals.cpp +++ b/src/port/UI/LighthouseModals.cpp @@ -33,7 +33,7 @@ void LighthouseModalWindow::DrawElement() { if (modals.size() > 0) { LighthouseModal curModal = modals.at(0); if (!ImGui::IsPopupOpen(curModal.title_.c_str())) { - ImVec2 center = ImGui::GetMainViewport()->GetWorkCenter(); + ImVec2 center = ImGui::GetMainViewport()->GetCenter(); ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGui::OpenPopup(curModal.title_.c_str()); } @@ -46,11 +46,6 @@ void LighthouseModalWindow::DrawElement() { ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) { - // Show the nav highlight on the default button (button1) the moment the popup opens, so a - // gamepad/keyboard user sees the selection immediately rather than after a first input. - if (ImGui::IsWindowAppearing()) { - ImGui::SetNavCursorVisible(true); - } ImGui::Text("%s", curModal.message_.c_str()); UIWidgets::PushStyleButton(THEME_COLOR); if (ImGui::Button(curModal.button1_.c_str())) { diff --git a/src/port/UI/Menu.cpp b/src/port/UI/Menu.cpp index 778aff569..a79fef5f0 100644 --- a/src/port/UI/Menu.cpp +++ b/src/port/UI/Menu.cpp @@ -15,6 +15,7 @@ std::vector windowTypeSizes = { {} }; extern std::unordered_map warpPointSceneList; +extern void Warp(); namespace LighthouseGui { extern std::shared_ptr mModalWindow; @@ -113,13 +114,6 @@ void Menu::UpdateWindowBackendObjects() { } } -void Menu::UpdateAudioBackendObjects() { - availableAudioBackends = Ship::Context::GetRawInstance()->GetAudio()->GetAvailableAudioBackends(); - for (auto& backend : *availableAudioBackends) { - availableAudioBackendsMap[backend] = audioBackendsMap.at(backend); - } -} - bool Menu::IsMenuPopped() { return popped; } @@ -142,7 +136,6 @@ void Menu::InitElement() { menuThemeIndex = static_cast(CVarGetInteger(CVAR_SETTING("Menu.Theme"), defaultThemeIndex)); UpdateWindowBackendObjects(); - UpdateAudioBackendObjects(); } void Menu::UpdateElement() { @@ -256,9 +249,8 @@ uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { entry.info.type == WIDGET_SEPARATOR_TEXT || entry.info.isHidden || entry.info.hideInSearch) { continue; } - const char* extraTooltip = entry.info.options->tooltip; - std::string widgetStr = entry.info.name + std::string(extraTooltip != nullptr ? extraTooltip : "") + - entry.extraTerms + entry.sidebarName; + std::string widgetStr = + entry.info.name + entry.info.options->tooltip + entry.extraTerms + entry.sidebarName; std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); if (widgetStr.find(menuSearchText) != std::string::npos) { @@ -350,9 +342,10 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me UIWidgets::ComboboxOptions options = {}; options.color = menuThemeIndex; options.tooltip = "Sets the audio API used by the game. Requires a relaunch to take effect."; - options.disabled = availableAudioBackends->size() <= 1; + options.disabled = + Ship::Context::GetRawInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1; options.disabledTooltip = "Only one audio API is available on this platform."; - if (UIWidgets::Combobox("Audio API", ¤tAudioBackend, availableAudioBackendsMap, options)) { + if (UIWidgets::Combobox("Audio API", ¤tAudioBackend, audioBackendsMap, options)) { Ship::Context::GetRawInstance()->GetAudio()->SetCurrentAudioBackend(currentAudioBackend); } } break; diff --git a/src/port/UI/Menu.h b/src/port/UI/Menu.h index b1b8378e3..f32c349d6 100644 --- a/src/port/UI/Menu.h +++ b/src/port/UI/Menu.h @@ -20,7 +20,6 @@ class Menu : public GuiWindow { void InsertSidebarSearch(); void RemoveSidebarSearch(); void UpdateWindowBackendObjects(); - void UpdateAudioBackendObjects(); bool IsMenuPopped(); UIWidgets::Colors GetMenuThemeColor(); @@ -42,8 +41,6 @@ class Menu : public GuiWindow { std::shared_ptr> availableWindowBackends; std::unordered_map availableWindowBackendsMap; Fast::WindowBackend configWindowBackend; - std::shared_ptr> availableAudioBackends; - std::unordered_map availableAudioBackendsMap; std::unordered_map disabledMap; std::vector disabledVector; diff --git a/src/port/UI/MenuTypes.h b/src/port/UI/MenuTypes.h index f86cf363b..b0ef5b269 100644 --- a/src/port/UI/MenuTypes.h +++ b/src/port/UI/MenuTypes.h @@ -23,7 +23,6 @@ typedef enum { DISABLE_FOR_SINGLE_LANGUAGE, DISABLE_DURING_PARADE, DISABLE_FOR_ROMHACK, - FORCED_ON_FOR_ANCHOR_CONNECTED, } DisableOption; struct WidgetInfo; @@ -266,7 +265,6 @@ struct MainMenuEntry { static const std::unordered_map audioBackendsMap = { { Ship::AudioBackend::WASAPI, "Windows Audio Session API" }, - { Ship::AudioBackend::COREAUDIO, "Core Audio" }, { Ship::AudioBackend::SDL, "SDL" }, { Ship::AudioBackend::NUL, "Null" }, }; diff --git a/src/port/UI/Notification.cpp b/src/port/UI/Notification.cpp index cb89c0311..e7380efb0 100644 --- a/src/port/UI/Notification.cpp +++ b/src/port/UI/Notification.cpp @@ -2,15 +2,11 @@ #include "port/UI/cvar_prefixes.h" #include #include -#include -#include namespace Notification { static uint32_t nextId = 0; static std::vector notifications = {}; -// Emit() runs on the game thread; Draw()/UpdateElement() run on the render thread. -static std::mutex notificationsMutex; #define ABS(x) ((x) >= 0 ? (x) : -(x)) @@ -50,17 +46,9 @@ void Window::Draw() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f * CVarGetFloat(CVAR_SETTING("Notifications.Size"), 1.8f), 8.0f)); - // Render from a snapshot rather than the live vector, so a concurrent Emit() can - // reallocate without invalidating anything this loop is reading. - std::vector snapshot; - { - std::lock_guard lock(notificationsMutex); - snapshot = notifications; - } - - for (size_t index = 0; index < snapshot.size(); ++index) { - auto& notification = snapshot[index]; - int inverseIndex = -ABS((int)index - (int)(snapshot.size() - 1)); + for (size_t index = 0; index < notifications.size(); ++index) { + auto& notification = notifications[index]; + int inverseIndex = -ABS((int)index - (int)(notifications.size() - 1)); ImGui::SetNextWindowViewport(vp->ID); if (notification.remainingTime < 4.0f) { @@ -126,7 +114,6 @@ void Window::Draw() { } void Window::UpdateElement() { - std::lock_guard lock(notificationsMutex); for (int index = 0; index < notifications.size(); ++index) { auto& notification = notifications[index]; @@ -142,14 +129,11 @@ void Window::UpdateElement() { } void Emit(Options notification) { + notification.id = nextId++; if (notification.remainingTime == 0.0f) { notification.remainingTime = CVarGetFloat(CVAR_SETTING("Notifications.Duration"), 10.0f); } - { - std::lock_guard lock(notificationsMutex); - notification.id = nextId++; - notifications.push_back(notification); - } + notifications.push_back(notification); if (!notification.mute) { // TODO: play game notification sound } diff --git a/src/port/UI/ResolutionEditor.cpp b/src/port/UI/ResolutionEditor.cpp index 305131005..433f8cc41 100644 --- a/src/port/UI/ResolutionEditor.cpp +++ b/src/port/UI/ResolutionEditor.cpp @@ -404,13 +404,13 @@ void RegisterResolutionWidgets() { .CVar(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled") .RaceDisable(false); // Error/Warning display - // LighthouseMenu - // ->AddWidget(path, ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring.", - // WIDGET_TEXT) - // .RaceDisable(false) - // .PreFunc( - // [](WidgetInfo& info) { info.isHidden = !(!CVarGetInteger(CVAR_LOW_RES_MODE, 0) && IsDroppingFrames()); }) - // .Options(TextOptions().Color(Colors::Orange)); + mLighthouseMenu + ->AddWidget(path, ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring.", + WIDGET_TEXT) + .RaceDisable(false) + .PreFunc( + [](WidgetInfo& info) { info.isHidden = !(!CVarGetInteger(CVAR_LOW_RES_MODE, 0) && IsDroppingFrames()); }) + .Options(TextOptions().Color(Colors::Orange)); mLighthouseMenu->AddWidget(path, ICON_FA_QUESTION_CIRCLE " \"N64 Mode\" is overriding these settings.", WIDGET_TEXT) .RaceDisable(false) .PreFunc([](WidgetInfo& info) { info.isHidden = !CVarGetInteger(CVAR_LOW_RES_MODE, 0); }) @@ -589,13 +589,13 @@ void UpdateResolutionVars() { disabled_pixelCount = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0); } -// bool IsDroppingFrames() { -// // a rather imprecise way of checking for frame drops. -// // but it's mostly there to inform the player of large drops. -// const short targetFPS = GameEngine::Instance->GetInterpolationFPS(); -// const float threshold = targetFPS / 20.0f + 4.1f; -// return ImGui::GetIO().Framerate < targetFPS - threshold; -// } +bool IsDroppingFrames() { + // a rather imprecise way of checking for frame drops. + // but it's mostly there to inform the player of large drops. + const short targetFPS = GameEngine::Instance->GetInterpolationFPS(); + const float threshold = targetFPS / 20.0f + 4.1f; + return ImGui::GetIO().Framerate < targetFPS - threshold; +} static RegisterMenuUpdateFunc updateFunc(UpdateResolutionVars, "Settings", "Graphics"); static RegisterMenuInitFunc menuInitFunc(RegisterResolutionWidgets); diff --git a/src/port/UI/ResolutionEditor.h b/src/port/UI/ResolutionEditor.h index 316680534..a640b1e2c 100644 --- a/src/port/UI/ResolutionEditor.h +++ b/src/port/UI/ResolutionEditor.h @@ -2,7 +2,7 @@ #define RESOLUTIONEDITOR_H namespace LighthouseGui { -// bool IsDroppingFrames(); +bool IsDroppingFrames(); void RegisterResolutionWidgets(); void UpdateResolutionVars(); } // namespace LighthouseGui diff --git a/src/port/UI/UIWidgets.cpp b/src/port/UI/UIWidgets.cpp index e41ab88db..e2b670a1f 100644 --- a/src/port/UI/UIWidgets.cpp +++ b/src/port/UI/UIWidgets.cpp @@ -529,7 +529,7 @@ bool SliderInt(const char* label, int32_t* value, const IntSliderOptions& option } ImGui::AlignTextToFramePadding(); if (options.alignment == ComponentAlignments::Right && options.labelPosition != LabelPositions::None) { - ImGui::Text("%s", label); + ImGui::Text(label, *value); if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(ImGui::GetContentRegionAvail().x - width); @@ -540,7 +540,7 @@ bool SliderInt(const char* label, int32_t* value, const IntSliderOptions& option } } else if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text("%s", label); + ImGui::Text(label, *value); } } if (options.showButtons) { @@ -585,11 +585,11 @@ bool SliderInt(const char* label, int32_t* value, const IntSliderOptions& option if (options.alignment == ComponentAlignments::Left && options.labelPosition != LabelPositions::None) { if (options.labelPosition == LabelPositions::Near) { ImGui::SameLine(); - ImGui::Text("%s", label); + ImGui::Text(label, *value); } else if (options.labelPosition == LabelPositions::Far) { ImGui::SameLine(ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize(label).x + ImGui::GetStyle().ItemSpacing.x); - ImGui::Text("%s", label); + ImGui::Text(label, *value); } } PopStyleSlider(); @@ -665,7 +665,7 @@ bool SliderFloat(const char* label, float* value, const FloatSliderOptions& opti } ImGui::AlignTextToFramePadding(); if (options.alignment == ComponentAlignments::Right) { - ImGui::Text("%s", label); + ImGui::Text(label, *value); if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(ImGui::GetContentRegionAvail().x - width); @@ -678,7 +678,7 @@ bool SliderFloat(const char* label, float* value, const FloatSliderOptions& opti } } else if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text("%s", label); + ImGui::Text(label, *value); } } if (options.showButtons) { @@ -717,10 +717,10 @@ bool SliderFloat(const char* label, float* value, const FloatSliderOptions& opti if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Near) { ImGui::SameLine(); - ImGui::Text("%s", label); + ImGui::Text(label, *value); } else if (options.labelPosition == LabelPositions::Far || options.labelPosition == LabelPositions::None) { ImGui::SameLine(ImGui::GetContentRegionAvail().x - labelSpacing); - ImGui::Text("%s", label); + ImGui::Text(label, *value); } } PopStyleSlider(); @@ -771,13 +771,13 @@ bool InputString(const char* label, std::string* value, const InputOptions& opti if (labelSize.x != 0) { if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text("%s", label); + ImGui::Text(label, *value->c_str()); } } else if (options.alignment == ComponentAlignments::Right) { if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(width - ImGui::CalcTextSize(label).x); - ImGui::Text("%s", label); + ImGui::Text(label, *value->c_str()); } } } @@ -834,13 +834,13 @@ bool InputInt(const char* label, int32_t* value, const InputOptions& options) { float width = (options.size == ImVec2(0, 0)) ? ImGui::GetContentRegionAvail().x : options.size.x; if (options.alignment == ComponentAlignments::Left) { if (options.labelPosition == LabelPositions::Above) { - ImGui::Text("%s", label); + ImGui::Text(label, *value); } } else if (options.alignment == ComponentAlignments::Right) { if (options.labelPosition == LabelPositions::Above) { ImGui::NewLine(); ImGui::SameLine(width - ImGui::CalcTextSize(label).x); - ImGui::Text("%s", label); + ImGui::Text(label, *value); } } ImGui::SetNextItemWidth(width); @@ -903,8 +903,7 @@ bool CVarColorPicker(const char* label, const char* cvarName, Color_RGBA8 defaul ImGui::AlignTextToFramePadding(); if (showReset) { ImGui::SameLine(); - // Tag off the CVar, not the label. - std::string uniqueTag = "Reset##" + std::string(cvarName) + ".Reset"; + std::string uniqueTag = "Reset##" + std::string(label); if (UIWidgets::Button(uniqueTag.c_str(), UIWidgets::ButtonOptions({ { .tooltip = "Resets this color to its default value" } }) .Color(themeColor) @@ -921,7 +920,7 @@ bool CVarColorPicker(const char* label, const char* cvarName, Color_RGBA8 defaul } if (showRandom) { ImGui::SameLine(); - std::string uniqueTag = "Random##" + std::string(cvarName) + ".Random"; + std::string uniqueTag = "Random##" + std::string(label); if (UIWidgets::Button(uniqueTag.c_str(), UIWidgets::ButtonOptions({ { .tooltip = "Generates a random color value to use" } }) .Color(themeColor) diff --git a/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp b/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp index 5d2c7c7a4..aad0f5b07 100644 --- a/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp +++ b/src/port/enhancements/Gameplay/DisableSnackerSpawn.cpp @@ -7,7 +7,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +extern "C" { #include "enums.h" +} #define CVAR_DISABLE_SNACKER CVAR_ENHANCEMENT("Gameplay.DisableSnackerSpawn") #define CVAR CVarGetInteger(CVAR_DISABLE_SNACKER, 0) diff --git a/src/port/enhancements/Gameplay/EasierMrVile.cpp b/src/port/enhancements/Gameplay/EasierMrVile.cpp index 94ce8d771..9e3b89d18 100644 --- a/src/port/enhancements/Gameplay/EasierMrVile.cpp +++ b/src/port/enhancements/Gameplay/EasierMrVile.cpp @@ -7,7 +7,9 @@ #include "port/Enhancements/Events/Hooks/Events.h" #include "port/ShipInit.hpp" +extern "C" { #include "enums.h" +} #define CVAR_EASIER_MR_VILE CVAR_ENHANCEMENT("EasierMrVile") #define CVAR CVarGetInteger(CVAR_EASIER_MR_VILE, 0) diff --git a/src/port/OS/libultra.c b/src/port/stub.c similarity index 62% rename from src/port/OS/libultra.c rename to src/port/stub.c index b651a0bdc..20cf8c57f 100644 --- a/src/port/OS/libultra.c +++ b/src/port/stub.c @@ -1,14 +1,7 @@ -// BanjoDecomp: This file no longer exists upstream, -// but we do wrap its functions with our own. - -// Include the headers that declare what this file defines, so the compiler -// checks the definitions against them. #include "libultraship/libultra/types.h" #include "libultraship/libultra/interrupt.h" #include "libultraship/libultra/sptask.h" #include "libultraship/libultra/thread.h" -#include "libultraship/libultra/os.h" -#include "functions.h" #include "bk_string.h" #include @@ -23,35 +16,29 @@ s32 osViClock = VI_NTSC_CLOCK; u32 __osShutdown = 0; u32 __OSGlobalIntMask = OS_IM_ALL; s32 osCicId = 6103; -// On N64 this was a fixed-address depth buffer at 0x8000E800 (naturally 0x40-aligned). +// [port] On N64 this was a fixed-address depth buffer at 0x8000E800 (naturally 0x40-aligned). // On PC we need a properly sized and aligned buffer to avoid the alignment loop in func_80253428. _Alignas(0x40) u8 D_8000E800[DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIGHT * sizeof(u16)]; u16 gFramebuffers[2][DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIGHT]; -// Threads are in src/port/OS/OS.cpp. -void OS_CreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p); -void OS_StartThread(OSThread* thread); -void OS_StopThread(OSThread* thread); -void OS_DestroyThread(OSThread* thread); -void OS_SetThreadPri(OSThread* thread, OSPri p); - void osCreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p) { - OS_CreateThread(thread, id, entry, arg, sp, p); } void osStartThread(OSThread* thread) { - OS_StartThread(thread); } void osStopThread(OSThread* t) { - OS_StopThread(t); } void osDestroyThread(OSThread* thread) { - OS_DestroyThread(thread); +} +void osSpTaskYield(void) { +} +void osSpTaskLoad(OSTask* task) { +} +void osSpTaskStartGo(OSTask* task) { } void osViExtendVStart(u32 arg0) { } void osSetThreadPri(OSThread* thread, OSPri p) { - OS_SetThreadPri(thread, p); } s32 osContSetCh(u8 ch) { return 0; @@ -61,12 +48,23 @@ u32 __osGetSR(void) { } void __osSetSR(u32 value) { } -// All interrupt-enable bits set. thread5_checkAndExecutePreNMI reads SR_IBIT5 -// and treats a clear bit as "reset pressed"; with retraces running, returning -// 0 fires the PreNMI handler 60 times a second. u32 bkGetSR(void) { - return 0xFFFFFFFFu; + return 0; +} +OSYieldResult osSpTaskYielded(OSTask* task) { + return 0; } +// Lighthouse TODO these need to be implemented in LUS +int osStartTimer(void* t) { + return 0; +} +int osStopTimer(void* t) { + return 0; +} + +void osDpSetStatus(u32 data) { +} + void __osError(s16 error_code, s16 num_args, ...) { } diff --git a/src/unused/datalookup.c b/src/unused/datalookup.c index c3033cebc..6da37f5f2 100644 --- a/src/unused/datalookup.c +++ b/src/unused/datalookup.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/code_5FD80.c +// BanjoDecomp: (unknown decomp origin - data lookup) #include #include "functions.h" #include "variables.h" diff --git a/src/unused/debug_assert.c b/src/unused/debug_assert.c index 4bba81053..4a0de56a5 100644 --- a/src/unused/debug_assert.c +++ b/src/unused/debug_assert.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/ultra/debug/assert.c (kept in unused/, not built on PC) +// BanjoDecomp: core2/ultra/debug/assert.c #include #include "functions.h" #include "variables.h" diff --git a/src/unused/debug_boxdraw.c b/src/unused/debug_boxdraw.c index 8dec67ea0..c49e57865 100644 --- a/src/unused/debug_boxdraw.c +++ b/src/unused/debug_boxdraw.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core1/stub_3A70.c +// BanjoDecomp: (unknown decomp origin - unused debug drawing) #include #include "core1/core1.h" #include "functions.h" diff --git a/src/unused/unused_block.c b/src/unused/unused_block.c index a71bdf874..9f2f5b6a0 100644 --- a/src/unused/unused_block.c +++ b/src/unused/unused_block.c @@ -1,4 +1,4 @@ -// BanjoDecomp: core2/code_B7F40.c +// BanjoDecomp: (unknown decomp origin - unused block) #include #include "functions.h" #include "variables.h"